1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3 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 of the License, or
10 (at your option) any later version.
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. If not, see <http://www.gnu.org/licenses/>. */
20 /* Contributed by Andrew Choi (akochoi@mac.com). */
28 #include "blockinput.h"
36 #if !TARGET_API_MAC_CARBON
37 #include <Quickdraw.h>
38 #include <ToolUtils.h>
42 #include <Resources.h>
44 #include <TextUtils.h>
49 #if defined (__MRC__) || (__MSL__ >= 0x6000)
50 #include <ControlDefinitions.h>
56 #endif /* not TARGET_API_MAC_CARBON */
69 #include "dispextern.h"
71 #include "termhooks.h"
78 #include "intervals.h"
81 #include "character.h"
86 /* Non-nil means Emacs uses toolkit scroll bars. */
88 Lisp_Object Vx_toolkit_scroll_bars
;
90 /* If non-zero, the text will be rendered using Core Graphics text
91 rendering which may anti-alias the text. */
92 int mac_use_core_graphics
;
95 /* Non-zero means that a HELP_EVENT has been generated since Emacs
98 static int any_help_event_p
;
100 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
101 static Lisp_Object last_window
;
103 /* Non-zero means make use of UNDERLINE_POSITION font properties.
104 (Not yet supported.) */
105 int x_use_underline_position_properties
;
107 /* Non-zero means to draw the underline at the same place as the descent line. */
109 int x_underline_at_descent_line
;
111 /* This is a chain of structures for all the X displays currently in
114 struct x_display_info
*x_display_list
;
116 /* This is a list of cons cells, each of the form (NAME
117 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
118 x_display_list and in the same order. NAME is the name of the
119 frame. FONT-LIST-CACHE records previous values returned by
120 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
121 equivalent, which is implemented with a Lisp object, for the
124 Lisp_Object x_display_name_list
;
126 /* This is display since Mac does not support multiple ones. */
127 struct mac_display_info one_mac_display_info
;
129 /* Frame being updated by update_frame. This is declared in term.c.
130 This is set by update_begin and looked at by all the XT functions.
131 It is zero while not inside an update. In that case, the XT
132 functions assume that `selected_frame' is the frame to apply to. */
134 extern struct frame
*updating_frame
;
136 /* This is a frame waiting to be auto-raised, within XTread_socket. */
138 struct frame
*pending_autoraise_frame
;
142 Formerly, we used PointerMotionHintMask (in standard_event_mask)
143 so that we would have to call XQueryPointer after each MotionNotify
144 event to ask for another such event. However, this made mouse tracking
145 slow, and there was a bug that made it eventually stop.
147 Simply asking for MotionNotify all the time seems to work better.
149 In order to avoid asking for motion events and then throwing most
150 of them away or busy-polling the server for mouse positions, we ask
151 the server for pointer motion hints. This means that we get only
152 one event per group of mouse movements. "Groups" are delimited by
153 other kinds of events (focus changes and button clicks, for
154 example), or by XQueryPointer calls; when one of these happens, we
155 get another MotionNotify event the next time the mouse moves. This
156 is at least as efficient as getting motion events when mouse
157 tracking is on, and I suspect only negligibly worse when tracking
160 /* Where the mouse was last time we reported a mouse event. */
162 static Rect last_mouse_glyph
;
163 static FRAME_PTR last_mouse_glyph_frame
;
165 /* The scroll bar in which the last X motion event occurred.
167 If the last X motion event occurred in a scroll bar, we set this so
168 XTmouse_position can know whether to report a scroll bar motion or
171 If the last X motion event didn't occur in a scroll bar, we set
172 this to Qnil, to tell XTmouse_position to return an ordinary motion
175 static Lisp_Object last_mouse_scroll_bar
;
177 /* This is a hack. We would really prefer that XTmouse_position would
178 return the time associated with the position it returns, but there
179 doesn't seem to be any way to wrest the time-stamp from the server
180 along with the position query. So, we just keep track of the time
181 of the last movement we received, and return that in hopes that
182 it's somewhat accurate. */
184 static Time last_mouse_movement_time
;
186 struct scroll_bar
*tracked_scroll_bar
= NULL
;
188 /* Incremented by XTread_socket whenever it really tries to read
192 static int volatile input_signal_count
;
194 static int input_signal_count
;
197 extern Lisp_Object Vsystem_name
;
199 extern Lisp_Object Qeql
;
201 /* A mask of extra modifier bits to put into every keyboard char. */
203 extern EMACS_INT extra_keyboard_modifiers
;
205 /* The keysyms to use for the various modifiers. */
207 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
209 extern int inhibit_window_system
;
211 #if __MRC__ && !TARGET_API_MAC_CARBON
212 QDGlobals qd
; /* QuickDraw global information structure. */
215 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
217 struct mac_display_info
*mac_display_info_for_display (Display
*);
218 static void x_update_window_end
P_ ((struct window
*, int, int));
219 int x_catch_errors
P_ ((Display
*));
220 void x_uncatch_errors
P_ ((Display
*, int));
221 void x_lower_frame
P_ ((struct frame
*));
222 void x_scroll_bar_clear
P_ ((struct frame
*));
223 int x_had_errors_p
P_ ((Display
*));
224 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
225 void x_raise_frame
P_ ((struct frame
*));
226 void x_set_window_size
P_ ((struct frame
*, int, int, int));
227 void x_wm_set_window_state
P_ ((struct frame
*, int));
228 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
229 static void mac_initialize
P_ ((void));
230 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
231 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
232 static void x_update_end
P_ ((struct frame
*));
233 static void XTframe_up_to_date
P_ ((struct frame
*));
234 static void XTset_terminal_modes
P_ ((struct terminal
*));
235 static void XTreset_terminal_modes
P_ ((struct terminal
*));
236 static void x_clear_frame
P_ ((struct frame
*));
237 static void frame_highlight
P_ ((struct frame
*));
238 static void frame_unhighlight
P_ ((struct frame
*));
239 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
240 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
241 struct frame
*, struct input_event
*));
242 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
244 struct input_event
*));
245 static void XTframe_rehighlight
P_ ((struct frame
*));
246 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
247 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
248 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
249 enum text_cursor_kinds
));
251 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
252 static void x_flush
P_ ((struct frame
*f
));
253 static void x_update_begin
P_ ((struct frame
*));
254 static void x_update_window_begin
P_ ((struct window
*));
255 static void x_after_update_window_line
P_ ((struct glyph_row
*));
256 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
257 enum scroll_bar_part
*,
258 Lisp_Object
*, Lisp_Object
*,
261 static int is_emacs_window
P_ ((WindowRef
));
262 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
263 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
264 static struct terminal
*mac_create_terminal
P_ ((struct mac_display_info
*dpyinfo
));
267 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
268 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
269 #define GC_FONT(gc) ((gc)->xgcv.font)
270 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
272 #define CG_SET_FILL_COLOR(context, color) \
273 CGContextSetRGBFillColor (context, \
274 RED_FROM_ULONG (color) / 255.0f, \
275 GREEN_FROM_ULONG (color) / 255.0f, \
276 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
277 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
278 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
279 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
281 if (CGColorGetTypeID != NULL) \
282 CGContextSetFillColorWithColor (context, cg_color); \
284 CG_SET_FILL_COLOR (context, color); \
287 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
288 CGContextSetFillColorWithColor (context, cg_color)
291 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
292 CG_SET_FILL_COLOR (context, color)
294 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
295 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
297 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
298 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
302 #define CG_SET_STROKE_COLOR(context, color) \
303 CGContextSetRGBStrokeColor (context, \
304 RED_FROM_ULONG (color) / 255.0f, \
305 GREEN_FROM_ULONG (color) / 255.0f, \
306 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
307 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
308 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
309 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
311 if (CGColorGetTypeID != NULL) \
312 CGContextSetStrokeColorWithColor (context, cg_color); \
314 CG_SET_STROKE_COLOR (context, color); \
317 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
318 CGContextSetStrokeColorWithColor (context, cg_color)
321 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
322 CG_SET_STROKE_COLOR (context, color)
324 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
325 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
329 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
331 /* Fringe bitmaps. */
333 static int max_fringe_bmp
= 0;
334 static CGImageRef
*fringe_bmp
= 0;
336 CGColorSpaceRef mac_cg_color_space_rgb
;
337 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
338 static CGColorRef mac_cg_color_black
;
344 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
345 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
346 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
347 /* Don't check the availability of CGColorCreate; this symbol is
348 defined even in Mac OS X 10.1. */
349 if (CGColorGetTypeID
!= NULL
)
352 CGFloat rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
354 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
360 mac_begin_cg_clip (f
, gc
)
364 CGContextRef context
= FRAME_CG_CONTEXT (f
);
368 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
369 FRAME_CG_CONTEXT (f
) = context
;
372 CGContextSaveGState (context
);
373 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
374 CGContextScaleCTM (context
, 1, -1);
375 if (gc
&& gc
->n_clip_rects
)
376 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
385 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
389 mac_prepare_for_quickdraw (f
)
394 Lisp_Object rest
, frame
;
395 FOR_EACH_FRAME (rest
, frame
)
396 if (FRAME_MAC_P (XFRAME (frame
)))
397 mac_prepare_for_quickdraw (XFRAME (frame
));
401 CGContextRef context
= FRAME_CG_CONTEXT (f
);
405 CGContextSynchronize (context
);
406 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
407 &FRAME_CG_CONTEXT (f
));
413 static RgnHandle saved_port_clip_region
= NULL
;
416 mac_begin_clip (f
, gc
)
420 static RgnHandle new_region
= NULL
;
422 if (saved_port_clip_region
== NULL
)
423 saved_port_clip_region
= NewRgn ();
424 if (new_region
== NULL
)
425 new_region
= NewRgn ();
428 mac_prepare_for_quickdraw (f
);
430 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
432 if (gc
->n_clip_rects
)
434 GetClip (saved_port_clip_region
);
435 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
436 SetClip (new_region
);
444 if (gc
->n_clip_rects
)
445 SetClip (saved_port_clip_region
);
449 /* X display function emulation */
451 /* Mac version of XDrawLine. */
454 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
460 CGContextRef context
;
461 CGFloat gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
464 gx1
+= 0.5f
, gx2
+= 0.5f
;
466 gy1
+= 0.5f
, gy2
+= 0.5f
;
468 context
= mac_begin_cg_clip (f
, gc
);
469 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
470 CGContextBeginPath (context
);
471 CGContextMoveToPoint (context
, gx1
, gy1
);
472 CGContextAddLineToPoint (context
, gx2
, gy2
);
473 CGContextClosePath (context
);
474 CGContextStrokePath (context
);
492 mac_begin_clip (f
, gc
);
493 RGBForeColor (GC_FORE_COLOR (gc
));
500 /* Mac version of XDrawLine (to Pixmap). */
503 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
510 CGContextRef context
;
512 CGColorSpaceRef color_space
;
513 CGImageAlphaInfo alpha_info
;
514 CGFloat gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
517 gx1
+= 0.5f
, gx2
+= 0.5f
;
519 gy1
+= 0.5f
, gy2
+= 0.5f
;
521 if (ximg
->bits_per_pixel
== 32)
523 color_space
= mac_cg_color_space_rgb
;
524 alpha_info
= (kCGImageAlphaNoneSkipFirst
525 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
526 | kCGBitmapByteOrder32Host
533 alpha_info
= kCGImageAlphaOnly
;
535 if (color_space
== NULL
)
537 context
= CGBitmapContextCreate (ximg
->data
, ximg
->width
,
539 ximg
->bytes_per_line
, color_space
,
541 if (ximg
->bits_per_pixel
== 32)
542 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
544 CGContextSetGrayStrokeColor (context
, gc
->xgcv
.foreground
/ 255.0f
, 1.0);
545 CGContextMoveToPoint (context
, gx1
, gy1
);
546 CGContextAddLineToPoint (context
, gx2
, gy2
);
547 CGContextClosePath (context
);
548 CGContextStrokePath (context
);
549 CGContextRelease (context
);
569 GetGWorld (&old_port
, &old_gdh
);
572 RGBForeColor (GC_FORE_COLOR (gc
));
574 LockPixels (GetGWorldPixMap (p
));
577 UnlockPixels (GetGWorldPixMap (p
));
579 SetGWorld (old_port
, old_gdh
);
585 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
589 unsigned int width
, height
;
593 CGContextRef context
;
595 context
= mac_begin_cg_clip (f
, gc
);
596 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
597 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
604 mac_begin_clip (f
, gc
);
605 RGBBackColor (GC_BACK_COLOR (gc
));
606 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
608 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
615 /* Mac version of XClearArea. */
618 mac_clear_area (f
, x
, y
, width
, height
)
621 unsigned int width
, height
;
623 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
626 /* Mac version of XClearWindow. */
634 CGContextRef context
;
635 GC gc
= FRAME_NORMAL_GC (f
);
637 context
= mac_begin_cg_clip (f
, NULL
);
638 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
639 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
640 FRAME_PIXEL_HEIGHT (f
)));
643 #else /* !USE_CG_DRAWING */
644 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
646 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
648 #if TARGET_API_MAC_CARBON
652 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
655 #else /* not TARGET_API_MAC_CARBON */
656 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
657 #endif /* not TARGET_API_MAC_CARBON */
662 /* Mac replacement for XCopyArea. */
666 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
667 dest_x
, dest_y
, overlay_p
)
672 unsigned int width
, height
;
673 int dest_x
, dest_y
, overlay_p
;
675 CGContextRef context
;
676 CGFloat port_height
= FRAME_PIXEL_HEIGHT (f
);
677 CGRect dest_rect
= mac_rect_make (f
, dest_x
, dest_y
, width
, height
);
679 context
= mac_begin_cg_clip (f
, gc
);
682 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
683 CGContextFillRect (context
, dest_rect
);
685 CGContextClipToRect (context
, dest_rect
);
686 CGContextScaleCTM (context
, 1, -1);
687 CGContextTranslateCTM (context
, 0, -port_height
);
688 if (CGImageIsMask (image
))
689 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
690 CGContextDrawImage (context
,
691 mac_rect_make (f
, dest_x
- src_x
,
692 port_height
- (dest_y
- src_y
693 + CGImageGetHeight (image
)),
694 CGImageGetWidth (image
),
695 CGImageGetHeight (image
)),
700 #else /* !USE_CG_DRAWING */
703 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
706 int x
, y
, width
, height
;
707 unsigned short *bits
;
713 bitmap
.rowBytes
= sizeof(unsigned short);
714 bitmap
.baseAddr
= (char *)bits
;
715 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
717 mac_begin_clip (f
, gc
);
718 RGBForeColor (GC_FORE_COLOR (gc
));
719 RGBBackColor (GC_BACK_COLOR (gc
));
720 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
721 #if TARGET_API_MAC_CARBON
727 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
728 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
729 UnlockPortBits (port
);
731 #else /* not TARGET_API_MAC_CARBON */
732 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
733 overlay_p
? srcOr
: srcCopy
, 0);
734 #endif /* not TARGET_API_MAC_CARBON */
735 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
738 #endif /* !USE_CG_DRAWING */
741 /* Mac replacement for XCreateBitmapFromBitmapData. */
744 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
749 static const unsigned char swap_nibble
[16]
750 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
751 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
752 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
753 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
757 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
758 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
759 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
760 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
761 for (i
= 0; i
< h
; i
++)
763 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
764 for (j
= 0; j
< w1
; j
++)
766 /* Bitswap XBM bytes to match how Mac does things. */
767 unsigned char c
= *bits
++;
768 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
769 | (swap_nibble
[(c
>>4) & 0xf]));
773 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
778 mac_free_bitmap (bitmap
)
781 xfree (bitmap
->baseAddr
);
786 XCreatePixmap (display
, w
, width
, height
, depth
)
789 unsigned int width
, height
;
795 ximg
= xmalloc (sizeof (*ximg
));
797 ximg
->height
= height
;
798 ximg
->bits_per_pixel
= depth
== 1 ? 8 : 32;
799 ximg
->bytes_per_line
= width
* (ximg
->bits_per_pixel
/ 8);
800 ximg
->data
= xmalloc (ximg
->bytes_per_line
* height
);
808 SetPortWindowPort (w
);
810 SetRect (&r
, 0, 0, width
, height
);
811 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
814 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
815 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
817 /* CreateCGImageFromPixMaps requires ARGB format. */
818 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
828 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
832 unsigned int width
, height
;
833 unsigned long fg
, bg
;
839 CGDataProviderRef provider
;
840 CGImageRef image_mask
;
841 CGContextRef context
;
843 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
847 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
848 provider
= CGDataProviderCreateWithData (NULL
, bitmap
.baseAddr
,
849 bitmap
.rowBytes
* height
, NULL
);
850 image_mask
= CGImageMaskCreate (width
, height
, 1, 1, bitmap
.rowBytes
,
852 CGDataProviderRelease (provider
);
854 context
= CGBitmapContextCreate (pixmap
->data
, width
, height
, 8,
855 pixmap
->bytes_per_line
,
856 mac_cg_color_space_rgb
,
857 kCGImageAlphaNoneSkipFirst
858 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
859 | kCGBitmapByteOrder32Host
863 CG_SET_FILL_COLOR (context
, fg
);
864 CGContextFillRect (context
, CGRectMake (0, 0, width
, height
));
865 CG_SET_FILL_COLOR (context
, bg
);
866 CGContextDrawImage (context
, CGRectMake (0, 0, width
, height
), image_mask
);
867 CGContextRelease (context
);
868 CGImageRelease (image_mask
);
875 gc
= XCreateGC (display
, w
, 0, NULL
);
877 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
881 GetGWorld (&old_port
, &old_gdh
);
882 SetGWorld (pixmap
, NULL
);
883 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
884 XSetForeground (display
, gc
, fg
);
885 XSetBackground (display
, gc
, bg
);
886 RGBForeColor (GC_FORE_COLOR (gc
));
887 RGBBackColor (GC_BACK_COLOR (gc
));
888 LockPixels (GetGWorldPixMap (pixmap
));
889 #if TARGET_API_MAC_CARBON
890 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
891 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
892 #else /* not TARGET_API_MAC_CARBON */
893 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
894 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
895 #endif /* not TARGET_API_MAC_CARBON */
896 UnlockPixels (GetGWorldPixMap (pixmap
));
897 SetGWorld (old_port
, old_gdh
);
899 mac_free_bitmap (&bitmap
);
906 XFreePixmap (display
, pixmap
)
914 xfree (pixmap
->data
);
918 DisposeGWorld (pixmap
);
923 /* Mac replacement for XFillRectangle. */
926 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
930 unsigned int width
, height
;
933 CGContextRef context
;
935 context
= mac_begin_cg_clip (f
, gc
);
936 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
937 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
942 mac_begin_clip (f
, gc
);
943 RGBForeColor (GC_FORE_COLOR (gc
));
944 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
945 PaintRect (&r
); /* using foreground color of gc */
951 /* Mac replacement for XDrawRectangle: dest is a window. */
954 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
958 unsigned int width
, height
;
961 CGContextRef context
;
963 context
= mac_begin_cg_clip (f
, gc
);
964 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
965 CGContextStrokeRect (context
,
966 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
971 mac_begin_clip (f
, gc
);
972 RGBForeColor (GC_FORE_COLOR (gc
));
973 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
974 FrameRect (&r
); /* using foreground color of gc */
981 mac_invert_rectangle (f
, x
, y
, width
, height
)
984 unsigned int width
, height
;
986 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
987 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
988 if (CGContextSetBlendMode
!= NULL
)
991 CGContextRef context
;
993 context
= mac_begin_cg_clip (f
, NULL
);
994 CGContextSetRGBFillColor (context
, 1.0f
, 1.0f
, 1.0f
, 1.0f
);
995 CGContextSetBlendMode (context
, kCGBlendModeDifference
);
996 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
999 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
1000 else /* CGContextSetBlendMode == NULL */
1002 #endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
1003 #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)
1008 mac_prepare_for_quickdraw (f
);
1010 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1012 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
1020 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
1021 ConstUniCharArrayPtr text
;
1022 UniCharCount text_length
;
1024 ATSUTextLayout
*text_layout
;
1027 static ATSUTextLayout saved_text_layout
= NULL
;
1029 if (saved_text_layout
== NULL
)
1031 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
1032 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
1033 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
1034 static ATSLineLayoutOptions line_layout
=
1035 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1036 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
1037 | kATSLineUseQDRendering
1039 kATSLineIsDisplayOnly
| kATSLineFractDisable
1042 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
1044 err
= ATSUCreateTextLayoutWithTextPtr (text
,
1045 kATSUFromTextBeginning
,
1049 &saved_text_layout
);
1051 err
= ATSUSetLayoutControls (saved_text_layout
,
1052 sizeof (tags
) / sizeof (tags
[0]),
1053 tags
, sizes
, values
);
1055 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
1059 err
= ATSUSetRunStyle (saved_text_layout
, style
,
1060 kATSUFromTextBeginning
, kATSUToTextEnd
);
1062 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
1063 kATSUFromTextBeginning
,
1069 *text_layout
= saved_text_layout
;
1075 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1076 overstrike_p
, bytes_per_char
)
1081 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1084 ATSUTextLayout text_layout
;
1086 xassert (bytes_per_char
== 2);
1088 #ifndef WORDS_BIG_ENDIAN
1091 UniChar
*text
= (UniChar
*)buf
;
1093 for (i
= 0; i
< nchars
; i
++)
1094 text
[i
] = EndianU16_BtoN (text
[i
]);
1097 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
1099 GC_FONT (gc
)->mac_style
,
1104 if (!mac_use_core_graphics
)
1107 mac_begin_clip (f
, gc
);
1108 RGBForeColor (GC_FORE_COLOR (gc
));
1113 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1114 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1115 RGBBackColor (GC_BACK_COLOR (gc
));
1117 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1120 ATSUDrawText (text_layout
,
1121 kATSUFromTextBeginning
, kATSUToTextEnd
,
1122 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1126 ATSUDrawText (text_layout
,
1127 kATSUFromTextBeginning
, kATSUToTextEnd
,
1128 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1135 static CGContextRef context
;
1136 CGFloat port_height
= FRAME_PIXEL_HEIGHT (f
);
1137 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1138 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1139 static const ATSUAttributeValuePtr values
[] = {&context
};
1142 context
= mac_begin_cg_clip (f
, gc
);
1147 QDBeginCGContext (port
, &context
);
1148 if (gc
->n_clip_rects
|| bg_width
)
1150 CGContextTranslateCTM (context
, 0, port_height
);
1151 CGContextScaleCTM (context
, 1, -1);
1152 if (gc
->n_clip_rects
)
1153 CGContextClipToRects (context
, gc
->clip_rects
,
1158 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1159 CGContextFillRect (context
,
1161 x
, y
- FONT_BASE (GC_FONT (gc
)),
1163 FONT_HEIGHT (GC_FONT (gc
))));
1165 CGContextScaleCTM (context
, 1, -1);
1166 CGContextTranslateCTM (context
, 0, -port_height
);
1170 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1171 err
= ATSUSetLayoutControls (text_layout
,
1172 sizeof (tags
) / sizeof (tags
[0]),
1173 tags
, sizes
, values
);
1176 ATSUDrawText (text_layout
,
1177 kATSUFromTextBeginning
, kATSUToTextEnd
,
1178 Long2Fix (x
), Long2Fix (port_height
- y
));
1180 ATSUDrawText (text_layout
,
1181 kATSUFromTextBeginning
, kATSUToTextEnd
,
1182 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1185 mac_end_cg_clip (f
);
1188 CGContextSynchronize (context
);
1189 QDEndCGContext (port
, &context
);
1192 /* This doesn't work on Mac OS X 10.1. */
1193 ATSUClearLayoutControls (text_layout
,
1194 sizeof (tags
) / sizeof (tags
[0]), tags
);
1196 ATSUSetLayoutControls (text_layout
,
1197 sizeof (tags
) / sizeof (tags
[0]),
1198 tags
, sizes
, values
);
1201 #endif /* MAC_OSX */
1203 #endif /* USE_ATSUI */
1207 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1208 overstrike_p
, bytes_per_char
)
1213 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1215 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1219 mac_begin_clip (f
, gc
);
1220 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1221 if (mac_use_core_graphics
)
1222 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1224 RGBForeColor (GC_FORE_COLOR (gc
));
1228 RGBBackColor (GC_BACK_COLOR (gc
));
1234 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1236 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1237 into an offscreen graphics world first. So performance gain
1238 cannot be expected.)
1239 - It lowers rendering quality.
1240 - Some fonts leave garbage on cursor movement. */
1245 RGBBackColor (GC_BACK_COLOR (gc
));
1246 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1247 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1252 TextFont (GC_FONT (gc
)->mac_fontnum
);
1253 TextSize (GC_FONT (gc
)->mac_fontsize
);
1254 TextFace (GC_FONT (gc
)->mac_fontface
);
1256 DrawText (buf
, 0, nchars
* bytes_per_char
);
1261 DrawText (buf
, 0, nchars
* bytes_per_char
);
1264 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1267 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1268 if (mac_use_core_graphics
)
1269 SwapQDTextFlags(savedFlags
);
1275 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1276 overstrike_p
, bytes_per_char
)
1281 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1284 if (GC_FONT (gc
)->mac_style
)
1285 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1286 overstrike_p
, bytes_per_char
);
1288 #endif /* USE_ATSUI */
1289 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1290 overstrike_p
, bytes_per_char
);
1294 /* Mac replacement for XDrawImageString. */
1297 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1302 int nchars
, bg_width
, overstrike_p
;
1304 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1309 /* Mac replacement for XDrawImageString16. */
1312 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1317 int nchars
, bg_width
, overstrike_p
;
1319 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1324 /* Mac replacement for XQueryTextExtents, but takes a character. If
1325 STYLE is NULL, measurement is done by QuickDraw Text routines for
1326 the font of the current graphics port. If CG_GLYPH is not NULL,
1327 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1330 mac_query_char_extents (style
, c
,
1331 font_ascent_return
, font_descent_return
,
1332 overall_return
, cg_glyph
)
1339 int *font_ascent_return
, *font_descent_return
;
1340 XCharStruct
*overall_return
;
1341 #if USE_CG_TEXT_DRAWING
1347 OSStatus err
= noErr
;
1354 ATSUTextLayout text_layout
;
1357 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1359 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1361 ATSTrapezoid glyph_bounds
;
1363 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1364 kATSUFromTextBeginning
, kATSUToTextEnd
,
1365 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1366 kATSUseFractionalOrigins
,
1368 kATSUseDeviceOrigins
,
1370 1, &glyph_bounds
, NULL
);
1373 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1374 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1376 width
= Fix2Long (glyph_bounds
.upperRight
.x
1377 - glyph_bounds
.upperLeft
.x
);
1378 if (font_ascent_return
)
1379 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1380 if (font_descent_return
)
1381 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1384 if (err
== noErr
&& overall_return
)
1386 err
= ATSUMeasureTextImage (text_layout
,
1387 kATSUFromTextBeginning
, kATSUToTextEnd
,
1388 0, 0, &char_bounds
);
1390 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1391 #if USE_CG_TEXT_DRAWING
1392 if (err
== noErr
&& cg_glyph
)
1395 ATSUGlyphInfoArray glyph_info_array
;
1396 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1398 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1399 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1401 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1402 kATSUToTextEnd
, &count
,
1405 /* Make sure that we don't have to make layout
1407 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1408 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1409 && glyph_info_array
.glyphs
[0].screenX
== 0)
1411 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1412 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1423 if (font_ascent_return
|| font_descent_return
)
1427 GetFontInfo (&font_info
);
1428 if (font_ascent_return
)
1429 *font_ascent_return
= font_info
.ascent
;
1430 if (font_descent_return
)
1431 *font_descent_return
= font_info
.descent
;
1437 width
= CharWidth (ch
);
1438 QDTextBounds (1, &ch
, &char_bounds
);
1439 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1447 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1450 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1451 XFontStruct
*font_struct
;
1454 XCharStruct
*overall_return
;
1457 short width
= 0, lbearing
= 0, rbearing
= 0;
1460 for (i
= 0; i
< nchars
; i
++)
1462 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1464 width
+= FONT_WIDTH (font_struct
);
1467 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1468 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1469 width
+= pcm
->width
;
1474 overall_return
->lbearing
= lbearing
;
1475 overall_return
->rbearing
= rbearing
;
1476 overall_return
->width
= width
;
1478 /* What's the meaning of the return value of XTextExtents16? */
1482 #if USE_CG_TEXT_DRAWING
1483 static int cg_text_anti_aliasing_threshold
= 8;
1486 init_cg_text_anti_aliasing_threshold ()
1492 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1493 kCFPreferencesCurrentApplication
,
1496 cg_text_anti_aliasing_threshold
= threshold
;
1500 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1505 int nchars
, bg_width
, overstrike_p
;
1507 CGFloat port_height
, gx
, gy
;
1509 CGContextRef context
;
1513 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1516 port_height
= FRAME_PIXEL_HEIGHT (f
);
1518 gy
= port_height
- y
;
1519 glyphs
= (CGGlyph
*)buf
;
1520 advances
= alloca (sizeof (CGSize
) * nchars
);
1521 if (advances
== NULL
)
1523 for (i
= 0; i
< nchars
; i
++)
1525 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1527 advances
[i
].width
= pcm
->width
;
1528 advances
[i
].height
= 0;
1529 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1534 context
= mac_begin_cg_clip (f
, gc
);
1536 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1537 if (gc
->n_clip_rects
|| bg_width
)
1539 CGContextTranslateCTM (context
, 0, port_height
);
1540 CGContextScaleCTM (context
, 1, -1);
1541 if (gc
->n_clip_rects
)
1542 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1546 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1549 mac_rect_make (f
, gx
, y
- FONT_BASE (GC_FONT (gc
)),
1550 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1552 CGContextScaleCTM (context
, 1, -1);
1553 CGContextTranslateCTM (context
, 0, -port_height
);
1557 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1558 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1559 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1560 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1561 CGContextSetShouldAntialias (context
, false);
1562 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1563 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1564 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1567 CGContextSetTextPosition (context
, gx
, gy
);
1568 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1571 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1572 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1575 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1576 else /* CGContextShowGlyphsWithAdvances == NULL */
1578 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1579 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1581 for (i
= 0; i
< nchars
; i
++)
1583 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1585 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1586 gx
+= advances
[i
].width
;
1591 mac_end_cg_clip (f
);
1593 CGContextSynchronize (context
);
1594 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1603 /* Mac replacement for XCopyArea: dest must be window. */
1606 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1611 unsigned int width
, height
;
1616 mac_begin_clip (f
, gc
);
1618 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1619 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1621 ForeColor (blackColor
);
1622 BackColor (whiteColor
);
1624 LockPixels (GetGWorldPixMap (src
));
1625 #if TARGET_API_MAC_CARBON
1630 LockPortBits (port
);
1631 CopyBits (GetPortBitMapForCopyBits (src
),
1632 GetPortBitMapForCopyBits (port
),
1633 &src_r
, &dest_r
, srcCopy
, 0);
1634 UnlockPortBits (port
);
1636 #else /* not TARGET_API_MAC_CARBON */
1637 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1638 &src_r
, &dest_r
, srcCopy
, 0);
1639 #endif /* not TARGET_API_MAC_CARBON */
1640 UnlockPixels (GetGWorldPixMap (src
));
1642 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1649 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1650 width
, height
, dest_x
, dest_y
)
1655 unsigned int width
, height
;
1660 mac_begin_clip (f
, gc
);
1662 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1663 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1665 ForeColor (blackColor
);
1666 BackColor (whiteColor
);
1668 LockPixels (GetGWorldPixMap (src
));
1669 LockPixels (GetGWorldPixMap (mask
));
1670 #if TARGET_API_MAC_CARBON
1675 LockPortBits (port
);
1676 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1677 GetPortBitMapForCopyBits (port
),
1678 &src_r
, &src_r
, &dest_r
);
1679 UnlockPortBits (port
);
1681 #else /* not TARGET_API_MAC_CARBON */
1682 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1683 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1684 #endif /* not TARGET_API_MAC_CARBON */
1685 UnlockPixels (GetGWorldPixMap (mask
));
1686 UnlockPixels (GetGWorldPixMap (src
));
1688 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1692 #endif /* !USE_CG_DRAWING */
1695 /* Mac replacement for XCopyArea: used only for scrolling. */
1698 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1702 unsigned int width
, height
;
1705 #if TARGET_API_MAC_CARBON
1707 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1709 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1711 mac_prepare_for_quickdraw (f
);
1713 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1714 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1715 kScrollWindowNoOptions
, dummy
);
1717 #else /* not TARGET_API_MAC_CARBON */
1719 WindowRef w
= FRAME_MAC_WINDOW (f
);
1721 mac_begin_clip (f
, gc
);
1723 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1724 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1726 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1727 color mapping in CopyBits. Otherwise, it will be slow. */
1728 ForeColor (blackColor
);
1729 BackColor (whiteColor
);
1730 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1732 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1735 #endif /* not TARGET_API_MAC_CARBON */
1739 /* Mac replacement for XChangeGC. */
1742 XChangeGC (display
, gc
, mask
, xgcv
)
1748 if (mask
& GCForeground
)
1749 XSetForeground (display
, gc
, xgcv
->foreground
);
1750 if (mask
& GCBackground
)
1751 XSetBackground (display
, gc
, xgcv
->background
);
1753 XSetFont (display
, gc
, xgcv
->font
);
1757 /* Mac replacement for XCreateGC. */
1760 XCreateGC (display
, d
, mask
, xgcv
)
1766 GC gc
= xmalloc (sizeof (*gc
));
1768 bzero (gc
, sizeof (*gc
));
1769 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1770 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1771 if (CGColorGetTypeID
!= NULL
)
1774 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1775 CGColorRetain (gc
->cg_fore_color
);
1776 CGColorRetain (gc
->cg_back_color
);
1779 XChangeGC (display
, gc
, mask
, xgcv
);
1785 /* Used in xfaces.c. */
1788 XFreeGC (display
, gc
)
1792 if (gc
->clip_region
)
1793 DisposeRgn (gc
->clip_region
);
1794 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1795 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1796 if (CGColorGetTypeID
!= NULL
)
1799 CGColorRelease (gc
->cg_fore_color
);
1800 CGColorRelease (gc
->cg_back_color
);
1807 /* Mac replacement for XGetGCValues. */
1810 XGetGCValues (display
, gc
, mask
, xgcv
)
1816 if (mask
& GCForeground
)
1817 xgcv
->foreground
= gc
->xgcv
.foreground
;
1818 if (mask
& GCBackground
)
1819 xgcv
->background
= gc
->xgcv
.background
;
1821 xgcv
->font
= gc
->xgcv
.font
;
1825 /* Mac replacement for XSetForeground. */
1828 XSetForeground (display
, gc
, color
)
1831 unsigned long color
;
1833 if (gc
->xgcv
.foreground
!= color
)
1835 gc
->xgcv
.foreground
= color
;
1836 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1837 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1838 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1839 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1840 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1841 if (CGColorGetTypeID
!= NULL
)
1844 CGColorRelease (gc
->cg_fore_color
);
1847 gc
->cg_fore_color
= mac_cg_color_black
;
1848 CGColorRetain (gc
->cg_fore_color
);
1854 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1855 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1856 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1858 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1866 /* Mac replacement for XSetBackground. */
1869 XSetBackground (display
, gc
, color
)
1872 unsigned long color
;
1874 if (gc
->xgcv
.background
!= color
)
1876 gc
->xgcv
.background
= color
;
1877 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1878 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1879 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1880 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1881 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1882 if (CGColorGetTypeID
!= NULL
)
1885 CGColorRelease (gc
->cg_back_color
);
1888 gc
->cg_back_color
= mac_cg_color_black
;
1889 CGColorRetain (gc
->cg_back_color
);
1895 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1896 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1897 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1899 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1907 /* Mac replacement for XSetFont. */
1910 XSetFont (display
, gc
, font
)
1915 gc
->xgcv
.font
= font
;
1919 /* Mac replacement for XSetClipRectangles. */
1922 mac_set_clip_rectangles (f
, gc
, rectangles
, n
)
1930 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1932 gc
->n_clip_rects
= n
;
1935 if (gc
->clip_region
== NULL
)
1936 gc
->clip_region
= NewRgn ();
1937 RectRgn (gc
->clip_region
, rectangles
);
1940 RgnHandle region
= NewRgn ();
1942 for (i
= 1; i
< n
; i
++)
1944 RectRgn (region
, rectangles
+ i
);
1945 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1947 DisposeRgn (region
);
1950 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1951 for (i
= 0; i
< n
; i
++)
1953 Rect
*rect
= rectangles
+ i
;
1955 gc
->clip_rects
[i
] = mac_rect_make (f
, rect
->left
, rect
->top
,
1956 rect
->right
- rect
->left
,
1957 rect
->bottom
- rect
->top
);
1963 /* Mac replacement for XSetClipMask. */
1966 mac_reset_clip_rectangles (f
, gc
)
1970 gc
->n_clip_rects
= 0;
1974 /* Mac replacement for XSetWindowBackground. */
1977 XSetWindowBackground (display
, w
, color
)
1980 unsigned long color
;
1982 #if !TARGET_API_MAC_CARBON
1983 AuxWinHandle aw_handle
;
1984 CTabHandle ctab_handle
;
1985 ColorSpecPtr ct_table
;
1990 bg_color
.red
= RED16_FROM_ULONG (color
);
1991 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1992 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1994 #if TARGET_API_MAC_CARBON
1995 SetWindowContentColor (w
, &bg_color
);
1997 if (GetAuxWin (w
, &aw_handle
))
1999 ctab_handle
= (*aw_handle
)->awCTable
;
2000 HandToHand ((Handle
*) &ctab_handle
);
2001 ct_table
= (*ctab_handle
)->ctTable
;
2002 ct_size
= (*ctab_handle
)->ctSize
;
2003 while (ct_size
> -1)
2005 if (ct_table
->value
== 0)
2007 ct_table
->rgb
= bg_color
;
2008 CTabChanged (ctab_handle
);
2009 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
2017 /* Flush display of frame F, or of all frames if F is null. */
2023 #if TARGET_API_MAC_CARBON
2026 mac_prepare_for_quickdraw (f
);
2029 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
2031 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
2037 /* Remove calls to XFlush by defining XFlush to an empty replacement.
2038 Calls to XFlush should be unnecessary because the X output buffer
2039 is flushed automatically as needed by calls to XPending,
2040 XNextEvent, or XWindowEvent according to the XFlush man page.
2041 XTread_socket calls XPending. Removing XFlush improves
2044 #define XFlush(DISPLAY) (void) 0
2048 mac_flush_display_optional (f
)
2052 mac_prepare_for_quickdraw (f
);
2057 /***********************************************************************
2058 Starting and ending an update
2059 ***********************************************************************/
2061 /* Start an update of frame F. This function is installed as a hook
2062 for update_begin, i.e. it is called when update_begin is called.
2063 This function is called prior to calls to x_update_window_begin for
2064 each window being updated. */
2070 #if TARGET_API_MAC_CARBON
2071 /* During update of a frame, availability of input events is
2072 periodically checked with ReceiveNextEvent if
2073 redisplay-dont-pause is nil. That normally flushes window buffer
2074 changes for every check, and thus screen update looks waving even
2075 if no input is available. So we disable screen updates during
2076 update of a frame. */
2078 DisableScreenUpdates ();
2084 /* Start update of window W. Set the global variable updated_window
2085 to the window being updated and set output_cursor to the cursor
2089 x_update_window_begin (w
)
2092 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2093 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
2096 set_output_cursor (&w
->cursor
);
2100 if (f
== display_info
->mouse_face_mouse_frame
)
2102 /* Don't do highlighting for mouse motion during the update. */
2103 display_info
->mouse_face_defer
= 1;
2105 /* If F needs to be redrawn, simply forget about any prior mouse
2107 if (FRAME_GARBAGED_P (f
))
2108 display_info
->mouse_face_window
= Qnil
;
2110 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
2111 their mouse_face_p flag set, which means that they are always
2112 unequal to rows in a desired matrix which never have that
2113 flag set. So, rows containing mouse-face glyphs are never
2114 scrolled, and we don't have to switch the mouse highlight off
2115 here to prevent it from being scrolled. */
2117 /* Can we tell that this update does not affect the window
2118 where the mouse highlight is? If so, no need to turn off.
2119 Likewise, don't do anything if the frame is garbaged;
2120 in that case, the frame's current matrix that we would use
2121 is all wrong, and we will redisplay that line anyway. */
2122 if (!NILP (display_info
->mouse_face_window
)
2123 && w
== XWINDOW (display_info
->mouse_face_window
))
2127 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2128 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2131 if (i
< w
->desired_matrix
->nrows
)
2132 clear_mouse_face (display_info
);
2141 /* Draw a vertical window border from (x,y0) to (x,y1) */
2144 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2148 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2151 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2153 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2156 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2159 /* End update of window W (which is equal to updated_window).
2161 Draw vertical borders between horizontally adjacent windows, and
2162 display W's cursor if CURSOR_ON_P is non-zero.
2164 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2165 glyphs in mouse-face were overwritten. In that case we have to
2166 make sure that the mouse-highlight is properly redrawn.
2168 W may be a menu bar pseudo-window in case we don't have X toolkit
2169 support. Such windows don't have a cursor, so don't display it
2173 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2175 int cursor_on_p
, mouse_face_overwritten_p
;
2177 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2179 if (!w
->pseudo_window_p
)
2184 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2186 output_cursor
.x
, output_cursor
.y
);
2188 if (draw_window_fringes (w
, 1))
2189 x_draw_vertical_border (w
);
2194 /* If a row with mouse-face was overwritten, arrange for
2195 XTframe_up_to_date to redisplay the mouse highlight. */
2196 if (mouse_face_overwritten_p
)
2198 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2199 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2200 dpyinfo
->mouse_face_window
= Qnil
;
2203 updated_window
= NULL
;
2207 /* End update of frame F. This function is installed as a hook in
2214 /* Mouse highlight may be displayed again. */
2215 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2218 #if TARGET_API_MAC_CARBON
2219 EnableScreenUpdates ();
2221 XFlush (FRAME_MAC_DISPLAY (f
));
2226 /* This function is called from various places in xdisp.c whenever a
2227 complete update has been performed. The global variable
2228 updated_window is not available here. */
2231 XTframe_up_to_date (f
)
2234 if (FRAME_MAC_P (f
))
2236 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2238 if (dpyinfo
->mouse_face_deferred_gc
2239 || f
== dpyinfo
->mouse_face_mouse_frame
)
2242 if (dpyinfo
->mouse_face_mouse_frame
)
2243 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2244 dpyinfo
->mouse_face_mouse_x
,
2245 dpyinfo
->mouse_face_mouse_y
);
2246 dpyinfo
->mouse_face_deferred_gc
= 0;
2253 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2254 arrow bitmaps, or clear the fringes if no bitmaps are required
2255 before DESIRED_ROW is made current. The window being updated is
2256 found in updated_window. This function is called from
2257 update_window_line only if it is known that there are differences
2258 between bitmaps to be drawn between current row and DESIRED_ROW. */
2261 x_after_update_window_line (desired_row
)
2262 struct glyph_row
*desired_row
;
2264 struct window
*w
= updated_window
;
2270 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2271 desired_row
->redraw_fringe_bitmaps_p
= 1;
2273 /* When a window has disappeared, make sure that no rest of
2274 full-width rows stays visible in the internal border. Could
2275 check here if updated_window is the leftmost/rightmost window,
2276 but I guess it's not worth doing since vertically split windows
2277 are almost never used, internal border is rarely set, and the
2278 overhead is very small. */
2279 if (windows_or_buffers_changed
2280 && desired_row
->full_width_p
2281 && (f
= XFRAME (w
->frame
),
2282 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2284 && (height
= desired_row
->visible_height
,
2287 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2289 /* Internal border is drawn below the tool bar. */
2290 if (WINDOWP (f
->tool_bar_window
)
2291 && w
== XWINDOW (f
->tool_bar_window
))
2295 mac_clear_area (f
, 0, y
, width
, height
);
2296 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2302 /* Draw the bitmap WHICH in one of the left or right fringes of
2303 window W. ROW is the glyph row for which to display the bitmap; it
2304 determines the vertical position at which the bitmap has to be
2308 x_draw_fringe_bitmap (w
, row
, p
)
2310 struct glyph_row
*row
;
2311 struct draw_fringe_bitmap_params
*p
;
2313 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2314 Display
*display
= FRAME_MAC_DISPLAY (f
);
2315 struct face
*face
= p
->face
;
2317 int overlay_p
= p
->overlay_p
;
2322 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2324 #if 0 /* MAC_TODO: stipple */
2325 /* In case the same realized face is used for fringes and
2326 for something displayed in the text (e.g. face `region' on
2327 mono-displays, the fill style may have been changed to
2328 FillSolid in x_draw_glyph_string_background. */
2330 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2332 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2335 /* If the fringe is adjacent to the left (right) scroll bar of a
2336 leftmost (rightmost, respectively) window, then extend its
2337 background to the gap between the fringe and the bar. */
2338 if ((WINDOW_LEFTMOST_P (w
)
2339 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2340 || (WINDOW_RIGHTMOST_P (w
)
2341 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2343 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2347 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2348 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2349 * FRAME_COLUMN_WIDTH (f
));
2352 && (left
+ width
== p
->x
2353 || p
->x
+ p
->wd
== left
))
2355 /* Bitmap fills the fringe and we need background
2357 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
2361 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
2363 ny
= row
->visible_height
;
2368 if (left
+ width
== bx
)
2370 bx
= left
+ sb_width
;
2371 nx
+= width
- sb_width
;
2373 else if (bx
+ nx
== left
)
2374 nx
+= width
- sb_width
;
2381 mac_erase_rectangle (f
, face
->gc
, bx
, by
, nx
, ny
);
2382 /* The fringe background has already been filled. */
2386 #if 0 /* MAC_TODO: stipple */
2388 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2391 #endif /* MAC_OSX */
2393 /* Must clip because of partially visible lines. */
2394 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2397 /* Adjust position of "bottom aligned" bitmap on partially
2398 visible last row. */
2400 int oldVH
= row
->visible_height
;
2401 row
->visible_height
= p
->h
;
2402 row
->y
-= rowY
- p
->y
;
2403 x_clip_to_row (w
, row
, -1, face
->gc
);
2405 row
->visible_height
= oldVH
;
2408 x_clip_to_row (w
, row
, -1, face
->gc
);
2411 if (p
->bx
>= 0 && !p
->overlay_p
)
2413 #if 0 /* MAC_TODO: stipple */
2414 /* In case the same realized face is used for fringes and
2415 for something displayed in the text (e.g. face `region' on
2416 mono-displays, the fill style may have been changed to
2417 FillSolid in x_draw_glyph_string_background. */
2419 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2421 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2424 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2426 #if 0 /* MAC_TODO: stipple */
2428 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2431 #endif /* !MAC_OSX */
2435 && p
->which
< max_fringe_bmp
2441 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2442 XSetForeground (display
, face
->gc
,
2444 ? (p
->overlay_p
? face
->background
2445 : f
->output_data
.mac
->cursor_pixel
)
2446 : face
->foreground
));
2448 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2449 p
->wd
, p
->h
, p
->x
, p
->y
, overlay_p
);
2451 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2452 p
->wd
, p
->h
, p
->bits
+ p
->dh
, overlay_p
);
2454 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2457 mac_reset_clip_rectangles (f
, face
->gc
);
2462 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2464 unsigned short *bits
;
2468 CGDataProviderRef provider
;
2470 if (which
>= max_fringe_bmp
)
2473 max_fringe_bmp
= which
+ 20;
2474 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2475 while (i
< max_fringe_bmp
)
2476 fringe_bmp
[i
++] = 0;
2479 for (i
= 0; i
< h
; i
++)
2484 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2485 sizeof (unsigned short) * h
, NULL
);
2488 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2489 sizeof (unsigned short),
2491 CGDataProviderRelease (provider
);
2498 mac_destroy_fringe_bitmap (which
)
2501 if (which
>= max_fringe_bmp
)
2504 if (fringe_bmp
[which
])
2507 CGImageRelease (fringe_bmp
[which
]);
2510 fringe_bmp
[which
] = 0;
2515 /* This is called when starting Emacs and when restarting after
2516 suspend. When starting Emacs, no window is mapped. And nothing
2517 must be done to Emacs's own window if it is suspended (though that
2521 XTset_terminal_modes (struct terminal
*t
)
2525 /* This is called when exiting or suspending Emacs. Exiting will make
2526 the windows go away, and suspending requires no action. */
2529 XTreset_terminal_modes (struct terminal
*t
)
2535 /***********************************************************************
2537 ***********************************************************************/
2539 /* Function prototypes of this page. */
2541 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2542 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
2543 struct charset
*, int *));
2547 pcm_init (pcm
, count
)
2551 bzero (pcm
, sizeof (XCharStruct
) * count
);
2552 while (--count
>= 0)
2554 pcm
->descent
= PCM_INVALID
;
2559 static enum pcm_status
2560 pcm_get_status (pcm
)
2561 const XCharStruct
*pcm
;
2563 int height
= pcm
->ascent
+ pcm
->descent
;
2565 /* Negative height means some special status. */
2566 return height
>= 0 ? PCM_VALID
: height
;
2569 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2570 is not contained in the font. */
2572 static INLINE XCharStruct
*
2573 x_per_char_metric (font
, char2b
)
2577 /* The result metric information. */
2578 XCharStruct
*pcm
= NULL
;
2580 xassert (font
&& char2b
);
2583 if (font
->mac_style
)
2585 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2589 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2590 pcm_init (*row
, 0x100);
2592 pcm
= *row
+ char2b
->byte2
;
2593 if (pcm_get_status (pcm
) != PCM_VALID
)
2596 mac_query_char_extents (font
->mac_style
,
2597 (char2b
->byte1
<< 8) + char2b
->byte2
,
2598 NULL
, NULL
, pcm
, NULL
);
2605 if (font
->bounds
.per_char
!= NULL
)
2607 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2609 /* min_char_or_byte2 specifies the linear character index
2610 corresponding to the first element of the per_char array,
2611 max_char_or_byte2 is the index of the last character. A
2612 character with non-zero CHAR2B->byte1 is not in the font.
2613 A character with byte2 less than min_char_or_byte2 or
2614 greater max_char_or_byte2 is not in the font. */
2615 if (char2b
->byte1
== 0
2616 && char2b
->byte2
>= font
->min_char_or_byte2
2617 && char2b
->byte2
<= font
->max_char_or_byte2
)
2618 pcm
= font
->bounds
.per_char
2619 + (char2b
->byte2
- font
->min_char_or_byte2
);
2623 /* If either min_byte1 or max_byte1 are nonzero, both
2624 min_char_or_byte2 and max_char_or_byte2 are less than
2625 256, and the 2-byte character index values corresponding
2626 to the per_char array element N (counting from 0) are:
2628 byte1 = N/D + min_byte1
2629 byte2 = N\D + min_char_or_byte2
2633 D = max_char_or_byte2 - min_char_or_byte2 + 1
2634 / = integer division
2635 \ = integer modulus */
2636 if (char2b
->byte1
>= font
->min_byte1
2637 && char2b
->byte1
<= font
->max_byte1
2638 && char2b
->byte2
>= font
->min_char_or_byte2
2639 && char2b
->byte2
<= font
->max_char_or_byte2
)
2641 pcm
= (font
->bounds
.per_char
2642 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2643 * (char2b
->byte1
- font
->min_byte1
))
2644 + (char2b
->byte2
- font
->min_char_or_byte2
));
2650 /* If the per_char pointer is null, all glyphs between the first
2651 and last character indexes inclusive have the same
2652 information, as given by both min_bounds and max_bounds. */
2653 if (char2b
->byte2
>= font
->min_char_or_byte2
2654 && char2b
->byte2
<= font
->max_char_or_byte2
)
2655 pcm
= &font
->max_bounds
;
2661 return ((pcm
== NULL
2663 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2664 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2673 static XCharStruct
*
2674 mac_per_char_metric (font
, char2b
, font_type
)
2679 return x_per_char_metric (font
, char2b
);
2683 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2684 the two-byte form of C. Encoding is returned in *CHAR2B. */
2687 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
2690 struct font_info
*font_info
;
2691 struct charset
*charset
;
2694 XFontStruct
*font
= font_info
->font
;
2696 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2697 This may be either a program in a special encoder language or a
2699 if (font_info
->font_encoder
)
2701 /* It's a program. */
2702 struct ccl_program
*ccl
= font_info
->font_encoder
;
2704 check_ccl_update (ccl
);
2705 if (CHARSET_DIMENSION (charset
) == 1)
2707 ccl
->reg
[0] = CHARSET_ID (charset
);
2708 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
2713 ccl
->reg
[0] = CHARSET_ID (charset
);
2714 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
2715 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
2718 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
2720 /* We assume that MSBs are appropriately set/reset by CCL
2722 if (font
->max_byte1
== 0) /* 1-byte font */
2723 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
2725 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
2727 else if (font_info
->encoding_type
)
2729 /* Fixed encoding scheme. See fontset.h for the meaning of the
2730 encoding numbers. */
2731 unsigned char enc
= font_info
->encoding_type
;
2733 if ((enc
== 1 || enc
== 2)
2734 && CHARSET_DIMENSION (charset
) == 2)
2735 char2b
->byte1
|= 0x80;
2737 if (enc
== 1 || enc
== 3)
2738 char2b
->byte2
|= 0x80;
2742 int code
= (char2b
->byte1
<< 8) | char2b
->byte2
;
2745 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
2750 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2752 return FONT_TYPE_UNKNOWN
;
2757 /***********************************************************************
2759 ***********************************************************************/
2763 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2764 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2765 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2767 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2768 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2769 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2770 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2771 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2772 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2773 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2774 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2775 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2776 unsigned long *, double, int));*/
2777 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2778 double, int, unsigned long));
2779 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2780 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2781 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2782 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2783 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2785 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2786 int, int, int, int, int, int,
2788 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2789 int, int, int, Rect
*));
2792 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2796 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2801 struct glyph_string
*s
;
2803 if (s
->font
== FRAME_FONT (s
->f
)
2804 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2805 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2807 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2810 /* Cursor on non-default face: must merge. */
2814 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2815 xgcv
.foreground
= s
->face
->background
;
2817 /* If the glyph would be invisible, try a different foreground. */
2818 if (xgcv
.foreground
== xgcv
.background
)
2819 xgcv
.foreground
= s
->face
->foreground
;
2820 if (xgcv
.foreground
== xgcv
.background
)
2821 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2822 if (xgcv
.foreground
== xgcv
.background
)
2823 xgcv
.foreground
= s
->face
->foreground
;
2825 /* Make sure the cursor is distinct from text in this face. */
2826 if (xgcv
.background
== s
->face
->background
2827 && xgcv
.foreground
== s
->face
->foreground
)
2829 xgcv
.background
= s
->face
->foreground
;
2830 xgcv
.foreground
= s
->face
->background
;
2833 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2834 xgcv
.font
= s
->font
;
2835 mask
= GCForeground
| GCBackground
| GCFont
;
2837 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2838 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2841 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2842 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2844 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2849 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2852 x_set_mouse_face_gc (s
)
2853 struct glyph_string
*s
;
2858 /* What face has to be used last for the mouse face? */
2859 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2860 face
= FACE_FROM_ID (s
->f
, face_id
);
2862 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2864 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2865 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
2867 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
2868 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2869 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2871 /* If font in this face is same as S->font, use it. */
2872 if (s
->font
== s
->face
->font
)
2873 s
->gc
= s
->face
->gc
;
2876 /* Otherwise construct scratch_cursor_gc with values from FACE
2881 xgcv
.background
= s
->face
->background
;
2882 xgcv
.foreground
= s
->face
->foreground
;
2883 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2884 xgcv
.font
= s
->font
;
2885 mask
= GCForeground
| GCBackground
| GCFont
;
2887 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2888 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2891 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2892 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2894 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2897 xassert (s
->gc
!= 0);
2901 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2902 Faces to use in the mode line have already been computed when the
2903 matrix was built, so there isn't much to do, here. */
2906 x_set_mode_line_face_gc (s
)
2907 struct glyph_string
*s
;
2909 s
->gc
= s
->face
->gc
;
2913 /* Set S->gc of glyph string S for drawing that glyph string. Set
2914 S->stippled_p to a non-zero value if the face of S has a stipple
2918 x_set_glyph_string_gc (s
)
2919 struct glyph_string
*s
;
2921 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2923 if (s
->hl
== DRAW_NORMAL_TEXT
)
2925 s
->gc
= s
->face
->gc
;
2926 s
->stippled_p
= s
->face
->stipple
!= 0;
2928 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2930 x_set_mode_line_face_gc (s
);
2931 s
->stippled_p
= s
->face
->stipple
!= 0;
2933 else if (s
->hl
== DRAW_CURSOR
)
2935 x_set_cursor_gc (s
);
2938 else if (s
->hl
== DRAW_MOUSE_FACE
)
2940 x_set_mouse_face_gc (s
);
2941 s
->stippled_p
= s
->face
->stipple
!= 0;
2943 else if (s
->hl
== DRAW_IMAGE_RAISED
2944 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2946 s
->gc
= s
->face
->gc
;
2947 s
->stippled_p
= s
->face
->stipple
!= 0;
2951 s
->gc
= s
->face
->gc
;
2952 s
->stippled_p
= s
->face
->stipple
!= 0;
2955 /* GC must have been set. */
2956 xassert (s
->gc
!= 0);
2960 /* Set clipping for output of glyph string S. S may be part of a mode
2961 line or menu if we don't have X toolkit support. */
2964 x_set_glyph_string_clipping (s
)
2965 struct glyph_string
*s
;
2967 Rect rects
[MAX_CLIP_RECTS
];
2970 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2971 mac_set_clip_rectangles (s
->f
, s
->gc
, rects
, n
);
2976 Compute left and right overhang of glyph string S. If S is a glyph
2977 string for a composition, assume overhangs don't exist. */
2980 mac_compute_glyph_string_overhangs (s
)
2981 struct glyph_string
*s
;
2983 if (!(s
->cmp
== NULL
2984 && s
->first_glyph
->type
== CHAR_GLYPH
))
2989 || s
->font
->mac_style
2995 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2996 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2997 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
3002 MacFontStruct
*font
= s
->font
;
3005 mac_prepare_for_quickdraw (s
->f
);
3007 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
3009 TextFont (font
->mac_fontnum
);
3010 TextSize (font
->mac_fontsize
);
3011 TextFace (font
->mac_fontface
);
3013 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
3015 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
3016 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
3021 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3024 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
3025 struct glyph_string
*s
;
3028 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
3032 /* Draw the background of glyph_string S. If S->background_filled_p
3033 is non-zero don't draw it. FORCE_P non-zero means draw the
3034 background even if it wouldn't be drawn normally. This is used
3035 when a string preceding S draws into the background of S, or S
3036 contains the first component of a composition. */
3039 x_draw_glyph_string_background (s
, force_p
)
3040 struct glyph_string
*s
;
3043 /* Nothing to do if background has already been drawn or if it
3044 shouldn't be drawn in the first place. */
3045 if (!s
->background_filled_p
)
3047 int box_line_width
= max (s
->face
->box_line_width
, 0);
3049 #if 0 /* MAC_TODO: stipple */
3052 /* Fill background with a stipple pattern. */
3053 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3054 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
3055 s
->y
+ box_line_width
,
3056 s
->background_width
,
3057 s
->height
- 2 * box_line_width
);
3058 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3059 s
->background_filled_p
= 1;
3063 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
3064 || s
->font_not_found_p
3065 || s
->extends_to_end_of_line_p
3068 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
3069 s
->background_width
,
3070 s
->height
- 2 * box_line_width
);
3071 s
->background_filled_p
= 1;
3077 /* Draw the foreground of glyph string S. */
3080 x_draw_glyph_string_foreground (s
)
3081 struct glyph_string
*s
;
3085 /* If first glyph of S has a left box line, start drawing the text
3086 of S to the right of that box line. */
3087 if (s
->face
->box
!= FACE_NO_BOX
3088 && s
->first_glyph
->left_box_line_p
)
3089 x
= s
->x
+ eabs (s
->face
->box_line_width
);
3093 /* Draw characters of S as rectangles if S's font could not be
3095 if (s
->font_not_found_p
)
3097 for (i
= 0; i
< s
->nchars
; ++i
)
3099 struct glyph
*g
= s
->first_glyph
+ i
;
3100 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3101 g
->pixel_width
- 1, s
->height
- 1);
3102 x
+= g
->pixel_width
;
3107 char *char1b
= (char *) s
->char2b
;
3108 int boff
= s
->font_info
->baseline_offset
;
3110 if (s
->font_info
->vertical_centering
)
3111 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3113 /* If we can use 8-bit functions, condense S->char2b. */
3116 && GC_FONT (s
->gc
)->mac_style
== NULL
3119 for (i
= 0; i
< s
->nchars
; ++i
)
3120 char1b
[i
] = s
->char2b
[i
].byte2
;
3122 /* Draw text with XDrawString if background has already been
3123 filled. Otherwise, use XDrawImageString. (Note that
3124 XDrawImageString is usually faster than XDrawString.) Always
3125 use XDrawImageString when drawing the cursor so that there is
3126 no chance that characters under a box cursor are invisible. */
3128 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3129 bg_width
= 0; /* Corresponds to XDrawString. */
3131 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
3135 || GC_FONT (s
->gc
)->mac_style
3138 #if USE_CG_TEXT_DRAWING
3140 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3141 s
->char2b
, s
->nchars
, bg_width
,
3142 s
->face
->overstrike
))
3146 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3147 s
->char2b
, s
->nchars
, bg_width
,
3148 s
->face
->overstrike
);
3150 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3151 char1b
, s
->nchars
, bg_width
,
3152 s
->face
->overstrike
);
3156 /* Draw the foreground of composite glyph string S. */
3159 x_draw_composite_glyph_string_foreground (s
)
3160 struct glyph_string
*s
;
3164 /* If first glyph of S has a left box line, start drawing the text
3165 of S to the right of that box line. */
3166 if (s
->face
->box
!= FACE_NO_BOX
3167 && s
->first_glyph
->left_box_line_p
)
3168 x
= s
->x
+ eabs (s
->face
->box_line_width
);
3172 /* S is a glyph string for a composition. S->gidx is the index of
3173 the first character drawn for glyphs of this composition.
3174 S->gidx == 0 means we are drawing the very first character of
3175 this composition. */
3177 /* Draw a rectangle for the composition if the font for the very
3178 first character of the composition could not be loaded. */
3179 if (s
->font_not_found_p
)
3182 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3183 s
->width
- 1, s
->height
- 1);
3187 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3188 if (mac_per_char_metric (GC_FONT (s
->gc
), s
->char2b
+ i
, 0) == NULL
)
3189 /* This is a nonexistent or zero-width glyph such as a
3190 combining diacritic. Draw a rectangle. */
3191 mac_draw_rectangle (s
->f
, s
->gc
,
3192 x
+ s
->cmp
->offsets
[s
->gidx
* 2], s
->y
,
3193 FONT_WIDTH (GC_FONT (s
->gc
)) - 1, s
->height
- 1);
3195 mac_draw_image_string_16 (s
->f
, s
->gc
,
3196 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3197 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3198 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3203 #ifdef USE_X_TOOLKIT
3205 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3208 /* Return the frame on which widget WIDGET is used.. Abort if frame
3209 cannot be determined. */
3211 static struct frame
*
3212 x_frame_of_widget (widget
)
3215 struct x_display_info
*dpyinfo
;
3219 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3221 /* Find the top-level shell of the widget. Note that this function
3222 can be called when the widget is not yet realized, so XtWindow
3223 (widget) == 0. That's the reason we can't simply use
3224 x_any_window_to_frame. */
3225 while (!XtIsTopLevelShell (widget
))
3226 widget
= XtParent (widget
);
3228 /* Look for a frame with that top-level widget. Allocate the color
3229 on that frame to get the right gamma correction value. */
3230 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
3231 if (FRAMEP (XCAR (tail
))
3232 && (f
= XFRAME (XCAR (tail
)),
3233 (f
->output_data
.nothing
!= 1
3234 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3235 && f
->output_data
.x
->widget
== widget
)
3242 /* Allocate the color COLOR->pixel on the screen and display of
3243 widget WIDGET in colormap CMAP. If an exact match cannot be
3244 allocated, try the nearest color available. Value is non-zero
3245 if successful. This is called from lwlib. */
3248 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3253 struct frame
*f
= x_frame_of_widget (widget
);
3254 return x_alloc_nearest_color (f
, cmap
, color
);
3258 #endif /* USE_X_TOOLKIT */
3260 #if 0 /* MAC_TODO */
3262 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3263 CMAP. If an exact match can't be allocated, try the nearest color
3264 available. Value is non-zero if successful. Set *COLOR to the
3268 x_alloc_nearest_color (f
, cmap
, color
)
3273 Display
*display
= FRAME_X_DISPLAY (f
);
3274 Screen
*screen
= FRAME_X_SCREEN (f
);
3277 gamma_correct (f
, color
);
3278 rc
= XAllocColor (display
, cmap
, color
);
3281 /* If we got to this point, the colormap is full, so we're going
3282 to try to get the next closest color. The algorithm used is
3283 a least-squares matching, which is what X uses for closest
3284 color matching with StaticColor visuals. */
3286 unsigned long nearest_delta
= ~0;
3287 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3288 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3290 for (i
= 0; i
< ncells
; ++i
)
3292 XQueryColors (display
, cmap
, cells
, ncells
);
3294 for (nearest
= i
= 0; i
< ncells
; ++i
)
3296 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3297 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3298 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3299 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3301 if (delta
< nearest_delta
)
3304 nearest_delta
= delta
;
3308 color
->red
= cells
[nearest
].red
;
3309 color
->green
= cells
[nearest
].green
;
3310 color
->blue
= cells
[nearest
].blue
;
3311 rc
= XAllocColor (display
, cmap
, color
);
3314 #ifdef DEBUG_X_COLORS
3316 register_color (color
->pixel
);
3317 #endif /* DEBUG_X_COLORS */
3323 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3324 It's necessary to do this instead of just using PIXEL directly to
3325 get color reference counts right. */
3328 x_copy_color (f
, pixel
)
3330 unsigned long pixel
;
3334 color
.pixel
= pixel
;
3336 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3337 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3339 #ifdef DEBUG_X_COLORS
3340 register_color (pixel
);
3346 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3347 It's necessary to do this instead of just using PIXEL directly to
3348 get color reference counts right. */
3351 x_copy_dpy_color (dpy
, cmap
, pixel
)
3354 unsigned long pixel
;
3358 color
.pixel
= pixel
;
3360 XQueryColor (dpy
, cmap
, &color
);
3361 XAllocColor (dpy
, cmap
, &color
);
3363 #ifdef DEBUG_X_COLORS
3364 register_color (pixel
);
3369 #endif /* MAC_TODO */
3372 /* Brightness beyond which a color won't have its highlight brightness
3375 Nominally, highlight colors for `3d' faces are calculated by
3376 brightening an object's color by a constant scale factor, but this
3377 doesn't yield good results for dark colors, so for colors who's
3378 brightness is less than this value (on a scale of 0-255) have to
3379 use an additional additive factor.
3381 The value here is set so that the default menu-bar/mode-line color
3382 (grey75) will not have its highlights changed at all. */
3383 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3386 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3387 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3388 If this produces the same color as COLOR, try a color where all RGB
3389 values have DELTA added. Return the allocated color in *COLOR.
3390 DISPLAY is the X display, CMAP is the colormap to operate on.
3391 Value is non-zero if successful. */
3394 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3396 unsigned long *color
;
3403 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3406 /* Change RGB values by specified FACTOR. Avoid overflow! */
3407 xassert (factor
>= 0);
3408 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3409 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3410 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3412 /* Calculate brightness of COLOR. */
3413 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3414 + BLUE_FROM_ULONG (*color
)) / 6;
3416 /* We only boost colors that are darker than
3417 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3418 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3419 /* Make an additive adjustment to NEW, because it's dark enough so
3420 that scaling by FACTOR alone isn't enough. */
3422 /* How far below the limit this color is (0 - 1, 1 being darker). */
3423 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3424 /* The additive adjustment. */
3425 int min_delta
= delta
* dimness
* factor
/ 2;
3428 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3429 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3430 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3432 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3433 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3434 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3438 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3439 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3440 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3442 /* MAC_TODO: Map to palette and retry with delta if same? */
3443 /* MAC_TODO: Free colors (if using palette)? */
3454 /* Set up the foreground color for drawing relief lines of glyph
3455 string S. RELIEF is a pointer to a struct relief containing the GC
3456 with which lines will be drawn. Use a color that is FACTOR or
3457 DELTA lighter or darker than the relief's background which is found
3458 in S->f->output_data.x->relief_background. If such a color cannot
3459 be allocated, use DEFAULT_PIXEL, instead. */
3462 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3464 struct relief
*relief
;
3467 unsigned long default_pixel
;
3470 struct mac_output
*di
= f
->output_data
.mac
;
3471 unsigned long mask
= GCForeground
;
3472 unsigned long pixel
;
3473 unsigned long background
= di
->relief_background
;
3474 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3476 /* MAC_TODO: Free colors (if using palette)? */
3478 /* Allocate new color. */
3479 xgcv
.foreground
= default_pixel
;
3481 if (dpyinfo
->n_planes
!= 1
3482 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3484 relief
->allocated_p
= 1;
3485 xgcv
.foreground
= relief
->pixel
= pixel
;
3488 if (relief
->gc
== 0)
3490 #if 0 /* MAC_TODO: stipple */
3491 xgcv
.stipple
= dpyinfo
->gray
;
3494 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3497 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3501 /* Set up colors for the relief lines around glyph string S. */
3504 x_setup_relief_colors (s
)
3505 struct glyph_string
*s
;
3507 struct mac_output
*di
= s
->f
->output_data
.mac
;
3508 unsigned long color
;
3510 if (s
->face
->use_box_color_for_shadows_p
)
3511 color
= s
->face
->box_color
;
3512 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3514 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3515 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3520 /* Get the background color of the face. */
3521 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3522 color
= xgcv
.background
;
3525 if (di
->white_relief
.gc
== 0
3526 || color
!= di
->relief_background
)
3528 di
->relief_background
= color
;
3529 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3530 WHITE_PIX_DEFAULT (s
->f
));
3531 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3532 BLACK_PIX_DEFAULT (s
->f
));
3537 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3538 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3539 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3540 relief. LEFT_P non-zero means draw a relief on the left side of
3541 the rectangle. RIGHT_P non-zero means draw a relief on the right
3542 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3546 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3547 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3549 int left_x
, top_y
, right_x
, bottom_y
, width
;
3550 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3557 gc
= f
->output_data
.mac
->white_relief
.gc
;
3559 gc
= f
->output_data
.mac
->black_relief
.gc
;
3560 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3564 for (i
= 0; i
< width
; ++i
)
3565 mac_draw_line (f
, gc
,
3566 left_x
+ i
* left_p
, top_y
+ i
,
3567 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3571 for (i
= 0; i
< width
; ++i
)
3572 mac_draw_line (f
, gc
,
3573 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3575 mac_reset_clip_rectangles (f
, gc
);
3577 gc
= f
->output_data
.mac
->black_relief
.gc
;
3579 gc
= f
->output_data
.mac
->white_relief
.gc
;
3580 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3584 for (i
= 0; i
< width
; ++i
)
3585 mac_draw_line (f
, gc
,
3586 left_x
+ i
* left_p
, bottom_y
- i
,
3587 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3591 for (i
= 0; i
< width
; ++i
)
3592 mac_draw_line (f
, gc
,
3593 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3595 mac_reset_clip_rectangles (f
, gc
);
3599 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3600 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3601 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3602 left side of the rectangle. RIGHT_P non-zero means draw a line
3603 on the right side of the rectangle. CLIP_RECT is the clipping
3604 rectangle to use when drawing. */
3607 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3608 left_p
, right_p
, clip_rect
)
3609 struct glyph_string
*s
;
3610 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3615 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3616 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3617 mac_set_clip_rectangles (s
->f
, s
->gc
, clip_rect
, 1);
3620 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3621 right_x
- left_x
+ 1, width
);
3625 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3626 width
, bottom_y
- top_y
+ 1);
3629 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3630 right_x
- left_x
+ 1, width
);
3634 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3635 top_y
, width
, bottom_y
- top_y
+ 1);
3637 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3638 mac_reset_clip_rectangles (s
->f
, s
->gc
);
3642 /* Draw a box around glyph string S. */
3645 x_draw_glyph_string_box (s
)
3646 struct glyph_string
*s
;
3648 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3649 int left_p
, right_p
;
3650 struct glyph
*last_glyph
;
3653 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3654 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3655 : window_box_right (s
->w
, s
->area
));
3657 /* The glyph that may have a right box line. */
3658 last_glyph
= (s
->cmp
|| s
->img
3660 : s
->first_glyph
+ s
->nchars
- 1);
3662 width
= eabs (s
->face
->box_line_width
);
3663 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3665 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3667 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3669 bottom_y
= top_y
+ s
->height
- 1;
3671 left_p
= (s
->first_glyph
->left_box_line_p
3672 || (s
->hl
== DRAW_MOUSE_FACE
3674 || s
->prev
->hl
!= s
->hl
)));
3675 right_p
= (last_glyph
->right_box_line_p
3676 || (s
->hl
== DRAW_MOUSE_FACE
3678 || s
->next
->hl
!= s
->hl
)));
3680 get_glyph_string_clip_rect (s
, &clip_rect
);
3682 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3683 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3684 left_p
, right_p
, &clip_rect
);
3687 x_setup_relief_colors (s
);
3688 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3689 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3694 /* Draw foreground of image glyph string S. */
3697 x_draw_image_foreground (s
)
3698 struct glyph_string
*s
;
3701 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3703 /* If first glyph of S has a left box line, start drawing it to the
3704 right of that line. */
3705 if (s
->face
->box
!= FACE_NO_BOX
3706 && s
->first_glyph
->left_box_line_p
3708 x
+= eabs (s
->face
->box_line_width
);
3710 /* If there is a margin around the image, adjust x- and y-position
3712 if (s
->slice
.x
== 0)
3713 x
+= s
->img
->hmargin
;
3714 if (s
->slice
.y
== 0)
3715 y
+= s
->img
->vmargin
;
3719 x_set_glyph_string_clipping (s
);
3722 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3723 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3724 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3728 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3729 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3730 s
->slice
.width
, s
->slice
.height
, x
, y
);
3737 mac_copy_area (s
->img
->pixmap
,
3738 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3739 s
->slice
.width
, s
->slice
.height
, x
, y
);
3742 /* When the image has a mask, we can expect that at
3743 least part of a mouse highlight or a block cursor will
3744 be visible. If the image doesn't have a mask, make
3745 a block cursor visible by drawing a rectangle around
3746 the image. I believe it's looking better if we do
3747 nothing here for mouse-face. */
3748 if (s
->hl
== DRAW_CURSOR
)
3750 int r
= s
->img
->relief
;
3752 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3753 s
->slice
.width
+ r
*2 - 1,
3754 s
->slice
.height
+ r
*2 - 1);
3759 /* Draw a rectangle if image could not be loaded. */
3760 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3761 s
->slice
.width
- 1, s
->slice
.height
- 1);
3765 /* Draw a relief around the image glyph string S. */
3768 x_draw_image_relief (s
)
3769 struct glyph_string
*s
;
3771 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3774 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3776 /* If first glyph of S has a left box line, start drawing it to the
3777 right of that line. */
3778 if (s
->face
->box
!= FACE_NO_BOX
3779 && s
->first_glyph
->left_box_line_p
3781 x
+= eabs (s
->face
->box_line_width
);
3783 /* If there is a margin around the image, adjust x- and y-position
3785 if (s
->slice
.x
== 0)
3786 x
+= s
->img
->hmargin
;
3787 if (s
->slice
.y
== 0)
3788 y
+= s
->img
->vmargin
;
3790 if (s
->hl
== DRAW_IMAGE_SUNKEN
3791 || s
->hl
== DRAW_IMAGE_RAISED
)
3793 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3794 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3798 thick
= eabs (s
->img
->relief
);
3799 raised_p
= s
->img
->relief
> 0;
3804 x1
= x
+ s
->slice
.width
+ thick
- 1;
3805 y1
= y
+ s
->slice
.height
+ thick
- 1;
3807 x_setup_relief_colors (s
);
3808 get_glyph_string_clip_rect (s
, &r
);
3809 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3811 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3813 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3818 /* Draw part of the background of glyph string S. X, Y, W, and H
3819 give the rectangle to draw. */
3822 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3823 struct glyph_string
*s
;
3826 #if 0 /* MAC_TODO: stipple */
3829 /* Fill background with a stipple pattern. */
3830 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3831 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3832 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3835 #endif /* MAC_TODO */
3836 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3840 /* Draw image glyph string S.
3843 s->x +-------------------------
3846 | +-------------------------
3849 | | +-------------------
3855 x_draw_image_glyph_string (s
)
3856 struct glyph_string
*s
;
3859 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
3860 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3863 height
= s
->height
- 2 * box_line_vwidth
;
3866 /* Fill background with face under the image. Do it only if row is
3867 taller than image or if image has a clip mask to reduce
3869 s
->stippled_p
= s
->face
->stipple
!= 0;
3870 if (height
> s
->slice
.height
3874 || s
->img
->pixmap
== 0
3875 || s
->width
!= s
->background_width
)
3878 if (s
->first_glyph
->left_box_line_p
3880 x
+= box_line_hwidth
;
3883 if (s
->slice
.y
== 0)
3884 y
+= box_line_vwidth
;
3886 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3888 s
->background_filled_p
= 1;
3891 /* Draw the foreground. */
3892 x_draw_image_foreground (s
);
3894 /* If we must draw a relief around the image, do it. */
3896 || s
->hl
== DRAW_IMAGE_RAISED
3897 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3898 x_draw_image_relief (s
);
3902 /* Draw stretch glyph string S. */
3905 x_draw_stretch_glyph_string (s
)
3906 struct glyph_string
*s
;
3908 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3910 if (s
->hl
== DRAW_CURSOR
3911 && !x_stretch_cursor_p
)
3913 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3914 as wide as the stretch glyph. */
3915 int width
, background_width
= s
->background_width
;
3916 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3920 background_width
-= left_x
- x
;
3923 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3926 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3928 /* Clear rest using the GC of the original non-cursor face. */
3929 if (width
< background_width
)
3932 int w
= background_width
- width
, h
= s
->height
;
3937 if (s
->row
->mouse_face_p
3938 && cursor_in_mouse_face_p (s
->w
))
3940 x_set_mouse_face_gc (s
);
3946 get_glyph_string_clip_rect (s
, &r
);
3947 mac_set_clip_rectangles (s
->f
, gc
, &r
, 1);
3949 #if 0 /* MAC_TODO: stipple */
3950 if (s
->face
->stipple
)
3952 /* Fill background with a stipple pattern. */
3953 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3954 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3955 XSetFillStyle (s
->display
, gc
, FillSolid
);
3958 #endif /* MAC_TODO */
3959 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3962 else if (!s
->background_filled_p
)
3964 int background_width
= s
->background_width
;
3965 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3967 /* Don't draw into left margin, fringe or scrollbar area
3968 except for header line and mode line. */
3969 if (x
< left_x
&& !s
->row
->mode_line_p
)
3971 background_width
-= left_x
- x
;
3974 if (background_width
> 0)
3975 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3978 s
->background_filled_p
= 1;
3982 /* Draw glyph string S. */
3985 x_draw_glyph_string (s
)
3986 struct glyph_string
*s
;
3988 int relief_drawn_p
= 0;
3990 /* If S draws into the background of its successor that does not
3991 draw a cursor, draw the background of the successor first so that
3992 S can draw into it. This makes S->next use XDrawString instead
3993 of XDrawImageString. */
3994 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3995 && s
->next
->hl
!= DRAW_CURSOR
)
3997 xassert (s
->next
->img
== NULL
);
3998 x_set_glyph_string_gc (s
->next
);
3999 x_set_glyph_string_clipping (s
->next
);
4000 x_draw_glyph_string_background (s
->next
, 1);
4003 /* Set up S->gc, set clipping and draw S. */
4004 x_set_glyph_string_gc (s
);
4006 /* Draw relief (if any) in advance for char/composition so that the
4007 glyph string can be drawn over it. */
4008 if (!s
->for_overlaps
4009 && s
->face
->box
!= FACE_NO_BOX
4010 && (s
->first_glyph
->type
== CHAR_GLYPH
4011 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
4014 x_set_glyph_string_clipping (s
);
4015 x_draw_glyph_string_background (s
, 1);
4016 x_draw_glyph_string_box (s
);
4017 x_set_glyph_string_clipping (s
);
4021 x_set_glyph_string_clipping (s
);
4023 switch (s
->first_glyph
->type
)
4026 x_draw_image_glyph_string (s
);
4030 x_draw_stretch_glyph_string (s
);
4034 if (s
->for_overlaps
)
4035 s
->background_filled_p
= 1;
4037 x_draw_glyph_string_background (s
, 0);
4038 x_draw_glyph_string_foreground (s
);
4041 case COMPOSITE_GLYPH
:
4042 if (s
->for_overlaps
|| s
->gidx
> 0)
4043 s
->background_filled_p
= 1;
4045 x_draw_glyph_string_background (s
, 1);
4046 x_draw_composite_glyph_string_foreground (s
);
4053 if (!s
->for_overlaps
)
4055 /* Draw underline. */
4056 if (s
->face
->underline_p
)
4058 unsigned long tem
, h
;
4062 /* Get the underline thickness. Default is 1 pixel. */
4063 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
4067 y
= s
->y
+ s
->height
- h
;
4068 if (!x_underline_at_descent_line
)
4070 /* Get the underline position. This is the recommended
4071 vertical offset in pixels from the baseline to the top of
4072 the underline. This is a signed value according to the
4073 specs, and its default is
4075 ROUND ((maximum descent) / 2), with
4076 ROUND(x) = floor (x + 0.5) */
4079 if (x_use_underline_position_properties
4080 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
4081 y
= s
->ybase
+ (long) tem
;
4085 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
4088 if (s
->face
->underline_defaulted_p
)
4089 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
4090 s
->background_width
, h
);
4094 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4095 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4096 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
4097 s
->background_width
, h
);
4098 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4102 /* Draw overline. */
4103 if (s
->face
->overline_p
)
4105 unsigned long dy
= 0, h
= 1;
4107 if (s
->face
->overline_color_defaulted_p
)
4108 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4109 s
->background_width
, h
);
4113 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4114 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4115 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4116 s
->background_width
, h
);
4117 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4121 /* Draw strike-through. */
4122 if (s
->face
->strike_through_p
)
4124 unsigned long h
= 1;
4125 unsigned long dy
= (s
->height
- h
) / 2;
4127 if (s
->face
->strike_through_color_defaulted_p
)
4128 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4133 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4134 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4135 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4137 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4141 /* Draw relief if not yet drawn. */
4142 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4143 x_draw_glyph_string_box (s
);
4146 /* Reset clipping. */
4147 mac_reset_clip_rectangles (s
->f
, s
->gc
);
4150 /* Shift display to make room for inserted glyphs. */
4153 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4155 int x
, y
, width
, height
, shift_by
;
4157 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4158 x
, y
, width
, height
,
4162 /* Delete N glyphs at the nominal cursor position. Not implemented
4173 /* Clear entire frame. If updating_frame is non-null, clear that
4174 frame. Otherwise clear the selected frame. */
4177 x_clear_frame (struct frame
*f
)
4179 /* Clearing the frame will erase any cursor, so mark them all as no
4181 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4182 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4183 output_cursor
.x
= -1;
4185 /* We don't set the output cursor here because there will always
4186 follow an explicit cursor_to. */
4188 mac_clear_window (f
);
4190 /* We have to clear the scroll bars, too. If we have changed
4191 colors or something like that, then they should be notified. */
4192 x_scroll_bar_clear (f
);
4194 XFlush (FRAME_MAC_DISPLAY (f
));
4200 /* Invert the middle quarter of the frame for .15 sec. */
4202 /* We use the select system call to do the waiting, so we have to make
4203 sure it's available. If it isn't, we just won't do visual bells. */
4205 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4208 /* Subtract the `struct timeval' values X and Y, storing the result in
4209 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4212 timeval_subtract (result
, x
, y
)
4213 struct timeval
*result
, x
, y
;
4215 /* Perform the carry for the later subtraction by updating y. This
4216 is safer because on some systems the tv_sec member is unsigned. */
4217 if (x
.tv_usec
< y
.tv_usec
)
4219 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4220 y
.tv_usec
-= 1000000 * nsec
;
4224 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4226 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4227 y
.tv_usec
+= 1000000 * nsec
;
4231 /* Compute the time remaining to wait. tv_usec is certainly
4233 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4234 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4236 /* Return indication of whether the result should be considered
4238 return x
.tv_sec
< y
.tv_sec
;
4245 /* Get the height not including a menu bar widget. */
4246 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4247 /* Height of each line to flash. */
4248 int flash_height
= FRAME_LINE_HEIGHT (f
);
4249 /* These will be the left and right margins of the rectangles. */
4250 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4251 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4255 /* Don't flash the area between a scroll bar and the frame
4256 edge it is next to. */
4257 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4259 case vertical_scroll_bar_left
:
4260 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4263 case vertical_scroll_bar_right
:
4264 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4271 width
= flash_right
- flash_left
;
4275 /* If window is tall, flash top and bottom line. */
4276 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4278 mac_invert_rectangle (f
, flash_left
,
4279 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4280 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4281 width
, flash_height
);
4282 mac_invert_rectangle (f
, flash_left
,
4283 (height
- flash_height
4284 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4285 width
, flash_height
);
4288 /* If it is short, flash it all. */
4289 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4290 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4295 struct timeval wakeup
;
4297 EMACS_GET_TIME (wakeup
);
4299 /* Compute time to wait until, propagating carry from usecs. */
4300 wakeup
.tv_usec
+= 150000;
4301 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4302 wakeup
.tv_usec
%= 1000000;
4304 /* Keep waiting until past the time wakeup or any input gets
4306 while (! detect_input_pending ())
4308 struct timeval current
;
4309 struct timeval timeout
;
4311 EMACS_GET_TIME (current
);
4313 /* Break if result would be negative. */
4314 if (timeval_subtract (¤t
, wakeup
, current
))
4317 /* How long `select' should wait. */
4319 timeout
.tv_usec
= 10000;
4321 /* Try to wait that long--but we might wake up sooner. */
4322 select (0, NULL
, NULL
, NULL
, &timeout
);
4326 /* If window is tall, flash top and bottom line. */
4327 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4329 mac_invert_rectangle (f
, flash_left
,
4330 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4331 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4332 width
, flash_height
);
4333 mac_invert_rectangle (f
, flash_left
,
4334 (height
- flash_height
4335 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4336 width
, flash_height
);
4339 /* If it is short, flash it all. */
4340 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4341 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4348 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4351 /* Make audible bell. */
4356 struct frame
*f
= SELECTED_FRAME ();
4358 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4366 XFlush (FRAME_MAC_DISPLAY (f
));
4372 /* Specify how many text lines, from the top of the window,
4373 should be affected by insert-lines and delete-lines operations.
4374 This, and those operations, are used only within an update
4375 that is bounded by calls to x_update_begin and x_update_end. */
4378 XTset_terminal_window (n
)
4381 /* This function intentionally left blank. */
4386 /***********************************************************************
4388 ***********************************************************************/
4390 /* Perform an insert-lines or delete-lines operation, inserting N
4391 lines or deleting -N lines at vertical position VPOS. */
4394 x_ins_del_lines (vpos
, n
)
4401 /* Scroll part of the display as described by RUN. */
4404 x_scroll_run (w
, run
)
4408 struct frame
*f
= XFRAME (w
->frame
);
4409 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4411 /* Get frame-relative bounding box of the text display area of W,
4412 without mode lines. Include in this box the left and right
4414 window_box (w
, -1, &x
, &y
, &width
, &height
);
4416 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4417 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4418 bottom_y
= y
+ height
;
4422 /* Scrolling up. Make sure we don't copy part of the mode
4423 line at the bottom. */
4424 if (from_y
+ run
->height
> bottom_y
)
4425 height
= bottom_y
- from_y
;
4427 height
= run
->height
;
4431 /* Scolling down. Make sure we don't copy over the mode line.
4433 if (to_y
+ run
->height
> bottom_y
)
4434 height
= bottom_y
- to_y
;
4436 height
= run
->height
;
4441 /* Cursor off. Will be switched on again in x_update_window_end. */
4445 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4455 /***********************************************************************
4457 ***********************************************************************/
4464 x_update_cursor (f
, 1);
4468 frame_unhighlight (f
)
4471 x_update_cursor (f
, 1);
4474 /* The focus has changed. Update the frames as necessary to reflect
4475 the new situation. Note that we can't change the selected frame
4476 here, because the Lisp code we are interrupting might become confused.
4477 Each event gets marked with the frame in which it occurred, so the
4478 Lisp code can tell when the switch took place by examining the events. */
4481 x_new_focus_frame (dpyinfo
, frame
)
4482 struct x_display_info
*dpyinfo
;
4483 struct frame
*frame
;
4485 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4487 if (frame
!= dpyinfo
->x_focus_frame
)
4489 /* Set this before calling other routines, so that they see
4490 the correct value of x_focus_frame. */
4491 dpyinfo
->x_focus_frame
= frame
;
4493 if (old_focus
&& old_focus
->auto_lower
)
4494 x_lower_frame (old_focus
);
4497 selected_frame
= frame
;
4498 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4500 Fselect_window (selected_frame
->selected_window
, Qnil
);
4501 choose_minibuf_frame ();
4504 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4505 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4507 pending_autoraise_frame
= 0;
4509 #if USE_MAC_FONT_PANEL
4511 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4515 x_frame_rehighlight (dpyinfo
);
4518 /* Handle FocusIn and FocusOut state changes for FRAME.
4519 If FRAME has focus and there exists more than one frame, puts
4520 a FOCUS_IN_EVENT into *BUFP. */
4523 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4525 struct mac_display_info
*dpyinfo
;
4526 struct frame
*frame
;
4527 struct input_event
*bufp
;
4529 if (type
== activeFlag
)
4531 if (dpyinfo
->x_focus_event_frame
!= frame
)
4533 x_new_focus_frame (dpyinfo
, frame
);
4534 dpyinfo
->x_focus_event_frame
= frame
;
4536 /* Don't stop displaying the initial startup message
4537 for a switch-frame event we don't need. */
4538 if (NILP (Vterminal_frame
)
4539 && CONSP (Vframe_list
)
4540 && !NILP (XCDR (Vframe_list
)))
4542 bufp
->kind
= FOCUS_IN_EVENT
;
4543 XSETFRAME (bufp
->frame_or_window
, frame
);
4549 if (dpyinfo
->x_focus_event_frame
== frame
)
4551 dpyinfo
->x_focus_event_frame
= 0;
4552 x_new_focus_frame (dpyinfo
, 0);
4557 /* The focus may have changed. Figure out if it is a real focus change,
4558 by checking both FocusIn/Out and Enter/LeaveNotify events.
4560 Returns FOCUS_IN_EVENT event in *BUFP. */
4563 x_detect_focus_change (dpyinfo
, event
, bufp
)
4564 struct mac_display_info
*dpyinfo
;
4565 const EventRecord
*event
;
4566 struct input_event
*bufp
;
4568 struct frame
*frame
;
4570 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4574 /* On Mac, this is only called from focus events, so no switch needed. */
4575 mac_focus_changed ((event
->modifiers
& activeFlag
),
4576 dpyinfo
, frame
, bufp
);
4580 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4583 x_mouse_leave (dpyinfo
)
4584 struct x_display_info
*dpyinfo
;
4586 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4589 /* The focus has changed, or we have redirected a frame's focus to
4590 another frame (this happens when a frame uses a surrogate
4591 mini-buffer frame). Shift the highlight as appropriate.
4593 The FRAME argument doesn't necessarily have anything to do with which
4594 frame is being highlighted or un-highlighted; we only use it to find
4595 the appropriate X display info. */
4598 XTframe_rehighlight (frame
)
4599 struct frame
*frame
;
4601 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4605 x_frame_rehighlight (dpyinfo
)
4606 struct x_display_info
*dpyinfo
;
4608 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4610 if (dpyinfo
->x_focus_frame
)
4612 dpyinfo
->x_highlight_frame
4613 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4614 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4615 : dpyinfo
->x_focus_frame
);
4616 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4618 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4619 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4623 dpyinfo
->x_highlight_frame
= 0;
4625 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4628 frame_unhighlight (old_highlight
);
4629 if (dpyinfo
->x_highlight_frame
)
4630 frame_highlight (dpyinfo
->x_highlight_frame
);
4636 /* Convert a keysym to its name. */
4639 x_get_keysym_name (keysym
)
4646 value
= XKeysymToString (keysym
);
4657 /* Function to report a mouse movement to the mainstream Emacs code.
4658 The input handler calls this.
4660 We have received a mouse movement event, which is given in *event.
4661 If the mouse is over a different glyph than it was last time, tell
4662 the mainstream emacs code by setting mouse_moved. If not, ask for
4663 another motion event, so we can check again the next time it moves. */
4665 static Point last_mouse_motion_position
;
4666 static Lisp_Object last_mouse_motion_frame
;
4669 note_mouse_movement (frame
, pos
)
4673 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4674 #if TARGET_API_MAC_CARBON
4678 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4679 last_mouse_motion_position
= *pos
;
4680 XSETFRAME (last_mouse_motion_frame
, frame
);
4682 if (frame
== dpyinfo
->mouse_face_mouse_frame
4683 #if TARGET_API_MAC_CARBON
4684 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4686 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4690 /* This case corresponds to LeaveNotify in X11. If we move
4691 outside the frame, then we're certainly no longer on any text
4693 clear_mouse_face (dpyinfo
);
4694 dpyinfo
->mouse_face_mouse_frame
= 0;
4695 if (!dpyinfo
->grabbed
)
4696 FRAME_RIF (frame
)->define_frame_cursor (frame
,
4697 frame
->output_data
.mac
->nontext_cursor
);
4700 /* Has the mouse moved off the glyph it was on at the last sighting? */
4701 if (frame
!= last_mouse_glyph_frame
4702 || !PtInRect (*pos
, &last_mouse_glyph
))
4704 frame
->mouse_moved
= 1;
4705 last_mouse_scroll_bar
= Qnil
;
4706 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4707 /* Remember which glyph we're now on. */
4708 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4709 last_mouse_glyph_frame
= frame
;
4717 /************************************************************************
4719 ************************************************************************/
4721 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4724 redo_mouse_highlight ()
4726 if (!NILP (last_mouse_motion_frame
)
4727 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4728 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4729 last_mouse_motion_position
.h
,
4730 last_mouse_motion_position
.v
);
4734 static struct frame
*
4735 mac_focus_frame (dpyinfo
)
4736 struct mac_display_info
*dpyinfo
;
4738 if (dpyinfo
->x_focus_frame
)
4739 return dpyinfo
->x_focus_frame
;
4741 /* Mac version may get events, such as a menu bar click, even when
4742 all the frames are invisible. In this case, we regard the
4743 event came to the selected frame. */
4744 return SELECTED_FRAME ();
4748 /* Return the current position of the mouse.
4749 *FP should be a frame which indicates which display to ask about.
4751 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4752 and *PART to the frame, window, and scroll bar part that the mouse
4753 is over. Set *X and *Y to the portion and whole of the mouse's
4754 position on the scroll bar.
4756 If the mouse movement started elsewhere, set *FP to the frame the
4757 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4760 Set *TIME to the server time-stamp for the time at which the mouse
4761 was at this position.
4763 Don't store anything if we don't have a valid set of values to report.
4765 This clears the mouse_moved flag, so we can wait for the next mouse
4769 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4772 Lisp_Object
*bar_window
;
4773 enum scroll_bar_part
*part
;
4775 unsigned long *time
;
4781 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4782 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4785 Lisp_Object frame
, tail
;
4787 /* Clear the mouse-moved flag for every frame on this display. */
4788 FOR_EACH_FRAME (tail
, frame
)
4789 XFRAME (frame
)->mouse_moved
= 0;
4791 last_mouse_scroll_bar
= Qnil
;
4793 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4794 && FRAME_LIVE_P (last_mouse_frame
))
4795 f1
= last_mouse_frame
;
4797 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4801 /* Ok, we found a frame. Store all the values.
4802 last_mouse_glyph is a rectangle used to reduce the
4803 generation of mouse events. To not miss any motion
4804 events, we must divide the frame into rectangles of the
4805 size of the smallest character that could be displayed
4806 on it, i.e. into the same rectangles that matrices on
4807 the frame are divided into. */
4810 #if TARGET_API_MAC_CARBON
4811 GetGlobalMouse (&mouse_pos
);
4812 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4813 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4815 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4816 GetMouse (&mouse_pos
);
4818 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4820 last_mouse_glyph_frame
= f1
;
4825 XSETINT (*x
, mouse_pos
.h
);
4826 XSETINT (*y
, mouse_pos
.v
);
4827 *time
= last_mouse_movement_time
;
4835 /************************************************************************
4837 ************************************************************************/
4839 #ifdef USE_TOOLKIT_SCROLL_BARS
4841 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4842 static OSStatus install_scroll_bar_timer
P_ ((void));
4843 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4844 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4845 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4846 struct input_event
*));
4847 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4849 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4850 ControlPartCode
, Point
,
4851 struct input_event
*));
4852 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4853 struct input_event
*));
4854 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4855 Point
, struct input_event
*));
4856 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4859 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4861 static int last_scroll_bar_part
;
4863 static EventLoopTimerRef scroll_bar_timer
;
4865 static int scroll_bar_timer_event_posted_p
;
4867 #define SCROLL_BAR_FIRST_DELAY 0.5
4868 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4871 scroll_bar_timer_callback (timer
, data
)
4872 EventLoopTimerRef timer
;
4877 err
= mac_post_mouse_moved_event ();
4879 scroll_bar_timer_event_posted_p
= 1;
4883 install_scroll_bar_timer ()
4885 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4887 if (scroll_bar_timer_callbackUPP
== NULL
)
4888 scroll_bar_timer_callbackUPP
=
4889 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4891 if (scroll_bar_timer
== NULL
)
4892 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4893 kEventDurationForever as delays. */
4895 InstallEventLoopTimer (GetCurrentEventLoop (),
4896 kEventDurationForever
, kEventDurationForever
,
4897 scroll_bar_timer_callbackUPP
, NULL
,
4902 set_scroll_bar_timer (delay
)
4903 EventTimerInterval delay
;
4905 if (scroll_bar_timer
== NULL
)
4906 install_scroll_bar_timer ();
4908 scroll_bar_timer_event_posted_p
= 0;
4910 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4914 control_part_code_to_scroll_bar_part (part_code
)
4915 ControlPartCode part_code
;
4919 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4920 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4921 case kControlPageUpPart
: return scroll_bar_above_handle
;
4922 case kControlPageDownPart
: return scroll_bar_below_handle
;
4923 case kControlIndicatorPart
: return scroll_bar_handle
;
4930 construct_scroll_bar_click (bar
, part
, bufp
)
4931 struct scroll_bar
*bar
;
4933 struct input_event
*bufp
;
4935 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4936 bufp
->frame_or_window
= bar
->window
;
4940 XSETINT (bufp
->x
, 0);
4941 XSETINT (bufp
->y
, 0);
4942 bufp
->modifiers
= 0;
4946 get_control_part_bounds (ch
, part_code
, rect
)
4948 ControlPartCode part_code
;
4951 RgnHandle region
= NewRgn ();
4954 err
= GetControlRegion (ch
, part_code
, region
);
4956 GetRegionBounds (region
, rect
);
4957 DisposeRgn (region
);
4963 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4964 struct scroll_bar
*bar
;
4965 ControlPartCode part_code
;
4967 struct input_event
*bufp
;
4969 int part
= control_part_code_to_scroll_bar_part (part_code
);
4974 if (part
!= scroll_bar_handle
)
4976 construct_scroll_bar_click (bar
, part
, bufp
);
4977 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4978 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4979 bar
->dragging
= Qnil
;
4985 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4986 kControlIndicatorPart
, &r
);
4987 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4990 last_scroll_bar_part
= part
;
4991 tracked_scroll_bar
= bar
;
4995 x_scroll_bar_handle_release (bar
, bufp
)
4996 struct scroll_bar
*bar
;
4997 struct input_event
*bufp
;
4999 if (last_scroll_bar_part
!= scroll_bar_handle
5000 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
5001 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
5003 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
5004 set_scroll_bar_timer (kEventDurationForever
);
5006 last_scroll_bar_part
= -1;
5007 bar
->dragging
= Qnil
;
5008 tracked_scroll_bar
= NULL
;
5012 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
5014 struct scroll_bar
*bar
;
5016 struct input_event
*bufp
;
5018 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5020 if (last_scroll_bar_part
== scroll_bar_handle
)
5025 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
5026 kControlIndicatorPart
, &r
);
5028 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
5029 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
5031 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
5032 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
5036 if (top
> top_range
)
5039 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
5040 XSETINT (bufp
->x
, top
);
5041 XSETINT (bufp
->y
, top_range
);
5045 ControlPartCode part_code
;
5046 int unhilite_p
= 0, part
;
5048 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
5052 part
= control_part_code_to_scroll_bar_part (part_code
);
5054 switch (last_scroll_bar_part
)
5056 case scroll_bar_above_handle
:
5057 case scroll_bar_below_handle
:
5058 if (part
!= scroll_bar_above_handle
5059 && part
!= scroll_bar_below_handle
)
5063 case scroll_bar_up_arrow
:
5064 case scroll_bar_down_arrow
:
5065 if (part
!= scroll_bar_up_arrow
5066 && part
!= scroll_bar_down_arrow
)
5073 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
5074 else if (part
!= last_scroll_bar_part
5075 || scroll_bar_timer_event_posted_p
)
5077 construct_scroll_bar_click (bar
, part
, bufp
);
5078 last_scroll_bar_part
= part
;
5079 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
5080 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
5085 /* Set the thumb size and position of scroll bar BAR. We are currently
5086 displaying PORTION out of a whole WHOLE, and our position POSITION. */
5089 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
5090 struct scroll_bar
*bar
;
5091 int portion
, position
, whole
;
5093 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5094 int value
, viewsize
, maximum
;
5096 if (XINT (bar
->track_height
) == 0)
5099 if (whole
<= portion
)
5100 value
= 0, viewsize
= 1, maximum
= 0;
5105 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
5106 scale
= (float) maximum
/ (whole
- portion
);
5107 value
= position
* scale
+ 0.5f
;
5108 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
5113 if (GetControlViewSize (ch
) != viewsize
5114 || GetControl32BitValue (ch
) != value
5115 || GetControl32BitMaximum (ch
) != maximum
)
5117 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5118 SetControlVisibility (ch
, false, false);
5120 SetControl32BitMaximum (ch
, maximum
);
5121 SetControl32BitValue (ch
, value
);
5122 SetControlViewSize (ch
, viewsize
);
5124 SetControlVisibility (ch
, true, true);
5130 #endif /* USE_TOOLKIT_SCROLL_BARS */
5134 /************************************************************************
5135 Scroll bars, general
5136 ************************************************************************/
5138 /* Create a scroll bar and return the scroll bar vector for it. W is
5139 the Emacs window on which to create the scroll bar. TOP, LEFT,
5140 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5143 static struct scroll_bar
*
5144 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5146 int top
, left
, width
, height
, disp_top
, disp_height
;
5148 struct frame
*f
= XFRAME (w
->frame
);
5149 struct scroll_bar
*bar
5150 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5158 r
.right
= left
+ width
;
5159 r
.bottom
= disp_top
+ disp_height
;
5162 mac_prepare_for_quickdraw (f
);
5164 #if TARGET_API_MAC_CARBON
5165 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5166 #ifdef USE_TOOLKIT_SCROLL_BARS
5169 width
< disp_height
,
5171 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5173 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5174 0, 0, 0, scrollBarProc
, (long) bar
);
5176 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5178 XSETWINDOW (bar
->window
, w
);
5179 XSETINT (bar
->top
, top
);
5180 XSETINT (bar
->left
, left
);
5181 XSETINT (bar
->width
, width
);
5182 XSETINT (bar
->height
, height
);
5183 XSETINT (bar
->start
, 0);
5184 XSETINT (bar
->end
, 0);
5185 bar
->dragging
= Qnil
;
5187 bar
->fringe_extended_p
= Qnil
;
5189 bar
->redraw_needed_p
= Qnil
;
5190 #ifdef USE_TOOLKIT_SCROLL_BARS
5191 bar
->track_top
= Qnil
;
5192 bar
->track_height
= Qnil
;
5193 bar
->min_handle
= Qnil
;
5196 /* Add bar to its frame's list of scroll bars. */
5197 bar
->next
= FRAME_SCROLL_BARS (f
);
5199 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5200 if (!NILP (bar
->next
))
5201 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5208 /* Draw BAR's handle in the proper position.
5210 If the handle is already drawn from START to END, don't bother
5211 redrawing it, unless REBUILD is non-zero; in that case, always
5212 redraw it. (REBUILD is handy for drawing the handle after expose
5215 Normally, we want to constrain the start and end of the handle to
5216 fit inside its rectangle, but if the user is dragging the scroll
5217 bar handle, we want to let them drag it down all the way, so that
5218 the bar's top is as far down as it goes; otherwise, there's no way
5219 to move to the very end of the buffer. */
5221 #ifndef USE_TOOLKIT_SCROLL_BARS
5224 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5225 struct scroll_bar
*bar
;
5229 int dragging
= ! NILP (bar
->dragging
);
5230 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5231 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5232 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5233 int length
= end
- start
;
5235 /* If the display is already accurate, do nothing. */
5237 && start
== XINT (bar
->start
)
5238 && end
== XINT (bar
->end
))
5243 /* Make sure the values are reasonable, and try to preserve the
5244 distance between start and end. */
5247 else if (start
> top_range
)
5249 end
= start
+ length
;
5253 else if (end
> top_range
&& ! dragging
)
5256 /* Store the adjusted setting in the scroll bar. */
5257 XSETINT (bar
->start
, start
);
5258 XSETINT (bar
->end
, end
);
5260 /* Clip the end position, just for display. */
5261 if (end
> top_range
)
5264 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5265 top positions, to make sure the handle is always at least that
5266 many pixels tall. */
5267 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5269 SetControlMinimum (ch
, 0);
5270 /* Don't inadvertently activate deactivated scroll bars */
5271 if (GetControlMaximum (ch
) != -1)
5272 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5274 SetControlValue (ch
, start
);
5275 #if TARGET_API_MAC_CARBON
5276 SetControlViewSize (ch
, end
- start
);
5282 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5284 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5288 x_scroll_bar_remove (bar
)
5289 struct scroll_bar
*bar
;
5291 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5296 mac_prepare_for_quickdraw (f
);
5298 /* Destroy the Mac scroll bar control */
5299 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5301 /* Disassociate this scroll bar from its window. */
5302 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5308 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5309 that we are displaying PORTION characters out of a total of WHOLE
5310 characters, starting at POSITION. If WINDOW has no scroll bar,
5314 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5316 int portion
, whole
, position
;
5318 struct frame
*f
= XFRAME (w
->frame
);
5319 struct scroll_bar
*bar
;
5320 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5321 int window_y
, window_height
;
5323 int fringe_extended_p
;
5326 /* Get window dimensions. */
5327 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5329 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5330 height
= window_height
;
5332 /* Compute the left edge of the scroll bar area. */
5333 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5335 /* Compute the width of the scroll bar which might be less than
5336 the width of the area reserved for the scroll bar. */
5337 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5338 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5342 /* Compute the left edge of the scroll bar. */
5343 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5344 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5346 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5348 /* Adjustments according to Inside Macintosh to make it look nice */
5350 disp_height
= height
;
5357 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5363 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5368 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5369 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5370 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5371 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5372 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5374 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5375 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5376 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5377 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5380 /* Does the scroll bar exist yet? */
5381 if (NILP (w
->vertical_scroll_bar
))
5385 if (fringe_extended_p
)
5386 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5389 mac_clear_area (f
, left
, top
, width
, height
);
5391 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5393 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5397 /* It may just need to be moved and resized. */
5400 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5401 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5405 /* If already correctly positioned, do nothing. */
5406 if (XINT (bar
->left
) == sb_left
5407 && XINT (bar
->top
) == top
5408 && XINT (bar
->width
) == sb_width
5409 && XINT (bar
->height
) == height
5411 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5415 if (!NILP (bar
->redraw_needed_p
))
5418 mac_prepare_for_quickdraw (f
);
5420 Draw1Control (SCROLL_BAR_CONTROL_REF (bar
));
5425 /* Since toolkit scroll bars are smaller than the space reserved
5426 for them on the frame, we have to clear "under" them. */
5428 if (fringe_extended_p
)
5429 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5432 mac_clear_area (f
, left
, top
, width
, height
);
5435 mac_prepare_for_quickdraw (f
);
5438 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5439 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5441 #ifndef USE_TOOLKIT_SCROLL_BARS
5442 if (sb_width
< disp_height
)
5446 /* Remember new settings. */
5447 XSETINT (bar
->left
, sb_left
);
5448 XSETINT (bar
->top
, top
);
5449 XSETINT (bar
->width
, sb_width
);
5450 XSETINT (bar
->height
, height
);
5451 #ifdef USE_TOOLKIT_SCROLL_BARS
5452 bar
->track_top
= Qnil
;
5453 bar
->track_height
= Qnil
;
5454 bar
->min_handle
= Qnil
;
5462 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5465 bar
->redraw_needed_p
= Qnil
;
5467 #ifdef USE_TOOLKIT_SCROLL_BARS
5468 if (NILP (bar
->track_top
))
5470 if (sb_width
>= disp_height
5472 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5476 XSETINT (bar
->track_top
, 0);
5477 XSETINT (bar
->track_height
, 0);
5478 XSETINT (bar
->min_handle
, 0);
5482 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5487 SetControl32BitMinimum (ch
, 0);
5488 SetControl32BitMaximum (ch
, 1 << 30);
5489 SetControlViewSize (ch
, 1);
5491 /* Move the scroll bar thumb to the top. */
5492 SetControl32BitValue (ch
, 0);
5493 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5495 /* Move the scroll bar thumb to the bottom. */
5496 SetControl32BitValue (ch
, 1 << 30);
5497 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5499 UnionRect (&r0
, &r1
, &r0
);
5500 XSETINT (bar
->track_top
, r0
.top
);
5501 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5502 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5504 /* Don't show the scroll bar if its height is not enough to
5505 display the scroll bar thumb. */
5506 if (r0
.bottom
- r0
.top
> 0)
5513 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5514 #else /* not USE_TOOLKIT_SCROLL_BARS */
5515 /* Set the scroll bar's current state, unless we're currently being
5517 if (NILP (bar
->dragging
))
5519 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5522 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5525 int start
= ((double) position
* top_range
) / whole
;
5526 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5527 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5530 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5534 /* The following three hooks are used when we're doing a thorough
5535 redisplay of the frame. We don't explicitly know which scroll bars
5536 are going to be deleted, because keeping track of when windows go
5537 away is a real pain - "Can you say set-window-configuration, boys
5538 and girls?" Instead, we just assert at the beginning of redisplay
5539 that *all* scroll bars are to be removed, and then save a scroll bar
5540 from the fiery pit when we actually redisplay its window. */
5542 /* Arrange for all scroll bars on FRAME to be removed at the next call
5543 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5544 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5547 XTcondemn_scroll_bars (frame
)
5550 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5551 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5554 bar
= FRAME_SCROLL_BARS (frame
);
5555 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5556 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5557 XSCROLL_BAR (bar
)->prev
= Qnil
;
5558 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5559 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5560 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5565 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5566 Note that WINDOW isn't necessarily condemned at all. */
5569 XTredeem_scroll_bar (window
)
5570 struct window
*window
;
5572 struct scroll_bar
*bar
;
5575 /* We can't redeem this window's scroll bar if it doesn't have one. */
5576 if (NILP (window
->vertical_scroll_bar
))
5579 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5581 /* Unlink it from the condemned list. */
5582 f
= XFRAME (WINDOW_FRAME (window
));
5583 if (NILP (bar
->prev
))
5585 /* If the prev pointer is nil, it must be the first in one of
5587 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5588 /* It's not condemned. Everything's fine. */
5590 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5591 window
->vertical_scroll_bar
))
5592 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5594 /* If its prev pointer is nil, it must be at the front of
5595 one or the other! */
5599 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5601 if (! NILP (bar
->next
))
5602 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5604 bar
->next
= FRAME_SCROLL_BARS (f
);
5606 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5607 if (! NILP (bar
->next
))
5608 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5611 /* Remove all scroll bars on FRAME that haven't been saved since the
5612 last call to `*condemn_scroll_bars_hook'. */
5615 XTjudge_scroll_bars (f
)
5618 Lisp_Object bar
, next
;
5620 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5622 /* Clear out the condemned list now so we won't try to process any
5623 more events on the hapless scroll bars. */
5624 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5626 for (; ! NILP (bar
); bar
= next
)
5628 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5630 x_scroll_bar_remove (b
);
5633 b
->next
= b
->prev
= Qnil
;
5636 /* Now there should be no references to the condemned scroll bars,
5637 and they should get garbage-collected. */
5641 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5642 is set to something other than NO_EVENT, it is enqueued.
5644 This may be called from a signal handler, so we have to ignore GC
5648 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5649 struct scroll_bar
*bar
;
5650 ControlPartCode part_code
;
5651 const EventRecord
*er
;
5652 struct input_event
*bufp
;
5654 int win_y
, top_range
;
5656 if (! WINDOWP (bar
->window
))
5659 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5660 bufp
->frame_or_window
= bar
->window
;
5663 bar
->dragging
= Qnil
;
5667 case kControlUpButtonPart
:
5668 bufp
->part
= scroll_bar_up_arrow
;
5670 case kControlDownButtonPart
:
5671 bufp
->part
= scroll_bar_down_arrow
;
5673 case kControlPageUpPart
:
5674 bufp
->part
= scroll_bar_above_handle
;
5676 case kControlPageDownPart
:
5677 bufp
->part
= scroll_bar_below_handle
;
5679 #if TARGET_API_MAC_CARBON
5682 case kControlIndicatorPart
:
5684 if (er
->what
== mouseDown
)
5685 bar
->dragging
= make_number (0);
5686 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5687 bufp
->part
= scroll_bar_handle
;
5691 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5692 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5694 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5698 if (! NILP (bar
->dragging
))
5699 win_y
-= XINT (bar
->dragging
);
5703 if (win_y
> top_range
)
5706 XSETINT (bufp
->x
, win_y
);
5707 XSETINT (bufp
->y
, top_range
);
5710 #ifndef USE_TOOLKIT_SCROLL_BARS
5712 /* Handle some mouse motion while someone is dragging the scroll bar.
5714 This may be called from a signal handler, so we have to ignore GC
5718 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5719 struct scroll_bar
*bar
;
5723 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5725 last_mouse_movement_time
= t
;
5728 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5730 /* If we're dragging the bar, display it. */
5731 if (! NILP (bar
->dragging
))
5733 /* Where should the handle be now? */
5734 int new_start
= y_pos
- 24;
5736 if (new_start
!= XINT (bar
->start
))
5738 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5740 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5745 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5747 /* Return information to the user about the current position of the mouse
5748 on the scroll bar. */
5751 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5753 Lisp_Object
*bar_window
;
5754 enum scroll_bar_part
*part
;
5756 unsigned long *time
;
5758 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5759 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5760 #if TARGET_API_MAC_CARBON
5761 WindowRef wp
= GetControlOwner (ch
);
5763 WindowRef wp
= (*ch
)->contrlOwner
;
5766 struct frame
*f
= mac_window_to_frame (wp
);
5767 int win_y
, top_range
;
5769 #if TARGET_API_MAC_CARBON
5770 GetGlobalMouse (&mouse_pos
);
5771 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5772 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5774 SetPortWindowPort (wp
);
5775 GetMouse (&mouse_pos
);
5778 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5779 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5781 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5785 if (! NILP (bar
->dragging
))
5786 win_y
-= XINT (bar
->dragging
);
5790 if (win_y
> top_range
)
5794 *bar_window
= bar
->window
;
5796 if (! NILP (bar
->dragging
))
5797 *part
= scroll_bar_handle
;
5798 else if (win_y
< XINT (bar
->start
))
5799 *part
= scroll_bar_above_handle
;
5800 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5801 *part
= scroll_bar_handle
;
5803 *part
= scroll_bar_below_handle
;
5805 XSETINT (*x
, win_y
);
5806 XSETINT (*y
, top_range
);
5809 last_mouse_scroll_bar
= Qnil
;
5811 *time
= last_mouse_movement_time
;
5815 /* The screen has been cleared so we may have changed foreground or
5816 background colors, and the scroll bars may need to be redrawn.
5817 Clear out the scroll bars, and ask for expose events, so we can
5821 x_scroll_bar_clear (f
)
5826 /* We can have scroll bars even if this is 0,
5827 if we just turned off scroll bar mode.
5828 But in that case we should not clear them. */
5829 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5830 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5831 bar
= XSCROLL_BAR (bar
)->next
)
5832 XSCROLL_BAR (bar
)->redraw_needed_p
= Qt
;
5836 /***********************************************************************
5838 ***********************************************************************/
5841 /* In identifiers such as function/variable names, Emacs tool bar is
5842 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5844 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5845 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5847 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5848 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5849 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5850 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5851 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5852 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5853 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5855 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5856 static void mac_handle_origin_change
P_ ((struct frame
*));
5857 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5861 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5868 mac_get_window_bounds (f
, &inner
, &outer
);
5870 switch (win_gravity
)
5872 case NorthWestGravity
:
5874 case SouthWestGravity
:
5875 left
+= inner
.left
- outer
.left
;
5881 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5884 case NorthEastGravity
:
5886 case SouthEastGravity
:
5887 left
+= inner
.right
- outer
.right
;
5891 switch (win_gravity
)
5893 case NorthWestGravity
:
5895 case NorthEastGravity
:
5896 top
+= inner
.top
- outer
.top
;
5902 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5905 case SouthWestGravity
:
5907 case SouthEastGravity
:
5908 top
+= inner
.bottom
- outer
.bottom
;
5912 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5916 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5923 mac_get_window_bounds (f
, &inner
, &outer
);
5925 switch (win_gravity
)
5927 case NorthWestGravity
:
5929 case SouthWestGravity
:
5936 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5937 - (inner
.right
- inner
.left
)) / 2;
5940 case NorthEastGravity
:
5942 case SouthEastGravity
:
5943 *left
= outer
.right
- (inner
.right
- inner
.left
);
5947 switch (win_gravity
)
5949 case NorthWestGravity
:
5951 case NorthEastGravity
:
5958 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5959 - (inner
.bottom
- inner
.top
)) / 2;
5962 case SouthWestGravity
:
5964 case SouthEastGravity
:
5965 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5971 mac_handle_toolbar_event (next_handler
, event
, data
)
5972 EventHandlerCallRef next_handler
;
5976 OSStatus err
, result
= eventNotHandledErr
;
5978 switch (GetEventKind (event
))
5980 case kEventToolbarGetDefaultIdentifiers
:
5984 case kEventToolbarGetAllowedIdentifiers
:
5986 CFMutableArrayRef array
;
5988 GetEventParameter (event
, kEventParamMutableArray
,
5989 typeCFMutableArrayRef
, NULL
,
5990 sizeof (CFMutableArrayRef
), NULL
, &array
);
5991 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5996 case kEventToolbarCreateItemWithIdentifier
:
5998 CFStringRef identifier
;
5999 HIToolbarItemRef item
= NULL
;
6001 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
6002 typeCFStringRef
, NULL
,
6003 sizeof (CFStringRef
), NULL
, &identifier
);
6005 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
6006 == kCFCompareEqualTo
)
6007 HIToolbarItemCreate (identifier
,
6008 kHIToolbarItemAllowDuplicates
6009 | kHIToolbarItemCantBeRemoved
, &item
);
6013 SetEventParameter (event
, kEventParamToolbarItem
,
6014 typeHIToolbarItemRef
,
6015 sizeof (HIToolbarItemRef
), &item
);
6029 mac_image_spec_to_cg_image (f
, image
)
6033 if (!valid_image_p (image
))
6037 int img_id
= lookup_image (f
, image
);
6038 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
6040 prepare_image_for_display (f
, img
);
6042 return img
->data
.ptr_val
;
6046 /* Create a tool bar for frame F. */
6049 mac_create_frame_tool_bar (f
)
6053 HIToolbarRef toolbar
;
6055 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
6059 static const EventTypeSpec specs
[] =
6060 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
6061 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
6062 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
6064 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
6065 mac_handle_toolbar_event
,
6066 GetEventTypeCount (specs
), specs
,
6071 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
6074 static const EventTypeSpec specs
[] =
6075 {{kEventClassCommand
, kEventCommandProcess
}};
6077 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
6078 mac_handle_toolbar_command_event
,
6079 GetEventTypeCount (specs
),
6083 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
6086 CFRelease (toolbar
);
6091 /* Update the tool bar for frame F. Add new buttons and remove old. */
6094 update_frame_tool_bar (f
)
6097 HIToolbarRef toolbar
= NULL
;
6099 CFArrayRef old_items
= NULL
;
6101 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
6102 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6106 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
6107 if (toolbar
== NULL
)
6109 mac_create_frame_tool_bar (f
);
6110 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
6111 if (toolbar
== NULL
)
6113 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6114 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
6117 HIToolbarCopyItems (toolbar
, &old_items
);
6118 if (old_items
== NULL
)
6121 old_count
= CFArrayGetCount (old_items
);
6123 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
6125 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
6127 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
6128 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
6131 CGImageRef cg_image
;
6133 HIToolbarItemRef item
;
6135 /* If image is a vector, choose the image according to the
6137 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6138 if (VECTORP (image
))
6142 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6143 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6146 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6147 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6149 xassert (ASIZE (image
) >= idx
);
6150 image
= AREF (image
, idx
);
6155 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6156 /* Ignore invalid image specifications. */
6157 if (cg_image
== NULL
)
6160 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6164 if (pos
< old_count
)
6166 CGImageRef old_cg_image
= NULL
;
6167 CFStringRef old_label
= NULL
;
6168 Boolean old_enabled_p
;
6170 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6172 HIToolbarItemCopyImage (item
, &old_cg_image
);
6173 if (cg_image
!= old_cg_image
)
6174 HIToolbarItemSetImage (item
, cg_image
);
6175 CGImageRelease (old_cg_image
);
6177 HIToolbarItemCopyLabel (item
, &old_label
);
6178 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6179 HIToolbarItemSetLabel (item
, label
);
6180 CFRelease (old_label
);
6182 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6183 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6184 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6189 HIToolbarCreateItemWithIdentifier (toolbar
,
6190 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6194 HIToolbarItemSetImage (item
, cg_image
);
6195 HIToolbarItemSetLabel (item
, label
);
6196 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6197 HIToolbarAppendItem (toolbar
, item
);
6205 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6210 CFRelease (old_items
);
6212 while (pos
< old_count
)
6213 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6215 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6216 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6217 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6218 toolbar visibility change. */
6219 mac_handle_origin_change (f
);
6220 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6222 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6223 /* If the title bar is completely outside the screen, adjust the
6225 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6226 kWindowConstrainMoveRegardlessOfFit
6227 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6228 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6235 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6236 doesn't deallocate the resources. */
6239 free_frame_tool_bar (f
)
6242 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6244 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6247 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6248 (NILP (Fsymbol_value
6249 (intern ("frame-notice-user-settings")))
6250 && f
== mac_focus_frame (dpyinfo
)));
6251 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6252 on toolbar visibility change. */
6253 mac_handle_origin_change (f
);
6259 mac_tool_bar_note_mouse_movement (f
, event
)
6264 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6266 HIViewRef item_view
;
6269 mouse_down_p
= (dpyinfo
->grabbed
6270 && f
== last_mouse_frame
6271 && FRAME_LIVE_P (f
));
6275 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6277 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6278 toolbar item view seems to have the same command ID with that of
6279 the toolbar item. */
6281 err
= GetControlCommandID (item_view
, &command_id
);
6282 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6284 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6286 if (i
< f
->n_tool_bar_items
)
6289 HIViewRef content_view
;
6291 err
= HIViewGetBounds (item_view
, &bounds
);
6293 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6294 kHIViewWindowContentID
, &content_view
);
6296 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6298 SetRect (&last_mouse_glyph
,
6299 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6300 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6302 help_echo_object
= help_echo_window
= Qnil
;
6304 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6305 if (NILP (help_echo_string
))
6306 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6312 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6313 EventHandlerCallRef next_handler
;
6317 OSStatus err
, result
= eventNotHandledErr
;
6318 struct frame
*f
= (struct frame
*) data
;
6321 err
= GetEventParameter (event
, kEventParamDirectObject
,
6322 typeHICommand
, NULL
,
6323 sizeof (HICommand
), NULL
, &command
);
6327 switch (GetEventKind (event
))
6329 case kEventCommandProcess
:
6330 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6331 result
= CallNextEventHandler (next_handler
, event
);
6334 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6336 if (i
< f
->n_tool_bar_items
6337 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6340 struct input_event buf
;
6344 XSETFRAME (frame
, f
);
6345 buf
.kind
= TOOL_BAR_EVENT
;
6346 buf
.frame_or_window
= frame
;
6348 kbd_buffer_store_event (&buf
);
6350 buf
.kind
= TOOL_BAR_EVENT
;
6351 buf
.frame_or_window
= frame
;
6352 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6353 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6354 kbd_buffer_store_event (&buf
);
6368 #endif /* USE_MAC_TOOLBAR */
6371 /***********************************************************************
6373 ***********************************************************************/
6375 /* Set clipping for output in glyph row ROW. W is the window in which
6376 we operate. GC is the graphics context to set clipping in.
6378 ROW may be a text row or, e.g., a mode line. Text rows must be
6379 clipped to the interior of the window dedicated to text display,
6380 mode lines must be clipped to the whole window. */
6383 x_clip_to_row (w
, row
, area
, gc
)
6385 struct glyph_row
*row
;
6389 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6391 int window_x
, window_y
, window_width
;
6393 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6395 clip_rect
.left
= window_x
;
6396 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6397 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6398 clip_rect
.right
= clip_rect
.left
+ window_width
;
6399 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6401 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6405 /* Draw a hollow box cursor on window W in glyph row ROW. */
6408 x_draw_hollow_cursor (w
, row
)
6410 struct glyph_row
*row
;
6412 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6413 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6414 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6417 struct glyph
*cursor_glyph
;
6420 /* Get the glyph the cursor is on. If we can't tell because
6421 the current matrix is invalid or such, give up. */
6422 cursor_glyph
= get_phys_cursor_glyph (w
);
6423 if (cursor_glyph
== NULL
)
6426 /* Compute frame-relative coordinates for phys cursor. */
6427 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6428 wd
= w
->phys_cursor_width
;
6430 /* The foreground of cursor_gc is typically the same as the normal
6431 background color, which can cause the cursor box to be invisible. */
6432 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6433 if (dpyinfo
->scratch_cursor_gc
)
6434 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6436 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6437 GCForeground
, &xgcv
);
6438 gc
= dpyinfo
->scratch_cursor_gc
;
6440 /* Set clipping, draw the rectangle, and reset clipping again. */
6441 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6442 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6443 mac_reset_clip_rectangles (dpy
, gc
);
6447 /* Draw a bar cursor on window W in glyph row ROW.
6449 Implementation note: One would like to draw a bar cursor with an
6450 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6451 Unfortunately, I didn't find a font yet that has this property set.
6455 x_draw_bar_cursor (w
, row
, width
, kind
)
6457 struct glyph_row
*row
;
6459 enum text_cursor_kinds kind
;
6461 struct frame
*f
= XFRAME (w
->frame
);
6462 struct glyph
*cursor_glyph
;
6464 /* If cursor is out of bounds, don't draw garbage. This can happen
6465 in mini-buffer windows when switching between echo area glyphs
6467 cursor_glyph
= get_phys_cursor_glyph (w
);
6468 if (cursor_glyph
== NULL
)
6471 /* If on an image, draw like a normal cursor. That's usually better
6472 visible than drawing a bar, esp. if the image is large so that
6473 the bar might not be in the window. */
6474 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6476 struct glyph_row
*row
;
6477 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6478 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6482 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6483 Window window
= FRAME_MAC_WINDOW (f
);
6484 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6485 unsigned long mask
= GCForeground
| GCBackground
;
6486 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6489 /* If the glyph's background equals the color we normally draw
6490 the bar cursor in, the bar cursor in its normal color is
6491 invisible. Use the glyph's foreground color instead in this
6492 case, on the assumption that the glyph's colors are chosen so
6493 that the glyph is legible. */
6494 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6495 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6497 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6500 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6503 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6504 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6508 width
= FRAME_CURSOR_WIDTH (f
);
6509 width
= min (cursor_glyph
->pixel_width
, width
);
6511 w
->phys_cursor_width
= width
;
6512 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6514 if (kind
== BAR_CURSOR
)
6515 mac_fill_rectangle (f
, gc
,
6516 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6517 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6518 width
, row
->height
);
6520 mac_fill_rectangle (f
, gc
,
6521 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6522 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6523 row
->height
- width
),
6524 cursor_glyph
->pixel_width
,
6527 mac_reset_clip_rectangles (f
, gc
);
6532 /* RIF: Define cursor CURSOR on frame F. */
6535 mac_define_frame_cursor (f
, cursor
)
6539 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6541 if (dpyinfo
->x_focus_frame
== f
)
6542 SetThemeCursor (cursor
);
6546 /* RIF: Clear area on frame F. */
6549 mac_clear_frame_area (f
, x
, y
, width
, height
)
6551 int x
, y
, width
, height
;
6553 mac_clear_area (f
, x
, y
, width
, height
);
6557 /* RIF: Draw cursor on window W. */
6560 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6562 struct glyph_row
*glyph_row
;
6564 int cursor_type
, cursor_width
;
6569 w
->phys_cursor_type
= cursor_type
;
6570 w
->phys_cursor_on_p
= 1;
6572 if (glyph_row
->exact_window_width_line_p
6573 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6575 glyph_row
->cursor_in_fringe_p
= 1;
6576 draw_fringe_bitmap (w
, glyph_row
, 0);
6579 switch (cursor_type
)
6581 case HOLLOW_BOX_CURSOR
:
6582 x_draw_hollow_cursor (w
, glyph_row
);
6585 case FILLED_BOX_CURSOR
:
6586 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6590 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6594 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6598 w
->phys_cursor_width
= 0;
6610 #if 0 /* MAC_TODO: no icon support yet. */
6612 x_bitmap_icon (f
, icon
)
6618 if (FRAME_W32_WINDOW (f
) == 0)
6622 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6623 else if (STRINGP (icon
))
6624 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6625 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6626 else if (SYMBOLP (icon
))
6630 if (EQ (icon
, intern ("application")))
6631 name
= (LPCTSTR
) IDI_APPLICATION
;
6632 else if (EQ (icon
, intern ("hand")))
6633 name
= (LPCTSTR
) IDI_HAND
;
6634 else if (EQ (icon
, intern ("question")))
6635 name
= (LPCTSTR
) IDI_QUESTION
;
6636 else if (EQ (icon
, intern ("exclamation")))
6637 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6638 else if (EQ (icon
, intern ("asterisk")))
6639 name
= (LPCTSTR
) IDI_ASTERISK
;
6640 else if (EQ (icon
, intern ("winlogo")))
6641 name
= (LPCTSTR
) IDI_WINLOGO
;
6645 hicon
= LoadIcon (NULL
, name
);
6653 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6658 #endif /* MAC_TODO */
6660 /************************************************************************
6662 ************************************************************************/
6664 /* Display Error Handling functions not used on W32. Listing them here
6665 helps diff stay in step when comparing w32term.c with xterm.c.
6667 x_error_catcher (display, error)
6668 x_catch_errors (dpy)
6669 x_catch_errors_unwind (old_val)
6670 x_check_errors (dpy, format)
6671 x_had_errors_p (dpy)
6672 x_clear_errors (dpy)
6673 x_uncatch_errors (dpy, count)
6675 x_connection_signal (signalnum)
6676 x_connection_closed (dpy, error_message)
6677 x_error_quitter (display, error)
6678 x_error_handler (display, error)
6679 x_io_error_quitter (display)
6684 /* Changing the font of the frame. */
6686 /* Give frame F the font named FONTNAME as its default font, and
6687 return the full name of that font. FONTNAME may be a wildcard
6688 pattern; in that case, we choose some font that fits the pattern.
6689 The return value shows which font we chose. */
6692 x_new_font (f
, fontname
)
6694 register char *fontname
;
6696 struct font_info
*fontp
6697 = FS_LOAD_FONT (f
, fontname
);
6702 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
6703 /* This font is already set in frame F. There's nothing more to
6705 return build_string (fontp
->full_name
);
6707 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6708 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6709 FRAME_FONTSET (f
) = -1;
6711 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6712 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6713 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6715 compute_fringe_widths (f
, 1);
6717 /* Compute the scroll bar width in character columns. */
6718 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6720 int wid
= FRAME_COLUMN_WIDTH (f
);
6721 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6722 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6726 int wid
= FRAME_COLUMN_WIDTH (f
);
6727 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6730 /* Now make the frame display the given font. */
6731 if (FRAME_MAC_WINDOW (f
) != 0)
6733 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6735 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6737 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6740 /* Don't change the size of a tip frame; there's no point in
6741 doing it because it's done in Fx_show_tip, and it leads to
6742 problems because the tip frame has no widget. */
6743 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6744 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6747 return build_string (fontp
->full_name
);
6750 /* Give frame F the fontset named FONTSETNAME as its default fontset,
6751 and return the full name of that fontset. FONTSETNAME may be a
6752 wildcard pattern; in that case, we choose some fontset that fits
6753 the pattern. FONTSETNAME may be a font name for ASCII characters;
6754 in that case, we create a fontset from that font name.
6756 The return value shows which fontset we chose.
6757 If FONTSETNAME specifies the default fontset, return Qt.
6758 If an ASCII font in the specified fontset can't be loaded, return
6762 x_new_fontset (f
, fontsetname
)
6764 Lisp_Object fontsetname
;
6766 int fontset
= fs_query_fontset (fontsetname
, 0);
6769 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
6770 /* This fontset is already set in frame F. There's nothing more
6772 return fontset_name (fontset
);
6773 else if (fontset
== 0)
6774 /* The default fontset can't be the default font. */
6778 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6780 result
= x_new_font (f
, SDATA (fontsetname
));
6782 if (!STRINGP (result
))
6783 /* Can't load ASCII font. */
6787 fontset
= new_fontset_from_font_name (result
);
6789 /* Since x_new_font doesn't update any fontset information, do it now. */
6790 FRAME_FONTSET (f
) = fontset
;
6792 return fontset_name (fontset
);
6796 /***********************************************************************
6797 TODO: W32 Input Methods
6798 ***********************************************************************/
6799 /* Listing missing functions from xterm.c helps diff stay in step.
6801 xim_destroy_callback (xim, client_data, call_data)
6802 xim_open_dpy (dpyinfo, resource_name)
6804 xim_instantiate_callback (display, client_data, call_data)
6805 xim_initialize (dpyinfo, resource_name)
6806 xim_close_dpy (dpyinfo)
6812 mac_get_window_bounds (f
, inner
, outer
)
6814 Rect
*inner
, *outer
;
6816 #if TARGET_API_MAC_CARBON
6817 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6818 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6819 #else /* not TARGET_API_MAC_CARBON */
6820 RgnHandle region
= NewRgn ();
6822 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6823 *inner
= (*region
)->rgnBBox
;
6824 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6825 *outer
= (*region
)->rgnBBox
;
6826 DisposeRgn (region
);
6827 #endif /* not TARGET_API_MAC_CARBON */
6831 mac_handle_origin_change (f
)
6834 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6838 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6840 int pixelwidth
, pixelheight
;
6844 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6845 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6847 if (cols
!= FRAME_COLS (f
)
6848 || rows
!= FRAME_LINES (f
)
6849 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6850 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6852 /* We pass 1 for DELAY since we can't run Lisp code inside of
6854 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6855 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6856 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6858 /* If cursor was outside the new size, mark it as off. */
6859 mark_window_cursors_off (XWINDOW (f
->root_window
));
6861 /* Clear out any recollection of where the mouse highlighting
6862 was, since it might be in a place that's outside the new
6863 frame size. Actually checking whether it is outside is a
6864 pain in the neck, so don't try--just let the highlighting be
6865 done afresh with new size. */
6866 cancel_mouse_face (f
);
6868 #if TARGET_API_MAC_CARBON
6869 if (f
->output_data
.mac
->hourglass_control
)
6872 mac_prepare_for_quickdraw (f
);
6874 MoveControl (f
->output_data
.mac
->hourglass_control
,
6875 pixelwidth
- HOURGLASS_WIDTH
, 0);
6882 /* Calculate the absolute position in frame F
6883 from its current recorded position values and gravity. */
6886 x_calc_absolute_position (f
)
6889 int flags
= f
->size_hint_flags
;
6892 /* We have nothing to do if the current position
6893 is already for the top-left corner. */
6894 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6897 /* Find the offsets of the outside upper-left corner of
6898 the inner window, with respect to the outer window. */
6900 mac_get_window_bounds (f
, &inner
, &outer
);
6903 /* Treat negative positions as relative to the leftmost bottommost
6904 position that fits on the screen. */
6905 if (flags
& XNegative
)
6906 f
->left_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->width
6907 - (outer
.right
- outer
.left
));
6909 if (flags
& YNegative
)
6910 f
->top_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->height
6911 - (outer
.bottom
- outer
.top
));
6913 /* The left_pos and top_pos
6914 are now relative to the top and left screen edges,
6915 so the flags should correspond. */
6916 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6919 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6920 to really change the position, and 0 when calling from
6921 x_make_frame_visible (in that case, XOFF and YOFF are the current
6922 position values). It is -1 when calling from x_set_frame_parameters,
6923 which means, do adjust for borders but don't change the gravity. */
6926 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6928 register int xoff
, yoff
;
6931 if (change_gravity
> 0)
6935 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6937 f
->size_hint_flags
|= XNegative
;
6939 f
->size_hint_flags
|= YNegative
;
6940 f
->win_gravity
= NorthWestGravity
;
6942 x_calc_absolute_position (f
);
6945 x_wm_set_size_hint (f
, (long) 0, 0);
6947 #if TARGET_API_MAC_CARBON
6948 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6949 /* If the title bar is completely outside the screen, adjust the
6951 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6952 kWindowConstrainMoveRegardlessOfFit
6953 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6954 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6955 mac_handle_origin_change (f
);
6958 Rect inner
, outer
, screen_rect
, dummy
;
6959 RgnHandle region
= NewRgn ();
6961 mac_get_window_bounds (f
, &inner
, &outer
);
6962 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6963 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6964 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6965 f
->top_pos
+ f
->y_pixels_diff
, false);
6967 /* If the title bar is completely outside the screen, adjust the
6968 position. The variable `outer' holds the title bar rectangle.
6969 The variable `inner' holds slightly smaller one than `outer',
6970 so that the calculation of overlapping may not become too
6972 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6973 outer
= (*region
)->rgnBBox
;
6974 DisposeRgn (region
);
6976 InsetRect (&inner
, 8, 8);
6977 screen_rect
= qd
.screenBits
.bounds
;
6978 screen_rect
.top
+= GetMBarHeight ();
6980 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6982 if (inner
.right
<= screen_rect
.left
)
6983 f
->left_pos
= screen_rect
.left
;
6984 else if (inner
.left
>= screen_rect
.right
)
6985 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6987 if (inner
.bottom
<= screen_rect
.top
)
6988 f
->top_pos
= screen_rect
.top
;
6989 else if (inner
.top
>= screen_rect
.bottom
)
6990 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6992 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6993 f
->top_pos
+ f
->y_pixels_diff
, false);
7001 /* Call this to change the size of frame F's x-window.
7002 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
7003 for this size change and subsequent size changes.
7004 Otherwise we leave the window gravity unchanged. */
7007 x_set_window_size (f
, change_gravity
, cols
, rows
)
7012 int pixelwidth
, pixelheight
;
7016 check_frame_size (f
, &rows
, &cols
);
7017 f
->scroll_bar_actual_width
7018 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
7020 compute_fringe_widths (f
, 0);
7022 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
7023 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7025 f
->win_gravity
= NorthWestGravity
;
7026 x_wm_set_size_hint (f
, (long) 0, 0);
7028 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
7030 #if TARGET_API_MAC_CARBON
7031 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
7033 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
7035 if (f
->output_data
.mac
->internal_border_width
7036 != FRAME_INTERNAL_BORDER_WIDTH (f
))
7038 mac_clear_window (f
);
7039 f
->output_data
.mac
->internal_border_width
7040 = FRAME_INTERNAL_BORDER_WIDTH (f
);
7043 SET_FRAME_GARBAGED (f
);
7048 /* Mouse warping. */
7050 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
7053 x_set_mouse_position (f
, x
, y
)
7059 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
7060 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
7062 if (pix_x
< 0) pix_x
= 0;
7063 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
7065 if (pix_y
< 0) pix_y
= 0;
7066 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
7068 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
7072 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
7077 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
7078 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
7081 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
7084 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
7087 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
7088 0, 0, 0, 0, pix_x
, pix_y
);
7094 /* focus shifting, raising and lowering. */
7097 x_focus_on_frame (f
)
7100 #if 0 /* This proves to be unpleasant. */
7104 /* I don't think that the ICCCM allows programs to do things like this
7105 without the interaction of the window manager. Whatever you end up
7106 doing with this code, do it to x_unfocus_frame too. */
7107 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7108 RevertToPointerRoot
, CurrentTime
);
7118 /* Raise frame F. */
7124 if (f
->async_visible
)
7127 BringToFront (FRAME_MAC_WINDOW (f
));
7132 /* Lower frame F. */
7138 if (f
->async_visible
)
7141 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7147 XTframe_raise_lower (f
, raise_flag
)
7157 /* Change of visibility. */
7160 mac_handle_visibility_change (f
)
7163 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7164 int visible
= 0, iconified
= 0;
7165 struct input_event buf
;
7167 if (IsWindowVisible (wp
))
7169 if (IsWindowCollapsed (wp
))
7175 if (!f
->async_visible
&& visible
)
7179 /* wait_reading_process_output will notice this and update
7180 the frame's display structures. If we were made
7181 invisible, we should not set garbaged, because that stops
7182 redrawing on Update events. */
7183 SET_FRAME_GARBAGED (f
);
7186 buf
.kind
= DEICONIFY_EVENT
;
7187 XSETFRAME (buf
.frame_or_window
, f
);
7189 kbd_buffer_store_event (&buf
);
7191 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7192 /* Force a redisplay sooner or later to update the
7193 frame titles in case this is the second frame. */
7194 record_asynch_buffer_change ();
7196 else if (f
->async_visible
&& !visible
)
7200 buf
.kind
= ICONIFY_EVENT
;
7201 XSETFRAME (buf
.frame_or_window
, f
);
7203 kbd_buffer_store_event (&buf
);
7206 f
->async_visible
= visible
;
7207 f
->async_iconified
= iconified
;
7210 /* This tries to wait until the frame is really visible.
7211 However, if the window manager asks the user where to position
7212 the frame, this will return before the user finishes doing that.
7213 The frame will not actually be visible at that time,
7214 but it will become visible later when the window manager
7215 finishes with it. */
7218 x_make_frame_visible (f
)
7223 if (! FRAME_VISIBLE_P (f
))
7225 /* We test FRAME_GARBAGED_P here to make sure we don't
7226 call x_set_offset a second time
7227 if we get to x_make_frame_visible a second time
7228 before the window gets really visible. */
7229 if (! FRAME_ICONIFIED_P (f
)
7230 && ! f
->output_data
.mac
->asked_for_visible
)
7231 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7233 f
->output_data
.mac
->asked_for_visible
= 1;
7235 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7236 ShowWindow (FRAME_MAC_WINDOW (f
));
7239 XFlush (FRAME_MAC_DISPLAY (f
));
7241 /* Synchronize to ensure Emacs knows the frame is visible
7242 before we do anything else. We do this loop with input not blocked
7243 so that incoming events are handled. */
7248 /* This must come after we set COUNT. */
7251 XSETFRAME (frame
, f
);
7253 /* Wait until the frame is visible. Process X events until a
7254 MapNotify event has been seen, or until we think we won't get a
7255 MapNotify at all.. */
7256 for (count
= input_signal_count
+ 10;
7257 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7259 /* Force processing of queued events. */
7262 /* Machines that do polling rather than SIGIO have been
7263 observed to go into a busy-wait here. So we'll fake an
7264 alarm signal to let the handler know that there's something
7265 to be read. We used to raise a real alarm, but it seems
7266 that the handler isn't always enabled here. This is
7268 if (input_polling_used ())
7270 /* It could be confusing if a real alarm arrives while
7271 processing the fake one. Turn it off and let the
7272 handler reset it. */
7273 extern void poll_for_input_1
P_ ((void));
7274 int old_poll_suppress_count
= poll_suppress_count
;
7275 poll_suppress_count
= 1;
7276 poll_for_input_1 ();
7277 poll_suppress_count
= old_poll_suppress_count
;
7280 /* See if a MapNotify event has been processed. */
7281 FRAME_SAMPLE_VISIBILITY (f
);
7286 /* Change from mapped state to withdrawn state. */
7288 /* Make the frame visible (mapped and not iconified). */
7291 x_make_frame_invisible (f
)
7294 /* A deactivate event does not occur when the last visible frame is
7295 made invisible. So if we clear the highlight here, it will not
7296 be rehighlighted when it is made visible. */
7298 /* Don't keep the highlight on an invisible frame. */
7299 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7300 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7305 #if !TARGET_API_MAC_CARBON
7306 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7307 that the current position of the window is user-specified, rather than
7308 program-specified, so that when the window is mapped again, it will be
7309 placed at the same location, without forcing the user to position it
7310 by hand again (they have already done that once for this window.) */
7311 x_wm_set_size_hint (f
, (long) 0, 1);
7314 HideWindow (FRAME_MAC_WINDOW (f
));
7318 #if !TARGET_API_MAC_CARBON
7319 mac_handle_visibility_change (f
);
7323 /* Change window state from mapped to iconified. */
7331 /* A deactivate event does not occur when the last visible frame is
7332 iconified. So if we clear the highlight here, it will not be
7333 rehighlighted when it is deiconified. */
7335 /* Don't keep the highlight on an invisible frame. */
7336 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7337 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7340 if (f
->async_iconified
)
7345 FRAME_SAMPLE_VISIBILITY (f
);
7347 if (! FRAME_VISIBLE_P (f
))
7348 ShowWindow (FRAME_MAC_WINDOW (f
));
7350 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7355 error ("Can't notify window manager of iconification");
7357 #if !TARGET_API_MAC_CARBON
7358 mac_handle_visibility_change (f
);
7363 /* Free X resources of frame F. */
7366 x_free_frame_resources (f
)
7369 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7370 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7374 if (wp
!= tip_window
)
7375 remove_window_handler (wp
);
7378 mac_prepare_for_quickdraw (f
);
7381 if (wp
== tip_window
)
7382 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7383 closed' event. So we reset tip_window here. */
7386 free_frame_menubar (f
);
7388 if (FRAME_FACE_CACHE (f
))
7389 free_frame_faces (f
);
7393 if (FRAME_SIZE_HINTS (f
))
7394 xfree (FRAME_SIZE_HINTS (f
));
7396 xfree (f
->output_data
.mac
);
7397 f
->output_data
.mac
= NULL
;
7399 if (f
== dpyinfo
->x_focus_frame
)
7401 dpyinfo
->x_focus_frame
= 0;
7402 #if USE_MAC_FONT_PANEL
7403 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7406 if (f
== dpyinfo
->x_focus_event_frame
)
7407 dpyinfo
->x_focus_event_frame
= 0;
7408 if (f
== dpyinfo
->x_highlight_frame
)
7409 dpyinfo
->x_highlight_frame
= 0;
7411 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7413 dpyinfo
->mouse_face_beg_row
7414 = dpyinfo
->mouse_face_beg_col
= -1;
7415 dpyinfo
->mouse_face_end_row
7416 = dpyinfo
->mouse_face_end_col
= -1;
7417 dpyinfo
->mouse_face_window
= Qnil
;
7418 dpyinfo
->mouse_face_deferred_gc
= 0;
7419 dpyinfo
->mouse_face_mouse_frame
= 0;
7426 /* Destroy the X window of frame F. */
7429 x_destroy_window (f
)
7432 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7434 x_free_frame_resources (f
);
7436 dpyinfo
->reference_count
--;
7440 /* Setting window manager hints. */
7442 /* Set the normal size hints for the window manager, for frame F.
7443 FLAGS is the flags word to use--or 0 meaning preserve the flags
7444 that the window now has.
7445 If USER_POSITION is nonzero, we set the USPosition
7446 flag (this is useful when FLAGS is 0). */
7448 x_wm_set_size_hint (f
, flags
, user_position
)
7453 int base_width
, base_height
, width_inc
, height_inc
;
7454 int min_rows
= 0, min_cols
= 0;
7455 XSizeHints
*size_hints
;
7457 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7458 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7459 width_inc
= FRAME_COLUMN_WIDTH (f
);
7460 height_inc
= FRAME_LINE_HEIGHT (f
);
7462 check_frame_size (f
, &min_rows
, &min_cols
);
7464 size_hints
= FRAME_SIZE_HINTS (f
);
7465 if (size_hints
== NULL
)
7467 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7468 bzero (size_hints
, sizeof (XSizeHints
));
7471 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7472 size_hints
->width_inc
= width_inc
;
7473 size_hints
->height_inc
= height_inc
;
7474 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7475 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7476 size_hints
->base_width
= base_width
;
7477 size_hints
->base_height
= base_height
;
7480 size_hints
->flags
= flags
;
7481 else if (user_position
)
7483 size_hints
->flags
&= ~ PPosition
;
7484 size_hints
->flags
|= USPosition
;
7488 #if 0 /* MAC_TODO: hide application instead of iconify? */
7489 /* Used for IconicState or NormalState */
7492 x_wm_set_window_state (f
, state
)
7496 #ifdef USE_X_TOOLKIT
7499 XtSetArg (al
[0], XtNinitialState
, state
);
7500 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7501 #else /* not USE_X_TOOLKIT */
7502 Window window
= FRAME_X_WINDOW (f
);
7504 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7505 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7507 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7508 #endif /* not USE_X_TOOLKIT */
7512 x_wm_set_icon_pixmap (f
, pixmap_id
)
7518 #ifndef USE_X_TOOLKIT
7519 Window window
= FRAME_X_WINDOW (f
);
7524 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7525 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7529 /* It seems there is no way to turn off use of an icon pixmap.
7530 The following line does it, only if no icon has yet been created,
7531 for some window managers. But with mwm it crashes.
7532 Some people say it should clear the IconPixmapHint bit in this case,
7533 but that doesn't work, and the X consortium said it isn't the
7534 right thing at all. Since there is no way to win,
7535 best to explicitly give up. */
7537 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7543 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7547 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7548 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7551 #else /* not USE_X_TOOLKIT */
7553 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7554 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7556 #endif /* not USE_X_TOOLKIT */
7559 #endif /* MAC_TODO */
7562 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7566 #if 0 /* MAC_TODO: no icons on Mac */
7567 #ifdef USE_X_TOOLKIT
7568 Window window
= XtWindow (f
->output_data
.x
->widget
);
7570 Window window
= FRAME_X_WINDOW (f
);
7573 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7574 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7575 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7577 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7578 #endif /* MAC_TODO */
7582 /***********************************************************************
7584 ***********************************************************************/
7586 /* An XLFD pattern is divided into blocks delimited by '*'. This
7587 structure holds information for each block. */
7588 struct xlfdpat_block
7590 /* Length of the pattern string in this block. Non-zero except for
7591 the first and the last blocks. */
7594 /* Pattern string except the last character in this block. The last
7595 character is replaced with NUL in order to use it as a
7597 unsigned char *pattern
;
7599 /* Last character of the pattern string. Must not be '?'. */
7600 unsigned char last_char
;
7602 /* One of the tables for the Boyer-Moore string search. It
7603 specifies the number of positions to proceed for each character
7604 with which the match fails. */
7607 /* The skip value for the last character in the above `skip' is
7608 assigned to `infinity' in order to simplify a loop condition.
7609 The original value is saved here. */
7615 /* Normalized pattern string. "Normalized" means that capital
7616 letters are lowered, blocks are not empty except the first and
7617 the last ones, and trailing '?'s in a block that is not the last
7618 one are moved to the next one. The last character in each block
7619 is replaced with NUL. */
7622 /* Number of characters except '*'s and trailing '?'s in the
7623 normalized pattern string. */
7626 /* Number of trailing '?'s in the normalized pattern string. */
7627 int trailing_anychars
;
7629 /* Number of blocks and information for each block. The latter is
7630 NULL if the pattern is exact (no '*' or '?' in it). */
7632 struct xlfdpat_block
*blocks
;
7636 xlfdpat_destroy (pat
)
7637 struct xlfdpat
*pat
;
7644 xfree (pat
->blocks
);
7651 static struct xlfdpat
*
7652 xlfdpat_create (pattern
)
7653 const char *pattern
;
7655 struct xlfdpat
*pat
;
7656 int nblocks
, i
, skip
;
7657 unsigned char last_char
, *p
, *q
, *anychar_head
;
7658 const unsigned char *ptr
;
7659 struct xlfdpat_block
*blk
;
7661 pat
= xmalloc (sizeof (struct xlfdpat
));
7662 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7664 /* Normalize the pattern string and store it to `pat->buf'. */
7666 anychar_head
= NULL
;
7669 for (ptr
= pattern
; *ptr
; ptr
++)
7671 unsigned char c
= *ptr
;
7674 if (last_char
== '*')
7675 /* ...a** -> ...a* */
7679 if (last_char
== '?')
7681 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7682 /* ...*??* -> ...*?? */
7685 /* ...a??* -> ...a*?? */
7687 *anychar_head
++ = '*';
7695 if (last_char
!= '?')
7699 /* On Mac OS X 10.3, tolower also converts non-ASCII
7700 characters for some locales. */
7704 *q
++ = last_char
= c
;
7708 pat
->nblocks
= nblocks
;
7709 if (last_char
!= '?')
7710 pat
->trailing_anychars
= 0;
7713 pat
->trailing_anychars
= q
- anychar_head
;
7716 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7718 if (anychar_head
== NULL
&& nblocks
== 1)
7720 /* The pattern is exact. */
7725 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7727 /* Divide the normalized pattern into blocks. */
7729 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7734 blk
->len
= p
- blk
->pattern
;
7738 blk
->len
= q
- blk
->pattern
;
7740 /* Setup a table for the Boyer-Moore string search. */
7741 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7744 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7745 blk
->pattern
[blk
->len
- 1] = '\0';
7747 for (skip
= 1; skip
< blk
->len
; skip
++)
7748 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7751 for (i
= 0; i
< 256; i
++)
7752 blk
->skip
[i
] = skip
;
7754 p
= blk
->pattern
+ (blk
->len
- skip
);
7756 blk
->skip
[*p
++] = skip
;
7758 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7765 xlfdpat_exact_p (pat
)
7766 struct xlfdpat
*pat
;
7768 return pat
->blocks
== NULL
;
7771 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7772 that the pattern in *BLK matches with its prefix. Return NULL
7773 there is no such strings. STRING must be lowered in advance. */
7776 xlfdpat_block_match_1 (blk
, string
, start_max
)
7777 struct xlfdpat_block
*blk
;
7778 const unsigned char *string
;
7781 int start
, infinity
;
7783 const unsigned char *s
;
7785 xassert (blk
->len
> 0);
7786 xassert (start_max
+ blk
->len
<= strlen (string
));
7787 xassert (blk
->last_char
!= '?');
7789 /* See the comments in the function `boyer_moore' (search.c) for the
7790 use of `infinity'. */
7791 infinity
= start_max
+ blk
->len
+ 1;
7792 blk
->skip
[blk
->last_char
] = infinity
;
7797 /* Check the last character of the pattern. */
7798 s
= string
+ blk
->len
- 1;
7801 start
+= blk
->skip
[*(s
+ start
)];
7803 while (start
<= start_max
);
7805 if (start
< infinity
)
7806 /* Couldn't find the last character. */
7809 /* No less than `infinity' means we could find the last
7810 character at `s[start - infinity]'. */
7813 /* Check the remaining characters. We prefer making no-'?'
7814 cases faster because the use of '?' is really rare. */
7819 while (*p
++ == *s
++)
7822 while (*(p
- 1) == '?');
7824 if (*(p
- 1) == '\0')
7826 return string
+ start
;
7829 start
+= blk
->last_char_skip
;
7831 while (start
<= start_max
);
7836 #define xlfdpat_block_match(b, s, m) \
7837 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7838 : xlfdpat_block_match_1 (b, s, m))
7840 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7841 matches with STRING. STRING must be lowered in advance. */
7844 xlfdpat_match (pat
, string
)
7845 struct xlfdpat
*pat
;
7846 const unsigned char *string
;
7848 int str_len
, nblocks
, i
, start_max
;
7849 struct xlfdpat_block
*blk
;
7850 const unsigned char *s
;
7852 xassert (pat
->nblocks
> 0);
7854 if (xlfdpat_exact_p (pat
))
7855 return strcmp (pat
->buf
, string
) == 0;
7857 /* The number of the characters in the string must not be smaller
7858 than that in the pattern. */
7859 str_len
= strlen (string
);
7860 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7863 /* Chop off the trailing '?'s. */
7864 str_len
-= pat
->trailing_anychars
;
7866 /* The last block. When it is non-empty, it must match at the end
7868 nblocks
= pat
->nblocks
;
7869 blk
= pat
->blocks
+ (nblocks
- 1);
7871 /* The last block is also the first one. */
7872 return (str_len
== blk
->len
7873 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7874 else if (blk
->len
!= 0)
7875 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7878 /* The first block. When it is non-empty, it must match at the
7879 beginning of the string. */
7883 s
= xlfdpat_block_match (blk
, string
, 0);
7886 string
= s
+ blk
->len
;
7889 /* The rest of the blocks. */
7890 start_max
= str_len
- pat
->nchars
;
7891 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7893 s
= xlfdpat_block_match (blk
, string
, start_max
);
7896 start_max
-= s
- string
;
7897 string
= s
+ blk
->len
;
7904 /***********************************************************************
7906 ***********************************************************************/
7908 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7911 x_get_font_info (f
, font_idx
)
7915 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7918 /* the global font name table */
7919 static char **font_name_table
= NULL
;
7920 static int font_name_table_size
= 0;
7921 static int font_name_count
= 0;
7923 /* Alist linking font family names to Font Manager font family
7924 references (which can also be used as QuickDraw font IDs). We use
7925 an alist because hash tables are not ready when the terminal frame
7926 for Mac OS Classic is created. */
7927 static Lisp_Object fm_font_family_alist
;
7929 /* Hash table linking font family names to ATSU font IDs. */
7930 static Lisp_Object atsu_font_id_hash
;
7931 /* Alist linking Font Manager style to face attributes. */
7932 static Lisp_Object fm_style_face_attributes_alist
;
7933 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7936 /* Alist linking character set strings to Mac text encoding and Emacs
7938 static Lisp_Object Vmac_charset_info_alist
;
7941 create_text_encoding_info_alist ()
7943 Lisp_Object result
= Qnil
, rest
;
7945 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7947 Lisp_Object charset_info
= XCAR (rest
);
7948 Lisp_Object charset
, coding_system
, text_encoding
;
7949 Lisp_Object existing_info
;
7951 if (!(CONSP (charset_info
)
7952 && (charset
= XCAR (charset_info
),
7954 && CONSP (XCDR (charset_info
))
7955 && (text_encoding
= XCAR (XCDR (charset_info
)),
7956 INTEGERP (text_encoding
))
7957 && CONSP (XCDR (XCDR (charset_info
)))
7958 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7959 SYMBOLP (coding_system
))))
7962 existing_info
= assq_no_quit (text_encoding
, result
);
7963 if (NILP (existing_info
))
7964 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7967 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7968 XSETCDR (XCDR (existing_info
),
7969 Fcons (charset
, XCDR (XCDR (existing_info
))));
7977 decode_mac_font_name (name
, size
, coding_system
)
7980 Lisp_Object coding_system
;
7982 struct coding_system coding
;
7985 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7987 for (p
= name
; *p
; p
++)
7988 if (!isascii (*p
) || iscntrl (*p
))
7993 setup_coding_system (coding_system
, &coding
);
7994 coding
.src_multibyte
= 0;
7995 coding
.dst_multibyte
= 1;
7996 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7997 coding
.dst_bytes
= size
;
7998 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
8000 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
8001 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
8002 name
[min (coding
.produced
, size
)] = '\0';
8006 /* If there's just one occurrence of '-' in the family name, it is
8007 replaced with '_'. (More than one occurrence of '-' means a
8008 "FOUNDRY-FAMILY-CHARSET"-style name.) */
8009 p
= strchr (name
, '-');
8010 if (p
&& strchr (p
+ 1, '-') == NULL
)
8013 for (p
= name
; *p
; p
++)
8014 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8015 for some locales. */
8022 mac_to_x_fontname (name
, size
, style
, charset
)
8030 char xf
[256], *result
;
8033 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
8037 strcpy(foundry
, "Apple");
8038 strcpy(family
, name
);
8041 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
8042 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
8043 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
8045 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
8046 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
8047 for (p
= result
; *p
; p
++)
8048 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8049 for some locales. */
8056 /* Parse fully-specified and instantiated X11 font spec XF, and store
8057 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
8058 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
8059 caller must allocate at least 256 and 32 bytes respectively. For
8060 ordinary Mac fonts, the value stored to FAMILY should just be their
8061 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
8062 intlfonts collection contain their charset designation in their
8063 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
8064 types of font names are handled accordingly. */
8066 const int kDefaultFontSize
= 12;
8069 parse_x_font_name (xf
, family
, size
, style
, charset
)
8076 Str31 foundry
, weight
;
8077 int point_size
, avgwidth
;
8080 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
8081 foundry
, family
, weight
, slant
, size
,
8082 &point_size
, &avgwidth
, charset
) != 8
8083 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
8084 foundry
, family
, weight
, slant
, size
,
8085 &point_size
, &avgwidth
, charset
) != 8)
8091 *size
= point_size
/ 10;
8092 else if (avgwidth
> 0)
8093 *size
= avgwidth
/ 10;
8096 *size
= kDefaultFontSize
;
8099 if (strcmp (weight
, "bold") == 0)
8104 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
8106 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
8108 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
8110 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
8111 but take overlap into account. */
8112 memmove (family
+ foundry_len
+ 1, family
, family_len
);
8113 memcpy (family
, foundry
, foundry_len
);
8114 family
[foundry_len
] = '-';
8115 family
[foundry_len
+ 1 + family_len
] = '-';
8116 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
8122 for (p
= family
; *p
; p
++)
8123 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8124 for some locales. */
8133 add_font_name_table_entry (char *font_name
)
8135 if (font_name_table_size
== 0)
8137 font_name_table_size
= 256;
8138 font_name_table
= (char **)
8139 xmalloc (font_name_table_size
* sizeof (char *));
8141 else if (font_name_count
+ 1 >= font_name_table_size
)
8143 font_name_table_size
*= 2;
8144 font_name_table
= (char **)
8145 xrealloc (font_name_table
,
8146 font_name_table_size
* sizeof (char *));
8149 font_name_table
[font_name_count
++] = font_name
;
8153 add_mac_font_name (name
, size
, style
, charset
)
8157 const char *charset
;
8160 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8163 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8164 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8165 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8166 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8173 fm_get_style_from_font (font
)
8177 FMFontStyle style
= normal
;
8180 FMFontFamily font_family
;
8181 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8183 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8184 some font (e.g., Optima) even if it is `bold'. */
8185 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8186 sizeof (mac_style
), &mac_style
, &len
);
8188 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8189 style
= EndianU16_BtoN (mac_style
);
8191 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8197 atsu_find_font_from_family_name (family
)
8200 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8203 Lisp_Object rest
, best
;
8204 FMFontStyle min_style
, style
;
8206 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8209 return kATSUInvalidFontID
;
8211 rest
= HASH_VALUE (h
, i
);
8212 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8213 return cons_to_long (rest
);
8215 rest
= Fnreverse (rest
);
8219 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8222 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8223 if (style
< min_style
)
8226 if (style
== normal
)
8233 while (!NILP (rest
));
8235 HASH_VALUE (h
, i
) = best
;
8236 return cons_to_long (best
);
8240 fm_style_to_face_attributes (fm_style
)
8241 FMFontStyle fm_style
;
8245 fm_style
&= (bold
| italic
);
8246 tem
= assq_no_quit (make_number (fm_style
),
8247 fm_style_face_attributes_alist
);
8251 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8252 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8253 fm_style_face_attributes_alist
=
8254 Fcons (Fcons (make_number (fm_style
), tem
),
8255 fm_style_face_attributes_alist
);
8261 atsu_find_font_family_name (font_id
)
8266 Lisp_Object family
= Qnil
;
8268 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8269 kFontMacintoshPlatform
, kFontNoScript
,
8270 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8273 family
= make_uninit_string (len
);
8274 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8275 kFontMacintoshPlatform
, kFontNoScript
,
8276 kFontNoLanguage
, len
, SDATA (family
),
8280 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8286 mac_atsu_font_face_attributes (font_id
)
8289 Lisp_Object family
, style_attrs
;
8291 family
= atsu_find_font_family_name (font_id
);
8294 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8295 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8299 /* Sets up the table font_name_table to contain the list of all fonts
8300 in the system the first time the table is used so that the Resource
8301 Manager need not be accessed every time this information is
8305 init_font_name_table ()
8307 #if TARGET_API_MAC_CARBON
8308 FMFontFamilyIterator ffi
;
8309 FMFontFamilyInstanceIterator ffii
;
8311 Lisp_Object text_encoding_info_alist
;
8312 struct gcpro gcpro1
;
8314 text_encoding_info_alist
= create_text_encoding_info_alist ();
8317 #if USE_CG_TEXT_DRAWING
8318 init_cg_text_anti_aliasing_threshold ();
8320 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8321 text_encoding_info_alist
)))
8324 struct Lisp_Hash_Table
*h
;
8326 ItemCount nfonts
, i
;
8327 ATSUFontID
*font_ids
= NULL
;
8328 Lisp_Object prev_family
= Qnil
;
8332 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8333 make_float (DEFAULT_REHASH_SIZE
),
8334 make_float (DEFAULT_REHASH_THRESHOLD
),
8336 h
= XHASH_TABLE (atsu_font_id_hash
);
8338 err
= ATSUFontCount (&nfonts
);
8341 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8342 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8345 for (i
= 0; i
< nfonts
; i
++)
8349 family
= atsu_find_font_family_name (font_ids
[i
]);
8350 if (NILP (family
) || SREF (family
, 0) == '.')
8352 if (!NILP (Fequal (prev_family
, family
)))
8353 family
= prev_family
;
8355 j
= hash_lookup (h
, family
, &hash_code
);
8358 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8359 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8362 else if (EQ (prev_family
, family
))
8363 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8365 prev_family
= family
;
8372 /* Create a dummy instance iterator here to avoid creating and
8373 destroying it in the loop. */
8374 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8376 /* Create an iterator to enumerate the font families. */
8377 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8380 FMDisposeFontFamilyInstanceIterator (&ffii
);
8384 GCPRO1 (text_encoding_info_alist
);
8386 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8392 TextEncoding encoding
;
8393 TextEncodingBase sc
;
8394 Lisp_Object text_encoding_info
, family
;
8396 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8402 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8404 sc
= GetTextEncodingBase (encoding
);
8405 text_encoding_info
= assq_no_quit (make_number (sc
),
8406 text_encoding_info_alist
);
8407 if (NILP (text_encoding_info
))
8408 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8409 text_encoding_info_alist
);
8410 decode_mac_font_name (name
, sizeof (name
),
8411 XCAR (XCDR (text_encoding_info
)));
8412 family
= build_string (name
);
8413 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8415 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8416 fm_font_family_alist
);
8418 /* Point the instance iterator at the current font family. */
8419 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8422 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8425 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8427 if (size
> 0 || style
== normal
)
8428 for (; CONSP (rest
); rest
= XCDR (rest
))
8429 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8435 /* Dispose of the iterators. */
8436 FMDisposeFontFamilyIterator (&ffi
);
8437 FMDisposeFontFamilyInstanceIterator (&ffii
);
8438 #else /* !TARGET_API_MAC_CARBON */
8440 SInt16 fontnum
, old_fontnum
;
8441 int num_mac_fonts
= CountResources('FOND');
8443 Handle font_handle
, font_handle_2
;
8444 short id
, scriptcode
;
8447 struct FontAssoc
*fat
;
8448 struct AsscEntry
*assc_entry
;
8449 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8450 struct gcpro gcpro1
;
8452 GetPort (&port
); /* save the current font number used */
8453 old_fontnum
= port
->txFont
;
8455 text_encoding_info_alist
= create_text_encoding_info_alist ();
8457 GCPRO1 (text_encoding_info_alist
);
8459 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8461 font_handle
= GetIndResource ('FOND', i
);
8465 GetResInfo (font_handle
, &id
, &type
, name
);
8466 GetFNum (name
, &fontnum
);
8468 if (fontnum
== 0 || *name
== '.')
8472 scriptcode
= FontToScript (fontnum
);
8473 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8474 text_encoding_info_alist
);
8475 if (NILP (text_encoding_info
))
8476 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8477 text_encoding_info_alist
);
8478 decode_mac_font_name (name
, sizeof (name
),
8479 XCAR (XCDR (text_encoding_info
)));
8480 family
= build_string (name
);
8481 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8483 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8484 fm_font_family_alist
);
8487 HLock (font_handle
);
8489 if (GetResourceSizeOnDisk (font_handle
)
8490 >= sizeof (struct FamRec
))
8492 fat
= (struct FontAssoc
*) (*font_handle
8493 + sizeof (struct FamRec
));
8495 = (struct AsscEntry
*) (*font_handle
8496 + sizeof (struct FamRec
)
8497 + sizeof (struct FontAssoc
));
8499 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8501 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8503 for (; CONSP (rest
); rest
= XCDR (rest
))
8504 add_mac_font_name (name
, assc_entry
->fontSize
,
8505 assc_entry
->fontStyle
,
8506 SDATA (XCAR (rest
)));
8510 HUnlock (font_handle
);
8511 font_handle_2
= GetNextFOND (font_handle
);
8512 ReleaseResource (font_handle
);
8513 font_handle
= font_handle_2
;
8515 while (ResError () == noErr
&& font_handle
);
8520 TextFont (old_fontnum
);
8521 #endif /* !TARGET_API_MAC_CARBON */
8526 mac_clear_font_name_table ()
8530 for (i
= 0; i
< font_name_count
; i
++)
8531 xfree (font_name_table
[i
]);
8532 xfree (font_name_table
);
8533 font_name_table
= NULL
;
8534 font_name_table_size
= font_name_count
= 0;
8535 fm_font_family_alist
= Qnil
;
8539 enum xlfd_scalable_field_index
8541 XLFD_SCL_PIXEL_SIZE
,
8542 XLFD_SCL_POINT_SIZE
,
8547 static const int xlfd_scalable_fields
[] =
8556 mac_do_list_fonts (pattern
, maxnames
)
8557 const char *pattern
;
8561 Lisp_Object font_list
= Qnil
;
8562 struct xlfdpat
*pat
;
8565 int scl_val
[XLFD_SCL_LAST
], *val
;
8569 if (font_name_table
== NULL
) /* Initialize when first used. */
8570 init_font_name_table ();
8572 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8575 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8576 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8577 fonts are scaled according to the specified size. */
8580 field
= xlfd_scalable_fields
;
8588 if ('0' <= *ptr
&& *ptr
<= '9')
8590 *val
= *ptr
++ - '0';
8591 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8592 *val
= *val
* 10 + *ptr
++ - '0';
8599 ptr
= strchr (ptr
, '-');
8602 while (ptr
&& i
< 14);
8604 if (i
== 14 && ptr
== NULL
)
8606 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8607 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8608 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8609 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8611 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8612 scl_val
[XLFD_SCL_POINT_SIZE
] =
8613 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8614 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8616 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8617 scl_val
[XLFD_SCL_AVGWIDTH
] =
8618 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8619 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8623 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8625 pat
= xlfdpat_create (pattern
);
8629 exact
= xlfdpat_exact_p (pat
);
8631 for (i
= 0; i
< font_name_count
; i
++)
8633 if (xlfdpat_match (pat
, font_name_table
[i
]))
8635 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8636 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8639 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8640 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8642 int former_len
= ptr
- font_name_table
[i
];
8644 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8645 memcpy (scaled
, font_name_table
[i
], former_len
);
8646 sprintf (scaled
+ former_len
,
8647 "-%d-%d-72-72-m-%d-%s",
8648 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8649 scl_val
[XLFD_SCL_POINT_SIZE
],
8650 scl_val
[XLFD_SCL_AVGWIDTH
],
8651 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8653 if (xlfdpat_match (pat
, scaled
))
8655 font_list
= Fcons (build_string (scaled
), font_list
);
8657 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8665 xlfdpat_destroy (pat
);
8670 /* Return a list of names of available fonts matching PATTERN on frame F.
8672 Frame F null means we have not yet created any frame on Mac, and
8673 consult the first display in x_display_list. MAXNAMES sets a limit
8674 on how many fonts to match. */
8677 x_list_fonts (f
, pattern
, size
, maxnames
)
8679 Lisp_Object pattern
;
8682 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8683 struct mac_display_info
*dpyinfo
8684 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8686 xassert (size
<= 0);
8688 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8689 if (NILP (patterns
))
8690 patterns
= Fcons (pattern
, Qnil
);
8692 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8694 pattern
= XCAR (patterns
);
8696 if (!STRINGP (pattern
))
8699 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8700 key
= Fcons (pattern
, make_number (maxnames
));
8702 list
= Fassoc (key
, tem
);
8705 list
= Fcdr_safe (list
);
8706 /* We have a cashed list. Don't have to get the list again. */
8711 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8714 /* MAC_TODO: add code for matching outline fonts here */
8716 /* Now store the result in the cache. */
8717 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8718 Fcons (Fcons (key
, list
),
8719 XCAR (XCDR (dpyinfo
->name_list_element
))));
8722 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8731 /* Check that FONT is valid on frame F. It is if it can be found in F's
8735 x_check_font (f
, font
)
8740 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8742 xassert (font
!= NULL
);
8744 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8745 if (dpyinfo
->font_table
[i
].name
8746 && font
== dpyinfo
->font_table
[i
].font
)
8749 xassert (i
< dpyinfo
->n_fonts
);
8752 #endif /* GLYPH_DEBUG != 0 */
8754 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8755 Note: There are (broken) X fonts out there with invalid XFontStruct
8756 min_bounds contents. For example, handa@etl.go.jp reports that
8757 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8758 have font->min_bounds.width == 0. */
8761 x_font_min_bounds (font
, w
, h
)
8762 MacFontStruct
*font
;
8765 *h
= FONT_HEIGHT (font
);
8766 *w
= font
->min_bounds
.width
;
8770 /* Compute the smallest character width and smallest font height over
8771 all fonts available on frame F. Set the members smallest_char_width
8772 and smallest_font_height in F's x_display_info structure to
8773 the values computed. Value is non-zero if smallest_font_height or
8774 smallest_char_width become smaller than they were before. */
8777 x_compute_min_glyph_bounds (f
)
8781 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8782 MacFontStruct
*font
;
8783 int old_width
= dpyinfo
->smallest_char_width
;
8784 int old_height
= dpyinfo
->smallest_font_height
;
8786 dpyinfo
->smallest_font_height
= 100000;
8787 dpyinfo
->smallest_char_width
= 100000;
8789 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8790 if (dpyinfo
->font_table
[i
].name
)
8792 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8795 font
= (MacFontStruct
*) fontp
->font
;
8796 xassert (font
!= (MacFontStruct
*) ~0);
8797 x_font_min_bounds (font
, &w
, &h
);
8799 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8800 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8803 xassert (dpyinfo
->smallest_char_width
> 0
8804 && dpyinfo
->smallest_font_height
> 0);
8806 return (dpyinfo
->n_fonts
== 1
8807 || dpyinfo
->smallest_char_width
< old_width
8808 || dpyinfo
->smallest_font_height
< old_height
);
8812 /* Determine whether given string is a fully-specified XLFD: all 14
8813 fields are present, none is '*'. */
8816 is_fully_specified_xlfd (p
)
8825 for (i
= 0; i
< 13; i
++)
8827 q
= strchr (p
+ 1, '-');
8830 if (q
- p
== 2 && *(p
+ 1) == '*')
8835 if (strchr (p
+ 1, '-') != NULL
)
8838 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8845 /* mac_load_query_font creates and returns an internal representation
8846 for a font in a MacFontStruct struct. There is really no concept
8847 corresponding to "loading" a font on the Mac. But we check its
8848 existence and find the font number and all other information for it
8849 and store them in the returned MacFontStruct. */
8851 static MacFontStruct
*
8852 mac_load_query_font (f
, fontname
)
8862 static ATSUFontID font_id
;
8863 ATSUStyle mac_style
= NULL
;
8866 #if TARGET_API_MAC_CARBON
8867 TextEncoding encoding
;
8872 MacFontStruct
*font
;
8873 XCharStruct
*space_bounds
= NULL
, *pcm
;
8875 if (is_fully_specified_xlfd (fontname
))
8879 Lisp_Object matched_fonts
;
8881 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8882 if (NILP (matched_fonts
))
8884 name
= SDATA (XCAR (matched_fonts
));
8887 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8891 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8894 static const ATSUAttributeTag tags
[] =
8895 {kATSUFontTag
, kATSUSizeTag
,
8896 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8897 static const ByteCount sizes
[] =
8898 {sizeof (ATSUFontID
), sizeof (Fixed
),
8899 sizeof (Boolean
), sizeof (Boolean
)};
8900 static Fixed size_fixed
;
8901 static Boolean bold_p
, italic_p
;
8902 static const ATSUAttributeValuePtr values
[] =
8903 {&font_id
, &size_fixed
,
8904 &bold_p
, &italic_p
};
8905 static const ATSUFontFeatureType types
[] =
8906 {kAllTypographicFeaturesType
, kDiacriticsType
};
8907 static const ATSUFontFeatureSelector selectors
[] =
8908 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8911 font_id
= atsu_find_font_from_family_name (family
);
8912 if (font_id
== kATSUInvalidFontID
)
8914 size_fixed
= Long2Fix (size
);
8915 bold_p
= (fontface
& bold
) != 0;
8916 italic_p
= (fontface
& italic
) != 0;
8917 err
= ATSUCreateStyle (&mac_style
);
8920 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8924 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8925 tags
, sizes
, values
);
8928 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8931 scriptcode
= kTextEncodingMacUnicode
;
8936 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8940 fontnum
= XINT (XCDR (tmp
));
8941 #if TARGET_API_MAC_CARBON
8942 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8944 scriptcode
= GetTextEncodingBase (encoding
);
8946 scriptcode
= FontToScript (fontnum
);
8950 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8952 font
->mac_fontnum
= fontnum
;
8953 font
->mac_fontsize
= size
;
8954 font
->mac_fontface
= fontface
;
8955 font
->mac_scriptcode
= scriptcode
;
8957 font
->mac_style
= mac_style
;
8958 #if USE_CG_TEXT_DRAWING
8959 font
->cg_font
= NULL
;
8960 font
->cg_glyphs
= NULL
;
8964 /* Apple Japanese (SJIS) font is listed as both
8965 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8966 (Roman script) in init_font_name_table (). The latter should be
8967 treated as a one-byte font. */
8968 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8969 font
->mac_scriptcode
= smRoman
;
8971 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8974 if (font
->mac_style
)
8979 font
->min_byte1
= 0;
8980 font
->max_byte1
= 0xff;
8981 font
->min_char_or_byte2
= 0;
8982 font
->max_char_or_byte2
= 0xff;
8984 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8985 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8986 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8987 pcm_init (font
->bounds
.rows
[0], 0x100);
8989 #if USE_CG_TEXT_DRAWING
8993 ATSFontRef ats_font
;
8995 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8997 /* Use CG text drawing if italic/bold is not synthesized. */
8998 if (err
== noErr
&& style
== fontface
)
9000 ats_font
= FMGetATSFontRefFromFont (font_id
);
9001 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
9007 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
9008 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
9011 space_bounds
= font
->bounds
.rows
[0] + 0x20;
9012 err
= mac_query_char_extents (font
->mac_style
, 0x20,
9013 &font
->ascent
, &font
->descent
,
9015 #if USE_CG_TEXT_DRAWING
9016 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
9023 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
9025 mac_unload_font (&one_mac_display_info
, font
);
9029 pcm
= font
->bounds
.rows
[0];
9030 for (c
= 0x21; c
<= 0xff; c
++)
9033 /* Soft hyphen is not supported in ATSUI. */
9037 #if USE_CG_TEXT_DRAWING
9038 if (font
->cg_glyphs
)
9048 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
9049 pcm
? pcm
+ c
: NULL
,
9050 #if USE_CG_TEXT_DRAWING
9051 (font
->cg_glyphs
? font
->cg_glyphs
+ c
9058 #if USE_CG_TEXT_DRAWING
9059 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
9061 /* Don't use CG text drawing if font substitution occurs in
9062 ASCII or Latin-1 characters. */
9063 CGFontRelease (font
->cg_font
);
9064 font
->cg_font
= NULL
;
9065 xfree (font
->cg_glyphs
);
9066 font
->cg_glyphs
= NULL
;
9077 FontInfo the_fontinfo
;
9078 int is_two_byte_font
;
9081 mac_prepare_for_quickdraw (f
);
9083 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
9087 TextFace (fontface
);
9089 GetFontInfo (&the_fontinfo
);
9091 font
->ascent
= the_fontinfo
.ascent
;
9092 font
->descent
= the_fontinfo
.descent
;
9094 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
9095 || font
->mac_scriptcode
== smTradChinese
9096 || font
->mac_scriptcode
== smSimpChinese
9097 || font
->mac_scriptcode
== smKorean
);
9099 if (is_two_byte_font
)
9103 font
->min_byte1
= 0xa1;
9104 font
->max_byte1
= 0xfe;
9105 font
->min_char_or_byte2
= 0xa1;
9106 font
->max_char_or_byte2
= 0xfe;
9108 /* Use the width of an "ideographic space" of that font
9109 because the_fontinfo.widMax returns the wrong width for
9111 switch (font
->mac_scriptcode
)
9114 font
->min_byte1
= 0x81;
9115 font
->max_byte1
= 0xfc;
9116 font
->min_char_or_byte2
= 0x40;
9117 font
->max_char_or_byte2
= 0xfc;
9118 char_width
= StringWidth("\p\x81\x40");
9121 font
->min_char_or_byte2
= 0x40;
9122 char_width
= StringWidth("\p\xa1\x40");
9125 char_width
= StringWidth("\p\xa1\xa1");
9128 char_width
= StringWidth("\p\xa1\xa1");
9132 font
->bounds
.per_char
= NULL
;
9134 if (fontface
& italic
)
9135 font
->max_bounds
.rbearing
= char_width
+ 1;
9137 font
->max_bounds
.rbearing
= char_width
;
9138 font
->max_bounds
.lbearing
= 0;
9139 font
->max_bounds
.width
= char_width
;
9140 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
9141 font
->max_bounds
.descent
= the_fontinfo
.descent
;
9143 font
->min_bounds
= font
->max_bounds
;
9149 font
->min_byte1
= font
->max_byte1
= 0;
9150 font
->min_char_or_byte2
= 0x20;
9151 font
->max_char_or_byte2
= 0xff;
9153 font
->bounds
.per_char
=
9154 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9155 bzero (font
->bounds
.per_char
,
9156 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9158 space_bounds
= font
->bounds
.per_char
;
9159 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9160 &font
->descent
, space_bounds
, NULL
);
9161 if (err
!= noErr
|| space_bounds
->width
<= 0)
9163 mac_unload_font (&one_mac_display_info
, font
);
9167 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9168 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9176 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9177 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9180 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9182 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9184 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9186 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9188 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9191 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9193 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9195 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9197 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9199 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9204 font
->mac_style
== NULL
&&
9206 font
->max_bounds
.width
== font
->min_bounds
.width
9207 && font
->min_bounds
.lbearing
>= 0
9208 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9210 /* Fixed width and no overhangs. */
9211 xfree (font
->bounds
.per_char
);
9212 font
->bounds
.per_char
= NULL
;
9216 #if !defined (MAC_OS8) || USE_ATSUI
9217 /* AppKit and WebKit do some adjustment to the heights of Courier,
9218 Helvetica, and Times. This only works on the environments where
9219 srcCopy text transfer mode is never used. */
9221 #ifdef MAC_OS8 /* implies USE_ATSUI */
9224 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9225 || strcmp (family
, "times") == 0))
9226 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9234 mac_unload_font (dpyinfo
, font
)
9235 struct mac_display_info
*dpyinfo
;
9238 xfree (font
->full_name
);
9240 if (font
->mac_style
)
9244 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9245 if (font
->bounds
.rows
[i
])
9246 xfree (font
->bounds
.rows
[i
]);
9247 xfree (font
->bounds
.rows
);
9248 ATSUDisposeStyle (font
->mac_style
);
9252 if (font
->bounds
.per_char
)
9253 xfree (font
->bounds
.per_char
);
9254 #if USE_CG_TEXT_DRAWING
9256 CGFontRelease (font
->cg_font
);
9257 if (font
->cg_glyphs
)
9258 xfree (font
->cg_glyphs
);
9264 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9265 pointer to the structure font_info while allocating it dynamically.
9266 If SIZE is 0, load any size of font.
9267 If loading is failed, return NULL. */
9270 x_load_font (f
, fontname
, size
)
9272 register char *fontname
;
9275 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9276 Lisp_Object font_names
;
9278 /* Get a list of all the fonts that match this name. Once we
9279 have a list of matching fonts, we compare them against the fonts
9280 we already have by comparing names. */
9281 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9283 if (!NILP (font_names
))
9288 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9289 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9290 if (dpyinfo
->font_table
[i
].name
9291 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9292 SDATA (XCAR (tail
)))
9293 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9294 SDATA (XCAR (tail
)))))
9295 return (dpyinfo
->font_table
+ i
);
9300 /* Load the font and add it to the table. */
9302 struct MacFontStruct
*font
;
9303 struct font_info
*fontp
;
9306 fontname
= (char *) SDATA (XCAR (font_names
));
9309 font
= mac_load_query_font (f
, fontname
);
9314 /* Find a free slot in the font table. */
9315 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9316 if (dpyinfo
->font_table
[i
].name
== NULL
)
9319 /* If no free slot found, maybe enlarge the font table. */
9320 if (i
== dpyinfo
->n_fonts
9321 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9324 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9325 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9327 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9330 fontp
= dpyinfo
->font_table
+ i
;
9331 if (i
== dpyinfo
->n_fonts
)
9334 /* Now fill in the slots of *FONTP. */
9336 bzero (fontp
, sizeof (*fontp
));
9338 fontp
->font_idx
= i
;
9339 fontp
->charset
= -1; /* fs_load_font sets it. */
9340 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9341 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9343 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9345 /* Fixed width font. */
9346 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9353 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9354 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9356 fontp
->space_width
= pcm
->width
;
9358 fontp
->space_width
= FONT_WIDTH (font
);
9362 int width
= pcm
->width
;
9363 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9364 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9365 width
+= pcm
->width
;
9366 fontp
->average_width
= width
/ 95;
9369 fontp
->average_width
= FONT_WIDTH (font
);
9372 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9373 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9375 fontp
->size
= font
->max_bounds
.width
;
9376 fontp
->height
= FONT_HEIGHT (font
);
9378 /* For some font, ascent and descent in max_bounds field is
9379 larger than the above value. */
9380 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9381 if (max_height
> fontp
->height
)
9382 fontp
->height
= max_height
;
9385 /* MAC_TODO: The script encoding is irrelevant in unicode? */
9386 /* The slot `encoding' specifies how to map a character
9387 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9388 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9389 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9390 2:0xA020..0xFF7F). For the moment, we don't know which charset
9391 uses this font. So, we set information in fontp->encoding_type
9392 which is never used by any charset. If mapping can't be
9393 decided, set FONT_ENCODING_NOT_DECIDED. */
9394 if (font
->mac_scriptcode
== smJapanese
)
9395 fontp
->encoding_type
= 4;
9398 fontp
->encoding_type
9399 = (font
->max_byte1
== 0
9401 ? (font
->min_char_or_byte2
< 0x80
9402 ? (font
->max_char_or_byte2
< 0x80
9403 ? 0 /* 0x20..0x7F */
9404 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9405 : 1) /* 0xA0..0xFF */
9407 : (font
->min_byte1
< 0x80
9408 ? (font
->max_byte1
< 0x80
9409 ? (font
->min_char_or_byte2
< 0x80
9410 ? (font
->max_char_or_byte2
< 0x80
9411 ? 0 /* 0x2020..0x7F7F */
9412 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9413 : 3) /* 0x20A0..0x7FFF */
9414 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9415 : (font
->min_char_or_byte2
< 0x80
9416 ? (font
->max_char_or_byte2
< 0x80
9417 ? 2 /* 0xA020..0xFF7F */
9418 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9419 : 1))); /* 0xA0A0..0xFFFF */
9422 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9423 fontp
->baseline_offset
9424 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9425 ? (long) value
: 0);
9426 fontp
->relative_compose
9427 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9428 ? (long) value
: 0);
9429 fontp
->default_ascent
9430 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9431 ? (long) value
: 0);
9433 fontp
->baseline_offset
= 0;
9434 fontp
->relative_compose
= 0;
9435 fontp
->default_ascent
= 0;
9438 /* Set global flag fonts_changed_p to non-zero if the font loaded
9439 has a character with a smaller width than any other character
9440 before, or if the font loaded has a smaller height than any
9441 other font loaded before. If this happens, it will make a
9442 glyph matrix reallocation necessary. */
9443 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9450 /* Return a pointer to struct font_info of a font named FONTNAME for
9451 frame F. If no such font is loaded, return NULL. */
9454 x_query_font (f
, fontname
)
9456 register char *fontname
;
9458 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9461 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9462 if (dpyinfo
->font_table
[i
].name
9463 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9464 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9465 return (dpyinfo
->font_table
+ i
);
9470 /* Find a CCL program for a font specified by FONTP, and set the member
9471 `encoder' of the structure. */
9474 x_find_ccl_program (fontp
)
9475 struct font_info
*fontp
;
9477 Lisp_Object list
, elt
;
9479 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9483 && STRINGP (XCAR (elt
))
9484 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9490 struct ccl_program
*ccl
9491 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9493 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9496 fontp
->font_encoder
= ccl
;
9500 #if USE_MAC_FONT_PANEL
9501 /* Whether Font Panel has been shown before. The first call to font
9502 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9503 slow. This variable is used for deferring such a call as much as
9505 static int font_panel_shown_p
= 0;
9507 extern Lisp_Object Qfont
;
9508 static Lisp_Object Qpanel_closed
, Qselection
;
9510 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9514 const EventParamName
*,
9515 const EventParamType
*));
9518 mac_font_panel_visible_p ()
9520 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9523 static pascal OSStatus
9524 mac_handle_font_event (next_handler
, event
, data
)
9525 EventHandlerCallRef next_handler
;
9529 OSStatus result
, err
;
9532 const EventParamName
*names
;
9533 const EventParamType
*types
;
9534 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9535 kEventParamATSUFontSize
,
9536 kEventParamFMFontFamily
,
9537 kEventParamFMFontStyle
,
9538 kEventParamFMFontSize
,
9539 kEventParamFontColor
};
9540 static const EventParamType types_sel
[] = {typeATSUFontID
,
9547 result
= CallNextEventHandler (next_handler
, event
);
9548 if (result
!= eventNotHandledErr
)
9551 switch (GetEventKind (event
))
9553 case kEventFontPanelClosed
:
9554 id_key
= Qpanel_closed
;
9560 case kEventFontSelection
:
9561 id_key
= Qselection
;
9562 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9568 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9578 mac_show_hide_font_panel ()
9580 if (!font_panel_shown_p
)
9584 static const EventTypeSpec specs
[] =
9585 {{kEventClassFont
, kEventFontPanelClosed
},
9586 {kEventClassFont
, kEventFontSelection
}};
9588 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9589 GetEventTypeCount (specs
),
9594 font_panel_shown_p
= 1;
9597 return FPShowHideFontPanel ();
9601 mac_set_font_info_for_selection (f
, face_id
, c
)
9606 EventTargetRef target
= NULL
;
9607 XFontStruct
*font
= NULL
;
9609 if (!mac_font_panel_visible_p ())
9614 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9616 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9620 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9621 face
= FACE_FROM_ID (f
, face_id
);
9627 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9630 if (font
->mac_fontnum
!= -1)
9632 FontSelectionQDStyle qd_style
;
9634 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9635 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9636 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9637 qd_style
.size
= font
->mac_fontsize
;
9638 qd_style
.hasColor
= false;
9640 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9641 1, &qd_style
, target
);
9644 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9645 1, &font
->mac_style
, target
);
9653 /* The Mac Event loop code */
9655 #if !TARGET_API_MAC_CARBON
9657 #include <Quickdraw.h>
9658 #include <Balloons.h>
9659 #include <Devices.h>
9661 #include <Gestalt.h>
9663 #include <Processes.h>
9665 #include <ToolUtils.h>
9666 #include <TextUtils.h>
9667 #include <Dialogs.h>
9670 #include <Resources.h>
9675 #endif /* ! TARGET_API_MAC_CARBON */
9680 #define DEFAULT_NUM_COLS 80
9682 #define MIN_DOC_SIZE 64
9683 #define MAX_DOC_SIZE 32767
9685 #define EXTRA_STACK_ALLOC (256 * 1024)
9687 #define ARGV_STRING_LIST_ID 129
9688 #define ABOUT_ALERT_ID 128
9689 #define RAM_TOO_LARGE_ALERT_ID 129
9691 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9692 Lisp_Object Qreverse
;
9695 /* Modifier associated with the control key, or nil to ignore. */
9696 Lisp_Object Vmac_control_modifier
;
9698 /* Modifier associated with the option key, or nil to ignore. */
9699 Lisp_Object Vmac_option_modifier
;
9701 /* Modifier associated with the command key, or nil to ignore. */
9702 Lisp_Object Vmac_command_modifier
;
9704 /* Modifier associated with the function key, or nil to ignore. */
9705 Lisp_Object Vmac_function_modifier
;
9707 /* True if the option and command modifiers should be used to emulate
9708 a three button mouse */
9709 Lisp_Object Vmac_emulate_three_button_mouse
;
9711 #if TARGET_API_MAC_CARBON
9712 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9713 mouse-2, instead of mouse-3. */
9714 int mac_wheel_button_is_mouse_2
;
9716 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9717 for processing before Emacs sees it. */
9718 int mac_pass_command_to_system
;
9720 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9721 for processing before Emacs sees it. */
9722 int mac_pass_control_to_system
;
9725 /* Points to the variable `inev' in the function XTread_socket. It is
9726 used for passing an input event to the function back from
9727 Carbon/Apple event handlers. */
9728 static struct input_event
*read_socket_inev
= NULL
;
9730 /* Whether or not the screen configuration has changed. */
9731 static int mac_screen_config_changed
= 0;
9733 Point saved_menu_event_location
;
9736 #if TARGET_API_MAC_CARBON
9737 static Lisp_Object Qhi_command
;
9739 extern Lisp_Object Qwindow
;
9740 static Lisp_Object Qtoolbar_switch_mode
;
9743 static TSMDocumentID tsm_document_id
;
9744 Lisp_Object Qtext_input
;
9745 Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9746 Lisp_Object Vmac_ts_active_input_overlay
, Vmac_ts_active_input_buf
;
9747 extern Lisp_Object Qbefore_string
;
9748 static Lisp_Object Vmac_ts_script_language_on_focus
;
9749 static Lisp_Object saved_ts_script_language_on_focus
;
9750 static ScriptLanguageRecord saved_ts_language
;
9751 static Component saved_ts_component
;
9753 #endif /* TARGET_API_MAC_CARBON */
9754 extern int mac_ready_for_apple_events
;
9755 extern Lisp_Object Qundefined
;
9756 extern void init_apple_event_handler
P_ ((void));
9757 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9758 Lisp_Object
*, Lisp_Object
*,
9760 extern OSErr init_coercion_handler
P_ ((void));
9763 extern OSErr install_drag_handler
P_ ((WindowRef
));
9764 extern void remove_drag_handler
P_ ((WindowRef
));
9766 #if TARGET_API_MAC_CARBON
9767 /* Showing help echo string during menu tracking */
9768 extern OSStatus install_menu_target_item_handler
P_ ((void));
9771 extern OSStatus
install_service_handler ();
9772 Lisp_Object Qservice
, Qpaste
, Qperform
;
9773 Lisp_Object Qmouse_drag_overlay
;
9777 extern void init_emacs_passwd_dir ();
9778 extern int emacs_main (int, char **, char **);
9780 extern void initialize_applescript();
9781 extern void terminate_applescript();
9783 /* Table for translating Mac keycode to X keysym values. Contributed
9785 Mapping for special keys is now identical to that in Apple X11
9786 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9787 on the right of the Cmd key on laptops, and fn + `enter' (->
9789 static const unsigned char keycode_to_xkeysym_table
[] = {
9790 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9791 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9792 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9794 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9795 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9796 /*0x38*/ 0, 0, 0, 0,
9797 /*0x3C*/ 0, 0, 0, 0,
9799 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9800 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9801 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9802 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9804 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9805 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9806 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9807 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9809 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9810 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9811 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9812 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9814 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9815 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9816 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9817 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9821 /* Table for translating Mac keycode with the laptop `fn' key to that
9822 without it. Destination symbols in comments are keys on US
9823 keyboard, and they may not be the same on other types of keyboards.
9824 If the destination is identical to the source (f1 ... f12), it
9825 doesn't map `fn' key to a modifier. */
9826 static const unsigned char fn_keycode_to_keycode_table
[] = {
9827 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9828 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9829 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9831 /*0x30*/ 0, 0, 0, 0,
9832 /*0x34*/ 0, 0, 0, 0,
9833 /*0x38*/ 0, 0, 0, 0,
9834 /*0x3C*/ 0, 0, 0, 0,
9836 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9837 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9838 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9839 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9841 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9842 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9843 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9844 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9846 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9847 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9848 /*0x68*/ 0, 0, 0, 0,
9849 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9851 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9852 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9853 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9856 #endif /* MAC_OSX */
9859 #if TARGET_API_MAC_CARBON
9860 mac_to_emacs_modifiers (UInt32 mods
)
9862 mac_to_emacs_modifiers (EventModifiers mods
)
9865 unsigned int result
= 0;
9866 if (mods
& shiftKey
)
9867 result
|= shift_modifier
;
9869 /* Deactivated to simplify configuration:
9870 if Vmac_option_modifier is non-NIL, we fully process the Option
9871 key. Otherwise, we only process it if an additional Ctrl or Command
9872 is pressed. That way the system may convert the character to a
9874 if ((mods & optionKey) &&
9875 (( !NILP(Vmac_option_modifier) ||
9876 ((mods & cmdKey) || (mods & controlKey))))) */
9878 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9879 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9881 result
|= XUINT(val
);
9883 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9884 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9886 result
|= XUINT(val
);
9888 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9889 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9891 result
|= XUINT(val
);
9895 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9896 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9898 result
|= XUINT(val
);
9906 mac_mapped_modifiers (modifiers
)
9909 UInt32 mapped_modifiers_all
=
9910 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9911 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9912 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9915 mapped_modifiers_all
|=
9916 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9919 return mapped_modifiers_all
& modifiers
;
9923 mac_get_emulated_btn ( UInt32 modifiers
)
9926 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9927 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9928 if (modifiers
& cmdKey
)
9929 result
= cmdIs3
? 2 : 1;
9930 else if (modifiers
& optionKey
)
9931 result
= cmdIs3
? 1 : 2;
9938 mac_get_selected_range (w
, range
)
9942 Lisp_Object overlay
= find_symbol_value (Qmouse_drag_overlay
);
9943 struct buffer
*b
= XBUFFER (w
->buffer
);
9944 int begv
= BUF_BEGV (b
), zv
= BUF_ZV (b
);
9947 if (OVERLAYP (overlay
)
9948 && EQ (Foverlay_buffer (overlay
), w
->buffer
)
9949 && (start
= XINT (Foverlay_start (overlay
)),
9950 end
= XINT (Foverlay_end (overlay
)),
9955 if (w
== XWINDOW (selected_window
) && b
== current_buffer
)
9958 start
= marker_position (w
->pointm
);
9960 if (NILP (Vtransient_mark_mode
) || NILP (b
->mark_active
))
9964 int mark_pos
= marker_position (b
->mark
);
9966 if (start
<= mark_pos
)
9980 else if (start
> zv
)
9989 range
->location
= start
- begv
;
9990 range
->length
= end
- start
;
9993 /* Store the text of the buffer BUF from START to END as Unicode
9994 characters in CHARACTERS. Return non-zero if successful. */
9997 mac_store_buffer_text_to_unicode_chars (buf
, start
, end
, characters
)
10000 UniChar
*characters
;
10002 int start_byte
, end_byte
, char_count
, byte_count
;
10003 struct coding_system coding
;
10004 unsigned char *dst
= (unsigned char *) characters
;
10006 start_byte
= buf_charpos_to_bytepos (buf
, start
);
10007 end_byte
= buf_charpos_to_bytepos (buf
, end
);
10008 char_count
= end
- start
;
10009 byte_count
= end_byte
- start_byte
;
10011 if (setup_coding_system (
10012 #ifdef WORDS_BIG_ENDIAN
10013 intern ("utf-16be")
10015 intern ("utf-16le")
10020 coding
.src_multibyte
= !NILP (buf
->enable_multibyte_characters
);
10021 coding
.dst_multibyte
= 0;
10022 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
10023 coding
.composing
= COMPOSITION_DISABLED
;
10025 if (BUF_GPT_BYTE (buf
) <= start_byte
|| end_byte
<= BUF_GPT_BYTE (buf
))
10026 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
10027 byte_count
, char_count
* sizeof (UniChar
));
10030 int first_byte_count
= BUF_GPT_BYTE (buf
) - start_byte
;
10032 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
10033 first_byte_count
, char_count
* sizeof (UniChar
));
10034 if (coding
.result
== CODING_FINISH_NORMAL
)
10035 encode_coding (&coding
,
10036 BUF_BYTE_ADDRESS (buf
, start_byte
+ first_byte_count
),
10037 dst
+ coding
.produced
,
10038 byte_count
- first_byte_count
,
10039 char_count
* sizeof (UniChar
) - coding
.produced
);
10042 if (coding
.result
!= CODING_FINISH_NORMAL
)
10049 mac_ax_selected_text_range (f
, range
)
10053 mac_get_selected_range (XWINDOW (f
->selected_window
), range
);
10056 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
10058 mac_ax_number_of_characters (f
)
10061 struct buffer
*b
= XBUFFER (XWINDOW (f
->selected_window
)->buffer
);
10063 return BUF_ZV (b
) - BUF_BEGV (b
);
10070 mac_restore_keyboard_input_source ()
10072 OSStatus err
= noErr
;
10073 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10075 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10076 && EQ (saved_ts_script_language_on_focus
, Qt
))
10077 slptr
= &saved_ts_language
;
10078 else if (CONSP (Vmac_ts_script_language_on_focus
)
10079 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10080 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10081 && CONSP (saved_ts_script_language_on_focus
)
10082 && EQ (XCAR (saved_ts_script_language_on_focus
),
10083 XCAR (Vmac_ts_script_language_on_focus
))
10084 && EQ (XCDR (saved_ts_script_language_on_focus
),
10085 XCDR (Vmac_ts_script_language_on_focus
)))
10087 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10088 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10094 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10095 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10096 kKeyboardInputMethodClass
);
10098 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10101 err
= SetTextServiceLanguage (slptr
);
10103 /* Seems to be needed on Mac OS X 10.2. */
10105 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10112 mac_save_keyboard_input_source ()
10115 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10117 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10119 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10121 err
= GetTextServiceLanguage (&saved_ts_language
);
10123 slptr
= &saved_ts_language
;
10125 else if (CONSP (Vmac_ts_script_language_on_focus
)
10126 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10127 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10129 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10130 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10136 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10137 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10138 kKeyboardInputMethodClass
);
10140 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10146 #if TARGET_API_MAC_CARBON
10147 /***** Code to handle C-g testing *****/
10148 extern int quit_char
;
10149 extern int make_ctrl_char
P_ ((int));
10152 mac_quit_char_key_p (modifiers
, key_code
)
10153 UInt32 modifiers
, key_code
;
10156 unsigned long some_state
= 0;
10157 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10158 int c
, emacs_modifiers
;
10160 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
10161 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
10162 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
10163 if (char_code
& ~0xff)
10166 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
10167 if (emacs_modifiers
& ctrl_modifier
)
10168 c
= make_ctrl_char (char_code
);
10170 c
|= (emacs_modifiers
10171 & (meta_modifier
| alt_modifier
10172 | hyper_modifier
| super_modifier
));
10174 return c
== quit_char
;
10178 #if TARGET_API_MAC_CARBON
10179 /* Obtains the event modifiers from the event ref and then calls
10180 mac_to_emacs_modifiers. */
10182 mac_event_to_emacs_modifiers (EventRef eventRef
)
10184 UInt32 mods
= 0, class;
10186 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
10187 sizeof (UInt32
), NULL
, &mods
);
10188 class = GetEventClass (eventRef
);
10189 if (!NILP (Vmac_emulate_three_button_mouse
) &&
10190 (class == kEventClassMouse
|| class == kEventClassCommand
))
10192 mods
&= ~(optionKey
| cmdKey
);
10194 return mac_to_emacs_modifiers (mods
);
10197 /* Given an event ref, return the code to use for the mouse button
10198 code in the emacs input_event. */
10200 mac_get_mouse_btn (EventRef ref
)
10202 EventMouseButton result
= kEventMouseButtonPrimary
;
10203 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
10204 sizeof (EventMouseButton
), NULL
, &result
);
10207 case kEventMouseButtonPrimary
:
10208 if (NILP (Vmac_emulate_three_button_mouse
))
10212 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
10213 sizeof (UInt32
), NULL
, &mods
);
10214 return mac_get_emulated_btn(mods
);
10216 case kEventMouseButtonSecondary
:
10217 return mac_wheel_button_is_mouse_2
? 2 : 1;
10218 case kEventMouseButtonTertiary
:
10219 case 4: /* 4 is the number for the mouse wheel button */
10220 return mac_wheel_button_is_mouse_2
? 1 : 2;
10226 /* Normally, ConvertEventRefToEventRecord will correctly handle all
10227 events. However the click of the mouse wheel is not converted to a
10228 mouseDown or mouseUp event. Likewise for dead key events. This
10229 calls ConvertEventRefToEventRecord, but then checks to see if it is
10230 a mouse up/down, or a dead key Carbon event that has not been
10231 converted, and if so, converts it by hand (to be picked up in the
10232 XTread_socket loop). */
10233 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
10236 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
10242 switch (GetEventClass (eventRef
))
10244 case kEventClassMouse
:
10245 switch (GetEventKind (eventRef
))
10247 case kEventMouseDown
:
10248 eventRec
->what
= mouseDown
;
10252 case kEventMouseUp
:
10253 eventRec
->what
= mouseUp
;
10262 case kEventClassKeyboard
:
10263 switch (GetEventKind (eventRef
))
10265 case kEventRawKeyDown
:
10267 goto keystroke_common
;
10268 case kEventRawKeyRepeat
:
10270 goto keystroke_common
;
10271 case kEventRawKeyUp
:
10275 unsigned char char_codes
;
10278 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
10279 typeChar
, NULL
, sizeof (char),
10280 NULL
, &char_codes
);
10282 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
10283 typeUInt32
, NULL
, sizeof (UInt32
),
10287 eventRec
->what
= action
;
10288 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
10305 /* Need where and when. */
10308 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
10309 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
10310 /* Use two step process because new event modifiers are 32-bit
10311 and old are 16-bit. Currently, only loss is NumLock & Fn. */
10312 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
10313 NULL
, sizeof (UInt32
), NULL
, &mods
);
10314 eventRec
->modifiers
= mods
;
10316 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
10326 do_get_menus (void)
10328 Handle menubar_handle
;
10331 menubar_handle
= GetNewMBar (128);
10332 if(menubar_handle
== NULL
)
10334 SetMenuBar (menubar_handle
);
10337 #if !TARGET_API_MAC_CARBON
10338 menu
= GetMenuRef (M_APPLE
);
10340 AppendResMenu (menu
, 'DRVR');
10348 do_init_managers (void)
10350 #if !TARGET_API_MAC_CARBON
10351 InitGraf (&qd
.thePort
);
10353 FlushEvents (everyEvent
, 0);
10357 InitDialogs (NULL
);
10358 #endif /* !TARGET_API_MAC_CARBON */
10361 #if !TARGET_API_MAC_CARBON
10362 /* set up some extra stack space for use by emacs */
10363 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10365 /* MaxApplZone must be called for AppleScript to execute more
10366 complicated scripts */
10369 #endif /* !TARGET_API_MAC_CARBON */
10373 do_check_ram_size (void)
10375 SInt32 physical_ram_size
, logical_ram_size
;
10377 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10378 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10379 || physical_ram_size
> (1 << VALBITS
)
10380 || logical_ram_size
> (1 << VALBITS
))
10382 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10386 #endif /* MAC_OS8 */
10389 do_window_update (WindowRef win
)
10391 struct frame
*f
= mac_window_to_frame (win
);
10395 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10397 if (win
!= tip_window
)
10399 if (f
->async_visible
== 0)
10401 /* Update events may occur when a frame gets iconified. */
10403 f
->async_visible
= 1;
10404 f
->async_iconified
= 0;
10405 SET_FRAME_GARBAGED (f
);
10411 #if TARGET_API_MAC_CARBON
10412 RgnHandle region
= NewRgn ();
10414 GetPortVisibleRegion (GetWindowPort (win
), region
);
10415 GetRegionBounds (region
, &r
);
10416 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10418 mac_prepare_for_quickdraw (f
);
10420 UpdateControls (win
, region
);
10421 DisposeRgn (region
);
10423 r
= (*win
->visRgn
)->rgnBBox
;
10424 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10425 UpdateControls (win
, win
->visRgn
);
10434 is_emacs_window (WindowRef win
)
10436 Lisp_Object tail
, frame
;
10441 FOR_EACH_FRAME (tail
, frame
)
10442 if (FRAME_MAC_P (XFRAME (frame
)))
10443 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10454 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10456 err
= ActivateTSMDocument (tsm_document_id
);
10460 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10461 && EQ (saved_ts_script_language_on_focus
, Qt
))
10462 slptr
= &saved_ts_language
;
10463 else if (CONSP (Vmac_ts_script_language_on_focus
)
10464 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10465 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10466 && CONSP (saved_ts_script_language_on_focus
)
10467 && EQ (XCAR (saved_ts_script_language_on_focus
),
10468 XCAR (Vmac_ts_script_language_on_focus
))
10469 && EQ (XCDR (saved_ts_script_language_on_focus
),
10470 XCDR (Vmac_ts_script_language_on_focus
)))
10472 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10473 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10480 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10481 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10482 kKeyboardInputMethodClass
);
10484 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10487 err
= SetTextServiceLanguage (slptr
);
10489 /* Seems to be needed on Mac OS X 10.2. */
10491 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10501 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10503 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10505 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10507 err
= GetTextServiceLanguage (&saved_ts_language
);
10509 slptr
= &saved_ts_language
;
10511 else if (CONSP (Vmac_ts_script_language_on_focus
)
10512 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10513 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10515 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10516 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10522 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10523 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10524 kKeyboardInputMethodClass
);
10526 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10530 err
= DeactivateTSMDocument (tsm_document_id
);
10536 #if !TARGET_API_MAC_CARBON
10538 do_apple_menu (SInt16 menu_item
)
10541 SInt16 da_driver_refnum
;
10543 if (menu_item
== I_ABOUT
)
10544 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10547 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10548 da_driver_refnum
= OpenDeskAcc (item_name
);
10551 #endif /* !TARGET_API_MAC_CARBON */
10553 /* Handle drags in size box. Based on code contributed by Ben
10554 Mesander and IM - Window Manager A. */
10557 do_grow_window (w
, e
)
10559 const EventRecord
*e
;
10562 int rows
, columns
, width
, height
;
10563 struct frame
*f
= mac_window_to_frame (w
);
10564 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10565 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10566 #if TARGET_API_MAC_CARBON
10572 if (size_hints
->flags
& PMinSize
)
10574 min_width
= size_hints
->min_width
;
10575 min_height
= size_hints
->min_height
;
10577 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10579 #if TARGET_API_MAC_CARBON
10580 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10582 height
= new_rect
.bottom
- new_rect
.top
;
10583 width
= new_rect
.right
- new_rect
.left
;
10585 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10586 /* see if it really changed size */
10587 if (grow_size
== 0)
10589 height
= HiWord (grow_size
);
10590 width
= LoWord (grow_size
);
10593 if (width
!= FRAME_PIXEL_WIDTH (f
)
10594 || height
!= FRAME_PIXEL_HEIGHT (f
))
10596 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10597 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10599 x_set_window_size (f
, 0, columns
, rows
);
10604 #if TARGET_API_MAC_CARBON
10606 mac_get_ideal_size (f
)
10609 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10610 WindowRef w
= FRAME_MAC_WINDOW (f
);
10612 Rect standard_rect
;
10613 int height
, width
, columns
, rows
;
10615 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10616 ideal_size
.v
= dpyinfo
->height
;
10617 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10618 /* Adjust the standard size according to character boundaries. */
10619 width
= standard_rect
.right
- standard_rect
.left
;
10620 height
= standard_rect
.bottom
- standard_rect
.top
;
10621 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10622 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10623 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10624 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10630 /* Handle clicks in zoom box. Calculation of "standard state" based
10631 on code in IM - Window Manager A and code contributed by Ben
10632 Mesander. The standard state of an Emacs window is 80-characters
10633 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10636 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10638 Rect zoom_rect
, port_rect
;
10640 struct frame
*f
= mac_window_to_frame (w
);
10641 #if TARGET_API_MAC_CARBON
10642 Point ideal_size
= mac_get_ideal_size (f
);
10644 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10645 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10646 && port_rect
.left
== zoom_rect
.left
10647 && port_rect
.top
== zoom_rect
.top
)
10648 zoom_in_or_out
= inZoomIn
;
10650 zoom_in_or_out
= inZoomOut
;
10653 mac_clear_window (f
);
10655 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10656 #else /* not TARGET_API_MAC_CARBON */
10659 int w_title_height
, rows
;
10660 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10662 GetPort (&save_port
);
10664 SetPortWindowPort (w
);
10666 /* Clear window to avoid flicker. */
10667 EraseRect (&(w
->portRect
));
10668 if (zoom_in_or_out
== inZoomOut
)
10670 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10671 LocalToGlobal (&top_left
);
10673 /* calculate height of window's title bar */
10674 w_title_height
= top_left
.v
- 1
10675 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10677 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10678 zoom_rect
= qd
.screenBits
.bounds
;
10679 zoom_rect
.top
+= w_title_height
;
10680 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10682 zoom_rect
.right
= zoom_rect
.left
10683 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10685 /* Adjust the standard size according to character boundaries. */
10686 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10688 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10690 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10694 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10696 SetPort (save_port
);
10697 #endif /* not TARGET_API_MAC_CARBON */
10699 #if !TARGET_API_MAC_CARBON
10700 /* retrieve window size and update application values */
10701 port_rect
= w
->portRect
;
10702 height
= port_rect
.bottom
- port_rect
.top
;
10703 width
= port_rect
.right
- port_rect
.left
;
10705 mac_handle_size_change (f
, width
, height
);
10706 mac_handle_origin_change (f
);
10711 mac_set_unicode_keystroke_event (code
, buf
)
10713 struct input_event
*buf
;
10715 int charset_id
, c1
, c2
;
10719 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10722 else if (code
< 0x100)
10725 charset_id
= CHARSET_8_BIT_CONTROL
;
10727 charset_id
= charset_latin_iso8859_1
;
10728 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10729 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10734 charset_id
= charset_mule_unicode_0100_24ff
,
10736 else if (code
< 0x33FF)
10737 charset_id
= charset_mule_unicode_2500_33ff
,
10739 else if (code
>= 0xE000)
10740 charset_id
= charset_mule_unicode_e000_ffff
,
10742 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10743 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10744 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10749 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10751 unsigned char char_code
;
10752 UInt32 key_code
, modifiers
;
10753 unsigned long timestamp
;
10754 struct input_event
*buf
;
10756 static SInt16 last_key_script
= -1;
10757 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10758 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10761 if (mapped_modifiers
& kEventKeyModifierFnMask
10762 && key_code
<= 0x7f
10763 && fn_keycode_to_keycode_table
[key_code
])
10764 key_code
= fn_keycode_to_keycode_table
[key_code
];
10767 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10769 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10770 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10772 if (modifiers
& kEventKeyModifierFnMask
10773 && key_code
<= 0x7f
10774 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10775 modifiers
&= ~kEventKeyModifierFnMask
;
10778 else if (mapped_modifiers
)
10780 /* translate the keycode back to determine the original key */
10782 UCKeyboardLayout
*uchr_ptr
= NULL
;
10783 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10785 KeyboardLayoutRef layout
;
10787 err
= KLGetCurrentKeyboardLayout (&layout
);
10789 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10790 (const void **) &uchr_ptr
);
10792 static SInt16 last_key_layout_id
= 0;
10793 static Handle uchr_handle
= (Handle
)-1;
10794 SInt16 current_key_layout_id
=
10795 GetScriptVariable (current_key_script
, smScriptKeys
);
10797 if (uchr_handle
== (Handle
)-1
10798 || last_key_layout_id
!= current_key_layout_id
)
10800 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10801 last_key_layout_id
= current_key_layout_id
;
10804 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10810 UInt16 key_action
= action
- keyDown
;
10811 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10812 UInt32 keyboard_type
= LMGetKbdType ();
10813 SInt32 dead_key_state
= 0;
10815 UniCharCount actual_length
;
10817 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10818 modifier_key_state
, keyboard_type
,
10819 kUCKeyTranslateNoDeadKeysMask
,
10821 1, &actual_length
, &code
);
10822 if (status
== noErr
&& actual_length
== 1)
10823 mac_set_unicode_keystroke_event (code
, buf
);
10825 #endif /* MAC_OSX */
10827 if (buf
->kind
== NO_EVENT
)
10829 /* This code comes from Keyboard Resource, Appendix C of IM
10830 - Text. This is necessary since shift is ignored in KCHR
10831 table translation when option or command is pressed. It
10832 also does not translate correctly control-shift chars
10833 like C-% so mask off shift here also. */
10834 /* Mask off modifier keys that are mapped to some Emacs
10836 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10837 /* set high byte of keycode to modifier high byte*/
10838 int new_key_code
= key_code
| new_modifiers
;
10839 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10840 unsigned long some_state
= 0;
10841 UInt32 new_char_code
;
10843 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10844 if (new_char_code
== 0)
10845 /* Seems like a dead key. Append up-stroke. */
10846 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10850 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10851 buf
->code
= new_char_code
& 0xff;
10856 if (buf
->kind
== NO_EVENT
)
10858 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10859 buf
->code
= char_code
;
10862 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10863 buf
->modifiers
|= (extra_keyboard_modifiers
10864 & (meta_modifier
| alt_modifier
10865 | hyper_modifier
| super_modifier
));
10867 #if TARGET_API_MAC_CARBON
10868 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10869 && buf
->code
>= 0x80 && buf
->modifiers
)
10872 TextEncoding encoding
= kTextEncodingMacRoman
;
10873 TextToUnicodeInfo ttu_info
;
10875 UpgradeScriptInfoToTextEncoding (current_key_script
,
10876 kTextLanguageDontCare
,
10877 kTextRegionDontCare
,
10879 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10884 ByteCount unicode_len
;
10887 pstr
[1] = buf
->code
;
10888 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10890 &unicode_len
, &code
);
10891 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10892 mac_set_unicode_keystroke_event (code
, buf
);
10893 DisposeTextToUnicodeInfo (&ttu_info
);
10898 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10899 && buf
->code
>= 0x80
10900 && last_key_script
!= current_key_script
)
10902 struct input_event event
;
10904 EVENT_INIT (event
);
10905 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10907 event
.code
= current_key_script
;
10908 event
.timestamp
= timestamp
;
10909 kbd_buffer_store_event (&event
);
10910 last_key_script
= current_key_script
;
10915 mac_store_apple_event (class, id
, desc
)
10916 Lisp_Object
class, id
;
10917 const AEDesc
*desc
;
10919 struct input_event buf
;
10923 buf
.kind
= MAC_APPLE_EVENT
;
10926 XSETFRAME (buf
.frame_or_window
,
10927 mac_focus_frame (&one_mac_display_info
));
10928 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10929 is safe to use them during read_socket_hook. */
10930 buf
.arg
= mac_aedesc_to_lisp (desc
);
10931 kbd_buffer_store_event (&buf
);
10934 #if TARGET_API_MAC_CARBON
10936 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10937 event
, num_params
, names
, types
)
10938 AEEventClass
class;
10940 Lisp_Object class_key
, id_key
;
10943 const EventParamName
*names
;
10944 const EventParamType
*types
;
10946 OSStatus err
= eventNotHandledErr
;
10947 Lisp_Object binding
;
10949 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10950 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10952 if (INTEGERP (binding
))
10953 err
= XINT (binding
);
10956 AppleEvent apple_event
;
10957 err
= create_apple_event_from_event_ref (event
, num_params
,
10962 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10963 AEDisposeDesc (&apple_event
);
10964 mac_wakeup_from_rne ();
10973 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10977 const AEDesc
*desc
;
10979 struct input_event buf
;
10983 buf
.kind
= DRAG_N_DROP_EVENT
;
10984 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10985 buf
.timestamp
= TickCount () * (1000 / 60);
10986 XSETINT (buf
.x
, mouse_pos
.h
);
10987 XSETINT (buf
.y
, mouse_pos
.v
);
10988 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10989 buf
.arg
= mac_aedesc_to_lisp (desc
);
10990 kbd_buffer_store_event (&buf
);
10995 mac_store_service_event (event
)
10999 Lisp_Object id_key
;
11001 const EventParamName
*names
;
11002 const EventParamType
*types
;
11003 static const EventParamName names_pfm
[] =
11004 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
11005 static const EventParamType types_pfm
[] =
11006 {typeCFStringRef
, typeCFStringRef
};
11008 switch (GetEventKind (event
))
11010 case kEventServicePaste
:
11017 case kEventServicePerform
:
11019 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
11028 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
11034 #endif /* MAC_OSX */
11036 static pascal OSStatus
11037 mac_handle_window_event (next_handler
, event
, data
)
11038 EventHandlerCallRef next_handler
;
11043 OSStatus err
, result
= eventNotHandledErr
;
11046 XSizeHints
*size_hints
;
11048 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
11049 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11051 return eventNotHandledErr
;
11053 f
= mac_window_to_frame (wp
);
11054 switch (GetEventKind (event
))
11056 /* -- window refresh events -- */
11058 case kEventWindowUpdate
:
11059 result
= CallNextEventHandler (next_handler
, event
);
11060 if (result
!= eventNotHandledErr
)
11063 do_window_update (wp
);
11067 /* -- window state change events -- */
11069 case kEventWindowShowing
:
11070 size_hints
= FRAME_SIZE_HINTS (f
);
11071 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
11073 struct frame
*sf
= SELECTED_FRAME ();
11075 if (!(FRAME_MAC_P (sf
) && sf
->async_visible
))
11076 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
11079 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
11080 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11081 kWindowCascadeStartAtParentWindowScreen
11083 kWindowCascadeOnParentWindowScreen
11086 #if USE_MAC_TOOLBAR
11087 /* This is a workaround. RepositionWindow fails to put
11088 a window at the cascading position when its parent
11089 window has a Carbon HIToolbar. */
11090 if ((f
->left_pos
== sf
->left_pos
11091 && f
->top_pos
== sf
->top_pos
)
11092 || (f
->left_pos
== sf
->left_pos
+ 10 * 2
11093 && f
->top_pos
== sf
->top_pos
+ 32 * 2))
11094 MoveWindowStructure (wp
, sf
->left_pos
+ 10, sf
->top_pos
+ 32);
11101 case kEventWindowHiding
:
11102 /* Before unmapping the window, update the WM_SIZE_HINTS
11103 property to claim that the current position of the window is
11104 user-specified, rather than program-specified, so that when
11105 the window is mapped again, it will be placed at the same
11106 location, without forcing the user to position it by hand
11107 again (they have already done that once for this window.) */
11108 x_wm_set_size_hint (f
, (long) 0, 1);
11112 case kEventWindowShown
:
11113 case kEventWindowHidden
:
11114 case kEventWindowCollapsed
:
11115 case kEventWindowExpanded
:
11116 mac_handle_visibility_change (f
);
11120 case kEventWindowBoundsChanging
:
11121 result
= CallNextEventHandler (next_handler
, event
);
11122 if (result
!= eventNotHandledErr
)
11125 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
11126 NULL
, sizeof (UInt32
), NULL
, &attributes
);
11130 size_hints
= FRAME_SIZE_HINTS (f
);
11131 if ((attributes
& kWindowBoundsChangeUserResize
)
11132 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
11133 == (PResizeInc
| PBaseSize
| PMinSize
)))
11138 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
11139 typeQDRectangle
, NULL
, sizeof (Rect
),
11144 width
= bounds
.right
- bounds
.left
;
11145 height
= bounds
.bottom
- bounds
.top
;
11147 if (width
< size_hints
->min_width
)
11148 width
= size_hints
->min_width
;
11150 width
= size_hints
->base_width
11151 + (int) ((width
- size_hints
->base_width
)
11152 / (float) size_hints
->width_inc
+ .5)
11153 * size_hints
->width_inc
;
11155 if (height
< size_hints
->min_height
)
11156 height
= size_hints
->min_height
;
11158 height
= size_hints
->base_height
11159 + (int) ((height
- size_hints
->base_height
)
11160 / (float) size_hints
->height_inc
+ .5)
11161 * size_hints
->height_inc
;
11163 bounds
.right
= bounds
.left
+ width
;
11164 bounds
.bottom
= bounds
.top
+ height
;
11165 SetEventParameter (event
, kEventParamCurrentBounds
,
11166 typeQDRectangle
, sizeof (Rect
), &bounds
);
11171 case kEventWindowBoundsChanged
:
11172 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
11173 NULL
, sizeof (UInt32
), NULL
, &attributes
);
11177 if (attributes
& kWindowBoundsChangeSizeChanged
)
11181 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
11182 typeQDRectangle
, NULL
, sizeof (Rect
),
11188 width
= bounds
.right
- bounds
.left
;
11189 height
= bounds
.bottom
- bounds
.top
;
11190 mac_handle_size_change (f
, width
, height
);
11191 mac_wakeup_from_rne ();
11195 if (attributes
& kWindowBoundsChangeOriginChanged
)
11196 mac_handle_origin_change (f
);
11201 /* -- window action events -- */
11203 case kEventWindowClose
:
11205 struct input_event buf
;
11208 buf
.kind
= DELETE_WINDOW_EVENT
;
11209 XSETFRAME (buf
.frame_or_window
, f
);
11211 kbd_buffer_store_event (&buf
);
11216 case kEventWindowGetIdealSize
:
11217 result
= CallNextEventHandler (next_handler
, event
);
11218 if (result
!= eventNotHandledErr
)
11222 Point ideal_size
= mac_get_ideal_size (f
);
11224 err
= SetEventParameter (event
, kEventParamDimensions
,
11225 typeQDPoint
, sizeof (Point
), &ideal_size
);
11232 case kEventWindowToolbarSwitchMode
:
11234 static const EventParamName names
[] = {kEventParamDirectObject
,
11235 kEventParamWindowMouseLocation
,
11236 kEventParamKeyModifiers
,
11237 kEventParamMouseButton
,
11238 kEventParamClickCount
,
11239 kEventParamMouseChord
};
11240 static const EventParamType types
[] = {typeWindowRef
,
11246 int num_params
= sizeof (names
) / sizeof (names
[0]);
11248 err
= mac_store_event_ref_as_apple_event (0, 0,
11250 Qtoolbar_switch_mode
,
11260 /* -- window focus events -- */
11262 case kEventWindowFocusAcquired
:
11263 err
= mac_tsm_resume ();
11268 case kEventWindowFocusRelinquish
:
11269 err
= mac_tsm_suspend ();
11282 static pascal OSStatus
11283 mac_handle_application_event (next_handler
, event
, data
)
11284 EventHandlerCallRef next_handler
;
11288 OSStatus err
, result
= eventNotHandledErr
;
11290 switch (GetEventKind (event
))
11293 case kEventAppActivated
:
11294 err
= mac_tsm_resume ();
11297 case kEventAppDeactivated
:
11298 err
= mac_tsm_suspend ();
11312 static pascal OSStatus
11313 mac_handle_keyboard_event (next_handler
, event
, data
)
11314 EventHandlerCallRef next_handler
;
11318 OSStatus err
, result
= eventNotHandledErr
;
11319 UInt32 event_kind
, key_code
, modifiers
;
11320 unsigned char char_code
;
11322 event_kind
= GetEventKind (event
);
11323 switch (event_kind
)
11325 case kEventRawKeyDown
:
11326 case kEventRawKeyRepeat
:
11327 case kEventRawKeyUp
:
11328 /* When using Carbon Events, we need to pass raw keyboard events
11329 to the TSM ourselves. If TSM handles it, it will pass back
11330 noErr, otherwise it will pass back "eventNotHandledErr" and
11331 we can process it normally. */
11332 result
= CallNextEventHandler (next_handler
, event
);
11333 if (result
!= eventNotHandledErr
)
11336 if (read_socket_inev
== NULL
)
11340 if (read_socket_inev
->kind
!= NO_EVENT
)
11347 if (event_kind
== kEventRawKeyUp
)
11350 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11352 sizeof (char), NULL
, &char_code
);
11356 err
= GetEventParameter (event
, kEventParamKeyCode
,
11358 sizeof (UInt32
), NULL
, &key_code
);
11362 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
11364 sizeof (UInt32
), NULL
, &modifiers
);
11368 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11369 char_code
, key_code
, modifiers
,
11371 (GetEventTime (event
) / kEventDurationMillisecond
)),
11383 static pascal OSStatus
11384 mac_handle_command_event (next_handler
, event
, data
)
11385 EventHandlerCallRef next_handler
;
11389 OSStatus err
, result
= eventNotHandledErr
;
11391 static const EventParamName names
[] =
11392 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11393 static const EventParamType types
[] =
11394 {typeHICommand
, typeUInt32
};
11395 int num_params
= sizeof (names
) / sizeof (names
[0]);
11397 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11398 NULL
, sizeof (HICommand
), NULL
, &command
);
11400 return eventNotHandledErr
;
11402 switch (GetEventKind (event
))
11404 case kEventCommandProcess
:
11405 result
= CallNextEventHandler (next_handler
, event
);
11406 if (result
!= eventNotHandledErr
)
11409 err
= GetEventParameter (event
, kEventParamDirectObject
,
11410 typeHICommand
, NULL
,
11411 sizeof (HICommand
), NULL
, &command
);
11413 if (err
!= noErr
|| command
.commandID
== 0)
11416 /* A HI command event is mapped to an Apple event whose event
11417 class symbol is `hi-command' and event ID is its command
11419 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11434 static pascal OSStatus
11435 mac_handle_mouse_event (next_handler
, event
, data
)
11436 EventHandlerCallRef next_handler
;
11440 OSStatus err
, result
= eventNotHandledErr
;
11442 switch (GetEventKind (event
))
11444 case kEventMouseWheelMoved
:
11448 EventMouseWheelAxis axis
;
11452 result
= CallNextEventHandler (next_handler
, event
);
11453 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11456 f
= mac_focus_frame (&one_mac_display_info
);
11458 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11459 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11461 || wp
!= FRAME_MAC_WINDOW (f
))
11464 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11465 typeMouseWheelAxis
, NULL
,
11466 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11467 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11470 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11471 typeQDPoint
, NULL
, sizeof (Point
),
11476 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11477 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11478 if (point
.h
< 0 || point
.v
< 0
11479 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11480 f
->tool_bar_window
))
11483 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11484 typeSInt32
, NULL
, sizeof (SInt32
),
11489 read_socket_inev
->kind
= WHEEL_EVENT
;
11490 read_socket_inev
->code
= 0;
11491 read_socket_inev
->modifiers
=
11492 (mac_event_to_emacs_modifiers (event
)
11493 | ((delta
< 0) ? down_modifier
: up_modifier
));
11494 XSETINT (read_socket_inev
->x
, point
.h
);
11495 XSETINT (read_socket_inev
->y
, point
.v
);
11496 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11510 static pascal OSStatus
11511 mac_handle_text_input_event (next_handler
, event
, data
)
11512 EventHandlerCallRef next_handler
;
11516 OSStatus err
, result
;
11517 Lisp_Object id_key
= Qnil
;
11519 const EventParamName
*names
;
11520 const EventParamType
*types
;
11521 static UInt32 seqno_uaia
= 0;
11522 static const EventParamName names_uaia
[] =
11523 {kEventParamTextInputSendComponentInstance
,
11524 kEventParamTextInputSendRefCon
,
11525 kEventParamTextInputSendSLRec
,
11526 kEventParamTextInputSendFixLen
,
11527 kEventParamTextInputSendText
,
11528 kEventParamTextInputSendUpdateRng
,
11529 kEventParamTextInputSendHiliteRng
,
11530 kEventParamTextInputSendClauseRng
,
11531 kEventParamTextInputSendPinRng
,
11532 kEventParamTextInputSendTextServiceEncoding
,
11533 kEventParamTextInputSendTextServiceMacEncoding
,
11534 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11535 static const EventParamType types_uaia
[] =
11536 {typeComponentInstance
,
11538 typeIntlWritingCode
,
11545 typeTextRangeArray
,
11546 typeTextRangeArray
,
11552 static const EventParamName names_ufke
[] =
11553 {kEventParamTextInputSendComponentInstance
,
11554 kEventParamTextInputSendRefCon
,
11555 kEventParamTextInputSendSLRec
,
11556 kEventParamTextInputSendText
};
11557 static const EventParamType types_ufke
[] =
11558 {typeComponentInstance
,
11560 typeIntlWritingCode
,
11563 result
= CallNextEventHandler (next_handler
, event
);
11564 if (result
!= eventNotHandledErr
)
11567 switch (GetEventKind (event
))
11569 case kEventTextInputUpdateActiveInputArea
:
11570 id_key
= Qupdate_active_input_area
;
11571 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11572 names
= names_uaia
;
11573 types
= types_uaia
;
11574 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11575 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11580 case kEventTextInputUnicodeForKeyEvent
:
11582 EventRef kbd_event
;
11583 UInt32 actual_size
, modifiers
;
11585 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11586 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11589 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11591 sizeof (UInt32
), NULL
, &modifiers
);
11592 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11593 /* There're mapped modifier keys. Process it in
11597 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11598 typeUnicodeText
, NULL
, 0, &actual_size
,
11600 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11604 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11605 typeUnicodeText
, NULL
,
11606 sizeof (UniChar
), NULL
, &code
);
11607 if (err
== noErr
&& code
< 0x80)
11609 /* ASCII character. Process it in do_keystroke. */
11610 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11614 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11615 typeUInt32
, NULL
, sizeof (UInt32
),
11617 if (!(err
== noErr
&& key_code
<= 0x7f
11618 && keycode_to_xkeysym_table
[key_code
]))
11621 mac_focus_frame (&one_mac_display_info
);
11623 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11624 read_socket_inev
->code
= code
;
11625 read_socket_inev
->modifiers
=
11626 mac_to_emacs_modifiers (modifiers
);
11627 read_socket_inev
->modifiers
|=
11628 (extra_keyboard_modifiers
11629 & (meta_modifier
| alt_modifier
11630 | hyper_modifier
| super_modifier
));
11631 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11639 /* Non-ASCII keystrokes without mapped modifiers are
11640 processed at the Lisp level. */
11641 id_key
= Qunicode_for_key_event
;
11642 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11643 names
= names_ufke
;
11644 types
= types_ufke
;
11650 case kEventTextInputOffsetToPos
:
11656 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11659 /* Strictly speaking, this is not always correct because
11660 previous events may change some states about display. */
11661 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11663 /* Active input area is displayed around the current point. */
11664 f
= SELECTED_FRAME ();
11665 w
= XWINDOW (f
->selected_window
);
11667 else if (WINDOWP (echo_area_window
))
11669 /* Active input area is displayed in the echo area. */
11670 w
= XWINDOW (echo_area_window
);
11671 f
= WINDOW_XFRAME (w
);
11676 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11677 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11678 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11679 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11680 + FONT_BASE (FRAME_FONT (f
))
11681 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11682 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11683 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11693 if (!NILP (id_key
))
11694 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11700 #endif /* TARGET_API_MAC_CARBON */
11704 install_window_handler (window
)
11707 OSStatus err
= noErr
;
11709 #if TARGET_API_MAC_CARBON
11712 static const EventTypeSpec specs
[] =
11714 /* -- window refresh events -- */
11715 {kEventClassWindow
, kEventWindowUpdate
},
11716 /* -- window state change events -- */
11717 {kEventClassWindow
, kEventWindowShowing
},
11718 {kEventClassWindow
, kEventWindowHiding
},
11719 {kEventClassWindow
, kEventWindowShown
},
11720 {kEventClassWindow
, kEventWindowHidden
},
11721 {kEventClassWindow
, kEventWindowCollapsed
},
11722 {kEventClassWindow
, kEventWindowExpanded
},
11723 {kEventClassWindow
, kEventWindowBoundsChanging
},
11724 {kEventClassWindow
, kEventWindowBoundsChanged
},
11725 /* -- window action events -- */
11726 {kEventClassWindow
, kEventWindowClose
},
11727 {kEventClassWindow
, kEventWindowGetIdealSize
},
11729 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11732 /* -- window focus events -- */
11733 {kEventClassWindow
, kEventWindowFocusAcquired
},
11734 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11737 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11739 if (handle_window_eventUPP
== NULL
)
11740 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11742 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11743 GetEventTypeCount (specs
),
11744 specs
, NULL
, NULL
);
11749 err
= install_drag_handler (window
);
11755 remove_window_handler (window
)
11758 remove_drag_handler (window
);
11761 #if TARGET_API_MAC_CARBON
11763 install_application_handler ()
11765 OSStatus err
= noErr
;
11769 static const EventTypeSpec specs
[] = {
11771 {kEventClassApplication
, kEventAppActivated
},
11772 {kEventClassApplication
, kEventAppDeactivated
},
11776 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11777 (mac_handle_application_event
),
11778 GetEventTypeCount (specs
),
11779 specs
, NULL
, NULL
);
11784 static const EventTypeSpec specs
[] =
11785 {{kEventClassKeyboard
, kEventRawKeyDown
},
11786 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11787 {kEventClassKeyboard
, kEventRawKeyUp
}};
11789 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11790 (mac_handle_keyboard_event
),
11791 GetEventTypeCount (specs
),
11792 specs
, NULL
, NULL
);
11797 static const EventTypeSpec specs
[] =
11798 {{kEventClassCommand
, kEventCommandProcess
}};
11800 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11801 (mac_handle_command_event
),
11802 GetEventTypeCount (specs
),
11803 specs
, NULL
, NULL
);
11808 static const EventTypeSpec specs
[] =
11809 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11811 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11812 (mac_handle_mouse_event
),
11813 GetEventTypeCount (specs
),
11814 specs
, NULL
, NULL
);
11820 static const EventTypeSpec spec
[] =
11821 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11822 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11823 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11825 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11826 (mac_handle_text_input_event
),
11827 GetEventTypeCount (spec
),
11833 err
= install_menu_target_item_handler ();
11837 err
= install_service_handler ();
11845 mac_handle_dm_notification (event
)
11848 mac_screen_config_changed
= 1;
11851 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11853 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11854 CGDirectDisplayID display
;
11855 CGDisplayChangeSummaryFlags flags
;
11858 mac_screen_config_changed
= 1;
11863 init_dm_notification_handler ()
11867 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11868 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11869 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11872 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11875 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11876 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11878 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11879 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11881 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11882 ProcessSerialNumber psn
;
11884 if (handle_dm_notificationUPP
== NULL
)
11885 handle_dm_notificationUPP
=
11886 NewDMNotificationUPP (mac_handle_dm_notification
);
11888 err
= GetCurrentProcess (&psn
);
11890 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11898 mac_get_screen_info (dpyinfo
)
11899 struct mac_display_info
*dpyinfo
;
11902 /* HasDepth returns true if it is possible to have a 32 bit display,
11903 but this may not be what is actually used. Mac OSX can do better. */
11904 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11905 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11908 CGDisplayCount ndisps
;
11909 CGDirectDisplayID
*displays
;
11911 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11914 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11915 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11919 CGRect bounds
= CGRectZero
;
11921 while (ndisps
-- > 0)
11922 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11923 dpyinfo
->height
= CGRectGetHeight (bounds
);
11924 dpyinfo
->width
= CGRectGetWidth (bounds
);
11928 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11929 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11932 #else /* !MAC_OSX */
11934 GDHandle gdh
= GetMainDevice ();
11935 Rect rect
= (**gdh
).gdRect
;
11937 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11938 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11939 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11942 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11943 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11944 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11946 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11947 dpyinfo
->width
= rect
.right
- rect
.left
;
11949 #endif /* !MAC_OSX */
11955 profiler_exit_proc ()
11957 ProfilerDump ("\pEmacs.prof");
11962 /* These few functions implement Emacs as a normal Mac application
11963 (almost): set up the heap and the Toolbox, handle necessary system
11964 events plus a few simple menu events. They also set up Emacs's
11965 access to functions defined in the rest of this file. Emacs uses
11966 function hooks to perform all its terminal I/O. A complete list of
11967 these functions appear in termhooks.h. For what they do, read the
11968 comments there and see also w32term.c and xterm.c. What's
11969 noticeably missing here is the event loop, which is normally
11970 present in most Mac application. After performing the necessary
11971 Mac initializations, main passes off control to emacs_main
11972 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11973 (defined further below) to read input. This is where
11974 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11981 #if __profile__ /* is the profiler on? */
11982 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11987 /* set creator and type for files created by MSL */
11988 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11992 do_init_managers ();
11996 #ifndef USE_LSB_TAG
11997 do_check_ram_size ();
12000 init_emacs_passwd_dir ();
12004 init_coercion_handler ();
12006 initialize_applescript ();
12008 init_apple_event_handler ();
12010 init_dm_notification_handler ();
12016 /* set up argv array from STR# resource */
12017 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
12021 /* free up AppleScript resources on exit */
12022 atexit (terminate_applescript
);
12024 #if __profile__ /* is the profiler on? */
12025 atexit (profiler_exit_proc
);
12028 /* 3rd param "envp" never used in emacs_main */
12029 (void) emacs_main (argc
, argv
, 0);
12032 /* Never reached - real exit in Fkill_emacs */
12037 #if !TARGET_API_MAC_CARBON
12038 static RgnHandle mouse_region
= NULL
;
12041 mac_wait_next_event (er
, sleep_time
, dequeue
)
12046 static EventRecord er_buf
= {nullEvent
};
12047 UInt32 target_tick
, current_tick
;
12048 EventMask event_mask
;
12050 if (mouse_region
== NULL
)
12051 mouse_region
= NewRgn ();
12053 event_mask
= everyEvent
;
12054 if (!mac_ready_for_apple_events
)
12055 event_mask
-= highLevelEventMask
;
12057 current_tick
= TickCount ();
12058 target_tick
= current_tick
+ sleep_time
;
12060 if (er_buf
.what
== nullEvent
)
12061 while (!WaitNextEvent (event_mask
, &er_buf
,
12062 target_tick
- current_tick
, mouse_region
))
12064 current_tick
= TickCount ();
12065 if (target_tick
<= current_tick
)
12071 er_buf
.what
= nullEvent
;
12074 #endif /* not TARGET_API_MAC_CARBON */
12076 #if TARGET_API_MAC_CARBON
12078 mac_post_mouse_moved_event ()
12080 EventRef event
= NULL
;
12083 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
12084 kEventAttributeNone
, &event
);
12089 GetGlobalMouse (&mouse_pos
);
12090 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
12091 sizeof (Point
), &mouse_pos
);
12095 UInt32 modifiers
= GetCurrentKeyModifiers ();
12097 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
12098 sizeof (UInt32
), &modifiers
);
12101 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
12102 kEventPriorityStandard
);
12104 ReleaseEvent (event
);
12110 /* Emacs calls this whenever it wants to read an input event from the
12113 XTread_socket (sd
, expected
, hold_quit
)
12115 struct input_event
*hold_quit
;
12117 struct input_event inev
;
12119 #if TARGET_API_MAC_CARBON
12121 EventTargetRef toolbox_dispatcher
;
12124 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
12126 if (interrupt_input_blocked
)
12128 interrupt_input_pending
= 1;
12132 interrupt_input_pending
= 0;
12135 /* So people can tell when we have read the available input. */
12136 input_signal_count
++;
12140 #if TARGET_API_MAC_CARBON
12141 toolbox_dispatcher
= GetEventDispatcherTarget ();
12145 mac_prepare_for_quickdraw (NULL
),
12147 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
12148 kEventRemoveFromQueue
, &eventRef
))
12149 #else /* !TARGET_API_MAC_CARBON */
12150 while (mac_wait_next_event (&er
, 0, true))
12151 #endif /* !TARGET_API_MAC_CARBON */
12155 unsigned long timestamp
;
12158 inev
.kind
= NO_EVENT
;
12161 #if TARGET_API_MAC_CARBON
12162 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
12164 if (!mac_convert_event_ref (eventRef
, &er
))
12166 #else /* !TARGET_API_MAC_CARBON */
12167 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
12168 #endif /* !TARGET_API_MAC_CARBON */
12175 WindowRef window_ptr
;
12176 ControlPartCode part_code
;
12177 int tool_bar_p
= 0;
12179 #if TARGET_API_MAC_CARBON
12182 /* This is needed to send mouse events like aqua window
12183 buttons to the correct handler. */
12184 read_socket_inev
= &inev
;
12185 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12186 read_socket_inev
= NULL
;
12187 if (err
!= eventNotHandledErr
)
12190 last_mouse_glyph_frame
= 0;
12192 if (dpyinfo
->grabbed
&& last_mouse_frame
12193 && FRAME_LIVE_P (last_mouse_frame
))
12195 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
12196 part_code
= inContent
;
12200 part_code
= FindWindow (er
.where
, &window_ptr
);
12201 if (tip_window
&& window_ptr
== tip_window
)
12203 HideWindow (tip_window
);
12204 part_code
= FindWindow (er
.where
, &window_ptr
);
12208 if (er
.what
!= mouseDown
&&
12209 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
12215 f
= mac_focus_frame (dpyinfo
);
12216 saved_menu_event_location
= er
.where
;
12217 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
12218 XSETFRAME (inev
.frame_or_window
, f
);
12223 #if TARGET_API_MAC_CARBON
12224 FrontNonFloatingWindow ()
12229 || (mac_window_to_frame (window_ptr
)
12230 != dpyinfo
->x_focus_frame
))
12231 SelectWindow (window_ptr
);
12234 ControlPartCode control_part_code
;
12238 ControlKind control_kind
;
12241 f
= mac_window_to_frame (window_ptr
);
12242 /* convert to local coordinates of new window */
12243 mouse_loc
.h
= (er
.where
.h
12245 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12246 mouse_loc
.v
= (er
.where
.v
12248 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12249 #if TARGET_API_MAC_CARBON
12250 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
12251 &control_part_code
);
12254 GetControlKind (ch
, &control_kind
);
12257 control_part_code
= FindControl (mouse_loc
, window_ptr
,
12261 #if TARGET_API_MAC_CARBON
12262 inev
.code
= mac_get_mouse_btn (eventRef
);
12263 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12265 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
12266 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12268 XSETINT (inev
.x
, mouse_loc
.h
);
12269 XSETINT (inev
.y
, mouse_loc
.v
);
12271 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
12273 #ifndef USE_TOOLKIT_SCROLL_BARS
12274 /* control_part_code becomes kControlNoPart if
12275 a progress indicator is clicked. */
12276 && control_part_code
!= kControlNoPart
12277 #else /* USE_TOOLKIT_SCROLL_BARS */
12279 && control_kind
.kind
== kControlKindScrollBar
12280 #endif /* MAC_OSX */
12281 #endif /* USE_TOOLKIT_SCROLL_BARS */
12284 struct scroll_bar
*bar
;
12286 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12288 bar
= tracked_scroll_bar
;
12289 #ifndef USE_TOOLKIT_SCROLL_BARS
12290 control_part_code
= kControlIndicatorPart
;
12294 bar
= (struct scroll_bar
*) GetControlReference (ch
);
12295 #ifdef USE_TOOLKIT_SCROLL_BARS
12296 /* Make the "Ctrl-Mouse-2 splits window" work
12297 for toolkit scroll bars. */
12298 if (inev
.modifiers
& ctrl_modifier
)
12299 x_scroll_bar_handle_click (bar
, control_part_code
,
12301 else if (er
.what
== mouseDown
)
12302 x_scroll_bar_handle_press (bar
, control_part_code
,
12305 x_scroll_bar_handle_release (bar
, &inev
);
12306 #else /* not USE_TOOLKIT_SCROLL_BARS */
12307 x_scroll_bar_handle_click (bar
, control_part_code
,
12309 if (er
.what
== mouseDown
12310 && control_part_code
== kControlIndicatorPart
)
12311 tracked_scroll_bar
= bar
;
12313 tracked_scroll_bar
= NULL
;
12314 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12318 Lisp_Object window
;
12319 int x
= mouse_loc
.h
;
12320 int y
= mouse_loc
.v
;
12322 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
12323 if (EQ (window
, f
->tool_bar_window
))
12325 if (er
.what
== mouseDown
)
12326 handle_tool_bar_click (f
, x
, y
, 1, 0);
12328 handle_tool_bar_click (f
, x
, y
, 0,
12334 XSETFRAME (inev
.frame_or_window
, f
);
12335 inev
.kind
= MOUSE_CLICK_EVENT
;
12339 if (er
.what
== mouseDown
)
12341 dpyinfo
->grabbed
|= (1 << inev
.code
);
12342 last_mouse_frame
= f
;
12345 last_tool_bar_item
= -1;
12349 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
12350 /* If a button is released though it was not
12351 previously pressed, that would be because
12352 of multi-button emulation. */
12353 dpyinfo
->grabbed
= 0;
12355 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
12358 /* Ignore any mouse motion that happened before
12359 this event; any subsequent mouse-movement Emacs
12360 events should reflect only motion after the
12363 f
->mouse_moved
= 0;
12365 #ifdef USE_TOOLKIT_SCROLL_BARS
12366 if (inev
.kind
== MOUSE_CLICK_EVENT
12367 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12368 && (inev
.modifiers
& ctrl_modifier
)))
12373 inev
.modifiers
|= down_modifier
;
12376 inev
.modifiers
|= up_modifier
;
12383 #if TARGET_API_MAC_CARBON
12385 if (IsWindowPathSelectClick (window_ptr
, &er
))
12387 WindowPathSelect (window_ptr
, NULL
, NULL
);
12390 if (part_code
== inProxyIcon
12391 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12392 != errUserWantsToDragWindow
))
12394 DragWindow (window_ptr
, er
.where
, NULL
);
12395 #else /* not TARGET_API_MAC_CARBON */
12396 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12397 /* Update the frame parameters. */
12399 struct frame
*f
= mac_window_to_frame (window_ptr
);
12401 if (f
&& !f
->async_iconified
)
12402 mac_handle_origin_change (f
);
12404 #endif /* not TARGET_API_MAC_CARBON */
12408 if (TrackGoAway (window_ptr
, er
.where
))
12410 inev
.kind
= DELETE_WINDOW_EVENT
;
12411 XSETFRAME (inev
.frame_or_window
,
12412 mac_window_to_frame (window_ptr
));
12416 /* window resize handling added --ben */
12418 do_grow_window (window_ptr
, &er
);
12421 /* window zoom handling added --ben */
12424 if (TrackBox (window_ptr
, er
.where
, part_code
))
12425 do_zoom_window (window_ptr
, part_code
);
12428 #if USE_MAC_TOOLBAR
12434 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12436 /* This doesn't work on Mac OS X 10.2. */
12438 HIViewClick (ch
, eventRef
);
12441 #endif /* USE_MAC_TOOLBAR */
12449 #if !TARGET_API_MAC_CARBON
12451 do_window_update ((WindowRef
) er
.message
);
12456 switch ((er
.message
>> 24) & 0x000000FF)
12458 case mouseMovedMessage
:
12459 #if !TARGET_API_MAC_CARBON
12460 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12461 er
.where
.h
+ 1, er
.where
.v
+ 1);
12463 previous_help_echo_string
= help_echo_string
;
12464 help_echo_string
= Qnil
;
12466 if (dpyinfo
->grabbed
&& last_mouse_frame
12467 && FRAME_LIVE_P (last_mouse_frame
))
12468 f
= last_mouse_frame
;
12470 f
= dpyinfo
->x_focus_frame
;
12472 if (dpyinfo
->mouse_face_hidden
)
12474 dpyinfo
->mouse_face_hidden
= 0;
12475 clear_mouse_face (dpyinfo
);
12480 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12483 mouse_pos
.h
= (er
.where
.h
12485 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12486 mouse_pos
.v
= (er
.where
.v
12488 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12489 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12490 #ifdef USE_TOOLKIT_SCROLL_BARS
12491 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12493 #else /* not USE_TOOLKIT_SCROLL_BARS */
12494 x_scroll_bar_note_movement (tracked_scroll_bar
,
12496 - XINT (tracked_scroll_bar
->top
),
12497 er
.when
* (1000 / 60));
12498 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12501 /* Generate SELECT_WINDOW_EVENTs when needed. */
12502 if (!NILP (Vmouse_autoselect_window
))
12504 Lisp_Object window
;
12506 window
= window_from_coordinates (f
,
12511 /* Window will be selected only when it is
12512 not selected now and last mouse movement
12513 event was not in it. Minibuffer window
12514 will be selected only when it is active. */
12515 if (WINDOWP (window
)
12516 && !EQ (window
, last_window
)
12517 && !EQ (window
, selected_window
)
12518 /* For click-to-focus window managers
12519 create event iff we don't leave the
12521 && (focus_follows_mouse
12522 || (EQ (XWINDOW (window
)->frame
,
12523 XWINDOW (selected_window
)->frame
))))
12525 inev
.kind
= SELECT_WINDOW_EVENT
;
12526 inev
.frame_or_window
= window
;
12529 last_window
=window
;
12531 if (!note_mouse_movement (f
, &mouse_pos
))
12532 help_echo_string
= previous_help_echo_string
;
12533 #if USE_MAC_TOOLBAR
12535 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12540 /* If the contents of the global variable
12541 help_echo_string has changed, generate a
12543 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12554 WindowRef window_ptr
= (WindowRef
) er
.message
;
12556 ControlRef root_control
;
12558 if (window_ptr
== tip_window
)
12560 HideWindow (tip_window
);
12564 if (!is_emacs_window (window_ptr
))
12567 f
= mac_window_to_frame (window_ptr
);
12569 if ((er
.modifiers
& activeFlag
) != 0)
12571 /* A window has been activated */
12574 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12576 ActivateControl (root_control
);
12578 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12580 mouse_loc
.h
= (er
.where
.h
12582 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12583 mouse_loc
.v
= (er
.where
.v
12585 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12586 /* Window-activated event counts as mouse movement,
12587 so update things that depend on mouse position. */
12588 note_mouse_movement (f
, &mouse_loc
);
12592 /* A window has been deactivated */
12593 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12595 DeactivateControl (root_control
);
12597 #ifdef USE_TOOLKIT_SCROLL_BARS
12598 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12600 struct input_event event
;
12602 EVENT_INIT (event
);
12603 event
.kind
= NO_EVENT
;
12604 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12605 if (event
.kind
!= NO_EVENT
)
12607 event
.timestamp
= timestamp
;
12608 kbd_buffer_store_event_hold (&event
, hold_quit
);
12613 dpyinfo
->grabbed
= 0;
12615 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12617 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12619 /* If we move outside the frame, then we're
12620 certainly no longer on any text in the
12622 clear_mouse_face (dpyinfo
);
12623 dpyinfo
->mouse_face_mouse_frame
= 0;
12626 /* Generate a nil HELP_EVENT to cancel a help-echo.
12627 Do it only if there's something to cancel.
12628 Otherwise, the startup message is cleared when the
12629 mouse leaves the frame. */
12630 if (any_help_event_p
)
12641 f
= mac_focus_frame (dpyinfo
);
12642 XSETFRAME (inev
.frame_or_window
, f
);
12644 /* If mouse-highlight is an integer, input clears out mouse
12646 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12647 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12649 clear_mouse_face (dpyinfo
);
12650 dpyinfo
->mouse_face_hidden
= 1;
12654 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
12657 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
12659 sizeof (UInt32
), NULL
, &modifiers
);
12661 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
12663 #if TARGET_API_MAC_CARBON
12664 if (!(mapped_modifiers
12665 & ~(mac_pass_command_to_system
? cmdKey
: 0)
12666 & ~(mac_pass_control_to_system
? controlKey
: 0)))
12670 if (er
.what
!= keyUp
)
12671 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12672 (er
.message
& keyCodeMask
) >> 8,
12673 modifiers
, timestamp
, &inev
);
12677 case kHighLevelEvent
:
12678 AEProcessAppleEvent (&er
);
12683 #if TARGET_API_MAC_CARBON
12687 read_socket_inev
= &inev
;
12688 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12689 read_socket_inev
= NULL
;
12694 #if TARGET_API_MAC_CARBON
12695 ReleaseEvent (eventRef
);
12698 if (inev
.kind
!= NO_EVENT
)
12700 inev
.timestamp
= timestamp
;
12701 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12706 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12711 XSETFRAME (frame
, f
);
12717 any_help_event_p
= 1;
12718 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12719 help_echo_object
, help_echo_pos
);
12723 help_echo_string
= Qnil
;
12724 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12730 /* If the focus was just given to an autoraising frame,
12732 /* ??? This ought to be able to handle more than one such frame. */
12733 if (pending_autoraise_frame
)
12735 x_raise_frame (pending_autoraise_frame
);
12736 pending_autoraise_frame
= 0;
12739 if (mac_screen_config_changed
)
12741 mac_get_screen_info (dpyinfo
);
12742 mac_screen_config_changed
= 0;
12745 #if !TARGET_API_MAC_CARBON
12746 /* Check which frames are still visible. We do this here because
12747 there doesn't seem to be any direct notification from the Window
12748 Manager that the visibility of a window has changed (at least,
12749 not in all cases). */
12751 Lisp_Object tail
, frame
;
12753 FOR_EACH_FRAME (tail
, frame
)
12755 struct frame
*f
= XFRAME (frame
);
12757 /* The tooltip has been drawn already. Avoid the
12758 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12759 if (EQ (frame
, tip_frame
))
12762 if (FRAME_MAC_P (f
))
12763 mac_handle_visibility_change (f
);
12774 /* Need to override CodeWarrior's input function so no conversion is
12775 done on newlines Otherwise compiled functions in .elc files will be
12776 read incorrectly. Defined in ...:MSL C:MSL
12777 Common:Source:buffer_io.c. */
12780 __convert_to_newlines (unsigned char * p
, size_t * n
)
12782 #pragma unused(p,n)
12786 __convert_from_newlines (unsigned char * p
, size_t * n
)
12788 #pragma unused(p,n)
12794 make_mac_terminal_frame (struct frame
*f
)
12799 XSETFRAME (frame
, f
);
12801 f
->output_method
= output_mac
;
12802 f
->output_data
.mac
= (struct mac_output
*)
12803 xmalloc (sizeof (struct mac_output
));
12804 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12806 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12808 FRAME_COLS (f
) = 96;
12809 FRAME_LINES (f
) = 4;
12811 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12812 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12814 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12816 f
->output_data
.mac
->cursor_pixel
= 0;
12817 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12818 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12819 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12821 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12822 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12823 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12824 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12825 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12826 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12828 FRAME_FONTSET (f
) = -1;
12829 f
->output_data
.mac
->explicit_parent
= 0;
12832 f
->border_width
= 0;
12834 f
->internal_border_width
= 0;
12839 f
->new_text_cols
= 0;
12840 f
->new_text_lines
= 0;
12842 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12843 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12844 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12848 if (!(FRAME_MAC_WINDOW (f
) =
12849 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12850 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12852 /* so that update events can find this mac_output struct */
12853 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12859 /* Need to be initialized for unshow_buffer in window.c. */
12860 selected_window
= f
->selected_window
;
12862 Fmodify_frame_parameters (frame
,
12863 Fcons (Fcons (Qfont
,
12864 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12865 Fmodify_frame_parameters (frame
,
12866 Fcons (Fcons (Qforeground_color
,
12867 build_string ("black")), Qnil
));
12868 Fmodify_frame_parameters (frame
,
12869 Fcons (Fcons (Qbackground_color
,
12870 build_string ("white")), Qnil
));
12875 /***********************************************************************
12877 ***********************************************************************/
12879 static int mac_initialized
= 0;
12882 mac_make_rdb (xrm_option
)
12883 const char *xrm_option
;
12885 XrmDatabase database
;
12887 database
= xrm_get_preference_database (NULL
);
12889 xrm_merge_string_database (database
, xrm_option
);
12894 struct mac_display_info
*
12895 mac_term_init (display_name
, xrm_option
, resource_name
)
12896 Lisp_Object display_name
;
12898 char *resource_name
;
12900 struct mac_display_info
*dpyinfo
;
12901 struct terminal
*terminal
;
12905 if (!mac_initialized
)
12908 mac_initialized
= 1;
12911 if (x_display_list
)
12912 error ("Sorry, this version can only handle one display");
12914 dpyinfo
= &one_mac_display_info
;
12915 bzero (dpyinfo
, sizeof (*dpyinfo
));
12917 terminal
= mac_create_terminal (dpyinfo
);
12919 /* Set the name of the terminal. */
12920 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
12921 strncpy (terminal
->name
, SDATA (display_name
), SBYTES (display_name
));
12922 terminal
->name
[SBYTES (display_name
)] = 0;
12925 dpyinfo
->mac_id_name
12926 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12927 + SCHARS (Vsystem_name
)
12929 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12930 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12932 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12933 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12936 dpyinfo
->reference_count
= 0;
12937 dpyinfo
->resx
= 72.0;
12938 dpyinfo
->resy
= 72.0;
12940 mac_get_screen_info (dpyinfo
);
12942 dpyinfo
->grabbed
= 0;
12943 dpyinfo
->root_window
= NULL
;
12944 dpyinfo
->terminal
->image_cache
= make_image_cache ();
12946 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12947 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12948 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12949 dpyinfo
->mouse_face_window
= Qnil
;
12950 dpyinfo
->mouse_face_overlay
= Qnil
;
12951 dpyinfo
->mouse_face_hidden
= 0;
12953 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12955 /* Put this display on the chain. */
12956 dpyinfo
->next
= x_display_list
;
12957 x_display_list
= dpyinfo
;
12959 /* Put it on x_display_name_list. */
12960 x_display_name_list
= Fcons (Fcons (display_name
,
12961 Fcons (Qnil
, dpyinfo
->xrdb
)),
12962 x_display_name_list
);
12963 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12965 /* FIXME: Untested.
12966 Add the default keyboard. */
12967 add_keyboard_wait_descriptor (0);
12970 mac_init_fringe (terminal
->rif
);
12978 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12981 x_delete_display (dpyinfo
)
12982 struct mac_display_info
*dpyinfo
;
12986 /* Discard this display from x_display_name_list and x_display_list.
12987 We can't use Fdelq because that can quit. */
12988 if (! NILP (x_display_name_list
)
12989 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12990 x_display_name_list
= XCDR (x_display_name_list
);
12995 tail
= x_display_name_list
;
12996 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12998 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
13000 XSETCDR (tail
, XCDR (XCDR (tail
)));
13003 tail
= XCDR (tail
);
13007 if (x_display_list
== dpyinfo
)
13008 x_display_list
= dpyinfo
->next
;
13011 struct x_display_info
*tail
;
13013 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
13014 if (tail
->next
== dpyinfo
)
13015 tail
->next
= tail
->next
->next
;
13018 /* Free the font names in the font table. */
13019 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
13020 if (dpyinfo
->font_table
[i
].name
)
13022 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
13023 xfree (dpyinfo
->font_table
[i
].full_name
);
13024 xfree (dpyinfo
->font_table
[i
].name
);
13027 if (dpyinfo
->font_table
)
13029 if (dpyinfo
->font_table
->font_encoder
)
13030 xfree (dpyinfo
->font_table
->font_encoder
);
13031 xfree (dpyinfo
->font_table
);
13033 if (dpyinfo
->mac_id_name
)
13034 xfree (dpyinfo
->mac_id_name
);
13036 if (x_display_list
== 0)
13038 mac_clear_font_name_table ();
13039 bzero (dpyinfo
, sizeof (*dpyinfo
));
13050 MenuItemIndex menu_index
;
13052 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
13053 &menu
, &menu_index
);
13055 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
13056 EnableMenuCommand (NULL
, kHICommandPreferences
);
13057 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
13058 &menu
, &menu_index
);
13061 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
13062 InsertMenuItemTextWithCFString (menu
, NULL
,
13063 0, kMenuItemAttrSeparator
, 0);
13064 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
13065 0, 0, kHICommandAbout
);
13067 #else /* !MAC_OSX */
13068 #if TARGET_API_MAC_CARBON
13069 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
13079 static InterfaceTypeList types
= {kUnicodeDocument
};
13081 static InterfaceTypeList types
= {kTextService
};
13084 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
13085 &tsm_document_id
, 0);
13089 /* Set up use of X before we make the first connection. */
13091 extern frame_parm_handler mac_frame_parm_handlers
[];
13093 static struct redisplay_interface x_redisplay_interface
=
13095 mac_frame_parm_handlers
,
13099 x_clear_end_of_line
,
13101 x_after_update_window_line
,
13102 x_update_window_begin
,
13103 x_update_window_end
,
13107 mac_flush_display_optional
,
13109 0, /* flush_display_optional */
13111 x_clear_window_mouse_face
,
13112 x_get_glyph_overhangs
,
13113 x_fix_overlapping_area
,
13114 x_draw_fringe_bitmap
,
13116 mac_define_fringe_bitmap
,
13117 mac_destroy_fringe_bitmap
,
13119 0, /* define_fringe_bitmap */
13120 0, /* destroy_fringe_bitmap */
13122 mac_per_char_metric
,
13124 mac_compute_glyph_string_overhangs
,
13125 x_draw_glyph_string
,
13126 mac_define_frame_cursor
,
13127 mac_clear_frame_area
,
13128 mac_draw_window_cursor
,
13129 mac_draw_vertical_window_border
,
13130 mac_shift_glyphs_for_insert
13133 static struct terminal
*
13134 mac_create_terminal (struct mac_display_info
*dpyinfo
)
13136 struct terminal
*terminal
;
13138 terminal
= create_terminal ();
13140 terminal
->type
= output_mac
;
13141 terminal
->display_info
.mac
= dpyinfo
;
13142 dpyinfo
->terminal
= terminal
;
13144 terminal
->clear_frame_hook
= x_clear_frame
;
13145 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
13146 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
13147 terminal
->ring_bell_hook
= XTring_bell
;
13148 terminal
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
13149 terminal
->set_terminal_modes_hook
= XTset_terminal_modes
;
13150 terminal
->update_begin_hook
= x_update_begin
;
13151 terminal
->update_end_hook
= x_update_end
;
13152 terminal
->set_terminal_window_hook
= XTset_terminal_window
;
13153 terminal
->read_socket_hook
= XTread_socket
;
13154 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
13155 terminal
->mouse_position_hook
= XTmouse_position
;
13156 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
13157 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
13158 /* terminal->fullscreen_hook = XTfullscreen_hook; */
13159 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13160 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13161 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13162 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13163 terminal
->delete_frame_hook
= x_destroy_window
;
13164 /* terminal->delete_terminal_hook = x_delete_terminal; */
13166 terminal
->rif
= &x_redisplay_interface
;
13168 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
13169 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
13170 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
13171 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
13172 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
13176 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
13177 terminal
->char_ins_del_ok
= 1;
13178 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
13179 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
13180 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
13185 /* FIXME: This keyboard setup is 100% untested, just copied from
13186 w32_create_terminal in order to set window-system now that it's
13187 a keyboard object. */
13188 /* We don't yet support separate terminals on Mac, so don't try to share
13189 keyboards between virtual terminals that are on the same physical
13190 terminal like X does. */
13191 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
13192 init_kboard (terminal
->kboard
);
13193 terminal
->kboard
->Vwindow_system
= intern ("mac");
13194 terminal
->kboard
->next_kboard
= all_kboards
;
13195 all_kboards
= terminal
->kboard
;
13196 /* Don't let the initial kboard remain current longer than necessary.
13197 That would cause problems if a file loaded on startup tries to
13198 prompt in the mini-buffer. */
13199 if (current_kboard
== initial_kboard
)
13200 current_kboard
= terminal
->kboard
;
13201 terminal
->kboard
->reference_count
++;
13212 last_tool_bar_item
= -1;
13213 any_help_event_p
= 0;
13215 /* Try to use interrupt input; if we can't, then start polling. */
13216 Fset_input_interrupt_mode (Qt
);
13220 #if TARGET_API_MAC_CARBON
13222 install_application_handler ();
13231 init_coercion_handler ();
13233 init_apple_event_handler ();
13235 init_dm_notification_handler ();
13237 if (!inhibit_window_system
)
13239 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
13241 SetFrontProcess (&psn
);
13259 staticpro (&x_error_message_string
);
13260 x_error_message_string
= Qnil
;
13263 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
13264 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
13265 Qalt
= intern ("alt"); staticpro (&Qalt
);
13266 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
13267 Qsuper
= intern ("super"); staticpro (&Qsuper
);
13268 Qmodifier_value
= intern ("modifier-value");
13269 staticpro (&Qmodifier_value
);
13271 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
13272 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
13273 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
13274 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
13275 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
13277 #if TARGET_API_MAC_CARBON
13278 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
13280 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
13281 staticpro (&Qtoolbar_switch_mode
);
13282 #if USE_MAC_FONT_PANEL
13283 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
13284 Qselection
= intern ("selection"); staticpro (&Qselection
);
13287 Qservice
= intern ("service"); staticpro (&Qservice
);
13288 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
13289 Qperform
= intern ("perform"); staticpro (&Qperform
);
13291 Qmouse_drag_overlay
= intern ("mouse-drag-overlay");
13292 staticpro (&Qmouse_drag_overlay
);
13295 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
13296 Qupdate_active_input_area
= intern ("update-active-input-area");
13297 staticpro (&Qupdate_active_input_area
);
13298 Qunicode_for_key_event
= intern ("unicode-for-key-event");
13299 staticpro (&Qunicode_for_key_event
);
13304 Fprovide (intern ("mac-carbon"), Qnil
);
13307 staticpro (&Qreverse
);
13308 Qreverse
= intern ("reverse");
13310 staticpro (&x_display_name_list
);
13311 x_display_name_list
= Qnil
;
13313 staticpro (&last_mouse_scroll_bar
);
13314 last_mouse_scroll_bar
= Qnil
;
13316 staticpro (&fm_font_family_alist
);
13317 fm_font_family_alist
= Qnil
;
13320 staticpro (&atsu_font_id_hash
);
13321 atsu_font_id_hash
= Qnil
;
13323 staticpro (&fm_style_face_attributes_alist
);
13324 fm_style_face_attributes_alist
= Qnil
;
13328 staticpro (&saved_ts_script_language_on_focus
);
13329 saved_ts_script_language_on_focus
= Qnil
;
13332 /* We don't yet support this, but defining this here avoids whining
13333 from cus-start.el and other places, like "M-x set-variable". */
13334 DEFVAR_BOOL ("x-use-underline-position-properties",
13335 &x_use_underline_position_properties
,
13336 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13337 A value of nil means ignore them. If you encounter fonts with bogus
13338 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13339 to 4.1, set this to nil.
13341 NOTE: Not supported on Mac yet. */);
13342 x_use_underline_position_properties
= 0;
13344 DEFVAR_BOOL ("x-underline-at-descent-line",
13345 &x_underline_at_descent_line
,
13346 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
13347 A value of nil means to draw the underline according to the value of the
13348 variable `x-use-underline-position-properties', which is usually at the
13349 baseline level. The default value is nil. */);
13350 x_underline_at_descent_line
= 0;
13352 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
13353 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
13354 #ifdef USE_TOOLKIT_SCROLL_BARS
13355 Vx_toolkit_scroll_bars
= Qt
;
13357 Vx_toolkit_scroll_bars
= Qnil
;
13360 staticpro (&last_mouse_motion_frame
);
13361 last_mouse_motion_frame
= Qnil
;
13363 /* Variables to configure modifier key assignment. */
13365 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
13366 doc
: /* *Modifier key assumed when the Mac control key is pressed.
13367 The value can be `control', `meta', `alt', `hyper', or `super' for the
13368 respective modifier. The default is `control'. */);
13369 Vmac_control_modifier
= Qcontrol
;
13371 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
13372 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
13373 The value can be `control', `meta', `alt', `hyper', or `super' for the
13374 respective modifier. If the value is nil then the key will act as the
13375 normal Mac control modifier, and the option key can be used to compose
13376 characters depending on the chosen Mac keyboard setting. */);
13377 Vmac_option_modifier
= Qnil
;
13379 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
13380 doc
: /* *Modifier key assumed when the Mac command key is pressed.
13381 The value can be `control', `meta', `alt', `hyper', or `super' for the
13382 respective modifier. The default is `meta'. */);
13383 Vmac_command_modifier
= Qmeta
;
13385 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
13386 doc
: /* *Modifier key assumed when the Mac function key is pressed.
13387 The value can be `control', `meta', `alt', `hyper', or `super' for the
13388 respective modifier. Note that remapping the function key may lead to
13389 unexpected results for some keys on non-US/GB keyboards. */);
13390 Vmac_function_modifier
= Qnil
;
13392 DEFVAR_LISP ("mac-emulate-three-button-mouse",
13393 &Vmac_emulate_three_button_mouse
,
13394 doc
: /* *Specify a way of three button mouse emulation.
13395 The value can be nil, t, or the symbol `reverse'.
13396 A value of nil means that no emulation should be done and the modifiers
13397 should be placed on the mouse-1 event.
13398 t means that when the option-key is held down while pressing the mouse
13399 button, the click will register as mouse-2 and while the command-key
13400 is held down, the click will register as mouse-3.
13401 The symbol `reverse' means that the option-key will register for
13402 mouse-3 and the command-key will register for mouse-2. */);
13403 Vmac_emulate_three_button_mouse
= Qnil
;
13405 #if TARGET_API_MAC_CARBON
13406 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
13407 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
13408 Otherwise, the right click will be treated as mouse-2 and the wheel
13409 button will be mouse-3. */);
13410 mac_wheel_button_is_mouse_2
= 1;
13412 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
13413 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
13414 mac_pass_command_to_system
= 1;
13416 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
13417 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13418 mac_pass_control_to_system
= 1;
13422 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
13423 doc
: /* *If non-nil, allow anti-aliasing.
13424 The text will be rendered using Core Graphics text rendering which
13425 may anti-alias the text. */);
13427 mac_use_core_graphics
= 1;
13429 mac_use_core_graphics
= 0;
13432 /* Register an entry for `mac-roman' so that it can be used when
13433 creating the terminal frame on Mac OS 9 before loading
13434 term/mac-win.elc. */
13435 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
13436 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
13437 Each entry should be of the form:
13439 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13441 where CHARSET-NAME is a string used in font names to identify the
13442 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13443 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13444 Vmac_charset_info_alist
=
13445 Fcons (list3 (build_string ("mac-roman"),
13446 make_number (smRoman
), Qnil
), Qnil
);
13449 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13450 doc
: /* Overlay used to display Mac TSM active input area. */);
13451 Vmac_ts_active_input_overlay
= Qnil
;
13453 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf
,
13454 doc
: /* Byte sequence of the current Mac TSM active input area. */);
13455 /* `empty_string' is not ready yet on Mac OS Classic. */
13456 Vmac_ts_active_input_buf
= build_string ("");
13458 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13459 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13460 If the value is t, the input script and language are restored to those
13461 used in the last focus frame. If the value is a pair of integers, the
13462 input script and language codes, which are defined in the Script
13463 Manager, are set to its car and cdr parts, respectively. Otherwise,
13464 Emacs doesn't set them and thus follows the system default behavior. */);
13465 Vmac_ts_script_language_on_focus
= Qnil
;
13469 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13470 (do not change this comment) */