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
;
3553 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3558 gc
= f
->output_data
.mac
->white_relief
.gc
;
3560 gc
= f
->output_data
.mac
->black_relief
.gc
;
3561 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3565 for (i
= 0; i
< width
; ++i
)
3566 mac_draw_line (f
, gc
,
3567 left_x
+ i
* left_p
, top_y
+ i
,
3568 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3572 for (i
= 0; i
< width
; ++i
)
3573 mac_draw_line (f
, gc
,
3574 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3576 mac_reset_clip_rectangles (f
, gc
);
3578 gc
= f
->output_data
.mac
->black_relief
.gc
;
3580 gc
= f
->output_data
.mac
->white_relief
.gc
;
3581 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3585 for (i
= 0; i
< width
; ++i
)
3586 mac_draw_line (f
, gc
,
3587 left_x
+ i
* left_p
, bottom_y
- i
,
3588 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3592 for (i
= 0; i
< width
; ++i
)
3593 mac_draw_line (f
, gc
,
3594 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3596 mac_reset_clip_rectangles (f
, gc
);
3600 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3601 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3602 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3603 left side of the rectangle. RIGHT_P non-zero means draw a line
3604 on the right side of the rectangle. CLIP_RECT is the clipping
3605 rectangle to use when drawing. */
3608 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3609 left_p
, right_p
, clip_rect
)
3610 struct glyph_string
*s
;
3611 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3616 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3617 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3618 mac_set_clip_rectangles (s
->f
, s
->gc
, clip_rect
, 1);
3621 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3622 right_x
- left_x
+ 1, width
);
3626 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3627 width
, bottom_y
- top_y
+ 1);
3630 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3631 right_x
- left_x
+ 1, width
);
3635 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3636 top_y
, width
, bottom_y
- top_y
+ 1);
3638 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3639 mac_reset_clip_rectangles (s
->f
, s
->gc
);
3643 /* Draw a box around glyph string S. */
3646 x_draw_glyph_string_box (s
)
3647 struct glyph_string
*s
;
3649 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3650 int left_p
, right_p
;
3651 struct glyph
*last_glyph
;
3654 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3655 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3656 : window_box_right (s
->w
, s
->area
));
3658 /* The glyph that may have a right box line. */
3659 last_glyph
= (s
->cmp
|| s
->img
3661 : s
->first_glyph
+ s
->nchars
- 1);
3663 width
= eabs (s
->face
->box_line_width
);
3664 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3666 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3668 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3670 bottom_y
= top_y
+ s
->height
- 1;
3672 left_p
= (s
->first_glyph
->left_box_line_p
3673 || (s
->hl
== DRAW_MOUSE_FACE
3675 || s
->prev
->hl
!= s
->hl
)));
3676 right_p
= (last_glyph
->right_box_line_p
3677 || (s
->hl
== DRAW_MOUSE_FACE
3679 || s
->next
->hl
!= s
->hl
)));
3681 get_glyph_string_clip_rect (s
, &clip_rect
);
3683 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3684 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3685 left_p
, right_p
, &clip_rect
);
3688 x_setup_relief_colors (s
);
3689 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3690 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3695 /* Draw foreground of image glyph string S. */
3698 x_draw_image_foreground (s
)
3699 struct glyph_string
*s
;
3702 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3704 /* If first glyph of S has a left box line, start drawing it to the
3705 right of that line. */
3706 if (s
->face
->box
!= FACE_NO_BOX
3707 && s
->first_glyph
->left_box_line_p
3709 x
+= eabs (s
->face
->box_line_width
);
3711 /* If there is a margin around the image, adjust x- and y-position
3713 if (s
->slice
.x
== 0)
3714 x
+= s
->img
->hmargin
;
3715 if (s
->slice
.y
== 0)
3716 y
+= s
->img
->vmargin
;
3720 x_set_glyph_string_clipping (s
);
3723 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3724 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3725 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3729 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3730 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3731 s
->slice
.width
, s
->slice
.height
, x
, y
);
3738 mac_copy_area (s
->img
->pixmap
,
3739 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3740 s
->slice
.width
, s
->slice
.height
, x
, y
);
3743 /* When the image has a mask, we can expect that at
3744 least part of a mouse highlight or a block cursor will
3745 be visible. If the image doesn't have a mask, make
3746 a block cursor visible by drawing a rectangle around
3747 the image. I believe it's looking better if we do
3748 nothing here for mouse-face. */
3749 if (s
->hl
== DRAW_CURSOR
)
3751 int r
= s
->img
->relief
;
3753 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3754 s
->slice
.width
+ r
*2 - 1,
3755 s
->slice
.height
+ r
*2 - 1);
3760 /* Draw a rectangle if image could not be loaded. */
3761 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3762 s
->slice
.width
- 1, s
->slice
.height
- 1);
3766 /* Draw a relief around the image glyph string S. */
3769 x_draw_image_relief (s
)
3770 struct glyph_string
*s
;
3772 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3775 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3777 /* If first glyph of S has a left box line, start drawing it to the
3778 right of that line. */
3779 if (s
->face
->box
!= FACE_NO_BOX
3780 && s
->first_glyph
->left_box_line_p
3782 x
+= eabs (s
->face
->box_line_width
);
3784 /* If there is a margin around the image, adjust x- and y-position
3786 if (s
->slice
.x
== 0)
3787 x
+= s
->img
->hmargin
;
3788 if (s
->slice
.y
== 0)
3789 y
+= s
->img
->vmargin
;
3791 if (s
->hl
== DRAW_IMAGE_SUNKEN
3792 || s
->hl
== DRAW_IMAGE_RAISED
)
3794 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3795 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3799 thick
= eabs (s
->img
->relief
);
3800 raised_p
= s
->img
->relief
> 0;
3805 x1
= x
+ s
->slice
.width
+ thick
- 1;
3806 y1
= y
+ s
->slice
.height
+ thick
- 1;
3808 x_setup_relief_colors (s
);
3809 get_glyph_string_clip_rect (s
, &r
);
3810 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3812 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3814 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3819 /* Draw part of the background of glyph string S. X, Y, W, and H
3820 give the rectangle to draw. */
3823 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3824 struct glyph_string
*s
;
3827 #if 0 /* MAC_TODO: stipple */
3830 /* Fill background with a stipple pattern. */
3831 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3832 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3833 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3836 #endif /* MAC_TODO */
3837 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3841 /* Draw image glyph string S.
3844 s->x +-------------------------
3847 | +-------------------------
3850 | | +-------------------
3856 x_draw_image_glyph_string (s
)
3857 struct glyph_string
*s
;
3860 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
3861 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3864 height
= s
->height
- 2 * box_line_vwidth
;
3867 /* Fill background with face under the image. Do it only if row is
3868 taller than image or if image has a clip mask to reduce
3870 s
->stippled_p
= s
->face
->stipple
!= 0;
3871 if (height
> s
->slice
.height
3875 || s
->img
->pixmap
== 0
3876 || s
->width
!= s
->background_width
)
3879 if (s
->first_glyph
->left_box_line_p
3881 x
+= box_line_hwidth
;
3884 if (s
->slice
.y
== 0)
3885 y
+= box_line_vwidth
;
3887 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3889 s
->background_filled_p
= 1;
3892 /* Draw the foreground. */
3893 x_draw_image_foreground (s
);
3895 /* If we must draw a relief around the image, do it. */
3897 || s
->hl
== DRAW_IMAGE_RAISED
3898 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3899 x_draw_image_relief (s
);
3903 /* Draw stretch glyph string S. */
3906 x_draw_stretch_glyph_string (s
)
3907 struct glyph_string
*s
;
3909 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3911 if (s
->hl
== DRAW_CURSOR
3912 && !x_stretch_cursor_p
)
3914 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3915 as wide as the stretch glyph. */
3916 int width
, background_width
= s
->background_width
;
3917 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3921 background_width
-= left_x
- x
;
3924 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3927 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3929 /* Clear rest using the GC of the original non-cursor face. */
3930 if (width
< background_width
)
3933 int w
= background_width
- width
, h
= s
->height
;
3938 if (s
->row
->mouse_face_p
3939 && cursor_in_mouse_face_p (s
->w
))
3941 x_set_mouse_face_gc (s
);
3947 get_glyph_string_clip_rect (s
, &r
);
3948 mac_set_clip_rectangles (s
->f
, gc
, &r
, 1);
3950 #if 0 /* MAC_TODO: stipple */
3951 if (s
->face
->stipple
)
3953 /* Fill background with a stipple pattern. */
3954 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3955 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3956 XSetFillStyle (s
->display
, gc
, FillSolid
);
3959 #endif /* MAC_TODO */
3960 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3963 else if (!s
->background_filled_p
)
3965 int background_width
= s
->background_width
;
3966 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3968 /* Don't draw into left margin, fringe or scrollbar area
3969 except for header line and mode line. */
3970 if (x
< left_x
&& !s
->row
->mode_line_p
)
3972 background_width
-= left_x
- x
;
3975 if (background_width
> 0)
3976 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3979 s
->background_filled_p
= 1;
3983 /* Draw glyph string S. */
3986 x_draw_glyph_string (s
)
3987 struct glyph_string
*s
;
3989 int relief_drawn_p
= 0;
3991 /* If S draws into the background of its successor that does not
3992 draw a cursor, draw the background of the successor first so that
3993 S can draw into it. This makes S->next use XDrawString instead
3994 of XDrawImageString. */
3995 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3996 && s
->next
->hl
!= DRAW_CURSOR
)
3998 xassert (s
->next
->img
== NULL
);
3999 x_set_glyph_string_gc (s
->next
);
4000 x_set_glyph_string_clipping (s
->next
);
4001 x_draw_glyph_string_background (s
->next
, 1);
4004 /* Set up S->gc, set clipping and draw S. */
4005 x_set_glyph_string_gc (s
);
4007 /* Draw relief (if any) in advance for char/composition so that the
4008 glyph string can be drawn over it. */
4009 if (!s
->for_overlaps
4010 && s
->face
->box
!= FACE_NO_BOX
4011 && (s
->first_glyph
->type
== CHAR_GLYPH
4012 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
4015 x_set_glyph_string_clipping (s
);
4016 x_draw_glyph_string_background (s
, 1);
4017 x_draw_glyph_string_box (s
);
4018 x_set_glyph_string_clipping (s
);
4022 x_set_glyph_string_clipping (s
);
4024 switch (s
->first_glyph
->type
)
4027 x_draw_image_glyph_string (s
);
4031 x_draw_stretch_glyph_string (s
);
4035 if (s
->for_overlaps
)
4036 s
->background_filled_p
= 1;
4038 x_draw_glyph_string_background (s
, 0);
4039 x_draw_glyph_string_foreground (s
);
4042 case COMPOSITE_GLYPH
:
4043 if (s
->for_overlaps
|| s
->gidx
> 0)
4044 s
->background_filled_p
= 1;
4046 x_draw_glyph_string_background (s
, 1);
4047 x_draw_composite_glyph_string_foreground (s
);
4054 if (!s
->for_overlaps
)
4056 /* Draw underline. */
4057 if (s
->face
->underline_p
)
4059 unsigned long tem
, h
;
4063 /* Get the underline thickness. Default is 1 pixel. */
4064 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
4068 y
= s
->y
+ s
->height
- h
;
4069 if (!x_underline_at_descent_line
)
4071 /* Get the underline position. This is the recommended
4072 vertical offset in pixels from the baseline to the top of
4073 the underline. This is a signed value according to the
4074 specs, and its default is
4076 ROUND ((maximum descent) / 2), with
4077 ROUND(x) = floor (x + 0.5) */
4080 if (x_use_underline_position_properties
4081 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
4082 y
= s
->ybase
+ (long) tem
;
4086 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
4089 if (s
->face
->underline_defaulted_p
)
4090 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
4091 s
->background_width
, h
);
4095 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4096 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4097 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
4098 s
->background_width
, h
);
4099 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4103 /* Draw overline. */
4104 if (s
->face
->overline_p
)
4106 unsigned long dy
= 0, h
= 1;
4108 if (s
->face
->overline_color_defaulted_p
)
4109 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4110 s
->background_width
, h
);
4114 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4115 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4116 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4117 s
->background_width
, h
);
4118 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4122 /* Draw strike-through. */
4123 if (s
->face
->strike_through_p
)
4125 unsigned long h
= 1;
4126 unsigned long dy
= (s
->height
- h
) / 2;
4128 if (s
->face
->strike_through_color_defaulted_p
)
4129 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4134 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4135 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4136 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4138 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4142 /* Draw relief if not yet drawn. */
4143 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4144 x_draw_glyph_string_box (s
);
4147 /* Reset clipping. */
4148 mac_reset_clip_rectangles (s
->f
, s
->gc
);
4151 /* Shift display to make room for inserted glyphs. */
4154 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4156 int x
, y
, width
, height
, shift_by
;
4158 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4159 x
, y
, width
, height
,
4163 /* Delete N glyphs at the nominal cursor position. Not implemented
4174 /* Clear entire frame. If updating_frame is non-null, clear that
4175 frame. Otherwise clear the selected frame. */
4178 x_clear_frame (struct frame
*f
)
4180 /* Clearing the frame will erase any cursor, so mark them all as no
4182 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4183 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4184 output_cursor
.x
= -1;
4186 /* We don't set the output cursor here because there will always
4187 follow an explicit cursor_to. */
4189 mac_clear_window (f
);
4191 /* We have to clear the scroll bars, too. If we have changed
4192 colors or something like that, then they should be notified. */
4193 x_scroll_bar_clear (f
);
4195 XFlush (FRAME_MAC_DISPLAY (f
));
4201 /* Invert the middle quarter of the frame for .15 sec. */
4203 /* We use the select system call to do the waiting, so we have to make
4204 sure it's available. If it isn't, we just won't do visual bells. */
4206 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4209 /* Subtract the `struct timeval' values X and Y, storing the result in
4210 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4213 timeval_subtract (result
, x
, y
)
4214 struct timeval
*result
, x
, y
;
4216 /* Perform the carry for the later subtraction by updating y. This
4217 is safer because on some systems the tv_sec member is unsigned. */
4218 if (x
.tv_usec
< y
.tv_usec
)
4220 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4221 y
.tv_usec
-= 1000000 * nsec
;
4225 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4227 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4228 y
.tv_usec
+= 1000000 * nsec
;
4232 /* Compute the time remaining to wait. tv_usec is certainly
4234 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4235 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4237 /* Return indication of whether the result should be considered
4239 return x
.tv_sec
< y
.tv_sec
;
4246 /* Get the height not including a menu bar widget. */
4247 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4248 /* Height of each line to flash. */
4249 int flash_height
= FRAME_LINE_HEIGHT (f
);
4250 /* These will be the left and right margins of the rectangles. */
4251 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4252 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4256 /* Don't flash the area between a scroll bar and the frame
4257 edge it is next to. */
4258 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4260 case vertical_scroll_bar_left
:
4261 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4264 case vertical_scroll_bar_right
:
4265 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4272 width
= flash_right
- flash_left
;
4276 /* If window is tall, flash top and bottom line. */
4277 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4279 mac_invert_rectangle (f
, flash_left
,
4280 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4281 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4282 width
, flash_height
);
4283 mac_invert_rectangle (f
, flash_left
,
4284 (height
- flash_height
4285 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4286 width
, flash_height
);
4289 /* If it is short, flash it all. */
4290 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4291 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4296 struct timeval wakeup
;
4298 EMACS_GET_TIME (wakeup
);
4300 /* Compute time to wait until, propagating carry from usecs. */
4301 wakeup
.tv_usec
+= 150000;
4302 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4303 wakeup
.tv_usec
%= 1000000;
4305 /* Keep waiting until past the time wakeup or any input gets
4307 while (! detect_input_pending ())
4309 struct timeval current
;
4310 struct timeval timeout
;
4312 EMACS_GET_TIME (current
);
4314 /* Break if result would be negative. */
4315 if (timeval_subtract (¤t
, wakeup
, current
))
4318 /* How long `select' should wait. */
4320 timeout
.tv_usec
= 10000;
4322 /* Try to wait that long--but we might wake up sooner. */
4323 select (0, NULL
, NULL
, NULL
, &timeout
);
4327 /* If window is tall, flash top and bottom line. */
4328 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4330 mac_invert_rectangle (f
, flash_left
,
4331 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4332 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4333 width
, flash_height
);
4334 mac_invert_rectangle (f
, flash_left
,
4335 (height
- flash_height
4336 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4337 width
, flash_height
);
4340 /* If it is short, flash it all. */
4341 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4342 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4349 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4352 /* Make audible bell. */
4357 struct frame
*f
= SELECTED_FRAME ();
4359 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4367 XFlush (FRAME_MAC_DISPLAY (f
));
4373 /* Specify how many text lines, from the top of the window,
4374 should be affected by insert-lines and delete-lines operations.
4375 This, and those operations, are used only within an update
4376 that is bounded by calls to x_update_begin and x_update_end. */
4379 XTset_terminal_window (n
)
4382 /* This function intentionally left blank. */
4387 /***********************************************************************
4389 ***********************************************************************/
4391 /* Perform an insert-lines or delete-lines operation, inserting N
4392 lines or deleting -N lines at vertical position VPOS. */
4395 x_ins_del_lines (vpos
, n
)
4402 /* Scroll part of the display as described by RUN. */
4405 x_scroll_run (w
, run
)
4409 struct frame
*f
= XFRAME (w
->frame
);
4410 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4412 /* Get frame-relative bounding box of the text display area of W,
4413 without mode lines. Include in this box the left and right
4415 window_box (w
, -1, &x
, &y
, &width
, &height
);
4417 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4418 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4419 bottom_y
= y
+ height
;
4423 /* Scrolling up. Make sure we don't copy part of the mode
4424 line at the bottom. */
4425 if (from_y
+ run
->height
> bottom_y
)
4426 height
= bottom_y
- from_y
;
4428 height
= run
->height
;
4432 /* Scolling down. Make sure we don't copy over the mode line.
4434 if (to_y
+ run
->height
> bottom_y
)
4435 height
= bottom_y
- to_y
;
4437 height
= run
->height
;
4442 /* Cursor off. Will be switched on again in x_update_window_end. */
4446 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4456 /***********************************************************************
4458 ***********************************************************************/
4465 x_update_cursor (f
, 1);
4469 frame_unhighlight (f
)
4472 x_update_cursor (f
, 1);
4475 /* The focus has changed. Update the frames as necessary to reflect
4476 the new situation. Note that we can't change the selected frame
4477 here, because the Lisp code we are interrupting might become confused.
4478 Each event gets marked with the frame in which it occurred, so the
4479 Lisp code can tell when the switch took place by examining the events. */
4482 x_new_focus_frame (dpyinfo
, frame
)
4483 struct x_display_info
*dpyinfo
;
4484 struct frame
*frame
;
4486 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4488 if (frame
!= dpyinfo
->x_focus_frame
)
4490 /* Set this before calling other routines, so that they see
4491 the correct value of x_focus_frame. */
4492 dpyinfo
->x_focus_frame
= frame
;
4494 if (old_focus
&& old_focus
->auto_lower
)
4495 x_lower_frame (old_focus
);
4498 selected_frame
= frame
;
4499 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4501 Fselect_window (selected_frame
->selected_window
, Qnil
);
4502 choose_minibuf_frame ();
4505 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4506 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4508 pending_autoraise_frame
= 0;
4510 #if USE_MAC_FONT_PANEL
4512 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4516 x_frame_rehighlight (dpyinfo
);
4519 /* Handle FocusIn and FocusOut state changes for FRAME.
4520 If FRAME has focus and there exists more than one frame, puts
4521 a FOCUS_IN_EVENT into *BUFP. */
4524 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4526 struct mac_display_info
*dpyinfo
;
4527 struct frame
*frame
;
4528 struct input_event
*bufp
;
4530 if (type
== activeFlag
)
4532 if (dpyinfo
->x_focus_event_frame
!= frame
)
4534 x_new_focus_frame (dpyinfo
, frame
);
4535 dpyinfo
->x_focus_event_frame
= frame
;
4537 /* Don't stop displaying the initial startup message
4538 for a switch-frame event we don't need. */
4539 if (NILP (Vterminal_frame
)
4540 && CONSP (Vframe_list
)
4541 && !NILP (XCDR (Vframe_list
)))
4543 bufp
->kind
= FOCUS_IN_EVENT
;
4544 XSETFRAME (bufp
->frame_or_window
, frame
);
4550 if (dpyinfo
->x_focus_event_frame
== frame
)
4552 dpyinfo
->x_focus_event_frame
= 0;
4553 x_new_focus_frame (dpyinfo
, 0);
4558 /* The focus may have changed. Figure out if it is a real focus change,
4559 by checking both FocusIn/Out and Enter/LeaveNotify events.
4561 Returns FOCUS_IN_EVENT event in *BUFP. */
4564 x_detect_focus_change (dpyinfo
, event
, bufp
)
4565 struct mac_display_info
*dpyinfo
;
4566 const EventRecord
*event
;
4567 struct input_event
*bufp
;
4569 struct frame
*frame
;
4571 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4575 /* On Mac, this is only called from focus events, so no switch needed. */
4576 mac_focus_changed ((event
->modifiers
& activeFlag
),
4577 dpyinfo
, frame
, bufp
);
4581 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4584 x_mouse_leave (dpyinfo
)
4585 struct x_display_info
*dpyinfo
;
4587 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4590 /* The focus has changed, or we have redirected a frame's focus to
4591 another frame (this happens when a frame uses a surrogate
4592 mini-buffer frame). Shift the highlight as appropriate.
4594 The FRAME argument doesn't necessarily have anything to do with which
4595 frame is being highlighted or un-highlighted; we only use it to find
4596 the appropriate X display info. */
4599 XTframe_rehighlight (frame
)
4600 struct frame
*frame
;
4602 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4606 x_frame_rehighlight (dpyinfo
)
4607 struct x_display_info
*dpyinfo
;
4609 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4611 if (dpyinfo
->x_focus_frame
)
4613 dpyinfo
->x_highlight_frame
4614 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4615 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4616 : dpyinfo
->x_focus_frame
);
4617 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4619 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4620 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4624 dpyinfo
->x_highlight_frame
= 0;
4626 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4629 frame_unhighlight (old_highlight
);
4630 if (dpyinfo
->x_highlight_frame
)
4631 frame_highlight (dpyinfo
->x_highlight_frame
);
4637 /* Convert a keysym to its name. */
4640 x_get_keysym_name (keysym
)
4647 value
= XKeysymToString (keysym
);
4658 /* Function to report a mouse movement to the mainstream Emacs code.
4659 The input handler calls this.
4661 We have received a mouse movement event, which is given in *event.
4662 If the mouse is over a different glyph than it was last time, tell
4663 the mainstream emacs code by setting mouse_moved. If not, ask for
4664 another motion event, so we can check again the next time it moves. */
4666 static Point last_mouse_motion_position
;
4667 static Lisp_Object last_mouse_motion_frame
;
4670 note_mouse_movement (frame
, pos
)
4674 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4675 #if TARGET_API_MAC_CARBON
4679 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4680 last_mouse_motion_position
= *pos
;
4681 XSETFRAME (last_mouse_motion_frame
, frame
);
4683 if (frame
== dpyinfo
->mouse_face_mouse_frame
4684 #if TARGET_API_MAC_CARBON
4685 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4687 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4691 /* This case corresponds to LeaveNotify in X11. If we move
4692 outside the frame, then we're certainly no longer on any text
4694 clear_mouse_face (dpyinfo
);
4695 dpyinfo
->mouse_face_mouse_frame
= 0;
4696 if (!dpyinfo
->grabbed
)
4697 FRAME_RIF (frame
)->define_frame_cursor (frame
,
4698 frame
->output_data
.mac
->nontext_cursor
);
4701 /* Has the mouse moved off the glyph it was on at the last sighting? */
4702 if (frame
!= last_mouse_glyph_frame
4703 || !PtInRect (*pos
, &last_mouse_glyph
))
4705 frame
->mouse_moved
= 1;
4706 last_mouse_scroll_bar
= Qnil
;
4707 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4708 /* Remember which glyph we're now on. */
4709 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4710 last_mouse_glyph_frame
= frame
;
4718 /************************************************************************
4720 ************************************************************************/
4722 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4725 redo_mouse_highlight ()
4727 if (!NILP (last_mouse_motion_frame
)
4728 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4729 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4730 last_mouse_motion_position
.h
,
4731 last_mouse_motion_position
.v
);
4735 static struct frame
*
4736 mac_focus_frame (dpyinfo
)
4737 struct mac_display_info
*dpyinfo
;
4739 if (dpyinfo
->x_focus_frame
)
4740 return dpyinfo
->x_focus_frame
;
4742 /* Mac version may get events, such as a menu bar click, even when
4743 all the frames are invisible. In this case, we regard the
4744 event came to the selected frame. */
4745 return SELECTED_FRAME ();
4749 /* Return the current position of the mouse.
4750 *FP should be a frame which indicates which display to ask about.
4752 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4753 and *PART to the frame, window, and scroll bar part that the mouse
4754 is over. Set *X and *Y to the portion and whole of the mouse's
4755 position on the scroll bar.
4757 If the mouse movement started elsewhere, set *FP to the frame the
4758 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4761 Set *TIME to the server time-stamp for the time at which the mouse
4762 was at this position.
4764 Don't store anything if we don't have a valid set of values to report.
4766 This clears the mouse_moved flag, so we can wait for the next mouse
4770 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4773 Lisp_Object
*bar_window
;
4774 enum scroll_bar_part
*part
;
4776 unsigned long *time
;
4782 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4783 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4786 Lisp_Object frame
, tail
;
4788 /* Clear the mouse-moved flag for every frame on this display. */
4789 FOR_EACH_FRAME (tail
, frame
)
4790 XFRAME (frame
)->mouse_moved
= 0;
4792 last_mouse_scroll_bar
= Qnil
;
4794 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4795 && FRAME_LIVE_P (last_mouse_frame
))
4796 f1
= last_mouse_frame
;
4798 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4802 /* Ok, we found a frame. Store all the values.
4803 last_mouse_glyph is a rectangle used to reduce the
4804 generation of mouse events. To not miss any motion
4805 events, we must divide the frame into rectangles of the
4806 size of the smallest character that could be displayed
4807 on it, i.e. into the same rectangles that matrices on
4808 the frame are divided into. */
4811 #if TARGET_API_MAC_CARBON
4812 GetGlobalMouse (&mouse_pos
);
4813 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4814 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4816 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4817 GetMouse (&mouse_pos
);
4819 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4821 last_mouse_glyph_frame
= f1
;
4826 XSETINT (*x
, mouse_pos
.h
);
4827 XSETINT (*y
, mouse_pos
.v
);
4828 *time
= last_mouse_movement_time
;
4836 /************************************************************************
4838 ************************************************************************/
4840 #ifdef USE_TOOLKIT_SCROLL_BARS
4842 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4843 static OSStatus install_scroll_bar_timer
P_ ((void));
4844 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4845 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4846 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4847 struct input_event
*));
4848 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4850 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4851 ControlPartCode
, Point
,
4852 struct input_event
*));
4853 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4854 struct input_event
*));
4855 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4856 Point
, struct input_event
*));
4857 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4860 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4862 static int last_scroll_bar_part
;
4864 static EventLoopTimerRef scroll_bar_timer
;
4866 static int scroll_bar_timer_event_posted_p
;
4868 #define SCROLL_BAR_FIRST_DELAY 0.5
4869 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4872 scroll_bar_timer_callback (timer
, data
)
4873 EventLoopTimerRef timer
;
4878 err
= mac_post_mouse_moved_event ();
4880 scroll_bar_timer_event_posted_p
= 1;
4884 install_scroll_bar_timer ()
4886 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4888 if (scroll_bar_timer_callbackUPP
== NULL
)
4889 scroll_bar_timer_callbackUPP
=
4890 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4892 if (scroll_bar_timer
== NULL
)
4893 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4894 kEventDurationForever as delays. */
4896 InstallEventLoopTimer (GetCurrentEventLoop (),
4897 kEventDurationForever
, kEventDurationForever
,
4898 scroll_bar_timer_callbackUPP
, NULL
,
4903 set_scroll_bar_timer (delay
)
4904 EventTimerInterval delay
;
4906 if (scroll_bar_timer
== NULL
)
4907 install_scroll_bar_timer ();
4909 scroll_bar_timer_event_posted_p
= 0;
4911 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4915 control_part_code_to_scroll_bar_part (part_code
)
4916 ControlPartCode part_code
;
4920 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4921 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4922 case kControlPageUpPart
: return scroll_bar_above_handle
;
4923 case kControlPageDownPart
: return scroll_bar_below_handle
;
4924 case kControlIndicatorPart
: return scroll_bar_handle
;
4931 construct_scroll_bar_click (bar
, part
, bufp
)
4932 struct scroll_bar
*bar
;
4934 struct input_event
*bufp
;
4936 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4937 bufp
->frame_or_window
= bar
->window
;
4941 XSETINT (bufp
->x
, 0);
4942 XSETINT (bufp
->y
, 0);
4943 bufp
->modifiers
= 0;
4947 get_control_part_bounds (ch
, part_code
, rect
)
4949 ControlPartCode part_code
;
4952 RgnHandle region
= NewRgn ();
4955 err
= GetControlRegion (ch
, part_code
, region
);
4957 GetRegionBounds (region
, rect
);
4958 DisposeRgn (region
);
4964 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4965 struct scroll_bar
*bar
;
4966 ControlPartCode part_code
;
4968 struct input_event
*bufp
;
4970 int part
= control_part_code_to_scroll_bar_part (part_code
);
4975 if (part
!= scroll_bar_handle
)
4977 construct_scroll_bar_click (bar
, part
, bufp
);
4978 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4979 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4980 bar
->dragging
= Qnil
;
4986 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4987 kControlIndicatorPart
, &r
);
4988 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4991 last_scroll_bar_part
= part
;
4992 tracked_scroll_bar
= bar
;
4996 x_scroll_bar_handle_release (bar
, bufp
)
4997 struct scroll_bar
*bar
;
4998 struct input_event
*bufp
;
5000 if (last_scroll_bar_part
!= scroll_bar_handle
5001 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
5002 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
5004 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
5005 set_scroll_bar_timer (kEventDurationForever
);
5007 last_scroll_bar_part
= -1;
5008 bar
->dragging
= Qnil
;
5009 tracked_scroll_bar
= NULL
;
5013 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
5015 struct scroll_bar
*bar
;
5017 struct input_event
*bufp
;
5019 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5021 if (last_scroll_bar_part
== scroll_bar_handle
)
5026 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
5027 kControlIndicatorPart
, &r
);
5029 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
5030 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
5032 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
5033 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
5037 if (top
> top_range
)
5040 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
5041 XSETINT (bufp
->x
, top
);
5042 XSETINT (bufp
->y
, top_range
);
5046 ControlPartCode part_code
;
5047 int unhilite_p
= 0, part
;
5049 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
5053 part
= control_part_code_to_scroll_bar_part (part_code
);
5055 switch (last_scroll_bar_part
)
5057 case scroll_bar_above_handle
:
5058 case scroll_bar_below_handle
:
5059 if (part
!= scroll_bar_above_handle
5060 && part
!= scroll_bar_below_handle
)
5064 case scroll_bar_up_arrow
:
5065 case scroll_bar_down_arrow
:
5066 if (part
!= scroll_bar_up_arrow
5067 && part
!= scroll_bar_down_arrow
)
5074 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
5075 else if (part
!= last_scroll_bar_part
5076 || scroll_bar_timer_event_posted_p
)
5078 construct_scroll_bar_click (bar
, part
, bufp
);
5079 last_scroll_bar_part
= part
;
5080 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
5081 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
5086 /* Set the thumb size and position of scroll bar BAR. We are currently
5087 displaying PORTION out of a whole WHOLE, and our position POSITION. */
5090 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
5091 struct scroll_bar
*bar
;
5092 int portion
, position
, whole
;
5094 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5095 int value
, viewsize
, maximum
;
5097 if (XINT (bar
->track_height
) == 0)
5100 if (whole
<= portion
)
5101 value
= 0, viewsize
= 1, maximum
= 0;
5106 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
5107 scale
= (float) maximum
/ (whole
- portion
);
5108 value
= position
* scale
+ 0.5f
;
5109 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
5114 if (GetControlViewSize (ch
) != viewsize
5115 || GetControl32BitValue (ch
) != value
5116 || GetControl32BitMaximum (ch
) != maximum
)
5118 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5119 SetControlVisibility (ch
, false, false);
5121 SetControl32BitMaximum (ch
, maximum
);
5122 SetControl32BitValue (ch
, value
);
5123 SetControlViewSize (ch
, viewsize
);
5125 SetControlVisibility (ch
, true, true);
5131 #endif /* USE_TOOLKIT_SCROLL_BARS */
5135 /************************************************************************
5136 Scroll bars, general
5137 ************************************************************************/
5139 /* Create a scroll bar and return the scroll bar vector for it. W is
5140 the Emacs window on which to create the scroll bar. TOP, LEFT,
5141 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5144 static struct scroll_bar
*
5145 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5147 int top
, left
, width
, height
, disp_top
, disp_height
;
5149 struct frame
*f
= XFRAME (w
->frame
);
5150 struct scroll_bar
*bar
5151 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5159 r
.right
= left
+ width
;
5160 r
.bottom
= disp_top
+ disp_height
;
5163 mac_prepare_for_quickdraw (f
);
5165 #if TARGET_API_MAC_CARBON
5166 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5167 #ifdef USE_TOOLKIT_SCROLL_BARS
5170 width
< disp_height
,
5172 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5174 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5175 0, 0, 0, scrollBarProc
, (long) bar
);
5177 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5179 XSETWINDOW (bar
->window
, w
);
5180 XSETINT (bar
->top
, top
);
5181 XSETINT (bar
->left
, left
);
5182 XSETINT (bar
->width
, width
);
5183 XSETINT (bar
->height
, height
);
5184 XSETINT (bar
->start
, 0);
5185 XSETINT (bar
->end
, 0);
5186 bar
->dragging
= Qnil
;
5188 bar
->fringe_extended_p
= Qnil
;
5190 bar
->redraw_needed_p
= Qnil
;
5191 #ifdef USE_TOOLKIT_SCROLL_BARS
5192 bar
->track_top
= Qnil
;
5193 bar
->track_height
= Qnil
;
5194 bar
->min_handle
= Qnil
;
5197 /* Add bar to its frame's list of scroll bars. */
5198 bar
->next
= FRAME_SCROLL_BARS (f
);
5200 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5201 if (!NILP (bar
->next
))
5202 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5209 /* Draw BAR's handle in the proper position.
5211 If the handle is already drawn from START to END, don't bother
5212 redrawing it, unless REBUILD is non-zero; in that case, always
5213 redraw it. (REBUILD is handy for drawing the handle after expose
5216 Normally, we want to constrain the start and end of the handle to
5217 fit inside its rectangle, but if the user is dragging the scroll
5218 bar handle, we want to let them drag it down all the way, so that
5219 the bar's top is as far down as it goes; otherwise, there's no way
5220 to move to the very end of the buffer. */
5222 #ifndef USE_TOOLKIT_SCROLL_BARS
5225 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5226 struct scroll_bar
*bar
;
5230 int dragging
= ! NILP (bar
->dragging
);
5231 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5232 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5233 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5234 int length
= end
- start
;
5236 /* If the display is already accurate, do nothing. */
5238 && start
== XINT (bar
->start
)
5239 && end
== XINT (bar
->end
))
5244 /* Make sure the values are reasonable, and try to preserve the
5245 distance between start and end. */
5248 else if (start
> top_range
)
5250 end
= start
+ length
;
5254 else if (end
> top_range
&& ! dragging
)
5257 /* Store the adjusted setting in the scroll bar. */
5258 XSETINT (bar
->start
, start
);
5259 XSETINT (bar
->end
, end
);
5261 /* Clip the end position, just for display. */
5262 if (end
> top_range
)
5265 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5266 top positions, to make sure the handle is always at least that
5267 many pixels tall. */
5268 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5270 SetControlMinimum (ch
, 0);
5271 /* Don't inadvertently activate deactivated scroll bars */
5272 if (GetControlMaximum (ch
) != -1)
5273 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5275 SetControlValue (ch
, start
);
5276 #if TARGET_API_MAC_CARBON
5277 SetControlViewSize (ch
, end
- start
);
5283 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5285 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5289 x_scroll_bar_remove (bar
)
5290 struct scroll_bar
*bar
;
5292 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5297 mac_prepare_for_quickdraw (f
);
5299 /* Destroy the Mac scroll bar control */
5300 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5302 /* Disassociate this scroll bar from its window. */
5303 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5309 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5310 that we are displaying PORTION characters out of a total of WHOLE
5311 characters, starting at POSITION. If WINDOW has no scroll bar,
5315 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5317 int portion
, whole
, position
;
5319 struct frame
*f
= XFRAME (w
->frame
);
5320 struct scroll_bar
*bar
;
5321 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5322 int window_y
, window_height
;
5324 int fringe_extended_p
;
5327 /* Get window dimensions. */
5328 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5330 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5331 height
= window_height
;
5333 /* Compute the left edge of the scroll bar area. */
5334 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5336 /* Compute the width of the scroll bar which might be less than
5337 the width of the area reserved for the scroll bar. */
5338 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5339 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5343 /* Compute the left edge of the scroll bar. */
5344 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5345 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5347 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5349 /* Adjustments according to Inside Macintosh to make it look nice */
5351 disp_height
= height
;
5358 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5364 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5369 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5370 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5371 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5372 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5373 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5375 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5376 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5377 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5378 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5381 /* Does the scroll bar exist yet? */
5382 if (NILP (w
->vertical_scroll_bar
))
5386 if (fringe_extended_p
)
5387 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5390 mac_clear_area (f
, left
, top
, width
, height
);
5392 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5394 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5398 /* It may just need to be moved and resized. */
5401 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5402 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5406 /* If already correctly positioned, do nothing. */
5407 if (XINT (bar
->left
) == sb_left
5408 && XINT (bar
->top
) == top
5409 && XINT (bar
->width
) == sb_width
5410 && XINT (bar
->height
) == height
5412 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5416 if (!NILP (bar
->redraw_needed_p
))
5419 mac_prepare_for_quickdraw (f
);
5421 Draw1Control (SCROLL_BAR_CONTROL_REF (bar
));
5426 /* Since toolkit scroll bars are smaller than the space reserved
5427 for them on the frame, we have to clear "under" them. */
5429 if (fringe_extended_p
)
5430 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5433 mac_clear_area (f
, left
, top
, width
, height
);
5436 mac_prepare_for_quickdraw (f
);
5439 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5440 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5442 #ifndef USE_TOOLKIT_SCROLL_BARS
5443 if (sb_width
< disp_height
)
5447 /* Remember new settings. */
5448 XSETINT (bar
->left
, sb_left
);
5449 XSETINT (bar
->top
, top
);
5450 XSETINT (bar
->width
, sb_width
);
5451 XSETINT (bar
->height
, height
);
5452 #ifdef USE_TOOLKIT_SCROLL_BARS
5453 bar
->track_top
= Qnil
;
5454 bar
->track_height
= Qnil
;
5455 bar
->min_handle
= Qnil
;
5463 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5466 bar
->redraw_needed_p
= Qnil
;
5468 #ifdef USE_TOOLKIT_SCROLL_BARS
5469 if (NILP (bar
->track_top
))
5471 if (sb_width
>= disp_height
5473 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5477 XSETINT (bar
->track_top
, 0);
5478 XSETINT (bar
->track_height
, 0);
5479 XSETINT (bar
->min_handle
, 0);
5483 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5488 SetControl32BitMinimum (ch
, 0);
5489 SetControl32BitMaximum (ch
, 1 << 30);
5490 SetControlViewSize (ch
, 1);
5492 /* Move the scroll bar thumb to the top. */
5493 SetControl32BitValue (ch
, 0);
5494 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5496 /* Move the scroll bar thumb to the bottom. */
5497 SetControl32BitValue (ch
, 1 << 30);
5498 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5500 UnionRect (&r0
, &r1
, &r0
);
5501 XSETINT (bar
->track_top
, r0
.top
);
5502 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5503 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5505 /* Don't show the scroll bar if its height is not enough to
5506 display the scroll bar thumb. */
5507 if (r0
.bottom
- r0
.top
> 0)
5514 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5515 #else /* not USE_TOOLKIT_SCROLL_BARS */
5516 /* Set the scroll bar's current state, unless we're currently being
5518 if (NILP (bar
->dragging
))
5520 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5523 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5526 int start
= ((double) position
* top_range
) / whole
;
5527 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5528 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5531 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5535 /* The following three hooks are used when we're doing a thorough
5536 redisplay of the frame. We don't explicitly know which scroll bars
5537 are going to be deleted, because keeping track of when windows go
5538 away is a real pain - "Can you say set-window-configuration, boys
5539 and girls?" Instead, we just assert at the beginning of redisplay
5540 that *all* scroll bars are to be removed, and then save a scroll bar
5541 from the fiery pit when we actually redisplay its window. */
5543 /* Arrange for all scroll bars on FRAME to be removed at the next call
5544 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5545 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5548 XTcondemn_scroll_bars (frame
)
5551 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5552 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5555 bar
= FRAME_SCROLL_BARS (frame
);
5556 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5557 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5558 XSCROLL_BAR (bar
)->prev
= Qnil
;
5559 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5560 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5561 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5566 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5567 Note that WINDOW isn't necessarily condemned at all. */
5570 XTredeem_scroll_bar (window
)
5571 struct window
*window
;
5573 struct scroll_bar
*bar
;
5576 /* We can't redeem this window's scroll bar if it doesn't have one. */
5577 if (NILP (window
->vertical_scroll_bar
))
5580 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5582 /* Unlink it from the condemned list. */
5583 f
= XFRAME (WINDOW_FRAME (window
));
5584 if (NILP (bar
->prev
))
5586 /* If the prev pointer is nil, it must be the first in one of
5588 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5589 /* It's not condemned. Everything's fine. */
5591 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5592 window
->vertical_scroll_bar
))
5593 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5595 /* If its prev pointer is nil, it must be at the front of
5596 one or the other! */
5600 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5602 if (! NILP (bar
->next
))
5603 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5605 bar
->next
= FRAME_SCROLL_BARS (f
);
5607 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5608 if (! NILP (bar
->next
))
5609 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5612 /* Remove all scroll bars on FRAME that haven't been saved since the
5613 last call to `*condemn_scroll_bars_hook'. */
5616 XTjudge_scroll_bars (f
)
5619 Lisp_Object bar
, next
;
5621 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5623 /* Clear out the condemned list now so we won't try to process any
5624 more events on the hapless scroll bars. */
5625 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5627 for (; ! NILP (bar
); bar
= next
)
5629 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5631 x_scroll_bar_remove (b
);
5634 b
->next
= b
->prev
= Qnil
;
5637 /* Now there should be no references to the condemned scroll bars,
5638 and they should get garbage-collected. */
5642 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5643 is set to something other than NO_EVENT, it is enqueued.
5645 This may be called from a signal handler, so we have to ignore GC
5649 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5650 struct scroll_bar
*bar
;
5651 ControlPartCode part_code
;
5652 const EventRecord
*er
;
5653 struct input_event
*bufp
;
5655 int win_y
, top_range
;
5657 if (! WINDOWP (bar
->window
))
5660 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5661 bufp
->frame_or_window
= bar
->window
;
5664 bar
->dragging
= Qnil
;
5668 case kControlUpButtonPart
:
5669 bufp
->part
= scroll_bar_up_arrow
;
5671 case kControlDownButtonPart
:
5672 bufp
->part
= scroll_bar_down_arrow
;
5674 case kControlPageUpPart
:
5675 bufp
->part
= scroll_bar_above_handle
;
5677 case kControlPageDownPart
:
5678 bufp
->part
= scroll_bar_below_handle
;
5680 #if TARGET_API_MAC_CARBON
5683 case kControlIndicatorPart
:
5685 if (er
->what
== mouseDown
)
5686 bar
->dragging
= make_number (0);
5687 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5688 bufp
->part
= scroll_bar_handle
;
5692 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5693 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5695 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5699 if (! NILP (bar
->dragging
))
5700 win_y
-= XINT (bar
->dragging
);
5704 if (win_y
> top_range
)
5707 XSETINT (bufp
->x
, win_y
);
5708 XSETINT (bufp
->y
, top_range
);
5711 #ifndef USE_TOOLKIT_SCROLL_BARS
5713 /* Handle some mouse motion while someone is dragging the scroll bar.
5715 This may be called from a signal handler, so we have to ignore GC
5719 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5720 struct scroll_bar
*bar
;
5724 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5726 last_mouse_movement_time
= t
;
5729 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5731 /* If we're dragging the bar, display it. */
5732 if (! NILP (bar
->dragging
))
5734 /* Where should the handle be now? */
5735 int new_start
= y_pos
- 24;
5737 if (new_start
!= XINT (bar
->start
))
5739 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5741 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5746 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5748 /* Return information to the user about the current position of the mouse
5749 on the scroll bar. */
5752 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5754 Lisp_Object
*bar_window
;
5755 enum scroll_bar_part
*part
;
5757 unsigned long *time
;
5759 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5760 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5761 #if TARGET_API_MAC_CARBON
5762 WindowRef wp
= GetControlOwner (ch
);
5764 WindowRef wp
= (*ch
)->contrlOwner
;
5767 struct frame
*f
= mac_window_to_frame (wp
);
5768 int win_y
, top_range
;
5770 #if TARGET_API_MAC_CARBON
5771 GetGlobalMouse (&mouse_pos
);
5772 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5773 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5775 SetPortWindowPort (wp
);
5776 GetMouse (&mouse_pos
);
5779 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5780 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5782 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5786 if (! NILP (bar
->dragging
))
5787 win_y
-= XINT (bar
->dragging
);
5791 if (win_y
> top_range
)
5795 *bar_window
= bar
->window
;
5797 if (! NILP (bar
->dragging
))
5798 *part
= scroll_bar_handle
;
5799 else if (win_y
< XINT (bar
->start
))
5800 *part
= scroll_bar_above_handle
;
5801 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5802 *part
= scroll_bar_handle
;
5804 *part
= scroll_bar_below_handle
;
5806 XSETINT (*x
, win_y
);
5807 XSETINT (*y
, top_range
);
5810 last_mouse_scroll_bar
= Qnil
;
5812 *time
= last_mouse_movement_time
;
5816 /* The screen has been cleared so we may have changed foreground or
5817 background colors, and the scroll bars may need to be redrawn.
5818 Clear out the scroll bars, and ask for expose events, so we can
5822 x_scroll_bar_clear (f
)
5827 /* We can have scroll bars even if this is 0,
5828 if we just turned off scroll bar mode.
5829 But in that case we should not clear them. */
5830 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5831 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5832 bar
= XSCROLL_BAR (bar
)->next
)
5833 XSCROLL_BAR (bar
)->redraw_needed_p
= Qt
;
5837 /***********************************************************************
5839 ***********************************************************************/
5842 /* In identifiers such as function/variable names, Emacs tool bar is
5843 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5845 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5846 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5848 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5849 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5850 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5851 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5852 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5853 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5854 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5856 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5857 static void mac_handle_origin_change
P_ ((struct frame
*));
5858 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5862 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5869 mac_get_window_bounds (f
, &inner
, &outer
);
5871 switch (win_gravity
)
5873 case NorthWestGravity
:
5875 case SouthWestGravity
:
5876 left
+= inner
.left
- outer
.left
;
5882 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5885 case NorthEastGravity
:
5887 case SouthEastGravity
:
5888 left
+= inner
.right
- outer
.right
;
5892 switch (win_gravity
)
5894 case NorthWestGravity
:
5896 case NorthEastGravity
:
5897 top
+= inner
.top
- outer
.top
;
5903 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5906 case SouthWestGravity
:
5908 case SouthEastGravity
:
5909 top
+= inner
.bottom
- outer
.bottom
;
5913 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5917 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5924 mac_get_window_bounds (f
, &inner
, &outer
);
5926 switch (win_gravity
)
5928 case NorthWestGravity
:
5930 case SouthWestGravity
:
5937 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5938 - (inner
.right
- inner
.left
)) / 2;
5941 case NorthEastGravity
:
5943 case SouthEastGravity
:
5944 *left
= outer
.right
- (inner
.right
- inner
.left
);
5948 switch (win_gravity
)
5950 case NorthWestGravity
:
5952 case NorthEastGravity
:
5959 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5960 - (inner
.bottom
- inner
.top
)) / 2;
5963 case SouthWestGravity
:
5965 case SouthEastGravity
:
5966 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5972 mac_handle_toolbar_event (next_handler
, event
, data
)
5973 EventHandlerCallRef next_handler
;
5977 OSStatus err
, result
= eventNotHandledErr
;
5979 switch (GetEventKind (event
))
5981 case kEventToolbarGetDefaultIdentifiers
:
5985 case kEventToolbarGetAllowedIdentifiers
:
5987 CFMutableArrayRef array
;
5989 GetEventParameter (event
, kEventParamMutableArray
,
5990 typeCFMutableArrayRef
, NULL
,
5991 sizeof (CFMutableArrayRef
), NULL
, &array
);
5992 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5997 case kEventToolbarCreateItemWithIdentifier
:
5999 CFStringRef identifier
;
6000 HIToolbarItemRef item
= NULL
;
6002 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
6003 typeCFStringRef
, NULL
,
6004 sizeof (CFStringRef
), NULL
, &identifier
);
6006 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
6007 == kCFCompareEqualTo
)
6008 HIToolbarItemCreate (identifier
,
6009 kHIToolbarItemAllowDuplicates
6010 | kHIToolbarItemCantBeRemoved
, &item
);
6014 SetEventParameter (event
, kEventParamToolbarItem
,
6015 typeHIToolbarItemRef
,
6016 sizeof (HIToolbarItemRef
), &item
);
6030 mac_image_spec_to_cg_image (f
, image
)
6034 if (!valid_image_p (image
))
6038 int img_id
= lookup_image (f
, image
);
6039 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
6041 prepare_image_for_display (f
, img
);
6043 return img
->data
.ptr_val
;
6047 /* Create a tool bar for frame F. */
6050 mac_create_frame_tool_bar (f
)
6054 HIToolbarRef toolbar
;
6056 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
6060 static const EventTypeSpec specs
[] =
6061 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
6062 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
6063 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
6065 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
6066 mac_handle_toolbar_event
,
6067 GetEventTypeCount (specs
), specs
,
6072 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
6075 static const EventTypeSpec specs
[] =
6076 {{kEventClassCommand
, kEventCommandProcess
}};
6078 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
6079 mac_handle_toolbar_command_event
,
6080 GetEventTypeCount (specs
),
6084 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
6087 CFRelease (toolbar
);
6092 /* Update the tool bar for frame F. Add new buttons and remove old. */
6095 update_frame_tool_bar (f
)
6098 HIToolbarRef toolbar
= NULL
;
6100 CFArrayRef old_items
= NULL
;
6102 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
6103 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6107 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
6108 if (toolbar
== NULL
)
6110 mac_create_frame_tool_bar (f
);
6111 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
6112 if (toolbar
== NULL
)
6114 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6115 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
6118 HIToolbarCopyItems (toolbar
, &old_items
);
6119 if (old_items
== NULL
)
6122 old_count
= CFArrayGetCount (old_items
);
6124 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
6126 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
6128 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
6129 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
6132 CGImageRef cg_image
;
6134 HIToolbarItemRef item
;
6136 /* If image is a vector, choose the image according to the
6138 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6139 if (VECTORP (image
))
6143 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6144 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6147 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6148 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6150 xassert (ASIZE (image
) >= idx
);
6151 image
= AREF (image
, idx
);
6156 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6157 /* Ignore invalid image specifications. */
6158 if (cg_image
== NULL
)
6161 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6165 if (pos
< old_count
)
6167 CGImageRef old_cg_image
= NULL
;
6168 CFStringRef old_label
= NULL
;
6169 Boolean old_enabled_p
;
6171 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6173 HIToolbarItemCopyImage (item
, &old_cg_image
);
6174 if (cg_image
!= old_cg_image
)
6175 HIToolbarItemSetImage (item
, cg_image
);
6176 CGImageRelease (old_cg_image
);
6178 HIToolbarItemCopyLabel (item
, &old_label
);
6179 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6180 HIToolbarItemSetLabel (item
, label
);
6181 CFRelease (old_label
);
6183 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6184 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6185 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6190 HIToolbarCreateItemWithIdentifier (toolbar
,
6191 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6195 HIToolbarItemSetImage (item
, cg_image
);
6196 HIToolbarItemSetLabel (item
, label
);
6197 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6198 HIToolbarAppendItem (toolbar
, item
);
6206 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6211 CFRelease (old_items
);
6213 while (pos
< old_count
)
6214 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6216 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6217 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6218 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6219 toolbar visibility change. */
6220 mac_handle_origin_change (f
);
6221 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6223 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6224 /* If the title bar is completely outside the screen, adjust the
6226 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6227 kWindowConstrainMoveRegardlessOfFit
6228 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6229 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6236 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6237 doesn't deallocate the resources. */
6240 free_frame_tool_bar (f
)
6243 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6245 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6248 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6249 (NILP (Fsymbol_value
6250 (intern ("frame-notice-user-settings")))
6251 && f
== mac_focus_frame (dpyinfo
)));
6252 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6253 on toolbar visibility change. */
6254 mac_handle_origin_change (f
);
6260 mac_tool_bar_note_mouse_movement (f
, event
)
6265 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6267 HIViewRef item_view
;
6270 mouse_down_p
= (dpyinfo
->grabbed
6271 && f
== last_mouse_frame
6272 && FRAME_LIVE_P (f
));
6276 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6278 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6279 toolbar item view seems to have the same command ID with that of
6280 the toolbar item. */
6282 err
= GetControlCommandID (item_view
, &command_id
);
6283 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6285 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6287 if (i
< f
->n_tool_bar_items
)
6290 HIViewRef content_view
;
6292 err
= HIViewGetBounds (item_view
, &bounds
);
6294 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6295 kHIViewWindowContentID
, &content_view
);
6297 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6299 SetRect (&last_mouse_glyph
,
6300 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6301 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6303 help_echo_object
= help_echo_window
= Qnil
;
6305 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6306 if (NILP (help_echo_string
))
6307 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6313 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6314 EventHandlerCallRef next_handler
;
6318 OSStatus err
, result
= eventNotHandledErr
;
6319 struct frame
*f
= (struct frame
*) data
;
6322 err
= GetEventParameter (event
, kEventParamDirectObject
,
6323 typeHICommand
, NULL
,
6324 sizeof (HICommand
), NULL
, &command
);
6328 switch (GetEventKind (event
))
6330 case kEventCommandProcess
:
6331 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6332 result
= CallNextEventHandler (next_handler
, event
);
6335 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6337 if (i
< f
->n_tool_bar_items
6338 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6341 struct input_event buf
;
6345 XSETFRAME (frame
, f
);
6346 buf
.kind
= TOOL_BAR_EVENT
;
6347 buf
.frame_or_window
= frame
;
6349 kbd_buffer_store_event (&buf
);
6351 buf
.kind
= TOOL_BAR_EVENT
;
6352 buf
.frame_or_window
= frame
;
6353 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6354 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6355 kbd_buffer_store_event (&buf
);
6369 #endif /* USE_MAC_TOOLBAR */
6372 /***********************************************************************
6374 ***********************************************************************/
6376 /* Set clipping for output in glyph row ROW. W is the window in which
6377 we operate. GC is the graphics context to set clipping in.
6379 ROW may be a text row or, e.g., a mode line. Text rows must be
6380 clipped to the interior of the window dedicated to text display,
6381 mode lines must be clipped to the whole window. */
6384 x_clip_to_row (w
, row
, area
, gc
)
6386 struct glyph_row
*row
;
6390 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6392 int window_x
, window_y
, window_width
;
6394 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6396 clip_rect
.left
= window_x
;
6397 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6398 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6399 clip_rect
.right
= clip_rect
.left
+ window_width
;
6400 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6402 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6406 /* Draw a hollow box cursor on window W in glyph row ROW. */
6409 x_draw_hollow_cursor (w
, row
)
6411 struct glyph_row
*row
;
6413 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6414 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6415 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6418 struct glyph
*cursor_glyph
;
6421 /* Get the glyph the cursor is on. If we can't tell because
6422 the current matrix is invalid or such, give up. */
6423 cursor_glyph
= get_phys_cursor_glyph (w
);
6424 if (cursor_glyph
== NULL
)
6427 /* Compute frame-relative coordinates for phys cursor. */
6428 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6429 wd
= w
->phys_cursor_width
;
6431 /* The foreground of cursor_gc is typically the same as the normal
6432 background color, which can cause the cursor box to be invisible. */
6433 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6434 if (dpyinfo
->scratch_cursor_gc
)
6435 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6437 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6438 GCForeground
, &xgcv
);
6439 gc
= dpyinfo
->scratch_cursor_gc
;
6441 /* Set clipping, draw the rectangle, and reset clipping again. */
6442 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6443 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6444 mac_reset_clip_rectangles (dpy
, gc
);
6448 /* Draw a bar cursor on window W in glyph row ROW.
6450 Implementation note: One would like to draw a bar cursor with an
6451 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6452 Unfortunately, I didn't find a font yet that has this property set.
6456 x_draw_bar_cursor (w
, row
, width
, kind
)
6458 struct glyph_row
*row
;
6460 enum text_cursor_kinds kind
;
6462 struct frame
*f
= XFRAME (w
->frame
);
6463 struct glyph
*cursor_glyph
;
6465 /* If cursor is out of bounds, don't draw garbage. This can happen
6466 in mini-buffer windows when switching between echo area glyphs
6468 cursor_glyph
= get_phys_cursor_glyph (w
);
6469 if (cursor_glyph
== NULL
)
6472 /* If on an image, draw like a normal cursor. That's usually better
6473 visible than drawing a bar, esp. if the image is large so that
6474 the bar might not be in the window. */
6475 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6477 struct glyph_row
*row
;
6478 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6479 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6483 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6484 Window window
= FRAME_MAC_WINDOW (f
);
6485 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6486 unsigned long mask
= GCForeground
| GCBackground
;
6487 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6490 /* If the glyph's background equals the color we normally draw
6491 the bar cursor in, the bar cursor in its normal color is
6492 invisible. Use the glyph's foreground color instead in this
6493 case, on the assumption that the glyph's colors are chosen so
6494 that the glyph is legible. */
6495 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6496 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6498 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6501 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6504 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6505 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6509 width
= FRAME_CURSOR_WIDTH (f
);
6510 width
= min (cursor_glyph
->pixel_width
, width
);
6512 w
->phys_cursor_width
= width
;
6513 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6515 if (kind
== BAR_CURSOR
)
6516 mac_fill_rectangle (f
, gc
,
6517 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6518 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6519 width
, row
->height
);
6521 mac_fill_rectangle (f
, gc
,
6522 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6523 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6524 row
->height
- width
),
6525 cursor_glyph
->pixel_width
,
6528 mac_reset_clip_rectangles (f
, gc
);
6533 /* RIF: Define cursor CURSOR on frame F. */
6536 mac_define_frame_cursor (f
, cursor
)
6540 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6542 if (dpyinfo
->x_focus_frame
== f
)
6543 SetThemeCursor (cursor
);
6547 /* RIF: Clear area on frame F. */
6550 mac_clear_frame_area (f
, x
, y
, width
, height
)
6552 int x
, y
, width
, height
;
6554 mac_clear_area (f
, x
, y
, width
, height
);
6558 /* RIF: Draw cursor on window W. */
6561 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6563 struct glyph_row
*glyph_row
;
6565 int cursor_type
, cursor_width
;
6570 w
->phys_cursor_type
= cursor_type
;
6571 w
->phys_cursor_on_p
= 1;
6573 if (glyph_row
->exact_window_width_line_p
6574 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6576 glyph_row
->cursor_in_fringe_p
= 1;
6577 draw_fringe_bitmap (w
, glyph_row
, 0);
6580 switch (cursor_type
)
6582 case HOLLOW_BOX_CURSOR
:
6583 x_draw_hollow_cursor (w
, glyph_row
);
6586 case FILLED_BOX_CURSOR
:
6587 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6591 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6595 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6599 w
->phys_cursor_width
= 0;
6611 #if 0 /* MAC_TODO: no icon support yet. */
6613 x_bitmap_icon (f
, icon
)
6619 if (FRAME_W32_WINDOW (f
) == 0)
6623 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6624 else if (STRINGP (icon
))
6625 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6626 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6627 else if (SYMBOLP (icon
))
6631 if (EQ (icon
, intern ("application")))
6632 name
= (LPCTSTR
) IDI_APPLICATION
;
6633 else if (EQ (icon
, intern ("hand")))
6634 name
= (LPCTSTR
) IDI_HAND
;
6635 else if (EQ (icon
, intern ("question")))
6636 name
= (LPCTSTR
) IDI_QUESTION
;
6637 else if (EQ (icon
, intern ("exclamation")))
6638 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6639 else if (EQ (icon
, intern ("asterisk")))
6640 name
= (LPCTSTR
) IDI_ASTERISK
;
6641 else if (EQ (icon
, intern ("winlogo")))
6642 name
= (LPCTSTR
) IDI_WINLOGO
;
6646 hicon
= LoadIcon (NULL
, name
);
6654 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6659 #endif /* MAC_TODO */
6661 /************************************************************************
6663 ************************************************************************/
6665 /* Display Error Handling functions not used on W32. Listing them here
6666 helps diff stay in step when comparing w32term.c with xterm.c.
6668 x_error_catcher (display, error)
6669 x_catch_errors (dpy)
6670 x_catch_errors_unwind (old_val)
6671 x_check_errors (dpy, format)
6672 x_had_errors_p (dpy)
6673 x_clear_errors (dpy)
6674 x_uncatch_errors (dpy, count)
6676 x_connection_signal (signalnum)
6677 x_connection_closed (dpy, error_message)
6678 x_error_quitter (display, error)
6679 x_error_handler (display, error)
6680 x_io_error_quitter (display)
6685 /* Changing the font of the frame. */
6687 /* Give frame F the font named FONTNAME as its default font, and
6688 return the full name of that font. FONTNAME may be a wildcard
6689 pattern; in that case, we choose some font that fits the pattern.
6690 The return value shows which font we chose. */
6693 x_new_font (f
, fontname
)
6695 register char *fontname
;
6697 struct font_info
*fontp
6698 = FS_LOAD_FONT (f
, fontname
);
6703 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
6704 /* This font is already set in frame F. There's nothing more to
6706 return build_string (fontp
->full_name
);
6708 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6709 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6710 FRAME_FONTSET (f
) = -1;
6712 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6713 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6714 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6716 compute_fringe_widths (f
, 1);
6718 /* Compute the scroll bar width in character columns. */
6719 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6721 int wid
= FRAME_COLUMN_WIDTH (f
);
6722 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6723 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6727 int wid
= FRAME_COLUMN_WIDTH (f
);
6728 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6731 /* Now make the frame display the given font. */
6732 if (FRAME_MAC_WINDOW (f
) != 0)
6734 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6736 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6738 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6741 /* Don't change the size of a tip frame; there's no point in
6742 doing it because it's done in Fx_show_tip, and it leads to
6743 problems because the tip frame has no widget. */
6744 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6745 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6748 return build_string (fontp
->full_name
);
6751 /* Give frame F the fontset named FONTSETNAME as its default fontset,
6752 and return the full name of that fontset. FONTSETNAME may be a
6753 wildcard pattern; in that case, we choose some fontset that fits
6754 the pattern. FONTSETNAME may be a font name for ASCII characters;
6755 in that case, we create a fontset from that font name.
6757 The return value shows which fontset we chose.
6758 If FONTSETNAME specifies the default fontset, return Qt.
6759 If an ASCII font in the specified fontset can't be loaded, return
6763 x_new_fontset (f
, fontsetname
)
6765 Lisp_Object fontsetname
;
6767 int fontset
= fs_query_fontset (fontsetname
, 0);
6770 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
6771 /* This fontset is already set in frame F. There's nothing more
6773 return fontset_name (fontset
);
6774 else if (fontset
== 0)
6775 /* The default fontset can't be the default font. */
6779 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6781 result
= x_new_font (f
, SDATA (fontsetname
));
6783 if (!STRINGP (result
))
6784 /* Can't load ASCII font. */
6788 fontset
= new_fontset_from_font_name (result
);
6790 /* Since x_new_font doesn't update any fontset information, do it now. */
6791 FRAME_FONTSET (f
) = fontset
;
6793 return fontset_name (fontset
);
6797 /***********************************************************************
6798 TODO: W32 Input Methods
6799 ***********************************************************************/
6800 /* Listing missing functions from xterm.c helps diff stay in step.
6802 xim_destroy_callback (xim, client_data, call_data)
6803 xim_open_dpy (dpyinfo, resource_name)
6805 xim_instantiate_callback (display, client_data, call_data)
6806 xim_initialize (dpyinfo, resource_name)
6807 xim_close_dpy (dpyinfo)
6813 mac_get_window_bounds (f
, inner
, outer
)
6815 Rect
*inner
, *outer
;
6817 #if TARGET_API_MAC_CARBON
6818 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6819 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6820 #else /* not TARGET_API_MAC_CARBON */
6821 RgnHandle region
= NewRgn ();
6823 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6824 *inner
= (*region
)->rgnBBox
;
6825 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6826 *outer
= (*region
)->rgnBBox
;
6827 DisposeRgn (region
);
6828 #endif /* not TARGET_API_MAC_CARBON */
6832 mac_handle_origin_change (f
)
6835 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6839 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6841 int pixelwidth
, pixelheight
;
6845 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6846 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6848 if (cols
!= FRAME_COLS (f
)
6849 || rows
!= FRAME_LINES (f
)
6850 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6851 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6853 /* We pass 1 for DELAY since we can't run Lisp code inside of
6855 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6856 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6857 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6859 /* If cursor was outside the new size, mark it as off. */
6860 mark_window_cursors_off (XWINDOW (f
->root_window
));
6862 /* Clear out any recollection of where the mouse highlighting
6863 was, since it might be in a place that's outside the new
6864 frame size. Actually checking whether it is outside is a
6865 pain in the neck, so don't try--just let the highlighting be
6866 done afresh with new size. */
6867 cancel_mouse_face (f
);
6869 #if TARGET_API_MAC_CARBON
6870 if (f
->output_data
.mac
->hourglass_control
)
6873 mac_prepare_for_quickdraw (f
);
6875 MoveControl (f
->output_data
.mac
->hourglass_control
,
6876 pixelwidth
- HOURGLASS_WIDTH
, 0);
6883 /* Calculate the absolute position in frame F
6884 from its current recorded position values and gravity. */
6887 x_calc_absolute_position (f
)
6890 int flags
= f
->size_hint_flags
;
6893 /* We have nothing to do if the current position
6894 is already for the top-left corner. */
6895 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6898 /* Find the offsets of the outside upper-left corner of
6899 the inner window, with respect to the outer window. */
6901 mac_get_window_bounds (f
, &inner
, &outer
);
6904 /* Treat negative positions as relative to the leftmost bottommost
6905 position that fits on the screen. */
6906 if (flags
& XNegative
)
6907 f
->left_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->width
6908 - (outer
.right
- outer
.left
));
6910 if (flags
& YNegative
)
6911 f
->top_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->height
6912 - (outer
.bottom
- outer
.top
));
6914 /* The left_pos and top_pos
6915 are now relative to the top and left screen edges,
6916 so the flags should correspond. */
6917 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6920 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6921 to really change the position, and 0 when calling from
6922 x_make_frame_visible (in that case, XOFF and YOFF are the current
6923 position values). It is -1 when calling from x_set_frame_parameters,
6924 which means, do adjust for borders but don't change the gravity. */
6927 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6929 register int xoff
, yoff
;
6932 if (change_gravity
> 0)
6936 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6938 f
->size_hint_flags
|= XNegative
;
6940 f
->size_hint_flags
|= YNegative
;
6941 f
->win_gravity
= NorthWestGravity
;
6943 x_calc_absolute_position (f
);
6946 x_wm_set_size_hint (f
, (long) 0, 0);
6948 #if TARGET_API_MAC_CARBON
6949 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6950 /* If the title bar is completely outside the screen, adjust the
6952 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6953 kWindowConstrainMoveRegardlessOfFit
6954 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6955 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6956 mac_handle_origin_change (f
);
6959 Rect inner
, outer
, screen_rect
, dummy
;
6960 RgnHandle region
= NewRgn ();
6962 mac_get_window_bounds (f
, &inner
, &outer
);
6963 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6964 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6965 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6966 f
->top_pos
+ f
->y_pixels_diff
, false);
6968 /* If the title bar is completely outside the screen, adjust the
6969 position. The variable `outer' holds the title bar rectangle.
6970 The variable `inner' holds slightly smaller one than `outer',
6971 so that the calculation of overlapping may not become too
6973 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6974 outer
= (*region
)->rgnBBox
;
6975 DisposeRgn (region
);
6977 InsetRect (&inner
, 8, 8);
6978 screen_rect
= qd
.screenBits
.bounds
;
6979 screen_rect
.top
+= GetMBarHeight ();
6981 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6983 if (inner
.right
<= screen_rect
.left
)
6984 f
->left_pos
= screen_rect
.left
;
6985 else if (inner
.left
>= screen_rect
.right
)
6986 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6988 if (inner
.bottom
<= screen_rect
.top
)
6989 f
->top_pos
= screen_rect
.top
;
6990 else if (inner
.top
>= screen_rect
.bottom
)
6991 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6993 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6994 f
->top_pos
+ f
->y_pixels_diff
, false);
7002 /* Call this to change the size of frame F's x-window.
7003 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
7004 for this size change and subsequent size changes.
7005 Otherwise we leave the window gravity unchanged. */
7008 x_set_window_size (f
, change_gravity
, cols
, rows
)
7013 int pixelwidth
, pixelheight
;
7017 check_frame_size (f
, &rows
, &cols
);
7018 f
->scroll_bar_actual_width
7019 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
7021 compute_fringe_widths (f
, 0);
7023 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
7024 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7026 f
->win_gravity
= NorthWestGravity
;
7027 x_wm_set_size_hint (f
, (long) 0, 0);
7029 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
7031 #if TARGET_API_MAC_CARBON
7032 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
7034 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
7036 if (f
->output_data
.mac
->internal_border_width
7037 != FRAME_INTERNAL_BORDER_WIDTH (f
))
7039 mac_clear_window (f
);
7040 f
->output_data
.mac
->internal_border_width
7041 = FRAME_INTERNAL_BORDER_WIDTH (f
);
7044 SET_FRAME_GARBAGED (f
);
7049 /* Mouse warping. */
7051 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
7054 x_set_mouse_position (f
, x
, y
)
7060 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
7061 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
7063 if (pix_x
< 0) pix_x
= 0;
7064 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
7066 if (pix_y
< 0) pix_y
= 0;
7067 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
7069 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
7073 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
7078 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
7079 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
7082 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
7085 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
7088 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
7089 0, 0, 0, 0, pix_x
, pix_y
);
7095 /* focus shifting, raising and lowering. */
7098 x_focus_on_frame (f
)
7101 #if 0 /* This proves to be unpleasant. */
7105 /* I don't think that the ICCCM allows programs to do things like this
7106 without the interaction of the window manager. Whatever you end up
7107 doing with this code, do it to x_unfocus_frame too. */
7108 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7109 RevertToPointerRoot
, CurrentTime
);
7119 /* Raise frame F. */
7125 if (f
->async_visible
)
7128 BringToFront (FRAME_MAC_WINDOW (f
));
7133 /* Lower frame F. */
7139 if (f
->async_visible
)
7142 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7148 XTframe_raise_lower (f
, raise_flag
)
7158 /* Change of visibility. */
7161 mac_handle_visibility_change (f
)
7164 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7165 int visible
= 0, iconified
= 0;
7166 struct input_event buf
;
7168 if (IsWindowVisible (wp
))
7170 if (IsWindowCollapsed (wp
))
7176 if (!f
->async_visible
&& visible
)
7180 /* wait_reading_process_output will notice this and update
7181 the frame's display structures. If we were made
7182 invisible, we should not set garbaged, because that stops
7183 redrawing on Update events. */
7184 SET_FRAME_GARBAGED (f
);
7187 buf
.kind
= DEICONIFY_EVENT
;
7188 XSETFRAME (buf
.frame_or_window
, f
);
7190 kbd_buffer_store_event (&buf
);
7192 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7193 /* Force a redisplay sooner or later to update the
7194 frame titles in case this is the second frame. */
7195 record_asynch_buffer_change ();
7197 else if (f
->async_visible
&& !visible
)
7201 buf
.kind
= ICONIFY_EVENT
;
7202 XSETFRAME (buf
.frame_or_window
, f
);
7204 kbd_buffer_store_event (&buf
);
7207 f
->async_visible
= visible
;
7208 f
->async_iconified
= iconified
;
7211 /* This tries to wait until the frame is really visible.
7212 However, if the window manager asks the user where to position
7213 the frame, this will return before the user finishes doing that.
7214 The frame will not actually be visible at that time,
7215 but it will become visible later when the window manager
7216 finishes with it. */
7219 x_make_frame_visible (f
)
7224 if (! FRAME_VISIBLE_P (f
))
7226 /* We test FRAME_GARBAGED_P here to make sure we don't
7227 call x_set_offset a second time
7228 if we get to x_make_frame_visible a second time
7229 before the window gets really visible. */
7230 if (! FRAME_ICONIFIED_P (f
)
7231 && ! f
->output_data
.mac
->asked_for_visible
)
7232 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7234 f
->output_data
.mac
->asked_for_visible
= 1;
7236 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7237 ShowWindow (FRAME_MAC_WINDOW (f
));
7240 XFlush (FRAME_MAC_DISPLAY (f
));
7242 /* Synchronize to ensure Emacs knows the frame is visible
7243 before we do anything else. We do this loop with input not blocked
7244 so that incoming events are handled. */
7249 /* This must come after we set COUNT. */
7252 XSETFRAME (frame
, f
);
7254 /* Wait until the frame is visible. Process X events until a
7255 MapNotify event has been seen, or until we think we won't get a
7256 MapNotify at all.. */
7257 for (count
= input_signal_count
+ 10;
7258 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7260 /* Force processing of queued events. */
7263 /* Machines that do polling rather than SIGIO have been
7264 observed to go into a busy-wait here. So we'll fake an
7265 alarm signal to let the handler know that there's something
7266 to be read. We used to raise a real alarm, but it seems
7267 that the handler isn't always enabled here. This is
7269 if (input_polling_used ())
7271 /* It could be confusing if a real alarm arrives while
7272 processing the fake one. Turn it off and let the
7273 handler reset it. */
7274 extern void poll_for_input_1
P_ ((void));
7275 int old_poll_suppress_count
= poll_suppress_count
;
7276 poll_suppress_count
= 1;
7277 poll_for_input_1 ();
7278 poll_suppress_count
= old_poll_suppress_count
;
7281 /* See if a MapNotify event has been processed. */
7282 FRAME_SAMPLE_VISIBILITY (f
);
7287 /* Change from mapped state to withdrawn state. */
7289 /* Make the frame visible (mapped and not iconified). */
7292 x_make_frame_invisible (f
)
7295 /* A deactivate event does not occur when the last visible frame is
7296 made invisible. So if we clear the highlight here, it will not
7297 be rehighlighted when it is made visible. */
7299 /* Don't keep the highlight on an invisible frame. */
7300 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7301 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7306 #if !TARGET_API_MAC_CARBON
7307 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7308 that the current position of the window is user-specified, rather than
7309 program-specified, so that when the window is mapped again, it will be
7310 placed at the same location, without forcing the user to position it
7311 by hand again (they have already done that once for this window.) */
7312 x_wm_set_size_hint (f
, (long) 0, 1);
7315 HideWindow (FRAME_MAC_WINDOW (f
));
7319 #if !TARGET_API_MAC_CARBON
7320 mac_handle_visibility_change (f
);
7324 /* Change window state from mapped to iconified. */
7332 /* A deactivate event does not occur when the last visible frame is
7333 iconified. So if we clear the highlight here, it will not be
7334 rehighlighted when it is deiconified. */
7336 /* Don't keep the highlight on an invisible frame. */
7337 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7338 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7341 if (f
->async_iconified
)
7346 FRAME_SAMPLE_VISIBILITY (f
);
7348 if (! FRAME_VISIBLE_P (f
))
7349 ShowWindow (FRAME_MAC_WINDOW (f
));
7351 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7356 error ("Can't notify window manager of iconification");
7358 #if !TARGET_API_MAC_CARBON
7359 mac_handle_visibility_change (f
);
7364 /* Free X resources of frame F. */
7367 x_free_frame_resources (f
)
7370 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7371 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7375 if (wp
!= tip_window
)
7376 remove_window_handler (wp
);
7379 mac_prepare_for_quickdraw (f
);
7382 if (wp
== tip_window
)
7383 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7384 closed' event. So we reset tip_window here. */
7387 free_frame_menubar (f
);
7389 if (FRAME_FACE_CACHE (f
))
7390 free_frame_faces (f
);
7394 if (FRAME_SIZE_HINTS (f
))
7395 xfree (FRAME_SIZE_HINTS (f
));
7397 xfree (f
->output_data
.mac
);
7398 f
->output_data
.mac
= NULL
;
7400 if (f
== dpyinfo
->x_focus_frame
)
7402 dpyinfo
->x_focus_frame
= 0;
7403 #if USE_MAC_FONT_PANEL
7404 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7407 if (f
== dpyinfo
->x_focus_event_frame
)
7408 dpyinfo
->x_focus_event_frame
= 0;
7409 if (f
== dpyinfo
->x_highlight_frame
)
7410 dpyinfo
->x_highlight_frame
= 0;
7412 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7414 dpyinfo
->mouse_face_beg_row
7415 = dpyinfo
->mouse_face_beg_col
= -1;
7416 dpyinfo
->mouse_face_end_row
7417 = dpyinfo
->mouse_face_end_col
= -1;
7418 dpyinfo
->mouse_face_window
= Qnil
;
7419 dpyinfo
->mouse_face_deferred_gc
= 0;
7420 dpyinfo
->mouse_face_mouse_frame
= 0;
7427 /* Destroy the X window of frame F. */
7430 x_destroy_window (f
)
7433 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7435 x_free_frame_resources (f
);
7437 dpyinfo
->reference_count
--;
7441 /* Setting window manager hints. */
7443 /* Set the normal size hints for the window manager, for frame F.
7444 FLAGS is the flags word to use--or 0 meaning preserve the flags
7445 that the window now has.
7446 If USER_POSITION is nonzero, we set the USPosition
7447 flag (this is useful when FLAGS is 0). */
7449 x_wm_set_size_hint (f
, flags
, user_position
)
7454 int base_width
, base_height
, width_inc
, height_inc
;
7455 int min_rows
= 0, min_cols
= 0;
7456 XSizeHints
*size_hints
;
7458 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7459 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7460 width_inc
= FRAME_COLUMN_WIDTH (f
);
7461 height_inc
= FRAME_LINE_HEIGHT (f
);
7463 check_frame_size (f
, &min_rows
, &min_cols
);
7465 size_hints
= FRAME_SIZE_HINTS (f
);
7466 if (size_hints
== NULL
)
7468 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7469 bzero (size_hints
, sizeof (XSizeHints
));
7472 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7473 size_hints
->width_inc
= width_inc
;
7474 size_hints
->height_inc
= height_inc
;
7475 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7476 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7477 size_hints
->base_width
= base_width
;
7478 size_hints
->base_height
= base_height
;
7481 size_hints
->flags
= flags
;
7482 else if (user_position
)
7484 size_hints
->flags
&= ~ PPosition
;
7485 size_hints
->flags
|= USPosition
;
7489 #if 0 /* MAC_TODO: hide application instead of iconify? */
7490 /* Used for IconicState or NormalState */
7493 x_wm_set_window_state (f
, state
)
7497 #ifdef USE_X_TOOLKIT
7500 XtSetArg (al
[0], XtNinitialState
, state
);
7501 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7502 #else /* not USE_X_TOOLKIT */
7503 Window window
= FRAME_X_WINDOW (f
);
7505 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7506 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7508 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7509 #endif /* not USE_X_TOOLKIT */
7513 x_wm_set_icon_pixmap (f
, pixmap_id
)
7519 #ifndef USE_X_TOOLKIT
7520 Window window
= FRAME_X_WINDOW (f
);
7525 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7526 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7530 /* It seems there is no way to turn off use of an icon pixmap.
7531 The following line does it, only if no icon has yet been created,
7532 for some window managers. But with mwm it crashes.
7533 Some people say it should clear the IconPixmapHint bit in this case,
7534 but that doesn't work, and the X consortium said it isn't the
7535 right thing at all. Since there is no way to win,
7536 best to explicitly give up. */
7538 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7544 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7548 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7549 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7552 #else /* not USE_X_TOOLKIT */
7554 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7555 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7557 #endif /* not USE_X_TOOLKIT */
7560 #endif /* MAC_TODO */
7563 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7567 #if 0 /* MAC_TODO: no icons on Mac */
7568 #ifdef USE_X_TOOLKIT
7569 Window window
= XtWindow (f
->output_data
.x
->widget
);
7571 Window window
= FRAME_X_WINDOW (f
);
7574 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7575 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7576 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7578 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7579 #endif /* MAC_TODO */
7583 /***********************************************************************
7585 ***********************************************************************/
7587 /* An XLFD pattern is divided into blocks delimited by '*'. This
7588 structure holds information for each block. */
7589 struct xlfdpat_block
7591 /* Length of the pattern string in this block. Non-zero except for
7592 the first and the last blocks. */
7595 /* Pattern string except the last character in this block. The last
7596 character is replaced with NUL in order to use it as a
7598 unsigned char *pattern
;
7600 /* Last character of the pattern string. Must not be '?'. */
7601 unsigned char last_char
;
7603 /* One of the tables for the Boyer-Moore string search. It
7604 specifies the number of positions to proceed for each character
7605 with which the match fails. */
7608 /* The skip value for the last character in the above `skip' is
7609 assigned to `infinity' in order to simplify a loop condition.
7610 The original value is saved here. */
7616 /* Normalized pattern string. "Normalized" means that capital
7617 letters are lowered, blocks are not empty except the first and
7618 the last ones, and trailing '?'s in a block that is not the last
7619 one are moved to the next one. The last character in each block
7620 is replaced with NUL. */
7623 /* Number of characters except '*'s and trailing '?'s in the
7624 normalized pattern string. */
7627 /* Number of trailing '?'s in the normalized pattern string. */
7628 int trailing_anychars
;
7630 /* Number of blocks and information for each block. The latter is
7631 NULL if the pattern is exact (no '*' or '?' in it). */
7633 struct xlfdpat_block
*blocks
;
7637 xlfdpat_destroy (pat
)
7638 struct xlfdpat
*pat
;
7645 xfree (pat
->blocks
);
7652 static struct xlfdpat
*
7653 xlfdpat_create (pattern
)
7654 const char *pattern
;
7656 struct xlfdpat
*pat
;
7657 int nblocks
, i
, skip
;
7658 unsigned char last_char
, *p
, *q
, *anychar_head
;
7659 const unsigned char *ptr
;
7660 struct xlfdpat_block
*blk
;
7662 pat
= xmalloc (sizeof (struct xlfdpat
));
7663 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7665 /* Normalize the pattern string and store it to `pat->buf'. */
7667 anychar_head
= NULL
;
7670 for (ptr
= pattern
; *ptr
; ptr
++)
7672 unsigned char c
= *ptr
;
7675 if (last_char
== '*')
7676 /* ...a** -> ...a* */
7680 if (last_char
== '?')
7682 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7683 /* ...*??* -> ...*?? */
7686 /* ...a??* -> ...a*?? */
7688 *anychar_head
++ = '*';
7696 if (last_char
!= '?')
7700 /* On Mac OS X 10.3, tolower also converts non-ASCII
7701 characters for some locales. */
7705 *q
++ = last_char
= c
;
7709 pat
->nblocks
= nblocks
;
7710 if (last_char
!= '?')
7711 pat
->trailing_anychars
= 0;
7714 pat
->trailing_anychars
= q
- anychar_head
;
7717 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7719 if (anychar_head
== NULL
&& nblocks
== 1)
7721 /* The pattern is exact. */
7726 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7728 /* Divide the normalized pattern into blocks. */
7730 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7735 blk
->len
= p
- blk
->pattern
;
7739 blk
->len
= q
- blk
->pattern
;
7741 /* Setup a table for the Boyer-Moore string search. */
7742 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7745 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7746 blk
->pattern
[blk
->len
- 1] = '\0';
7748 for (skip
= 1; skip
< blk
->len
; skip
++)
7749 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7752 for (i
= 0; i
< 256; i
++)
7753 blk
->skip
[i
] = skip
;
7755 p
= blk
->pattern
+ (blk
->len
- skip
);
7757 blk
->skip
[*p
++] = skip
;
7759 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7766 xlfdpat_exact_p (pat
)
7767 struct xlfdpat
*pat
;
7769 return pat
->blocks
== NULL
;
7772 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7773 that the pattern in *BLK matches with its prefix. Return NULL
7774 there is no such strings. STRING must be lowered in advance. */
7777 xlfdpat_block_match_1 (blk
, string
, start_max
)
7778 struct xlfdpat_block
*blk
;
7779 const unsigned char *string
;
7782 int start
, infinity
;
7784 const unsigned char *s
;
7786 xassert (blk
->len
> 0);
7787 xassert (start_max
+ blk
->len
<= strlen (string
));
7788 xassert (blk
->last_char
!= '?');
7790 /* See the comments in the function `boyer_moore' (search.c) for the
7791 use of `infinity'. */
7792 infinity
= start_max
+ blk
->len
+ 1;
7793 blk
->skip
[blk
->last_char
] = infinity
;
7798 /* Check the last character of the pattern. */
7799 s
= string
+ blk
->len
- 1;
7802 start
+= blk
->skip
[*(s
+ start
)];
7804 while (start
<= start_max
);
7806 if (start
< infinity
)
7807 /* Couldn't find the last character. */
7810 /* No less than `infinity' means we could find the last
7811 character at `s[start - infinity]'. */
7814 /* Check the remaining characters. We prefer making no-'?'
7815 cases faster because the use of '?' is really rare. */
7820 while (*p
++ == *s
++)
7823 while (*(p
- 1) == '?');
7825 if (*(p
- 1) == '\0')
7827 return string
+ start
;
7830 start
+= blk
->last_char_skip
;
7832 while (start
<= start_max
);
7837 #define xlfdpat_block_match(b, s, m) \
7838 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7839 : xlfdpat_block_match_1 (b, s, m))
7841 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7842 matches with STRING. STRING must be lowered in advance. */
7845 xlfdpat_match (pat
, string
)
7846 struct xlfdpat
*pat
;
7847 const unsigned char *string
;
7849 int str_len
, nblocks
, i
, start_max
;
7850 struct xlfdpat_block
*blk
;
7851 const unsigned char *s
;
7853 xassert (pat
->nblocks
> 0);
7855 if (xlfdpat_exact_p (pat
))
7856 return strcmp (pat
->buf
, string
) == 0;
7858 /* The number of the characters in the string must not be smaller
7859 than that in the pattern. */
7860 str_len
= strlen (string
);
7861 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7864 /* Chop off the trailing '?'s. */
7865 str_len
-= pat
->trailing_anychars
;
7867 /* The last block. When it is non-empty, it must match at the end
7869 nblocks
= pat
->nblocks
;
7870 blk
= pat
->blocks
+ (nblocks
- 1);
7872 /* The last block is also the first one. */
7873 return (str_len
== blk
->len
7874 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7875 else if (blk
->len
!= 0)
7876 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7879 /* The first block. When it is non-empty, it must match at the
7880 beginning of the string. */
7884 s
= xlfdpat_block_match (blk
, string
, 0);
7887 string
= s
+ blk
->len
;
7890 /* The rest of the blocks. */
7891 start_max
= str_len
- pat
->nchars
;
7892 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7894 s
= xlfdpat_block_match (blk
, string
, start_max
);
7897 start_max
-= s
- string
;
7898 string
= s
+ blk
->len
;
7905 /***********************************************************************
7907 ***********************************************************************/
7909 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7912 x_get_font_info (f
, font_idx
)
7916 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7919 /* the global font name table */
7920 static char **font_name_table
= NULL
;
7921 static int font_name_table_size
= 0;
7922 static int font_name_count
= 0;
7924 /* Alist linking font family names to Font Manager font family
7925 references (which can also be used as QuickDraw font IDs). We use
7926 an alist because hash tables are not ready when the terminal frame
7927 for Mac OS Classic is created. */
7928 static Lisp_Object fm_font_family_alist
;
7930 /* Hash table linking font family names to ATSU font IDs. */
7931 static Lisp_Object atsu_font_id_hash
;
7932 /* Alist linking Font Manager style to face attributes. */
7933 static Lisp_Object fm_style_face_attributes_alist
;
7934 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7937 /* Alist linking character set strings to Mac text encoding and Emacs
7939 static Lisp_Object Vmac_charset_info_alist
;
7942 create_text_encoding_info_alist ()
7944 Lisp_Object result
= Qnil
, rest
;
7946 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7948 Lisp_Object charset_info
= XCAR (rest
);
7949 Lisp_Object charset
, coding_system
, text_encoding
;
7950 Lisp_Object existing_info
;
7952 if (!(CONSP (charset_info
)
7953 && (charset
= XCAR (charset_info
),
7955 && CONSP (XCDR (charset_info
))
7956 && (text_encoding
= XCAR (XCDR (charset_info
)),
7957 INTEGERP (text_encoding
))
7958 && CONSP (XCDR (XCDR (charset_info
)))
7959 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7960 SYMBOLP (coding_system
))))
7963 existing_info
= assq_no_quit (text_encoding
, result
);
7964 if (NILP (existing_info
))
7965 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7968 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7969 XSETCDR (XCDR (existing_info
),
7970 Fcons (charset
, XCDR (XCDR (existing_info
))));
7978 decode_mac_font_name (name
, size
, coding_system
)
7981 Lisp_Object coding_system
;
7983 struct coding_system coding
;
7986 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7988 for (p
= name
; *p
; p
++)
7989 if (!isascii (*p
) || iscntrl (*p
))
7994 setup_coding_system (coding_system
, &coding
);
7995 coding
.src_multibyte
= 0;
7996 coding
.dst_multibyte
= 1;
7997 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7998 coding
.dst_bytes
= size
;
7999 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
8001 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
8002 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
8003 name
[min (coding
.produced
, size
)] = '\0';
8007 /* If there's just one occurrence of '-' in the family name, it is
8008 replaced with '_'. (More than one occurrence of '-' means a
8009 "FOUNDRY-FAMILY-CHARSET"-style name.) */
8010 p
= strchr (name
, '-');
8011 if (p
&& strchr (p
+ 1, '-') == NULL
)
8014 for (p
= name
; *p
; p
++)
8015 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8016 for some locales. */
8023 mac_to_x_fontname (name
, size
, style
, charset
)
8031 char xf
[256], *result
;
8034 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
8038 strcpy(foundry
, "Apple");
8039 strcpy(family
, name
);
8042 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
8043 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
8044 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
8046 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
8047 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
8048 for (p
= result
; *p
; p
++)
8049 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8050 for some locales. */
8057 /* Parse fully-specified and instantiated X11 font spec XF, and store
8058 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
8059 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
8060 caller must allocate at least 256 and 32 bytes respectively. For
8061 ordinary Mac fonts, the value stored to FAMILY should just be their
8062 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
8063 intlfonts collection contain their charset designation in their
8064 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
8065 types of font names are handled accordingly. */
8067 const int kDefaultFontSize
= 12;
8070 parse_x_font_name (xf
, family
, size
, style
, charset
)
8077 Str31 foundry
, weight
;
8078 int point_size
, avgwidth
;
8081 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
8082 foundry
, family
, weight
, slant
, size
,
8083 &point_size
, &avgwidth
, charset
) != 8
8084 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
8085 foundry
, family
, weight
, slant
, size
,
8086 &point_size
, &avgwidth
, charset
) != 8)
8092 *size
= point_size
/ 10;
8093 else if (avgwidth
> 0)
8094 *size
= avgwidth
/ 10;
8097 *size
= kDefaultFontSize
;
8100 if (strcmp (weight
, "bold") == 0)
8105 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
8107 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
8109 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
8111 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
8112 but take overlap into account. */
8113 memmove (family
+ foundry_len
+ 1, family
, family_len
);
8114 memcpy (family
, foundry
, foundry_len
);
8115 family
[foundry_len
] = '-';
8116 family
[foundry_len
+ 1 + family_len
] = '-';
8117 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
8123 for (p
= family
; *p
; p
++)
8124 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8125 for some locales. */
8134 add_font_name_table_entry (char *font_name
)
8136 if (font_name_table_size
== 0)
8138 font_name_table_size
= 256;
8139 font_name_table
= (char **)
8140 xmalloc (font_name_table_size
* sizeof (char *));
8142 else if (font_name_count
+ 1 >= font_name_table_size
)
8144 font_name_table_size
*= 2;
8145 font_name_table
= (char **)
8146 xrealloc (font_name_table
,
8147 font_name_table_size
* sizeof (char *));
8150 font_name_table
[font_name_count
++] = font_name
;
8154 add_mac_font_name (name
, size
, style
, charset
)
8158 const char *charset
;
8161 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8164 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8165 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8166 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8167 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8174 fm_get_style_from_font (font
)
8178 FMFontStyle style
= normal
;
8181 FMFontFamily font_family
;
8182 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8184 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8185 some font (e.g., Optima) even if it is `bold'. */
8186 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8187 sizeof (mac_style
), &mac_style
, &len
);
8189 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8190 style
= EndianU16_BtoN (mac_style
);
8192 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8198 atsu_find_font_from_family_name (family
)
8201 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8204 Lisp_Object rest
, best
;
8205 FMFontStyle min_style
, style
;
8207 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8210 return kATSUInvalidFontID
;
8212 rest
= HASH_VALUE (h
, i
);
8213 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8214 return cons_to_long (rest
);
8216 rest
= Fnreverse (rest
);
8220 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8223 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8224 if (style
< min_style
)
8227 if (style
== normal
)
8234 while (!NILP (rest
));
8236 HASH_VALUE (h
, i
) = best
;
8237 return cons_to_long (best
);
8241 fm_style_to_face_attributes (fm_style
)
8242 FMFontStyle fm_style
;
8246 fm_style
&= (bold
| italic
);
8247 tem
= assq_no_quit (make_number (fm_style
),
8248 fm_style_face_attributes_alist
);
8252 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8253 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8254 fm_style_face_attributes_alist
=
8255 Fcons (Fcons (make_number (fm_style
), tem
),
8256 fm_style_face_attributes_alist
);
8262 atsu_find_font_family_name (font_id
)
8267 Lisp_Object family
= Qnil
;
8269 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8270 kFontMacintoshPlatform
, kFontNoScript
,
8271 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8274 family
= make_uninit_string (len
);
8275 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8276 kFontMacintoshPlatform
, kFontNoScript
,
8277 kFontNoLanguage
, len
, SDATA (family
),
8281 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8287 mac_atsu_font_face_attributes (font_id
)
8290 Lisp_Object family
, style_attrs
;
8292 family
= atsu_find_font_family_name (font_id
);
8295 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8296 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8300 /* Sets up the table font_name_table to contain the list of all fonts
8301 in the system the first time the table is used so that the Resource
8302 Manager need not be accessed every time this information is
8306 init_font_name_table ()
8308 #if TARGET_API_MAC_CARBON
8309 FMFontFamilyIterator ffi
;
8310 FMFontFamilyInstanceIterator ffii
;
8312 Lisp_Object text_encoding_info_alist
;
8313 struct gcpro gcpro1
;
8315 text_encoding_info_alist
= create_text_encoding_info_alist ();
8318 #if USE_CG_TEXT_DRAWING
8319 init_cg_text_anti_aliasing_threshold ();
8321 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8322 text_encoding_info_alist
)))
8325 struct Lisp_Hash_Table
*h
;
8327 ItemCount nfonts
, i
;
8328 ATSUFontID
*font_ids
= NULL
;
8329 Lisp_Object prev_family
= Qnil
;
8333 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8334 make_float (DEFAULT_REHASH_SIZE
),
8335 make_float (DEFAULT_REHASH_THRESHOLD
),
8337 h
= XHASH_TABLE (atsu_font_id_hash
);
8339 err
= ATSUFontCount (&nfonts
);
8342 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8343 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8346 for (i
= 0; i
< nfonts
; i
++)
8350 family
= atsu_find_font_family_name (font_ids
[i
]);
8351 if (NILP (family
) || SREF (family
, 0) == '.')
8353 if (!NILP (Fequal (prev_family
, family
)))
8354 family
= prev_family
;
8356 j
= hash_lookup (h
, family
, &hash_code
);
8359 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8360 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8363 else if (EQ (prev_family
, family
))
8364 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8366 prev_family
= family
;
8373 /* Create a dummy instance iterator here to avoid creating and
8374 destroying it in the loop. */
8375 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8377 /* Create an iterator to enumerate the font families. */
8378 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8381 FMDisposeFontFamilyInstanceIterator (&ffii
);
8385 GCPRO1 (text_encoding_info_alist
);
8387 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8393 TextEncoding encoding
;
8394 TextEncodingBase sc
;
8395 Lisp_Object text_encoding_info
, family
;
8397 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8403 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8405 sc
= GetTextEncodingBase (encoding
);
8406 text_encoding_info
= assq_no_quit (make_number (sc
),
8407 text_encoding_info_alist
);
8408 if (NILP (text_encoding_info
))
8409 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8410 text_encoding_info_alist
);
8411 decode_mac_font_name (name
, sizeof (name
),
8412 XCAR (XCDR (text_encoding_info
)));
8413 family
= build_string (name
);
8414 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8416 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8417 fm_font_family_alist
);
8419 /* Point the instance iterator at the current font family. */
8420 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8423 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8426 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8428 if (size
> 0 || style
== normal
)
8429 for (; CONSP (rest
); rest
= XCDR (rest
))
8430 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8436 /* Dispose of the iterators. */
8437 FMDisposeFontFamilyIterator (&ffi
);
8438 FMDisposeFontFamilyInstanceIterator (&ffii
);
8439 #else /* !TARGET_API_MAC_CARBON */
8441 SInt16 fontnum
, old_fontnum
;
8442 int num_mac_fonts
= CountResources('FOND');
8444 Handle font_handle
, font_handle_2
;
8445 short id
, scriptcode
;
8448 struct FontAssoc
*fat
;
8449 struct AsscEntry
*assc_entry
;
8450 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8451 struct gcpro gcpro1
;
8453 GetPort (&port
); /* save the current font number used */
8454 old_fontnum
= port
->txFont
;
8456 text_encoding_info_alist
= create_text_encoding_info_alist ();
8458 GCPRO1 (text_encoding_info_alist
);
8460 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8462 font_handle
= GetIndResource ('FOND', i
);
8466 GetResInfo (font_handle
, &id
, &type
, name
);
8467 GetFNum (name
, &fontnum
);
8469 if (fontnum
== 0 || *name
== '.')
8473 scriptcode
= FontToScript (fontnum
);
8474 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8475 text_encoding_info_alist
);
8476 if (NILP (text_encoding_info
))
8477 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8478 text_encoding_info_alist
);
8479 decode_mac_font_name (name
, sizeof (name
),
8480 XCAR (XCDR (text_encoding_info
)));
8481 family
= build_string (name
);
8482 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8484 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8485 fm_font_family_alist
);
8488 HLock (font_handle
);
8490 if (GetResourceSizeOnDisk (font_handle
)
8491 >= sizeof (struct FamRec
))
8493 fat
= (struct FontAssoc
*) (*font_handle
8494 + sizeof (struct FamRec
));
8496 = (struct AsscEntry
*) (*font_handle
8497 + sizeof (struct FamRec
)
8498 + sizeof (struct FontAssoc
));
8500 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8502 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8504 for (; CONSP (rest
); rest
= XCDR (rest
))
8505 add_mac_font_name (name
, assc_entry
->fontSize
,
8506 assc_entry
->fontStyle
,
8507 SDATA (XCAR (rest
)));
8511 HUnlock (font_handle
);
8512 font_handle_2
= GetNextFOND (font_handle
);
8513 ReleaseResource (font_handle
);
8514 font_handle
= font_handle_2
;
8516 while (ResError () == noErr
&& font_handle
);
8521 TextFont (old_fontnum
);
8522 #endif /* !TARGET_API_MAC_CARBON */
8527 mac_clear_font_name_table ()
8531 for (i
= 0; i
< font_name_count
; i
++)
8532 xfree (font_name_table
[i
]);
8533 xfree (font_name_table
);
8534 font_name_table
= NULL
;
8535 font_name_table_size
= font_name_count
= 0;
8536 fm_font_family_alist
= Qnil
;
8540 enum xlfd_scalable_field_index
8542 XLFD_SCL_PIXEL_SIZE
,
8543 XLFD_SCL_POINT_SIZE
,
8548 static const int xlfd_scalable_fields
[] =
8557 mac_do_list_fonts (pattern
, maxnames
)
8558 const char *pattern
;
8562 Lisp_Object font_list
= Qnil
;
8563 struct xlfdpat
*pat
;
8566 int scl_val
[XLFD_SCL_LAST
], *val
;
8570 if (font_name_table
== NULL
) /* Initialize when first used. */
8571 init_font_name_table ();
8573 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8576 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8577 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8578 fonts are scaled according to the specified size. */
8581 field
= xlfd_scalable_fields
;
8589 if ('0' <= *ptr
&& *ptr
<= '9')
8591 *val
= *ptr
++ - '0';
8592 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8593 *val
= *val
* 10 + *ptr
++ - '0';
8600 ptr
= strchr (ptr
, '-');
8603 while (ptr
&& i
< 14);
8605 if (i
== 14 && ptr
== NULL
)
8607 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8608 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8609 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8610 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8612 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8613 scl_val
[XLFD_SCL_POINT_SIZE
] =
8614 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8615 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8617 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8618 scl_val
[XLFD_SCL_AVGWIDTH
] =
8619 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8620 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8624 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8626 pat
= xlfdpat_create (pattern
);
8630 exact
= xlfdpat_exact_p (pat
);
8632 for (i
= 0; i
< font_name_count
; i
++)
8634 if (xlfdpat_match (pat
, font_name_table
[i
]))
8636 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8637 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8640 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8641 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8643 int former_len
= ptr
- font_name_table
[i
];
8645 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8646 memcpy (scaled
, font_name_table
[i
], former_len
);
8647 sprintf (scaled
+ former_len
,
8648 "-%d-%d-72-72-m-%d-%s",
8649 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8650 scl_val
[XLFD_SCL_POINT_SIZE
],
8651 scl_val
[XLFD_SCL_AVGWIDTH
],
8652 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8654 if (xlfdpat_match (pat
, scaled
))
8656 font_list
= Fcons (build_string (scaled
), font_list
);
8658 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8666 xlfdpat_destroy (pat
);
8671 /* Return a list of names of available fonts matching PATTERN on frame F.
8673 Frame F null means we have not yet created any frame on Mac, and
8674 consult the first display in x_display_list. MAXNAMES sets a limit
8675 on how many fonts to match. */
8678 x_list_fonts (f
, pattern
, size
, maxnames
)
8680 Lisp_Object pattern
;
8683 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8684 struct mac_display_info
*dpyinfo
8685 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8687 xassert (size
<= 0);
8689 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8690 if (NILP (patterns
))
8691 patterns
= Fcons (pattern
, Qnil
);
8693 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8695 pattern
= XCAR (patterns
);
8697 if (!STRINGP (pattern
))
8700 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8701 key
= Fcons (pattern
, make_number (maxnames
));
8703 list
= Fassoc (key
, tem
);
8706 list
= Fcdr_safe (list
);
8707 /* We have a cashed list. Don't have to get the list again. */
8712 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8715 /* MAC_TODO: add code for matching outline fonts here */
8717 /* Now store the result in the cache. */
8718 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8719 Fcons (Fcons (key
, list
),
8720 XCAR (XCDR (dpyinfo
->name_list_element
))));
8723 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8732 /* Check that FONT is valid on frame F. It is if it can be found in F's
8736 x_check_font (f
, font
)
8741 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8743 xassert (font
!= NULL
);
8745 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8746 if (dpyinfo
->font_table
[i
].name
8747 && font
== dpyinfo
->font_table
[i
].font
)
8750 xassert (i
< dpyinfo
->n_fonts
);
8753 #endif /* GLYPH_DEBUG != 0 */
8755 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8756 Note: There are (broken) X fonts out there with invalid XFontStruct
8757 min_bounds contents. For example, handa@etl.go.jp reports that
8758 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8759 have font->min_bounds.width == 0. */
8762 x_font_min_bounds (font
, w
, h
)
8763 MacFontStruct
*font
;
8766 *h
= FONT_HEIGHT (font
);
8767 *w
= font
->min_bounds
.width
;
8771 /* Compute the smallest character width and smallest font height over
8772 all fonts available on frame F. Set the members smallest_char_width
8773 and smallest_font_height in F's x_display_info structure to
8774 the values computed. Value is non-zero if smallest_font_height or
8775 smallest_char_width become smaller than they were before. */
8778 x_compute_min_glyph_bounds (f
)
8782 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8783 MacFontStruct
*font
;
8784 int old_width
= dpyinfo
->smallest_char_width
;
8785 int old_height
= dpyinfo
->smallest_font_height
;
8787 dpyinfo
->smallest_font_height
= 100000;
8788 dpyinfo
->smallest_char_width
= 100000;
8790 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8791 if (dpyinfo
->font_table
[i
].name
)
8793 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8796 font
= (MacFontStruct
*) fontp
->font
;
8797 xassert (font
!= (MacFontStruct
*) ~0);
8798 x_font_min_bounds (font
, &w
, &h
);
8800 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8801 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8804 xassert (dpyinfo
->smallest_char_width
> 0
8805 && dpyinfo
->smallest_font_height
> 0);
8807 return (dpyinfo
->n_fonts
== 1
8808 || dpyinfo
->smallest_char_width
< old_width
8809 || dpyinfo
->smallest_font_height
< old_height
);
8813 /* Determine whether given string is a fully-specified XLFD: all 14
8814 fields are present, none is '*'. */
8817 is_fully_specified_xlfd (p
)
8826 for (i
= 0; i
< 13; i
++)
8828 q
= strchr (p
+ 1, '-');
8831 if (q
- p
== 2 && *(p
+ 1) == '*')
8836 if (strchr (p
+ 1, '-') != NULL
)
8839 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8846 /* mac_load_query_font creates and returns an internal representation
8847 for a font in a MacFontStruct struct. There is really no concept
8848 corresponding to "loading" a font on the Mac. But we check its
8849 existence and find the font number and all other information for it
8850 and store them in the returned MacFontStruct. */
8852 static MacFontStruct
*
8853 mac_load_query_font (f
, fontname
)
8863 static ATSUFontID font_id
;
8864 ATSUStyle mac_style
= NULL
;
8867 #if TARGET_API_MAC_CARBON
8868 TextEncoding encoding
;
8873 MacFontStruct
*font
;
8874 XCharStruct
*space_bounds
= NULL
, *pcm
;
8876 if (is_fully_specified_xlfd (fontname
))
8880 Lisp_Object matched_fonts
;
8882 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8883 if (NILP (matched_fonts
))
8885 name
= SDATA (XCAR (matched_fonts
));
8888 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8892 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8895 static const ATSUAttributeTag tags
[] =
8896 {kATSUFontTag
, kATSUSizeTag
,
8897 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8898 static const ByteCount sizes
[] =
8899 {sizeof (ATSUFontID
), sizeof (Fixed
),
8900 sizeof (Boolean
), sizeof (Boolean
)};
8901 static Fixed size_fixed
;
8902 static Boolean bold_p
, italic_p
;
8903 static const ATSUAttributeValuePtr values
[] =
8904 {&font_id
, &size_fixed
,
8905 &bold_p
, &italic_p
};
8906 static const ATSUFontFeatureType types
[] =
8907 {kAllTypographicFeaturesType
, kDiacriticsType
};
8908 static const ATSUFontFeatureSelector selectors
[] =
8909 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8912 font_id
= atsu_find_font_from_family_name (family
);
8913 if (font_id
== kATSUInvalidFontID
)
8915 size_fixed
= Long2Fix (size
);
8916 bold_p
= (fontface
& bold
) != 0;
8917 italic_p
= (fontface
& italic
) != 0;
8918 err
= ATSUCreateStyle (&mac_style
);
8921 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8925 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8926 tags
, sizes
, values
);
8929 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8932 scriptcode
= kTextEncodingMacUnicode
;
8937 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8941 fontnum
= XINT (XCDR (tmp
));
8942 #if TARGET_API_MAC_CARBON
8943 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8945 scriptcode
= GetTextEncodingBase (encoding
);
8947 scriptcode
= FontToScript (fontnum
);
8951 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8953 font
->mac_fontnum
= fontnum
;
8954 font
->mac_fontsize
= size
;
8955 font
->mac_fontface
= fontface
;
8956 font
->mac_scriptcode
= scriptcode
;
8958 font
->mac_style
= mac_style
;
8959 #if USE_CG_TEXT_DRAWING
8960 font
->cg_font
= NULL
;
8961 font
->cg_glyphs
= NULL
;
8965 /* Apple Japanese (SJIS) font is listed as both
8966 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8967 (Roman script) in init_font_name_table (). The latter should be
8968 treated as a one-byte font. */
8969 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8970 font
->mac_scriptcode
= smRoman
;
8972 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8975 if (font
->mac_style
)
8980 font
->min_byte1
= 0;
8981 font
->max_byte1
= 0xff;
8982 font
->min_char_or_byte2
= 0;
8983 font
->max_char_or_byte2
= 0xff;
8985 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8986 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8987 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8988 pcm_init (font
->bounds
.rows
[0], 0x100);
8990 #if USE_CG_TEXT_DRAWING
8994 ATSFontRef ats_font
;
8996 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8998 /* Use CG text drawing if italic/bold is not synthesized. */
8999 if (err
== noErr
&& style
== fontface
)
9001 ats_font
= FMGetATSFontRefFromFont (font_id
);
9002 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
9008 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
9009 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
9012 space_bounds
= font
->bounds
.rows
[0] + 0x20;
9013 err
= mac_query_char_extents (font
->mac_style
, 0x20,
9014 &font
->ascent
, &font
->descent
,
9016 #if USE_CG_TEXT_DRAWING
9017 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
9024 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
9026 mac_unload_font (&one_mac_display_info
, font
);
9030 pcm
= font
->bounds
.rows
[0];
9031 for (c
= 0x21; c
<= 0xff; c
++)
9034 /* Soft hyphen is not supported in ATSUI. */
9038 #if USE_CG_TEXT_DRAWING
9039 if (font
->cg_glyphs
)
9049 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
9050 pcm
? pcm
+ c
: NULL
,
9051 #if USE_CG_TEXT_DRAWING
9052 (font
->cg_glyphs
? font
->cg_glyphs
+ c
9059 #if USE_CG_TEXT_DRAWING
9060 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
9062 /* Don't use CG text drawing if font substitution occurs in
9063 ASCII or Latin-1 characters. */
9064 CGFontRelease (font
->cg_font
);
9065 font
->cg_font
= NULL
;
9066 xfree (font
->cg_glyphs
);
9067 font
->cg_glyphs
= NULL
;
9078 FontInfo the_fontinfo
;
9079 int is_two_byte_font
;
9082 mac_prepare_for_quickdraw (f
);
9084 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
9088 TextFace (fontface
);
9090 GetFontInfo (&the_fontinfo
);
9092 font
->ascent
= the_fontinfo
.ascent
;
9093 font
->descent
= the_fontinfo
.descent
;
9095 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
9096 || font
->mac_scriptcode
== smTradChinese
9097 || font
->mac_scriptcode
== smSimpChinese
9098 || font
->mac_scriptcode
== smKorean
);
9100 if (is_two_byte_font
)
9104 font
->min_byte1
= 0xa1;
9105 font
->max_byte1
= 0xfe;
9106 font
->min_char_or_byte2
= 0xa1;
9107 font
->max_char_or_byte2
= 0xfe;
9109 /* Use the width of an "ideographic space" of that font
9110 because the_fontinfo.widMax returns the wrong width for
9112 switch (font
->mac_scriptcode
)
9115 font
->min_byte1
= 0x81;
9116 font
->max_byte1
= 0xfc;
9117 font
->min_char_or_byte2
= 0x40;
9118 font
->max_char_or_byte2
= 0xfc;
9119 char_width
= StringWidth("\p\x81\x40");
9122 font
->min_char_or_byte2
= 0x40;
9123 char_width
= StringWidth("\p\xa1\x40");
9126 char_width
= StringWidth("\p\xa1\xa1");
9129 char_width
= StringWidth("\p\xa1\xa1");
9133 font
->bounds
.per_char
= NULL
;
9135 if (fontface
& italic
)
9136 font
->max_bounds
.rbearing
= char_width
+ 1;
9138 font
->max_bounds
.rbearing
= char_width
;
9139 font
->max_bounds
.lbearing
= 0;
9140 font
->max_bounds
.width
= char_width
;
9141 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
9142 font
->max_bounds
.descent
= the_fontinfo
.descent
;
9144 font
->min_bounds
= font
->max_bounds
;
9150 font
->min_byte1
= font
->max_byte1
= 0;
9151 font
->min_char_or_byte2
= 0x20;
9152 font
->max_char_or_byte2
= 0xff;
9154 font
->bounds
.per_char
=
9155 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9156 bzero (font
->bounds
.per_char
,
9157 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9159 space_bounds
= font
->bounds
.per_char
;
9160 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9161 &font
->descent
, space_bounds
, NULL
);
9162 if (err
!= noErr
|| space_bounds
->width
<= 0)
9164 mac_unload_font (&one_mac_display_info
, font
);
9168 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9169 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9177 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9178 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9181 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9183 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9185 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9187 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9189 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9192 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9194 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9196 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9198 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9200 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9205 font
->mac_style
== NULL
&&
9207 font
->max_bounds
.width
== font
->min_bounds
.width
9208 && font
->min_bounds
.lbearing
>= 0
9209 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9211 /* Fixed width and no overhangs. */
9212 xfree (font
->bounds
.per_char
);
9213 font
->bounds
.per_char
= NULL
;
9217 #if !defined (MAC_OS8) || USE_ATSUI
9218 /* AppKit and WebKit do some adjustment to the heights of Courier,
9219 Helvetica, and Times. This only works on the environments where
9220 srcCopy text transfer mode is never used. */
9222 #ifdef MAC_OS8 /* implies USE_ATSUI */
9225 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9226 || strcmp (family
, "times") == 0))
9227 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9235 mac_unload_font (dpyinfo
, font
)
9236 struct mac_display_info
*dpyinfo
;
9239 xfree (font
->full_name
);
9241 if (font
->mac_style
)
9245 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9246 if (font
->bounds
.rows
[i
])
9247 xfree (font
->bounds
.rows
[i
]);
9248 xfree (font
->bounds
.rows
);
9249 ATSUDisposeStyle (font
->mac_style
);
9253 if (font
->bounds
.per_char
)
9254 xfree (font
->bounds
.per_char
);
9255 #if USE_CG_TEXT_DRAWING
9257 CGFontRelease (font
->cg_font
);
9258 if (font
->cg_glyphs
)
9259 xfree (font
->cg_glyphs
);
9265 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9266 pointer to the structure font_info while allocating it dynamically.
9267 If SIZE is 0, load any size of font.
9268 If loading is failed, return NULL. */
9271 x_load_font (f
, fontname
, size
)
9273 register char *fontname
;
9276 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9277 Lisp_Object font_names
;
9279 /* Get a list of all the fonts that match this name. Once we
9280 have a list of matching fonts, we compare them against the fonts
9281 we already have by comparing names. */
9282 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9284 if (!NILP (font_names
))
9289 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9290 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9291 if (dpyinfo
->font_table
[i
].name
9292 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9293 SDATA (XCAR (tail
)))
9294 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9295 SDATA (XCAR (tail
)))))
9296 return (dpyinfo
->font_table
+ i
);
9301 /* Load the font and add it to the table. */
9303 struct MacFontStruct
*font
;
9304 struct font_info
*fontp
;
9307 fontname
= (char *) SDATA (XCAR (font_names
));
9310 font
= mac_load_query_font (f
, fontname
);
9315 /* Find a free slot in the font table. */
9316 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9317 if (dpyinfo
->font_table
[i
].name
== NULL
)
9320 /* If no free slot found, maybe enlarge the font table. */
9321 if (i
== dpyinfo
->n_fonts
9322 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9325 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9326 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9328 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9331 fontp
= dpyinfo
->font_table
+ i
;
9332 if (i
== dpyinfo
->n_fonts
)
9335 /* Now fill in the slots of *FONTP. */
9337 bzero (fontp
, sizeof (*fontp
));
9339 fontp
->font_idx
= i
;
9340 fontp
->charset
= -1; /* fs_load_font sets it. */
9341 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9342 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9344 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9346 /* Fixed width font. */
9347 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9354 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9355 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9357 fontp
->space_width
= pcm
->width
;
9359 fontp
->space_width
= FONT_WIDTH (font
);
9363 int width
= pcm
->width
;
9364 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9365 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9366 width
+= pcm
->width
;
9367 fontp
->average_width
= width
/ 95;
9370 fontp
->average_width
= FONT_WIDTH (font
);
9373 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9374 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9376 fontp
->size
= font
->max_bounds
.width
;
9377 fontp
->height
= FONT_HEIGHT (font
);
9379 /* For some font, ascent and descent in max_bounds field is
9380 larger than the above value. */
9381 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9382 if (max_height
> fontp
->height
)
9383 fontp
->height
= max_height
;
9386 /* MAC_TODO: The script encoding is irrelevant in unicode? */
9387 /* The slot `encoding' specifies how to map a character
9388 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9389 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9390 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9391 2:0xA020..0xFF7F). For the moment, we don't know which charset
9392 uses this font. So, we set information in fontp->encoding_type
9393 which is never used by any charset. If mapping can't be
9394 decided, set FONT_ENCODING_NOT_DECIDED. */
9395 if (font
->mac_scriptcode
== smJapanese
)
9396 fontp
->encoding_type
= 4;
9399 fontp
->encoding_type
9400 = (font
->max_byte1
== 0
9402 ? (font
->min_char_or_byte2
< 0x80
9403 ? (font
->max_char_or_byte2
< 0x80
9404 ? 0 /* 0x20..0x7F */
9405 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9406 : 1) /* 0xA0..0xFF */
9408 : (font
->min_byte1
< 0x80
9409 ? (font
->max_byte1
< 0x80
9410 ? (font
->min_char_or_byte2
< 0x80
9411 ? (font
->max_char_or_byte2
< 0x80
9412 ? 0 /* 0x2020..0x7F7F */
9413 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9414 : 3) /* 0x20A0..0x7FFF */
9415 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9416 : (font
->min_char_or_byte2
< 0x80
9417 ? (font
->max_char_or_byte2
< 0x80
9418 ? 2 /* 0xA020..0xFF7F */
9419 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9420 : 1))); /* 0xA0A0..0xFFFF */
9423 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9424 fontp
->baseline_offset
9425 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9426 ? (long) value
: 0);
9427 fontp
->relative_compose
9428 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9429 ? (long) value
: 0);
9430 fontp
->default_ascent
9431 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9432 ? (long) value
: 0);
9434 fontp
->baseline_offset
= 0;
9435 fontp
->relative_compose
= 0;
9436 fontp
->default_ascent
= 0;
9439 /* Set global flag fonts_changed_p to non-zero if the font loaded
9440 has a character with a smaller width than any other character
9441 before, or if the font loaded has a smaller height than any
9442 other font loaded before. If this happens, it will make a
9443 glyph matrix reallocation necessary. */
9444 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9451 /* Return a pointer to struct font_info of a font named FONTNAME for
9452 frame F. If no such font is loaded, return NULL. */
9455 x_query_font (f
, fontname
)
9457 register char *fontname
;
9459 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9462 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9463 if (dpyinfo
->font_table
[i
].name
9464 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9465 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9466 return (dpyinfo
->font_table
+ i
);
9471 /* Find a CCL program for a font specified by FONTP, and set the member
9472 `encoder' of the structure. */
9475 x_find_ccl_program (fontp
)
9476 struct font_info
*fontp
;
9478 Lisp_Object list
, elt
;
9480 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9484 && STRINGP (XCAR (elt
))
9485 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9491 struct ccl_program
*ccl
9492 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9494 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9497 fontp
->font_encoder
= ccl
;
9501 #if USE_MAC_FONT_PANEL
9502 /* Whether Font Panel has been shown before. The first call to font
9503 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9504 slow. This variable is used for deferring such a call as much as
9506 static int font_panel_shown_p
= 0;
9508 extern Lisp_Object Qfont
;
9509 static Lisp_Object Qpanel_closed
, Qselection
;
9511 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9515 const EventParamName
*,
9516 const EventParamType
*));
9519 mac_font_panel_visible_p ()
9521 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9524 static pascal OSStatus
9525 mac_handle_font_event (next_handler
, event
, data
)
9526 EventHandlerCallRef next_handler
;
9530 OSStatus result
, err
;
9533 const EventParamName
*names
;
9534 const EventParamType
*types
;
9535 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9536 kEventParamATSUFontSize
,
9537 kEventParamFMFontFamily
,
9538 kEventParamFMFontStyle
,
9539 kEventParamFMFontSize
,
9540 kEventParamFontColor
};
9541 static const EventParamType types_sel
[] = {typeATSUFontID
,
9548 result
= CallNextEventHandler (next_handler
, event
);
9549 if (result
!= eventNotHandledErr
)
9552 switch (GetEventKind (event
))
9554 case kEventFontPanelClosed
:
9555 id_key
= Qpanel_closed
;
9561 case kEventFontSelection
:
9562 id_key
= Qselection
;
9563 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9569 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9579 mac_show_hide_font_panel ()
9581 if (!font_panel_shown_p
)
9585 static const EventTypeSpec specs
[] =
9586 {{kEventClassFont
, kEventFontPanelClosed
},
9587 {kEventClassFont
, kEventFontSelection
}};
9589 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9590 GetEventTypeCount (specs
),
9595 font_panel_shown_p
= 1;
9598 return FPShowHideFontPanel ();
9602 mac_set_font_info_for_selection (f
, face_id
, c
)
9607 EventTargetRef target
= NULL
;
9608 XFontStruct
*font
= NULL
;
9610 if (!mac_font_panel_visible_p ())
9615 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9617 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9621 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9622 face
= FACE_FROM_ID (f
, face_id
);
9628 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9631 if (font
->mac_fontnum
!= -1)
9633 FontSelectionQDStyle qd_style
;
9635 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9636 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9637 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9638 qd_style
.size
= font
->mac_fontsize
;
9639 qd_style
.hasColor
= false;
9641 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9642 1, &qd_style
, target
);
9645 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9646 1, &font
->mac_style
, target
);
9654 /* The Mac Event loop code */
9656 #if !TARGET_API_MAC_CARBON
9658 #include <Quickdraw.h>
9659 #include <Balloons.h>
9660 #include <Devices.h>
9662 #include <Gestalt.h>
9664 #include <Processes.h>
9666 #include <ToolUtils.h>
9667 #include <TextUtils.h>
9668 #include <Dialogs.h>
9671 #include <Resources.h>
9676 #endif /* ! TARGET_API_MAC_CARBON */
9681 #define DEFAULT_NUM_COLS 80
9683 #define MIN_DOC_SIZE 64
9684 #define MAX_DOC_SIZE 32767
9686 #define EXTRA_STACK_ALLOC (256 * 1024)
9688 #define ARGV_STRING_LIST_ID 129
9689 #define ABOUT_ALERT_ID 128
9690 #define RAM_TOO_LARGE_ALERT_ID 129
9692 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9693 Lisp_Object Qreverse
;
9696 /* Modifier associated with the control key, or nil to ignore. */
9697 Lisp_Object Vmac_control_modifier
;
9699 /* Modifier associated with the option key, or nil to ignore. */
9700 Lisp_Object Vmac_option_modifier
;
9702 /* Modifier associated with the command key, or nil to ignore. */
9703 Lisp_Object Vmac_command_modifier
;
9705 /* Modifier associated with the function key, or nil to ignore. */
9706 Lisp_Object Vmac_function_modifier
;
9708 /* True if the option and command modifiers should be used to emulate
9709 a three button mouse */
9710 Lisp_Object Vmac_emulate_three_button_mouse
;
9712 #if TARGET_API_MAC_CARBON
9713 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9714 mouse-2, instead of mouse-3. */
9715 int mac_wheel_button_is_mouse_2
;
9717 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9718 for processing before Emacs sees it. */
9719 int mac_pass_command_to_system
;
9721 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9722 for processing before Emacs sees it. */
9723 int mac_pass_control_to_system
;
9726 /* Points to the variable `inev' in the function XTread_socket. It is
9727 used for passing an input event to the function back from
9728 Carbon/Apple event handlers. */
9729 static struct input_event
*read_socket_inev
= NULL
;
9731 /* Whether or not the screen configuration has changed. */
9732 static int mac_screen_config_changed
= 0;
9734 Point saved_menu_event_location
;
9737 #if TARGET_API_MAC_CARBON
9738 static Lisp_Object Qhi_command
;
9740 extern Lisp_Object Qwindow
;
9741 static Lisp_Object Qtoolbar_switch_mode
;
9744 static TSMDocumentID tsm_document_id
;
9745 Lisp_Object Qtext_input
;
9746 Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9747 Lisp_Object Vmac_ts_active_input_overlay
, Vmac_ts_active_input_buf
;
9748 extern Lisp_Object Qbefore_string
;
9749 static Lisp_Object Vmac_ts_script_language_on_focus
;
9750 static Lisp_Object saved_ts_script_language_on_focus
;
9751 static ScriptLanguageRecord saved_ts_language
;
9752 static Component saved_ts_component
;
9754 #endif /* TARGET_API_MAC_CARBON */
9755 extern int mac_ready_for_apple_events
;
9756 extern Lisp_Object Qundefined
;
9757 extern void init_apple_event_handler
P_ ((void));
9758 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9759 Lisp_Object
*, Lisp_Object
*,
9761 extern OSErr init_coercion_handler
P_ ((void));
9764 extern OSErr install_drag_handler
P_ ((WindowRef
));
9765 extern void remove_drag_handler
P_ ((WindowRef
));
9767 #if TARGET_API_MAC_CARBON
9768 /* Showing help echo string during menu tracking */
9769 extern OSStatus install_menu_target_item_handler
P_ ((void));
9772 extern OSStatus
install_service_handler ();
9773 Lisp_Object Qservice
, Qpaste
, Qperform
;
9774 Lisp_Object Qmouse_drag_overlay
;
9778 extern void init_emacs_passwd_dir ();
9779 extern int emacs_main (int, char **, char **);
9781 extern void initialize_applescript();
9782 extern void terminate_applescript();
9784 /* Table for translating Mac keycode to X keysym values. Contributed
9786 Mapping for special keys is now identical to that in Apple X11
9787 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9788 on the right of the Cmd key on laptops, and fn + `enter' (->
9790 static const unsigned char keycode_to_xkeysym_table
[] = {
9791 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9792 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9793 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9795 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9796 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9797 /*0x38*/ 0, 0, 0, 0,
9798 /*0x3C*/ 0, 0, 0, 0,
9800 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9801 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9802 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9803 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9805 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9806 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9807 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9808 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9810 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9811 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9812 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9813 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9815 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9816 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9817 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9818 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9822 /* Table for translating Mac keycode with the laptop `fn' key to that
9823 without it. Destination symbols in comments are keys on US
9824 keyboard, and they may not be the same on other types of keyboards.
9825 If the destination is identical to the source (f1 ... f12), it
9826 doesn't map `fn' key to a modifier. */
9827 static const unsigned char fn_keycode_to_keycode_table
[] = {
9828 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9829 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9830 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9832 /*0x30*/ 0, 0, 0, 0,
9833 /*0x34*/ 0, 0, 0, 0,
9834 /*0x38*/ 0, 0, 0, 0,
9835 /*0x3C*/ 0, 0, 0, 0,
9837 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9838 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9839 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9840 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9842 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9843 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9844 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9845 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9847 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9848 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9849 /*0x68*/ 0, 0, 0, 0,
9850 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9852 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9853 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9854 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9857 #endif /* MAC_OSX */
9860 #if TARGET_API_MAC_CARBON
9861 mac_to_emacs_modifiers (UInt32 mods
)
9863 mac_to_emacs_modifiers (EventModifiers mods
)
9866 unsigned int result
= 0;
9867 if (mods
& shiftKey
)
9868 result
|= shift_modifier
;
9870 /* Deactivated to simplify configuration:
9871 if Vmac_option_modifier is non-NIL, we fully process the Option
9872 key. Otherwise, we only process it if an additional Ctrl or Command
9873 is pressed. That way the system may convert the character to a
9875 if ((mods & optionKey) &&
9876 (( !NILP(Vmac_option_modifier) ||
9877 ((mods & cmdKey) || (mods & controlKey))))) */
9879 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9880 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9882 result
|= XUINT(val
);
9884 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9885 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9887 result
|= XUINT(val
);
9889 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9890 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9892 result
|= XUINT(val
);
9896 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9897 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9899 result
|= XUINT(val
);
9907 mac_mapped_modifiers (modifiers
)
9910 UInt32 mapped_modifiers_all
=
9911 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9912 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9913 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9916 mapped_modifiers_all
|=
9917 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9920 return mapped_modifiers_all
& modifiers
;
9924 mac_get_emulated_btn ( UInt32 modifiers
)
9927 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9928 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9929 if (modifiers
& cmdKey
)
9930 result
= cmdIs3
? 2 : 1;
9931 else if (modifiers
& optionKey
)
9932 result
= cmdIs3
? 1 : 2;
9939 mac_get_selected_range (w
, range
)
9943 Lisp_Object overlay
= find_symbol_value (Qmouse_drag_overlay
);
9944 struct buffer
*b
= XBUFFER (w
->buffer
);
9945 int begv
= BUF_BEGV (b
), zv
= BUF_ZV (b
);
9948 if (OVERLAYP (overlay
)
9949 && EQ (Foverlay_buffer (overlay
), w
->buffer
)
9950 && (start
= XINT (Foverlay_start (overlay
)),
9951 end
= XINT (Foverlay_end (overlay
)),
9956 if (w
== XWINDOW (selected_window
) && b
== current_buffer
)
9959 start
= marker_position (w
->pointm
);
9961 if (NILP (Vtransient_mark_mode
) || NILP (b
->mark_active
))
9965 int mark_pos
= marker_position (b
->mark
);
9967 if (start
<= mark_pos
)
9981 else if (start
> zv
)
9990 range
->location
= start
- begv
;
9991 range
->length
= end
- start
;
9994 /* Store the text of the buffer BUF from START to END as Unicode
9995 characters in CHARACTERS. Return non-zero if successful. */
9998 mac_store_buffer_text_to_unicode_chars (buf
, start
, end
, characters
)
10001 UniChar
*characters
;
10003 int start_byte
, end_byte
, char_count
, byte_count
;
10004 struct coding_system coding
;
10005 unsigned char *dst
= (unsigned char *) characters
;
10007 start_byte
= buf_charpos_to_bytepos (buf
, start
);
10008 end_byte
= buf_charpos_to_bytepos (buf
, end
);
10009 char_count
= end
- start
;
10010 byte_count
= end_byte
- start_byte
;
10012 if (setup_coding_system (
10013 #ifdef WORDS_BIG_ENDIAN
10014 intern ("utf-16be")
10016 intern ("utf-16le")
10021 coding
.src_multibyte
= !NILP (buf
->enable_multibyte_characters
);
10022 coding
.dst_multibyte
= 0;
10023 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
10024 coding
.composing
= COMPOSITION_DISABLED
;
10026 if (BUF_GPT_BYTE (buf
) <= start_byte
|| end_byte
<= BUF_GPT_BYTE (buf
))
10027 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
10028 byte_count
, char_count
* sizeof (UniChar
));
10031 int first_byte_count
= BUF_GPT_BYTE (buf
) - start_byte
;
10033 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
10034 first_byte_count
, char_count
* sizeof (UniChar
));
10035 if (coding
.result
== CODING_FINISH_NORMAL
)
10036 encode_coding (&coding
,
10037 BUF_BYTE_ADDRESS (buf
, start_byte
+ first_byte_count
),
10038 dst
+ coding
.produced
,
10039 byte_count
- first_byte_count
,
10040 char_count
* sizeof (UniChar
) - coding
.produced
);
10043 if (coding
.result
!= CODING_FINISH_NORMAL
)
10050 mac_ax_selected_text_range (f
, range
)
10054 mac_get_selected_range (XWINDOW (f
->selected_window
), range
);
10057 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
10059 mac_ax_number_of_characters (f
)
10062 struct buffer
*b
= XBUFFER (XWINDOW (f
->selected_window
)->buffer
);
10064 return BUF_ZV (b
) - BUF_BEGV (b
);
10071 mac_restore_keyboard_input_source ()
10073 OSStatus err
= noErr
;
10074 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10076 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10077 && EQ (saved_ts_script_language_on_focus
, Qt
))
10078 slptr
= &saved_ts_language
;
10079 else if (CONSP (Vmac_ts_script_language_on_focus
)
10080 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10081 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10082 && CONSP (saved_ts_script_language_on_focus
)
10083 && EQ (XCAR (saved_ts_script_language_on_focus
),
10084 XCAR (Vmac_ts_script_language_on_focus
))
10085 && EQ (XCDR (saved_ts_script_language_on_focus
),
10086 XCDR (Vmac_ts_script_language_on_focus
)))
10088 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10089 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10095 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10096 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10097 kKeyboardInputMethodClass
);
10099 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10102 err
= SetTextServiceLanguage (slptr
);
10104 /* Seems to be needed on Mac OS X 10.2. */
10106 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10113 mac_save_keyboard_input_source ()
10116 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10118 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10120 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10122 err
= GetTextServiceLanguage (&saved_ts_language
);
10124 slptr
= &saved_ts_language
;
10126 else if (CONSP (Vmac_ts_script_language_on_focus
)
10127 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10128 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10130 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10131 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10137 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10138 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10139 kKeyboardInputMethodClass
);
10141 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10147 #if TARGET_API_MAC_CARBON
10148 /***** Code to handle C-g testing *****/
10149 extern int quit_char
;
10150 extern int make_ctrl_char
P_ ((int));
10153 mac_quit_char_key_p (modifiers
, key_code
)
10154 UInt32 modifiers
, key_code
;
10157 unsigned long some_state
= 0;
10158 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10159 int c
, emacs_modifiers
;
10161 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
10162 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
10163 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
10164 if (char_code
& ~0xff)
10167 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
10168 if (emacs_modifiers
& ctrl_modifier
)
10169 c
= make_ctrl_char (char_code
);
10171 c
|= (emacs_modifiers
10172 & (meta_modifier
| alt_modifier
10173 | hyper_modifier
| super_modifier
));
10175 return c
== quit_char
;
10179 #if TARGET_API_MAC_CARBON
10180 /* Obtains the event modifiers from the event ref and then calls
10181 mac_to_emacs_modifiers. */
10183 mac_event_to_emacs_modifiers (EventRef eventRef
)
10185 UInt32 mods
= 0, class;
10187 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
10188 sizeof (UInt32
), NULL
, &mods
);
10189 class = GetEventClass (eventRef
);
10190 if (!NILP (Vmac_emulate_three_button_mouse
) &&
10191 (class == kEventClassMouse
|| class == kEventClassCommand
))
10193 mods
&= ~(optionKey
| cmdKey
);
10195 return mac_to_emacs_modifiers (mods
);
10198 /* Given an event ref, return the code to use for the mouse button
10199 code in the emacs input_event. */
10201 mac_get_mouse_btn (EventRef ref
)
10203 EventMouseButton result
= kEventMouseButtonPrimary
;
10204 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
10205 sizeof (EventMouseButton
), NULL
, &result
);
10208 case kEventMouseButtonPrimary
:
10209 if (NILP (Vmac_emulate_three_button_mouse
))
10213 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
10214 sizeof (UInt32
), NULL
, &mods
);
10215 return mac_get_emulated_btn(mods
);
10217 case kEventMouseButtonSecondary
:
10218 return mac_wheel_button_is_mouse_2
? 2 : 1;
10219 case kEventMouseButtonTertiary
:
10220 case 4: /* 4 is the number for the mouse wheel button */
10221 return mac_wheel_button_is_mouse_2
? 1 : 2;
10227 /* Normally, ConvertEventRefToEventRecord will correctly handle all
10228 events. However the click of the mouse wheel is not converted to a
10229 mouseDown or mouseUp event. Likewise for dead key events. This
10230 calls ConvertEventRefToEventRecord, but then checks to see if it is
10231 a mouse up/down, or a dead key Carbon event that has not been
10232 converted, and if so, converts it by hand (to be picked up in the
10233 XTread_socket loop). */
10234 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
10237 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
10243 switch (GetEventClass (eventRef
))
10245 case kEventClassMouse
:
10246 switch (GetEventKind (eventRef
))
10248 case kEventMouseDown
:
10249 eventRec
->what
= mouseDown
;
10253 case kEventMouseUp
:
10254 eventRec
->what
= mouseUp
;
10263 case kEventClassKeyboard
:
10264 switch (GetEventKind (eventRef
))
10266 case kEventRawKeyDown
:
10268 goto keystroke_common
;
10269 case kEventRawKeyRepeat
:
10271 goto keystroke_common
;
10272 case kEventRawKeyUp
:
10276 unsigned char char_codes
;
10279 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
10280 typeChar
, NULL
, sizeof (char),
10281 NULL
, &char_codes
);
10283 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
10284 typeUInt32
, NULL
, sizeof (UInt32
),
10288 eventRec
->what
= action
;
10289 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
10306 /* Need where and when. */
10309 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
10310 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
10311 /* Use two step process because new event modifiers are 32-bit
10312 and old are 16-bit. Currently, only loss is NumLock & Fn. */
10313 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
10314 NULL
, sizeof (UInt32
), NULL
, &mods
);
10315 eventRec
->modifiers
= mods
;
10317 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
10327 do_get_menus (void)
10329 Handle menubar_handle
;
10332 menubar_handle
= GetNewMBar (128);
10333 if(menubar_handle
== NULL
)
10335 SetMenuBar (menubar_handle
);
10338 #if !TARGET_API_MAC_CARBON
10339 menu
= GetMenuRef (M_APPLE
);
10341 AppendResMenu (menu
, 'DRVR');
10349 do_init_managers (void)
10351 #if !TARGET_API_MAC_CARBON
10352 InitGraf (&qd
.thePort
);
10354 FlushEvents (everyEvent
, 0);
10358 InitDialogs (NULL
);
10359 #endif /* !TARGET_API_MAC_CARBON */
10362 #if !TARGET_API_MAC_CARBON
10363 /* set up some extra stack space for use by emacs */
10364 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10366 /* MaxApplZone must be called for AppleScript to execute more
10367 complicated scripts */
10370 #endif /* !TARGET_API_MAC_CARBON */
10374 do_check_ram_size (void)
10376 SInt32 physical_ram_size
, logical_ram_size
;
10378 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10379 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10380 || physical_ram_size
> (1 << VALBITS
)
10381 || logical_ram_size
> (1 << VALBITS
))
10383 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10387 #endif /* MAC_OS8 */
10390 do_window_update (WindowRef win
)
10392 struct frame
*f
= mac_window_to_frame (win
);
10396 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10398 if (win
!= tip_window
)
10400 if (f
->async_visible
== 0)
10402 /* Update events may occur when a frame gets iconified. */
10404 f
->async_visible
= 1;
10405 f
->async_iconified
= 0;
10406 SET_FRAME_GARBAGED (f
);
10412 #if TARGET_API_MAC_CARBON
10413 RgnHandle region
= NewRgn ();
10415 GetPortVisibleRegion (GetWindowPort (win
), region
);
10416 GetRegionBounds (region
, &r
);
10417 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10419 mac_prepare_for_quickdraw (f
);
10421 UpdateControls (win
, region
);
10422 DisposeRgn (region
);
10424 r
= (*win
->visRgn
)->rgnBBox
;
10425 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10426 UpdateControls (win
, win
->visRgn
);
10435 is_emacs_window (WindowRef win
)
10437 Lisp_Object tail
, frame
;
10442 FOR_EACH_FRAME (tail
, frame
)
10443 if (FRAME_MAC_P (XFRAME (frame
)))
10444 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10455 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10457 err
= ActivateTSMDocument (tsm_document_id
);
10461 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10462 && EQ (saved_ts_script_language_on_focus
, Qt
))
10463 slptr
= &saved_ts_language
;
10464 else if (CONSP (Vmac_ts_script_language_on_focus
)
10465 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10466 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10467 && CONSP (saved_ts_script_language_on_focus
)
10468 && EQ (XCAR (saved_ts_script_language_on_focus
),
10469 XCAR (Vmac_ts_script_language_on_focus
))
10470 && EQ (XCDR (saved_ts_script_language_on_focus
),
10471 XCDR (Vmac_ts_script_language_on_focus
)))
10473 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10474 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10481 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10482 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10483 kKeyboardInputMethodClass
);
10485 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10488 err
= SetTextServiceLanguage (slptr
);
10490 /* Seems to be needed on Mac OS X 10.2. */
10492 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10502 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10504 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10506 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10508 err
= GetTextServiceLanguage (&saved_ts_language
);
10510 slptr
= &saved_ts_language
;
10512 else if (CONSP (Vmac_ts_script_language_on_focus
)
10513 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10514 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10516 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10517 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10523 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10524 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10525 kKeyboardInputMethodClass
);
10527 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10531 err
= DeactivateTSMDocument (tsm_document_id
);
10537 #if !TARGET_API_MAC_CARBON
10539 do_apple_menu (SInt16 menu_item
)
10542 SInt16 da_driver_refnum
;
10544 if (menu_item
== I_ABOUT
)
10545 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10548 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10549 da_driver_refnum
= OpenDeskAcc (item_name
);
10552 #endif /* !TARGET_API_MAC_CARBON */
10554 /* Handle drags in size box. Based on code contributed by Ben
10555 Mesander and IM - Window Manager A. */
10558 do_grow_window (w
, e
)
10560 const EventRecord
*e
;
10563 int rows
, columns
, width
, height
;
10564 struct frame
*f
= mac_window_to_frame (w
);
10565 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10566 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10567 #if TARGET_API_MAC_CARBON
10573 if (size_hints
->flags
& PMinSize
)
10575 min_width
= size_hints
->min_width
;
10576 min_height
= size_hints
->min_height
;
10578 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10580 #if TARGET_API_MAC_CARBON
10581 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10583 height
= new_rect
.bottom
- new_rect
.top
;
10584 width
= new_rect
.right
- new_rect
.left
;
10586 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10587 /* see if it really changed size */
10588 if (grow_size
== 0)
10590 height
= HiWord (grow_size
);
10591 width
= LoWord (grow_size
);
10594 if (width
!= FRAME_PIXEL_WIDTH (f
)
10595 || height
!= FRAME_PIXEL_HEIGHT (f
))
10597 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10598 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10600 x_set_window_size (f
, 0, columns
, rows
);
10605 #if TARGET_API_MAC_CARBON
10607 mac_get_ideal_size (f
)
10610 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10611 WindowRef w
= FRAME_MAC_WINDOW (f
);
10613 Rect standard_rect
;
10614 int height
, width
, columns
, rows
;
10616 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10617 ideal_size
.v
= dpyinfo
->height
;
10618 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10619 /* Adjust the standard size according to character boundaries. */
10620 width
= standard_rect
.right
- standard_rect
.left
;
10621 height
= standard_rect
.bottom
- standard_rect
.top
;
10622 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10623 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10624 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10625 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10631 /* Handle clicks in zoom box. Calculation of "standard state" based
10632 on code in IM - Window Manager A and code contributed by Ben
10633 Mesander. The standard state of an Emacs window is 80-characters
10634 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10637 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10639 Rect zoom_rect
, port_rect
;
10641 struct frame
*f
= mac_window_to_frame (w
);
10642 #if TARGET_API_MAC_CARBON
10643 Point ideal_size
= mac_get_ideal_size (f
);
10645 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10646 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10647 && port_rect
.left
== zoom_rect
.left
10648 && port_rect
.top
== zoom_rect
.top
)
10649 zoom_in_or_out
= inZoomIn
;
10651 zoom_in_or_out
= inZoomOut
;
10654 mac_clear_window (f
);
10656 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10657 #else /* not TARGET_API_MAC_CARBON */
10660 int w_title_height
, rows
;
10661 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10663 GetPort (&save_port
);
10665 SetPortWindowPort (w
);
10667 /* Clear window to avoid flicker. */
10668 EraseRect (&(w
->portRect
));
10669 if (zoom_in_or_out
== inZoomOut
)
10671 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10672 LocalToGlobal (&top_left
);
10674 /* calculate height of window's title bar */
10675 w_title_height
= top_left
.v
- 1
10676 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10678 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10679 zoom_rect
= qd
.screenBits
.bounds
;
10680 zoom_rect
.top
+= w_title_height
;
10681 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10683 zoom_rect
.right
= zoom_rect
.left
10684 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10686 /* Adjust the standard size according to character boundaries. */
10687 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10689 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10691 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10695 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10697 SetPort (save_port
);
10698 #endif /* not TARGET_API_MAC_CARBON */
10700 #if !TARGET_API_MAC_CARBON
10701 /* retrieve window size and update application values */
10702 port_rect
= w
->portRect
;
10703 height
= port_rect
.bottom
- port_rect
.top
;
10704 width
= port_rect
.right
- port_rect
.left
;
10706 mac_handle_size_change (f
, width
, height
);
10707 mac_handle_origin_change (f
);
10712 mac_set_unicode_keystroke_event (code
, buf
)
10714 struct input_event
*buf
;
10716 int charset_id
, c1
, c2
;
10720 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10723 else if (code
< 0x100)
10726 charset_id
= CHARSET_8_BIT_CONTROL
;
10728 charset_id
= charset_latin_iso8859_1
;
10729 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10730 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10735 charset_id
= charset_mule_unicode_0100_24ff
,
10737 else if (code
< 0x33FF)
10738 charset_id
= charset_mule_unicode_2500_33ff
,
10740 else if (code
>= 0xE000)
10741 charset_id
= charset_mule_unicode_e000_ffff
,
10743 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10744 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10745 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10750 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10752 unsigned char char_code
;
10753 UInt32 key_code
, modifiers
;
10754 unsigned long timestamp
;
10755 struct input_event
*buf
;
10757 static SInt16 last_key_script
= -1;
10758 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10759 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10762 if (mapped_modifiers
& kEventKeyModifierFnMask
10763 && key_code
<= 0x7f
10764 && fn_keycode_to_keycode_table
[key_code
])
10765 key_code
= fn_keycode_to_keycode_table
[key_code
];
10768 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10770 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10771 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10773 if (modifiers
& kEventKeyModifierFnMask
10774 && key_code
<= 0x7f
10775 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10776 modifiers
&= ~kEventKeyModifierFnMask
;
10779 else if (mapped_modifiers
)
10781 /* translate the keycode back to determine the original key */
10783 UCKeyboardLayout
*uchr_ptr
= NULL
;
10784 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10786 KeyboardLayoutRef layout
;
10788 err
= KLGetCurrentKeyboardLayout (&layout
);
10790 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10791 (const void **) &uchr_ptr
);
10793 static SInt16 last_key_layout_id
= 0;
10794 static Handle uchr_handle
= (Handle
)-1;
10795 SInt16 current_key_layout_id
=
10796 GetScriptVariable (current_key_script
, smScriptKeys
);
10798 if (uchr_handle
== (Handle
)-1
10799 || last_key_layout_id
!= current_key_layout_id
)
10801 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10802 last_key_layout_id
= current_key_layout_id
;
10805 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10811 UInt16 key_action
= action
- keyDown
;
10812 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10813 UInt32 keyboard_type
= LMGetKbdType ();
10814 SInt32 dead_key_state
= 0;
10816 UniCharCount actual_length
;
10818 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10819 modifier_key_state
, keyboard_type
,
10820 kUCKeyTranslateNoDeadKeysMask
,
10822 1, &actual_length
, &code
);
10823 if (status
== noErr
&& actual_length
== 1)
10824 mac_set_unicode_keystroke_event (code
, buf
);
10826 #endif /* MAC_OSX */
10828 if (buf
->kind
== NO_EVENT
)
10830 /* This code comes from Keyboard Resource, Appendix C of IM
10831 - Text. This is necessary since shift is ignored in KCHR
10832 table translation when option or command is pressed. It
10833 also does not translate correctly control-shift chars
10834 like C-% so mask off shift here also. */
10835 /* Mask off modifier keys that are mapped to some Emacs
10837 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10838 /* set high byte of keycode to modifier high byte*/
10839 int new_key_code
= key_code
| new_modifiers
;
10840 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10841 unsigned long some_state
= 0;
10842 UInt32 new_char_code
;
10844 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10845 if (new_char_code
== 0)
10846 /* Seems like a dead key. Append up-stroke. */
10847 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10851 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10852 buf
->code
= new_char_code
& 0xff;
10857 if (buf
->kind
== NO_EVENT
)
10859 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10860 buf
->code
= char_code
;
10863 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10864 buf
->modifiers
|= (extra_keyboard_modifiers
10865 & (meta_modifier
| alt_modifier
10866 | hyper_modifier
| super_modifier
));
10868 #if TARGET_API_MAC_CARBON
10869 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10870 && buf
->code
>= 0x80 && buf
->modifiers
)
10873 TextEncoding encoding
= kTextEncodingMacRoman
;
10874 TextToUnicodeInfo ttu_info
;
10876 UpgradeScriptInfoToTextEncoding (current_key_script
,
10877 kTextLanguageDontCare
,
10878 kTextRegionDontCare
,
10880 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10885 ByteCount unicode_len
;
10888 pstr
[1] = buf
->code
;
10889 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10891 &unicode_len
, &code
);
10892 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10893 mac_set_unicode_keystroke_event (code
, buf
);
10894 DisposeTextToUnicodeInfo (&ttu_info
);
10899 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10900 && buf
->code
>= 0x80
10901 && last_key_script
!= current_key_script
)
10903 struct input_event event
;
10905 EVENT_INIT (event
);
10906 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10908 event
.code
= current_key_script
;
10909 event
.timestamp
= timestamp
;
10910 kbd_buffer_store_event (&event
);
10911 last_key_script
= current_key_script
;
10916 mac_store_apple_event (class, id
, desc
)
10917 Lisp_Object
class, id
;
10918 const AEDesc
*desc
;
10920 struct input_event buf
;
10924 buf
.kind
= MAC_APPLE_EVENT
;
10927 XSETFRAME (buf
.frame_or_window
,
10928 mac_focus_frame (&one_mac_display_info
));
10929 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10930 is safe to use them during read_socket_hook. */
10931 buf
.arg
= mac_aedesc_to_lisp (desc
);
10932 kbd_buffer_store_event (&buf
);
10935 #if TARGET_API_MAC_CARBON
10937 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10938 event
, num_params
, names
, types
)
10939 AEEventClass
class;
10941 Lisp_Object class_key
, id_key
;
10944 const EventParamName
*names
;
10945 const EventParamType
*types
;
10947 OSStatus err
= eventNotHandledErr
;
10948 Lisp_Object binding
;
10950 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10951 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10953 if (INTEGERP (binding
))
10954 err
= XINT (binding
);
10957 AppleEvent apple_event
;
10958 err
= create_apple_event_from_event_ref (event
, num_params
,
10963 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10964 AEDisposeDesc (&apple_event
);
10965 mac_wakeup_from_rne ();
10974 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10978 const AEDesc
*desc
;
10980 struct input_event buf
;
10984 buf
.kind
= DRAG_N_DROP_EVENT
;
10985 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10986 buf
.timestamp
= TickCount () * (1000 / 60);
10987 XSETINT (buf
.x
, mouse_pos
.h
);
10988 XSETINT (buf
.y
, mouse_pos
.v
);
10989 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10990 buf
.arg
= mac_aedesc_to_lisp (desc
);
10991 kbd_buffer_store_event (&buf
);
10996 mac_store_service_event (event
)
11000 Lisp_Object id_key
;
11002 const EventParamName
*names
;
11003 const EventParamType
*types
;
11004 static const EventParamName names_pfm
[] =
11005 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
11006 static const EventParamType types_pfm
[] =
11007 {typeCFStringRef
, typeCFStringRef
};
11009 switch (GetEventKind (event
))
11011 case kEventServicePaste
:
11018 case kEventServicePerform
:
11020 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
11029 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
11035 #endif /* MAC_OSX */
11037 static pascal OSStatus
11038 mac_handle_window_event (next_handler
, event
, data
)
11039 EventHandlerCallRef next_handler
;
11044 OSStatus err
, result
= eventNotHandledErr
;
11047 XSizeHints
*size_hints
;
11049 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
11050 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11052 return eventNotHandledErr
;
11054 f
= mac_window_to_frame (wp
);
11055 switch (GetEventKind (event
))
11057 /* -- window refresh events -- */
11059 case kEventWindowUpdate
:
11060 result
= CallNextEventHandler (next_handler
, event
);
11061 if (result
!= eventNotHandledErr
)
11064 do_window_update (wp
);
11068 /* -- window state change events -- */
11070 case kEventWindowShowing
:
11071 size_hints
= FRAME_SIZE_HINTS (f
);
11072 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
11074 struct frame
*sf
= SELECTED_FRAME ();
11076 if (!(FRAME_MAC_P (sf
) && sf
->async_visible
))
11077 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
11080 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
11081 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11082 kWindowCascadeStartAtParentWindowScreen
11084 kWindowCascadeOnParentWindowScreen
11087 #if USE_MAC_TOOLBAR
11088 /* This is a workaround. RepositionWindow fails to put
11089 a window at the cascading position when its parent
11090 window has a Carbon HIToolbar. */
11091 if ((f
->left_pos
== sf
->left_pos
11092 && f
->top_pos
== sf
->top_pos
)
11093 || (f
->left_pos
== sf
->left_pos
+ 10 * 2
11094 && f
->top_pos
== sf
->top_pos
+ 32 * 2))
11095 MoveWindowStructure (wp
, sf
->left_pos
+ 10, sf
->top_pos
+ 32);
11102 case kEventWindowHiding
:
11103 /* Before unmapping the window, update the WM_SIZE_HINTS
11104 property to claim that the current position of the window is
11105 user-specified, rather than program-specified, so that when
11106 the window is mapped again, it will be placed at the same
11107 location, without forcing the user to position it by hand
11108 again (they have already done that once for this window.) */
11109 x_wm_set_size_hint (f
, (long) 0, 1);
11113 case kEventWindowShown
:
11114 case kEventWindowHidden
:
11115 case kEventWindowCollapsed
:
11116 case kEventWindowExpanded
:
11117 mac_handle_visibility_change (f
);
11121 case kEventWindowBoundsChanging
:
11122 result
= CallNextEventHandler (next_handler
, event
);
11123 if (result
!= eventNotHandledErr
)
11126 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
11127 NULL
, sizeof (UInt32
), NULL
, &attributes
);
11131 size_hints
= FRAME_SIZE_HINTS (f
);
11132 if ((attributes
& kWindowBoundsChangeUserResize
)
11133 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
11134 == (PResizeInc
| PBaseSize
| PMinSize
)))
11139 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
11140 typeQDRectangle
, NULL
, sizeof (Rect
),
11145 width
= bounds
.right
- bounds
.left
;
11146 height
= bounds
.bottom
- bounds
.top
;
11148 if (width
< size_hints
->min_width
)
11149 width
= size_hints
->min_width
;
11151 width
= size_hints
->base_width
11152 + (int) ((width
- size_hints
->base_width
)
11153 / (float) size_hints
->width_inc
+ .5)
11154 * size_hints
->width_inc
;
11156 if (height
< size_hints
->min_height
)
11157 height
= size_hints
->min_height
;
11159 height
= size_hints
->base_height
11160 + (int) ((height
- size_hints
->base_height
)
11161 / (float) size_hints
->height_inc
+ .5)
11162 * size_hints
->height_inc
;
11164 bounds
.right
= bounds
.left
+ width
;
11165 bounds
.bottom
= bounds
.top
+ height
;
11166 SetEventParameter (event
, kEventParamCurrentBounds
,
11167 typeQDRectangle
, sizeof (Rect
), &bounds
);
11172 case kEventWindowBoundsChanged
:
11173 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
11174 NULL
, sizeof (UInt32
), NULL
, &attributes
);
11178 if (attributes
& kWindowBoundsChangeSizeChanged
)
11182 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
11183 typeQDRectangle
, NULL
, sizeof (Rect
),
11189 width
= bounds
.right
- bounds
.left
;
11190 height
= bounds
.bottom
- bounds
.top
;
11191 mac_handle_size_change (f
, width
, height
);
11192 mac_wakeup_from_rne ();
11196 if (attributes
& kWindowBoundsChangeOriginChanged
)
11197 mac_handle_origin_change (f
);
11202 /* -- window action events -- */
11204 case kEventWindowClose
:
11206 struct input_event buf
;
11209 buf
.kind
= DELETE_WINDOW_EVENT
;
11210 XSETFRAME (buf
.frame_or_window
, f
);
11212 kbd_buffer_store_event (&buf
);
11217 case kEventWindowGetIdealSize
:
11218 result
= CallNextEventHandler (next_handler
, event
);
11219 if (result
!= eventNotHandledErr
)
11223 Point ideal_size
= mac_get_ideal_size (f
);
11225 err
= SetEventParameter (event
, kEventParamDimensions
,
11226 typeQDPoint
, sizeof (Point
), &ideal_size
);
11233 case kEventWindowToolbarSwitchMode
:
11235 static const EventParamName names
[] = {kEventParamDirectObject
,
11236 kEventParamWindowMouseLocation
,
11237 kEventParamKeyModifiers
,
11238 kEventParamMouseButton
,
11239 kEventParamClickCount
,
11240 kEventParamMouseChord
};
11241 static const EventParamType types
[] = {typeWindowRef
,
11247 int num_params
= sizeof (names
) / sizeof (names
[0]);
11249 err
= mac_store_event_ref_as_apple_event (0, 0,
11251 Qtoolbar_switch_mode
,
11261 /* -- window focus events -- */
11263 case kEventWindowFocusAcquired
:
11264 err
= mac_tsm_resume ();
11269 case kEventWindowFocusRelinquish
:
11270 err
= mac_tsm_suspend ();
11283 static pascal OSStatus
11284 mac_handle_application_event (next_handler
, event
, data
)
11285 EventHandlerCallRef next_handler
;
11289 OSStatus err
, result
= eventNotHandledErr
;
11291 switch (GetEventKind (event
))
11294 case kEventAppActivated
:
11295 err
= mac_tsm_resume ();
11298 case kEventAppDeactivated
:
11299 err
= mac_tsm_suspend ();
11313 static pascal OSStatus
11314 mac_handle_keyboard_event (next_handler
, event
, data
)
11315 EventHandlerCallRef next_handler
;
11319 OSStatus err
, result
= eventNotHandledErr
;
11320 UInt32 event_kind
, key_code
, modifiers
;
11321 unsigned char char_code
;
11323 event_kind
= GetEventKind (event
);
11324 switch (event_kind
)
11326 case kEventRawKeyDown
:
11327 case kEventRawKeyRepeat
:
11328 case kEventRawKeyUp
:
11329 /* When using Carbon Events, we need to pass raw keyboard events
11330 to the TSM ourselves. If TSM handles it, it will pass back
11331 noErr, otherwise it will pass back "eventNotHandledErr" and
11332 we can process it normally. */
11333 result
= CallNextEventHandler (next_handler
, event
);
11334 if (result
!= eventNotHandledErr
)
11337 if (read_socket_inev
== NULL
)
11341 if (read_socket_inev
->kind
!= NO_EVENT
)
11348 if (event_kind
== kEventRawKeyUp
)
11351 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11353 sizeof (char), NULL
, &char_code
);
11357 err
= GetEventParameter (event
, kEventParamKeyCode
,
11359 sizeof (UInt32
), NULL
, &key_code
);
11363 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
11365 sizeof (UInt32
), NULL
, &modifiers
);
11369 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11370 char_code
, key_code
, modifiers
,
11372 (GetEventTime (event
) / kEventDurationMillisecond
)),
11384 static pascal OSStatus
11385 mac_handle_command_event (next_handler
, event
, data
)
11386 EventHandlerCallRef next_handler
;
11390 OSStatus err
, result
= eventNotHandledErr
;
11392 static const EventParamName names
[] =
11393 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11394 static const EventParamType types
[] =
11395 {typeHICommand
, typeUInt32
};
11396 int num_params
= sizeof (names
) / sizeof (names
[0]);
11398 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11399 NULL
, sizeof (HICommand
), NULL
, &command
);
11401 return eventNotHandledErr
;
11403 switch (GetEventKind (event
))
11405 case kEventCommandProcess
:
11406 result
= CallNextEventHandler (next_handler
, event
);
11407 if (result
!= eventNotHandledErr
)
11410 err
= GetEventParameter (event
, kEventParamDirectObject
,
11411 typeHICommand
, NULL
,
11412 sizeof (HICommand
), NULL
, &command
);
11414 if (err
!= noErr
|| command
.commandID
== 0)
11417 /* A HI command event is mapped to an Apple event whose event
11418 class symbol is `hi-command' and event ID is its command
11420 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11435 static pascal OSStatus
11436 mac_handle_mouse_event (next_handler
, event
, data
)
11437 EventHandlerCallRef next_handler
;
11441 OSStatus err
, result
= eventNotHandledErr
;
11443 switch (GetEventKind (event
))
11445 case kEventMouseWheelMoved
:
11449 EventMouseWheelAxis axis
;
11453 result
= CallNextEventHandler (next_handler
, event
);
11454 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11457 f
= mac_focus_frame (&one_mac_display_info
);
11459 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11460 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11462 || wp
!= FRAME_MAC_WINDOW (f
))
11465 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11466 typeMouseWheelAxis
, NULL
,
11467 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11468 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11471 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11472 typeQDPoint
, NULL
, sizeof (Point
),
11477 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11478 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11479 if (point
.h
< 0 || point
.v
< 0
11480 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11481 f
->tool_bar_window
))
11484 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11485 typeSInt32
, NULL
, sizeof (SInt32
),
11490 read_socket_inev
->kind
= WHEEL_EVENT
;
11491 read_socket_inev
->code
= 0;
11492 read_socket_inev
->modifiers
=
11493 (mac_event_to_emacs_modifiers (event
)
11494 | ((delta
< 0) ? down_modifier
: up_modifier
));
11495 XSETINT (read_socket_inev
->x
, point
.h
);
11496 XSETINT (read_socket_inev
->y
, point
.v
);
11497 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11511 static pascal OSStatus
11512 mac_handle_text_input_event (next_handler
, event
, data
)
11513 EventHandlerCallRef next_handler
;
11517 OSStatus err
, result
;
11518 Lisp_Object id_key
= Qnil
;
11520 const EventParamName
*names
;
11521 const EventParamType
*types
;
11522 static UInt32 seqno_uaia
= 0;
11523 static const EventParamName names_uaia
[] =
11524 {kEventParamTextInputSendComponentInstance
,
11525 kEventParamTextInputSendRefCon
,
11526 kEventParamTextInputSendSLRec
,
11527 kEventParamTextInputSendFixLen
,
11528 kEventParamTextInputSendText
,
11529 kEventParamTextInputSendUpdateRng
,
11530 kEventParamTextInputSendHiliteRng
,
11531 kEventParamTextInputSendClauseRng
,
11532 kEventParamTextInputSendPinRng
,
11533 kEventParamTextInputSendTextServiceEncoding
,
11534 kEventParamTextInputSendTextServiceMacEncoding
,
11535 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11536 static const EventParamType types_uaia
[] =
11537 {typeComponentInstance
,
11539 typeIntlWritingCode
,
11546 typeTextRangeArray
,
11547 typeTextRangeArray
,
11553 static const EventParamName names_ufke
[] =
11554 {kEventParamTextInputSendComponentInstance
,
11555 kEventParamTextInputSendRefCon
,
11556 kEventParamTextInputSendSLRec
,
11557 kEventParamTextInputSendText
};
11558 static const EventParamType types_ufke
[] =
11559 {typeComponentInstance
,
11561 typeIntlWritingCode
,
11564 result
= CallNextEventHandler (next_handler
, event
);
11565 if (result
!= eventNotHandledErr
)
11568 switch (GetEventKind (event
))
11570 case kEventTextInputUpdateActiveInputArea
:
11571 id_key
= Qupdate_active_input_area
;
11572 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11573 names
= names_uaia
;
11574 types
= types_uaia
;
11575 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11576 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11581 case kEventTextInputUnicodeForKeyEvent
:
11583 EventRef kbd_event
;
11584 UInt32 actual_size
, modifiers
;
11586 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11587 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11590 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11592 sizeof (UInt32
), NULL
, &modifiers
);
11593 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11594 /* There're mapped modifier keys. Process it in
11598 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11599 typeUnicodeText
, NULL
, 0, &actual_size
,
11601 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11605 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11606 typeUnicodeText
, NULL
,
11607 sizeof (UniChar
), NULL
, &code
);
11608 if (err
== noErr
&& code
< 0x80)
11610 /* ASCII character. Process it in do_keystroke. */
11611 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11615 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11616 typeUInt32
, NULL
, sizeof (UInt32
),
11618 if (!(err
== noErr
&& key_code
<= 0x7f
11619 && keycode_to_xkeysym_table
[key_code
]))
11622 mac_focus_frame (&one_mac_display_info
);
11624 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11625 read_socket_inev
->code
= code
;
11626 read_socket_inev
->modifiers
=
11627 mac_to_emacs_modifiers (modifiers
);
11628 read_socket_inev
->modifiers
|=
11629 (extra_keyboard_modifiers
11630 & (meta_modifier
| alt_modifier
11631 | hyper_modifier
| super_modifier
));
11632 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11640 /* Non-ASCII keystrokes without mapped modifiers are
11641 processed at the Lisp level. */
11642 id_key
= Qunicode_for_key_event
;
11643 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11644 names
= names_ufke
;
11645 types
= types_ufke
;
11651 case kEventTextInputOffsetToPos
:
11657 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11660 /* Strictly speaking, this is not always correct because
11661 previous events may change some states about display. */
11662 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11664 /* Active input area is displayed around the current point. */
11665 f
= SELECTED_FRAME ();
11666 w
= XWINDOW (f
->selected_window
);
11668 else if (WINDOWP (echo_area_window
))
11670 /* Active input area is displayed in the echo area. */
11671 w
= XWINDOW (echo_area_window
);
11672 f
= WINDOW_XFRAME (w
);
11677 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11678 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11679 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11680 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11681 + FONT_BASE (FRAME_FONT (f
))
11682 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11683 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11684 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11694 if (!NILP (id_key
))
11695 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11701 #endif /* TARGET_API_MAC_CARBON */
11705 install_window_handler (window
)
11708 OSStatus err
= noErr
;
11710 #if TARGET_API_MAC_CARBON
11713 static const EventTypeSpec specs
[] =
11715 /* -- window refresh events -- */
11716 {kEventClassWindow
, kEventWindowUpdate
},
11717 /* -- window state change events -- */
11718 {kEventClassWindow
, kEventWindowShowing
},
11719 {kEventClassWindow
, kEventWindowHiding
},
11720 {kEventClassWindow
, kEventWindowShown
},
11721 {kEventClassWindow
, kEventWindowHidden
},
11722 {kEventClassWindow
, kEventWindowCollapsed
},
11723 {kEventClassWindow
, kEventWindowExpanded
},
11724 {kEventClassWindow
, kEventWindowBoundsChanging
},
11725 {kEventClassWindow
, kEventWindowBoundsChanged
},
11726 /* -- window action events -- */
11727 {kEventClassWindow
, kEventWindowClose
},
11728 {kEventClassWindow
, kEventWindowGetIdealSize
},
11730 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11733 /* -- window focus events -- */
11734 {kEventClassWindow
, kEventWindowFocusAcquired
},
11735 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11738 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11740 if (handle_window_eventUPP
== NULL
)
11741 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11743 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11744 GetEventTypeCount (specs
),
11745 specs
, NULL
, NULL
);
11750 err
= install_drag_handler (window
);
11756 remove_window_handler (window
)
11759 remove_drag_handler (window
);
11762 #if TARGET_API_MAC_CARBON
11764 install_application_handler ()
11766 OSStatus err
= noErr
;
11770 static const EventTypeSpec specs
[] = {
11772 {kEventClassApplication
, kEventAppActivated
},
11773 {kEventClassApplication
, kEventAppDeactivated
},
11777 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11778 (mac_handle_application_event
),
11779 GetEventTypeCount (specs
),
11780 specs
, NULL
, NULL
);
11785 static const EventTypeSpec specs
[] =
11786 {{kEventClassKeyboard
, kEventRawKeyDown
},
11787 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11788 {kEventClassKeyboard
, kEventRawKeyUp
}};
11790 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11791 (mac_handle_keyboard_event
),
11792 GetEventTypeCount (specs
),
11793 specs
, NULL
, NULL
);
11798 static const EventTypeSpec specs
[] =
11799 {{kEventClassCommand
, kEventCommandProcess
}};
11801 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11802 (mac_handle_command_event
),
11803 GetEventTypeCount (specs
),
11804 specs
, NULL
, NULL
);
11809 static const EventTypeSpec specs
[] =
11810 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11812 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11813 (mac_handle_mouse_event
),
11814 GetEventTypeCount (specs
),
11815 specs
, NULL
, NULL
);
11821 static const EventTypeSpec spec
[] =
11822 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11823 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11824 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11826 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11827 (mac_handle_text_input_event
),
11828 GetEventTypeCount (spec
),
11834 err
= install_menu_target_item_handler ();
11838 err
= install_service_handler ();
11846 mac_handle_dm_notification (event
)
11849 mac_screen_config_changed
= 1;
11852 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11854 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11855 CGDirectDisplayID display
;
11856 CGDisplayChangeSummaryFlags flags
;
11859 mac_screen_config_changed
= 1;
11864 init_dm_notification_handler ()
11868 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11869 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11870 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11873 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11876 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11877 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11879 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11880 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11882 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11883 ProcessSerialNumber psn
;
11885 if (handle_dm_notificationUPP
== NULL
)
11886 handle_dm_notificationUPP
=
11887 NewDMNotificationUPP (mac_handle_dm_notification
);
11889 err
= GetCurrentProcess (&psn
);
11891 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11899 mac_get_screen_info (dpyinfo
)
11900 struct mac_display_info
*dpyinfo
;
11903 /* HasDepth returns true if it is possible to have a 32 bit display,
11904 but this may not be what is actually used. Mac OSX can do better. */
11905 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11906 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11909 CGDisplayCount ndisps
;
11910 CGDirectDisplayID
*displays
;
11912 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11915 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11916 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11920 CGRect bounds
= CGRectZero
;
11922 while (ndisps
-- > 0)
11923 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11924 dpyinfo
->height
= CGRectGetHeight (bounds
);
11925 dpyinfo
->width
= CGRectGetWidth (bounds
);
11929 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11930 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11933 #else /* !MAC_OSX */
11935 GDHandle gdh
= GetMainDevice ();
11936 Rect rect
= (**gdh
).gdRect
;
11938 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11939 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11940 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11943 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11944 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11945 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11947 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11948 dpyinfo
->width
= rect
.right
- rect
.left
;
11950 #endif /* !MAC_OSX */
11956 profiler_exit_proc ()
11958 ProfilerDump ("\pEmacs.prof");
11963 /* These few functions implement Emacs as a normal Mac application
11964 (almost): set up the heap and the Toolbox, handle necessary system
11965 events plus a few simple menu events. They also set up Emacs's
11966 access to functions defined in the rest of this file. Emacs uses
11967 function hooks to perform all its terminal I/O. A complete list of
11968 these functions appear in termhooks.h. For what they do, read the
11969 comments there and see also w32term.c and xterm.c. What's
11970 noticeably missing here is the event loop, which is normally
11971 present in most Mac application. After performing the necessary
11972 Mac initializations, main passes off control to emacs_main
11973 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11974 (defined further below) to read input. This is where
11975 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11982 #if __profile__ /* is the profiler on? */
11983 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11988 /* set creator and type for files created by MSL */
11989 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11993 do_init_managers ();
11997 #ifndef USE_LSB_TAG
11998 do_check_ram_size ();
12001 init_emacs_passwd_dir ();
12005 init_coercion_handler ();
12007 initialize_applescript ();
12009 init_apple_event_handler ();
12011 init_dm_notification_handler ();
12017 /* set up argv array from STR# resource */
12018 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
12022 /* free up AppleScript resources on exit */
12023 atexit (terminate_applescript
);
12025 #if __profile__ /* is the profiler on? */
12026 atexit (profiler_exit_proc
);
12029 /* 3rd param "envp" never used in emacs_main */
12030 (void) emacs_main (argc
, argv
, 0);
12033 /* Never reached - real exit in Fkill_emacs */
12038 #if !TARGET_API_MAC_CARBON
12039 static RgnHandle mouse_region
= NULL
;
12042 mac_wait_next_event (er
, sleep_time
, dequeue
)
12047 static EventRecord er_buf
= {nullEvent
};
12048 UInt32 target_tick
, current_tick
;
12049 EventMask event_mask
;
12051 if (mouse_region
== NULL
)
12052 mouse_region
= NewRgn ();
12054 event_mask
= everyEvent
;
12055 if (!mac_ready_for_apple_events
)
12056 event_mask
-= highLevelEventMask
;
12058 current_tick
= TickCount ();
12059 target_tick
= current_tick
+ sleep_time
;
12061 if (er_buf
.what
== nullEvent
)
12062 while (!WaitNextEvent (event_mask
, &er_buf
,
12063 target_tick
- current_tick
, mouse_region
))
12065 current_tick
= TickCount ();
12066 if (target_tick
<= current_tick
)
12072 er_buf
.what
= nullEvent
;
12075 #endif /* not TARGET_API_MAC_CARBON */
12077 #if TARGET_API_MAC_CARBON
12079 mac_post_mouse_moved_event ()
12081 EventRef event
= NULL
;
12084 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
12085 kEventAttributeNone
, &event
);
12090 GetGlobalMouse (&mouse_pos
);
12091 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
12092 sizeof (Point
), &mouse_pos
);
12096 UInt32 modifiers
= GetCurrentKeyModifiers ();
12098 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
12099 sizeof (UInt32
), &modifiers
);
12102 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
12103 kEventPriorityStandard
);
12105 ReleaseEvent (event
);
12111 /* Emacs calls this whenever it wants to read an input event from the
12114 XTread_socket (sd
, expected
, hold_quit
)
12116 struct input_event
*hold_quit
;
12118 struct input_event inev
;
12120 #if TARGET_API_MAC_CARBON
12122 EventTargetRef toolbox_dispatcher
;
12125 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
12127 if (interrupt_input_blocked
)
12129 interrupt_input_pending
= 1;
12133 interrupt_input_pending
= 0;
12136 /* So people can tell when we have read the available input. */
12137 input_signal_count
++;
12141 #if TARGET_API_MAC_CARBON
12142 toolbox_dispatcher
= GetEventDispatcherTarget ();
12146 mac_prepare_for_quickdraw (NULL
),
12148 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
12149 kEventRemoveFromQueue
, &eventRef
))
12150 #else /* !TARGET_API_MAC_CARBON */
12151 while (mac_wait_next_event (&er
, 0, true))
12152 #endif /* !TARGET_API_MAC_CARBON */
12156 unsigned long timestamp
;
12159 inev
.kind
= NO_EVENT
;
12162 #if TARGET_API_MAC_CARBON
12163 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
12165 if (!mac_convert_event_ref (eventRef
, &er
))
12167 #else /* !TARGET_API_MAC_CARBON */
12168 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
12169 #endif /* !TARGET_API_MAC_CARBON */
12176 WindowRef window_ptr
;
12177 ControlPartCode part_code
;
12178 int tool_bar_p
= 0;
12180 #if TARGET_API_MAC_CARBON
12183 /* This is needed to send mouse events like aqua window
12184 buttons to the correct handler. */
12185 read_socket_inev
= &inev
;
12186 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12187 read_socket_inev
= NULL
;
12188 if (err
!= eventNotHandledErr
)
12191 last_mouse_glyph_frame
= 0;
12193 if (dpyinfo
->grabbed
&& last_mouse_frame
12194 && FRAME_LIVE_P (last_mouse_frame
))
12196 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
12197 part_code
= inContent
;
12201 part_code
= FindWindow (er
.where
, &window_ptr
);
12202 if (tip_window
&& window_ptr
== tip_window
)
12204 HideWindow (tip_window
);
12205 part_code
= FindWindow (er
.where
, &window_ptr
);
12209 if (er
.what
!= mouseDown
&&
12210 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
12216 f
= mac_focus_frame (dpyinfo
);
12217 saved_menu_event_location
= er
.where
;
12218 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
12219 XSETFRAME (inev
.frame_or_window
, f
);
12224 #if TARGET_API_MAC_CARBON
12225 FrontNonFloatingWindow ()
12230 || (mac_window_to_frame (window_ptr
)
12231 != dpyinfo
->x_focus_frame
))
12232 SelectWindow (window_ptr
);
12235 ControlPartCode control_part_code
;
12239 ControlKind control_kind
;
12242 f
= mac_window_to_frame (window_ptr
);
12243 /* convert to local coordinates of new window */
12244 mouse_loc
.h
= (er
.where
.h
12246 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12247 mouse_loc
.v
= (er
.where
.v
12249 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12250 #if TARGET_API_MAC_CARBON
12251 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
12252 &control_part_code
);
12255 GetControlKind (ch
, &control_kind
);
12258 control_part_code
= FindControl (mouse_loc
, window_ptr
,
12262 #if TARGET_API_MAC_CARBON
12263 inev
.code
= mac_get_mouse_btn (eventRef
);
12264 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12266 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
12267 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12269 XSETINT (inev
.x
, mouse_loc
.h
);
12270 XSETINT (inev
.y
, mouse_loc
.v
);
12272 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
12274 #ifndef USE_TOOLKIT_SCROLL_BARS
12275 /* control_part_code becomes kControlNoPart if
12276 a progress indicator is clicked. */
12277 && control_part_code
!= kControlNoPart
12278 #else /* USE_TOOLKIT_SCROLL_BARS */
12280 && control_kind
.kind
== kControlKindScrollBar
12281 #endif /* MAC_OSX */
12282 #endif /* USE_TOOLKIT_SCROLL_BARS */
12285 struct scroll_bar
*bar
;
12287 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12289 bar
= tracked_scroll_bar
;
12290 #ifndef USE_TOOLKIT_SCROLL_BARS
12291 control_part_code
= kControlIndicatorPart
;
12295 bar
= (struct scroll_bar
*) GetControlReference (ch
);
12296 #ifdef USE_TOOLKIT_SCROLL_BARS
12297 /* Make the "Ctrl-Mouse-2 splits window" work
12298 for toolkit scroll bars. */
12299 if (inev
.modifiers
& ctrl_modifier
)
12300 x_scroll_bar_handle_click (bar
, control_part_code
,
12302 else if (er
.what
== mouseDown
)
12303 x_scroll_bar_handle_press (bar
, control_part_code
,
12306 x_scroll_bar_handle_release (bar
, &inev
);
12307 #else /* not USE_TOOLKIT_SCROLL_BARS */
12308 x_scroll_bar_handle_click (bar
, control_part_code
,
12310 if (er
.what
== mouseDown
12311 && control_part_code
== kControlIndicatorPart
)
12312 tracked_scroll_bar
= bar
;
12314 tracked_scroll_bar
= NULL
;
12315 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12319 Lisp_Object window
;
12320 int x
= mouse_loc
.h
;
12321 int y
= mouse_loc
.v
;
12323 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
12324 if (EQ (window
, f
->tool_bar_window
))
12326 if (er
.what
== mouseDown
)
12327 handle_tool_bar_click (f
, x
, y
, 1, 0);
12329 handle_tool_bar_click (f
, x
, y
, 0,
12335 XSETFRAME (inev
.frame_or_window
, f
);
12336 inev
.kind
= MOUSE_CLICK_EVENT
;
12340 if (er
.what
== mouseDown
)
12342 dpyinfo
->grabbed
|= (1 << inev
.code
);
12343 last_mouse_frame
= f
;
12346 last_tool_bar_item
= -1;
12350 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
12351 /* If a button is released though it was not
12352 previously pressed, that would be because
12353 of multi-button emulation. */
12354 dpyinfo
->grabbed
= 0;
12356 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
12359 /* Ignore any mouse motion that happened before
12360 this event; any subsequent mouse-movement Emacs
12361 events should reflect only motion after the
12364 f
->mouse_moved
= 0;
12366 #ifdef USE_TOOLKIT_SCROLL_BARS
12367 if (inev
.kind
== MOUSE_CLICK_EVENT
12368 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12369 && (inev
.modifiers
& ctrl_modifier
)))
12374 inev
.modifiers
|= down_modifier
;
12377 inev
.modifiers
|= up_modifier
;
12384 #if TARGET_API_MAC_CARBON
12386 if (IsWindowPathSelectClick (window_ptr
, &er
))
12388 WindowPathSelect (window_ptr
, NULL
, NULL
);
12391 if (part_code
== inProxyIcon
12392 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12393 != errUserWantsToDragWindow
))
12395 DragWindow (window_ptr
, er
.where
, NULL
);
12396 #else /* not TARGET_API_MAC_CARBON */
12397 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12398 /* Update the frame parameters. */
12400 struct frame
*f
= mac_window_to_frame (window_ptr
);
12402 if (f
&& !f
->async_iconified
)
12403 mac_handle_origin_change (f
);
12405 #endif /* not TARGET_API_MAC_CARBON */
12409 if (TrackGoAway (window_ptr
, er
.where
))
12411 inev
.kind
= DELETE_WINDOW_EVENT
;
12412 XSETFRAME (inev
.frame_or_window
,
12413 mac_window_to_frame (window_ptr
));
12417 /* window resize handling added --ben */
12419 do_grow_window (window_ptr
, &er
);
12422 /* window zoom handling added --ben */
12425 if (TrackBox (window_ptr
, er
.where
, part_code
))
12426 do_zoom_window (window_ptr
, part_code
);
12429 #if USE_MAC_TOOLBAR
12435 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12437 /* This doesn't work on Mac OS X 10.2. */
12439 HIViewClick (ch
, eventRef
);
12442 #endif /* USE_MAC_TOOLBAR */
12450 #if !TARGET_API_MAC_CARBON
12452 do_window_update ((WindowRef
) er
.message
);
12457 switch ((er
.message
>> 24) & 0x000000FF)
12459 case mouseMovedMessage
:
12460 #if !TARGET_API_MAC_CARBON
12461 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12462 er
.where
.h
+ 1, er
.where
.v
+ 1);
12464 previous_help_echo_string
= help_echo_string
;
12465 help_echo_string
= Qnil
;
12467 if (dpyinfo
->grabbed
&& last_mouse_frame
12468 && FRAME_LIVE_P (last_mouse_frame
))
12469 f
= last_mouse_frame
;
12471 f
= dpyinfo
->x_focus_frame
;
12473 if (dpyinfo
->mouse_face_hidden
)
12475 dpyinfo
->mouse_face_hidden
= 0;
12476 clear_mouse_face (dpyinfo
);
12481 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12484 mouse_pos
.h
= (er
.where
.h
12486 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12487 mouse_pos
.v
= (er
.where
.v
12489 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12490 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12491 #ifdef USE_TOOLKIT_SCROLL_BARS
12492 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12494 #else /* not USE_TOOLKIT_SCROLL_BARS */
12495 x_scroll_bar_note_movement (tracked_scroll_bar
,
12497 - XINT (tracked_scroll_bar
->top
),
12498 er
.when
* (1000 / 60));
12499 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12502 /* Generate SELECT_WINDOW_EVENTs when needed. */
12503 if (!NILP (Vmouse_autoselect_window
))
12505 Lisp_Object window
;
12507 window
= window_from_coordinates (f
,
12512 /* Window will be selected only when it is
12513 not selected now and last mouse movement
12514 event was not in it. Minibuffer window
12515 will be selected only when it is active. */
12516 if (WINDOWP (window
)
12517 && !EQ (window
, last_window
)
12518 && !EQ (window
, selected_window
)
12519 /* For click-to-focus window managers
12520 create event iff we don't leave the
12522 && (focus_follows_mouse
12523 || (EQ (XWINDOW (window
)->frame
,
12524 XWINDOW (selected_window
)->frame
))))
12526 inev
.kind
= SELECT_WINDOW_EVENT
;
12527 inev
.frame_or_window
= window
;
12530 last_window
=window
;
12532 if (!note_mouse_movement (f
, &mouse_pos
))
12533 help_echo_string
= previous_help_echo_string
;
12534 #if USE_MAC_TOOLBAR
12536 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12541 /* If the contents of the global variable
12542 help_echo_string has changed, generate a
12544 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12555 WindowRef window_ptr
= (WindowRef
) er
.message
;
12557 ControlRef root_control
;
12559 if (window_ptr
== tip_window
)
12561 HideWindow (tip_window
);
12565 if (!is_emacs_window (window_ptr
))
12568 f
= mac_window_to_frame (window_ptr
);
12570 if ((er
.modifiers
& activeFlag
) != 0)
12572 /* A window has been activated */
12575 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12577 ActivateControl (root_control
);
12579 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12581 mouse_loc
.h
= (er
.where
.h
12583 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12584 mouse_loc
.v
= (er
.where
.v
12586 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12587 /* Window-activated event counts as mouse movement,
12588 so update things that depend on mouse position. */
12589 note_mouse_movement (f
, &mouse_loc
);
12593 /* A window has been deactivated */
12594 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12596 DeactivateControl (root_control
);
12598 #ifdef USE_TOOLKIT_SCROLL_BARS
12599 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12601 struct input_event event
;
12603 EVENT_INIT (event
);
12604 event
.kind
= NO_EVENT
;
12605 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12606 if (event
.kind
!= NO_EVENT
)
12608 event
.timestamp
= timestamp
;
12609 kbd_buffer_store_event_hold (&event
, hold_quit
);
12614 dpyinfo
->grabbed
= 0;
12616 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12618 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12620 /* If we move outside the frame, then we're
12621 certainly no longer on any text in the
12623 clear_mouse_face (dpyinfo
);
12624 dpyinfo
->mouse_face_mouse_frame
= 0;
12627 /* Generate a nil HELP_EVENT to cancel a help-echo.
12628 Do it only if there's something to cancel.
12629 Otherwise, the startup message is cleared when the
12630 mouse leaves the frame. */
12631 if (any_help_event_p
)
12642 f
= mac_focus_frame (dpyinfo
);
12643 XSETFRAME (inev
.frame_or_window
, f
);
12645 /* If mouse-highlight is an integer, input clears out mouse
12647 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12648 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12650 clear_mouse_face (dpyinfo
);
12651 dpyinfo
->mouse_face_hidden
= 1;
12655 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
12658 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
12660 sizeof (UInt32
), NULL
, &modifiers
);
12662 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
12664 #if TARGET_API_MAC_CARBON
12665 if (!(mapped_modifiers
12666 & ~(mac_pass_command_to_system
? cmdKey
: 0)
12667 & ~(mac_pass_control_to_system
? controlKey
: 0)))
12671 if (er
.what
!= keyUp
)
12672 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12673 (er
.message
& keyCodeMask
) >> 8,
12674 modifiers
, timestamp
, &inev
);
12678 case kHighLevelEvent
:
12679 AEProcessAppleEvent (&er
);
12684 #if TARGET_API_MAC_CARBON
12688 read_socket_inev
= &inev
;
12689 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12690 read_socket_inev
= NULL
;
12695 #if TARGET_API_MAC_CARBON
12696 ReleaseEvent (eventRef
);
12699 if (inev
.kind
!= NO_EVENT
)
12701 inev
.timestamp
= timestamp
;
12702 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12707 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12712 XSETFRAME (frame
, f
);
12718 any_help_event_p
= 1;
12719 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12720 help_echo_object
, help_echo_pos
);
12724 help_echo_string
= Qnil
;
12725 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12731 /* If the focus was just given to an autoraising frame,
12733 /* ??? This ought to be able to handle more than one such frame. */
12734 if (pending_autoraise_frame
)
12736 x_raise_frame (pending_autoraise_frame
);
12737 pending_autoraise_frame
= 0;
12740 if (mac_screen_config_changed
)
12742 mac_get_screen_info (dpyinfo
);
12743 mac_screen_config_changed
= 0;
12746 #if !TARGET_API_MAC_CARBON
12747 /* Check which frames are still visible. We do this here because
12748 there doesn't seem to be any direct notification from the Window
12749 Manager that the visibility of a window has changed (at least,
12750 not in all cases). */
12752 Lisp_Object tail
, frame
;
12754 FOR_EACH_FRAME (tail
, frame
)
12756 struct frame
*f
= XFRAME (frame
);
12758 /* The tooltip has been drawn already. Avoid the
12759 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12760 if (EQ (frame
, tip_frame
))
12763 if (FRAME_MAC_P (f
))
12764 mac_handle_visibility_change (f
);
12775 /* Need to override CodeWarrior's input function so no conversion is
12776 done on newlines Otherwise compiled functions in .elc files will be
12777 read incorrectly. Defined in ...:MSL C:MSL
12778 Common:Source:buffer_io.c. */
12781 __convert_to_newlines (unsigned char * p
, size_t * n
)
12783 #pragma unused(p,n)
12787 __convert_from_newlines (unsigned char * p
, size_t * n
)
12789 #pragma unused(p,n)
12795 make_mac_terminal_frame (struct frame
*f
)
12800 XSETFRAME (frame
, f
);
12802 f
->output_method
= output_mac
;
12803 f
->output_data
.mac
= (struct mac_output
*)
12804 xmalloc (sizeof (struct mac_output
));
12805 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12807 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12809 FRAME_COLS (f
) = 96;
12810 FRAME_LINES (f
) = 4;
12812 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12813 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12815 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12817 f
->output_data
.mac
->cursor_pixel
= 0;
12818 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12819 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12820 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12822 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12823 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12824 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12825 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12826 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12827 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12829 FRAME_FONTSET (f
) = -1;
12830 f
->output_data
.mac
->explicit_parent
= 0;
12833 f
->border_width
= 0;
12835 f
->internal_border_width
= 0;
12840 f
->new_text_cols
= 0;
12841 f
->new_text_lines
= 0;
12843 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12844 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12845 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12849 if (!(FRAME_MAC_WINDOW (f
) =
12850 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12851 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12853 /* so that update events can find this mac_output struct */
12854 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12860 /* Need to be initialized for unshow_buffer in window.c. */
12861 selected_window
= f
->selected_window
;
12863 Fmodify_frame_parameters (frame
,
12864 Fcons (Fcons (Qfont
,
12865 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12866 Fmodify_frame_parameters (frame
,
12867 Fcons (Fcons (Qforeground_color
,
12868 build_string ("black")), Qnil
));
12869 Fmodify_frame_parameters (frame
,
12870 Fcons (Fcons (Qbackground_color
,
12871 build_string ("white")), Qnil
));
12876 /***********************************************************************
12878 ***********************************************************************/
12880 static int mac_initialized
= 0;
12883 mac_make_rdb (xrm_option
)
12884 const char *xrm_option
;
12886 XrmDatabase database
;
12888 database
= xrm_get_preference_database (NULL
);
12890 xrm_merge_string_database (database
, xrm_option
);
12895 struct mac_display_info
*
12896 mac_term_init (display_name
, xrm_option
, resource_name
)
12897 Lisp_Object display_name
;
12899 char *resource_name
;
12901 struct mac_display_info
*dpyinfo
;
12902 struct terminal
*terminal
;
12906 if (!mac_initialized
)
12909 mac_initialized
= 1;
12912 if (x_display_list
)
12913 error ("Sorry, this version can only handle one display");
12915 dpyinfo
= &one_mac_display_info
;
12916 bzero (dpyinfo
, sizeof (*dpyinfo
));
12918 terminal
= mac_create_terminal (dpyinfo
);
12920 /* Set the name of the terminal. */
12921 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
12922 strncpy (terminal
->name
, SDATA (display_name
), SBYTES (display_name
));
12923 terminal
->name
[SBYTES (display_name
)] = 0;
12926 dpyinfo
->mac_id_name
12927 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12928 + SCHARS (Vsystem_name
)
12930 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12931 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12933 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12934 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12937 dpyinfo
->reference_count
= 0;
12938 dpyinfo
->resx
= 72.0;
12939 dpyinfo
->resy
= 72.0;
12941 mac_get_screen_info (dpyinfo
);
12943 dpyinfo
->grabbed
= 0;
12944 dpyinfo
->root_window
= NULL
;
12945 dpyinfo
->terminal
->image_cache
= make_image_cache ();
12947 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12948 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12949 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12950 dpyinfo
->mouse_face_window
= Qnil
;
12951 dpyinfo
->mouse_face_overlay
= Qnil
;
12952 dpyinfo
->mouse_face_hidden
= 0;
12954 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12956 /* Put this display on the chain. */
12957 dpyinfo
->next
= x_display_list
;
12958 x_display_list
= dpyinfo
;
12960 /* Put it on x_display_name_list. */
12961 x_display_name_list
= Fcons (Fcons (display_name
,
12962 Fcons (Qnil
, dpyinfo
->xrdb
)),
12963 x_display_name_list
);
12964 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12966 /* FIXME: Untested.
12967 Add the default keyboard. */
12968 add_keyboard_wait_descriptor (0);
12971 mac_init_fringe (terminal
->rif
);
12979 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12982 x_delete_display (dpyinfo
)
12983 struct mac_display_info
*dpyinfo
;
12987 /* Discard this display from x_display_name_list and x_display_list.
12988 We can't use Fdelq because that can quit. */
12989 if (! NILP (x_display_name_list
)
12990 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12991 x_display_name_list
= XCDR (x_display_name_list
);
12996 tail
= x_display_name_list
;
12997 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12999 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
13001 XSETCDR (tail
, XCDR (XCDR (tail
)));
13004 tail
= XCDR (tail
);
13008 if (x_display_list
== dpyinfo
)
13009 x_display_list
= dpyinfo
->next
;
13012 struct x_display_info
*tail
;
13014 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
13015 if (tail
->next
== dpyinfo
)
13016 tail
->next
= tail
->next
->next
;
13019 /* Free the font names in the font table. */
13020 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
13021 if (dpyinfo
->font_table
[i
].name
)
13023 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
13024 xfree (dpyinfo
->font_table
[i
].full_name
);
13025 xfree (dpyinfo
->font_table
[i
].name
);
13028 if (dpyinfo
->font_table
)
13030 if (dpyinfo
->font_table
->font_encoder
)
13031 xfree (dpyinfo
->font_table
->font_encoder
);
13032 xfree (dpyinfo
->font_table
);
13034 if (dpyinfo
->mac_id_name
)
13035 xfree (dpyinfo
->mac_id_name
);
13037 if (x_display_list
== 0)
13039 mac_clear_font_name_table ();
13040 bzero (dpyinfo
, sizeof (*dpyinfo
));
13051 MenuItemIndex menu_index
;
13053 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
13054 &menu
, &menu_index
);
13056 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
13057 EnableMenuCommand (NULL
, kHICommandPreferences
);
13058 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
13059 &menu
, &menu_index
);
13062 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
13063 InsertMenuItemTextWithCFString (menu
, NULL
,
13064 0, kMenuItemAttrSeparator
, 0);
13065 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
13066 0, 0, kHICommandAbout
);
13068 #else /* !MAC_OSX */
13069 #if TARGET_API_MAC_CARBON
13070 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
13080 static InterfaceTypeList types
= {kUnicodeDocument
};
13082 static InterfaceTypeList types
= {kTextService
};
13085 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
13086 &tsm_document_id
, 0);
13090 /* Set up use of X before we make the first connection. */
13092 extern frame_parm_handler mac_frame_parm_handlers
[];
13094 static struct redisplay_interface x_redisplay_interface
=
13096 mac_frame_parm_handlers
,
13100 x_clear_end_of_line
,
13102 x_after_update_window_line
,
13103 x_update_window_begin
,
13104 x_update_window_end
,
13108 mac_flush_display_optional
,
13110 0, /* flush_display_optional */
13112 x_clear_window_mouse_face
,
13113 x_get_glyph_overhangs
,
13114 x_fix_overlapping_area
,
13115 x_draw_fringe_bitmap
,
13117 mac_define_fringe_bitmap
,
13118 mac_destroy_fringe_bitmap
,
13120 0, /* define_fringe_bitmap */
13121 0, /* destroy_fringe_bitmap */
13123 mac_per_char_metric
,
13125 mac_compute_glyph_string_overhangs
,
13126 x_draw_glyph_string
,
13127 mac_define_frame_cursor
,
13128 mac_clear_frame_area
,
13129 mac_draw_window_cursor
,
13130 mac_draw_vertical_window_border
,
13131 mac_shift_glyphs_for_insert
13134 static struct terminal
*
13135 mac_create_terminal (struct mac_display_info
*dpyinfo
)
13137 struct terminal
*terminal
;
13139 terminal
= create_terminal ();
13141 terminal
->type
= output_mac
;
13142 terminal
->display_info
.mac
= dpyinfo
;
13143 dpyinfo
->terminal
= terminal
;
13145 terminal
->clear_frame_hook
= x_clear_frame
;
13146 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
13147 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
13148 terminal
->ring_bell_hook
= XTring_bell
;
13149 terminal
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
13150 terminal
->set_terminal_modes_hook
= XTset_terminal_modes
;
13151 terminal
->update_begin_hook
= x_update_begin
;
13152 terminal
->update_end_hook
= x_update_end
;
13153 terminal
->set_terminal_window_hook
= XTset_terminal_window
;
13154 terminal
->read_socket_hook
= XTread_socket
;
13155 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
13156 terminal
->mouse_position_hook
= XTmouse_position
;
13157 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
13158 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
13159 /* terminal->fullscreen_hook = XTfullscreen_hook; */
13160 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13161 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13162 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13163 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13164 terminal
->delete_frame_hook
= x_destroy_window
;
13165 /* terminal->delete_terminal_hook = x_delete_terminal; */
13167 terminal
->rif
= &x_redisplay_interface
;
13169 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
13170 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
13171 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
13172 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
13173 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
13177 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
13178 terminal
->char_ins_del_ok
= 1;
13179 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
13180 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
13181 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
13186 /* FIXME: This keyboard setup is 100% untested, just copied from
13187 w32_create_terminal in order to set window-system now that it's
13188 a keyboard object. */
13189 /* We don't yet support separate terminals on Mac, so don't try to share
13190 keyboards between virtual terminals that are on the same physical
13191 terminal like X does. */
13192 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
13193 init_kboard (terminal
->kboard
);
13194 terminal
->kboard
->Vwindow_system
= intern ("mac");
13195 terminal
->kboard
->next_kboard
= all_kboards
;
13196 all_kboards
= terminal
->kboard
;
13197 /* Don't let the initial kboard remain current longer than necessary.
13198 That would cause problems if a file loaded on startup tries to
13199 prompt in the mini-buffer. */
13200 if (current_kboard
== initial_kboard
)
13201 current_kboard
= terminal
->kboard
;
13202 terminal
->kboard
->reference_count
++;
13213 last_tool_bar_item
= -1;
13214 any_help_event_p
= 0;
13216 /* Try to use interrupt input; if we can't, then start polling. */
13217 Fset_input_interrupt_mode (Qt
);
13221 #if TARGET_API_MAC_CARBON
13223 install_application_handler ();
13232 init_coercion_handler ();
13234 init_apple_event_handler ();
13236 init_dm_notification_handler ();
13238 if (!inhibit_window_system
)
13240 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
13242 SetFrontProcess (&psn
);
13260 staticpro (&x_error_message_string
);
13261 x_error_message_string
= Qnil
;
13264 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
13265 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
13266 Qalt
= intern ("alt"); staticpro (&Qalt
);
13267 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
13268 Qsuper
= intern ("super"); staticpro (&Qsuper
);
13269 Qmodifier_value
= intern ("modifier-value");
13270 staticpro (&Qmodifier_value
);
13272 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
13273 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
13274 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
13275 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
13276 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
13278 #if TARGET_API_MAC_CARBON
13279 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
13281 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
13282 staticpro (&Qtoolbar_switch_mode
);
13283 #if USE_MAC_FONT_PANEL
13284 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
13285 Qselection
= intern ("selection"); staticpro (&Qselection
);
13288 Qservice
= intern ("service"); staticpro (&Qservice
);
13289 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
13290 Qperform
= intern ("perform"); staticpro (&Qperform
);
13292 Qmouse_drag_overlay
= intern ("mouse-drag-overlay");
13293 staticpro (&Qmouse_drag_overlay
);
13296 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
13297 Qupdate_active_input_area
= intern ("update-active-input-area");
13298 staticpro (&Qupdate_active_input_area
);
13299 Qunicode_for_key_event
= intern ("unicode-for-key-event");
13300 staticpro (&Qunicode_for_key_event
);
13305 Fprovide (intern ("mac-carbon"), Qnil
);
13308 staticpro (&Qreverse
);
13309 Qreverse
= intern ("reverse");
13311 staticpro (&x_display_name_list
);
13312 x_display_name_list
= Qnil
;
13314 staticpro (&last_mouse_scroll_bar
);
13315 last_mouse_scroll_bar
= Qnil
;
13317 staticpro (&fm_font_family_alist
);
13318 fm_font_family_alist
= Qnil
;
13321 staticpro (&atsu_font_id_hash
);
13322 atsu_font_id_hash
= Qnil
;
13324 staticpro (&fm_style_face_attributes_alist
);
13325 fm_style_face_attributes_alist
= Qnil
;
13329 staticpro (&saved_ts_script_language_on_focus
);
13330 saved_ts_script_language_on_focus
= Qnil
;
13333 /* We don't yet support this, but defining this here avoids whining
13334 from cus-start.el and other places, like "M-x set-variable". */
13335 DEFVAR_BOOL ("x-use-underline-position-properties",
13336 &x_use_underline_position_properties
,
13337 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13338 A value of nil means ignore them. If you encounter fonts with bogus
13339 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13340 to 4.1, set this to nil.
13342 NOTE: Not supported on Mac yet. */);
13343 x_use_underline_position_properties
= 0;
13345 DEFVAR_BOOL ("x-underline-at-descent-line",
13346 &x_underline_at_descent_line
,
13347 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
13348 A value of nil means to draw the underline according to the value of the
13349 variable `x-use-underline-position-properties', which is usually at the
13350 baseline level. The default value is nil. */);
13351 x_underline_at_descent_line
= 0;
13353 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
13354 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
13355 #ifdef USE_TOOLKIT_SCROLL_BARS
13356 Vx_toolkit_scroll_bars
= Qt
;
13358 Vx_toolkit_scroll_bars
= Qnil
;
13361 staticpro (&last_mouse_motion_frame
);
13362 last_mouse_motion_frame
= Qnil
;
13364 /* Variables to configure modifier key assignment. */
13366 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
13367 doc
: /* *Modifier key assumed when the Mac control key is pressed.
13368 The value can be `control', `meta', `alt', `hyper', or `super' for the
13369 respective modifier. The default is `control'. */);
13370 Vmac_control_modifier
= Qcontrol
;
13372 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
13373 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
13374 The value can be `control', `meta', `alt', `hyper', or `super' for the
13375 respective modifier. If the value is nil then the key will act as the
13376 normal Mac control modifier, and the option key can be used to compose
13377 characters depending on the chosen Mac keyboard setting. */);
13378 Vmac_option_modifier
= Qnil
;
13380 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
13381 doc
: /* *Modifier key assumed when the Mac command key is pressed.
13382 The value can be `control', `meta', `alt', `hyper', or `super' for the
13383 respective modifier. The default is `meta'. */);
13384 Vmac_command_modifier
= Qmeta
;
13386 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
13387 doc
: /* *Modifier key assumed when the Mac function key is pressed.
13388 The value can be `control', `meta', `alt', `hyper', or `super' for the
13389 respective modifier. Note that remapping the function key may lead to
13390 unexpected results for some keys on non-US/GB keyboards. */);
13391 Vmac_function_modifier
= Qnil
;
13393 DEFVAR_LISP ("mac-emulate-three-button-mouse",
13394 &Vmac_emulate_three_button_mouse
,
13395 doc
: /* *Specify a way of three button mouse emulation.
13396 The value can be nil, t, or the symbol `reverse'.
13397 A value of nil means that no emulation should be done and the modifiers
13398 should be placed on the mouse-1 event.
13399 t means that when the option-key is held down while pressing the mouse
13400 button, the click will register as mouse-2 and while the command-key
13401 is held down, the click will register as mouse-3.
13402 The symbol `reverse' means that the option-key will register for
13403 mouse-3 and the command-key will register for mouse-2. */);
13404 Vmac_emulate_three_button_mouse
= Qnil
;
13406 #if TARGET_API_MAC_CARBON
13407 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
13408 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
13409 Otherwise, the right click will be treated as mouse-2 and the wheel
13410 button will be mouse-3. */);
13411 mac_wheel_button_is_mouse_2
= 1;
13413 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
13414 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
13415 mac_pass_command_to_system
= 1;
13417 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
13418 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13419 mac_pass_control_to_system
= 1;
13423 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
13424 doc
: /* *If non-nil, allow anti-aliasing.
13425 The text will be rendered using Core Graphics text rendering which
13426 may anti-alias the text. */);
13428 mac_use_core_graphics
= 1;
13430 mac_use_core_graphics
= 0;
13433 /* Register an entry for `mac-roman' so that it can be used when
13434 creating the terminal frame on Mac OS 9 before loading
13435 term/mac-win.elc. */
13436 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
13437 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
13438 Each entry should be of the form:
13440 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13442 where CHARSET-NAME is a string used in font names to identify the
13443 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13444 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13445 Vmac_charset_info_alist
=
13446 Fcons (list3 (build_string ("mac-roman"),
13447 make_number (smRoman
), Qnil
), Qnil
);
13450 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13451 doc
: /* Overlay used to display Mac TSM active input area. */);
13452 Vmac_ts_active_input_overlay
= Qnil
;
13454 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf
,
13455 doc
: /* Byte sequence of the current Mac TSM active input area. */);
13456 /* `empty_string' is not ready yet on Mac OS Classic. */
13457 Vmac_ts_active_input_buf
= build_string ("");
13459 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13460 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13461 If the value is t, the input script and language are restored to those
13462 used in the last focus frame. If the value is a pair of integers, the
13463 input script and language codes, which are defined in the Script
13464 Manager, are set to its car and cdr parts, respectively. Otherwise,
13465 Emacs doesn't set them and thus follows the system default behavior. */);
13466 Vmac_ts_script_language_on_focus
= Qnil
;
13470 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13471 (do not change this comment) */