1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
83 #include "character.h"
88 /* Non-nil means Emacs uses toolkit scroll bars. */
90 Lisp_Object Vx_toolkit_scroll_bars
;
92 /* If non-zero, the text will be rendered using Core Graphics text
93 rendering which may anti-alias the text. */
94 int mac_use_core_graphics
;
97 /* Non-zero means that a HELP_EVENT has been generated since Emacs
100 static int any_help_event_p
;
102 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
103 static Lisp_Object last_window
;
105 /* Non-zero means make use of UNDERLINE_POSITION font properties.
106 (Not yet supported.) */
107 int x_use_underline_position_properties
;
109 /* Non-zero means to draw the underline at the same place as the descent line. */
111 int x_underline_at_descent_line
;
113 /* This is a chain of structures for all the X displays currently in
116 struct x_display_info
*x_display_list
;
118 /* This is a list of cons cells, each of the form (NAME
119 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
120 x_display_list and in the same order. NAME is the name of the
121 frame. FONT-LIST-CACHE records previous values returned by
122 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
123 equivalent, which is implemented with a Lisp object, for the
126 Lisp_Object x_display_name_list
;
128 /* This is display since Mac does not support multiple ones. */
129 struct mac_display_info one_mac_display_info
;
131 /* Frame being updated by update_frame. This is declared in term.c.
132 This is set by update_begin and looked at by all the XT functions.
133 It is zero while not inside an update. In that case, the XT
134 functions assume that `selected_frame' is the frame to apply to. */
136 extern struct frame
*updating_frame
;
138 /* This is a frame waiting to be auto-raised, within XTread_socket. */
140 struct frame
*pending_autoraise_frame
;
144 Formerly, we used PointerMotionHintMask (in standard_event_mask)
145 so that we would have to call XQueryPointer after each MotionNotify
146 event to ask for another such event. However, this made mouse tracking
147 slow, and there was a bug that made it eventually stop.
149 Simply asking for MotionNotify all the time seems to work better.
151 In order to avoid asking for motion events and then throwing most
152 of them away or busy-polling the server for mouse positions, we ask
153 the server for pointer motion hints. This means that we get only
154 one event per group of mouse movements. "Groups" are delimited by
155 other kinds of events (focus changes and button clicks, for
156 example), or by XQueryPointer calls; when one of these happens, we
157 get another MotionNotify event the next time the mouse moves. This
158 is at least as efficient as getting motion events when mouse
159 tracking is on, and I suspect only negligibly worse when tracking
162 /* Where the mouse was last time we reported a mouse event. */
164 static Rect last_mouse_glyph
;
165 static FRAME_PTR last_mouse_glyph_frame
;
167 /* The scroll bar in which the last X motion event occurred.
169 If the last X motion event occurred in a scroll bar, we set this so
170 XTmouse_position can know whether to report a scroll bar motion or
173 If the last X motion event didn't occur in a scroll bar, we set
174 this to Qnil, to tell XTmouse_position to return an ordinary motion
177 static Lisp_Object last_mouse_scroll_bar
;
179 /* This is a hack. We would really prefer that XTmouse_position would
180 return the time associated with the position it returns, but there
181 doesn't seem to be any way to wrest the time-stamp from the server
182 along with the position query. So, we just keep track of the time
183 of the last movement we received, and return that in hopes that
184 it's somewhat accurate. */
186 static Time last_mouse_movement_time
;
188 struct scroll_bar
*tracked_scroll_bar
= NULL
;
190 /* Incremented by XTread_socket whenever it really tries to read
194 static int volatile input_signal_count
;
196 static int input_signal_count
;
199 extern Lisp_Object Vsystem_name
;
201 extern Lisp_Object Qeql
;
203 /* A mask of extra modifier bits to put into every keyboard char. */
205 extern EMACS_INT extra_keyboard_modifiers
;
207 /* The keysyms to use for the various modifiers. */
209 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
211 extern int inhibit_window_system
;
213 #if __MRC__ && !TARGET_API_MAC_CARBON
214 QDGlobals qd
; /* QuickDraw global information structure. */
217 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
219 struct mac_display_info
*mac_display_info_for_display (Display
*);
220 static void x_update_window_end
P_ ((struct window
*, int, int));
221 int x_catch_errors
P_ ((Display
*));
222 void x_uncatch_errors
P_ ((Display
*, int));
223 void x_lower_frame
P_ ((struct frame
*));
224 void x_scroll_bar_clear
P_ ((struct frame
*));
225 int x_had_errors_p
P_ ((Display
*));
226 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
227 void x_raise_frame
P_ ((struct frame
*));
228 void x_set_window_size
P_ ((struct frame
*, int, int, int));
229 void x_wm_set_window_state
P_ ((struct frame
*, int));
230 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
231 static void mac_initialize
P_ ((void));
232 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
233 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
234 static void x_update_end
P_ ((struct frame
*));
235 static void XTframe_up_to_date
P_ ((struct frame
*));
236 static void XTset_terminal_modes
P_ ((struct terminal
*));
237 static void XTreset_terminal_modes
P_ ((struct terminal
*));
238 static void x_clear_frame
P_ ((struct frame
*));
239 static void frame_highlight
P_ ((struct frame
*));
240 static void frame_unhighlight
P_ ((struct frame
*));
241 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
242 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
243 struct frame
*, struct input_event
*));
244 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
246 struct input_event
*));
247 static void XTframe_rehighlight
P_ ((struct frame
*));
248 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
249 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
250 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
251 enum text_cursor_kinds
));
253 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
254 static void x_flush
P_ ((struct frame
*f
));
255 static void x_update_begin
P_ ((struct frame
*));
256 static void x_update_window_begin
P_ ((struct window
*));
257 static void x_after_update_window_line
P_ ((struct glyph_row
*));
258 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
259 enum scroll_bar_part
*,
260 Lisp_Object
*, Lisp_Object
*,
263 static int is_emacs_window
P_ ((WindowRef
));
264 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
265 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
266 static struct terminal
*mac_create_terminal
P_ ((struct mac_display_info
*dpyinfo
));
269 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
270 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
271 #define GC_FONT(gc) ((gc)->xgcv.font)
272 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
274 #define CG_SET_FILL_COLOR(context, color) \
275 CGContextSetRGBFillColor (context, \
276 RED_FROM_ULONG (color) / 255.0f, \
277 GREEN_FROM_ULONG (color) / 255.0f, \
278 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
279 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
280 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
281 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
283 if (CGColorGetTypeID != NULL) \
284 CGContextSetFillColorWithColor (context, cg_color); \
286 CG_SET_FILL_COLOR (context, color); \
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CGContextSetFillColorWithColor (context, cg_color)
293 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
294 CG_SET_FILL_COLOR (context, color)
296 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
297 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
299 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
300 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
304 #define CG_SET_STROKE_COLOR(context, color) \
305 CGContextSetRGBStrokeColor (context, \
306 RED_FROM_ULONG (color) / 255.0f, \
307 GREEN_FROM_ULONG (color) / 255.0f, \
308 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
309 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
310 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
311 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
313 if (CGColorGetTypeID != NULL) \
314 CGContextSetStrokeColorWithColor (context, cg_color); \
316 CG_SET_STROKE_COLOR (context, color); \
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CGContextSetStrokeColorWithColor (context, cg_color)
323 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
324 CG_SET_STROKE_COLOR (context, color)
326 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
327 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
331 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
333 /* Fringe bitmaps. */
335 static int max_fringe_bmp
= 0;
336 static CGImageRef
*fringe_bmp
= 0;
338 static CGColorSpaceRef mac_cg_color_space_rgb
;
339 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
340 static CGColorRef mac_cg_color_black
;
346 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
347 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
348 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
349 /* Don't check the availability of CGColorCreate; this symbol is
350 defined even in Mac OS X 10.1. */
351 if (CGColorGetTypeID
!= NULL
)
354 CGFloat rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
356 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
362 mac_begin_cg_clip (f
, gc
)
366 CGContextRef context
= FRAME_CG_CONTEXT (f
);
370 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
371 FRAME_CG_CONTEXT (f
) = context
;
374 CGContextSaveGState (context
);
375 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
376 CGContextScaleCTM (context
, 1, -1);
377 if (gc
&& gc
->n_clip_rects
)
378 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
387 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
391 mac_prepare_for_quickdraw (f
)
396 Lisp_Object rest
, frame
;
397 FOR_EACH_FRAME (rest
, frame
)
398 if (FRAME_MAC_P (XFRAME (frame
)))
399 mac_prepare_for_quickdraw (XFRAME (frame
));
403 CGContextRef context
= FRAME_CG_CONTEXT (f
);
407 CGContextSynchronize (context
);
408 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
409 &FRAME_CG_CONTEXT (f
));
415 static RgnHandle saved_port_clip_region
= NULL
;
418 mac_begin_clip (f
, gc
)
422 static RgnHandle new_region
= NULL
;
424 if (saved_port_clip_region
== NULL
)
425 saved_port_clip_region
= NewRgn ();
426 if (new_region
== NULL
)
427 new_region
= NewRgn ();
430 mac_prepare_for_quickdraw (f
);
432 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
434 if (gc
->n_clip_rects
)
436 GetClip (saved_port_clip_region
);
437 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
438 SetClip (new_region
);
446 if (gc
->n_clip_rects
)
447 SetClip (saved_port_clip_region
);
451 /* X display function emulation */
453 /* Mac version of XDrawLine. */
456 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
462 CGContextRef context
;
463 CGFloat gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
466 gx1
+= 0.5f
, gx2
+= 0.5f
;
468 gy1
+= 0.5f
, gy2
+= 0.5f
;
470 context
= mac_begin_cg_clip (f
, gc
);
471 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
472 CGContextBeginPath (context
);
473 CGContextMoveToPoint (context
, gx1
, gy1
);
474 CGContextAddLineToPoint (context
, gx2
, gy2
);
475 CGContextClosePath (context
);
476 CGContextStrokePath (context
);
494 mac_begin_clip (f
, gc
);
495 RGBForeColor (GC_FORE_COLOR (gc
));
502 /* Mac version of XDrawLine (to Pixmap). */
505 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
529 GetGWorld (&old_port
, &old_gdh
);
532 RGBForeColor (GC_FORE_COLOR (gc
));
534 LockPixels (GetGWorldPixMap (p
));
537 UnlockPixels (GetGWorldPixMap (p
));
539 SetGWorld (old_port
, old_gdh
);
544 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
548 unsigned int width
, height
;
552 CGContextRef context
;
554 context
= mac_begin_cg_clip (f
, gc
);
555 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
556 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
563 mac_begin_clip (f
, gc
);
564 RGBBackColor (GC_BACK_COLOR (gc
));
565 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
567 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
574 /* Mac version of XClearArea. */
577 mac_clear_area (f
, x
, y
, width
, height
)
580 unsigned int width
, height
;
582 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
585 /* Mac version of XClearWindow. */
593 CGContextRef context
;
594 GC gc
= FRAME_NORMAL_GC (f
);
596 context
= mac_begin_cg_clip (f
, NULL
);
597 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
598 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
599 FRAME_PIXEL_HEIGHT (f
)));
602 #else /* !USE_CG_DRAWING */
603 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
605 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
607 #if TARGET_API_MAC_CARBON
611 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
614 #else /* not TARGET_API_MAC_CARBON */
615 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
616 #endif /* not TARGET_API_MAC_CARBON */
621 /* Mac replacement for XCopyArea. */
625 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
626 dest_x
, dest_y
, overlay_p
)
631 unsigned int width
, height
;
632 int dest_x
, dest_y
, overlay_p
;
634 CGContextRef context
;
635 CGFloat port_height
= FRAME_PIXEL_HEIGHT (f
);
636 CGRect dest_rect
= mac_rect_make (f
, dest_x
, dest_y
, width
, height
);
638 context
= mac_begin_cg_clip (f
, gc
);
641 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
642 CGContextFillRect (context
, dest_rect
);
644 CGContextClipToRect (context
, dest_rect
);
645 CGContextScaleCTM (context
, 1, -1);
646 CGContextTranslateCTM (context
, 0, -port_height
);
647 if (CGImageIsMask (image
))
648 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
649 CGContextDrawImage (context
,
650 mac_rect_make (f
, dest_x
- src_x
,
651 port_height
- (dest_y
- src_y
652 + CGImageGetHeight (image
)),
653 CGImageGetWidth (image
),
654 CGImageGetHeight (image
)),
659 #else /* !USE_CG_DRAWING */
662 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
665 int x
, y
, width
, height
;
666 unsigned short *bits
;
672 bitmap
.rowBytes
= sizeof(unsigned short);
673 bitmap
.baseAddr
= (char *)bits
;
674 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
676 mac_begin_clip (f
, gc
);
677 RGBForeColor (GC_FORE_COLOR (gc
));
678 RGBBackColor (GC_BACK_COLOR (gc
));
679 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
680 #if TARGET_API_MAC_CARBON
686 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
687 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
688 UnlockPortBits (port
);
690 #else /* not TARGET_API_MAC_CARBON */
691 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
692 overlay_p
? srcOr
: srcCopy
, 0);
693 #endif /* not TARGET_API_MAC_CARBON */
694 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
697 #endif /* !USE_CG_DRAWING */
700 /* Mac replacement for XCreateBitmapFromBitmapData. */
703 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
708 static const unsigned char swap_nibble
[16]
709 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
710 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
711 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
712 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
716 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
717 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
718 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
719 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
720 for (i
= 0; i
< h
; i
++)
722 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
723 for (j
= 0; j
< w1
; j
++)
725 /* Bitswap XBM bytes to match how Mac does things. */
726 unsigned char c
= *bits
++;
727 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
728 | (swap_nibble
[(c
>>4) & 0xf]));
732 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
737 mac_free_bitmap (bitmap
)
740 xfree (bitmap
->baseAddr
);
745 XCreatePixmap (display
, w
, width
, height
, depth
)
748 unsigned int width
, height
;
756 SetPortWindowPort (w
);
758 SetRect (&r
, 0, 0, width
, height
);
759 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
762 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
763 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
765 /* CreateCGImageFromPixMaps requires ARGB format. */
766 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
775 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
779 unsigned int width
, height
;
780 unsigned long fg
, bg
;
790 gc
= XCreateGC (display
, w
, 0, NULL
);
792 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
796 GetGWorld (&old_port
, &old_gdh
);
797 SetGWorld (pixmap
, NULL
);
798 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
799 XSetForeground (display
, gc
, fg
);
800 XSetBackground (display
, gc
, bg
);
801 RGBForeColor (GC_FORE_COLOR (gc
));
802 RGBBackColor (GC_BACK_COLOR (gc
));
803 LockPixels (GetGWorldPixMap (pixmap
));
804 #if TARGET_API_MAC_CARBON
805 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
806 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
807 #else /* not TARGET_API_MAC_CARBON */
808 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
809 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
810 #endif /* not TARGET_API_MAC_CARBON */
811 UnlockPixels (GetGWorldPixMap (pixmap
));
812 SetGWorld (old_port
, old_gdh
);
813 mac_free_bitmap (&bitmap
);
820 XFreePixmap (display
, pixmap
)
824 DisposeGWorld (pixmap
);
828 /* Mac replacement for XFillRectangle. */
831 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
835 unsigned int width
, height
;
838 CGContextRef context
;
840 context
= mac_begin_cg_clip (f
, gc
);
841 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
842 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
847 mac_begin_clip (f
, gc
);
848 RGBForeColor (GC_FORE_COLOR (gc
));
849 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
850 PaintRect (&r
); /* using foreground color of gc */
856 /* Mac replacement for XDrawRectangle: dest is a window. */
859 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
863 unsigned int width
, height
;
866 CGContextRef context
;
868 context
= mac_begin_cg_clip (f
, gc
);
869 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
870 CGContextStrokeRect (context
,
871 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
876 mac_begin_clip (f
, gc
);
877 RGBForeColor (GC_FORE_COLOR (gc
));
878 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
879 FrameRect (&r
); /* using foreground color of gc */
886 mac_invert_rectangle (f
, x
, y
, width
, height
)
889 unsigned int width
, height
;
891 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
892 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
893 if (CGContextSetBlendMode
!= NULL
)
896 CGContextRef context
;
898 context
= mac_begin_cg_clip (f
, NULL
);
899 CGContextSetRGBFillColor (context
, 1.0f
, 1.0f
, 1.0f
, 1.0f
);
900 CGContextSetBlendMode (context
, kCGBlendModeDifference
);
901 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
904 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
905 else /* CGContextSetBlendMode == NULL */
907 #endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
908 #if !USE_CG_DRAWING || MAC_OS_X_VERSION_MAX_ALLOWED < 1040 || (MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020)
913 mac_prepare_for_quickdraw (f
);
915 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
917 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
925 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
926 ConstUniCharArrayPtr text
;
927 UniCharCount text_length
;
929 ATSUTextLayout
*text_layout
;
932 static ATSUTextLayout saved_text_layout
= NULL
;
934 if (saved_text_layout
== NULL
)
936 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
937 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
938 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
939 static ATSLineLayoutOptions line_layout
=
940 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
941 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
942 | kATSLineUseQDRendering
944 kATSLineIsDisplayOnly
| kATSLineFractDisable
947 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
949 err
= ATSUCreateTextLayoutWithTextPtr (text
,
950 kATSUFromTextBeginning
,
956 err
= ATSUSetLayoutControls (saved_text_layout
,
957 sizeof (tags
) / sizeof (tags
[0]),
958 tags
, sizes
, values
);
960 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
964 err
= ATSUSetRunStyle (saved_text_layout
, style
,
965 kATSUFromTextBeginning
, kATSUToTextEnd
);
967 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
968 kATSUFromTextBeginning
,
974 *text_layout
= saved_text_layout
;
980 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
981 overstrike_p
, bytes_per_char
)
986 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
989 ATSUTextLayout text_layout
;
991 xassert (bytes_per_char
== 2);
993 #ifndef WORDS_BIG_ENDIAN
996 UniChar
*text
= (UniChar
*)buf
;
998 for (i
= 0; i
< nchars
; i
++)
999 text
[i
] = EndianU16_BtoN (text
[i
]);
1002 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
1004 GC_FONT (gc
)->mac_style
,
1009 if (!mac_use_core_graphics
)
1012 mac_begin_clip (f
, gc
);
1013 RGBForeColor (GC_FORE_COLOR (gc
));
1018 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1019 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1020 RGBBackColor (GC_BACK_COLOR (gc
));
1022 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1025 ATSUDrawText (text_layout
,
1026 kATSUFromTextBeginning
, kATSUToTextEnd
,
1027 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1031 ATSUDrawText (text_layout
,
1032 kATSUFromTextBeginning
, kATSUToTextEnd
,
1033 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1040 static CGContextRef context
;
1041 CGFloat port_height
= FRAME_PIXEL_HEIGHT (f
);
1042 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1043 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1044 static const ATSUAttributeValuePtr values
[] = {&context
};
1047 context
= mac_begin_cg_clip (f
, gc
);
1052 QDBeginCGContext (port
, &context
);
1053 if (gc
->n_clip_rects
|| bg_width
)
1055 CGContextTranslateCTM (context
, 0, port_height
);
1056 CGContextScaleCTM (context
, 1, -1);
1057 if (gc
->n_clip_rects
)
1058 CGContextClipToRects (context
, gc
->clip_rects
,
1063 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1064 CGContextFillRect (context
,
1066 x
, y
- FONT_BASE (GC_FONT (gc
)),
1068 FONT_HEIGHT (GC_FONT (gc
))));
1070 CGContextScaleCTM (context
, 1, -1);
1071 CGContextTranslateCTM (context
, 0, -port_height
);
1075 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1076 err
= ATSUSetLayoutControls (text_layout
,
1077 sizeof (tags
) / sizeof (tags
[0]),
1078 tags
, sizes
, values
);
1081 ATSUDrawText (text_layout
,
1082 kATSUFromTextBeginning
, kATSUToTextEnd
,
1083 Long2Fix (x
), Long2Fix (port_height
- y
));
1085 ATSUDrawText (text_layout
,
1086 kATSUFromTextBeginning
, kATSUToTextEnd
,
1087 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1090 mac_end_cg_clip (f
);
1093 CGContextSynchronize (context
);
1094 QDEndCGContext (port
, &context
);
1097 /* This doesn't work on Mac OS X 10.1. */
1098 ATSUClearLayoutControls (text_layout
,
1099 sizeof (tags
) / sizeof (tags
[0]), tags
);
1101 ATSUSetLayoutControls (text_layout
,
1102 sizeof (tags
) / sizeof (tags
[0]),
1103 tags
, sizes
, values
);
1106 #endif /* MAC_OSX */
1108 #endif /* USE_ATSUI */
1112 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1113 overstrike_p
, bytes_per_char
)
1118 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1120 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1124 mac_begin_clip (f
, gc
);
1125 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1126 if (mac_use_core_graphics
)
1127 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1129 RGBForeColor (GC_FORE_COLOR (gc
));
1133 RGBBackColor (GC_BACK_COLOR (gc
));
1139 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1141 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1142 into an offscreen graphics world first. So performance gain
1143 cannot be expected.)
1144 - It lowers rendering quality.
1145 - Some fonts leave garbage on cursor movement. */
1150 RGBBackColor (GC_BACK_COLOR (gc
));
1151 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1152 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1157 TextFont (GC_FONT (gc
)->mac_fontnum
);
1158 TextSize (GC_FONT (gc
)->mac_fontsize
);
1159 TextFace (GC_FONT (gc
)->mac_fontface
);
1161 DrawText (buf
, 0, nchars
* bytes_per_char
);
1166 DrawText (buf
, 0, nchars
* bytes_per_char
);
1169 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1172 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1173 if (mac_use_core_graphics
)
1174 SwapQDTextFlags(savedFlags
);
1180 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1181 overstrike_p
, bytes_per_char
)
1186 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1189 if (GC_FONT (gc
)->mac_style
)
1190 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1191 overstrike_p
, bytes_per_char
);
1193 #endif /* USE_ATSUI */
1194 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1195 overstrike_p
, bytes_per_char
);
1199 /* Mac replacement for XDrawImageString. */
1202 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1207 int nchars
, bg_width
, overstrike_p
;
1209 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1214 /* Mac replacement for XDrawImageString16. */
1217 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1222 int nchars
, bg_width
, overstrike_p
;
1224 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1229 /* Mac replacement for XQueryTextExtents, but takes a character. If
1230 STYLE is NULL, measurement is done by QuickDraw Text routines for
1231 the font of the current graphics port. If CG_GLYPH is not NULL,
1232 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1235 mac_query_char_extents (style
, c
,
1236 font_ascent_return
, font_descent_return
,
1237 overall_return
, cg_glyph
)
1244 int *font_ascent_return
, *font_descent_return
;
1245 XCharStruct
*overall_return
;
1246 #if USE_CG_TEXT_DRAWING
1252 OSStatus err
= noErr
;
1259 ATSUTextLayout text_layout
;
1262 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1264 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1266 ATSTrapezoid glyph_bounds
;
1268 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1269 kATSUFromTextBeginning
, kATSUToTextEnd
,
1270 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1271 kATSUseFractionalOrigins
,
1273 kATSUseDeviceOrigins
,
1275 1, &glyph_bounds
, NULL
);
1278 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1279 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1281 width
= Fix2Long (glyph_bounds
.upperRight
.x
1282 - glyph_bounds
.upperLeft
.x
);
1283 if (font_ascent_return
)
1284 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1285 if (font_descent_return
)
1286 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1289 if (err
== noErr
&& overall_return
)
1291 err
= ATSUMeasureTextImage (text_layout
,
1292 kATSUFromTextBeginning
, kATSUToTextEnd
,
1293 0, 0, &char_bounds
);
1295 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1296 #if USE_CG_TEXT_DRAWING
1297 if (err
== noErr
&& cg_glyph
)
1300 ATSUGlyphInfoArray glyph_info_array
;
1301 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1303 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1304 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1306 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1307 kATSUToTextEnd
, &count
,
1310 /* Make sure that we don't have to make layout
1312 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1313 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1314 && glyph_info_array
.glyphs
[0].screenX
== 0)
1316 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1317 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1328 if (font_ascent_return
|| font_descent_return
)
1332 GetFontInfo (&font_info
);
1333 if (font_ascent_return
)
1334 *font_ascent_return
= font_info
.ascent
;
1335 if (font_descent_return
)
1336 *font_descent_return
= font_info
.descent
;
1342 width
= CharWidth (ch
);
1343 QDTextBounds (1, &ch
, &char_bounds
);
1344 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1352 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1355 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1356 XFontStruct
*font_struct
;
1359 XCharStruct
*overall_return
;
1362 short width
= 0, lbearing
= 0, rbearing
= 0;
1365 for (i
= 0; i
< nchars
; i
++)
1367 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1369 width
+= FONT_WIDTH (font_struct
);
1372 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1373 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1374 width
+= pcm
->width
;
1379 overall_return
->lbearing
= lbearing
;
1380 overall_return
->rbearing
= rbearing
;
1381 overall_return
->width
= width
;
1383 /* What's the meaning of the return value of XTextExtents16? */
1387 #if USE_CG_TEXT_DRAWING
1388 static int cg_text_anti_aliasing_threshold
= 8;
1391 init_cg_text_anti_aliasing_threshold ()
1397 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1398 kCFPreferencesCurrentApplication
,
1401 cg_text_anti_aliasing_threshold
= threshold
;
1405 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1410 int nchars
, bg_width
, overstrike_p
;
1412 CGFloat port_height
, gx
, gy
;
1414 CGContextRef context
;
1418 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1421 port_height
= FRAME_PIXEL_HEIGHT (f
);
1423 gy
= port_height
- y
;
1424 glyphs
= (CGGlyph
*)buf
;
1425 advances
= alloca (sizeof (CGSize
) * nchars
);
1426 if (advances
== NULL
)
1428 for (i
= 0; i
< nchars
; i
++)
1430 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1432 advances
[i
].width
= pcm
->width
;
1433 advances
[i
].height
= 0;
1434 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1439 context
= mac_begin_cg_clip (f
, gc
);
1441 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1442 if (gc
->n_clip_rects
|| bg_width
)
1444 CGContextTranslateCTM (context
, 0, port_height
);
1445 CGContextScaleCTM (context
, 1, -1);
1446 if (gc
->n_clip_rects
)
1447 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1451 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1454 mac_rect_make (f
, gx
, y
- FONT_BASE (GC_FONT (gc
)),
1455 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1457 CGContextScaleCTM (context
, 1, -1);
1458 CGContextTranslateCTM (context
, 0, -port_height
);
1462 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1463 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1464 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1465 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1466 CGContextSetShouldAntialias (context
, false);
1467 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1468 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1469 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1472 CGContextSetTextPosition (context
, gx
, gy
);
1473 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1476 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1477 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1480 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1481 else /* CGContextShowGlyphsWithAdvances == NULL */
1483 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1484 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1486 for (i
= 0; i
< nchars
; i
++)
1488 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1490 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1491 gx
+= advances
[i
].width
;
1496 mac_end_cg_clip (f
);
1498 CGContextSynchronize (context
);
1499 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1508 /* Mac replacement for XCopyArea: dest must be window. */
1511 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1516 unsigned int width
, height
;
1521 mac_begin_clip (f
, gc
);
1523 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1524 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1526 ForeColor (blackColor
);
1527 BackColor (whiteColor
);
1529 LockPixels (GetGWorldPixMap (src
));
1530 #if TARGET_API_MAC_CARBON
1535 LockPortBits (port
);
1536 CopyBits (GetPortBitMapForCopyBits (src
),
1537 GetPortBitMapForCopyBits (port
),
1538 &src_r
, &dest_r
, srcCopy
, 0);
1539 UnlockPortBits (port
);
1541 #else /* not TARGET_API_MAC_CARBON */
1542 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1543 &src_r
, &dest_r
, srcCopy
, 0);
1544 #endif /* not TARGET_API_MAC_CARBON */
1545 UnlockPixels (GetGWorldPixMap (src
));
1547 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1554 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1555 width
, height
, dest_x
, dest_y
)
1560 unsigned int width
, height
;
1565 mac_begin_clip (f
, gc
);
1567 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1568 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1570 ForeColor (blackColor
);
1571 BackColor (whiteColor
);
1573 LockPixels (GetGWorldPixMap (src
));
1574 LockPixels (GetGWorldPixMap (mask
));
1575 #if TARGET_API_MAC_CARBON
1580 LockPortBits (port
);
1581 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1582 GetPortBitMapForCopyBits (port
),
1583 &src_r
, &src_r
, &dest_r
);
1584 UnlockPortBits (port
);
1586 #else /* not TARGET_API_MAC_CARBON */
1587 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1588 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1589 #endif /* not TARGET_API_MAC_CARBON */
1590 UnlockPixels (GetGWorldPixMap (mask
));
1591 UnlockPixels (GetGWorldPixMap (src
));
1593 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1597 #endif /* !USE_CG_DRAWING */
1600 /* Mac replacement for XCopyArea: used only for scrolling. */
1603 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1607 unsigned int width
, height
;
1610 #if TARGET_API_MAC_CARBON
1612 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1614 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1616 mac_prepare_for_quickdraw (f
);
1618 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1619 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1620 kScrollWindowNoOptions
, dummy
);
1622 #else /* not TARGET_API_MAC_CARBON */
1624 WindowRef w
= FRAME_MAC_WINDOW (f
);
1626 mac_begin_clip (f
, gc
);
1628 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1629 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1631 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1632 color mapping in CopyBits. Otherwise, it will be slow. */
1633 ForeColor (blackColor
);
1634 BackColor (whiteColor
);
1635 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1637 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1640 #endif /* not TARGET_API_MAC_CARBON */
1644 /* Mac replacement for XChangeGC. */
1647 XChangeGC (display
, gc
, mask
, xgcv
)
1653 if (mask
& GCForeground
)
1654 XSetForeground (display
, gc
, xgcv
->foreground
);
1655 if (mask
& GCBackground
)
1656 XSetBackground (display
, gc
, xgcv
->background
);
1658 XSetFont (display
, gc
, xgcv
->font
);
1662 /* Mac replacement for XCreateGC. */
1665 XCreateGC (display
, d
, mask
, xgcv
)
1671 GC gc
= xmalloc (sizeof (*gc
));
1673 bzero (gc
, sizeof (*gc
));
1674 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1675 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1676 if (CGColorGetTypeID
!= NULL
)
1679 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1680 CGColorRetain (gc
->cg_fore_color
);
1681 CGColorRetain (gc
->cg_back_color
);
1684 XChangeGC (display
, gc
, mask
, xgcv
);
1690 /* Used in xfaces.c. */
1693 XFreeGC (display
, gc
)
1697 if (gc
->clip_region
)
1698 DisposeRgn (gc
->clip_region
);
1699 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1700 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1701 if (CGColorGetTypeID
!= NULL
)
1704 CGColorRelease (gc
->cg_fore_color
);
1705 CGColorRelease (gc
->cg_back_color
);
1712 /* Mac replacement for XGetGCValues. */
1715 XGetGCValues (display
, gc
, mask
, xgcv
)
1721 if (mask
& GCForeground
)
1722 xgcv
->foreground
= gc
->xgcv
.foreground
;
1723 if (mask
& GCBackground
)
1724 xgcv
->background
= gc
->xgcv
.background
;
1726 xgcv
->font
= gc
->xgcv
.font
;
1730 /* Mac replacement for XSetForeground. */
1733 XSetForeground (display
, gc
, color
)
1736 unsigned long color
;
1738 if (gc
->xgcv
.foreground
!= color
)
1740 gc
->xgcv
.foreground
= color
;
1741 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1742 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1743 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1744 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1745 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1746 if (CGColorGetTypeID
!= NULL
)
1749 CGColorRelease (gc
->cg_fore_color
);
1752 gc
->cg_fore_color
= mac_cg_color_black
;
1753 CGColorRetain (gc
->cg_fore_color
);
1759 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1760 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1761 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1763 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1771 /* Mac replacement for XSetBackground. */
1774 XSetBackground (display
, gc
, color
)
1777 unsigned long color
;
1779 if (gc
->xgcv
.background
!= color
)
1781 gc
->xgcv
.background
= color
;
1782 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1783 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1784 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1785 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1786 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1787 if (CGColorGetTypeID
!= NULL
)
1790 CGColorRelease (gc
->cg_back_color
);
1793 gc
->cg_back_color
= mac_cg_color_black
;
1794 CGColorRetain (gc
->cg_back_color
);
1800 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1801 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1802 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1804 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1812 /* Mac replacement for XSetFont. */
1815 XSetFont (display
, gc
, font
)
1820 gc
->xgcv
.font
= font
;
1824 /* Mac replacement for XSetClipRectangles. */
1827 mac_set_clip_rectangles (f
, gc
, rectangles
, n
)
1835 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1837 gc
->n_clip_rects
= n
;
1840 if (gc
->clip_region
== NULL
)
1841 gc
->clip_region
= NewRgn ();
1842 RectRgn (gc
->clip_region
, rectangles
);
1845 RgnHandle region
= NewRgn ();
1847 for (i
= 1; i
< n
; i
++)
1849 RectRgn (region
, rectangles
+ i
);
1850 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1852 DisposeRgn (region
);
1855 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1856 for (i
= 0; i
< n
; i
++)
1858 Rect
*rect
= rectangles
+ i
;
1860 gc
->clip_rects
[i
] = mac_rect_make (f
, rect
->left
, rect
->top
,
1861 rect
->right
- rect
->left
,
1862 rect
->bottom
- rect
->top
);
1868 /* Mac replacement for XSetClipMask. */
1871 mac_reset_clip_rectangles (f
, gc
)
1875 gc
->n_clip_rects
= 0;
1879 /* Mac replacement for XSetWindowBackground. */
1882 XSetWindowBackground (display
, w
, color
)
1885 unsigned long color
;
1887 #if !TARGET_API_MAC_CARBON
1888 AuxWinHandle aw_handle
;
1889 CTabHandle ctab_handle
;
1890 ColorSpecPtr ct_table
;
1895 bg_color
.red
= RED16_FROM_ULONG (color
);
1896 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1897 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1899 #if TARGET_API_MAC_CARBON
1900 SetWindowContentColor (w
, &bg_color
);
1902 if (GetAuxWin (w
, &aw_handle
))
1904 ctab_handle
= (*aw_handle
)->awCTable
;
1905 HandToHand ((Handle
*) &ctab_handle
);
1906 ct_table
= (*ctab_handle
)->ctTable
;
1907 ct_size
= (*ctab_handle
)->ctSize
;
1908 while (ct_size
> -1)
1910 if (ct_table
->value
== 0)
1912 ct_table
->rgb
= bg_color
;
1913 CTabChanged (ctab_handle
);
1914 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1922 /* Flush display of frame F, or of all frames if F is null. */
1928 #if TARGET_API_MAC_CARBON
1931 mac_prepare_for_quickdraw (f
);
1934 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1936 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1942 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1943 Calls to XFlush should be unnecessary because the X output buffer
1944 is flushed automatically as needed by calls to XPending,
1945 XNextEvent, or XWindowEvent according to the XFlush man page.
1946 XTread_socket calls XPending. Removing XFlush improves
1949 #define XFlush(DISPLAY) (void) 0
1953 mac_flush_display_optional (f
)
1957 mac_prepare_for_quickdraw (f
);
1962 /***********************************************************************
1963 Starting and ending an update
1964 ***********************************************************************/
1966 /* Start an update of frame F. This function is installed as a hook
1967 for update_begin, i.e. it is called when update_begin is called.
1968 This function is called prior to calls to x_update_window_begin for
1969 each window being updated. */
1975 #if TARGET_API_MAC_CARBON
1976 /* During update of a frame, availability of input events is
1977 periodically checked with ReceiveNextEvent if
1978 redisplay-dont-pause is nil. That normally flushes window buffer
1979 changes for every check, and thus screen update looks waving even
1980 if no input is available. So we disable screen updates during
1981 update of a frame. */
1983 DisableScreenUpdates ();
1989 /* Start update of window W. Set the global variable updated_window
1990 to the window being updated and set output_cursor to the cursor
1994 x_update_window_begin (w
)
1997 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1998 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
2001 set_output_cursor (&w
->cursor
);
2005 if (f
== display_info
->mouse_face_mouse_frame
)
2007 /* Don't do highlighting for mouse motion during the update. */
2008 display_info
->mouse_face_defer
= 1;
2010 /* If F needs to be redrawn, simply forget about any prior mouse
2012 if (FRAME_GARBAGED_P (f
))
2013 display_info
->mouse_face_window
= Qnil
;
2015 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
2016 their mouse_face_p flag set, which means that they are always
2017 unequal to rows in a desired matrix which never have that
2018 flag set. So, rows containing mouse-face glyphs are never
2019 scrolled, and we don't have to switch the mouse highlight off
2020 here to prevent it from being scrolled. */
2022 /* Can we tell that this update does not affect the window
2023 where the mouse highlight is? If so, no need to turn off.
2024 Likewise, don't do anything if the frame is garbaged;
2025 in that case, the frame's current matrix that we would use
2026 is all wrong, and we will redisplay that line anyway. */
2027 if (!NILP (display_info
->mouse_face_window
)
2028 && w
== XWINDOW (display_info
->mouse_face_window
))
2032 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2033 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2036 if (i
< w
->desired_matrix
->nrows
)
2037 clear_mouse_face (display_info
);
2046 /* Draw a vertical window border from (x,y0) to (x,y1) */
2049 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2053 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2056 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2058 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2061 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2064 /* End update of window W (which is equal to updated_window).
2066 Draw vertical borders between horizontally adjacent windows, and
2067 display W's cursor if CURSOR_ON_P is non-zero.
2069 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2070 glyphs in mouse-face were overwritten. In that case we have to
2071 make sure that the mouse-highlight is properly redrawn.
2073 W may be a menu bar pseudo-window in case we don't have X toolkit
2074 support. Such windows don't have a cursor, so don't display it
2078 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2080 int cursor_on_p
, mouse_face_overwritten_p
;
2082 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2084 if (!w
->pseudo_window_p
)
2089 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2091 output_cursor
.x
, output_cursor
.y
);
2093 if (draw_window_fringes (w
, 1))
2094 x_draw_vertical_border (w
);
2099 /* If a row with mouse-face was overwritten, arrange for
2100 XTframe_up_to_date to redisplay the mouse highlight. */
2101 if (mouse_face_overwritten_p
)
2103 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2104 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2105 dpyinfo
->mouse_face_window
= Qnil
;
2108 updated_window
= NULL
;
2112 /* End update of frame F. This function is installed as a hook in
2119 /* Mouse highlight may be displayed again. */
2120 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2123 #if TARGET_API_MAC_CARBON
2124 EnableScreenUpdates ();
2126 XFlush (FRAME_MAC_DISPLAY (f
));
2131 /* This function is called from various places in xdisp.c whenever a
2132 complete update has been performed. The global variable
2133 updated_window is not available here. */
2136 XTframe_up_to_date (f
)
2139 if (FRAME_MAC_P (f
))
2141 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2143 if (dpyinfo
->mouse_face_deferred_gc
2144 || f
== dpyinfo
->mouse_face_mouse_frame
)
2147 if (dpyinfo
->mouse_face_mouse_frame
)
2148 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2149 dpyinfo
->mouse_face_mouse_x
,
2150 dpyinfo
->mouse_face_mouse_y
);
2151 dpyinfo
->mouse_face_deferred_gc
= 0;
2158 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2159 arrow bitmaps, or clear the fringes if no bitmaps are required
2160 before DESIRED_ROW is made current. The window being updated is
2161 found in updated_window. This function is called from
2162 update_window_line only if it is known that there are differences
2163 between bitmaps to be drawn between current row and DESIRED_ROW. */
2166 x_after_update_window_line (desired_row
)
2167 struct glyph_row
*desired_row
;
2169 struct window
*w
= updated_window
;
2175 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2176 desired_row
->redraw_fringe_bitmaps_p
= 1;
2178 /* When a window has disappeared, make sure that no rest of
2179 full-width rows stays visible in the internal border. Could
2180 check here if updated_window is the leftmost/rightmost window,
2181 but I guess it's not worth doing since vertically split windows
2182 are almost never used, internal border is rarely set, and the
2183 overhead is very small. */
2184 if (windows_or_buffers_changed
2185 && desired_row
->full_width_p
2186 && (f
= XFRAME (w
->frame
),
2187 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2189 && (height
= desired_row
->visible_height
,
2192 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2194 /* Internal border is drawn below the tool bar. */
2195 if (WINDOWP (f
->tool_bar_window
)
2196 && w
== XWINDOW (f
->tool_bar_window
))
2200 mac_clear_area (f
, 0, y
, width
, height
);
2201 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2207 /* Draw the bitmap WHICH in one of the left or right fringes of
2208 window W. ROW is the glyph row for which to display the bitmap; it
2209 determines the vertical position at which the bitmap has to be
2213 x_draw_fringe_bitmap (w
, row
, p
)
2215 struct glyph_row
*row
;
2216 struct draw_fringe_bitmap_params
*p
;
2218 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2219 Display
*display
= FRAME_MAC_DISPLAY (f
);
2220 struct face
*face
= p
->face
;
2222 int overlay_p
= p
->overlay_p
;
2227 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2229 #if 0 /* MAC_TODO: stipple */
2230 /* In case the same realized face is used for fringes and
2231 for something displayed in the text (e.g. face `region' on
2232 mono-displays, the fill style may have been changed to
2233 FillSolid in x_draw_glyph_string_background. */
2235 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2237 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2240 /* If the fringe is adjacent to the left (right) scroll bar of a
2241 leftmost (rightmost, respectively) window, then extend its
2242 background to the gap between the fringe and the bar. */
2243 if ((WINDOW_LEFTMOST_P (w
)
2244 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2245 || (WINDOW_RIGHTMOST_P (w
)
2246 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2248 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2252 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2253 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2254 * FRAME_COLUMN_WIDTH (f
));
2257 && (left
+ width
== p
->x
2258 || p
->x
+ p
->wd
== left
))
2260 /* Bitmap fills the fringe and we need background
2262 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
2266 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
2268 ny
= row
->visible_height
;
2273 if (left
+ width
== bx
)
2275 bx
= left
+ sb_width
;
2276 nx
+= width
- sb_width
;
2278 else if (bx
+ nx
== left
)
2279 nx
+= width
- sb_width
;
2286 mac_erase_rectangle (f
, face
->gc
, bx
, by
, nx
, ny
);
2287 /* The fringe background has already been filled. */
2291 #if 0 /* MAC_TODO: stipple */
2293 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2296 #endif /* MAC_OSX */
2298 /* Must clip because of partially visible lines. */
2299 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2302 /* Adjust position of "bottom aligned" bitmap on partially
2303 visible last row. */
2305 int oldVH
= row
->visible_height
;
2306 row
->visible_height
= p
->h
;
2307 row
->y
-= rowY
- p
->y
;
2308 x_clip_to_row (w
, row
, -1, face
->gc
);
2310 row
->visible_height
= oldVH
;
2313 x_clip_to_row (w
, row
, -1, face
->gc
);
2316 if (p
->bx
>= 0 && !p
->overlay_p
)
2318 #if 0 /* MAC_TODO: stipple */
2319 /* In case the same realized face is used for fringes and
2320 for something displayed in the text (e.g. face `region' on
2321 mono-displays, the fill style may have been changed to
2322 FillSolid in x_draw_glyph_string_background. */
2324 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2326 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2329 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2331 #if 0 /* MAC_TODO: stipple */
2333 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2336 #endif /* !MAC_OSX */
2340 && p
->which
< max_fringe_bmp
2346 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2347 XSetForeground (display
, face
->gc
,
2349 ? (p
->overlay_p
? face
->background
2350 : f
->output_data
.mac
->cursor_pixel
)
2351 : face
->foreground
));
2353 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2354 p
->wd
, p
->h
, p
->x
, p
->y
, overlay_p
);
2356 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2357 p
->wd
, p
->h
, p
->bits
+ p
->dh
, overlay_p
);
2359 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2362 mac_reset_clip_rectangles (f
, face
->gc
);
2367 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2369 unsigned short *bits
;
2373 CGDataProviderRef provider
;
2375 if (which
>= max_fringe_bmp
)
2378 max_fringe_bmp
= which
+ 20;
2379 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2380 while (i
< max_fringe_bmp
)
2381 fringe_bmp
[i
++] = 0;
2384 for (i
= 0; i
< h
; i
++)
2389 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2390 sizeof (unsigned short) * h
, NULL
);
2393 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2394 sizeof (unsigned short),
2396 CGDataProviderRelease (provider
);
2403 mac_destroy_fringe_bitmap (which
)
2406 if (which
>= max_fringe_bmp
)
2409 if (fringe_bmp
[which
])
2412 CGImageRelease (fringe_bmp
[which
]);
2415 fringe_bmp
[which
] = 0;
2420 /* This is called when starting Emacs and when restarting after
2421 suspend. When starting Emacs, no window is mapped. And nothing
2422 must be done to Emacs's own window if it is suspended (though that
2426 XTset_terminal_modes (struct terminal
*t
)
2430 /* This is called when exiting or suspending Emacs. Exiting will make
2431 the windows go away, and suspending requires no action. */
2434 XTreset_terminal_modes (struct terminal
*t
)
2440 /***********************************************************************
2442 ***********************************************************************/
2444 /* Function prototypes of this page. */
2446 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2447 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
2448 struct charset
*, int *));
2452 pcm_init (pcm
, count
)
2456 bzero (pcm
, sizeof (XCharStruct
) * count
);
2457 while (--count
>= 0)
2459 pcm
->descent
= PCM_INVALID
;
2464 static enum pcm_status
2465 pcm_get_status (pcm
)
2466 const XCharStruct
*pcm
;
2468 int height
= pcm
->ascent
+ pcm
->descent
;
2470 /* Negative height means some special status. */
2471 return height
>= 0 ? PCM_VALID
: height
;
2474 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2475 is not contained in the font. */
2477 static INLINE XCharStruct
*
2478 x_per_char_metric (font
, char2b
)
2482 /* The result metric information. */
2483 XCharStruct
*pcm
= NULL
;
2485 xassert (font
&& char2b
);
2488 if (font
->mac_style
)
2490 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2494 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2495 pcm_init (*row
, 0x100);
2497 pcm
= *row
+ char2b
->byte2
;
2498 if (pcm_get_status (pcm
) != PCM_VALID
)
2501 mac_query_char_extents (font
->mac_style
,
2502 (char2b
->byte1
<< 8) + char2b
->byte2
,
2503 NULL
, NULL
, pcm
, NULL
);
2510 if (font
->bounds
.per_char
!= NULL
)
2512 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2514 /* min_char_or_byte2 specifies the linear character index
2515 corresponding to the first element of the per_char array,
2516 max_char_or_byte2 is the index of the last character. A
2517 character with non-zero CHAR2B->byte1 is not in the font.
2518 A character with byte2 less than min_char_or_byte2 or
2519 greater max_char_or_byte2 is not in the font. */
2520 if (char2b
->byte1
== 0
2521 && char2b
->byte2
>= font
->min_char_or_byte2
2522 && char2b
->byte2
<= font
->max_char_or_byte2
)
2523 pcm
= font
->bounds
.per_char
2524 + (char2b
->byte2
- font
->min_char_or_byte2
);
2528 /* If either min_byte1 or max_byte1 are nonzero, both
2529 min_char_or_byte2 and max_char_or_byte2 are less than
2530 256, and the 2-byte character index values corresponding
2531 to the per_char array element N (counting from 0) are:
2533 byte1 = N/D + min_byte1
2534 byte2 = N\D + min_char_or_byte2
2538 D = max_char_or_byte2 - min_char_or_byte2 + 1
2539 / = integer division
2540 \ = integer modulus */
2541 if (char2b
->byte1
>= font
->min_byte1
2542 && char2b
->byte1
<= font
->max_byte1
2543 && char2b
->byte2
>= font
->min_char_or_byte2
2544 && char2b
->byte2
<= font
->max_char_or_byte2
)
2546 pcm
= (font
->bounds
.per_char
2547 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2548 * (char2b
->byte1
- font
->min_byte1
))
2549 + (char2b
->byte2
- font
->min_char_or_byte2
));
2555 /* If the per_char pointer is null, all glyphs between the first
2556 and last character indexes inclusive have the same
2557 information, as given by both min_bounds and max_bounds. */
2558 if (char2b
->byte2
>= font
->min_char_or_byte2
2559 && char2b
->byte2
<= font
->max_char_or_byte2
)
2560 pcm
= &font
->max_bounds
;
2566 return ((pcm
== NULL
2568 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2569 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2578 static XCharStruct
*
2579 mac_per_char_metric (font
, char2b
, font_type
)
2584 return x_per_char_metric (font
, char2b
);
2588 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2589 the two-byte form of C. Encoding is returned in *CHAR2B. */
2592 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
2595 struct font_info
*font_info
;
2596 struct charset
*charset
;
2599 XFontStruct
*font
= font_info
->font
;
2601 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2602 This may be either a program in a special encoder language or a
2604 if (font_info
->font_encoder
)
2606 /* It's a program. */
2607 struct ccl_program
*ccl
= font_info
->font_encoder
;
2609 check_ccl_update (ccl
);
2610 if (CHARSET_DIMENSION (charset
) == 1)
2612 ccl
->reg
[0] = CHARSET_ID (charset
);
2613 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
2618 ccl
->reg
[0] = CHARSET_ID (charset
);
2619 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
2620 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
2623 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
2625 /* We assume that MSBs are appropriately set/reset by CCL
2627 if (font
->max_byte1
== 0) /* 1-byte font */
2628 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
2630 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
2632 else if (font_info
->encoding_type
)
2634 /* Fixed encoding scheme. See fontset.h for the meaning of the
2635 encoding numbers. */
2636 unsigned char enc
= font_info
->encoding_type
;
2638 if ((enc
== 1 || enc
== 2)
2639 && CHARSET_DIMENSION (charset
) == 2)
2640 char2b
->byte1
|= 0x80;
2642 if (enc
== 1 || enc
== 3)
2643 char2b
->byte2
|= 0x80;
2647 int code
= (char2b
->byte1
<< 8) | char2b
->byte2
;
2650 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
2655 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2657 return FONT_TYPE_UNKNOWN
;
2662 /***********************************************************************
2664 ***********************************************************************/
2668 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2669 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2670 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2672 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2673 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2674 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2675 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2676 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2677 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2678 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2679 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2680 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2681 unsigned long *, double, int));*/
2682 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2683 double, int, unsigned long));
2684 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2685 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2686 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2687 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2688 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2690 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2691 int, int, int, int, int, int,
2693 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2694 int, int, int, Rect
*));
2697 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2701 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2706 struct glyph_string
*s
;
2708 if (s
->font
== FRAME_FONT (s
->f
)
2709 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2710 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2712 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2715 /* Cursor on non-default face: must merge. */
2719 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2720 xgcv
.foreground
= s
->face
->background
;
2722 /* If the glyph would be invisible, try a different foreground. */
2723 if (xgcv
.foreground
== xgcv
.background
)
2724 xgcv
.foreground
= s
->face
->foreground
;
2725 if (xgcv
.foreground
== xgcv
.background
)
2726 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2727 if (xgcv
.foreground
== xgcv
.background
)
2728 xgcv
.foreground
= s
->face
->foreground
;
2730 /* Make sure the cursor is distinct from text in this face. */
2731 if (xgcv
.background
== s
->face
->background
2732 && xgcv
.foreground
== s
->face
->foreground
)
2734 xgcv
.background
= s
->face
->foreground
;
2735 xgcv
.foreground
= s
->face
->background
;
2738 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2739 xgcv
.font
= s
->font
;
2740 mask
= GCForeground
| GCBackground
| GCFont
;
2742 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2743 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2746 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2747 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2749 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2754 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2757 x_set_mouse_face_gc (s
)
2758 struct glyph_string
*s
;
2763 /* What face has to be used last for the mouse face? */
2764 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2765 face
= FACE_FROM_ID (s
->f
, face_id
);
2767 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2769 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2770 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
2772 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
2773 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2774 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2776 /* If font in this face is same as S->font, use it. */
2777 if (s
->font
== s
->face
->font
)
2778 s
->gc
= s
->face
->gc
;
2781 /* Otherwise construct scratch_cursor_gc with values from FACE
2786 xgcv
.background
= s
->face
->background
;
2787 xgcv
.foreground
= s
->face
->foreground
;
2788 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2789 xgcv
.font
= s
->font
;
2790 mask
= GCForeground
| GCBackground
| GCFont
;
2792 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2793 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2796 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2797 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2799 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2802 xassert (s
->gc
!= 0);
2806 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2807 Faces to use in the mode line have already been computed when the
2808 matrix was built, so there isn't much to do, here. */
2811 x_set_mode_line_face_gc (s
)
2812 struct glyph_string
*s
;
2814 s
->gc
= s
->face
->gc
;
2818 /* Set S->gc of glyph string S for drawing that glyph string. Set
2819 S->stippled_p to a non-zero value if the face of S has a stipple
2823 x_set_glyph_string_gc (s
)
2824 struct glyph_string
*s
;
2826 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2828 if (s
->hl
== DRAW_NORMAL_TEXT
)
2830 s
->gc
= s
->face
->gc
;
2831 s
->stippled_p
= s
->face
->stipple
!= 0;
2833 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2835 x_set_mode_line_face_gc (s
);
2836 s
->stippled_p
= s
->face
->stipple
!= 0;
2838 else if (s
->hl
== DRAW_CURSOR
)
2840 x_set_cursor_gc (s
);
2843 else if (s
->hl
== DRAW_MOUSE_FACE
)
2845 x_set_mouse_face_gc (s
);
2846 s
->stippled_p
= s
->face
->stipple
!= 0;
2848 else if (s
->hl
== DRAW_IMAGE_RAISED
2849 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2851 s
->gc
= s
->face
->gc
;
2852 s
->stippled_p
= s
->face
->stipple
!= 0;
2856 s
->gc
= s
->face
->gc
;
2857 s
->stippled_p
= s
->face
->stipple
!= 0;
2860 /* GC must have been set. */
2861 xassert (s
->gc
!= 0);
2865 /* Set clipping for output of glyph string S. S may be part of a mode
2866 line or menu if we don't have X toolkit support. */
2869 x_set_glyph_string_clipping (s
)
2870 struct glyph_string
*s
;
2872 Rect rects
[MAX_CLIP_RECTS
];
2875 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2876 mac_set_clip_rectangles (s
->f
, s
->gc
, rects
, n
);
2881 Compute left and right overhang of glyph string S. If S is a glyph
2882 string for a composition, assume overhangs don't exist. */
2885 mac_compute_glyph_string_overhangs (s
)
2886 struct glyph_string
*s
;
2888 if (!(s
->cmp
== NULL
2889 && s
->first_glyph
->type
== CHAR_GLYPH
))
2894 || s
->font
->mac_style
2900 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2901 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2902 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2907 MacFontStruct
*font
= s
->font
;
2910 mac_prepare_for_quickdraw (s
->f
);
2912 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2914 TextFont (font
->mac_fontnum
);
2915 TextSize (font
->mac_fontsize
);
2916 TextFace (font
->mac_fontface
);
2918 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2920 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2921 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2926 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2929 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2930 struct glyph_string
*s
;
2933 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2937 /* Draw the background of glyph_string S. If S->background_filled_p
2938 is non-zero don't draw it. FORCE_P non-zero means draw the
2939 background even if it wouldn't be drawn normally. This is used
2940 when a string preceding S draws into the background of S, or S
2941 contains the first component of a composition. */
2944 x_draw_glyph_string_background (s
, force_p
)
2945 struct glyph_string
*s
;
2948 /* Nothing to do if background has already been drawn or if it
2949 shouldn't be drawn in the first place. */
2950 if (!s
->background_filled_p
)
2952 int box_line_width
= max (s
->face
->box_line_width
, 0);
2954 #if 0 /* MAC_TODO: stipple */
2957 /* Fill background with a stipple pattern. */
2958 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2959 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2960 s
->y
+ box_line_width
,
2961 s
->background_width
,
2962 s
->height
- 2 * box_line_width
);
2963 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2964 s
->background_filled_p
= 1;
2968 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2969 || s
->font_not_found_p
2970 || s
->extends_to_end_of_line_p
2973 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2974 s
->background_width
,
2975 s
->height
- 2 * box_line_width
);
2976 s
->background_filled_p
= 1;
2982 /* Draw the foreground of glyph string S. */
2985 x_draw_glyph_string_foreground (s
)
2986 struct glyph_string
*s
;
2990 /* If first glyph of S has a left box line, start drawing the text
2991 of S to the right of that box line. */
2992 if (s
->face
->box
!= FACE_NO_BOX
2993 && s
->first_glyph
->left_box_line_p
)
2994 x
= s
->x
+ eabs (s
->face
->box_line_width
);
2998 /* Draw characters of S as rectangles if S's font could not be
3000 if (s
->font_not_found_p
)
3002 for (i
= 0; i
< s
->nchars
; ++i
)
3004 struct glyph
*g
= s
->first_glyph
+ i
;
3005 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3006 g
->pixel_width
- 1, s
->height
- 1);
3007 x
+= g
->pixel_width
;
3012 char *char1b
= (char *) s
->char2b
;
3013 int boff
= s
->font_info
->baseline_offset
;
3015 if (s
->font_info
->vertical_centering
)
3016 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3018 /* If we can use 8-bit functions, condense S->char2b. */
3021 && GC_FONT (s
->gc
)->mac_style
== NULL
3024 for (i
= 0; i
< s
->nchars
; ++i
)
3025 char1b
[i
] = s
->char2b
[i
].byte2
;
3027 /* Draw text with XDrawString if background has already been
3028 filled. Otherwise, use XDrawImageString. (Note that
3029 XDrawImageString is usually faster than XDrawString.) Always
3030 use XDrawImageString when drawing the cursor so that there is
3031 no chance that characters under a box cursor are invisible. */
3033 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3034 bg_width
= 0; /* Corresponds to XDrawString. */
3036 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
3040 || GC_FONT (s
->gc
)->mac_style
3043 #if USE_CG_TEXT_DRAWING
3045 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3046 s
->char2b
, s
->nchars
, bg_width
,
3047 s
->face
->overstrike
))
3051 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3052 s
->char2b
, s
->nchars
, bg_width
,
3053 s
->face
->overstrike
);
3055 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3056 char1b
, s
->nchars
, bg_width
,
3057 s
->face
->overstrike
);
3061 /* Draw the foreground of composite glyph string S. */
3064 x_draw_composite_glyph_string_foreground (s
)
3065 struct glyph_string
*s
;
3069 /* If first glyph of S has a left box line, start drawing the text
3070 of S to the right of that box line. */
3071 if (s
->face
->box
!= FACE_NO_BOX
3072 && s
->first_glyph
->left_box_line_p
)
3073 x
= s
->x
+ eabs (s
->face
->box_line_width
);
3077 /* S is a glyph string for a composition. S->gidx is the index of
3078 the first character drawn for glyphs of this composition.
3079 S->gidx == 0 means we are drawing the very first character of
3080 this composition. */
3082 /* Draw a rectangle for the composition if the font for the very
3083 first character of the composition could not be loaded. */
3084 if (s
->font_not_found_p
)
3087 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3088 s
->width
- 1, s
->height
- 1);
3092 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3093 if (mac_per_char_metric (GC_FONT (s
->gc
), s
->char2b
+ i
, 0) == NULL
)
3094 /* This is a nonexistent or zero-width glyph such as a
3095 combining diacritic. Draw a rectangle. */
3096 mac_draw_rectangle (s
->f
, s
->gc
,
3097 x
+ s
->cmp
->offsets
[s
->gidx
* 2], s
->y
,
3098 FONT_WIDTH (GC_FONT (s
->gc
)) - 1, s
->height
- 1);
3100 mac_draw_image_string_16 (s
->f
, s
->gc
,
3101 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3102 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3103 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3108 #ifdef USE_X_TOOLKIT
3110 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3113 /* Return the frame on which widget WIDGET is used.. Abort if frame
3114 cannot be determined. */
3116 static struct frame
*
3117 x_frame_of_widget (widget
)
3120 struct x_display_info
*dpyinfo
;
3124 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3126 /* Find the top-level shell of the widget. Note that this function
3127 can be called when the widget is not yet realized, so XtWindow
3128 (widget) == 0. That's the reason we can't simply use
3129 x_any_window_to_frame. */
3130 while (!XtIsTopLevelShell (widget
))
3131 widget
= XtParent (widget
);
3133 /* Look for a frame with that top-level widget. Allocate the color
3134 on that frame to get the right gamma correction value. */
3135 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
3136 if (FRAMEP (XCAR (tail
))
3137 && (f
= XFRAME (XCAR (tail
)),
3138 (f
->output_data
.nothing
!= 1
3139 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3140 && f
->output_data
.x
->widget
== widget
)
3147 /* Allocate the color COLOR->pixel on the screen and display of
3148 widget WIDGET in colormap CMAP. If an exact match cannot be
3149 allocated, try the nearest color available. Value is non-zero
3150 if successful. This is called from lwlib. */
3153 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3158 struct frame
*f
= x_frame_of_widget (widget
);
3159 return x_alloc_nearest_color (f
, cmap
, color
);
3163 #endif /* USE_X_TOOLKIT */
3165 #if 0 /* MAC_TODO */
3167 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3168 CMAP. If an exact match can't be allocated, try the nearest color
3169 available. Value is non-zero if successful. Set *COLOR to the
3173 x_alloc_nearest_color (f
, cmap
, color
)
3178 Display
*display
= FRAME_X_DISPLAY (f
);
3179 Screen
*screen
= FRAME_X_SCREEN (f
);
3182 gamma_correct (f
, color
);
3183 rc
= XAllocColor (display
, cmap
, color
);
3186 /* If we got to this point, the colormap is full, so we're going
3187 to try to get the next closest color. The algorithm used is
3188 a least-squares matching, which is what X uses for closest
3189 color matching with StaticColor visuals. */
3191 unsigned long nearest_delta
= ~0;
3192 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3193 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3195 for (i
= 0; i
< ncells
; ++i
)
3197 XQueryColors (display
, cmap
, cells
, ncells
);
3199 for (nearest
= i
= 0; i
< ncells
; ++i
)
3201 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3202 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3203 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3204 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3206 if (delta
< nearest_delta
)
3209 nearest_delta
= delta
;
3213 color
->red
= cells
[nearest
].red
;
3214 color
->green
= cells
[nearest
].green
;
3215 color
->blue
= cells
[nearest
].blue
;
3216 rc
= XAllocColor (display
, cmap
, color
);
3219 #ifdef DEBUG_X_COLORS
3221 register_color (color
->pixel
);
3222 #endif /* DEBUG_X_COLORS */
3228 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3229 It's necessary to do this instead of just using PIXEL directly to
3230 get color reference counts right. */
3233 x_copy_color (f
, pixel
)
3235 unsigned long pixel
;
3239 color
.pixel
= pixel
;
3241 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3242 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3244 #ifdef DEBUG_X_COLORS
3245 register_color (pixel
);
3251 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3252 It's necessary to do this instead of just using PIXEL directly to
3253 get color reference counts right. */
3256 x_copy_dpy_color (dpy
, cmap
, pixel
)
3259 unsigned long pixel
;
3263 color
.pixel
= pixel
;
3265 XQueryColor (dpy
, cmap
, &color
);
3266 XAllocColor (dpy
, cmap
, &color
);
3268 #ifdef DEBUG_X_COLORS
3269 register_color (pixel
);
3274 #endif /* MAC_TODO */
3277 /* Brightness beyond which a color won't have its highlight brightness
3280 Nominally, highlight colors for `3d' faces are calculated by
3281 brightening an object's color by a constant scale factor, but this
3282 doesn't yield good results for dark colors, so for colors who's
3283 brightness is less than this value (on a scale of 0-255) have to
3284 use an additional additive factor.
3286 The value here is set so that the default menu-bar/mode-line color
3287 (grey75) will not have its highlights changed at all. */
3288 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3291 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3292 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3293 If this produces the same color as COLOR, try a color where all RGB
3294 values have DELTA added. Return the allocated color in *COLOR.
3295 DISPLAY is the X display, CMAP is the colormap to operate on.
3296 Value is non-zero if successful. */
3299 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3301 unsigned long *color
;
3308 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3311 /* Change RGB values by specified FACTOR. Avoid overflow! */
3312 xassert (factor
>= 0);
3313 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3314 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3315 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3317 /* Calculate brightness of COLOR. */
3318 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3319 + BLUE_FROM_ULONG (*color
)) / 6;
3321 /* We only boost colors that are darker than
3322 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3323 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3324 /* Make an additive adjustment to NEW, because it's dark enough so
3325 that scaling by FACTOR alone isn't enough. */
3327 /* How far below the limit this color is (0 - 1, 1 being darker). */
3328 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3329 /* The additive adjustment. */
3330 int min_delta
= delta
* dimness
* factor
/ 2;
3333 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3334 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3335 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3337 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3338 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3339 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3343 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3344 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3345 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3347 /* MAC_TODO: Map to palette and retry with delta if same? */
3348 /* MAC_TODO: Free colors (if using palette)? */
3359 /* Set up the foreground color for drawing relief lines of glyph
3360 string S. RELIEF is a pointer to a struct relief containing the GC
3361 with which lines will be drawn. Use a color that is FACTOR or
3362 DELTA lighter or darker than the relief's background which is found
3363 in S->f->output_data.x->relief_background. If such a color cannot
3364 be allocated, use DEFAULT_PIXEL, instead. */
3367 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3369 struct relief
*relief
;
3372 unsigned long default_pixel
;
3375 struct mac_output
*di
= f
->output_data
.mac
;
3376 unsigned long mask
= GCForeground
;
3377 unsigned long pixel
;
3378 unsigned long background
= di
->relief_background
;
3379 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3381 /* MAC_TODO: Free colors (if using palette)? */
3383 /* Allocate new color. */
3384 xgcv
.foreground
= default_pixel
;
3386 if (dpyinfo
->n_planes
!= 1
3387 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3389 relief
->allocated_p
= 1;
3390 xgcv
.foreground
= relief
->pixel
= pixel
;
3393 if (relief
->gc
== 0)
3395 #if 0 /* MAC_TODO: stipple */
3396 xgcv
.stipple
= dpyinfo
->gray
;
3399 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3402 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3406 /* Set up colors for the relief lines around glyph string S. */
3409 x_setup_relief_colors (s
)
3410 struct glyph_string
*s
;
3412 struct mac_output
*di
= s
->f
->output_data
.mac
;
3413 unsigned long color
;
3415 if (s
->face
->use_box_color_for_shadows_p
)
3416 color
= s
->face
->box_color
;
3417 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3419 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3420 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3425 /* Get the background color of the face. */
3426 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3427 color
= xgcv
.background
;
3430 if (di
->white_relief
.gc
== 0
3431 || color
!= di
->relief_background
)
3433 di
->relief_background
= color
;
3434 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3435 WHITE_PIX_DEFAULT (s
->f
));
3436 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3437 BLACK_PIX_DEFAULT (s
->f
));
3442 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3443 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3444 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3445 relief. LEFT_P non-zero means draw a relief on the left side of
3446 the rectangle. RIGHT_P non-zero means draw a relief on the right
3447 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3451 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3452 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3454 int left_x
, top_y
, right_x
, bottom_y
, width
;
3455 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3458 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3463 gc
= f
->output_data
.mac
->white_relief
.gc
;
3465 gc
= f
->output_data
.mac
->black_relief
.gc
;
3466 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3470 for (i
= 0; i
< width
; ++i
)
3471 mac_draw_line (f
, gc
,
3472 left_x
+ i
* left_p
, top_y
+ i
,
3473 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3477 for (i
= 0; i
< width
; ++i
)
3478 mac_draw_line (f
, gc
,
3479 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3481 mac_reset_clip_rectangles (f
, gc
);
3483 gc
= f
->output_data
.mac
->black_relief
.gc
;
3485 gc
= f
->output_data
.mac
->white_relief
.gc
;
3486 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3490 for (i
= 0; i
< width
; ++i
)
3491 mac_draw_line (f
, gc
,
3492 left_x
+ i
* left_p
, bottom_y
- i
,
3493 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3497 for (i
= 0; i
< width
; ++i
)
3498 mac_draw_line (f
, gc
,
3499 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3501 mac_reset_clip_rectangles (f
, gc
);
3505 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3506 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3507 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3508 left side of the rectangle. RIGHT_P non-zero means draw a line
3509 on the right side of the rectangle. CLIP_RECT is the clipping
3510 rectangle to use when drawing. */
3513 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3514 left_p
, right_p
, clip_rect
)
3515 struct glyph_string
*s
;
3516 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3521 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3522 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3523 mac_set_clip_rectangles (s
->f
, s
->gc
, clip_rect
, 1);
3526 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3527 right_x
- left_x
+ 1, width
);
3531 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3532 width
, bottom_y
- top_y
+ 1);
3535 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3536 right_x
- left_x
+ 1, width
);
3540 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3541 top_y
, width
, bottom_y
- top_y
+ 1);
3543 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3544 mac_reset_clip_rectangles (s
->f
, s
->gc
);
3548 /* Draw a box around glyph string S. */
3551 x_draw_glyph_string_box (s
)
3552 struct glyph_string
*s
;
3554 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3555 int left_p
, right_p
;
3556 struct glyph
*last_glyph
;
3559 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3560 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3561 : window_box_right (s
->w
, s
->area
));
3563 /* The glyph that may have a right box line. */
3564 last_glyph
= (s
->cmp
|| s
->img
3566 : s
->first_glyph
+ s
->nchars
- 1);
3568 width
= eabs (s
->face
->box_line_width
);
3569 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3571 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3573 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3575 bottom_y
= top_y
+ s
->height
- 1;
3577 left_p
= (s
->first_glyph
->left_box_line_p
3578 || (s
->hl
== DRAW_MOUSE_FACE
3580 || s
->prev
->hl
!= s
->hl
)));
3581 right_p
= (last_glyph
->right_box_line_p
3582 || (s
->hl
== DRAW_MOUSE_FACE
3584 || s
->next
->hl
!= s
->hl
)));
3586 get_glyph_string_clip_rect (s
, &clip_rect
);
3588 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3589 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3590 left_p
, right_p
, &clip_rect
);
3593 x_setup_relief_colors (s
);
3594 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3595 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3600 /* Draw foreground of image glyph string S. */
3603 x_draw_image_foreground (s
)
3604 struct glyph_string
*s
;
3607 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3609 /* If first glyph of S has a left box line, start drawing it to the
3610 right of that line. */
3611 if (s
->face
->box
!= FACE_NO_BOX
3612 && s
->first_glyph
->left_box_line_p
3614 x
+= eabs (s
->face
->box_line_width
);
3616 /* If there is a margin around the image, adjust x- and y-position
3618 if (s
->slice
.x
== 0)
3619 x
+= s
->img
->hmargin
;
3620 if (s
->slice
.y
== 0)
3621 y
+= s
->img
->vmargin
;
3625 x_set_glyph_string_clipping (s
);
3628 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3629 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3630 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3634 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3635 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3636 s
->slice
.width
, s
->slice
.height
, x
, y
);
3643 mac_copy_area (s
->img
->pixmap
,
3644 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3645 s
->slice
.width
, s
->slice
.height
, x
, y
);
3648 /* When the image has a mask, we can expect that at
3649 least part of a mouse highlight or a block cursor will
3650 be visible. If the image doesn't have a mask, make
3651 a block cursor visible by drawing a rectangle around
3652 the image. I believe it's looking better if we do
3653 nothing here for mouse-face. */
3654 if (s
->hl
== DRAW_CURSOR
)
3656 int r
= s
->img
->relief
;
3658 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3659 s
->slice
.width
+ r
*2 - 1,
3660 s
->slice
.height
+ r
*2 - 1);
3665 /* Draw a rectangle if image could not be loaded. */
3666 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3667 s
->slice
.width
- 1, s
->slice
.height
- 1);
3671 /* Draw a relief around the image glyph string S. */
3674 x_draw_image_relief (s
)
3675 struct glyph_string
*s
;
3677 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3680 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3682 /* If first glyph of S has a left box line, start drawing it to the
3683 right of that line. */
3684 if (s
->face
->box
!= FACE_NO_BOX
3685 && s
->first_glyph
->left_box_line_p
3687 x
+= eabs (s
->face
->box_line_width
);
3689 /* If there is a margin around the image, adjust x- and y-position
3691 if (s
->slice
.x
== 0)
3692 x
+= s
->img
->hmargin
;
3693 if (s
->slice
.y
== 0)
3694 y
+= s
->img
->vmargin
;
3696 if (s
->hl
== DRAW_IMAGE_SUNKEN
3697 || s
->hl
== DRAW_IMAGE_RAISED
)
3699 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3700 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3704 thick
= eabs (s
->img
->relief
);
3705 raised_p
= s
->img
->relief
> 0;
3710 x1
= x
+ s
->slice
.width
+ thick
- 1;
3711 y1
= y
+ s
->slice
.height
+ thick
- 1;
3713 x_setup_relief_colors (s
);
3714 get_glyph_string_clip_rect (s
, &r
);
3715 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3717 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3719 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3724 /* Draw part of the background of glyph string S. X, Y, W, and H
3725 give the rectangle to draw. */
3728 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3729 struct glyph_string
*s
;
3732 #if 0 /* MAC_TODO: stipple */
3735 /* Fill background with a stipple pattern. */
3736 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3737 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3738 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3741 #endif /* MAC_TODO */
3742 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3746 /* Draw image glyph string S.
3749 s->x +-------------------------
3752 | +-------------------------
3755 | | +-------------------
3761 x_draw_image_glyph_string (s
)
3762 struct glyph_string
*s
;
3765 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
3766 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3769 height
= s
->height
- 2 * box_line_vwidth
;
3772 /* Fill background with face under the image. Do it only if row is
3773 taller than image or if image has a clip mask to reduce
3775 s
->stippled_p
= s
->face
->stipple
!= 0;
3776 if (height
> s
->slice
.height
3780 || s
->img
->pixmap
== 0
3781 || s
->width
!= s
->background_width
)
3784 if (s
->first_glyph
->left_box_line_p
3786 x
+= box_line_hwidth
;
3789 if (s
->slice
.y
== 0)
3790 y
+= box_line_vwidth
;
3792 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3794 s
->background_filled_p
= 1;
3797 /* Draw the foreground. */
3798 x_draw_image_foreground (s
);
3800 /* If we must draw a relief around the image, do it. */
3802 || s
->hl
== DRAW_IMAGE_RAISED
3803 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3804 x_draw_image_relief (s
);
3808 /* Draw stretch glyph string S. */
3811 x_draw_stretch_glyph_string (s
)
3812 struct glyph_string
*s
;
3814 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3816 if (s
->hl
== DRAW_CURSOR
3817 && !x_stretch_cursor_p
)
3819 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3820 as wide as the stretch glyph. */
3821 int width
, background_width
= s
->background_width
;
3822 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3826 background_width
-= left_x
- x
;
3829 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3832 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3834 /* Clear rest using the GC of the original non-cursor face. */
3835 if (width
< background_width
)
3838 int w
= background_width
- width
, h
= s
->height
;
3843 if (s
->row
->mouse_face_p
3844 && cursor_in_mouse_face_p (s
->w
))
3846 x_set_mouse_face_gc (s
);
3852 get_glyph_string_clip_rect (s
, &r
);
3853 mac_set_clip_rectangles (s
->f
, gc
, &r
, 1);
3855 #if 0 /* MAC_TODO: stipple */
3856 if (s
->face
->stipple
)
3858 /* Fill background with a stipple pattern. */
3859 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3860 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3861 XSetFillStyle (s
->display
, gc
, FillSolid
);
3864 #endif /* MAC_TODO */
3865 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3868 else if (!s
->background_filled_p
)
3870 int background_width
= s
->background_width
;
3871 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3873 /* Don't draw into left margin, fringe or scrollbar area
3874 except for header line and mode line. */
3875 if (x
< left_x
&& !s
->row
->mode_line_p
)
3877 background_width
-= left_x
- x
;
3880 if (background_width
> 0)
3881 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3884 s
->background_filled_p
= 1;
3888 /* Draw glyph string S. */
3891 x_draw_glyph_string (s
)
3892 struct glyph_string
*s
;
3894 int relief_drawn_p
= 0;
3896 /* If S draws into the background of its successor that does not
3897 draw a cursor, draw the background of the successor first so that
3898 S can draw into it. This makes S->next use XDrawString instead
3899 of XDrawImageString. */
3900 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3901 && s
->next
->hl
!= DRAW_CURSOR
)
3903 xassert (s
->next
->img
== NULL
);
3904 x_set_glyph_string_gc (s
->next
);
3905 x_set_glyph_string_clipping (s
->next
);
3906 x_draw_glyph_string_background (s
->next
, 1);
3909 /* Set up S->gc, set clipping and draw S. */
3910 x_set_glyph_string_gc (s
);
3912 /* Draw relief (if any) in advance for char/composition so that the
3913 glyph string can be drawn over it. */
3914 if (!s
->for_overlaps
3915 && s
->face
->box
!= FACE_NO_BOX
3916 && (s
->first_glyph
->type
== CHAR_GLYPH
3917 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3920 x_set_glyph_string_clipping (s
);
3921 x_draw_glyph_string_background (s
, 1);
3922 x_draw_glyph_string_box (s
);
3923 x_set_glyph_string_clipping (s
);
3927 x_set_glyph_string_clipping (s
);
3929 switch (s
->first_glyph
->type
)
3932 x_draw_image_glyph_string (s
);
3936 x_draw_stretch_glyph_string (s
);
3940 if (s
->for_overlaps
)
3941 s
->background_filled_p
= 1;
3943 x_draw_glyph_string_background (s
, 0);
3944 x_draw_glyph_string_foreground (s
);
3947 case COMPOSITE_GLYPH
:
3948 if (s
->for_overlaps
|| s
->gidx
> 0)
3949 s
->background_filled_p
= 1;
3951 x_draw_glyph_string_background (s
, 1);
3952 x_draw_composite_glyph_string_foreground (s
);
3959 if (!s
->for_overlaps
)
3961 /* Draw underline. */
3962 if (s
->face
->underline_p
)
3964 unsigned long tem
, h
;
3968 /* Get the underline thickness. Default is 1 pixel. */
3969 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3973 y
= s
->y
+ s
->height
- h
;
3974 if (!x_underline_at_descent_line
)
3976 /* Get the underline position. This is the recommended
3977 vertical offset in pixels from the baseline to the top of
3978 the underline. This is a signed value according to the
3979 specs, and its default is
3981 ROUND ((maximum descent) / 2), with
3982 ROUND(x) = floor (x + 0.5) */
3985 if (x_use_underline_position_properties
3986 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3987 y
= s
->ybase
+ (long) tem
;
3991 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3994 if (s
->face
->underline_defaulted_p
)
3995 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3996 s
->background_width
, h
);
4000 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4001 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4002 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
4003 s
->background_width
, h
);
4004 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4008 /* Draw overline. */
4009 if (s
->face
->overline_p
)
4011 unsigned long dy
= 0, h
= 1;
4013 if (s
->face
->overline_color_defaulted_p
)
4014 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4015 s
->background_width
, h
);
4019 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4020 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4021 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4022 s
->background_width
, h
);
4023 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4027 /* Draw strike-through. */
4028 if (s
->face
->strike_through_p
)
4030 unsigned long h
= 1;
4031 unsigned long dy
= (s
->height
- h
) / 2;
4033 if (s
->face
->strike_through_color_defaulted_p
)
4034 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4039 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4040 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4041 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4043 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4047 /* Draw relief if not yet drawn. */
4048 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4049 x_draw_glyph_string_box (s
);
4052 /* Reset clipping. */
4053 mac_reset_clip_rectangles (s
->f
, s
->gc
);
4056 /* Shift display to make room for inserted glyphs. */
4059 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4061 int x
, y
, width
, height
, shift_by
;
4063 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4064 x
, y
, width
, height
,
4068 /* Delete N glyphs at the nominal cursor position. Not implemented
4079 /* Clear entire frame. If updating_frame is non-null, clear that
4080 frame. Otherwise clear the selected frame. */
4083 x_clear_frame (struct frame
*f
)
4085 /* Clearing the frame will erase any cursor, so mark them all as no
4087 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4088 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4089 output_cursor
.x
= -1;
4091 /* We don't set the output cursor here because there will always
4092 follow an explicit cursor_to. */
4094 mac_clear_window (f
);
4096 /* We have to clear the scroll bars, too. If we have changed
4097 colors or something like that, then they should be notified. */
4098 x_scroll_bar_clear (f
);
4100 XFlush (FRAME_MAC_DISPLAY (f
));
4106 /* Invert the middle quarter of the frame for .15 sec. */
4108 /* We use the select system call to do the waiting, so we have to make
4109 sure it's available. If it isn't, we just won't do visual bells. */
4111 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4114 /* Subtract the `struct timeval' values X and Y, storing the result in
4115 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4118 timeval_subtract (result
, x
, y
)
4119 struct timeval
*result
, x
, y
;
4121 /* Perform the carry for the later subtraction by updating y. This
4122 is safer because on some systems the tv_sec member is unsigned. */
4123 if (x
.tv_usec
< y
.tv_usec
)
4125 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4126 y
.tv_usec
-= 1000000 * nsec
;
4130 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4132 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4133 y
.tv_usec
+= 1000000 * nsec
;
4137 /* Compute the time remaining to wait. tv_usec is certainly
4139 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4140 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4142 /* Return indication of whether the result should be considered
4144 return x
.tv_sec
< y
.tv_sec
;
4151 /* Get the height not including a menu bar widget. */
4152 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4153 /* Height of each line to flash. */
4154 int flash_height
= FRAME_LINE_HEIGHT (f
);
4155 /* These will be the left and right margins of the rectangles. */
4156 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4157 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4161 /* Don't flash the area between a scroll bar and the frame
4162 edge it is next to. */
4163 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4165 case vertical_scroll_bar_left
:
4166 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4169 case vertical_scroll_bar_right
:
4170 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4177 width
= flash_right
- flash_left
;
4181 /* If window is tall, flash top and bottom line. */
4182 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4184 mac_invert_rectangle (f
, flash_left
,
4185 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4186 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4187 width
, flash_height
);
4188 mac_invert_rectangle (f
, flash_left
,
4189 (height
- flash_height
4190 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4191 width
, flash_height
);
4194 /* If it is short, flash it all. */
4195 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4196 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4201 struct timeval wakeup
;
4203 EMACS_GET_TIME (wakeup
);
4205 /* Compute time to wait until, propagating carry from usecs. */
4206 wakeup
.tv_usec
+= 150000;
4207 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4208 wakeup
.tv_usec
%= 1000000;
4210 /* Keep waiting until past the time wakeup or any input gets
4212 while (! detect_input_pending ())
4214 struct timeval current
;
4215 struct timeval timeout
;
4217 EMACS_GET_TIME (current
);
4219 /* Break if result would be negative. */
4220 if (timeval_subtract (¤t
, wakeup
, current
))
4223 /* How long `select' should wait. */
4225 timeout
.tv_usec
= 10000;
4227 /* Try to wait that long--but we might wake up sooner. */
4228 select (0, NULL
, NULL
, NULL
, &timeout
);
4232 /* If window is tall, flash top and bottom line. */
4233 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4235 mac_invert_rectangle (f
, flash_left
,
4236 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4237 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4238 width
, flash_height
);
4239 mac_invert_rectangle (f
, flash_left
,
4240 (height
- flash_height
4241 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4242 width
, flash_height
);
4245 /* If it is short, flash it all. */
4246 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4247 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4254 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4257 /* Make audible bell. */
4262 struct frame
*f
= SELECTED_FRAME ();
4264 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4272 XFlush (FRAME_MAC_DISPLAY (f
));
4278 /* Specify how many text lines, from the top of the window,
4279 should be affected by insert-lines and delete-lines operations.
4280 This, and those operations, are used only within an update
4281 that is bounded by calls to x_update_begin and x_update_end. */
4284 XTset_terminal_window (n
)
4287 /* This function intentionally left blank. */
4292 /***********************************************************************
4294 ***********************************************************************/
4296 /* Perform an insert-lines or delete-lines operation, inserting N
4297 lines or deleting -N lines at vertical position VPOS. */
4300 x_ins_del_lines (vpos
, n
)
4307 /* Scroll part of the display as described by RUN. */
4310 x_scroll_run (w
, run
)
4314 struct frame
*f
= XFRAME (w
->frame
);
4315 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4317 /* Get frame-relative bounding box of the text display area of W,
4318 without mode lines. Include in this box the left and right
4320 window_box (w
, -1, &x
, &y
, &width
, &height
);
4322 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4323 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4324 bottom_y
= y
+ height
;
4328 /* Scrolling up. Make sure we don't copy part of the mode
4329 line at the bottom. */
4330 if (from_y
+ run
->height
> bottom_y
)
4331 height
= bottom_y
- from_y
;
4333 height
= run
->height
;
4337 /* Scolling down. Make sure we don't copy over the mode line.
4339 if (to_y
+ run
->height
> bottom_y
)
4340 height
= bottom_y
- to_y
;
4342 height
= run
->height
;
4347 /* Cursor off. Will be switched on again in x_update_window_end. */
4351 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4361 /***********************************************************************
4363 ***********************************************************************/
4370 x_update_cursor (f
, 1);
4374 frame_unhighlight (f
)
4377 x_update_cursor (f
, 1);
4380 /* The focus has changed. Update the frames as necessary to reflect
4381 the new situation. Note that we can't change the selected frame
4382 here, because the Lisp code we are interrupting might become confused.
4383 Each event gets marked with the frame in which it occurred, so the
4384 Lisp code can tell when the switch took place by examining the events. */
4387 x_new_focus_frame (dpyinfo
, frame
)
4388 struct x_display_info
*dpyinfo
;
4389 struct frame
*frame
;
4391 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4393 if (frame
!= dpyinfo
->x_focus_frame
)
4395 /* Set this before calling other routines, so that they see
4396 the correct value of x_focus_frame. */
4397 dpyinfo
->x_focus_frame
= frame
;
4399 if (old_focus
&& old_focus
->auto_lower
)
4400 x_lower_frame (old_focus
);
4403 selected_frame
= frame
;
4404 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4406 Fselect_window (selected_frame
->selected_window
, Qnil
);
4407 choose_minibuf_frame ();
4410 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4411 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4413 pending_autoraise_frame
= 0;
4415 #if USE_MAC_FONT_PANEL
4417 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4421 x_frame_rehighlight (dpyinfo
);
4424 /* Handle FocusIn and FocusOut state changes for FRAME.
4425 If FRAME has focus and there exists more than one frame, puts
4426 a FOCUS_IN_EVENT into *BUFP. */
4429 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4431 struct mac_display_info
*dpyinfo
;
4432 struct frame
*frame
;
4433 struct input_event
*bufp
;
4435 if (type
== activeFlag
)
4437 if (dpyinfo
->x_focus_event_frame
!= frame
)
4439 x_new_focus_frame (dpyinfo
, frame
);
4440 dpyinfo
->x_focus_event_frame
= frame
;
4442 /* Don't stop displaying the initial startup message
4443 for a switch-frame event we don't need. */
4444 if (NILP (Vterminal_frame
)
4445 && CONSP (Vframe_list
)
4446 && !NILP (XCDR (Vframe_list
)))
4448 bufp
->kind
= FOCUS_IN_EVENT
;
4449 XSETFRAME (bufp
->frame_or_window
, frame
);
4455 if (dpyinfo
->x_focus_event_frame
== frame
)
4457 dpyinfo
->x_focus_event_frame
= 0;
4458 x_new_focus_frame (dpyinfo
, 0);
4463 /* The focus may have changed. Figure out if it is a real focus change,
4464 by checking both FocusIn/Out and Enter/LeaveNotify events.
4466 Returns FOCUS_IN_EVENT event in *BUFP. */
4469 x_detect_focus_change (dpyinfo
, event
, bufp
)
4470 struct mac_display_info
*dpyinfo
;
4471 const EventRecord
*event
;
4472 struct input_event
*bufp
;
4474 struct frame
*frame
;
4476 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4480 /* On Mac, this is only called from focus events, so no switch needed. */
4481 mac_focus_changed ((event
->modifiers
& activeFlag
),
4482 dpyinfo
, frame
, bufp
);
4486 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4489 x_mouse_leave (dpyinfo
)
4490 struct x_display_info
*dpyinfo
;
4492 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4495 /* The focus has changed, or we have redirected a frame's focus to
4496 another frame (this happens when a frame uses a surrogate
4497 mini-buffer frame). Shift the highlight as appropriate.
4499 The FRAME argument doesn't necessarily have anything to do with which
4500 frame is being highlighted or un-highlighted; we only use it to find
4501 the appropriate X display info. */
4504 XTframe_rehighlight (frame
)
4505 struct frame
*frame
;
4507 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4511 x_frame_rehighlight (dpyinfo
)
4512 struct x_display_info
*dpyinfo
;
4514 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4516 if (dpyinfo
->x_focus_frame
)
4518 dpyinfo
->x_highlight_frame
4519 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4520 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4521 : dpyinfo
->x_focus_frame
);
4522 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4524 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4525 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4529 dpyinfo
->x_highlight_frame
= 0;
4531 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4534 frame_unhighlight (old_highlight
);
4535 if (dpyinfo
->x_highlight_frame
)
4536 frame_highlight (dpyinfo
->x_highlight_frame
);
4542 /* Convert a keysym to its name. */
4545 x_get_keysym_name (keysym
)
4552 value
= XKeysymToString (keysym
);
4563 /* Function to report a mouse movement to the mainstream Emacs code.
4564 The input handler calls this.
4566 We have received a mouse movement event, which is given in *event.
4567 If the mouse is over a different glyph than it was last time, tell
4568 the mainstream emacs code by setting mouse_moved. If not, ask for
4569 another motion event, so we can check again the next time it moves. */
4571 static Point last_mouse_motion_position
;
4572 static Lisp_Object last_mouse_motion_frame
;
4575 note_mouse_movement (frame
, pos
)
4579 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4580 #if TARGET_API_MAC_CARBON
4584 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4585 last_mouse_motion_position
= *pos
;
4586 XSETFRAME (last_mouse_motion_frame
, frame
);
4588 if (frame
== dpyinfo
->mouse_face_mouse_frame
4589 #if TARGET_API_MAC_CARBON
4590 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4592 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4596 /* This case corresponds to LeaveNotify in X11. If we move
4597 outside the frame, then we're certainly no longer on any text
4599 clear_mouse_face (dpyinfo
);
4600 dpyinfo
->mouse_face_mouse_frame
= 0;
4601 if (!dpyinfo
->grabbed
)
4602 FRAME_RIF (frame
)->define_frame_cursor (frame
,
4603 frame
->output_data
.mac
->nontext_cursor
);
4606 /* Has the mouse moved off the glyph it was on at the last sighting? */
4607 if (frame
!= last_mouse_glyph_frame
4608 || !PtInRect (*pos
, &last_mouse_glyph
))
4610 frame
->mouse_moved
= 1;
4611 last_mouse_scroll_bar
= Qnil
;
4612 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4613 /* Remember which glyph we're now on. */
4614 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4615 last_mouse_glyph_frame
= frame
;
4623 /************************************************************************
4625 ************************************************************************/
4627 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4630 redo_mouse_highlight ()
4632 if (!NILP (last_mouse_motion_frame
)
4633 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4634 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4635 last_mouse_motion_position
.h
,
4636 last_mouse_motion_position
.v
);
4640 static struct frame
*
4641 mac_focus_frame (dpyinfo
)
4642 struct mac_display_info
*dpyinfo
;
4644 if (dpyinfo
->x_focus_frame
)
4645 return dpyinfo
->x_focus_frame
;
4647 /* Mac version may get events, such as a menu bar click, even when
4648 all the frames are invisible. In this case, we regard the
4649 event came to the selected frame. */
4650 return SELECTED_FRAME ();
4654 /* Return the current position of the mouse.
4655 *FP should be a frame which indicates which display to ask about.
4657 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4658 and *PART to the frame, window, and scroll bar part that the mouse
4659 is over. Set *X and *Y to the portion and whole of the mouse's
4660 position on the scroll bar.
4662 If the mouse movement started elsewhere, set *FP to the frame the
4663 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4666 Set *TIME to the server time-stamp for the time at which the mouse
4667 was at this position.
4669 Don't store anything if we don't have a valid set of values to report.
4671 This clears the mouse_moved flag, so we can wait for the next mouse
4675 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4678 Lisp_Object
*bar_window
;
4679 enum scroll_bar_part
*part
;
4681 unsigned long *time
;
4687 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4688 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4691 Lisp_Object frame
, tail
;
4693 /* Clear the mouse-moved flag for every frame on this display. */
4694 FOR_EACH_FRAME (tail
, frame
)
4695 XFRAME (frame
)->mouse_moved
= 0;
4697 last_mouse_scroll_bar
= Qnil
;
4699 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4700 && FRAME_LIVE_P (last_mouse_frame
))
4701 f1
= last_mouse_frame
;
4703 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4707 /* Ok, we found a frame. Store all the values.
4708 last_mouse_glyph is a rectangle used to reduce the
4709 generation of mouse events. To not miss any motion
4710 events, we must divide the frame into rectangles of the
4711 size of the smallest character that could be displayed
4712 on it, i.e. into the same rectangles that matrices on
4713 the frame are divided into. */
4716 #if TARGET_API_MAC_CARBON
4717 GetGlobalMouse (&mouse_pos
);
4718 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4719 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4721 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4722 GetMouse (&mouse_pos
);
4724 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4726 last_mouse_glyph_frame
= f1
;
4731 XSETINT (*x
, mouse_pos
.h
);
4732 XSETINT (*y
, mouse_pos
.v
);
4733 *time
= last_mouse_movement_time
;
4741 /************************************************************************
4743 ************************************************************************/
4745 #ifdef USE_TOOLKIT_SCROLL_BARS
4747 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4748 static OSStatus install_scroll_bar_timer
P_ ((void));
4749 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4750 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4751 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4752 struct input_event
*));
4753 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4755 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4756 ControlPartCode
, Point
,
4757 struct input_event
*));
4758 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4759 struct input_event
*));
4760 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4761 Point
, struct input_event
*));
4762 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4765 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4767 static int last_scroll_bar_part
;
4769 static EventLoopTimerRef scroll_bar_timer
;
4771 static int scroll_bar_timer_event_posted_p
;
4773 #define SCROLL_BAR_FIRST_DELAY 0.5
4774 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4777 scroll_bar_timer_callback (timer
, data
)
4778 EventLoopTimerRef timer
;
4783 err
= mac_post_mouse_moved_event ();
4785 scroll_bar_timer_event_posted_p
= 1;
4789 install_scroll_bar_timer ()
4791 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4793 if (scroll_bar_timer_callbackUPP
== NULL
)
4794 scroll_bar_timer_callbackUPP
=
4795 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4797 if (scroll_bar_timer
== NULL
)
4798 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4799 kEventDurationForever as delays. */
4801 InstallEventLoopTimer (GetCurrentEventLoop (),
4802 kEventDurationForever
, kEventDurationForever
,
4803 scroll_bar_timer_callbackUPP
, NULL
,
4808 set_scroll_bar_timer (delay
)
4809 EventTimerInterval delay
;
4811 if (scroll_bar_timer
== NULL
)
4812 install_scroll_bar_timer ();
4814 scroll_bar_timer_event_posted_p
= 0;
4816 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4820 control_part_code_to_scroll_bar_part (part_code
)
4821 ControlPartCode part_code
;
4825 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4826 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4827 case kControlPageUpPart
: return scroll_bar_above_handle
;
4828 case kControlPageDownPart
: return scroll_bar_below_handle
;
4829 case kControlIndicatorPart
: return scroll_bar_handle
;
4836 construct_scroll_bar_click (bar
, part
, bufp
)
4837 struct scroll_bar
*bar
;
4839 struct input_event
*bufp
;
4841 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4842 bufp
->frame_or_window
= bar
->window
;
4846 XSETINT (bufp
->x
, 0);
4847 XSETINT (bufp
->y
, 0);
4848 bufp
->modifiers
= 0;
4852 get_control_part_bounds (ch
, part_code
, rect
)
4854 ControlPartCode part_code
;
4857 RgnHandle region
= NewRgn ();
4860 err
= GetControlRegion (ch
, part_code
, region
);
4862 GetRegionBounds (region
, rect
);
4863 DisposeRgn (region
);
4869 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4870 struct scroll_bar
*bar
;
4871 ControlPartCode part_code
;
4873 struct input_event
*bufp
;
4875 int part
= control_part_code_to_scroll_bar_part (part_code
);
4880 if (part
!= scroll_bar_handle
)
4882 construct_scroll_bar_click (bar
, part
, bufp
);
4883 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4884 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4885 bar
->dragging
= Qnil
;
4891 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4892 kControlIndicatorPart
, &r
);
4893 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4896 last_scroll_bar_part
= part
;
4897 tracked_scroll_bar
= bar
;
4901 x_scroll_bar_handle_release (bar
, bufp
)
4902 struct scroll_bar
*bar
;
4903 struct input_event
*bufp
;
4905 if (last_scroll_bar_part
!= scroll_bar_handle
4906 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4907 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4909 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4910 set_scroll_bar_timer (kEventDurationForever
);
4912 last_scroll_bar_part
= -1;
4913 bar
->dragging
= Qnil
;
4914 tracked_scroll_bar
= NULL
;
4918 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4920 struct scroll_bar
*bar
;
4922 struct input_event
*bufp
;
4924 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4926 if (last_scroll_bar_part
== scroll_bar_handle
)
4931 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4932 kControlIndicatorPart
, &r
);
4934 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4935 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4937 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4938 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4942 if (top
> top_range
)
4945 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4946 XSETINT (bufp
->x
, top
);
4947 XSETINT (bufp
->y
, top_range
);
4951 ControlPartCode part_code
;
4952 int unhilite_p
= 0, part
;
4954 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4958 part
= control_part_code_to_scroll_bar_part (part_code
);
4960 switch (last_scroll_bar_part
)
4962 case scroll_bar_above_handle
:
4963 case scroll_bar_below_handle
:
4964 if (part
!= scroll_bar_above_handle
4965 && part
!= scroll_bar_below_handle
)
4969 case scroll_bar_up_arrow
:
4970 case scroll_bar_down_arrow
:
4971 if (part
!= scroll_bar_up_arrow
4972 && part
!= scroll_bar_down_arrow
)
4979 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4980 else if (part
!= last_scroll_bar_part
4981 || scroll_bar_timer_event_posted_p
)
4983 construct_scroll_bar_click (bar
, part
, bufp
);
4984 last_scroll_bar_part
= part
;
4985 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4986 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4991 /* Set the thumb size and position of scroll bar BAR. We are currently
4992 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4995 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4996 struct scroll_bar
*bar
;
4997 int portion
, position
, whole
;
4999 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5000 int value
, viewsize
, maximum
;
5002 if (XINT (bar
->track_height
) == 0)
5005 if (whole
<= portion
)
5006 value
= 0, viewsize
= 1, maximum
= 0;
5011 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
5012 scale
= (float) maximum
/ (whole
- portion
);
5013 value
= position
* scale
+ 0.5f
;
5014 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
5019 if (GetControlViewSize (ch
) != viewsize
5020 || GetControl32BitValue (ch
) != value
5021 || GetControl32BitMaximum (ch
) != maximum
)
5023 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5024 SetControlVisibility (ch
, false, false);
5026 SetControl32BitMaximum (ch
, maximum
);
5027 SetControl32BitValue (ch
, value
);
5028 SetControlViewSize (ch
, viewsize
);
5030 SetControlVisibility (ch
, true, true);
5036 #endif /* USE_TOOLKIT_SCROLL_BARS */
5040 /************************************************************************
5041 Scroll bars, general
5042 ************************************************************************/
5044 /* Create a scroll bar and return the scroll bar vector for it. W is
5045 the Emacs window on which to create the scroll bar. TOP, LEFT,
5046 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5049 static struct scroll_bar
*
5050 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5052 int top
, left
, width
, height
, disp_top
, disp_height
;
5054 struct frame
*f
= XFRAME (w
->frame
);
5055 struct scroll_bar
*bar
5056 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5064 r
.right
= left
+ width
;
5065 r
.bottom
= disp_top
+ disp_height
;
5068 mac_prepare_for_quickdraw (f
);
5070 #if TARGET_API_MAC_CARBON
5071 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5072 #ifdef USE_TOOLKIT_SCROLL_BARS
5075 width
< disp_height
,
5077 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5079 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5080 0, 0, 0, scrollBarProc
, (long) bar
);
5082 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5084 XSETWINDOW (bar
->window
, w
);
5085 XSETINT (bar
->top
, top
);
5086 XSETINT (bar
->left
, left
);
5087 XSETINT (bar
->width
, width
);
5088 XSETINT (bar
->height
, height
);
5089 XSETINT (bar
->start
, 0);
5090 XSETINT (bar
->end
, 0);
5091 bar
->dragging
= Qnil
;
5093 bar
->fringe_extended_p
= Qnil
;
5095 bar
->redraw_needed_p
= Qnil
;
5096 #ifdef USE_TOOLKIT_SCROLL_BARS
5097 bar
->track_top
= Qnil
;
5098 bar
->track_height
= Qnil
;
5099 bar
->min_handle
= Qnil
;
5102 /* Add bar to its frame's list of scroll bars. */
5103 bar
->next
= FRAME_SCROLL_BARS (f
);
5105 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5106 if (!NILP (bar
->next
))
5107 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5114 /* Draw BAR's handle in the proper position.
5116 If the handle is already drawn from START to END, don't bother
5117 redrawing it, unless REBUILD is non-zero; in that case, always
5118 redraw it. (REBUILD is handy for drawing the handle after expose
5121 Normally, we want to constrain the start and end of the handle to
5122 fit inside its rectangle, but if the user is dragging the scroll
5123 bar handle, we want to let them drag it down all the way, so that
5124 the bar's top is as far down as it goes; otherwise, there's no way
5125 to move to the very end of the buffer. */
5127 #ifndef USE_TOOLKIT_SCROLL_BARS
5130 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5131 struct scroll_bar
*bar
;
5135 int dragging
= ! NILP (bar
->dragging
);
5136 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5137 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5138 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5139 int length
= end
- start
;
5141 /* If the display is already accurate, do nothing. */
5143 && start
== XINT (bar
->start
)
5144 && end
== XINT (bar
->end
))
5149 /* Make sure the values are reasonable, and try to preserve the
5150 distance between start and end. */
5153 else if (start
> top_range
)
5155 end
= start
+ length
;
5159 else if (end
> top_range
&& ! dragging
)
5162 /* Store the adjusted setting in the scroll bar. */
5163 XSETINT (bar
->start
, start
);
5164 XSETINT (bar
->end
, end
);
5166 /* Clip the end position, just for display. */
5167 if (end
> top_range
)
5170 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5171 top positions, to make sure the handle is always at least that
5172 many pixels tall. */
5173 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5175 SetControlMinimum (ch
, 0);
5176 /* Don't inadvertently activate deactivated scroll bars */
5177 if (GetControlMaximum (ch
) != -1)
5178 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5180 SetControlValue (ch
, start
);
5181 #if TARGET_API_MAC_CARBON
5182 SetControlViewSize (ch
, end
- start
);
5188 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5190 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5194 x_scroll_bar_remove (bar
)
5195 struct scroll_bar
*bar
;
5197 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5202 mac_prepare_for_quickdraw (f
);
5204 /* Destroy the Mac scroll bar control */
5205 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5207 /* Disassociate this scroll bar from its window. */
5208 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5214 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5215 that we are displaying PORTION characters out of a total of WHOLE
5216 characters, starting at POSITION. If WINDOW has no scroll bar,
5220 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5222 int portion
, whole
, position
;
5224 struct frame
*f
= XFRAME (w
->frame
);
5225 struct scroll_bar
*bar
;
5226 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5227 int window_y
, window_height
;
5229 int fringe_extended_p
;
5232 /* Get window dimensions. */
5233 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5235 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5236 height
= window_height
;
5238 /* Compute the left edge of the scroll bar area. */
5239 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5241 /* Compute the width of the scroll bar which might be less than
5242 the width of the area reserved for the scroll bar. */
5243 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5244 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5248 /* Compute the left edge of the scroll bar. */
5249 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5250 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5252 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5254 /* Adjustments according to Inside Macintosh to make it look nice */
5256 disp_height
= height
;
5263 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5269 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5274 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5275 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5276 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5277 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5278 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5280 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5281 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5282 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5283 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5286 /* Does the scroll bar exist yet? */
5287 if (NILP (w
->vertical_scroll_bar
))
5291 if (fringe_extended_p
)
5292 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5295 mac_clear_area (f
, left
, top
, width
, height
);
5297 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5299 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5303 /* It may just need to be moved and resized. */
5306 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5307 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5311 /* If already correctly positioned, do nothing. */
5312 if (XINT (bar
->left
) == sb_left
5313 && XINT (bar
->top
) == top
5314 && XINT (bar
->width
) == sb_width
5315 && XINT (bar
->height
) == height
5317 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5321 if (!NILP (bar
->redraw_needed_p
))
5324 mac_prepare_for_quickdraw (f
);
5326 Draw1Control (SCROLL_BAR_CONTROL_REF (bar
));
5331 /* Since toolkit scroll bars are smaller than the space reserved
5332 for them on the frame, we have to clear "under" them. */
5334 if (fringe_extended_p
)
5335 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5338 mac_clear_area (f
, left
, top
, width
, height
);
5341 mac_prepare_for_quickdraw (f
);
5344 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5345 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5347 #ifndef USE_TOOLKIT_SCROLL_BARS
5348 if (sb_width
< disp_height
)
5352 /* Remember new settings. */
5353 XSETINT (bar
->left
, sb_left
);
5354 XSETINT (bar
->top
, top
);
5355 XSETINT (bar
->width
, sb_width
);
5356 XSETINT (bar
->height
, height
);
5357 #ifdef USE_TOOLKIT_SCROLL_BARS
5358 bar
->track_top
= Qnil
;
5359 bar
->track_height
= Qnil
;
5360 bar
->min_handle
= Qnil
;
5368 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5371 bar
->redraw_needed_p
= Qnil
;
5373 #ifdef USE_TOOLKIT_SCROLL_BARS
5374 if (NILP (bar
->track_top
))
5376 if (sb_width
>= disp_height
5378 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5382 XSETINT (bar
->track_top
, 0);
5383 XSETINT (bar
->track_height
, 0);
5384 XSETINT (bar
->min_handle
, 0);
5388 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5393 SetControl32BitMinimum (ch
, 0);
5394 SetControl32BitMaximum (ch
, 1 << 30);
5395 SetControlViewSize (ch
, 1);
5397 /* Move the scroll bar thumb to the top. */
5398 SetControl32BitValue (ch
, 0);
5399 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5401 /* Move the scroll bar thumb to the bottom. */
5402 SetControl32BitValue (ch
, 1 << 30);
5403 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5405 UnionRect (&r0
, &r1
, &r0
);
5406 XSETINT (bar
->track_top
, r0
.top
);
5407 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5408 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5410 /* Don't show the scroll bar if its height is not enough to
5411 display the scroll bar thumb. */
5412 if (r0
.bottom
- r0
.top
> 0)
5419 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5420 #else /* not USE_TOOLKIT_SCROLL_BARS */
5421 /* Set the scroll bar's current state, unless we're currently being
5423 if (NILP (bar
->dragging
))
5425 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5428 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5431 int start
= ((double) position
* top_range
) / whole
;
5432 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5433 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5436 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5440 /* The following three hooks are used when we're doing a thorough
5441 redisplay of the frame. We don't explicitly know which scroll bars
5442 are going to be deleted, because keeping track of when windows go
5443 away is a real pain - "Can you say set-window-configuration, boys
5444 and girls?" Instead, we just assert at the beginning of redisplay
5445 that *all* scroll bars are to be removed, and then save a scroll bar
5446 from the fiery pit when we actually redisplay its window. */
5448 /* Arrange for all scroll bars on FRAME to be removed at the next call
5449 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5450 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5453 XTcondemn_scroll_bars (frame
)
5456 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5457 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5460 bar
= FRAME_SCROLL_BARS (frame
);
5461 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5462 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5463 XSCROLL_BAR (bar
)->prev
= Qnil
;
5464 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5465 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5466 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5471 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5472 Note that WINDOW isn't necessarily condemned at all. */
5475 XTredeem_scroll_bar (window
)
5476 struct window
*window
;
5478 struct scroll_bar
*bar
;
5481 /* We can't redeem this window's scroll bar if it doesn't have one. */
5482 if (NILP (window
->vertical_scroll_bar
))
5485 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5487 /* Unlink it from the condemned list. */
5488 f
= XFRAME (WINDOW_FRAME (window
));
5489 if (NILP (bar
->prev
))
5491 /* If the prev pointer is nil, it must be the first in one of
5493 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5494 /* It's not condemned. Everything's fine. */
5496 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5497 window
->vertical_scroll_bar
))
5498 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5500 /* If its prev pointer is nil, it must be at the front of
5501 one or the other! */
5505 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5507 if (! NILP (bar
->next
))
5508 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5510 bar
->next
= FRAME_SCROLL_BARS (f
);
5512 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5513 if (! NILP (bar
->next
))
5514 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5517 /* Remove all scroll bars on FRAME that haven't been saved since the
5518 last call to `*condemn_scroll_bars_hook'. */
5521 XTjudge_scroll_bars (f
)
5524 Lisp_Object bar
, next
;
5526 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5528 /* Clear out the condemned list now so we won't try to process any
5529 more events on the hapless scroll bars. */
5530 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5532 for (; ! NILP (bar
); bar
= next
)
5534 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5536 x_scroll_bar_remove (b
);
5539 b
->next
= b
->prev
= Qnil
;
5542 /* Now there should be no references to the condemned scroll bars,
5543 and they should get garbage-collected. */
5547 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5548 is set to something other than NO_EVENT, it is enqueued.
5550 This may be called from a signal handler, so we have to ignore GC
5554 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5555 struct scroll_bar
*bar
;
5556 ControlPartCode part_code
;
5557 const EventRecord
*er
;
5558 struct input_event
*bufp
;
5560 int win_y
, top_range
;
5562 if (! WINDOWP (bar
->window
))
5565 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5566 bufp
->frame_or_window
= bar
->window
;
5569 bar
->dragging
= Qnil
;
5573 case kControlUpButtonPart
:
5574 bufp
->part
= scroll_bar_up_arrow
;
5576 case kControlDownButtonPart
:
5577 bufp
->part
= scroll_bar_down_arrow
;
5579 case kControlPageUpPart
:
5580 bufp
->part
= scroll_bar_above_handle
;
5582 case kControlPageDownPart
:
5583 bufp
->part
= scroll_bar_below_handle
;
5585 #if TARGET_API_MAC_CARBON
5588 case kControlIndicatorPart
:
5590 if (er
->what
== mouseDown
)
5591 bar
->dragging
= make_number (0);
5592 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5593 bufp
->part
= scroll_bar_handle
;
5597 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5598 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5600 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5604 if (! NILP (bar
->dragging
))
5605 win_y
-= XINT (bar
->dragging
);
5609 if (win_y
> top_range
)
5612 XSETINT (bufp
->x
, win_y
);
5613 XSETINT (bufp
->y
, top_range
);
5616 #ifndef USE_TOOLKIT_SCROLL_BARS
5618 /* Handle some mouse motion while someone is dragging the scroll bar.
5620 This may be called from a signal handler, so we have to ignore GC
5624 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5625 struct scroll_bar
*bar
;
5629 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5631 last_mouse_movement_time
= t
;
5634 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5636 /* If we're dragging the bar, display it. */
5637 if (! NILP (bar
->dragging
))
5639 /* Where should the handle be now? */
5640 int new_start
= y_pos
- 24;
5642 if (new_start
!= XINT (bar
->start
))
5644 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5646 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5651 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5653 /* Return information to the user about the current position of the mouse
5654 on the scroll bar. */
5657 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5659 Lisp_Object
*bar_window
;
5660 enum scroll_bar_part
*part
;
5662 unsigned long *time
;
5664 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5665 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5666 #if TARGET_API_MAC_CARBON
5667 WindowRef wp
= GetControlOwner (ch
);
5669 WindowRef wp
= (*ch
)->contrlOwner
;
5672 struct frame
*f
= mac_window_to_frame (wp
);
5673 int win_y
, top_range
;
5675 #if TARGET_API_MAC_CARBON
5676 GetGlobalMouse (&mouse_pos
);
5677 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5678 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5680 SetPortWindowPort (wp
);
5681 GetMouse (&mouse_pos
);
5684 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5685 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5687 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5691 if (! NILP (bar
->dragging
))
5692 win_y
-= XINT (bar
->dragging
);
5696 if (win_y
> top_range
)
5700 *bar_window
= bar
->window
;
5702 if (! NILP (bar
->dragging
))
5703 *part
= scroll_bar_handle
;
5704 else if (win_y
< XINT (bar
->start
))
5705 *part
= scroll_bar_above_handle
;
5706 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5707 *part
= scroll_bar_handle
;
5709 *part
= scroll_bar_below_handle
;
5711 XSETINT (*x
, win_y
);
5712 XSETINT (*y
, top_range
);
5715 last_mouse_scroll_bar
= Qnil
;
5717 *time
= last_mouse_movement_time
;
5721 /* The screen has been cleared so we may have changed foreground or
5722 background colors, and the scroll bars may need to be redrawn.
5723 Clear out the scroll bars, and ask for expose events, so we can
5727 x_scroll_bar_clear (f
)
5732 /* We can have scroll bars even if this is 0,
5733 if we just turned off scroll bar mode.
5734 But in that case we should not clear them. */
5735 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5736 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5737 bar
= XSCROLL_BAR (bar
)->next
)
5738 XSCROLL_BAR (bar
)->redraw_needed_p
= Qt
;
5742 /***********************************************************************
5744 ***********************************************************************/
5747 /* In identifiers such as function/variable names, Emacs tool bar is
5748 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5750 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5751 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5753 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5754 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5755 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5756 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5757 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5758 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5759 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5761 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5762 static void mac_handle_origin_change
P_ ((struct frame
*));
5763 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5767 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5774 mac_get_window_bounds (f
, &inner
, &outer
);
5776 switch (win_gravity
)
5778 case NorthWestGravity
:
5780 case SouthWestGravity
:
5781 left
+= inner
.left
- outer
.left
;
5787 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5790 case NorthEastGravity
:
5792 case SouthEastGravity
:
5793 left
+= inner
.right
- outer
.right
;
5797 switch (win_gravity
)
5799 case NorthWestGravity
:
5801 case NorthEastGravity
:
5802 top
+= inner
.top
- outer
.top
;
5808 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5811 case SouthWestGravity
:
5813 case SouthEastGravity
:
5814 top
+= inner
.bottom
- outer
.bottom
;
5818 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5822 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5829 mac_get_window_bounds (f
, &inner
, &outer
);
5831 switch (win_gravity
)
5833 case NorthWestGravity
:
5835 case SouthWestGravity
:
5842 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5843 - (inner
.right
- inner
.left
)) / 2;
5846 case NorthEastGravity
:
5848 case SouthEastGravity
:
5849 *left
= outer
.right
- (inner
.right
- inner
.left
);
5853 switch (win_gravity
)
5855 case NorthWestGravity
:
5857 case NorthEastGravity
:
5864 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5865 - (inner
.bottom
- inner
.top
)) / 2;
5868 case SouthWestGravity
:
5870 case SouthEastGravity
:
5871 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5877 mac_handle_toolbar_event (next_handler
, event
, data
)
5878 EventHandlerCallRef next_handler
;
5882 OSStatus err
, result
= eventNotHandledErr
;
5884 switch (GetEventKind (event
))
5886 case kEventToolbarGetDefaultIdentifiers
:
5890 case kEventToolbarGetAllowedIdentifiers
:
5892 CFMutableArrayRef array
;
5894 GetEventParameter (event
, kEventParamMutableArray
,
5895 typeCFMutableArrayRef
, NULL
,
5896 sizeof (CFMutableArrayRef
), NULL
, &array
);
5897 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5902 case kEventToolbarCreateItemWithIdentifier
:
5904 CFStringRef identifier
;
5905 HIToolbarItemRef item
= NULL
;
5907 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
5908 typeCFStringRef
, NULL
,
5909 sizeof (CFStringRef
), NULL
, &identifier
);
5911 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
5912 == kCFCompareEqualTo
)
5913 HIToolbarItemCreate (identifier
,
5914 kHIToolbarItemAllowDuplicates
5915 | kHIToolbarItemCantBeRemoved
, &item
);
5919 SetEventParameter (event
, kEventParamToolbarItem
,
5920 typeHIToolbarItemRef
,
5921 sizeof (HIToolbarItemRef
), &item
);
5935 mac_image_spec_to_cg_image (f
, image
)
5939 if (!valid_image_p (image
))
5943 int img_id
= lookup_image (f
, image
);
5944 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
5946 prepare_image_for_display (f
, img
);
5948 return img
->data
.ptr_val
;
5952 /* Create a tool bar for frame F. */
5955 mac_create_frame_tool_bar (f
)
5959 HIToolbarRef toolbar
;
5961 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
5965 static const EventTypeSpec specs
[] =
5966 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
5967 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
5968 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
5970 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
5971 mac_handle_toolbar_event
,
5972 GetEventTypeCount (specs
), specs
,
5977 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
5980 static const EventTypeSpec specs
[] =
5981 {{kEventClassCommand
, kEventCommandProcess
}};
5983 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
5984 mac_handle_toolbar_command_event
,
5985 GetEventTypeCount (specs
),
5989 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
5992 CFRelease (toolbar
);
5997 /* Update the tool bar for frame F. Add new buttons and remove old. */
6000 update_frame_tool_bar (f
)
6003 HIToolbarRef toolbar
= NULL
;
6005 CFArrayRef old_items
= NULL
;
6007 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
6008 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6012 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
6013 if (toolbar
== NULL
)
6015 mac_create_frame_tool_bar (f
);
6016 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
6017 if (toolbar
== NULL
)
6019 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6020 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
6023 HIToolbarCopyItems (toolbar
, &old_items
);
6024 if (old_items
== NULL
)
6027 old_count
= CFArrayGetCount (old_items
);
6029 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
6031 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
6033 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
6034 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
6037 CGImageRef cg_image
;
6039 HIToolbarItemRef item
;
6041 /* If image is a vector, choose the image according to the
6043 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6044 if (VECTORP (image
))
6048 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6049 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6052 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6053 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6055 xassert (ASIZE (image
) >= idx
);
6056 image
= AREF (image
, idx
);
6061 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6062 /* Ignore invalid image specifications. */
6063 if (cg_image
== NULL
)
6066 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6070 if (pos
< old_count
)
6072 CGImageRef old_cg_image
= NULL
;
6073 CFStringRef old_label
= NULL
;
6074 Boolean old_enabled_p
;
6076 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6078 HIToolbarItemCopyImage (item
, &old_cg_image
);
6079 if (cg_image
!= old_cg_image
)
6080 HIToolbarItemSetImage (item
, cg_image
);
6081 CGImageRelease (old_cg_image
);
6083 HIToolbarItemCopyLabel (item
, &old_label
);
6084 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6085 HIToolbarItemSetLabel (item
, label
);
6086 CFRelease (old_label
);
6088 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6089 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6090 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6095 HIToolbarCreateItemWithIdentifier (toolbar
,
6096 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6100 HIToolbarItemSetImage (item
, cg_image
);
6101 HIToolbarItemSetLabel (item
, label
);
6102 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6103 HIToolbarAppendItem (toolbar
, item
);
6111 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6116 CFRelease (old_items
);
6118 while (pos
< old_count
)
6119 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6121 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6122 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6123 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6124 toolbar visibility change. */
6125 mac_handle_origin_change (f
);
6126 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6128 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6129 /* If the title bar is completely outside the screen, adjust the
6131 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6132 kWindowConstrainMoveRegardlessOfFit
6133 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6134 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6141 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6142 doesn't deallocate the resources. */
6145 free_frame_tool_bar (f
)
6148 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6150 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6153 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6154 (NILP (Fsymbol_value
6155 (intern ("frame-notice-user-settings")))
6156 && f
== mac_focus_frame (dpyinfo
)));
6157 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6158 on toolbar visibility change. */
6159 mac_handle_origin_change (f
);
6165 mac_tool_bar_note_mouse_movement (f
, event
)
6170 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6172 HIViewRef item_view
;
6175 mouse_down_p
= (dpyinfo
->grabbed
6176 && f
== last_mouse_frame
6177 && FRAME_LIVE_P (f
));
6181 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6183 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6184 toolbar item view seems to have the same command ID with that of
6185 the toolbar item. */
6187 err
= GetControlCommandID (item_view
, &command_id
);
6188 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6190 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6192 if (i
< f
->n_tool_bar_items
)
6195 HIViewRef content_view
;
6197 err
= HIViewGetBounds (item_view
, &bounds
);
6199 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6200 kHIViewWindowContentID
, &content_view
);
6202 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6204 SetRect (&last_mouse_glyph
,
6205 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6206 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6208 help_echo_object
= help_echo_window
= Qnil
;
6210 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6211 if (NILP (help_echo_string
))
6212 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6218 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6219 EventHandlerCallRef next_handler
;
6223 OSStatus err
, result
= eventNotHandledErr
;
6224 struct frame
*f
= (struct frame
*) data
;
6227 err
= GetEventParameter (event
, kEventParamDirectObject
,
6228 typeHICommand
, NULL
,
6229 sizeof (HICommand
), NULL
, &command
);
6233 switch (GetEventKind (event
))
6235 case kEventCommandProcess
:
6236 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6237 result
= CallNextEventHandler (next_handler
, event
);
6240 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6242 if (i
< f
->n_tool_bar_items
6243 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6246 struct input_event buf
;
6250 XSETFRAME (frame
, f
);
6251 buf
.kind
= TOOL_BAR_EVENT
;
6252 buf
.frame_or_window
= frame
;
6254 kbd_buffer_store_event (&buf
);
6256 buf
.kind
= TOOL_BAR_EVENT
;
6257 buf
.frame_or_window
= frame
;
6258 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6259 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6260 kbd_buffer_store_event (&buf
);
6274 #endif /* USE_MAC_TOOLBAR */
6277 /***********************************************************************
6279 ***********************************************************************/
6281 /* Set clipping for output in glyph row ROW. W is the window in which
6282 we operate. GC is the graphics context to set clipping in.
6284 ROW may be a text row or, e.g., a mode line. Text rows must be
6285 clipped to the interior of the window dedicated to text display,
6286 mode lines must be clipped to the whole window. */
6289 x_clip_to_row (w
, row
, area
, gc
)
6291 struct glyph_row
*row
;
6295 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6297 int window_x
, window_y
, window_width
;
6299 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6301 clip_rect
.left
= window_x
;
6302 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6303 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6304 clip_rect
.right
= clip_rect
.left
+ window_width
;
6305 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6307 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6311 /* Draw a hollow box cursor on window W in glyph row ROW. */
6314 x_draw_hollow_cursor (w
, row
)
6316 struct glyph_row
*row
;
6318 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6319 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6320 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6323 struct glyph
*cursor_glyph
;
6326 /* Get the glyph the cursor is on. If we can't tell because
6327 the current matrix is invalid or such, give up. */
6328 cursor_glyph
= get_phys_cursor_glyph (w
);
6329 if (cursor_glyph
== NULL
)
6332 /* Compute frame-relative coordinates for phys cursor. */
6333 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6334 wd
= w
->phys_cursor_width
;
6336 /* The foreground of cursor_gc is typically the same as the normal
6337 background color, which can cause the cursor box to be invisible. */
6338 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6339 if (dpyinfo
->scratch_cursor_gc
)
6340 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6342 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6343 GCForeground
, &xgcv
);
6344 gc
= dpyinfo
->scratch_cursor_gc
;
6346 /* Set clipping, draw the rectangle, and reset clipping again. */
6347 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6348 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6349 mac_reset_clip_rectangles (dpy
, gc
);
6353 /* Draw a bar cursor on window W in glyph row ROW.
6355 Implementation note: One would like to draw a bar cursor with an
6356 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6357 Unfortunately, I didn't find a font yet that has this property set.
6361 x_draw_bar_cursor (w
, row
, width
, kind
)
6363 struct glyph_row
*row
;
6365 enum text_cursor_kinds kind
;
6367 struct frame
*f
= XFRAME (w
->frame
);
6368 struct glyph
*cursor_glyph
;
6370 /* If cursor is out of bounds, don't draw garbage. This can happen
6371 in mini-buffer windows when switching between echo area glyphs
6373 cursor_glyph
= get_phys_cursor_glyph (w
);
6374 if (cursor_glyph
== NULL
)
6377 /* If on an image, draw like a normal cursor. That's usually better
6378 visible than drawing a bar, esp. if the image is large so that
6379 the bar might not be in the window. */
6380 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6382 struct glyph_row
*row
;
6383 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6384 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6388 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6389 Window window
= FRAME_MAC_WINDOW (f
);
6390 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6391 unsigned long mask
= GCForeground
| GCBackground
;
6392 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6395 /* If the glyph's background equals the color we normally draw
6396 the bar cursor in, the bar cursor in its normal color is
6397 invisible. Use the glyph's foreground color instead in this
6398 case, on the assumption that the glyph's colors are chosen so
6399 that the glyph is legible. */
6400 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6401 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6403 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6406 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6409 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6410 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6414 width
= FRAME_CURSOR_WIDTH (f
);
6415 width
= min (cursor_glyph
->pixel_width
, width
);
6417 w
->phys_cursor_width
= width
;
6418 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6420 if (kind
== BAR_CURSOR
)
6421 mac_fill_rectangle (f
, gc
,
6422 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6423 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6424 width
, row
->height
);
6426 mac_fill_rectangle (f
, gc
,
6427 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6428 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6429 row
->height
- width
),
6430 cursor_glyph
->pixel_width
,
6433 mac_reset_clip_rectangles (f
, gc
);
6438 /* RIF: Define cursor CURSOR on frame F. */
6441 mac_define_frame_cursor (f
, cursor
)
6445 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6447 if (dpyinfo
->x_focus_frame
== f
)
6448 SetThemeCursor (cursor
);
6452 /* RIF: Clear area on frame F. */
6455 mac_clear_frame_area (f
, x
, y
, width
, height
)
6457 int x
, y
, width
, height
;
6459 mac_clear_area (f
, x
, y
, width
, height
);
6463 /* RIF: Draw cursor on window W. */
6466 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6468 struct glyph_row
*glyph_row
;
6470 int cursor_type
, cursor_width
;
6475 w
->phys_cursor_type
= cursor_type
;
6476 w
->phys_cursor_on_p
= 1;
6478 if (glyph_row
->exact_window_width_line_p
6479 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6481 glyph_row
->cursor_in_fringe_p
= 1;
6482 draw_fringe_bitmap (w
, glyph_row
, 0);
6485 switch (cursor_type
)
6487 case HOLLOW_BOX_CURSOR
:
6488 x_draw_hollow_cursor (w
, glyph_row
);
6491 case FILLED_BOX_CURSOR
:
6492 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6496 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6500 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6504 w
->phys_cursor_width
= 0;
6516 #if 0 /* MAC_TODO: no icon support yet. */
6518 x_bitmap_icon (f
, icon
)
6524 if (FRAME_W32_WINDOW (f
) == 0)
6528 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6529 else if (STRINGP (icon
))
6530 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6531 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6532 else if (SYMBOLP (icon
))
6536 if (EQ (icon
, intern ("application")))
6537 name
= (LPCTSTR
) IDI_APPLICATION
;
6538 else if (EQ (icon
, intern ("hand")))
6539 name
= (LPCTSTR
) IDI_HAND
;
6540 else if (EQ (icon
, intern ("question")))
6541 name
= (LPCTSTR
) IDI_QUESTION
;
6542 else if (EQ (icon
, intern ("exclamation")))
6543 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6544 else if (EQ (icon
, intern ("asterisk")))
6545 name
= (LPCTSTR
) IDI_ASTERISK
;
6546 else if (EQ (icon
, intern ("winlogo")))
6547 name
= (LPCTSTR
) IDI_WINLOGO
;
6551 hicon
= LoadIcon (NULL
, name
);
6559 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6564 #endif /* MAC_TODO */
6566 /************************************************************************
6568 ************************************************************************/
6570 /* Display Error Handling functions not used on W32. Listing them here
6571 helps diff stay in step when comparing w32term.c with xterm.c.
6573 x_error_catcher (display, error)
6574 x_catch_errors (dpy)
6575 x_catch_errors_unwind (old_val)
6576 x_check_errors (dpy, format)
6577 x_had_errors_p (dpy)
6578 x_clear_errors (dpy)
6579 x_uncatch_errors (dpy, count)
6581 x_connection_signal (signalnum)
6582 x_connection_closed (dpy, error_message)
6583 x_error_quitter (display, error)
6584 x_error_handler (display, error)
6585 x_io_error_quitter (display)
6590 /* Changing the font of the frame. */
6592 /* Give frame F the font named FONTNAME as its default font, and
6593 return the full name of that font. FONTNAME may be a wildcard
6594 pattern; in that case, we choose some font that fits the pattern.
6595 The return value shows which font we chose. */
6598 x_new_font (f
, fontname
)
6600 register char *fontname
;
6602 struct font_info
*fontp
6603 = FS_LOAD_FONT (f
, fontname
);
6608 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
6609 /* This font is already set in frame F. There's nothing more to
6611 return build_string (fontp
->full_name
);
6613 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6614 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6615 FRAME_FONTSET (f
) = -1;
6617 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6618 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6619 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6621 compute_fringe_widths (f
, 1);
6623 /* Compute the scroll bar width in character columns. */
6624 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6626 int wid
= FRAME_COLUMN_WIDTH (f
);
6627 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6628 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6632 int wid
= FRAME_COLUMN_WIDTH (f
);
6633 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6636 /* Now make the frame display the given font. */
6637 if (FRAME_MAC_WINDOW (f
) != 0)
6639 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6641 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6643 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6646 /* Don't change the size of a tip frame; there's no point in
6647 doing it because it's done in Fx_show_tip, and it leads to
6648 problems because the tip frame has no widget. */
6649 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6650 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6653 return build_string (fontp
->full_name
);
6656 /* Give frame F the fontset named FONTSETNAME as its default fontset,
6657 and return the full name of that fontset. FONTSETNAME may be a
6658 wildcard pattern; in that case, we choose some fontset that fits
6659 the pattern. FONTSETNAME may be a font name for ASCII characters;
6660 in that case, we create a fontset from that font name.
6662 The return value shows which fontset we chose.
6663 If FONTSETNAME specifies the default fontset, return Qt.
6664 If an ASCII font in the specified fontset can't be loaded, return
6668 x_new_fontset (f
, fontsetname
)
6670 Lisp_Object fontsetname
;
6672 int fontset
= fs_query_fontset (fontsetname
, 0);
6675 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
6676 /* This fontset is already set in frame F. There's nothing more
6678 return fontset_name (fontset
);
6679 else if (fontset
== 0)
6680 /* The default fontset can't be the default font. */
6684 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6686 result
= x_new_font (f
, SDATA (fontsetname
));
6688 if (!STRINGP (result
))
6689 /* Can't load ASCII font. */
6693 fontset
= new_fontset_from_font_name (result
);
6695 /* Since x_new_font doesn't update any fontset information, do it now. */
6696 FRAME_FONTSET (f
) = fontset
;
6698 return fontset_name (fontset
);
6702 /***********************************************************************
6703 TODO: W32 Input Methods
6704 ***********************************************************************/
6705 /* Listing missing functions from xterm.c helps diff stay in step.
6707 xim_destroy_callback (xim, client_data, call_data)
6708 xim_open_dpy (dpyinfo, resource_name)
6710 xim_instantiate_callback (display, client_data, call_data)
6711 xim_initialize (dpyinfo, resource_name)
6712 xim_close_dpy (dpyinfo)
6718 mac_get_window_bounds (f
, inner
, outer
)
6720 Rect
*inner
, *outer
;
6722 #if TARGET_API_MAC_CARBON
6723 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6724 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6725 #else /* not TARGET_API_MAC_CARBON */
6726 RgnHandle region
= NewRgn ();
6728 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6729 *inner
= (*region
)->rgnBBox
;
6730 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6731 *outer
= (*region
)->rgnBBox
;
6732 DisposeRgn (region
);
6733 #endif /* not TARGET_API_MAC_CARBON */
6737 mac_handle_origin_change (f
)
6740 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6744 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6746 int pixelwidth
, pixelheight
;
6750 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6751 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6753 if (cols
!= FRAME_COLS (f
)
6754 || rows
!= FRAME_LINES (f
)
6755 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6756 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6758 /* We pass 1 for DELAY since we can't run Lisp code inside of
6760 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6761 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6762 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6764 /* If cursor was outside the new size, mark it as off. */
6765 mark_window_cursors_off (XWINDOW (f
->root_window
));
6767 /* Clear out any recollection of where the mouse highlighting
6768 was, since it might be in a place that's outside the new
6769 frame size. Actually checking whether it is outside is a
6770 pain in the neck, so don't try--just let the highlighting be
6771 done afresh with new size. */
6772 cancel_mouse_face (f
);
6774 #if TARGET_API_MAC_CARBON
6775 if (f
->output_data
.mac
->hourglass_control
)
6778 mac_prepare_for_quickdraw (f
);
6780 MoveControl (f
->output_data
.mac
->hourglass_control
,
6781 pixelwidth
- HOURGLASS_WIDTH
, 0);
6788 /* Calculate the absolute position in frame F
6789 from its current recorded position values and gravity. */
6792 x_calc_absolute_position (f
)
6795 int flags
= f
->size_hint_flags
;
6798 /* We have nothing to do if the current position
6799 is already for the top-left corner. */
6800 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6803 /* Find the offsets of the outside upper-left corner of
6804 the inner window, with respect to the outer window. */
6806 mac_get_window_bounds (f
, &inner
, &outer
);
6809 /* Treat negative positions as relative to the leftmost bottommost
6810 position that fits on the screen. */
6811 if (flags
& XNegative
)
6812 f
->left_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->width
6813 - (outer
.right
- outer
.left
));
6815 if (flags
& YNegative
)
6816 f
->top_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->height
6817 - (outer
.bottom
- outer
.top
));
6819 /* The left_pos and top_pos
6820 are now relative to the top and left screen edges,
6821 so the flags should correspond. */
6822 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6825 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6826 to really change the position, and 0 when calling from
6827 x_make_frame_visible (in that case, XOFF and YOFF are the current
6828 position values). It is -1 when calling from x_set_frame_parameters,
6829 which means, do adjust for borders but don't change the gravity. */
6832 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6834 register int xoff
, yoff
;
6837 if (change_gravity
> 0)
6841 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6843 f
->size_hint_flags
|= XNegative
;
6845 f
->size_hint_flags
|= YNegative
;
6846 f
->win_gravity
= NorthWestGravity
;
6848 x_calc_absolute_position (f
);
6851 x_wm_set_size_hint (f
, (long) 0, 0);
6853 #if TARGET_API_MAC_CARBON
6854 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6855 /* If the title bar is completely outside the screen, adjust the
6857 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6858 kWindowConstrainMoveRegardlessOfFit
6859 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6860 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6861 mac_handle_origin_change (f
);
6864 Rect inner
, outer
, screen_rect
, dummy
;
6865 RgnHandle region
= NewRgn ();
6867 mac_get_window_bounds (f
, &inner
, &outer
);
6868 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6869 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6870 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6871 f
->top_pos
+ f
->y_pixels_diff
, false);
6873 /* If the title bar is completely outside the screen, adjust the
6874 position. The variable `outer' holds the title bar rectangle.
6875 The variable `inner' holds slightly smaller one than `outer',
6876 so that the calculation of overlapping may not become too
6878 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6879 outer
= (*region
)->rgnBBox
;
6880 DisposeRgn (region
);
6882 InsetRect (&inner
, 8, 8);
6883 screen_rect
= qd
.screenBits
.bounds
;
6884 screen_rect
.top
+= GetMBarHeight ();
6886 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6888 if (inner
.right
<= screen_rect
.left
)
6889 f
->left_pos
= screen_rect
.left
;
6890 else if (inner
.left
>= screen_rect
.right
)
6891 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6893 if (inner
.bottom
<= screen_rect
.top
)
6894 f
->top_pos
= screen_rect
.top
;
6895 else if (inner
.top
>= screen_rect
.bottom
)
6896 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6898 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6899 f
->top_pos
+ f
->y_pixels_diff
, false);
6907 /* Call this to change the size of frame F's x-window.
6908 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6909 for this size change and subsequent size changes.
6910 Otherwise we leave the window gravity unchanged. */
6913 x_set_window_size (f
, change_gravity
, cols
, rows
)
6918 int pixelwidth
, pixelheight
;
6922 check_frame_size (f
, &rows
, &cols
);
6923 f
->scroll_bar_actual_width
6924 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6926 compute_fringe_widths (f
, 0);
6928 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6929 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6931 f
->win_gravity
= NorthWestGravity
;
6932 x_wm_set_size_hint (f
, (long) 0, 0);
6934 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6936 #if TARGET_API_MAC_CARBON
6937 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6939 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6941 if (f
->output_data
.mac
->internal_border_width
6942 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6944 mac_clear_window (f
);
6945 f
->output_data
.mac
->internal_border_width
6946 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6949 SET_FRAME_GARBAGED (f
);
6954 /* Mouse warping. */
6956 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6959 x_set_mouse_position (f
, x
, y
)
6965 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6966 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6968 if (pix_x
< 0) pix_x
= 0;
6969 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6971 if (pix_y
< 0) pix_y
= 0;
6972 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6974 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6978 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6983 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
6984 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
6987 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
6990 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6993 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6994 0, 0, 0, 0, pix_x
, pix_y
);
7000 /* focus shifting, raising and lowering. */
7003 x_focus_on_frame (f
)
7006 #if 0 /* This proves to be unpleasant. */
7010 /* I don't think that the ICCCM allows programs to do things like this
7011 without the interaction of the window manager. Whatever you end up
7012 doing with this code, do it to x_unfocus_frame too. */
7013 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7014 RevertToPointerRoot
, CurrentTime
);
7024 /* Raise frame F. */
7030 if (f
->async_visible
)
7033 BringToFront (FRAME_MAC_WINDOW (f
));
7038 /* Lower frame F. */
7044 if (f
->async_visible
)
7047 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7053 XTframe_raise_lower (f
, raise_flag
)
7063 /* Change of visibility. */
7066 mac_handle_visibility_change (f
)
7069 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7070 int visible
= 0, iconified
= 0;
7071 struct input_event buf
;
7073 if (IsWindowVisible (wp
))
7075 if (IsWindowCollapsed (wp
))
7081 if (!f
->async_visible
&& visible
)
7085 /* wait_reading_process_output will notice this and update
7086 the frame's display structures. If we were made
7087 invisible, we should not set garbaged, because that stops
7088 redrawing on Update events. */
7089 SET_FRAME_GARBAGED (f
);
7092 buf
.kind
= DEICONIFY_EVENT
;
7093 XSETFRAME (buf
.frame_or_window
, f
);
7095 kbd_buffer_store_event (&buf
);
7097 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7098 /* Force a redisplay sooner or later to update the
7099 frame titles in case this is the second frame. */
7100 record_asynch_buffer_change ();
7102 else if (f
->async_visible
&& !visible
)
7106 buf
.kind
= ICONIFY_EVENT
;
7107 XSETFRAME (buf
.frame_or_window
, f
);
7109 kbd_buffer_store_event (&buf
);
7112 f
->async_visible
= visible
;
7113 f
->async_iconified
= iconified
;
7116 /* This tries to wait until the frame is really visible.
7117 However, if the window manager asks the user where to position
7118 the frame, this will return before the user finishes doing that.
7119 The frame will not actually be visible at that time,
7120 but it will become visible later when the window manager
7121 finishes with it. */
7124 x_make_frame_visible (f
)
7129 if (! FRAME_VISIBLE_P (f
))
7131 /* We test FRAME_GARBAGED_P here to make sure we don't
7132 call x_set_offset a second time
7133 if we get to x_make_frame_visible a second time
7134 before the window gets really visible. */
7135 if (! FRAME_ICONIFIED_P (f
)
7136 && ! f
->output_data
.mac
->asked_for_visible
)
7137 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7139 f
->output_data
.mac
->asked_for_visible
= 1;
7141 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7142 ShowWindow (FRAME_MAC_WINDOW (f
));
7145 XFlush (FRAME_MAC_DISPLAY (f
));
7147 /* Synchronize to ensure Emacs knows the frame is visible
7148 before we do anything else. We do this loop with input not blocked
7149 so that incoming events are handled. */
7154 /* This must come after we set COUNT. */
7157 XSETFRAME (frame
, f
);
7159 /* Wait until the frame is visible. Process X events until a
7160 MapNotify event has been seen, or until we think we won't get a
7161 MapNotify at all.. */
7162 for (count
= input_signal_count
+ 10;
7163 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7165 /* Force processing of queued events. */
7168 /* Machines that do polling rather than SIGIO have been
7169 observed to go into a busy-wait here. So we'll fake an
7170 alarm signal to let the handler know that there's something
7171 to be read. We used to raise a real alarm, but it seems
7172 that the handler isn't always enabled here. This is
7174 if (input_polling_used ())
7176 /* It could be confusing if a real alarm arrives while
7177 processing the fake one. Turn it off and let the
7178 handler reset it. */
7179 extern void poll_for_input_1
P_ ((void));
7180 int old_poll_suppress_count
= poll_suppress_count
;
7181 poll_suppress_count
= 1;
7182 poll_for_input_1 ();
7183 poll_suppress_count
= old_poll_suppress_count
;
7186 /* See if a MapNotify event has been processed. */
7187 FRAME_SAMPLE_VISIBILITY (f
);
7192 /* Change from mapped state to withdrawn state. */
7194 /* Make the frame visible (mapped and not iconified). */
7197 x_make_frame_invisible (f
)
7200 /* A deactivate event does not occur when the last visible frame is
7201 made invisible. So if we clear the highlight here, it will not
7202 be rehighlighted when it is made visible. */
7204 /* Don't keep the highlight on an invisible frame. */
7205 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7206 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7211 #if !TARGET_API_MAC_CARBON
7212 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7213 that the current position of the window is user-specified, rather than
7214 program-specified, so that when the window is mapped again, it will be
7215 placed at the same location, without forcing the user to position it
7216 by hand again (they have already done that once for this window.) */
7217 x_wm_set_size_hint (f
, (long) 0, 1);
7220 HideWindow (FRAME_MAC_WINDOW (f
));
7224 #if !TARGET_API_MAC_CARBON
7225 mac_handle_visibility_change (f
);
7229 /* Change window state from mapped to iconified. */
7237 /* A deactivate event does not occur when the last visible frame is
7238 iconified. So if we clear the highlight here, it will not be
7239 rehighlighted when it is deiconified. */
7241 /* Don't keep the highlight on an invisible frame. */
7242 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7243 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7246 if (f
->async_iconified
)
7251 FRAME_SAMPLE_VISIBILITY (f
);
7253 if (! FRAME_VISIBLE_P (f
))
7254 ShowWindow (FRAME_MAC_WINDOW (f
));
7256 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7261 error ("Can't notify window manager of iconification");
7263 #if !TARGET_API_MAC_CARBON
7264 mac_handle_visibility_change (f
);
7269 /* Free X resources of frame F. */
7272 x_free_frame_resources (f
)
7275 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7276 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7280 if (wp
!= tip_window
)
7281 remove_window_handler (wp
);
7284 mac_prepare_for_quickdraw (f
);
7287 if (wp
== tip_window
)
7288 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7289 closed' event. So we reset tip_window here. */
7292 free_frame_menubar (f
);
7294 if (FRAME_FACE_CACHE (f
))
7295 free_frame_faces (f
);
7299 if (FRAME_SIZE_HINTS (f
))
7300 xfree (FRAME_SIZE_HINTS (f
));
7302 xfree (f
->output_data
.mac
);
7303 f
->output_data
.mac
= NULL
;
7305 if (f
== dpyinfo
->x_focus_frame
)
7307 dpyinfo
->x_focus_frame
= 0;
7308 #if USE_MAC_FONT_PANEL
7309 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7312 if (f
== dpyinfo
->x_focus_event_frame
)
7313 dpyinfo
->x_focus_event_frame
= 0;
7314 if (f
== dpyinfo
->x_highlight_frame
)
7315 dpyinfo
->x_highlight_frame
= 0;
7317 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7319 dpyinfo
->mouse_face_beg_row
7320 = dpyinfo
->mouse_face_beg_col
= -1;
7321 dpyinfo
->mouse_face_end_row
7322 = dpyinfo
->mouse_face_end_col
= -1;
7323 dpyinfo
->mouse_face_window
= Qnil
;
7324 dpyinfo
->mouse_face_deferred_gc
= 0;
7325 dpyinfo
->mouse_face_mouse_frame
= 0;
7332 /* Destroy the X window of frame F. */
7335 x_destroy_window (f
)
7338 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7340 x_free_frame_resources (f
);
7342 dpyinfo
->reference_count
--;
7346 /* Setting window manager hints. */
7348 /* Set the normal size hints for the window manager, for frame F.
7349 FLAGS is the flags word to use--or 0 meaning preserve the flags
7350 that the window now has.
7351 If USER_POSITION is nonzero, we set the USPosition
7352 flag (this is useful when FLAGS is 0). */
7354 x_wm_set_size_hint (f
, flags
, user_position
)
7359 int base_width
, base_height
, width_inc
, height_inc
;
7360 int min_rows
= 0, min_cols
= 0;
7361 XSizeHints
*size_hints
;
7363 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7364 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7365 width_inc
= FRAME_COLUMN_WIDTH (f
);
7366 height_inc
= FRAME_LINE_HEIGHT (f
);
7368 check_frame_size (f
, &min_rows
, &min_cols
);
7370 size_hints
= FRAME_SIZE_HINTS (f
);
7371 if (size_hints
== NULL
)
7373 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7374 bzero (size_hints
, sizeof (XSizeHints
));
7377 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7378 size_hints
->width_inc
= width_inc
;
7379 size_hints
->height_inc
= height_inc
;
7380 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7381 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7382 size_hints
->base_width
= base_width
;
7383 size_hints
->base_height
= base_height
;
7386 size_hints
->flags
= flags
;
7387 else if (user_position
)
7389 size_hints
->flags
&= ~ PPosition
;
7390 size_hints
->flags
|= USPosition
;
7394 #if 0 /* MAC_TODO: hide application instead of iconify? */
7395 /* Used for IconicState or NormalState */
7398 x_wm_set_window_state (f
, state
)
7402 #ifdef USE_X_TOOLKIT
7405 XtSetArg (al
[0], XtNinitialState
, state
);
7406 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7407 #else /* not USE_X_TOOLKIT */
7408 Window window
= FRAME_X_WINDOW (f
);
7410 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7411 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7413 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7414 #endif /* not USE_X_TOOLKIT */
7418 x_wm_set_icon_pixmap (f
, pixmap_id
)
7424 #ifndef USE_X_TOOLKIT
7425 Window window
= FRAME_X_WINDOW (f
);
7430 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7431 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7435 /* It seems there is no way to turn off use of an icon pixmap.
7436 The following line does it, only if no icon has yet been created,
7437 for some window managers. But with mwm it crashes.
7438 Some people say it should clear the IconPixmapHint bit in this case,
7439 but that doesn't work, and the X consortium said it isn't the
7440 right thing at all. Since there is no way to win,
7441 best to explicitly give up. */
7443 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7449 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7453 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7454 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7457 #else /* not USE_X_TOOLKIT */
7459 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7460 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7462 #endif /* not USE_X_TOOLKIT */
7465 #endif /* MAC_TODO */
7468 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7472 #if 0 /* MAC_TODO: no icons on Mac */
7473 #ifdef USE_X_TOOLKIT
7474 Window window
= XtWindow (f
->output_data
.x
->widget
);
7476 Window window
= FRAME_X_WINDOW (f
);
7479 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7480 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7481 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7483 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7484 #endif /* MAC_TODO */
7488 /***********************************************************************
7490 ***********************************************************************/
7492 /* An XLFD pattern is divided into blocks delimited by '*'. This
7493 structure holds information for each block. */
7494 struct xlfdpat_block
7496 /* Length of the pattern string in this block. Non-zero except for
7497 the first and the last blocks. */
7500 /* Pattern string except the last character in this block. The last
7501 character is replaced with NUL in order to use it as a
7503 unsigned char *pattern
;
7505 /* Last character of the pattern string. Must not be '?'. */
7506 unsigned char last_char
;
7508 /* One of the tables for the Boyer-Moore string search. It
7509 specifies the number of positions to proceed for each character
7510 with which the match fails. */
7513 /* The skip value for the last character in the above `skip' is
7514 assigned to `infinity' in order to simplify a loop condition.
7515 The original value is saved here. */
7521 /* Normalized pattern string. "Normalized" means that capital
7522 letters are lowered, blocks are not empty except the first and
7523 the last ones, and trailing '?'s in a block that is not the last
7524 one are moved to the next one. The last character in each block
7525 is replaced with NUL. */
7528 /* Number of characters except '*'s and trailing '?'s in the
7529 normalized pattern string. */
7532 /* Number of trailing '?'s in the normalized pattern string. */
7533 int trailing_anychars
;
7535 /* Number of blocks and information for each block. The latter is
7536 NULL if the pattern is exact (no '*' or '?' in it). */
7538 struct xlfdpat_block
*blocks
;
7542 xlfdpat_destroy (pat
)
7543 struct xlfdpat
*pat
;
7550 xfree (pat
->blocks
);
7557 static struct xlfdpat
*
7558 xlfdpat_create (pattern
)
7559 const char *pattern
;
7561 struct xlfdpat
*pat
;
7562 int nblocks
, i
, skip
;
7563 unsigned char last_char
, *p
, *q
, *anychar_head
;
7564 const unsigned char *ptr
;
7565 struct xlfdpat_block
*blk
;
7567 pat
= xmalloc (sizeof (struct xlfdpat
));
7568 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7570 /* Normalize the pattern string and store it to `pat->buf'. */
7572 anychar_head
= NULL
;
7575 for (ptr
= pattern
; *ptr
; ptr
++)
7577 unsigned char c
= *ptr
;
7580 if (last_char
== '*')
7581 /* ...a** -> ...a* */
7585 if (last_char
== '?')
7587 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7588 /* ...*??* -> ...*?? */
7591 /* ...a??* -> ...a*?? */
7593 *anychar_head
++ = '*';
7601 if (last_char
!= '?')
7605 /* On Mac OS X 10.3, tolower also converts non-ASCII
7606 characters for some locales. */
7610 *q
++ = last_char
= c
;
7614 pat
->nblocks
= nblocks
;
7615 if (last_char
!= '?')
7616 pat
->trailing_anychars
= 0;
7619 pat
->trailing_anychars
= q
- anychar_head
;
7622 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7624 if (anychar_head
== NULL
&& nblocks
== 1)
7626 /* The pattern is exact. */
7631 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7633 /* Divide the normalized pattern into blocks. */
7635 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7640 blk
->len
= p
- blk
->pattern
;
7644 blk
->len
= q
- blk
->pattern
;
7646 /* Setup a table for the Boyer-Moore string search. */
7647 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7650 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7651 blk
->pattern
[blk
->len
- 1] = '\0';
7653 for (skip
= 1; skip
< blk
->len
; skip
++)
7654 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7657 for (i
= 0; i
< 256; i
++)
7658 blk
->skip
[i
] = skip
;
7660 p
= blk
->pattern
+ (blk
->len
- skip
);
7662 blk
->skip
[*p
++] = skip
;
7664 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7671 xlfdpat_exact_p (pat
)
7672 struct xlfdpat
*pat
;
7674 return pat
->blocks
== NULL
;
7677 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7678 that the pattern in *BLK matches with its prefix. Return NULL
7679 there is no such strings. STRING must be lowered in advance. */
7682 xlfdpat_block_match_1 (blk
, string
, start_max
)
7683 struct xlfdpat_block
*blk
;
7684 const unsigned char *string
;
7687 int start
, infinity
;
7689 const unsigned char *s
;
7691 xassert (blk
->len
> 0);
7692 xassert (start_max
+ blk
->len
<= strlen (string
));
7693 xassert (blk
->last_char
!= '?');
7695 /* See the comments in the function `boyer_moore' (search.c) for the
7696 use of `infinity'. */
7697 infinity
= start_max
+ blk
->len
+ 1;
7698 blk
->skip
[blk
->last_char
] = infinity
;
7703 /* Check the last character of the pattern. */
7704 s
= string
+ blk
->len
- 1;
7707 start
+= blk
->skip
[*(s
+ start
)];
7709 while (start
<= start_max
);
7711 if (start
< infinity
)
7712 /* Couldn't find the last character. */
7715 /* No less than `infinity' means we could find the last
7716 character at `s[start - infinity]'. */
7719 /* Check the remaining characters. We prefer making no-'?'
7720 cases faster because the use of '?' is really rare. */
7725 while (*p
++ == *s
++)
7728 while (*(p
- 1) == '?');
7730 if (*(p
- 1) == '\0')
7732 return string
+ start
;
7735 start
+= blk
->last_char_skip
;
7737 while (start
<= start_max
);
7742 #define xlfdpat_block_match(b, s, m) \
7743 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7744 : xlfdpat_block_match_1 (b, s, m))
7746 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7747 matches with STRING. STRING must be lowered in advance. */
7750 xlfdpat_match (pat
, string
)
7751 struct xlfdpat
*pat
;
7752 const unsigned char *string
;
7754 int str_len
, nblocks
, i
, start_max
;
7755 struct xlfdpat_block
*blk
;
7756 const unsigned char *s
;
7758 xassert (pat
->nblocks
> 0);
7760 if (xlfdpat_exact_p (pat
))
7761 return strcmp (pat
->buf
, string
) == 0;
7763 /* The number of the characters in the string must not be smaller
7764 than that in the pattern. */
7765 str_len
= strlen (string
);
7766 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7769 /* Chop off the trailing '?'s. */
7770 str_len
-= pat
->trailing_anychars
;
7772 /* The last block. When it is non-empty, it must match at the end
7774 nblocks
= pat
->nblocks
;
7775 blk
= pat
->blocks
+ (nblocks
- 1);
7777 /* The last block is also the first one. */
7778 return (str_len
== blk
->len
7779 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7780 else if (blk
->len
!= 0)
7781 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7784 /* The first block. When it is non-empty, it must match at the
7785 beginning of the string. */
7789 s
= xlfdpat_block_match (blk
, string
, 0);
7792 string
= s
+ blk
->len
;
7795 /* The rest of the blocks. */
7796 start_max
= str_len
- pat
->nchars
;
7797 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7799 s
= xlfdpat_block_match (blk
, string
, start_max
);
7802 start_max
-= s
- string
;
7803 string
= s
+ blk
->len
;
7810 /***********************************************************************
7812 ***********************************************************************/
7814 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7817 x_get_font_info (f
, font_idx
)
7821 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7824 /* the global font name table */
7825 static char **font_name_table
= NULL
;
7826 static int font_name_table_size
= 0;
7827 static int font_name_count
= 0;
7829 /* Alist linking font family names to Font Manager font family
7830 references (which can also be used as QuickDraw font IDs). We use
7831 an alist because hash tables are not ready when the terminal frame
7832 for Mac OS Classic is created. */
7833 static Lisp_Object fm_font_family_alist
;
7835 /* Hash table linking font family names to ATSU font IDs. */
7836 static Lisp_Object atsu_font_id_hash
;
7837 /* Alist linking Font Manager style to face attributes. */
7838 static Lisp_Object fm_style_face_attributes_alist
;
7839 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7842 /* Alist linking character set strings to Mac text encoding and Emacs
7844 static Lisp_Object Vmac_charset_info_alist
;
7847 create_text_encoding_info_alist ()
7849 Lisp_Object result
= Qnil
, rest
;
7851 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7853 Lisp_Object charset_info
= XCAR (rest
);
7854 Lisp_Object charset
, coding_system
, text_encoding
;
7855 Lisp_Object existing_info
;
7857 if (!(CONSP (charset_info
)
7858 && (charset
= XCAR (charset_info
),
7860 && CONSP (XCDR (charset_info
))
7861 && (text_encoding
= XCAR (XCDR (charset_info
)),
7862 INTEGERP (text_encoding
))
7863 && CONSP (XCDR (XCDR (charset_info
)))
7864 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7865 SYMBOLP (coding_system
))))
7868 existing_info
= assq_no_quit (text_encoding
, result
);
7869 if (NILP (existing_info
))
7870 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7873 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7874 XSETCDR (XCDR (existing_info
),
7875 Fcons (charset
, XCDR (XCDR (existing_info
))));
7883 decode_mac_font_name (name
, size
, coding_system
)
7886 Lisp_Object coding_system
;
7888 struct coding_system coding
;
7891 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7893 for (p
= name
; *p
; p
++)
7894 if (!isascii (*p
) || iscntrl (*p
))
7899 setup_coding_system (coding_system
, &coding
);
7900 coding
.src_multibyte
= 0;
7901 coding
.dst_multibyte
= 1;
7902 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7903 coding
.dst_bytes
= size
;
7904 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
7906 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
7907 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
7908 name
[min (coding
.produced
, size
)] = '\0';
7912 /* If there's just one occurrence of '-' in the family name, it is
7913 replaced with '_'. (More than one occurrence of '-' means a
7914 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7915 p
= strchr (name
, '-');
7916 if (p
&& strchr (p
+ 1, '-') == NULL
)
7919 for (p
= name
; *p
; p
++)
7920 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7921 for some locales. */
7928 mac_to_x_fontname (name
, size
, style
, charset
)
7936 char xf
[256], *result
;
7939 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7943 strcpy(foundry
, "Apple");
7944 strcpy(family
, name
);
7947 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7948 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7949 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7951 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7952 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7953 for (p
= result
; *p
; p
++)
7954 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7955 for some locales. */
7962 /* Parse fully-specified and instantiated X11 font spec XF, and store
7963 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7964 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7965 caller must allocate at least 256 and 32 bytes respectively. For
7966 ordinary Mac fonts, the value stored to FAMILY should just be their
7967 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7968 intlfonts collection contain their charset designation in their
7969 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7970 types of font names are handled accordingly. */
7972 const int kDefaultFontSize
= 12;
7975 parse_x_font_name (xf
, family
, size
, style
, charset
)
7982 Str31 foundry
, weight
;
7983 int point_size
, avgwidth
;
7986 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7987 foundry
, family
, weight
, slant
, size
,
7988 &point_size
, &avgwidth
, charset
) != 8
7989 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7990 foundry
, family
, weight
, slant
, size
,
7991 &point_size
, &avgwidth
, charset
) != 8)
7997 *size
= point_size
/ 10;
7998 else if (avgwidth
> 0)
7999 *size
= avgwidth
/ 10;
8002 *size
= kDefaultFontSize
;
8005 if (strcmp (weight
, "bold") == 0)
8010 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
8012 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
8014 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
8016 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
8017 but take overlap into account. */
8018 memmove (family
+ foundry_len
+ 1, family
, family_len
);
8019 memcpy (family
, foundry
, foundry_len
);
8020 family
[foundry_len
] = '-';
8021 family
[foundry_len
+ 1 + family_len
] = '-';
8022 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
8028 for (p
= family
; *p
; p
++)
8029 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8030 for some locales. */
8039 add_font_name_table_entry (char *font_name
)
8041 if (font_name_table_size
== 0)
8043 font_name_table_size
= 256;
8044 font_name_table
= (char **)
8045 xmalloc (font_name_table_size
* sizeof (char *));
8047 else if (font_name_count
+ 1 >= font_name_table_size
)
8049 font_name_table_size
*= 2;
8050 font_name_table
= (char **)
8051 xrealloc (font_name_table
,
8052 font_name_table_size
* sizeof (char *));
8055 font_name_table
[font_name_count
++] = font_name
;
8059 add_mac_font_name (name
, size
, style
, charset
)
8063 const char *charset
;
8066 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8069 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8070 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8071 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8072 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8079 fm_get_style_from_font (font
)
8083 FMFontStyle style
= normal
;
8086 FMFontFamily font_family
;
8087 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8089 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8090 some font (e.g., Optima) even if it is `bold'. */
8091 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8092 sizeof (mac_style
), &mac_style
, &len
);
8094 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8095 style
= EndianU16_BtoN (mac_style
);
8097 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8103 atsu_find_font_from_family_name (family
)
8106 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8109 Lisp_Object rest
, best
;
8110 FMFontStyle min_style
, style
;
8112 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8115 return kATSUInvalidFontID
;
8117 rest
= HASH_VALUE (h
, i
);
8118 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8119 return cons_to_long (rest
);
8121 rest
= Fnreverse (rest
);
8125 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8128 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8129 if (style
< min_style
)
8132 if (style
== normal
)
8139 while (!NILP (rest
));
8141 HASH_VALUE (h
, i
) = best
;
8142 return cons_to_long (best
);
8146 fm_style_to_face_attributes (fm_style
)
8147 FMFontStyle fm_style
;
8151 fm_style
&= (bold
| italic
);
8152 tem
= assq_no_quit (make_number (fm_style
),
8153 fm_style_face_attributes_alist
);
8157 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8158 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8159 fm_style_face_attributes_alist
=
8160 Fcons (Fcons (make_number (fm_style
), tem
),
8161 fm_style_face_attributes_alist
);
8167 atsu_find_font_family_name (font_id
)
8172 Lisp_Object family
= Qnil
;
8174 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8175 kFontMacintoshPlatform
, kFontNoScript
,
8176 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8179 family
= make_uninit_string (len
);
8180 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8181 kFontMacintoshPlatform
, kFontNoScript
,
8182 kFontNoLanguage
, len
, SDATA (family
),
8186 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8192 mac_atsu_font_face_attributes (font_id
)
8195 Lisp_Object family
, style_attrs
;
8197 family
= atsu_find_font_family_name (font_id
);
8200 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8201 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8205 /* Sets up the table font_name_table to contain the list of all fonts
8206 in the system the first time the table is used so that the Resource
8207 Manager need not be accessed every time this information is
8211 init_font_name_table ()
8213 #if TARGET_API_MAC_CARBON
8214 FMFontFamilyIterator ffi
;
8215 FMFontFamilyInstanceIterator ffii
;
8217 Lisp_Object text_encoding_info_alist
;
8218 struct gcpro gcpro1
;
8220 text_encoding_info_alist
= create_text_encoding_info_alist ();
8223 #if USE_CG_TEXT_DRAWING
8224 init_cg_text_anti_aliasing_threshold ();
8226 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8227 text_encoding_info_alist
)))
8230 struct Lisp_Hash_Table
*h
;
8232 ItemCount nfonts
, i
;
8233 ATSUFontID
*font_ids
= NULL
;
8234 Lisp_Object prev_family
= Qnil
;
8238 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8239 make_float (DEFAULT_REHASH_SIZE
),
8240 make_float (DEFAULT_REHASH_THRESHOLD
),
8242 h
= XHASH_TABLE (atsu_font_id_hash
);
8244 err
= ATSUFontCount (&nfonts
);
8247 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8248 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8251 for (i
= 0; i
< nfonts
; i
++)
8255 family
= atsu_find_font_family_name (font_ids
[i
]);
8256 if (NILP (family
) || SREF (family
, 0) == '.')
8258 if (!NILP (Fequal (prev_family
, family
)))
8259 family
= prev_family
;
8261 j
= hash_lookup (h
, family
, &hash_code
);
8264 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8265 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8268 else if (EQ (prev_family
, family
))
8269 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8271 prev_family
= family
;
8278 /* Create a dummy instance iterator here to avoid creating and
8279 destroying it in the loop. */
8280 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8282 /* Create an iterator to enumerate the font families. */
8283 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8286 FMDisposeFontFamilyInstanceIterator (&ffii
);
8290 GCPRO1 (text_encoding_info_alist
);
8292 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8298 TextEncoding encoding
;
8299 TextEncodingBase sc
;
8300 Lisp_Object text_encoding_info
, family
;
8302 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8308 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8310 sc
= GetTextEncodingBase (encoding
);
8311 text_encoding_info
= assq_no_quit (make_number (sc
),
8312 text_encoding_info_alist
);
8313 if (NILP (text_encoding_info
))
8314 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8315 text_encoding_info_alist
);
8316 decode_mac_font_name (name
, sizeof (name
),
8317 XCAR (XCDR (text_encoding_info
)));
8318 family
= build_string (name
);
8319 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8321 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8322 fm_font_family_alist
);
8324 /* Point the instance iterator at the current font family. */
8325 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8328 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8331 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8333 if (size
> 0 || style
== normal
)
8334 for (; CONSP (rest
); rest
= XCDR (rest
))
8335 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8341 /* Dispose of the iterators. */
8342 FMDisposeFontFamilyIterator (&ffi
);
8343 FMDisposeFontFamilyInstanceIterator (&ffii
);
8344 #else /* !TARGET_API_MAC_CARBON */
8346 SInt16 fontnum
, old_fontnum
;
8347 int num_mac_fonts
= CountResources('FOND');
8349 Handle font_handle
, font_handle_2
;
8350 short id
, scriptcode
;
8353 struct FontAssoc
*fat
;
8354 struct AsscEntry
*assc_entry
;
8355 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8356 struct gcpro gcpro1
;
8358 GetPort (&port
); /* save the current font number used */
8359 old_fontnum
= port
->txFont
;
8361 text_encoding_info_alist
= create_text_encoding_info_alist ();
8363 GCPRO1 (text_encoding_info_alist
);
8365 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8367 font_handle
= GetIndResource ('FOND', i
);
8371 GetResInfo (font_handle
, &id
, &type
, name
);
8372 GetFNum (name
, &fontnum
);
8374 if (fontnum
== 0 || *name
== '.')
8378 scriptcode
= FontToScript (fontnum
);
8379 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8380 text_encoding_info_alist
);
8381 if (NILP (text_encoding_info
))
8382 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8383 text_encoding_info_alist
);
8384 decode_mac_font_name (name
, sizeof (name
),
8385 XCAR (XCDR (text_encoding_info
)));
8386 family
= build_string (name
);
8387 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8389 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8390 fm_font_family_alist
);
8393 HLock (font_handle
);
8395 if (GetResourceSizeOnDisk (font_handle
)
8396 >= sizeof (struct FamRec
))
8398 fat
= (struct FontAssoc
*) (*font_handle
8399 + sizeof (struct FamRec
));
8401 = (struct AsscEntry
*) (*font_handle
8402 + sizeof (struct FamRec
)
8403 + sizeof (struct FontAssoc
));
8405 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8407 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8409 for (; CONSP (rest
); rest
= XCDR (rest
))
8410 add_mac_font_name (name
, assc_entry
->fontSize
,
8411 assc_entry
->fontStyle
,
8412 SDATA (XCAR (rest
)));
8416 HUnlock (font_handle
);
8417 font_handle_2
= GetNextFOND (font_handle
);
8418 ReleaseResource (font_handle
);
8419 font_handle
= font_handle_2
;
8421 while (ResError () == noErr
&& font_handle
);
8426 TextFont (old_fontnum
);
8427 #endif /* !TARGET_API_MAC_CARBON */
8432 mac_clear_font_name_table ()
8436 for (i
= 0; i
< font_name_count
; i
++)
8437 xfree (font_name_table
[i
]);
8438 xfree (font_name_table
);
8439 font_name_table
= NULL
;
8440 font_name_table_size
= font_name_count
= 0;
8441 fm_font_family_alist
= Qnil
;
8445 enum xlfd_scalable_field_index
8447 XLFD_SCL_PIXEL_SIZE
,
8448 XLFD_SCL_POINT_SIZE
,
8453 static const int xlfd_scalable_fields
[] =
8462 mac_do_list_fonts (pattern
, maxnames
)
8463 const char *pattern
;
8467 Lisp_Object font_list
= Qnil
;
8468 struct xlfdpat
*pat
;
8471 int scl_val
[XLFD_SCL_LAST
], *val
;
8475 if (font_name_table
== NULL
) /* Initialize when first used. */
8476 init_font_name_table ();
8478 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8481 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8482 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8483 fonts are scaled according to the specified size. */
8486 field
= xlfd_scalable_fields
;
8494 if ('0' <= *ptr
&& *ptr
<= '9')
8496 *val
= *ptr
++ - '0';
8497 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8498 *val
= *val
* 10 + *ptr
++ - '0';
8505 ptr
= strchr (ptr
, '-');
8508 while (ptr
&& i
< 14);
8510 if (i
== 14 && ptr
== NULL
)
8512 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8513 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8514 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8515 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8517 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8518 scl_val
[XLFD_SCL_POINT_SIZE
] =
8519 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8520 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8522 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8523 scl_val
[XLFD_SCL_AVGWIDTH
] =
8524 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8525 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8529 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8531 pat
= xlfdpat_create (pattern
);
8535 exact
= xlfdpat_exact_p (pat
);
8537 for (i
= 0; i
< font_name_count
; i
++)
8539 if (xlfdpat_match (pat
, font_name_table
[i
]))
8541 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8542 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8545 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8546 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8548 int former_len
= ptr
- font_name_table
[i
];
8550 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8551 memcpy (scaled
, font_name_table
[i
], former_len
);
8552 sprintf (scaled
+ former_len
,
8553 "-%d-%d-72-72-m-%d-%s",
8554 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8555 scl_val
[XLFD_SCL_POINT_SIZE
],
8556 scl_val
[XLFD_SCL_AVGWIDTH
],
8557 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8559 if (xlfdpat_match (pat
, scaled
))
8561 font_list
= Fcons (build_string (scaled
), font_list
);
8563 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8571 xlfdpat_destroy (pat
);
8576 /* Return a list of names of available fonts matching PATTERN on frame F.
8578 Frame F null means we have not yet created any frame on Mac, and
8579 consult the first display in x_display_list. MAXNAMES sets a limit
8580 on how many fonts to match. */
8583 x_list_fonts (f
, pattern
, size
, maxnames
)
8585 Lisp_Object pattern
;
8588 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8589 struct mac_display_info
*dpyinfo
8590 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8592 xassert (size
<= 0);
8594 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8595 if (NILP (patterns
))
8596 patterns
= Fcons (pattern
, Qnil
);
8598 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8600 pattern
= XCAR (patterns
);
8602 if (!STRINGP (pattern
))
8605 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8606 key
= Fcons (pattern
, make_number (maxnames
));
8608 list
= Fassoc (key
, tem
);
8611 list
= Fcdr_safe (list
);
8612 /* We have a cashed list. Don't have to get the list again. */
8617 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8620 /* MAC_TODO: add code for matching outline fonts here */
8622 /* Now store the result in the cache. */
8623 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8624 Fcons (Fcons (key
, list
),
8625 XCAR (XCDR (dpyinfo
->name_list_element
))));
8628 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8637 /* Check that FONT is valid on frame F. It is if it can be found in F's
8641 x_check_font (f
, font
)
8646 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8648 xassert (font
!= NULL
);
8650 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8651 if (dpyinfo
->font_table
[i
].name
8652 && font
== dpyinfo
->font_table
[i
].font
)
8655 xassert (i
< dpyinfo
->n_fonts
);
8658 #endif /* GLYPH_DEBUG != 0 */
8660 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8661 Note: There are (broken) X fonts out there with invalid XFontStruct
8662 min_bounds contents. For example, handa@etl.go.jp reports that
8663 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8664 have font->min_bounds.width == 0. */
8667 x_font_min_bounds (font
, w
, h
)
8668 MacFontStruct
*font
;
8671 *h
= FONT_HEIGHT (font
);
8672 *w
= font
->min_bounds
.width
;
8676 /* Compute the smallest character width and smallest font height over
8677 all fonts available on frame F. Set the members smallest_char_width
8678 and smallest_font_height in F's x_display_info structure to
8679 the values computed. Value is non-zero if smallest_font_height or
8680 smallest_char_width become smaller than they were before. */
8683 x_compute_min_glyph_bounds (f
)
8687 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8688 MacFontStruct
*font
;
8689 int old_width
= dpyinfo
->smallest_char_width
;
8690 int old_height
= dpyinfo
->smallest_font_height
;
8692 dpyinfo
->smallest_font_height
= 100000;
8693 dpyinfo
->smallest_char_width
= 100000;
8695 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8696 if (dpyinfo
->font_table
[i
].name
)
8698 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8701 font
= (MacFontStruct
*) fontp
->font
;
8702 xassert (font
!= (MacFontStruct
*) ~0);
8703 x_font_min_bounds (font
, &w
, &h
);
8705 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8706 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8709 xassert (dpyinfo
->smallest_char_width
> 0
8710 && dpyinfo
->smallest_font_height
> 0);
8712 return (dpyinfo
->n_fonts
== 1
8713 || dpyinfo
->smallest_char_width
< old_width
8714 || dpyinfo
->smallest_font_height
< old_height
);
8718 /* Determine whether given string is a fully-specified XLFD: all 14
8719 fields are present, none is '*'. */
8722 is_fully_specified_xlfd (p
)
8731 for (i
= 0; i
< 13; i
++)
8733 q
= strchr (p
+ 1, '-');
8736 if (q
- p
== 2 && *(p
+ 1) == '*')
8741 if (strchr (p
+ 1, '-') != NULL
)
8744 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8751 /* mac_load_query_font creates and returns an internal representation
8752 for a font in a MacFontStruct struct. There is really no concept
8753 corresponding to "loading" a font on the Mac. But we check its
8754 existence and find the font number and all other information for it
8755 and store them in the returned MacFontStruct. */
8757 static MacFontStruct
*
8758 mac_load_query_font (f
, fontname
)
8768 static ATSUFontID font_id
;
8769 ATSUStyle mac_style
= NULL
;
8772 #if TARGET_API_MAC_CARBON
8773 TextEncoding encoding
;
8778 MacFontStruct
*font
;
8779 XCharStruct
*space_bounds
= NULL
, *pcm
;
8781 if (is_fully_specified_xlfd (fontname
))
8785 Lisp_Object matched_fonts
;
8787 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8788 if (NILP (matched_fonts
))
8790 name
= SDATA (XCAR (matched_fonts
));
8793 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8797 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8800 static const ATSUAttributeTag tags
[] =
8801 {kATSUFontTag
, kATSUSizeTag
,
8802 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8803 static const ByteCount sizes
[] =
8804 {sizeof (ATSUFontID
), sizeof (Fixed
),
8805 sizeof (Boolean
), sizeof (Boolean
)};
8806 static Fixed size_fixed
;
8807 static Boolean bold_p
, italic_p
;
8808 static const ATSUAttributeValuePtr values
[] =
8809 {&font_id
, &size_fixed
,
8810 &bold_p
, &italic_p
};
8811 static const ATSUFontFeatureType types
[] =
8812 {kAllTypographicFeaturesType
, kDiacriticsType
};
8813 static const ATSUFontFeatureSelector selectors
[] =
8814 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8817 font_id
= atsu_find_font_from_family_name (family
);
8818 if (font_id
== kATSUInvalidFontID
)
8820 size_fixed
= Long2Fix (size
);
8821 bold_p
= (fontface
& bold
) != 0;
8822 italic_p
= (fontface
& italic
) != 0;
8823 err
= ATSUCreateStyle (&mac_style
);
8826 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8830 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8831 tags
, sizes
, values
);
8834 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8837 scriptcode
= kTextEncodingMacUnicode
;
8842 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8846 fontnum
= XINT (XCDR (tmp
));
8847 #if TARGET_API_MAC_CARBON
8848 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8850 scriptcode
= GetTextEncodingBase (encoding
);
8852 scriptcode
= FontToScript (fontnum
);
8856 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8858 font
->mac_fontnum
= fontnum
;
8859 font
->mac_fontsize
= size
;
8860 font
->mac_fontface
= fontface
;
8861 font
->mac_scriptcode
= scriptcode
;
8863 font
->mac_style
= mac_style
;
8864 #if USE_CG_TEXT_DRAWING
8865 font
->cg_font
= NULL
;
8866 font
->cg_glyphs
= NULL
;
8870 /* Apple Japanese (SJIS) font is listed as both
8871 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8872 (Roman script) in init_font_name_table (). The latter should be
8873 treated as a one-byte font. */
8874 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8875 font
->mac_scriptcode
= smRoman
;
8877 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8880 if (font
->mac_style
)
8885 font
->min_byte1
= 0;
8886 font
->max_byte1
= 0xff;
8887 font
->min_char_or_byte2
= 0;
8888 font
->max_char_or_byte2
= 0xff;
8890 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8891 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8892 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8893 pcm_init (font
->bounds
.rows
[0], 0x100);
8895 #if USE_CG_TEXT_DRAWING
8899 ATSFontRef ats_font
;
8901 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8903 /* Use CG text drawing if italic/bold is not synthesized. */
8904 if (err
== noErr
&& style
== fontface
)
8906 ats_font
= FMGetATSFontRefFromFont (font_id
);
8907 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8913 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8914 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8917 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8918 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8919 &font
->ascent
, &font
->descent
,
8921 #if USE_CG_TEXT_DRAWING
8922 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8929 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8931 mac_unload_font (&one_mac_display_info
, font
);
8935 pcm
= font
->bounds
.rows
[0];
8936 for (c
= 0x21; c
<= 0xff; c
++)
8939 /* Soft hyphen is not supported in ATSUI. */
8943 #if USE_CG_TEXT_DRAWING
8944 if (font
->cg_glyphs
)
8954 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8955 pcm
? pcm
+ c
: NULL
,
8956 #if USE_CG_TEXT_DRAWING
8957 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8964 #if USE_CG_TEXT_DRAWING
8965 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8967 /* Don't use CG text drawing if font substitution occurs in
8968 ASCII or Latin-1 characters. */
8969 CGFontRelease (font
->cg_font
);
8970 font
->cg_font
= NULL
;
8971 xfree (font
->cg_glyphs
);
8972 font
->cg_glyphs
= NULL
;
8983 FontInfo the_fontinfo
;
8984 int is_two_byte_font
;
8987 mac_prepare_for_quickdraw (f
);
8989 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8993 TextFace (fontface
);
8995 GetFontInfo (&the_fontinfo
);
8997 font
->ascent
= the_fontinfo
.ascent
;
8998 font
->descent
= the_fontinfo
.descent
;
9000 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
9001 || font
->mac_scriptcode
== smTradChinese
9002 || font
->mac_scriptcode
== smSimpChinese
9003 || font
->mac_scriptcode
== smKorean
);
9005 if (is_two_byte_font
)
9009 font
->min_byte1
= 0xa1;
9010 font
->max_byte1
= 0xfe;
9011 font
->min_char_or_byte2
= 0xa1;
9012 font
->max_char_or_byte2
= 0xfe;
9014 /* Use the width of an "ideographic space" of that font
9015 because the_fontinfo.widMax returns the wrong width for
9017 switch (font
->mac_scriptcode
)
9020 font
->min_byte1
= 0x81;
9021 font
->max_byte1
= 0xfc;
9022 font
->min_char_or_byte2
= 0x40;
9023 font
->max_char_or_byte2
= 0xfc;
9024 char_width
= StringWidth("\p\x81\x40");
9027 font
->min_char_or_byte2
= 0x40;
9028 char_width
= StringWidth("\p\xa1\x40");
9031 char_width
= StringWidth("\p\xa1\xa1");
9034 char_width
= StringWidth("\p\xa1\xa1");
9038 font
->bounds
.per_char
= NULL
;
9040 if (fontface
& italic
)
9041 font
->max_bounds
.rbearing
= char_width
+ 1;
9043 font
->max_bounds
.rbearing
= char_width
;
9044 font
->max_bounds
.lbearing
= 0;
9045 font
->max_bounds
.width
= char_width
;
9046 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
9047 font
->max_bounds
.descent
= the_fontinfo
.descent
;
9049 font
->min_bounds
= font
->max_bounds
;
9055 font
->min_byte1
= font
->max_byte1
= 0;
9056 font
->min_char_or_byte2
= 0x20;
9057 font
->max_char_or_byte2
= 0xff;
9059 font
->bounds
.per_char
=
9060 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9061 bzero (font
->bounds
.per_char
,
9062 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9064 space_bounds
= font
->bounds
.per_char
;
9065 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9066 &font
->descent
, space_bounds
, NULL
);
9067 if (err
!= noErr
|| space_bounds
->width
<= 0)
9069 mac_unload_font (&one_mac_display_info
, font
);
9073 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9074 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9082 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9083 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9086 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9088 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9090 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9092 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9094 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9097 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9099 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9101 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9103 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9105 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9110 font
->mac_style
== NULL
&&
9112 font
->max_bounds
.width
== font
->min_bounds
.width
9113 && font
->min_bounds
.lbearing
>= 0
9114 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9116 /* Fixed width and no overhangs. */
9117 xfree (font
->bounds
.per_char
);
9118 font
->bounds
.per_char
= NULL
;
9122 #if !defined (MAC_OS8) || USE_ATSUI
9123 /* AppKit and WebKit do some adjustment to the heights of Courier,
9124 Helvetica, and Times. This only works on the environments where
9125 srcCopy text transfer mode is never used. */
9127 #ifdef MAC_OS8 /* implies USE_ATSUI */
9130 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9131 || strcmp (family
, "times") == 0))
9132 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9140 mac_unload_font (dpyinfo
, font
)
9141 struct mac_display_info
*dpyinfo
;
9144 xfree (font
->full_name
);
9146 if (font
->mac_style
)
9150 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9151 if (font
->bounds
.rows
[i
])
9152 xfree (font
->bounds
.rows
[i
]);
9153 xfree (font
->bounds
.rows
);
9154 ATSUDisposeStyle (font
->mac_style
);
9158 if (font
->bounds
.per_char
)
9159 xfree (font
->bounds
.per_char
);
9160 #if USE_CG_TEXT_DRAWING
9162 CGFontRelease (font
->cg_font
);
9163 if (font
->cg_glyphs
)
9164 xfree (font
->cg_glyphs
);
9170 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9171 pointer to the structure font_info while allocating it dynamically.
9172 If SIZE is 0, load any size of font.
9173 If loading is failed, return NULL. */
9176 x_load_font (f
, fontname
, size
)
9178 register char *fontname
;
9181 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9182 Lisp_Object font_names
;
9184 /* Get a list of all the fonts that match this name. Once we
9185 have a list of matching fonts, we compare them against the fonts
9186 we already have by comparing names. */
9187 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9189 if (!NILP (font_names
))
9194 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9195 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9196 if (dpyinfo
->font_table
[i
].name
9197 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9198 SDATA (XCAR (tail
)))
9199 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9200 SDATA (XCAR (tail
)))))
9201 return (dpyinfo
->font_table
+ i
);
9206 /* Load the font and add it to the table. */
9208 struct MacFontStruct
*font
;
9209 struct font_info
*fontp
;
9212 fontname
= (char *) SDATA (XCAR (font_names
));
9215 font
= mac_load_query_font (f
, fontname
);
9220 /* Find a free slot in the font table. */
9221 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9222 if (dpyinfo
->font_table
[i
].name
== NULL
)
9225 /* If no free slot found, maybe enlarge the font table. */
9226 if (i
== dpyinfo
->n_fonts
9227 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9230 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9231 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9233 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9236 fontp
= dpyinfo
->font_table
+ i
;
9237 if (i
== dpyinfo
->n_fonts
)
9240 /* Now fill in the slots of *FONTP. */
9242 bzero (fontp
, sizeof (*fontp
));
9244 fontp
->font_idx
= i
;
9245 fontp
->charset
= -1; /* fs_load_font sets it. */
9246 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9247 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9249 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9251 /* Fixed width font. */
9252 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9259 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9260 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9262 fontp
->space_width
= pcm
->width
;
9264 fontp
->space_width
= FONT_WIDTH (font
);
9268 int width
= pcm
->width
;
9269 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9270 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9271 width
+= pcm
->width
;
9272 fontp
->average_width
= width
/ 95;
9275 fontp
->average_width
= FONT_WIDTH (font
);
9278 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9279 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9281 fontp
->size
= font
->max_bounds
.width
;
9282 fontp
->height
= FONT_HEIGHT (font
);
9284 /* For some font, ascent and descent in max_bounds field is
9285 larger than the above value. */
9286 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9287 if (max_height
> fontp
->height
)
9288 fontp
->height
= max_height
;
9291 /* MAC_TODO: The script encoding is irrelevant in unicode? */
9292 /* The slot `encoding' specifies how to map a character
9293 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9294 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9295 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9296 2:0xA020..0xFF7F). For the moment, we don't know which charset
9297 uses this font. So, we set information in fontp->encoding_type
9298 which is never used by any charset. If mapping can't be
9299 decided, set FONT_ENCODING_NOT_DECIDED. */
9300 if (font
->mac_scriptcode
== smJapanese
)
9301 fontp
->encoding_type
= 4;
9304 fontp
->encoding_type
9305 = (font
->max_byte1
== 0
9307 ? (font
->min_char_or_byte2
< 0x80
9308 ? (font
->max_char_or_byte2
< 0x80
9309 ? 0 /* 0x20..0x7F */
9310 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9311 : 1) /* 0xA0..0xFF */
9313 : (font
->min_byte1
< 0x80
9314 ? (font
->max_byte1
< 0x80
9315 ? (font
->min_char_or_byte2
< 0x80
9316 ? (font
->max_char_or_byte2
< 0x80
9317 ? 0 /* 0x2020..0x7F7F */
9318 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9319 : 3) /* 0x20A0..0x7FFF */
9320 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9321 : (font
->min_char_or_byte2
< 0x80
9322 ? (font
->max_char_or_byte2
< 0x80
9323 ? 2 /* 0xA020..0xFF7F */
9324 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9325 : 1))); /* 0xA0A0..0xFFFF */
9328 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9329 fontp
->baseline_offset
9330 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9331 ? (long) value
: 0);
9332 fontp
->relative_compose
9333 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9334 ? (long) value
: 0);
9335 fontp
->default_ascent
9336 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9337 ? (long) value
: 0);
9339 fontp
->baseline_offset
= 0;
9340 fontp
->relative_compose
= 0;
9341 fontp
->default_ascent
= 0;
9344 /* Set global flag fonts_changed_p to non-zero if the font loaded
9345 has a character with a smaller width than any other character
9346 before, or if the font loaded has a smaller height than any
9347 other font loaded before. If this happens, it will make a
9348 glyph matrix reallocation necessary. */
9349 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9356 /* Return a pointer to struct font_info of a font named FONTNAME for
9357 frame F. If no such font is loaded, return NULL. */
9360 x_query_font (f
, fontname
)
9362 register char *fontname
;
9364 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9367 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9368 if (dpyinfo
->font_table
[i
].name
9369 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9370 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9371 return (dpyinfo
->font_table
+ i
);
9376 /* Find a CCL program for a font specified by FONTP, and set the member
9377 `encoder' of the structure. */
9380 x_find_ccl_program (fontp
)
9381 struct font_info
*fontp
;
9383 Lisp_Object list
, elt
;
9385 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9389 && STRINGP (XCAR (elt
))
9390 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9396 struct ccl_program
*ccl
9397 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9399 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9402 fontp
->font_encoder
= ccl
;
9406 #if USE_MAC_FONT_PANEL
9407 /* Whether Font Panel has been shown before. The first call to font
9408 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9409 slow. This variable is used for deferring such a call as much as
9411 static int font_panel_shown_p
= 0;
9413 extern Lisp_Object Qfont
;
9414 static Lisp_Object Qpanel_closed
, Qselection
;
9416 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9420 const EventParamName
*,
9421 const EventParamType
*));
9424 mac_font_panel_visible_p ()
9426 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9429 static pascal OSStatus
9430 mac_handle_font_event (next_handler
, event
, data
)
9431 EventHandlerCallRef next_handler
;
9435 OSStatus result
, err
;
9438 const EventParamName
*names
;
9439 const EventParamType
*types
;
9440 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9441 kEventParamATSUFontSize
,
9442 kEventParamFMFontFamily
,
9443 kEventParamFMFontStyle
,
9444 kEventParamFMFontSize
,
9445 kEventParamFontColor
};
9446 static const EventParamType types_sel
[] = {typeATSUFontID
,
9453 result
= CallNextEventHandler (next_handler
, event
);
9454 if (result
!= eventNotHandledErr
)
9457 switch (GetEventKind (event
))
9459 case kEventFontPanelClosed
:
9460 id_key
= Qpanel_closed
;
9466 case kEventFontSelection
:
9467 id_key
= Qselection
;
9468 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9474 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9484 mac_show_hide_font_panel ()
9486 if (!font_panel_shown_p
)
9490 static const EventTypeSpec specs
[] =
9491 {{kEventClassFont
, kEventFontPanelClosed
},
9492 {kEventClassFont
, kEventFontSelection
}};
9494 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9495 GetEventTypeCount (specs
),
9500 font_panel_shown_p
= 1;
9503 return FPShowHideFontPanel ();
9507 mac_set_font_info_for_selection (f
, face_id
, c
)
9512 EventTargetRef target
= NULL
;
9513 XFontStruct
*font
= NULL
;
9515 if (!mac_font_panel_visible_p ())
9520 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9522 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9526 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9527 face
= FACE_FROM_ID (f
, face_id
);
9533 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9536 if (font
->mac_fontnum
!= -1)
9538 FontSelectionQDStyle qd_style
;
9540 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9541 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9542 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9543 qd_style
.size
= font
->mac_fontsize
;
9544 qd_style
.hasColor
= false;
9546 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9547 1, &qd_style
, target
);
9550 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9551 1, &font
->mac_style
, target
);
9559 /* The Mac Event loop code */
9561 #if !TARGET_API_MAC_CARBON
9563 #include <Quickdraw.h>
9564 #include <Balloons.h>
9565 #include <Devices.h>
9567 #include <Gestalt.h>
9569 #include <Processes.h>
9571 #include <ToolUtils.h>
9572 #include <TextUtils.h>
9573 #include <Dialogs.h>
9576 #include <Resources.h>
9581 #endif /* ! TARGET_API_MAC_CARBON */
9586 #define DEFAULT_NUM_COLS 80
9588 #define MIN_DOC_SIZE 64
9589 #define MAX_DOC_SIZE 32767
9591 #define EXTRA_STACK_ALLOC (256 * 1024)
9593 #define ARGV_STRING_LIST_ID 129
9594 #define ABOUT_ALERT_ID 128
9595 #define RAM_TOO_LARGE_ALERT_ID 129
9597 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9598 Lisp_Object Qreverse
;
9601 /* Modifier associated with the control key, or nil to ignore. */
9602 Lisp_Object Vmac_control_modifier
;
9604 /* Modifier associated with the option key, or nil to ignore. */
9605 Lisp_Object Vmac_option_modifier
;
9607 /* Modifier associated with the command key, or nil to ignore. */
9608 Lisp_Object Vmac_command_modifier
;
9610 /* Modifier associated with the function key, or nil to ignore. */
9611 Lisp_Object Vmac_function_modifier
;
9613 /* True if the option and command modifiers should be used to emulate
9614 a three button mouse */
9615 Lisp_Object Vmac_emulate_three_button_mouse
;
9617 #if TARGET_API_MAC_CARBON
9618 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9619 mouse-2, instead of mouse-3. */
9620 int mac_wheel_button_is_mouse_2
;
9622 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9623 for processing before Emacs sees it. */
9624 int mac_pass_command_to_system
;
9626 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9627 for processing before Emacs sees it. */
9628 int mac_pass_control_to_system
;
9631 /* Points to the variable `inev' in the function XTread_socket. It is
9632 used for passing an input event to the function back from
9633 Carbon/Apple event handlers. */
9634 static struct input_event
*read_socket_inev
= NULL
;
9636 /* Whether or not the screen configuration has changed. */
9637 static int mac_screen_config_changed
= 0;
9639 Point saved_menu_event_location
;
9642 #if TARGET_API_MAC_CARBON
9643 static Lisp_Object Qhi_command
;
9645 extern Lisp_Object Qwindow
;
9646 static Lisp_Object Qtoolbar_switch_mode
;
9649 static TSMDocumentID tsm_document_id
;
9650 Lisp_Object Qtext_input
;
9651 Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9652 Lisp_Object Vmac_ts_active_input_overlay
, Vmac_ts_active_input_buf
;
9653 extern Lisp_Object Qbefore_string
;
9654 static Lisp_Object Vmac_ts_script_language_on_focus
;
9655 static Lisp_Object saved_ts_script_language_on_focus
;
9656 static ScriptLanguageRecord saved_ts_language
;
9657 static Component saved_ts_component
;
9659 #endif /* TARGET_API_MAC_CARBON */
9660 extern int mac_ready_for_apple_events
;
9661 extern Lisp_Object Qundefined
;
9662 extern void init_apple_event_handler
P_ ((void));
9663 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9664 Lisp_Object
*, Lisp_Object
*,
9666 extern OSErr init_coercion_handler
P_ ((void));
9669 extern OSErr install_drag_handler
P_ ((WindowRef
));
9670 extern void remove_drag_handler
P_ ((WindowRef
));
9672 #if TARGET_API_MAC_CARBON
9673 /* Showing help echo string during menu tracking */
9674 extern OSStatus install_menu_target_item_handler
P_ ((void));
9677 extern OSStatus
install_service_handler ();
9678 Lisp_Object Qservice
, Qpaste
, Qperform
;
9679 Lisp_Object Qmouse_drag_overlay
;
9683 extern void init_emacs_passwd_dir ();
9684 extern int emacs_main (int, char **, char **);
9686 extern void initialize_applescript();
9687 extern void terminate_applescript();
9689 /* Table for translating Mac keycode to X keysym values. Contributed
9691 Mapping for special keys is now identical to that in Apple X11
9692 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9693 on the right of the Cmd key on laptops, and fn + `enter' (->
9695 static const unsigned char keycode_to_xkeysym_table
[] = {
9696 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9697 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9698 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9700 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9701 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9702 /*0x38*/ 0, 0, 0, 0,
9703 /*0x3C*/ 0, 0, 0, 0,
9705 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9706 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9707 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9708 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9710 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9711 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9712 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9713 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9715 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9716 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9717 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9718 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9720 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9721 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9722 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9723 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9727 /* Table for translating Mac keycode with the laptop `fn' key to that
9728 without it. Destination symbols in comments are keys on US
9729 keyboard, and they may not be the same on other types of keyboards.
9730 If the destination is identical to the source (f1 ... f12), it
9731 doesn't map `fn' key to a modifier. */
9732 static const unsigned char fn_keycode_to_keycode_table
[] = {
9733 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9734 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9735 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9737 /*0x30*/ 0, 0, 0, 0,
9738 /*0x34*/ 0, 0, 0, 0,
9739 /*0x38*/ 0, 0, 0, 0,
9740 /*0x3C*/ 0, 0, 0, 0,
9742 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9743 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9744 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9745 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9747 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9748 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9749 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9750 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9752 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9753 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9754 /*0x68*/ 0, 0, 0, 0,
9755 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9757 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9758 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9759 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9762 #endif /* MAC_OSX */
9765 #if TARGET_API_MAC_CARBON
9766 mac_to_emacs_modifiers (UInt32 mods
)
9768 mac_to_emacs_modifiers (EventModifiers mods
)
9771 unsigned int result
= 0;
9772 if (mods
& shiftKey
)
9773 result
|= shift_modifier
;
9775 /* Deactivated to simplify configuration:
9776 if Vmac_option_modifier is non-NIL, we fully process the Option
9777 key. Otherwise, we only process it if an additional Ctrl or Command
9778 is pressed. That way the system may convert the character to a
9780 if ((mods & optionKey) &&
9781 (( !NILP(Vmac_option_modifier) ||
9782 ((mods & cmdKey) || (mods & controlKey))))) */
9784 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9785 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9787 result
|= XUINT(val
);
9789 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9790 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9792 result
|= XUINT(val
);
9794 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9795 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9797 result
|= XUINT(val
);
9801 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9802 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9804 result
|= XUINT(val
);
9812 mac_mapped_modifiers (modifiers
)
9815 UInt32 mapped_modifiers_all
=
9816 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9817 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9818 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9821 mapped_modifiers_all
|=
9822 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9825 return mapped_modifiers_all
& modifiers
;
9829 mac_get_emulated_btn ( UInt32 modifiers
)
9832 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9833 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9834 if (modifiers
& cmdKey
)
9835 result
= cmdIs3
? 2 : 1;
9836 else if (modifiers
& optionKey
)
9837 result
= cmdIs3
? 1 : 2;
9844 mac_get_selected_range (w
, range
)
9848 Lisp_Object overlay
= find_symbol_value (Qmouse_drag_overlay
);
9849 struct buffer
*b
= XBUFFER (w
->buffer
);
9850 int begv
= BUF_BEGV (b
), zv
= BUF_ZV (b
);
9853 if (OVERLAYP (overlay
)
9854 && EQ (Foverlay_buffer (overlay
), w
->buffer
)
9855 && (start
= XINT (Foverlay_start (overlay
)),
9856 end
= XINT (Foverlay_end (overlay
)),
9861 if (w
== XWINDOW (selected_window
) && b
== current_buffer
)
9864 start
= marker_position (w
->pointm
);
9866 if (NILP (Vtransient_mark_mode
) || NILP (b
->mark_active
))
9870 int mark_pos
= marker_position (b
->mark
);
9872 if (start
<= mark_pos
)
9886 else if (start
> zv
)
9895 range
->location
= start
- begv
;
9896 range
->length
= end
- start
;
9899 /* Store the text of the buffer BUF from START to END as Unicode
9900 characters in CHARACTERS. Return non-zero if successful. */
9903 mac_store_buffer_text_to_unicode_chars (buf
, start
, end
, characters
)
9906 UniChar
*characters
;
9908 int start_byte
, end_byte
, char_count
, byte_count
;
9909 struct coding_system coding
;
9910 unsigned char *dst
= (unsigned char *) characters
;
9912 start_byte
= buf_charpos_to_bytepos (buf
, start
);
9913 end_byte
= buf_charpos_to_bytepos (buf
, end
);
9914 char_count
= end
- start
;
9915 byte_count
= end_byte
- start_byte
;
9917 if (setup_coding_system (
9918 #ifdef WORDS_BIG_ENDIAN
9926 coding
.src_multibyte
= !NILP (buf
->enable_multibyte_characters
);
9927 coding
.dst_multibyte
= 0;
9928 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
9929 coding
.composing
= COMPOSITION_DISABLED
;
9931 if (BUF_GPT_BYTE (buf
) <= start_byte
|| end_byte
<= BUF_GPT_BYTE (buf
))
9932 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
9933 byte_count
, char_count
* sizeof (UniChar
));
9936 int first_byte_count
= BUF_GPT_BYTE (buf
) - start_byte
;
9938 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
9939 first_byte_count
, char_count
* sizeof (UniChar
));
9940 if (coding
.result
== CODING_FINISH_NORMAL
)
9941 encode_coding (&coding
,
9942 BUF_BYTE_ADDRESS (buf
, start_byte
+ first_byte_count
),
9943 dst
+ coding
.produced
,
9944 byte_count
- first_byte_count
,
9945 char_count
* sizeof (UniChar
) - coding
.produced
);
9948 if (coding
.result
!= CODING_FINISH_NORMAL
)
9955 mac_ax_selected_text_range (f
, range
)
9959 mac_get_selected_range (XWINDOW (f
->selected_window
), range
);
9962 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
9964 mac_ax_number_of_characters (f
)
9967 struct buffer
*b
= XBUFFER (XWINDOW (f
->selected_window
)->buffer
);
9969 return BUF_ZV (b
) - BUF_BEGV (b
);
9976 mac_restore_keyboard_input_source ()
9978 OSStatus err
= noErr
;
9979 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9981 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9982 && EQ (saved_ts_script_language_on_focus
, Qt
))
9983 slptr
= &saved_ts_language
;
9984 else if (CONSP (Vmac_ts_script_language_on_focus
)
9985 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9986 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9987 && CONSP (saved_ts_script_language_on_focus
)
9988 && EQ (XCAR (saved_ts_script_language_on_focus
),
9989 XCAR (Vmac_ts_script_language_on_focus
))
9990 && EQ (XCDR (saved_ts_script_language_on_focus
),
9991 XCDR (Vmac_ts_script_language_on_focus
)))
9993 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9994 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10000 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10001 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10002 kKeyboardInputMethodClass
);
10004 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10007 err
= SetTextServiceLanguage (slptr
);
10009 /* Seems to be needed on Mac OS X 10.2. */
10011 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10018 mac_save_keyboard_input_source ()
10021 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10023 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10025 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10027 err
= GetTextServiceLanguage (&saved_ts_language
);
10029 slptr
= &saved_ts_language
;
10031 else if (CONSP (Vmac_ts_script_language_on_focus
)
10032 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10033 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10035 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10036 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10042 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10043 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10044 kKeyboardInputMethodClass
);
10046 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10052 #if TARGET_API_MAC_CARBON
10053 /***** Code to handle C-g testing *****/
10054 extern int quit_char
;
10055 extern int make_ctrl_char
P_ ((int));
10058 mac_quit_char_key_p (modifiers
, key_code
)
10059 UInt32 modifiers
, key_code
;
10062 unsigned long some_state
= 0;
10063 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10064 int c
, emacs_modifiers
;
10066 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
10067 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
10068 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
10069 if (char_code
& ~0xff)
10072 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
10073 if (emacs_modifiers
& ctrl_modifier
)
10074 c
= make_ctrl_char (char_code
);
10076 c
|= (emacs_modifiers
10077 & (meta_modifier
| alt_modifier
10078 | hyper_modifier
| super_modifier
));
10080 return c
== quit_char
;
10084 #if TARGET_API_MAC_CARBON
10085 /* Obtains the event modifiers from the event ref and then calls
10086 mac_to_emacs_modifiers. */
10088 mac_event_to_emacs_modifiers (EventRef eventRef
)
10090 UInt32 mods
= 0, class;
10092 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
10093 sizeof (UInt32
), NULL
, &mods
);
10094 class = GetEventClass (eventRef
);
10095 if (!NILP (Vmac_emulate_three_button_mouse
) &&
10096 (class == kEventClassMouse
|| class == kEventClassCommand
))
10098 mods
&= ~(optionKey
| cmdKey
);
10100 return mac_to_emacs_modifiers (mods
);
10103 /* Given an event ref, return the code to use for the mouse button
10104 code in the emacs input_event. */
10106 mac_get_mouse_btn (EventRef ref
)
10108 EventMouseButton result
= kEventMouseButtonPrimary
;
10109 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
10110 sizeof (EventMouseButton
), NULL
, &result
);
10113 case kEventMouseButtonPrimary
:
10114 if (NILP (Vmac_emulate_three_button_mouse
))
10118 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
10119 sizeof (UInt32
), NULL
, &mods
);
10120 return mac_get_emulated_btn(mods
);
10122 case kEventMouseButtonSecondary
:
10123 return mac_wheel_button_is_mouse_2
? 2 : 1;
10124 case kEventMouseButtonTertiary
:
10125 case 4: /* 4 is the number for the mouse wheel button */
10126 return mac_wheel_button_is_mouse_2
? 1 : 2;
10132 /* Normally, ConvertEventRefToEventRecord will correctly handle all
10133 events. However the click of the mouse wheel is not converted to a
10134 mouseDown or mouseUp event. Likewise for dead key events. This
10135 calls ConvertEventRefToEventRecord, but then checks to see if it is
10136 a mouse up/down, or a dead key Carbon event that has not been
10137 converted, and if so, converts it by hand (to be picked up in the
10138 XTread_socket loop). */
10139 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
10142 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
10148 switch (GetEventClass (eventRef
))
10150 case kEventClassMouse
:
10151 switch (GetEventKind (eventRef
))
10153 case kEventMouseDown
:
10154 eventRec
->what
= mouseDown
;
10158 case kEventMouseUp
:
10159 eventRec
->what
= mouseUp
;
10168 case kEventClassKeyboard
:
10169 switch (GetEventKind (eventRef
))
10171 case kEventRawKeyDown
:
10173 goto keystroke_common
;
10174 case kEventRawKeyRepeat
:
10176 goto keystroke_common
;
10177 case kEventRawKeyUp
:
10181 unsigned char char_codes
;
10184 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
10185 typeChar
, NULL
, sizeof (char),
10186 NULL
, &char_codes
);
10188 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
10189 typeUInt32
, NULL
, sizeof (UInt32
),
10193 eventRec
->what
= action
;
10194 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
10211 /* Need where and when. */
10214 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
10215 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
10216 /* Use two step process because new event modifiers are 32-bit
10217 and old are 16-bit. Currently, only loss is NumLock & Fn. */
10218 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
10219 NULL
, sizeof (UInt32
), NULL
, &mods
);
10220 eventRec
->modifiers
= mods
;
10222 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
10232 do_get_menus (void)
10234 Handle menubar_handle
;
10237 menubar_handle
= GetNewMBar (128);
10238 if(menubar_handle
== NULL
)
10240 SetMenuBar (menubar_handle
);
10243 #if !TARGET_API_MAC_CARBON
10244 menu
= GetMenuRef (M_APPLE
);
10246 AppendResMenu (menu
, 'DRVR');
10254 do_init_managers (void)
10256 #if !TARGET_API_MAC_CARBON
10257 InitGraf (&qd
.thePort
);
10259 FlushEvents (everyEvent
, 0);
10263 InitDialogs (NULL
);
10264 #endif /* !TARGET_API_MAC_CARBON */
10267 #if !TARGET_API_MAC_CARBON
10268 /* set up some extra stack space for use by emacs */
10269 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10271 /* MaxApplZone must be called for AppleScript to execute more
10272 complicated scripts */
10275 #endif /* !TARGET_API_MAC_CARBON */
10279 do_check_ram_size (void)
10281 SInt32 physical_ram_size
, logical_ram_size
;
10283 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10284 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10285 || physical_ram_size
> (1 << VALBITS
)
10286 || logical_ram_size
> (1 << VALBITS
))
10288 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10292 #endif /* MAC_OS8 */
10295 do_window_update (WindowRef win
)
10297 struct frame
*f
= mac_window_to_frame (win
);
10301 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10303 if (win
!= tip_window
)
10305 if (f
->async_visible
== 0)
10307 /* Update events may occur when a frame gets iconified. */
10309 f
->async_visible
= 1;
10310 f
->async_iconified
= 0;
10311 SET_FRAME_GARBAGED (f
);
10317 #if TARGET_API_MAC_CARBON
10318 RgnHandle region
= NewRgn ();
10320 GetPortVisibleRegion (GetWindowPort (win
), region
);
10321 GetRegionBounds (region
, &r
);
10322 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10324 mac_prepare_for_quickdraw (f
);
10326 UpdateControls (win
, region
);
10327 DisposeRgn (region
);
10329 r
= (*win
->visRgn
)->rgnBBox
;
10330 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10331 UpdateControls (win
, win
->visRgn
);
10340 is_emacs_window (WindowRef win
)
10342 Lisp_Object tail
, frame
;
10347 FOR_EACH_FRAME (tail
, frame
)
10348 if (FRAME_MAC_P (XFRAME (frame
)))
10349 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10360 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10362 err
= ActivateTSMDocument (tsm_document_id
);
10366 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10367 && EQ (saved_ts_script_language_on_focus
, Qt
))
10368 slptr
= &saved_ts_language
;
10369 else if (CONSP (Vmac_ts_script_language_on_focus
)
10370 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10371 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10372 && CONSP (saved_ts_script_language_on_focus
)
10373 && EQ (XCAR (saved_ts_script_language_on_focus
),
10374 XCAR (Vmac_ts_script_language_on_focus
))
10375 && EQ (XCDR (saved_ts_script_language_on_focus
),
10376 XCDR (Vmac_ts_script_language_on_focus
)))
10378 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10379 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10386 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10387 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10388 kKeyboardInputMethodClass
);
10390 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10393 err
= SetTextServiceLanguage (slptr
);
10395 /* Seems to be needed on Mac OS X 10.2. */
10397 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10407 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10409 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10411 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10413 err
= GetTextServiceLanguage (&saved_ts_language
);
10415 slptr
= &saved_ts_language
;
10417 else if (CONSP (Vmac_ts_script_language_on_focus
)
10418 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10419 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10421 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10422 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10428 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10429 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10430 kKeyboardInputMethodClass
);
10432 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10436 err
= DeactivateTSMDocument (tsm_document_id
);
10442 #if !TARGET_API_MAC_CARBON
10444 do_apple_menu (SInt16 menu_item
)
10447 SInt16 da_driver_refnum
;
10449 if (menu_item
== I_ABOUT
)
10450 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10453 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10454 da_driver_refnum
= OpenDeskAcc (item_name
);
10457 #endif /* !TARGET_API_MAC_CARBON */
10459 /* Handle drags in size box. Based on code contributed by Ben
10460 Mesander and IM - Window Manager A. */
10463 do_grow_window (w
, e
)
10465 const EventRecord
*e
;
10468 int rows
, columns
, width
, height
;
10469 struct frame
*f
= mac_window_to_frame (w
);
10470 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10471 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10472 #if TARGET_API_MAC_CARBON
10478 if (size_hints
->flags
& PMinSize
)
10480 min_width
= size_hints
->min_width
;
10481 min_height
= size_hints
->min_height
;
10483 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10485 #if TARGET_API_MAC_CARBON
10486 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10488 height
= new_rect
.bottom
- new_rect
.top
;
10489 width
= new_rect
.right
- new_rect
.left
;
10491 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10492 /* see if it really changed size */
10493 if (grow_size
== 0)
10495 height
= HiWord (grow_size
);
10496 width
= LoWord (grow_size
);
10499 if (width
!= FRAME_PIXEL_WIDTH (f
)
10500 || height
!= FRAME_PIXEL_HEIGHT (f
))
10502 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10503 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10505 x_set_window_size (f
, 0, columns
, rows
);
10510 #if TARGET_API_MAC_CARBON
10512 mac_get_ideal_size (f
)
10515 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10516 WindowRef w
= FRAME_MAC_WINDOW (f
);
10518 Rect standard_rect
;
10519 int height
, width
, columns
, rows
;
10521 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10522 ideal_size
.v
= dpyinfo
->height
;
10523 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10524 /* Adjust the standard size according to character boundaries. */
10525 width
= standard_rect
.right
- standard_rect
.left
;
10526 height
= standard_rect
.bottom
- standard_rect
.top
;
10527 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10528 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10529 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10530 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10536 /* Handle clicks in zoom box. Calculation of "standard state" based
10537 on code in IM - Window Manager A and code contributed by Ben
10538 Mesander. The standard state of an Emacs window is 80-characters
10539 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10542 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10544 Rect zoom_rect
, port_rect
;
10546 struct frame
*f
= mac_window_to_frame (w
);
10547 #if TARGET_API_MAC_CARBON
10548 Point ideal_size
= mac_get_ideal_size (f
);
10550 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10551 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10552 && port_rect
.left
== zoom_rect
.left
10553 && port_rect
.top
== zoom_rect
.top
)
10554 zoom_in_or_out
= inZoomIn
;
10556 zoom_in_or_out
= inZoomOut
;
10559 mac_clear_window (f
);
10561 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10562 #else /* not TARGET_API_MAC_CARBON */
10565 int w_title_height
, rows
;
10566 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10568 GetPort (&save_port
);
10570 SetPortWindowPort (w
);
10572 /* Clear window to avoid flicker. */
10573 EraseRect (&(w
->portRect
));
10574 if (zoom_in_or_out
== inZoomOut
)
10576 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10577 LocalToGlobal (&top_left
);
10579 /* calculate height of window's title bar */
10580 w_title_height
= top_left
.v
- 1
10581 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10583 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10584 zoom_rect
= qd
.screenBits
.bounds
;
10585 zoom_rect
.top
+= w_title_height
;
10586 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10588 zoom_rect
.right
= zoom_rect
.left
10589 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10591 /* Adjust the standard size according to character boundaries. */
10592 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10594 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10596 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10600 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10602 SetPort (save_port
);
10603 #endif /* not TARGET_API_MAC_CARBON */
10605 #if !TARGET_API_MAC_CARBON
10606 /* retrieve window size and update application values */
10607 port_rect
= w
->portRect
;
10608 height
= port_rect
.bottom
- port_rect
.top
;
10609 width
= port_rect
.right
- port_rect
.left
;
10611 mac_handle_size_change (f
, width
, height
);
10612 mac_handle_origin_change (f
);
10617 mac_set_unicode_keystroke_event (code
, buf
)
10619 struct input_event
*buf
;
10621 int charset_id
, c1
, c2
;
10625 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10628 else if (code
< 0x100)
10631 charset_id
= CHARSET_8_BIT_CONTROL
;
10633 charset_id
= charset_latin_iso8859_1
;
10634 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10635 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10640 charset_id
= charset_mule_unicode_0100_24ff
,
10642 else if (code
< 0x33FF)
10643 charset_id
= charset_mule_unicode_2500_33ff
,
10645 else if (code
>= 0xE000)
10646 charset_id
= charset_mule_unicode_e000_ffff
,
10648 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10649 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10650 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10655 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10657 unsigned char char_code
;
10658 UInt32 key_code
, modifiers
;
10659 unsigned long timestamp
;
10660 struct input_event
*buf
;
10662 static SInt16 last_key_script
= -1;
10663 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10664 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10667 if (mapped_modifiers
& kEventKeyModifierFnMask
10668 && key_code
<= 0x7f
10669 && fn_keycode_to_keycode_table
[key_code
])
10670 key_code
= fn_keycode_to_keycode_table
[key_code
];
10673 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10675 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10676 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10678 if (modifiers
& kEventKeyModifierFnMask
10679 && key_code
<= 0x7f
10680 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10681 modifiers
&= ~kEventKeyModifierFnMask
;
10684 else if (mapped_modifiers
)
10686 /* translate the keycode back to determine the original key */
10688 UCKeyboardLayout
*uchr_ptr
= NULL
;
10689 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10691 KeyboardLayoutRef layout
;
10693 err
= KLGetCurrentKeyboardLayout (&layout
);
10695 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10696 (const void **) &uchr_ptr
);
10698 static SInt16 last_key_layout_id
= 0;
10699 static Handle uchr_handle
= (Handle
)-1;
10700 SInt16 current_key_layout_id
=
10701 GetScriptVariable (current_key_script
, smScriptKeys
);
10703 if (uchr_handle
== (Handle
)-1
10704 || last_key_layout_id
!= current_key_layout_id
)
10706 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10707 last_key_layout_id
= current_key_layout_id
;
10710 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10716 UInt16 key_action
= action
- keyDown
;
10717 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10718 UInt32 keyboard_type
= LMGetKbdType ();
10719 SInt32 dead_key_state
= 0;
10721 UniCharCount actual_length
;
10723 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10724 modifier_key_state
, keyboard_type
,
10725 kUCKeyTranslateNoDeadKeysMask
,
10727 1, &actual_length
, &code
);
10728 if (status
== noErr
&& actual_length
== 1)
10729 mac_set_unicode_keystroke_event (code
, buf
);
10731 #endif /* MAC_OSX */
10733 if (buf
->kind
== NO_EVENT
)
10735 /* This code comes from Keyboard Resource, Appendix C of IM
10736 - Text. This is necessary since shift is ignored in KCHR
10737 table translation when option or command is pressed. It
10738 also does not translate correctly control-shift chars
10739 like C-% so mask off shift here also. */
10740 /* Mask off modifier keys that are mapped to some Emacs
10742 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10743 /* set high byte of keycode to modifier high byte*/
10744 int new_key_code
= key_code
| new_modifiers
;
10745 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10746 unsigned long some_state
= 0;
10747 UInt32 new_char_code
;
10749 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10750 if (new_char_code
== 0)
10751 /* Seems like a dead key. Append up-stroke. */
10752 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10756 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10757 buf
->code
= new_char_code
& 0xff;
10762 if (buf
->kind
== NO_EVENT
)
10764 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10765 buf
->code
= char_code
;
10768 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10769 buf
->modifiers
|= (extra_keyboard_modifiers
10770 & (meta_modifier
| alt_modifier
10771 | hyper_modifier
| super_modifier
));
10773 #if TARGET_API_MAC_CARBON
10774 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10775 && buf
->code
>= 0x80 && buf
->modifiers
)
10778 TextEncoding encoding
= kTextEncodingMacRoman
;
10779 TextToUnicodeInfo ttu_info
;
10781 UpgradeScriptInfoToTextEncoding (current_key_script
,
10782 kTextLanguageDontCare
,
10783 kTextRegionDontCare
,
10785 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10790 ByteCount unicode_len
;
10793 pstr
[1] = buf
->code
;
10794 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10796 &unicode_len
, &code
);
10797 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10798 mac_set_unicode_keystroke_event (code
, buf
);
10799 DisposeTextToUnicodeInfo (&ttu_info
);
10804 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10805 && buf
->code
>= 0x80
10806 && last_key_script
!= current_key_script
)
10808 struct input_event event
;
10810 EVENT_INIT (event
);
10811 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10813 event
.code
= current_key_script
;
10814 event
.timestamp
= timestamp
;
10815 kbd_buffer_store_event (&event
);
10816 last_key_script
= current_key_script
;
10821 mac_store_apple_event (class, id
, desc
)
10822 Lisp_Object
class, id
;
10823 const AEDesc
*desc
;
10825 struct input_event buf
;
10829 buf
.kind
= MAC_APPLE_EVENT
;
10832 XSETFRAME (buf
.frame_or_window
,
10833 mac_focus_frame (&one_mac_display_info
));
10834 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10835 is safe to use them during read_socket_hook. */
10836 buf
.arg
= mac_aedesc_to_lisp (desc
);
10837 kbd_buffer_store_event (&buf
);
10840 #if TARGET_API_MAC_CARBON
10842 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10843 event
, num_params
, names
, types
)
10844 AEEventClass
class;
10846 Lisp_Object class_key
, id_key
;
10849 const EventParamName
*names
;
10850 const EventParamType
*types
;
10852 OSStatus err
= eventNotHandledErr
;
10853 Lisp_Object binding
;
10855 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10856 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10858 if (INTEGERP (binding
))
10859 err
= XINT (binding
);
10862 AppleEvent apple_event
;
10863 err
= create_apple_event_from_event_ref (event
, num_params
,
10868 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10869 AEDisposeDesc (&apple_event
);
10870 mac_wakeup_from_rne ();
10879 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10883 const AEDesc
*desc
;
10885 struct input_event buf
;
10889 buf
.kind
= DRAG_N_DROP_EVENT
;
10890 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10891 buf
.timestamp
= TickCount () * (1000 / 60);
10892 XSETINT (buf
.x
, mouse_pos
.h
);
10893 XSETINT (buf
.y
, mouse_pos
.v
);
10894 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10895 buf
.arg
= mac_aedesc_to_lisp (desc
);
10896 kbd_buffer_store_event (&buf
);
10901 mac_store_service_event (event
)
10905 Lisp_Object id_key
;
10907 const EventParamName
*names
;
10908 const EventParamType
*types
;
10909 static const EventParamName names_pfm
[] =
10910 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10911 static const EventParamType types_pfm
[] =
10912 {typeCFStringRef
, typeCFStringRef
};
10914 switch (GetEventKind (event
))
10916 case kEventServicePaste
:
10923 case kEventServicePerform
:
10925 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10934 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10940 #endif /* MAC_OSX */
10942 static pascal OSStatus
10943 mac_handle_window_event (next_handler
, event
, data
)
10944 EventHandlerCallRef next_handler
;
10949 OSStatus err
, result
= eventNotHandledErr
;
10952 XSizeHints
*size_hints
;
10954 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
10955 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10957 return eventNotHandledErr
;
10959 f
= mac_window_to_frame (wp
);
10960 switch (GetEventKind (event
))
10962 /* -- window refresh events -- */
10964 case kEventWindowUpdate
:
10965 result
= CallNextEventHandler (next_handler
, event
);
10966 if (result
!= eventNotHandledErr
)
10969 do_window_update (wp
);
10973 /* -- window state change events -- */
10975 case kEventWindowShowing
:
10976 size_hints
= FRAME_SIZE_HINTS (f
);
10977 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
10979 struct frame
*sf
= SELECTED_FRAME ();
10981 if (!(FRAME_MAC_P (sf
) && sf
->async_visible
))
10982 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
10985 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
10986 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10987 kWindowCascadeStartAtParentWindowScreen
10989 kWindowCascadeOnParentWindowScreen
10992 #if USE_MAC_TOOLBAR
10993 /* This is a workaround. RepositionWindow fails to put
10994 a window at the cascading position when its parent
10995 window has a Carbon HIToolbar. */
10996 if ((f
->left_pos
== sf
->left_pos
10997 && f
->top_pos
== sf
->top_pos
)
10998 || (f
->left_pos
== sf
->left_pos
+ 10 * 2
10999 && f
->top_pos
== sf
->top_pos
+ 32 * 2))
11000 MoveWindowStructure (wp
, sf
->left_pos
+ 10, sf
->top_pos
+ 32);
11007 case kEventWindowHiding
:
11008 /* Before unmapping the window, update the WM_SIZE_HINTS
11009 property to claim that the current position of the window is
11010 user-specified, rather than program-specified, so that when
11011 the window is mapped again, it will be placed at the same
11012 location, without forcing the user to position it by hand
11013 again (they have already done that once for this window.) */
11014 x_wm_set_size_hint (f
, (long) 0, 1);
11018 case kEventWindowShown
:
11019 case kEventWindowHidden
:
11020 case kEventWindowCollapsed
:
11021 case kEventWindowExpanded
:
11022 mac_handle_visibility_change (f
);
11026 case kEventWindowBoundsChanging
:
11027 result
= CallNextEventHandler (next_handler
, event
);
11028 if (result
!= eventNotHandledErr
)
11031 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
11032 NULL
, sizeof (UInt32
), NULL
, &attributes
);
11036 size_hints
= FRAME_SIZE_HINTS (f
);
11037 if ((attributes
& kWindowBoundsChangeUserResize
)
11038 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
11039 == (PResizeInc
| PBaseSize
| PMinSize
)))
11044 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
11045 typeQDRectangle
, NULL
, sizeof (Rect
),
11050 width
= bounds
.right
- bounds
.left
;
11051 height
= bounds
.bottom
- bounds
.top
;
11053 if (width
< size_hints
->min_width
)
11054 width
= size_hints
->min_width
;
11056 width
= size_hints
->base_width
11057 + (int) ((width
- size_hints
->base_width
)
11058 / (float) size_hints
->width_inc
+ .5)
11059 * size_hints
->width_inc
;
11061 if (height
< size_hints
->min_height
)
11062 height
= size_hints
->min_height
;
11064 height
= size_hints
->base_height
11065 + (int) ((height
- size_hints
->base_height
)
11066 / (float) size_hints
->height_inc
+ .5)
11067 * size_hints
->height_inc
;
11069 bounds
.right
= bounds
.left
+ width
;
11070 bounds
.bottom
= bounds
.top
+ height
;
11071 SetEventParameter (event
, kEventParamCurrentBounds
,
11072 typeQDRectangle
, sizeof (Rect
), &bounds
);
11077 case kEventWindowBoundsChanged
:
11078 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
11079 NULL
, sizeof (UInt32
), NULL
, &attributes
);
11083 if (attributes
& kWindowBoundsChangeSizeChanged
)
11087 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
11088 typeQDRectangle
, NULL
, sizeof (Rect
),
11094 width
= bounds
.right
- bounds
.left
;
11095 height
= bounds
.bottom
- bounds
.top
;
11096 mac_handle_size_change (f
, width
, height
);
11097 mac_wakeup_from_rne ();
11101 if (attributes
& kWindowBoundsChangeOriginChanged
)
11102 mac_handle_origin_change (f
);
11107 /* -- window action events -- */
11109 case kEventWindowClose
:
11111 struct input_event buf
;
11114 buf
.kind
= DELETE_WINDOW_EVENT
;
11115 XSETFRAME (buf
.frame_or_window
, f
);
11117 kbd_buffer_store_event (&buf
);
11122 case kEventWindowGetIdealSize
:
11123 result
= CallNextEventHandler (next_handler
, event
);
11124 if (result
!= eventNotHandledErr
)
11128 Point ideal_size
= mac_get_ideal_size (f
);
11130 err
= SetEventParameter (event
, kEventParamDimensions
,
11131 typeQDPoint
, sizeof (Point
), &ideal_size
);
11138 case kEventWindowToolbarSwitchMode
:
11140 static const EventParamName names
[] = {kEventParamDirectObject
,
11141 kEventParamWindowMouseLocation
,
11142 kEventParamKeyModifiers
,
11143 kEventParamMouseButton
,
11144 kEventParamClickCount
,
11145 kEventParamMouseChord
};
11146 static const EventParamType types
[] = {typeWindowRef
,
11152 int num_params
= sizeof (names
) / sizeof (names
[0]);
11154 err
= mac_store_event_ref_as_apple_event (0, 0,
11156 Qtoolbar_switch_mode
,
11166 /* -- window focus events -- */
11168 case kEventWindowFocusAcquired
:
11169 err
= mac_tsm_resume ();
11174 case kEventWindowFocusRelinquish
:
11175 err
= mac_tsm_suspend ();
11188 static pascal OSStatus
11189 mac_handle_application_event (next_handler
, event
, data
)
11190 EventHandlerCallRef next_handler
;
11194 OSStatus err
, result
= eventNotHandledErr
;
11196 switch (GetEventKind (event
))
11199 case kEventAppActivated
:
11200 err
= mac_tsm_resume ();
11203 case kEventAppDeactivated
:
11204 err
= mac_tsm_suspend ();
11218 static pascal OSStatus
11219 mac_handle_keyboard_event (next_handler
, event
, data
)
11220 EventHandlerCallRef next_handler
;
11224 OSStatus err
, result
= eventNotHandledErr
;
11225 UInt32 event_kind
, key_code
, modifiers
;
11226 unsigned char char_code
;
11228 event_kind
= GetEventKind (event
);
11229 switch (event_kind
)
11231 case kEventRawKeyDown
:
11232 case kEventRawKeyRepeat
:
11233 case kEventRawKeyUp
:
11234 /* When using Carbon Events, we need to pass raw keyboard events
11235 to the TSM ourselves. If TSM handles it, it will pass back
11236 noErr, otherwise it will pass back "eventNotHandledErr" and
11237 we can process it normally. */
11238 result
= CallNextEventHandler (next_handler
, event
);
11239 if (result
!= eventNotHandledErr
)
11242 if (read_socket_inev
== NULL
)
11246 if (read_socket_inev
->kind
!= NO_EVENT
)
11253 if (event_kind
== kEventRawKeyUp
)
11256 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11258 sizeof (char), NULL
, &char_code
);
11262 err
= GetEventParameter (event
, kEventParamKeyCode
,
11264 sizeof (UInt32
), NULL
, &key_code
);
11268 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
11270 sizeof (UInt32
), NULL
, &modifiers
);
11274 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11275 char_code
, key_code
, modifiers
,
11277 (GetEventTime (event
) / kEventDurationMillisecond
)),
11289 static pascal OSStatus
11290 mac_handle_command_event (next_handler
, event
, data
)
11291 EventHandlerCallRef next_handler
;
11295 OSStatus err
, result
= eventNotHandledErr
;
11297 static const EventParamName names
[] =
11298 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11299 static const EventParamType types
[] =
11300 {typeHICommand
, typeUInt32
};
11301 int num_params
= sizeof (names
) / sizeof (names
[0]);
11303 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11304 NULL
, sizeof (HICommand
), NULL
, &command
);
11306 return eventNotHandledErr
;
11308 switch (GetEventKind (event
))
11310 case kEventCommandProcess
:
11311 result
= CallNextEventHandler (next_handler
, event
);
11312 if (result
!= eventNotHandledErr
)
11315 err
= GetEventParameter (event
, kEventParamDirectObject
,
11316 typeHICommand
, NULL
,
11317 sizeof (HICommand
), NULL
, &command
);
11319 if (err
!= noErr
|| command
.commandID
== 0)
11322 /* A HI command event is mapped to an Apple event whose event
11323 class symbol is `hi-command' and event ID is its command
11325 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11340 static pascal OSStatus
11341 mac_handle_mouse_event (next_handler
, event
, data
)
11342 EventHandlerCallRef next_handler
;
11346 OSStatus err
, result
= eventNotHandledErr
;
11348 switch (GetEventKind (event
))
11350 case kEventMouseWheelMoved
:
11354 EventMouseWheelAxis axis
;
11358 result
= CallNextEventHandler (next_handler
, event
);
11359 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11362 f
= mac_focus_frame (&one_mac_display_info
);
11364 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11365 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11367 || wp
!= FRAME_MAC_WINDOW (f
))
11370 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11371 typeMouseWheelAxis
, NULL
,
11372 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11373 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11376 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11377 typeQDPoint
, NULL
, sizeof (Point
),
11382 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11383 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11384 if (point
.h
< 0 || point
.v
< 0
11385 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11386 f
->tool_bar_window
))
11389 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11390 typeSInt32
, NULL
, sizeof (SInt32
),
11395 read_socket_inev
->kind
= WHEEL_EVENT
;
11396 read_socket_inev
->code
= 0;
11397 read_socket_inev
->modifiers
=
11398 (mac_event_to_emacs_modifiers (event
)
11399 | ((delta
< 0) ? down_modifier
: up_modifier
));
11400 XSETINT (read_socket_inev
->x
, point
.h
);
11401 XSETINT (read_socket_inev
->y
, point
.v
);
11402 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11416 static pascal OSStatus
11417 mac_handle_text_input_event (next_handler
, event
, data
)
11418 EventHandlerCallRef next_handler
;
11422 OSStatus err
, result
;
11423 Lisp_Object id_key
= Qnil
;
11425 const EventParamName
*names
;
11426 const EventParamType
*types
;
11427 static UInt32 seqno_uaia
= 0;
11428 static const EventParamName names_uaia
[] =
11429 {kEventParamTextInputSendComponentInstance
,
11430 kEventParamTextInputSendRefCon
,
11431 kEventParamTextInputSendSLRec
,
11432 kEventParamTextInputSendFixLen
,
11433 kEventParamTextInputSendText
,
11434 kEventParamTextInputSendUpdateRng
,
11435 kEventParamTextInputSendHiliteRng
,
11436 kEventParamTextInputSendClauseRng
,
11437 kEventParamTextInputSendPinRng
,
11438 kEventParamTextInputSendTextServiceEncoding
,
11439 kEventParamTextInputSendTextServiceMacEncoding
,
11440 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11441 static const EventParamType types_uaia
[] =
11442 {typeComponentInstance
,
11444 typeIntlWritingCode
,
11451 typeTextRangeArray
,
11452 typeTextRangeArray
,
11458 static const EventParamName names_ufke
[] =
11459 {kEventParamTextInputSendComponentInstance
,
11460 kEventParamTextInputSendRefCon
,
11461 kEventParamTextInputSendSLRec
,
11462 kEventParamTextInputSendText
};
11463 static const EventParamType types_ufke
[] =
11464 {typeComponentInstance
,
11466 typeIntlWritingCode
,
11469 result
= CallNextEventHandler (next_handler
, event
);
11470 if (result
!= eventNotHandledErr
)
11473 switch (GetEventKind (event
))
11475 case kEventTextInputUpdateActiveInputArea
:
11476 id_key
= Qupdate_active_input_area
;
11477 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11478 names
= names_uaia
;
11479 types
= types_uaia
;
11480 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11481 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11486 case kEventTextInputUnicodeForKeyEvent
:
11488 EventRef kbd_event
;
11489 UInt32 actual_size
, modifiers
;
11491 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11492 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11495 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11497 sizeof (UInt32
), NULL
, &modifiers
);
11498 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11499 /* There're mapped modifier keys. Process it in
11503 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11504 typeUnicodeText
, NULL
, 0, &actual_size
,
11506 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11510 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11511 typeUnicodeText
, NULL
,
11512 sizeof (UniChar
), NULL
, &code
);
11513 if (err
== noErr
&& code
< 0x80)
11515 /* ASCII character. Process it in do_keystroke. */
11516 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11520 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11521 typeUInt32
, NULL
, sizeof (UInt32
),
11523 if (!(err
== noErr
&& key_code
<= 0x7f
11524 && keycode_to_xkeysym_table
[key_code
]))
11527 mac_focus_frame (&one_mac_display_info
);
11529 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11530 read_socket_inev
->code
= code
;
11531 read_socket_inev
->modifiers
=
11532 mac_to_emacs_modifiers (modifiers
);
11533 read_socket_inev
->modifiers
|=
11534 (extra_keyboard_modifiers
11535 & (meta_modifier
| alt_modifier
11536 | hyper_modifier
| super_modifier
));
11537 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11545 /* Non-ASCII keystrokes without mapped modifiers are
11546 processed at the Lisp level. */
11547 id_key
= Qunicode_for_key_event
;
11548 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11549 names
= names_ufke
;
11550 types
= types_ufke
;
11556 case kEventTextInputOffsetToPos
:
11562 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11565 /* Strictly speaking, this is not always correct because
11566 previous events may change some states about display. */
11567 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11569 /* Active input area is displayed around the current point. */
11570 f
= SELECTED_FRAME ();
11571 w
= XWINDOW (f
->selected_window
);
11573 else if (WINDOWP (echo_area_window
))
11575 /* Active input area is displayed in the echo area. */
11576 w
= XWINDOW (echo_area_window
);
11577 f
= WINDOW_XFRAME (w
);
11582 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11583 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11584 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11585 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11586 + FONT_BASE (FRAME_FONT (f
))
11587 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11588 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11589 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11599 if (!NILP (id_key
))
11600 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11606 #endif /* TARGET_API_MAC_CARBON */
11610 install_window_handler (window
)
11613 OSStatus err
= noErr
;
11615 #if TARGET_API_MAC_CARBON
11618 static const EventTypeSpec specs
[] =
11620 /* -- window refresh events -- */
11621 {kEventClassWindow
, kEventWindowUpdate
},
11622 /* -- window state change events -- */
11623 {kEventClassWindow
, kEventWindowShowing
},
11624 {kEventClassWindow
, kEventWindowHiding
},
11625 {kEventClassWindow
, kEventWindowShown
},
11626 {kEventClassWindow
, kEventWindowHidden
},
11627 {kEventClassWindow
, kEventWindowCollapsed
},
11628 {kEventClassWindow
, kEventWindowExpanded
},
11629 {kEventClassWindow
, kEventWindowBoundsChanging
},
11630 {kEventClassWindow
, kEventWindowBoundsChanged
},
11631 /* -- window action events -- */
11632 {kEventClassWindow
, kEventWindowClose
},
11633 {kEventClassWindow
, kEventWindowGetIdealSize
},
11635 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11638 /* -- window focus events -- */
11639 {kEventClassWindow
, kEventWindowFocusAcquired
},
11640 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11643 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11645 if (handle_window_eventUPP
== NULL
)
11646 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11648 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11649 GetEventTypeCount (specs
),
11650 specs
, NULL
, NULL
);
11655 err
= install_drag_handler (window
);
11661 remove_window_handler (window
)
11664 remove_drag_handler (window
);
11667 #if TARGET_API_MAC_CARBON
11669 install_application_handler ()
11671 OSStatus err
= noErr
;
11675 static const EventTypeSpec specs
[] = {
11677 {kEventClassApplication
, kEventAppActivated
},
11678 {kEventClassApplication
, kEventAppDeactivated
},
11682 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11683 (mac_handle_application_event
),
11684 GetEventTypeCount (specs
),
11685 specs
, NULL
, NULL
);
11690 static const EventTypeSpec specs
[] =
11691 {{kEventClassKeyboard
, kEventRawKeyDown
},
11692 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11693 {kEventClassKeyboard
, kEventRawKeyUp
}};
11695 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11696 (mac_handle_keyboard_event
),
11697 GetEventTypeCount (specs
),
11698 specs
, NULL
, NULL
);
11703 static const EventTypeSpec specs
[] =
11704 {{kEventClassCommand
, kEventCommandProcess
}};
11706 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11707 (mac_handle_command_event
),
11708 GetEventTypeCount (specs
),
11709 specs
, NULL
, NULL
);
11714 static const EventTypeSpec specs
[] =
11715 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11717 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11718 (mac_handle_mouse_event
),
11719 GetEventTypeCount (specs
),
11720 specs
, NULL
, NULL
);
11726 static const EventTypeSpec spec
[] =
11727 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11728 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11729 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11731 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11732 (mac_handle_text_input_event
),
11733 GetEventTypeCount (spec
),
11739 err
= install_menu_target_item_handler ();
11743 err
= install_service_handler ();
11751 mac_handle_dm_notification (event
)
11754 mac_screen_config_changed
= 1;
11757 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11759 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11760 CGDirectDisplayID display
;
11761 CGDisplayChangeSummaryFlags flags
;
11764 mac_screen_config_changed
= 1;
11769 init_dm_notification_handler ()
11773 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11774 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11775 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11778 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11781 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11782 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11784 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11785 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11787 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11788 ProcessSerialNumber psn
;
11790 if (handle_dm_notificationUPP
== NULL
)
11791 handle_dm_notificationUPP
=
11792 NewDMNotificationUPP (mac_handle_dm_notification
);
11794 err
= GetCurrentProcess (&psn
);
11796 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11804 mac_get_screen_info (dpyinfo
)
11805 struct mac_display_info
*dpyinfo
;
11808 /* HasDepth returns true if it is possible to have a 32 bit display,
11809 but this may not be what is actually used. Mac OSX can do better. */
11810 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11811 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11814 CGDisplayCount ndisps
;
11815 CGDirectDisplayID
*displays
;
11817 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11820 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11821 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11825 CGRect bounds
= CGRectZero
;
11827 while (ndisps
-- > 0)
11828 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11829 dpyinfo
->height
= CGRectGetHeight (bounds
);
11830 dpyinfo
->width
= CGRectGetWidth (bounds
);
11834 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11835 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11838 #else /* !MAC_OSX */
11840 GDHandle gdh
= GetMainDevice ();
11841 Rect rect
= (**gdh
).gdRect
;
11843 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11844 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11845 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11848 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11849 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11850 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11852 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11853 dpyinfo
->width
= rect
.right
- rect
.left
;
11855 #endif /* !MAC_OSX */
11861 profiler_exit_proc ()
11863 ProfilerDump ("\pEmacs.prof");
11868 /* These few functions implement Emacs as a normal Mac application
11869 (almost): set up the heap and the Toolbox, handle necessary system
11870 events plus a few simple menu events. They also set up Emacs's
11871 access to functions defined in the rest of this file. Emacs uses
11872 function hooks to perform all its terminal I/O. A complete list of
11873 these functions appear in termhooks.h. For what they do, read the
11874 comments there and see also w32term.c and xterm.c. What's
11875 noticeably missing here is the event loop, which is normally
11876 present in most Mac application. After performing the necessary
11877 Mac initializations, main passes off control to emacs_main
11878 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11879 (defined further below) to read input. This is where
11880 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11887 #if __profile__ /* is the profiler on? */
11888 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11893 /* set creator and type for files created by MSL */
11894 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11898 do_init_managers ();
11902 #ifndef USE_LSB_TAG
11903 do_check_ram_size ();
11906 init_emacs_passwd_dir ();
11910 init_coercion_handler ();
11912 initialize_applescript ();
11914 init_apple_event_handler ();
11916 init_dm_notification_handler ();
11922 /* set up argv array from STR# resource */
11923 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
11927 /* free up AppleScript resources on exit */
11928 atexit (terminate_applescript
);
11930 #if __profile__ /* is the profiler on? */
11931 atexit (profiler_exit_proc
);
11934 /* 3rd param "envp" never used in emacs_main */
11935 (void) emacs_main (argc
, argv
, 0);
11938 /* Never reached - real exit in Fkill_emacs */
11943 #if !TARGET_API_MAC_CARBON
11944 static RgnHandle mouse_region
= NULL
;
11947 mac_wait_next_event (er
, sleep_time
, dequeue
)
11952 static EventRecord er_buf
= {nullEvent
};
11953 UInt32 target_tick
, current_tick
;
11954 EventMask event_mask
;
11956 if (mouse_region
== NULL
)
11957 mouse_region
= NewRgn ();
11959 event_mask
= everyEvent
;
11960 if (!mac_ready_for_apple_events
)
11961 event_mask
-= highLevelEventMask
;
11963 current_tick
= TickCount ();
11964 target_tick
= current_tick
+ sleep_time
;
11966 if (er_buf
.what
== nullEvent
)
11967 while (!WaitNextEvent (event_mask
, &er_buf
,
11968 target_tick
- current_tick
, mouse_region
))
11970 current_tick
= TickCount ();
11971 if (target_tick
<= current_tick
)
11977 er_buf
.what
= nullEvent
;
11980 #endif /* not TARGET_API_MAC_CARBON */
11982 #if TARGET_API_MAC_CARBON
11984 mac_post_mouse_moved_event ()
11986 EventRef event
= NULL
;
11989 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
11990 kEventAttributeNone
, &event
);
11995 GetGlobalMouse (&mouse_pos
);
11996 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
11997 sizeof (Point
), &mouse_pos
);
12001 UInt32 modifiers
= GetCurrentKeyModifiers ();
12003 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
12004 sizeof (UInt32
), &modifiers
);
12007 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
12008 kEventPriorityStandard
);
12010 ReleaseEvent (event
);
12016 /* Emacs calls this whenever it wants to read an input event from the
12019 XTread_socket (sd
, expected
, hold_quit
)
12021 struct input_event
*hold_quit
;
12023 struct input_event inev
;
12025 #if TARGET_API_MAC_CARBON
12027 EventTargetRef toolbox_dispatcher
;
12030 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
12032 if (interrupt_input_blocked
)
12034 interrupt_input_pending
= 1;
12038 interrupt_input_pending
= 0;
12041 /* So people can tell when we have read the available input. */
12042 input_signal_count
++;
12046 #if TARGET_API_MAC_CARBON
12047 toolbox_dispatcher
= GetEventDispatcherTarget ();
12051 mac_prepare_for_quickdraw (NULL
),
12053 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
12054 kEventRemoveFromQueue
, &eventRef
))
12055 #else /* !TARGET_API_MAC_CARBON */
12056 while (mac_wait_next_event (&er
, 0, true))
12057 #endif /* !TARGET_API_MAC_CARBON */
12061 unsigned long timestamp
;
12064 inev
.kind
= NO_EVENT
;
12067 #if TARGET_API_MAC_CARBON
12068 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
12070 if (!mac_convert_event_ref (eventRef
, &er
))
12072 #else /* !TARGET_API_MAC_CARBON */
12073 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
12074 #endif /* !TARGET_API_MAC_CARBON */
12081 WindowRef window_ptr
;
12082 ControlPartCode part_code
;
12083 int tool_bar_p
= 0;
12085 #if TARGET_API_MAC_CARBON
12088 /* This is needed to send mouse events like aqua window
12089 buttons to the correct handler. */
12090 read_socket_inev
= &inev
;
12091 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12092 read_socket_inev
= NULL
;
12093 if (err
!= eventNotHandledErr
)
12096 last_mouse_glyph_frame
= 0;
12098 if (dpyinfo
->grabbed
&& last_mouse_frame
12099 && FRAME_LIVE_P (last_mouse_frame
))
12101 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
12102 part_code
= inContent
;
12106 part_code
= FindWindow (er
.where
, &window_ptr
);
12107 if (tip_window
&& window_ptr
== tip_window
)
12109 HideWindow (tip_window
);
12110 part_code
= FindWindow (er
.where
, &window_ptr
);
12114 if (er
.what
!= mouseDown
&&
12115 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
12121 f
= mac_focus_frame (dpyinfo
);
12122 saved_menu_event_location
= er
.where
;
12123 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
12124 XSETFRAME (inev
.frame_or_window
, f
);
12129 #if TARGET_API_MAC_CARBON
12130 FrontNonFloatingWindow ()
12135 || (mac_window_to_frame (window_ptr
)
12136 != dpyinfo
->x_focus_frame
))
12137 SelectWindow (window_ptr
);
12140 ControlPartCode control_part_code
;
12144 ControlKind control_kind
;
12147 f
= mac_window_to_frame (window_ptr
);
12148 /* convert to local coordinates of new window */
12149 mouse_loc
.h
= (er
.where
.h
12151 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12152 mouse_loc
.v
= (er
.where
.v
12154 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12155 #if TARGET_API_MAC_CARBON
12156 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
12157 &control_part_code
);
12160 GetControlKind (ch
, &control_kind
);
12163 control_part_code
= FindControl (mouse_loc
, window_ptr
,
12167 #if TARGET_API_MAC_CARBON
12168 inev
.code
= mac_get_mouse_btn (eventRef
);
12169 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12171 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
12172 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12174 XSETINT (inev
.x
, mouse_loc
.h
);
12175 XSETINT (inev
.y
, mouse_loc
.v
);
12177 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
12179 #ifndef USE_TOOLKIT_SCROLL_BARS
12180 /* control_part_code becomes kControlNoPart if
12181 a progress indicator is clicked. */
12182 && control_part_code
!= kControlNoPart
12183 #else /* USE_TOOLKIT_SCROLL_BARS */
12185 && control_kind
.kind
== kControlKindScrollBar
12186 #endif /* MAC_OSX */
12187 #endif /* USE_TOOLKIT_SCROLL_BARS */
12190 struct scroll_bar
*bar
;
12192 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12194 bar
= tracked_scroll_bar
;
12195 #ifndef USE_TOOLKIT_SCROLL_BARS
12196 control_part_code
= kControlIndicatorPart
;
12200 bar
= (struct scroll_bar
*) GetControlReference (ch
);
12201 #ifdef USE_TOOLKIT_SCROLL_BARS
12202 /* Make the "Ctrl-Mouse-2 splits window" work
12203 for toolkit scroll bars. */
12204 if (inev
.modifiers
& ctrl_modifier
)
12205 x_scroll_bar_handle_click (bar
, control_part_code
,
12207 else if (er
.what
== mouseDown
)
12208 x_scroll_bar_handle_press (bar
, control_part_code
,
12211 x_scroll_bar_handle_release (bar
, &inev
);
12212 #else /* not USE_TOOLKIT_SCROLL_BARS */
12213 x_scroll_bar_handle_click (bar
, control_part_code
,
12215 if (er
.what
== mouseDown
12216 && control_part_code
== kControlIndicatorPart
)
12217 tracked_scroll_bar
= bar
;
12219 tracked_scroll_bar
= NULL
;
12220 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12224 Lisp_Object window
;
12225 int x
= mouse_loc
.h
;
12226 int y
= mouse_loc
.v
;
12228 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
12229 if (EQ (window
, f
->tool_bar_window
))
12231 if (er
.what
== mouseDown
)
12232 handle_tool_bar_click (f
, x
, y
, 1, 0);
12234 handle_tool_bar_click (f
, x
, y
, 0,
12240 XSETFRAME (inev
.frame_or_window
, f
);
12241 inev
.kind
= MOUSE_CLICK_EVENT
;
12245 if (er
.what
== mouseDown
)
12247 dpyinfo
->grabbed
|= (1 << inev
.code
);
12248 last_mouse_frame
= f
;
12251 last_tool_bar_item
= -1;
12255 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
12256 /* If a button is released though it was not
12257 previously pressed, that would be because
12258 of multi-button emulation. */
12259 dpyinfo
->grabbed
= 0;
12261 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
12264 /* Ignore any mouse motion that happened before
12265 this event; any subsequent mouse-movement Emacs
12266 events should reflect only motion after the
12269 f
->mouse_moved
= 0;
12271 #ifdef USE_TOOLKIT_SCROLL_BARS
12272 if (inev
.kind
== MOUSE_CLICK_EVENT
12273 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12274 && (inev
.modifiers
& ctrl_modifier
)))
12279 inev
.modifiers
|= down_modifier
;
12282 inev
.modifiers
|= up_modifier
;
12289 #if TARGET_API_MAC_CARBON
12291 if (IsWindowPathSelectClick (window_ptr
, &er
))
12293 WindowPathSelect (window_ptr
, NULL
, NULL
);
12296 if (part_code
== inProxyIcon
12297 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12298 != errUserWantsToDragWindow
))
12300 DragWindow (window_ptr
, er
.where
, NULL
);
12301 #else /* not TARGET_API_MAC_CARBON */
12302 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12303 /* Update the frame parameters. */
12305 struct frame
*f
= mac_window_to_frame (window_ptr
);
12307 if (f
&& !f
->async_iconified
)
12308 mac_handle_origin_change (f
);
12310 #endif /* not TARGET_API_MAC_CARBON */
12314 if (TrackGoAway (window_ptr
, er
.where
))
12316 inev
.kind
= DELETE_WINDOW_EVENT
;
12317 XSETFRAME (inev
.frame_or_window
,
12318 mac_window_to_frame (window_ptr
));
12322 /* window resize handling added --ben */
12324 do_grow_window (window_ptr
, &er
);
12327 /* window zoom handling added --ben */
12330 if (TrackBox (window_ptr
, er
.where
, part_code
))
12331 do_zoom_window (window_ptr
, part_code
);
12334 #if USE_MAC_TOOLBAR
12340 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12342 /* This doesn't work on Mac OS X 10.2. */
12344 HIViewClick (ch
, eventRef
);
12347 #endif /* USE_MAC_TOOLBAR */
12355 #if !TARGET_API_MAC_CARBON
12357 do_window_update ((WindowRef
) er
.message
);
12362 switch ((er
.message
>> 24) & 0x000000FF)
12364 case mouseMovedMessage
:
12365 #if !TARGET_API_MAC_CARBON
12366 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12367 er
.where
.h
+ 1, er
.where
.v
+ 1);
12369 previous_help_echo_string
= help_echo_string
;
12370 help_echo_string
= Qnil
;
12372 if (dpyinfo
->grabbed
&& last_mouse_frame
12373 && FRAME_LIVE_P (last_mouse_frame
))
12374 f
= last_mouse_frame
;
12376 f
= dpyinfo
->x_focus_frame
;
12378 if (dpyinfo
->mouse_face_hidden
)
12380 dpyinfo
->mouse_face_hidden
= 0;
12381 clear_mouse_face (dpyinfo
);
12386 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12389 mouse_pos
.h
= (er
.where
.h
12391 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12392 mouse_pos
.v
= (er
.where
.v
12394 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12395 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12396 #ifdef USE_TOOLKIT_SCROLL_BARS
12397 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12399 #else /* not USE_TOOLKIT_SCROLL_BARS */
12400 x_scroll_bar_note_movement (tracked_scroll_bar
,
12402 - XINT (tracked_scroll_bar
->top
),
12403 er
.when
* (1000 / 60));
12404 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12407 /* Generate SELECT_WINDOW_EVENTs when needed. */
12408 if (!NILP (Vmouse_autoselect_window
))
12410 Lisp_Object window
;
12412 window
= window_from_coordinates (f
,
12417 /* Window will be selected only when it is
12418 not selected now and last mouse movement
12419 event was not in it. Minibuffer window
12420 will be selected only when it is active. */
12421 if (WINDOWP (window
)
12422 && !EQ (window
, last_window
)
12423 && !EQ (window
, selected_window
)
12424 /* For click-to-focus window managers
12425 create event iff we don't leave the
12427 && (focus_follows_mouse
12428 || (EQ (XWINDOW (window
)->frame
,
12429 XWINDOW (selected_window
)->frame
))))
12431 inev
.kind
= SELECT_WINDOW_EVENT
;
12432 inev
.frame_or_window
= window
;
12435 last_window
=window
;
12437 if (!note_mouse_movement (f
, &mouse_pos
))
12438 help_echo_string
= previous_help_echo_string
;
12439 #if USE_MAC_TOOLBAR
12441 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12446 /* If the contents of the global variable
12447 help_echo_string has changed, generate a
12449 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12460 WindowRef window_ptr
= (WindowRef
) er
.message
;
12462 ControlRef root_control
;
12464 if (window_ptr
== tip_window
)
12466 HideWindow (tip_window
);
12470 if (!is_emacs_window (window_ptr
))
12473 f
= mac_window_to_frame (window_ptr
);
12475 if ((er
.modifiers
& activeFlag
) != 0)
12477 /* A window has been activated */
12480 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12482 ActivateControl (root_control
);
12484 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12486 mouse_loc
.h
= (er
.where
.h
12488 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12489 mouse_loc
.v
= (er
.where
.v
12491 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12492 /* Window-activated event counts as mouse movement,
12493 so update things that depend on mouse position. */
12494 note_mouse_movement (f
, &mouse_loc
);
12498 /* A window has been deactivated */
12499 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12501 DeactivateControl (root_control
);
12503 #ifdef USE_TOOLKIT_SCROLL_BARS
12504 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12506 struct input_event event
;
12508 EVENT_INIT (event
);
12509 event
.kind
= NO_EVENT
;
12510 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12511 if (event
.kind
!= NO_EVENT
)
12513 event
.timestamp
= timestamp
;
12514 kbd_buffer_store_event_hold (&event
, hold_quit
);
12519 dpyinfo
->grabbed
= 0;
12521 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12523 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12525 /* If we move outside the frame, then we're
12526 certainly no longer on any text in the
12528 clear_mouse_face (dpyinfo
);
12529 dpyinfo
->mouse_face_mouse_frame
= 0;
12532 /* Generate a nil HELP_EVENT to cancel a help-echo.
12533 Do it only if there's something to cancel.
12534 Otherwise, the startup message is cleared when the
12535 mouse leaves the frame. */
12536 if (any_help_event_p
)
12547 f
= mac_focus_frame (dpyinfo
);
12548 XSETFRAME (inev
.frame_or_window
, f
);
12550 /* If mouse-highlight is an integer, input clears out mouse
12552 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12553 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12555 clear_mouse_face (dpyinfo
);
12556 dpyinfo
->mouse_face_hidden
= 1;
12560 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
12563 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
12565 sizeof (UInt32
), NULL
, &modifiers
);
12567 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
12569 #if TARGET_API_MAC_CARBON
12570 if (!(mapped_modifiers
12571 & ~(mac_pass_command_to_system
? cmdKey
: 0)
12572 & ~(mac_pass_control_to_system
? controlKey
: 0)))
12576 if (er
.what
!= keyUp
)
12577 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12578 (er
.message
& keyCodeMask
) >> 8,
12579 modifiers
, timestamp
, &inev
);
12583 case kHighLevelEvent
:
12584 AEProcessAppleEvent (&er
);
12589 #if TARGET_API_MAC_CARBON
12593 read_socket_inev
= &inev
;
12594 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12595 read_socket_inev
= NULL
;
12600 #if TARGET_API_MAC_CARBON
12601 ReleaseEvent (eventRef
);
12604 if (inev
.kind
!= NO_EVENT
)
12606 inev
.timestamp
= timestamp
;
12607 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12612 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12617 XSETFRAME (frame
, f
);
12623 any_help_event_p
= 1;
12624 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12625 help_echo_object
, help_echo_pos
);
12629 help_echo_string
= Qnil
;
12630 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12636 /* If the focus was just given to an autoraising frame,
12638 /* ??? This ought to be able to handle more than one such frame. */
12639 if (pending_autoraise_frame
)
12641 x_raise_frame (pending_autoraise_frame
);
12642 pending_autoraise_frame
= 0;
12645 if (mac_screen_config_changed
)
12647 mac_get_screen_info (dpyinfo
);
12648 mac_screen_config_changed
= 0;
12651 #if !TARGET_API_MAC_CARBON
12652 /* Check which frames are still visible. We do this here because
12653 there doesn't seem to be any direct notification from the Window
12654 Manager that the visibility of a window has changed (at least,
12655 not in all cases). */
12657 Lisp_Object tail
, frame
;
12659 FOR_EACH_FRAME (tail
, frame
)
12661 struct frame
*f
= XFRAME (frame
);
12663 /* The tooltip has been drawn already. Avoid the
12664 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12665 if (EQ (frame
, tip_frame
))
12668 if (FRAME_MAC_P (f
))
12669 mac_handle_visibility_change (f
);
12680 /* Need to override CodeWarrior's input function so no conversion is
12681 done on newlines Otherwise compiled functions in .elc files will be
12682 read incorrectly. Defined in ...:MSL C:MSL
12683 Common:Source:buffer_io.c. */
12686 __convert_to_newlines (unsigned char * p
, size_t * n
)
12688 #pragma unused(p,n)
12692 __convert_from_newlines (unsigned char * p
, size_t * n
)
12694 #pragma unused(p,n)
12700 make_mac_terminal_frame (struct frame
*f
)
12705 XSETFRAME (frame
, f
);
12707 f
->output_method
= output_mac
;
12708 f
->output_data
.mac
= (struct mac_output
*)
12709 xmalloc (sizeof (struct mac_output
));
12710 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12712 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12714 FRAME_COLS (f
) = 96;
12715 FRAME_LINES (f
) = 4;
12717 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12718 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12720 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12722 f
->output_data
.mac
->cursor_pixel
= 0;
12723 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12724 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12725 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12727 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12728 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12729 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12730 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12731 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12732 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12734 FRAME_FONTSET (f
) = -1;
12735 f
->output_data
.mac
->explicit_parent
= 0;
12738 f
->border_width
= 0;
12740 f
->internal_border_width
= 0;
12745 f
->new_text_cols
= 0;
12746 f
->new_text_lines
= 0;
12748 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12749 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12750 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12754 if (!(FRAME_MAC_WINDOW (f
) =
12755 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12756 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12758 /* so that update events can find this mac_output struct */
12759 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12765 /* Need to be initialized for unshow_buffer in window.c. */
12766 selected_window
= f
->selected_window
;
12768 Fmodify_frame_parameters (frame
,
12769 Fcons (Fcons (Qfont
,
12770 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12771 Fmodify_frame_parameters (frame
,
12772 Fcons (Fcons (Qforeground_color
,
12773 build_string ("black")), Qnil
));
12774 Fmodify_frame_parameters (frame
,
12775 Fcons (Fcons (Qbackground_color
,
12776 build_string ("white")), Qnil
));
12781 /***********************************************************************
12783 ***********************************************************************/
12785 static int mac_initialized
= 0;
12788 mac_make_rdb (xrm_option
)
12789 const char *xrm_option
;
12791 XrmDatabase database
;
12793 database
= xrm_get_preference_database (NULL
);
12795 xrm_merge_string_database (database
, xrm_option
);
12800 struct mac_display_info
*
12801 mac_term_init (display_name
, xrm_option
, resource_name
)
12802 Lisp_Object display_name
;
12804 char *resource_name
;
12806 struct mac_display_info
*dpyinfo
;
12807 struct terminal
*terminal
;
12811 if (!mac_initialized
)
12814 mac_initialized
= 1;
12817 if (x_display_list
)
12818 error ("Sorry, this version can only handle one display");
12820 dpyinfo
= &one_mac_display_info
;
12821 bzero (dpyinfo
, sizeof (*dpyinfo
));
12823 terminal
= mac_create_terminal (dpyinfo
);
12825 /* Set the name of the terminal. */
12826 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
12827 strncpy (terminal
->name
, SDATA (display_name
), SBYTES (display_name
));
12828 terminal
->name
[SBYTES (display_name
)] = 0;
12831 dpyinfo
->mac_id_name
12832 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12833 + SCHARS (Vsystem_name
)
12835 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12836 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12838 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12839 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12842 dpyinfo
->reference_count
= 0;
12843 dpyinfo
->resx
= 72.0;
12844 dpyinfo
->resy
= 72.0;
12846 mac_get_screen_info (dpyinfo
);
12848 dpyinfo
->grabbed
= 0;
12849 dpyinfo
->root_window
= NULL
;
12850 dpyinfo
->terminal
->image_cache
= make_image_cache ();
12852 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12853 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12854 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12855 dpyinfo
->mouse_face_window
= Qnil
;
12856 dpyinfo
->mouse_face_overlay
= Qnil
;
12857 dpyinfo
->mouse_face_hidden
= 0;
12859 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12861 /* Put this display on the chain. */
12862 dpyinfo
->next
= x_display_list
;
12863 x_display_list
= dpyinfo
;
12865 /* Put it on x_display_name_list. */
12866 x_display_name_list
= Fcons (Fcons (display_name
,
12867 Fcons (Qnil
, dpyinfo
->xrdb
)),
12868 x_display_name_list
);
12869 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12871 /* FIXME: Untested.
12872 Add the default keyboard. */
12873 add_keyboard_wait_descriptor (0);
12876 mac_init_fringe (terminal
->rif
);
12884 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12887 x_delete_display (dpyinfo
)
12888 struct mac_display_info
*dpyinfo
;
12892 /* Discard this display from x_display_name_list and x_display_list.
12893 We can't use Fdelq because that can quit. */
12894 if (! NILP (x_display_name_list
)
12895 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12896 x_display_name_list
= XCDR (x_display_name_list
);
12901 tail
= x_display_name_list
;
12902 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12904 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
12906 XSETCDR (tail
, XCDR (XCDR (tail
)));
12909 tail
= XCDR (tail
);
12913 if (x_display_list
== dpyinfo
)
12914 x_display_list
= dpyinfo
->next
;
12917 struct x_display_info
*tail
;
12919 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12920 if (tail
->next
== dpyinfo
)
12921 tail
->next
= tail
->next
->next
;
12924 /* Free the font names in the font table. */
12925 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12926 if (dpyinfo
->font_table
[i
].name
)
12928 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
12929 xfree (dpyinfo
->font_table
[i
].full_name
);
12930 xfree (dpyinfo
->font_table
[i
].name
);
12933 if (dpyinfo
->font_table
)
12935 if (dpyinfo
->font_table
->font_encoder
)
12936 xfree (dpyinfo
->font_table
->font_encoder
);
12937 xfree (dpyinfo
->font_table
);
12939 if (dpyinfo
->mac_id_name
)
12940 xfree (dpyinfo
->mac_id_name
);
12942 if (x_display_list
== 0)
12944 mac_clear_font_name_table ();
12945 bzero (dpyinfo
, sizeof (*dpyinfo
));
12956 MenuItemIndex menu_index
;
12958 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
12959 &menu
, &menu_index
);
12961 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12962 EnableMenuCommand (NULL
, kHICommandPreferences
);
12963 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
12964 &menu
, &menu_index
);
12967 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12968 InsertMenuItemTextWithCFString (menu
, NULL
,
12969 0, kMenuItemAttrSeparator
, 0);
12970 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
12971 0, 0, kHICommandAbout
);
12973 #else /* !MAC_OSX */
12974 #if TARGET_API_MAC_CARBON
12975 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
12985 static InterfaceTypeList types
= {kUnicodeDocument
};
12987 static InterfaceTypeList types
= {kTextService
};
12990 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
12991 &tsm_document_id
, 0);
12995 /* Set up use of X before we make the first connection. */
12997 extern frame_parm_handler mac_frame_parm_handlers
[];
12999 static struct redisplay_interface x_redisplay_interface
=
13001 mac_frame_parm_handlers
,
13005 x_clear_end_of_line
,
13007 x_after_update_window_line
,
13008 x_update_window_begin
,
13009 x_update_window_end
,
13013 mac_flush_display_optional
,
13015 0, /* flush_display_optional */
13017 x_clear_window_mouse_face
,
13018 x_get_glyph_overhangs
,
13019 x_fix_overlapping_area
,
13020 x_draw_fringe_bitmap
,
13022 mac_define_fringe_bitmap
,
13023 mac_destroy_fringe_bitmap
,
13025 0, /* define_fringe_bitmap */
13026 0, /* destroy_fringe_bitmap */
13028 mac_per_char_metric
,
13030 mac_compute_glyph_string_overhangs
,
13031 x_draw_glyph_string
,
13032 mac_define_frame_cursor
,
13033 mac_clear_frame_area
,
13034 mac_draw_window_cursor
,
13035 mac_draw_vertical_window_border
,
13036 mac_shift_glyphs_for_insert
13039 static struct terminal
*
13040 mac_create_terminal (struct mac_display_info
*dpyinfo
)
13042 struct terminal
*terminal
;
13044 terminal
= create_terminal ();
13046 terminal
->type
= output_mac
;
13047 terminal
->display_info
.mac
= dpyinfo
;
13048 dpyinfo
->terminal
= terminal
;
13050 terminal
->clear_frame_hook
= x_clear_frame
;
13051 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
13052 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
13053 terminal
->ring_bell_hook
= XTring_bell
;
13054 terminal
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
13055 terminal
->set_terminal_modes_hook
= XTset_terminal_modes
;
13056 terminal
->update_begin_hook
= x_update_begin
;
13057 terminal
->update_end_hook
= x_update_end
;
13058 terminal
->set_terminal_window_hook
= XTset_terminal_window
;
13059 terminal
->read_socket_hook
= XTread_socket
;
13060 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
13061 terminal
->mouse_position_hook
= XTmouse_position
;
13062 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
13063 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
13064 /* terminal->fullscreen_hook = XTfullscreen_hook; */
13065 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13066 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13067 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13068 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13069 terminal
->delete_frame_hook
= x_destroy_window
;
13070 /* terminal->delete_terminal_hook = x_delete_terminal; */
13072 terminal
->rif
= &x_redisplay_interface
;
13074 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
13075 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
13076 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
13077 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
13078 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
13082 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
13083 terminal
->char_ins_del_ok
= 1;
13084 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
13085 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
13086 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
13091 /* FIXME: This keyboard setup is 100% untested, just copied from
13092 w32_create_terminal in order to set window-system now that it's
13093 a keyboard object. */
13094 /* We don't yet support separate terminals on Mac, so don't try to share
13095 keyboards between virtual terminals that are on the same physical
13096 terminal like X does. */
13097 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
13098 init_kboard (terminal
->kboard
);
13099 terminal
->kboard
->Vwindow_system
= intern ("mac");
13100 terminal
->kboard
->next_kboard
= all_kboards
;
13101 all_kboards
= terminal
->kboard
;
13102 /* Don't let the initial kboard remain current longer than necessary.
13103 That would cause problems if a file loaded on startup tries to
13104 prompt in the mini-buffer. */
13105 if (current_kboard
== initial_kboard
)
13106 current_kboard
= terminal
->kboard
;
13107 terminal
->kboard
->reference_count
++;
13118 last_tool_bar_item
= -1;
13119 any_help_event_p
= 0;
13121 /* Try to use interrupt input; if we can't, then start polling. */
13122 Fset_input_interrupt_mode (Qt
);
13126 #if TARGET_API_MAC_CARBON
13128 install_application_handler ();
13137 init_coercion_handler ();
13139 init_apple_event_handler ();
13141 init_dm_notification_handler ();
13143 if (!inhibit_window_system
)
13145 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
13147 SetFrontProcess (&psn
);
13165 staticpro (&x_error_message_string
);
13166 x_error_message_string
= Qnil
;
13169 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
13170 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
13171 Qalt
= intern ("alt"); staticpro (&Qalt
);
13172 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
13173 Qsuper
= intern ("super"); staticpro (&Qsuper
);
13174 Qmodifier_value
= intern ("modifier-value");
13175 staticpro (&Qmodifier_value
);
13177 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
13178 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
13179 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
13180 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
13181 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
13183 #if TARGET_API_MAC_CARBON
13184 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
13186 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
13187 staticpro (&Qtoolbar_switch_mode
);
13188 #if USE_MAC_FONT_PANEL
13189 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
13190 Qselection
= intern ("selection"); staticpro (&Qselection
);
13193 Qservice
= intern ("service"); staticpro (&Qservice
);
13194 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
13195 Qperform
= intern ("perform"); staticpro (&Qperform
);
13197 Qmouse_drag_overlay
= intern ("mouse-drag-overlay");
13198 staticpro (&Qmouse_drag_overlay
);
13201 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
13202 Qupdate_active_input_area
= intern ("update-active-input-area");
13203 staticpro (&Qupdate_active_input_area
);
13204 Qunicode_for_key_event
= intern ("unicode-for-key-event");
13205 staticpro (&Qunicode_for_key_event
);
13210 Fprovide (intern ("mac-carbon"), Qnil
);
13213 staticpro (&Qreverse
);
13214 Qreverse
= intern ("reverse");
13216 staticpro (&x_display_name_list
);
13217 x_display_name_list
= Qnil
;
13219 staticpro (&last_mouse_scroll_bar
);
13220 last_mouse_scroll_bar
= Qnil
;
13222 staticpro (&fm_font_family_alist
);
13223 fm_font_family_alist
= Qnil
;
13226 staticpro (&atsu_font_id_hash
);
13227 atsu_font_id_hash
= Qnil
;
13229 staticpro (&fm_style_face_attributes_alist
);
13230 fm_style_face_attributes_alist
= Qnil
;
13234 staticpro (&saved_ts_script_language_on_focus
);
13235 saved_ts_script_language_on_focus
= Qnil
;
13238 /* We don't yet support this, but defining this here avoids whining
13239 from cus-start.el and other places, like "M-x set-variable". */
13240 DEFVAR_BOOL ("x-use-underline-position-properties",
13241 &x_use_underline_position_properties
,
13242 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13243 A value of nil means ignore them. If you encounter fonts with bogus
13244 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13245 to 4.1, set this to nil.
13247 NOTE: Not supported on Mac yet. */);
13248 x_use_underline_position_properties
= 0;
13250 DEFVAR_BOOL ("x-underline-at-descent-line",
13251 &x_underline_at_descent_line
,
13252 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
13253 A value of nil means to draw the underline according to the value of the
13254 variable `x-use-underline-position-properties', which is usually at the
13255 baseline level. The default value is nil. */);
13256 x_underline_at_descent_line
= 0;
13258 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
13259 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
13260 #ifdef USE_TOOLKIT_SCROLL_BARS
13261 Vx_toolkit_scroll_bars
= Qt
;
13263 Vx_toolkit_scroll_bars
= Qnil
;
13266 staticpro (&last_mouse_motion_frame
);
13267 last_mouse_motion_frame
= Qnil
;
13269 /* Variables to configure modifier key assignment. */
13271 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
13272 doc
: /* *Modifier key assumed when the Mac control key is pressed.
13273 The value can be `control', `meta', `alt', `hyper', or `super' for the
13274 respective modifier. The default is `control'. */);
13275 Vmac_control_modifier
= Qcontrol
;
13277 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
13278 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
13279 The value can be `control', `meta', `alt', `hyper', or `super' for the
13280 respective modifier. If the value is nil then the key will act as the
13281 normal Mac control modifier, and the option key can be used to compose
13282 characters depending on the chosen Mac keyboard setting. */);
13283 Vmac_option_modifier
= Qnil
;
13285 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
13286 doc
: /* *Modifier key assumed when the Mac command key is pressed.
13287 The value can be `control', `meta', `alt', `hyper', or `super' for the
13288 respective modifier. The default is `meta'. */);
13289 Vmac_command_modifier
= Qmeta
;
13291 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
13292 doc
: /* *Modifier key assumed when the Mac function key is pressed.
13293 The value can be `control', `meta', `alt', `hyper', or `super' for the
13294 respective modifier. Note that remapping the function key may lead to
13295 unexpected results for some keys on non-US/GB keyboards. */);
13296 Vmac_function_modifier
= Qnil
;
13298 DEFVAR_LISP ("mac-emulate-three-button-mouse",
13299 &Vmac_emulate_three_button_mouse
,
13300 doc
: /* *Specify a way of three button mouse emulation.
13301 The value can be nil, t, or the symbol `reverse'.
13302 A value of nil means that no emulation should be done and the modifiers
13303 should be placed on the mouse-1 event.
13304 t means that when the option-key is held down while pressing the mouse
13305 button, the click will register as mouse-2 and while the command-key
13306 is held down, the click will register as mouse-3.
13307 The symbol `reverse' means that the option-key will register for
13308 mouse-3 and the command-key will register for mouse-2. */);
13309 Vmac_emulate_three_button_mouse
= Qnil
;
13311 #if TARGET_API_MAC_CARBON
13312 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
13313 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
13314 Otherwise, the right click will be treated as mouse-2 and the wheel
13315 button will be mouse-3. */);
13316 mac_wheel_button_is_mouse_2
= 1;
13318 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
13319 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
13320 mac_pass_command_to_system
= 1;
13322 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
13323 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13324 mac_pass_control_to_system
= 1;
13328 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
13329 doc
: /* *If non-nil, allow anti-aliasing.
13330 The text will be rendered using Core Graphics text rendering which
13331 may anti-alias the text. */);
13333 mac_use_core_graphics
= 1;
13335 mac_use_core_graphics
= 0;
13338 /* Register an entry for `mac-roman' so that it can be used when
13339 creating the terminal frame on Mac OS 9 before loading
13340 term/mac-win.elc. */
13341 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
13342 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
13343 Each entry should be of the form:
13345 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13347 where CHARSET-NAME is a string used in font names to identify the
13348 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13349 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13350 Vmac_charset_info_alist
=
13351 Fcons (list3 (build_string ("mac-roman"),
13352 make_number (smRoman
), Qnil
), Qnil
);
13355 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13356 doc
: /* Overlay used to display Mac TSM active input area. */);
13357 Vmac_ts_active_input_overlay
= Qnil
;
13359 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf
,
13360 doc
: /* Byte sequence of the current Mac TSM active input area. */);
13361 /* `empty_string' is not ready yet on Mac OS Classic. */
13362 Vmac_ts_active_input_buf
= build_string ("");
13364 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13365 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13366 If the value is t, the input script and language are restored to those
13367 used in the last focus frame. If the value is a pair of integers, the
13368 input script and language codes, which are defined in the Script
13369 Manager, are set to its car and cdr parts, respectively. Otherwise,
13370 Emacs doesn't set them and thus follows the system default behavior. */);
13371 Vmac_ts_script_language_on_focus
= Qnil
;
13375 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13376 (do not change this comment) */