1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
83 #include "character.h"
88 /* Non-nil means Emacs uses toolkit scroll bars. */
90 Lisp_Object Vx_toolkit_scroll_bars
;
92 /* If non-zero, the text will be rendered using Core Graphics text
93 rendering which may anti-alias the text. */
94 int mac_use_core_graphics
;
97 /* Non-zero means that a HELP_EVENT has been generated since Emacs
100 static int any_help_event_p
;
102 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
103 static Lisp_Object last_window
;
105 /* Non-zero means make use of UNDERLINE_POSITION font properties.
106 (Not yet supported.) */
107 int x_use_underline_position_properties
;
109 /* Non-zero means to draw the underline at the same place as the descent line. */
111 int x_underline_at_descent_line
;
113 /* This is a chain of structures for all the X displays currently in
116 struct x_display_info
*x_display_list
;
118 /* This is a list of cons cells, each of the form (NAME
119 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
120 x_display_list and in the same order. NAME is the name of the
121 frame. FONT-LIST-CACHE records previous values returned by
122 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
123 equivalent, which is implemented with a Lisp object, for the
126 Lisp_Object x_display_name_list
;
128 /* This is display since Mac does not support multiple ones. */
129 struct mac_display_info one_mac_display_info
;
131 /* Frame being updated by update_frame. This is declared in term.c.
132 This is set by update_begin and looked at by all the XT functions.
133 It is zero while not inside an update. In that case, the XT
134 functions assume that `selected_frame' is the frame to apply to. */
136 extern struct frame
*updating_frame
;
138 /* This is a frame waiting to be auto-raised, within XTread_socket. */
140 struct frame
*pending_autoraise_frame
;
144 Formerly, we used PointerMotionHintMask (in standard_event_mask)
145 so that we would have to call XQueryPointer after each MotionNotify
146 event to ask for another such event. However, this made mouse tracking
147 slow, and there was a bug that made it eventually stop.
149 Simply asking for MotionNotify all the time seems to work better.
151 In order to avoid asking for motion events and then throwing most
152 of them away or busy-polling the server for mouse positions, we ask
153 the server for pointer motion hints. This means that we get only
154 one event per group of mouse movements. "Groups" are delimited by
155 other kinds of events (focus changes and button clicks, for
156 example), or by XQueryPointer calls; when one of these happens, we
157 get another MotionNotify event the next time the mouse moves. This
158 is at least as efficient as getting motion events when mouse
159 tracking is on, and I suspect only negligibly worse when tracking
162 /* Where the mouse was last time we reported a mouse event. */
164 static Rect last_mouse_glyph
;
165 static FRAME_PTR last_mouse_glyph_frame
;
167 /* The scroll bar in which the last X motion event occurred.
169 If the last X motion event occurred in a scroll bar, we set this so
170 XTmouse_position can know whether to report a scroll bar motion or
173 If the last X motion event didn't occur in a scroll bar, we set
174 this to Qnil, to tell XTmouse_position to return an ordinary motion
177 static Lisp_Object last_mouse_scroll_bar
;
179 /* This is a hack. We would really prefer that XTmouse_position would
180 return the time associated with the position it returns, but there
181 doesn't seem to be any way to wrest the time-stamp from the server
182 along with the position query. So, we just keep track of the time
183 of the last movement we received, and return that in hopes that
184 it's somewhat accurate. */
186 static Time last_mouse_movement_time
;
188 struct scroll_bar
*tracked_scroll_bar
= NULL
;
190 /* Incremented by XTread_socket whenever it really tries to read
194 static int volatile input_signal_count
;
196 static int input_signal_count
;
199 extern Lisp_Object Vsystem_name
;
201 extern Lisp_Object Qeql
;
203 /* A mask of extra modifier bits to put into every keyboard char. */
205 extern EMACS_INT extra_keyboard_modifiers
;
207 /* The keysyms to use for the various modifiers. */
209 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
211 extern int inhibit_window_system
;
213 #if __MRC__ && !TARGET_API_MAC_CARBON
214 QDGlobals qd
; /* QuickDraw global information structure. */
217 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
219 struct mac_display_info
*mac_display_info_for_display (Display
*);
220 static void x_update_window_end
P_ ((struct window
*, int, int));
221 int x_catch_errors
P_ ((Display
*));
222 void x_uncatch_errors
P_ ((Display
*, int));
223 void x_lower_frame
P_ ((struct frame
*));
224 void x_scroll_bar_clear
P_ ((struct frame
*));
225 int x_had_errors_p
P_ ((Display
*));
226 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
227 void x_raise_frame
P_ ((struct frame
*));
228 void x_set_window_size
P_ ((struct frame
*, int, int, int));
229 void x_wm_set_window_state
P_ ((struct frame
*, int));
230 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
231 static void mac_initialize
P_ ((void));
232 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
233 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
234 static void x_update_end
P_ ((struct frame
*));
235 static void XTframe_up_to_date
P_ ((struct frame
*));
236 static void XTset_terminal_modes
P_ ((struct terminal
*));
237 static void XTreset_terminal_modes
P_ ((struct terminal
*));
238 static void x_clear_frame
P_ ((struct frame
*));
239 static void frame_highlight
P_ ((struct frame
*));
240 static void frame_unhighlight
P_ ((struct frame
*));
241 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
242 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
243 struct frame
*, struct input_event
*));
244 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
246 struct input_event
*));
247 static void XTframe_rehighlight
P_ ((struct frame
*));
248 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
249 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
250 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
251 enum text_cursor_kinds
));
253 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
254 static void x_flush
P_ ((struct frame
*f
));
255 static void x_update_begin
P_ ((struct frame
*));
256 static void x_update_window_begin
P_ ((struct window
*));
257 static void x_after_update_window_line
P_ ((struct glyph_row
*));
258 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
259 enum scroll_bar_part
*,
260 Lisp_Object
*, Lisp_Object
*,
263 static int is_emacs_window
P_ ((WindowRef
));
264 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
265 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
266 static struct terminal
*mac_create_terminal
P_ ((struct mac_display_info
*dpyinfo
));
269 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
270 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
271 #define GC_FONT(gc) ((gc)->xgcv.font)
272 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
274 #define CG_SET_FILL_COLOR(context, color) \
275 CGContextSetRGBFillColor (context, \
276 RED_FROM_ULONG (color) / 255.0f, \
277 GREEN_FROM_ULONG (color) / 255.0f, \
278 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
279 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
280 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
281 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
283 if (CGColorGetTypeID != NULL) \
284 CGContextSetFillColorWithColor (context, cg_color); \
286 CG_SET_FILL_COLOR (context, color); \
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CGContextSetFillColorWithColor (context, cg_color)
293 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
294 CG_SET_FILL_COLOR (context, color)
296 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
297 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
299 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
300 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
304 #define CG_SET_STROKE_COLOR(context, color) \
305 CGContextSetRGBStrokeColor (context, \
306 RED_FROM_ULONG (color) / 255.0f, \
307 GREEN_FROM_ULONG (color) / 255.0f, \
308 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
309 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
310 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
311 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
313 if (CGColorGetTypeID != NULL) \
314 CGContextSetStrokeColorWithColor (context, cg_color); \
316 CG_SET_STROKE_COLOR (context, color); \
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CGContextSetStrokeColorWithColor (context, cg_color)
323 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
324 CG_SET_STROKE_COLOR (context, color)
326 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
327 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
331 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
333 /* Fringe bitmaps. */
335 static int max_fringe_bmp
= 0;
336 static CGImageRef
*fringe_bmp
= 0;
338 CGColorSpaceRef mac_cg_color_space_rgb
;
339 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
340 static CGColorRef mac_cg_color_black
;
346 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
347 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
348 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
349 /* Don't check the availability of CGColorCreate; this symbol is
350 defined even in Mac OS X 10.1. */
351 if (CGColorGetTypeID
!= NULL
)
354 CGFloat rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
356 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
362 mac_begin_cg_clip (f
, gc
)
366 CGContextRef context
= FRAME_CG_CONTEXT (f
);
370 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
371 FRAME_CG_CONTEXT (f
) = context
;
374 CGContextSaveGState (context
);
375 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
376 CGContextScaleCTM (context
, 1, -1);
377 if (gc
&& gc
->n_clip_rects
)
378 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
387 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
391 mac_prepare_for_quickdraw (f
)
396 Lisp_Object rest
, frame
;
397 FOR_EACH_FRAME (rest
, frame
)
398 if (FRAME_MAC_P (XFRAME (frame
)))
399 mac_prepare_for_quickdraw (XFRAME (frame
));
403 CGContextRef context
= FRAME_CG_CONTEXT (f
);
407 CGContextSynchronize (context
);
408 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
409 &FRAME_CG_CONTEXT (f
));
415 static RgnHandle saved_port_clip_region
= NULL
;
418 mac_begin_clip (f
, gc
)
422 static RgnHandle new_region
= NULL
;
424 if (saved_port_clip_region
== NULL
)
425 saved_port_clip_region
= NewRgn ();
426 if (new_region
== NULL
)
427 new_region
= NewRgn ();
430 mac_prepare_for_quickdraw (f
);
432 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
434 if (gc
->n_clip_rects
)
436 GetClip (saved_port_clip_region
);
437 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
438 SetClip (new_region
);
446 if (gc
->n_clip_rects
)
447 SetClip (saved_port_clip_region
);
451 /* X display function emulation */
453 /* Mac version of XDrawLine. */
456 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
462 CGContextRef context
;
463 CGFloat gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
466 gx1
+= 0.5f
, gx2
+= 0.5f
;
468 gy1
+= 0.5f
, gy2
+= 0.5f
;
470 context
= mac_begin_cg_clip (f
, gc
);
471 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
472 CGContextBeginPath (context
);
473 CGContextMoveToPoint (context
, gx1
, gy1
);
474 CGContextAddLineToPoint (context
, gx2
, gy2
);
475 CGContextClosePath (context
);
476 CGContextStrokePath (context
);
494 mac_begin_clip (f
, gc
);
495 RGBForeColor (GC_FORE_COLOR (gc
));
502 /* Mac version of XDrawLine (to Pixmap). */
505 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
512 CGContextRef context
;
514 CGColorSpaceRef color_space
;
515 CGImageAlphaInfo alpha_info
;
516 CGFloat gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
519 gx1
+= 0.5f
, gx2
+= 0.5f
;
521 gy1
+= 0.5f
, gy2
+= 0.5f
;
523 if (ximg
->bits_per_pixel
== 32)
525 color_space
= mac_cg_color_space_rgb
;
526 alpha_info
= (kCGImageAlphaNoneSkipFirst
527 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
528 | kCGBitmapByteOrder32Host
535 alpha_info
= kCGImageAlphaOnly
;
537 if (color_space
== NULL
)
539 context
= CGBitmapContextCreate (ximg
->data
, ximg
->width
,
541 ximg
->bytes_per_line
, color_space
,
543 if (ximg
->bits_per_pixel
== 32)
544 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
546 CGContextSetGrayStrokeColor (context
, gc
->xgcv
.foreground
/ 255.0f
, 1.0);
547 CGContextMoveToPoint (context
, gx1
, gy1
);
548 CGContextAddLineToPoint (context
, gx2
, gy2
);
549 CGContextClosePath (context
);
550 CGContextStrokePath (context
);
551 CGContextRelease (context
);
571 GetGWorld (&old_port
, &old_gdh
);
574 RGBForeColor (GC_FORE_COLOR (gc
));
576 LockPixels (GetGWorldPixMap (p
));
579 UnlockPixels (GetGWorldPixMap (p
));
581 SetGWorld (old_port
, old_gdh
);
587 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
591 unsigned int width
, height
;
595 CGContextRef context
;
597 context
= mac_begin_cg_clip (f
, gc
);
598 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
599 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
606 mac_begin_clip (f
, gc
);
607 RGBBackColor (GC_BACK_COLOR (gc
));
608 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
610 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
617 /* Mac version of XClearArea. */
620 mac_clear_area (f
, x
, y
, width
, height
)
623 unsigned int width
, height
;
625 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
628 /* Mac version of XClearWindow. */
636 CGContextRef context
;
637 GC gc
= FRAME_NORMAL_GC (f
);
639 context
= mac_begin_cg_clip (f
, NULL
);
640 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
641 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
642 FRAME_PIXEL_HEIGHT (f
)));
645 #else /* !USE_CG_DRAWING */
646 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
648 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
650 #if TARGET_API_MAC_CARBON
654 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
657 #else /* not TARGET_API_MAC_CARBON */
658 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
659 #endif /* not TARGET_API_MAC_CARBON */
664 /* Mac replacement for XCopyArea. */
668 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
669 dest_x
, dest_y
, overlay_p
)
674 unsigned int width
, height
;
675 int dest_x
, dest_y
, overlay_p
;
677 CGContextRef context
;
678 CGFloat port_height
= FRAME_PIXEL_HEIGHT (f
);
679 CGRect dest_rect
= mac_rect_make (f
, dest_x
, dest_y
, width
, height
);
681 context
= mac_begin_cg_clip (f
, gc
);
684 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
685 CGContextFillRect (context
, dest_rect
);
687 CGContextClipToRect (context
, dest_rect
);
688 CGContextScaleCTM (context
, 1, -1);
689 CGContextTranslateCTM (context
, 0, -port_height
);
690 if (CGImageIsMask (image
))
691 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
692 CGContextDrawImage (context
,
693 mac_rect_make (f
, dest_x
- src_x
,
694 port_height
- (dest_y
- src_y
695 + CGImageGetHeight (image
)),
696 CGImageGetWidth (image
),
697 CGImageGetHeight (image
)),
702 #else /* !USE_CG_DRAWING */
705 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
708 int x
, y
, width
, height
;
709 unsigned short *bits
;
715 bitmap
.rowBytes
= sizeof(unsigned short);
716 bitmap
.baseAddr
= (char *)bits
;
717 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
719 mac_begin_clip (f
, gc
);
720 RGBForeColor (GC_FORE_COLOR (gc
));
721 RGBBackColor (GC_BACK_COLOR (gc
));
722 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
723 #if TARGET_API_MAC_CARBON
729 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
730 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
731 UnlockPortBits (port
);
733 #else /* not TARGET_API_MAC_CARBON */
734 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
735 overlay_p
? srcOr
: srcCopy
, 0);
736 #endif /* not TARGET_API_MAC_CARBON */
737 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
740 #endif /* !USE_CG_DRAWING */
743 /* Mac replacement for XCreateBitmapFromBitmapData. */
746 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
751 static const unsigned char swap_nibble
[16]
752 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
753 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
754 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
755 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
759 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
760 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
761 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
762 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
763 for (i
= 0; i
< h
; i
++)
765 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
766 for (j
= 0; j
< w1
; j
++)
768 /* Bitswap XBM bytes to match how Mac does things. */
769 unsigned char c
= *bits
++;
770 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
771 | (swap_nibble
[(c
>>4) & 0xf]));
775 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
780 mac_free_bitmap (bitmap
)
783 xfree (bitmap
->baseAddr
);
788 XCreatePixmap (display
, w
, width
, height
, depth
)
791 unsigned int width
, height
;
797 ximg
= xmalloc (sizeof (*ximg
));
799 ximg
->height
= height
;
800 ximg
->bits_per_pixel
= depth
== 1 ? 8 : 32;
801 ximg
->bytes_per_line
= width
* (ximg
->bits_per_pixel
/ 8);
802 ximg
->data
= xmalloc (ximg
->bytes_per_line
* height
);
810 SetPortWindowPort (w
);
812 SetRect (&r
, 0, 0, width
, height
);
813 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
816 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
817 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
819 /* CreateCGImageFromPixMaps requires ARGB format. */
820 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
830 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
834 unsigned int width
, height
;
835 unsigned long fg
, bg
;
841 CGDataProviderRef provider
;
842 CGImageRef image_mask
;
843 CGContextRef context
;
845 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
849 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
850 provider
= CGDataProviderCreateWithData (NULL
, bitmap
.baseAddr
,
851 bitmap
.rowBytes
* height
, NULL
);
852 image_mask
= CGImageMaskCreate (width
, height
, 1, 1, bitmap
.rowBytes
,
854 CGDataProviderRelease (provider
);
856 context
= CGBitmapContextCreate (pixmap
->data
, width
, height
, 8,
857 pixmap
->bytes_per_line
,
858 mac_cg_color_space_rgb
,
859 kCGImageAlphaNoneSkipFirst
860 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
861 | kCGBitmapByteOrder32Host
865 CG_SET_FILL_COLOR (context
, fg
);
866 CGContextFillRect (context
, CGRectMake (0, 0, width
, height
));
867 CG_SET_FILL_COLOR (context
, bg
);
868 CGContextDrawImage (context
, CGRectMake (0, 0, width
, height
), image_mask
);
869 CGContextRelease (context
);
870 CGImageRelease (image_mask
);
877 gc
= XCreateGC (display
, w
, 0, NULL
);
879 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
883 GetGWorld (&old_port
, &old_gdh
);
884 SetGWorld (pixmap
, NULL
);
885 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
886 XSetForeground (display
, gc
, fg
);
887 XSetBackground (display
, gc
, bg
);
888 RGBForeColor (GC_FORE_COLOR (gc
));
889 RGBBackColor (GC_BACK_COLOR (gc
));
890 LockPixels (GetGWorldPixMap (pixmap
));
891 #if TARGET_API_MAC_CARBON
892 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
893 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
894 #else /* not TARGET_API_MAC_CARBON */
895 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
896 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
897 #endif /* not TARGET_API_MAC_CARBON */
898 UnlockPixels (GetGWorldPixMap (pixmap
));
899 SetGWorld (old_port
, old_gdh
);
901 mac_free_bitmap (&bitmap
);
908 XFreePixmap (display
, pixmap
)
916 xfree (pixmap
->data
);
920 DisposeGWorld (pixmap
);
925 /* Mac replacement for XFillRectangle. */
928 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
932 unsigned int width
, height
;
935 CGContextRef context
;
937 context
= mac_begin_cg_clip (f
, gc
);
938 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
939 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
944 mac_begin_clip (f
, gc
);
945 RGBForeColor (GC_FORE_COLOR (gc
));
946 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
947 PaintRect (&r
); /* using foreground color of gc */
953 /* Mac replacement for XDrawRectangle: dest is a window. */
956 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
960 unsigned int width
, height
;
963 CGContextRef context
;
965 context
= mac_begin_cg_clip (f
, gc
);
966 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
967 CGContextStrokeRect (context
,
968 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
973 mac_begin_clip (f
, gc
);
974 RGBForeColor (GC_FORE_COLOR (gc
));
975 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
976 FrameRect (&r
); /* using foreground color of gc */
983 mac_invert_rectangle (f
, x
, y
, width
, height
)
986 unsigned int width
, height
;
988 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
989 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
990 if (CGContextSetBlendMode
!= NULL
)
993 CGContextRef context
;
995 context
= mac_begin_cg_clip (f
, NULL
);
996 CGContextSetRGBFillColor (context
, 1.0f
, 1.0f
, 1.0f
, 1.0f
);
997 CGContextSetBlendMode (context
, kCGBlendModeDifference
);
998 CGContextFillRect (context
, mac_rect_make (f
, x
, y
, width
, height
));
1001 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
1002 else /* CGContextSetBlendMode == NULL */
1004 #endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
1005 #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)
1010 mac_prepare_for_quickdraw (f
);
1012 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1014 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
1022 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
1023 ConstUniCharArrayPtr text
;
1024 UniCharCount text_length
;
1026 ATSUTextLayout
*text_layout
;
1029 static ATSUTextLayout saved_text_layout
= NULL
;
1031 if (saved_text_layout
== NULL
)
1033 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
1034 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
1035 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
1036 static ATSLineLayoutOptions line_layout
=
1037 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1038 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
1039 | kATSLineUseQDRendering
1041 kATSLineIsDisplayOnly
| kATSLineFractDisable
1044 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
1046 err
= ATSUCreateTextLayoutWithTextPtr (text
,
1047 kATSUFromTextBeginning
,
1051 &saved_text_layout
);
1053 err
= ATSUSetLayoutControls (saved_text_layout
,
1054 sizeof (tags
) / sizeof (tags
[0]),
1055 tags
, sizes
, values
);
1057 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
1061 err
= ATSUSetRunStyle (saved_text_layout
, style
,
1062 kATSUFromTextBeginning
, kATSUToTextEnd
);
1064 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
1065 kATSUFromTextBeginning
,
1071 *text_layout
= saved_text_layout
;
1077 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1078 overstrike_p
, bytes_per_char
)
1083 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1086 ATSUTextLayout text_layout
;
1088 xassert (bytes_per_char
== 2);
1090 #ifndef WORDS_BIG_ENDIAN
1093 UniChar
*text
= (UniChar
*)buf
;
1095 for (i
= 0; i
< nchars
; i
++)
1096 text
[i
] = EndianU16_BtoN (text
[i
]);
1099 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
1101 GC_FONT (gc
)->mac_style
,
1106 if (!mac_use_core_graphics
)
1109 mac_begin_clip (f
, gc
);
1110 RGBForeColor (GC_FORE_COLOR (gc
));
1115 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1116 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1117 RGBBackColor (GC_BACK_COLOR (gc
));
1119 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1122 ATSUDrawText (text_layout
,
1123 kATSUFromTextBeginning
, kATSUToTextEnd
,
1124 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1128 ATSUDrawText (text_layout
,
1129 kATSUFromTextBeginning
, kATSUToTextEnd
,
1130 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1137 static CGContextRef context
;
1138 CGFloat port_height
= FRAME_PIXEL_HEIGHT (f
);
1139 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1140 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1141 static const ATSUAttributeValuePtr values
[] = {&context
};
1144 context
= mac_begin_cg_clip (f
, gc
);
1149 QDBeginCGContext (port
, &context
);
1150 if (gc
->n_clip_rects
|| bg_width
)
1152 CGContextTranslateCTM (context
, 0, port_height
);
1153 CGContextScaleCTM (context
, 1, -1);
1154 if (gc
->n_clip_rects
)
1155 CGContextClipToRects (context
, gc
->clip_rects
,
1160 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1161 CGContextFillRect (context
,
1163 x
, y
- FONT_BASE (GC_FONT (gc
)),
1165 FONT_HEIGHT (GC_FONT (gc
))));
1167 CGContextScaleCTM (context
, 1, -1);
1168 CGContextTranslateCTM (context
, 0, -port_height
);
1172 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1173 err
= ATSUSetLayoutControls (text_layout
,
1174 sizeof (tags
) / sizeof (tags
[0]),
1175 tags
, sizes
, values
);
1178 ATSUDrawText (text_layout
,
1179 kATSUFromTextBeginning
, kATSUToTextEnd
,
1180 Long2Fix (x
), Long2Fix (port_height
- y
));
1182 ATSUDrawText (text_layout
,
1183 kATSUFromTextBeginning
, kATSUToTextEnd
,
1184 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1187 mac_end_cg_clip (f
);
1190 CGContextSynchronize (context
);
1191 QDEndCGContext (port
, &context
);
1194 /* This doesn't work on Mac OS X 10.1. */
1195 ATSUClearLayoutControls (text_layout
,
1196 sizeof (tags
) / sizeof (tags
[0]), tags
);
1198 ATSUSetLayoutControls (text_layout
,
1199 sizeof (tags
) / sizeof (tags
[0]),
1200 tags
, sizes
, values
);
1203 #endif /* MAC_OSX */
1205 #endif /* USE_ATSUI */
1209 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1210 overstrike_p
, bytes_per_char
)
1215 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1217 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1221 mac_begin_clip (f
, gc
);
1222 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1223 if (mac_use_core_graphics
)
1224 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1226 RGBForeColor (GC_FORE_COLOR (gc
));
1230 RGBBackColor (GC_BACK_COLOR (gc
));
1236 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1238 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1239 into an offscreen graphics world first. So performance gain
1240 cannot be expected.)
1241 - It lowers rendering quality.
1242 - Some fonts leave garbage on cursor movement. */
1247 RGBBackColor (GC_BACK_COLOR (gc
));
1248 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1249 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1254 TextFont (GC_FONT (gc
)->mac_fontnum
);
1255 TextSize (GC_FONT (gc
)->mac_fontsize
);
1256 TextFace (GC_FONT (gc
)->mac_fontface
);
1258 DrawText (buf
, 0, nchars
* bytes_per_char
);
1263 DrawText (buf
, 0, nchars
* bytes_per_char
);
1266 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1269 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1270 if (mac_use_core_graphics
)
1271 SwapQDTextFlags(savedFlags
);
1277 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1278 overstrike_p
, bytes_per_char
)
1283 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1286 if (GC_FONT (gc
)->mac_style
)
1287 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1288 overstrike_p
, bytes_per_char
);
1290 #endif /* USE_ATSUI */
1291 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1292 overstrike_p
, bytes_per_char
);
1296 /* Mac replacement for XDrawImageString. */
1299 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1304 int nchars
, bg_width
, overstrike_p
;
1306 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1311 /* Mac replacement for XDrawImageString16. */
1314 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1319 int nchars
, bg_width
, overstrike_p
;
1321 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1326 /* Mac replacement for XQueryTextExtents, but takes a character. If
1327 STYLE is NULL, measurement is done by QuickDraw Text routines for
1328 the font of the current graphics port. If CG_GLYPH is not NULL,
1329 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1332 mac_query_char_extents (style
, c
,
1333 font_ascent_return
, font_descent_return
,
1334 overall_return
, cg_glyph
)
1341 int *font_ascent_return
, *font_descent_return
;
1342 XCharStruct
*overall_return
;
1343 #if USE_CG_TEXT_DRAWING
1349 OSStatus err
= noErr
;
1356 ATSUTextLayout text_layout
;
1359 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1361 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1363 ATSTrapezoid glyph_bounds
;
1365 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1366 kATSUFromTextBeginning
, kATSUToTextEnd
,
1367 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1368 kATSUseFractionalOrigins
,
1370 kATSUseDeviceOrigins
,
1372 1, &glyph_bounds
, NULL
);
1375 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1376 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1378 width
= Fix2Long (glyph_bounds
.upperRight
.x
1379 - glyph_bounds
.upperLeft
.x
);
1380 if (font_ascent_return
)
1381 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1382 if (font_descent_return
)
1383 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1386 if (err
== noErr
&& overall_return
)
1388 err
= ATSUMeasureTextImage (text_layout
,
1389 kATSUFromTextBeginning
, kATSUToTextEnd
,
1390 0, 0, &char_bounds
);
1392 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1393 #if USE_CG_TEXT_DRAWING
1394 if (err
== noErr
&& cg_glyph
)
1397 ATSUGlyphInfoArray glyph_info_array
;
1398 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1400 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1401 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1403 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1404 kATSUToTextEnd
, &count
,
1407 /* Make sure that we don't have to make layout
1409 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1410 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1411 && glyph_info_array
.glyphs
[0].screenX
== 0)
1413 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1414 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1425 if (font_ascent_return
|| font_descent_return
)
1429 GetFontInfo (&font_info
);
1430 if (font_ascent_return
)
1431 *font_ascent_return
= font_info
.ascent
;
1432 if (font_descent_return
)
1433 *font_descent_return
= font_info
.descent
;
1439 width
= CharWidth (ch
);
1440 QDTextBounds (1, &ch
, &char_bounds
);
1441 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1449 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1452 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1453 XFontStruct
*font_struct
;
1456 XCharStruct
*overall_return
;
1459 short width
= 0, lbearing
= 0, rbearing
= 0;
1462 for (i
= 0; i
< nchars
; i
++)
1464 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1466 width
+= FONT_WIDTH (font_struct
);
1469 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1470 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1471 width
+= pcm
->width
;
1476 overall_return
->lbearing
= lbearing
;
1477 overall_return
->rbearing
= rbearing
;
1478 overall_return
->width
= width
;
1480 /* What's the meaning of the return value of XTextExtents16? */
1484 #if USE_CG_TEXT_DRAWING
1485 static int cg_text_anti_aliasing_threshold
= 8;
1488 init_cg_text_anti_aliasing_threshold ()
1494 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1495 kCFPreferencesCurrentApplication
,
1498 cg_text_anti_aliasing_threshold
= threshold
;
1502 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1507 int nchars
, bg_width
, overstrike_p
;
1509 CGFloat port_height
, gx
, gy
;
1511 CGContextRef context
;
1515 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1518 port_height
= FRAME_PIXEL_HEIGHT (f
);
1520 gy
= port_height
- y
;
1521 glyphs
= (CGGlyph
*)buf
;
1522 advances
= alloca (sizeof (CGSize
) * nchars
);
1523 if (advances
== NULL
)
1525 for (i
= 0; i
< nchars
; i
++)
1527 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1529 advances
[i
].width
= pcm
->width
;
1530 advances
[i
].height
= 0;
1531 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1536 context
= mac_begin_cg_clip (f
, gc
);
1538 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1539 if (gc
->n_clip_rects
|| bg_width
)
1541 CGContextTranslateCTM (context
, 0, port_height
);
1542 CGContextScaleCTM (context
, 1, -1);
1543 if (gc
->n_clip_rects
)
1544 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1548 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1551 mac_rect_make (f
, gx
, y
- FONT_BASE (GC_FONT (gc
)),
1552 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1554 CGContextScaleCTM (context
, 1, -1);
1555 CGContextTranslateCTM (context
, 0, -port_height
);
1559 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1560 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1561 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1562 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1563 CGContextSetShouldAntialias (context
, false);
1564 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1565 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1566 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1569 CGContextSetTextPosition (context
, gx
, gy
);
1570 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1573 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1574 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1577 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1578 else /* CGContextShowGlyphsWithAdvances == NULL */
1580 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1581 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1583 for (i
= 0; i
< nchars
; i
++)
1585 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1587 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1588 gx
+= advances
[i
].width
;
1593 mac_end_cg_clip (f
);
1595 CGContextSynchronize (context
);
1596 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1605 /* Mac replacement for XCopyArea: dest must be window. */
1608 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1613 unsigned int width
, height
;
1618 mac_begin_clip (f
, gc
);
1620 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1621 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1623 ForeColor (blackColor
);
1624 BackColor (whiteColor
);
1626 LockPixels (GetGWorldPixMap (src
));
1627 #if TARGET_API_MAC_CARBON
1632 LockPortBits (port
);
1633 CopyBits (GetPortBitMapForCopyBits (src
),
1634 GetPortBitMapForCopyBits (port
),
1635 &src_r
, &dest_r
, srcCopy
, 0);
1636 UnlockPortBits (port
);
1638 #else /* not TARGET_API_MAC_CARBON */
1639 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1640 &src_r
, &dest_r
, srcCopy
, 0);
1641 #endif /* not TARGET_API_MAC_CARBON */
1642 UnlockPixels (GetGWorldPixMap (src
));
1644 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1651 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1652 width
, height
, dest_x
, dest_y
)
1657 unsigned int width
, height
;
1662 mac_begin_clip (f
, gc
);
1664 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1665 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1667 ForeColor (blackColor
);
1668 BackColor (whiteColor
);
1670 LockPixels (GetGWorldPixMap (src
));
1671 LockPixels (GetGWorldPixMap (mask
));
1672 #if TARGET_API_MAC_CARBON
1677 LockPortBits (port
);
1678 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1679 GetPortBitMapForCopyBits (port
),
1680 &src_r
, &src_r
, &dest_r
);
1681 UnlockPortBits (port
);
1683 #else /* not TARGET_API_MAC_CARBON */
1684 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1685 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1686 #endif /* not TARGET_API_MAC_CARBON */
1687 UnlockPixels (GetGWorldPixMap (mask
));
1688 UnlockPixels (GetGWorldPixMap (src
));
1690 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1694 #endif /* !USE_CG_DRAWING */
1697 /* Mac replacement for XCopyArea: used only for scrolling. */
1700 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1704 unsigned int width
, height
;
1707 #if TARGET_API_MAC_CARBON
1709 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1711 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1713 mac_prepare_for_quickdraw (f
);
1715 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1716 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1717 kScrollWindowNoOptions
, dummy
);
1719 #else /* not TARGET_API_MAC_CARBON */
1721 WindowRef w
= FRAME_MAC_WINDOW (f
);
1723 mac_begin_clip (f
, gc
);
1725 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1726 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1728 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1729 color mapping in CopyBits. Otherwise, it will be slow. */
1730 ForeColor (blackColor
);
1731 BackColor (whiteColor
);
1732 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1734 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1737 #endif /* not TARGET_API_MAC_CARBON */
1741 /* Mac replacement for XChangeGC. */
1744 XChangeGC (display
, gc
, mask
, xgcv
)
1750 if (mask
& GCForeground
)
1751 XSetForeground (display
, gc
, xgcv
->foreground
);
1752 if (mask
& GCBackground
)
1753 XSetBackground (display
, gc
, xgcv
->background
);
1755 XSetFont (display
, gc
, xgcv
->font
);
1759 /* Mac replacement for XCreateGC. */
1762 XCreateGC (display
, d
, mask
, xgcv
)
1768 GC gc
= xmalloc (sizeof (*gc
));
1770 bzero (gc
, sizeof (*gc
));
1771 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1772 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1773 if (CGColorGetTypeID
!= NULL
)
1776 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1777 CGColorRetain (gc
->cg_fore_color
);
1778 CGColorRetain (gc
->cg_back_color
);
1781 XChangeGC (display
, gc
, mask
, xgcv
);
1787 /* Used in xfaces.c. */
1790 XFreeGC (display
, gc
)
1794 if (gc
->clip_region
)
1795 DisposeRgn (gc
->clip_region
);
1796 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1797 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1798 if (CGColorGetTypeID
!= NULL
)
1801 CGColorRelease (gc
->cg_fore_color
);
1802 CGColorRelease (gc
->cg_back_color
);
1809 /* Mac replacement for XGetGCValues. */
1812 XGetGCValues (display
, gc
, mask
, xgcv
)
1818 if (mask
& GCForeground
)
1819 xgcv
->foreground
= gc
->xgcv
.foreground
;
1820 if (mask
& GCBackground
)
1821 xgcv
->background
= gc
->xgcv
.background
;
1823 xgcv
->font
= gc
->xgcv
.font
;
1827 /* Mac replacement for XSetForeground. */
1830 XSetForeground (display
, gc
, color
)
1833 unsigned long color
;
1835 if (gc
->xgcv
.foreground
!= color
)
1837 gc
->xgcv
.foreground
= color
;
1838 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1839 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1840 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1841 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1842 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1843 if (CGColorGetTypeID
!= NULL
)
1846 CGColorRelease (gc
->cg_fore_color
);
1849 gc
->cg_fore_color
= mac_cg_color_black
;
1850 CGColorRetain (gc
->cg_fore_color
);
1856 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1857 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1858 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1860 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1868 /* Mac replacement for XSetBackground. */
1871 XSetBackground (display
, gc
, color
)
1874 unsigned long color
;
1876 if (gc
->xgcv
.background
!= color
)
1878 gc
->xgcv
.background
= color
;
1879 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1880 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1881 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1882 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1883 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1884 if (CGColorGetTypeID
!= NULL
)
1887 CGColorRelease (gc
->cg_back_color
);
1890 gc
->cg_back_color
= mac_cg_color_black
;
1891 CGColorRetain (gc
->cg_back_color
);
1897 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1898 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1899 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1901 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1909 /* Mac replacement for XSetFont. */
1912 XSetFont (display
, gc
, font
)
1917 gc
->xgcv
.font
= font
;
1921 /* Mac replacement for XSetClipRectangles. */
1924 mac_set_clip_rectangles (f
, gc
, rectangles
, n
)
1932 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1934 gc
->n_clip_rects
= n
;
1937 if (gc
->clip_region
== NULL
)
1938 gc
->clip_region
= NewRgn ();
1939 RectRgn (gc
->clip_region
, rectangles
);
1942 RgnHandle region
= NewRgn ();
1944 for (i
= 1; i
< n
; i
++)
1946 RectRgn (region
, rectangles
+ i
);
1947 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1949 DisposeRgn (region
);
1952 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1953 for (i
= 0; i
< n
; i
++)
1955 Rect
*rect
= rectangles
+ i
;
1957 gc
->clip_rects
[i
] = mac_rect_make (f
, rect
->left
, rect
->top
,
1958 rect
->right
- rect
->left
,
1959 rect
->bottom
- rect
->top
);
1965 /* Mac replacement for XSetClipMask. */
1968 mac_reset_clip_rectangles (f
, gc
)
1972 gc
->n_clip_rects
= 0;
1976 /* Mac replacement for XSetWindowBackground. */
1979 XSetWindowBackground (display
, w
, color
)
1982 unsigned long color
;
1984 #if !TARGET_API_MAC_CARBON
1985 AuxWinHandle aw_handle
;
1986 CTabHandle ctab_handle
;
1987 ColorSpecPtr ct_table
;
1992 bg_color
.red
= RED16_FROM_ULONG (color
);
1993 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1994 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1996 #if TARGET_API_MAC_CARBON
1997 SetWindowContentColor (w
, &bg_color
);
1999 if (GetAuxWin (w
, &aw_handle
))
2001 ctab_handle
= (*aw_handle
)->awCTable
;
2002 HandToHand ((Handle
*) &ctab_handle
);
2003 ct_table
= (*ctab_handle
)->ctTable
;
2004 ct_size
= (*ctab_handle
)->ctSize
;
2005 while (ct_size
> -1)
2007 if (ct_table
->value
== 0)
2009 ct_table
->rgb
= bg_color
;
2010 CTabChanged (ctab_handle
);
2011 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
2019 /* Flush display of frame F, or of all frames if F is null. */
2025 #if TARGET_API_MAC_CARBON
2028 mac_prepare_for_quickdraw (f
);
2031 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
2033 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
2039 /* Remove calls to XFlush by defining XFlush to an empty replacement.
2040 Calls to XFlush should be unnecessary because the X output buffer
2041 is flushed automatically as needed by calls to XPending,
2042 XNextEvent, or XWindowEvent according to the XFlush man page.
2043 XTread_socket calls XPending. Removing XFlush improves
2046 #define XFlush(DISPLAY) (void) 0
2050 mac_flush_display_optional (f
)
2054 mac_prepare_for_quickdraw (f
);
2059 /***********************************************************************
2060 Starting and ending an update
2061 ***********************************************************************/
2063 /* Start an update of frame F. This function is installed as a hook
2064 for update_begin, i.e. it is called when update_begin is called.
2065 This function is called prior to calls to x_update_window_begin for
2066 each window being updated. */
2072 #if TARGET_API_MAC_CARBON
2073 /* During update of a frame, availability of input events is
2074 periodically checked with ReceiveNextEvent if
2075 redisplay-dont-pause is nil. That normally flushes window buffer
2076 changes for every check, and thus screen update looks waving even
2077 if no input is available. So we disable screen updates during
2078 update of a frame. */
2080 DisableScreenUpdates ();
2086 /* Start update of window W. Set the global variable updated_window
2087 to the window being updated and set output_cursor to the cursor
2091 x_update_window_begin (w
)
2094 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2095 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
2098 set_output_cursor (&w
->cursor
);
2102 if (f
== display_info
->mouse_face_mouse_frame
)
2104 /* Don't do highlighting for mouse motion during the update. */
2105 display_info
->mouse_face_defer
= 1;
2107 /* If F needs to be redrawn, simply forget about any prior mouse
2109 if (FRAME_GARBAGED_P (f
))
2110 display_info
->mouse_face_window
= Qnil
;
2112 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
2113 their mouse_face_p flag set, which means that they are always
2114 unequal to rows in a desired matrix which never have that
2115 flag set. So, rows containing mouse-face glyphs are never
2116 scrolled, and we don't have to switch the mouse highlight off
2117 here to prevent it from being scrolled. */
2119 /* Can we tell that this update does not affect the window
2120 where the mouse highlight is? If so, no need to turn off.
2121 Likewise, don't do anything if the frame is garbaged;
2122 in that case, the frame's current matrix that we would use
2123 is all wrong, and we will redisplay that line anyway. */
2124 if (!NILP (display_info
->mouse_face_window
)
2125 && w
== XWINDOW (display_info
->mouse_face_window
))
2129 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2130 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2133 if (i
< w
->desired_matrix
->nrows
)
2134 clear_mouse_face (display_info
);
2143 /* Draw a vertical window border from (x,y0) to (x,y1) */
2146 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2150 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2153 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2155 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2158 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2161 /* End update of window W (which is equal to updated_window).
2163 Draw vertical borders between horizontally adjacent windows, and
2164 display W's cursor if CURSOR_ON_P is non-zero.
2166 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2167 glyphs in mouse-face were overwritten. In that case we have to
2168 make sure that the mouse-highlight is properly redrawn.
2170 W may be a menu bar pseudo-window in case we don't have X toolkit
2171 support. Such windows don't have a cursor, so don't display it
2175 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2177 int cursor_on_p
, mouse_face_overwritten_p
;
2179 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2181 if (!w
->pseudo_window_p
)
2186 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2188 output_cursor
.x
, output_cursor
.y
);
2190 if (draw_window_fringes (w
, 1))
2191 x_draw_vertical_border (w
);
2196 /* If a row with mouse-face was overwritten, arrange for
2197 XTframe_up_to_date to redisplay the mouse highlight. */
2198 if (mouse_face_overwritten_p
)
2200 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2201 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2202 dpyinfo
->mouse_face_window
= Qnil
;
2205 updated_window
= NULL
;
2209 /* End update of frame F. This function is installed as a hook in
2216 /* Mouse highlight may be displayed again. */
2217 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2220 #if TARGET_API_MAC_CARBON
2221 EnableScreenUpdates ();
2223 XFlush (FRAME_MAC_DISPLAY (f
));
2228 /* This function is called from various places in xdisp.c whenever a
2229 complete update has been performed. The global variable
2230 updated_window is not available here. */
2233 XTframe_up_to_date (f
)
2236 if (FRAME_MAC_P (f
))
2238 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2240 if (dpyinfo
->mouse_face_deferred_gc
2241 || f
== dpyinfo
->mouse_face_mouse_frame
)
2244 if (dpyinfo
->mouse_face_mouse_frame
)
2245 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2246 dpyinfo
->mouse_face_mouse_x
,
2247 dpyinfo
->mouse_face_mouse_y
);
2248 dpyinfo
->mouse_face_deferred_gc
= 0;
2255 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2256 arrow bitmaps, or clear the fringes if no bitmaps are required
2257 before DESIRED_ROW is made current. The window being updated is
2258 found in updated_window. This function is called from
2259 update_window_line only if it is known that there are differences
2260 between bitmaps to be drawn between current row and DESIRED_ROW. */
2263 x_after_update_window_line (desired_row
)
2264 struct glyph_row
*desired_row
;
2266 struct window
*w
= updated_window
;
2272 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2273 desired_row
->redraw_fringe_bitmaps_p
= 1;
2275 /* When a window has disappeared, make sure that no rest of
2276 full-width rows stays visible in the internal border. Could
2277 check here if updated_window is the leftmost/rightmost window,
2278 but I guess it's not worth doing since vertically split windows
2279 are almost never used, internal border is rarely set, and the
2280 overhead is very small. */
2281 if (windows_or_buffers_changed
2282 && desired_row
->full_width_p
2283 && (f
= XFRAME (w
->frame
),
2284 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2286 && (height
= desired_row
->visible_height
,
2289 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2291 /* Internal border is drawn below the tool bar. */
2292 if (WINDOWP (f
->tool_bar_window
)
2293 && w
== XWINDOW (f
->tool_bar_window
))
2297 mac_clear_area (f
, 0, y
, width
, height
);
2298 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2304 /* Draw the bitmap WHICH in one of the left or right fringes of
2305 window W. ROW is the glyph row for which to display the bitmap; it
2306 determines the vertical position at which the bitmap has to be
2310 x_draw_fringe_bitmap (w
, row
, p
)
2312 struct glyph_row
*row
;
2313 struct draw_fringe_bitmap_params
*p
;
2315 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2316 Display
*display
= FRAME_MAC_DISPLAY (f
);
2317 struct face
*face
= p
->face
;
2319 int overlay_p
= p
->overlay_p
;
2324 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2326 #if 0 /* MAC_TODO: stipple */
2327 /* In case the same realized face is used for fringes and
2328 for something displayed in the text (e.g. face `region' on
2329 mono-displays, the fill style may have been changed to
2330 FillSolid in x_draw_glyph_string_background. */
2332 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2334 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2337 /* If the fringe is adjacent to the left (right) scroll bar of a
2338 leftmost (rightmost, respectively) window, then extend its
2339 background to the gap between the fringe and the bar. */
2340 if ((WINDOW_LEFTMOST_P (w
)
2341 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2342 || (WINDOW_RIGHTMOST_P (w
)
2343 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2345 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2349 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2350 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2351 * FRAME_COLUMN_WIDTH (f
));
2354 && (left
+ width
== p
->x
2355 || p
->x
+ p
->wd
== left
))
2357 /* Bitmap fills the fringe and we need background
2359 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
2363 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
2365 ny
= row
->visible_height
;
2370 if (left
+ width
== bx
)
2372 bx
= left
+ sb_width
;
2373 nx
+= width
- sb_width
;
2375 else if (bx
+ nx
== left
)
2376 nx
+= width
- sb_width
;
2383 mac_erase_rectangle (f
, face
->gc
, bx
, by
, nx
, ny
);
2384 /* The fringe background has already been filled. */
2388 #if 0 /* MAC_TODO: stipple */
2390 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2393 #endif /* MAC_OSX */
2395 /* Must clip because of partially visible lines. */
2396 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2399 /* Adjust position of "bottom aligned" bitmap on partially
2400 visible last row. */
2402 int oldVH
= row
->visible_height
;
2403 row
->visible_height
= p
->h
;
2404 row
->y
-= rowY
- p
->y
;
2405 x_clip_to_row (w
, row
, -1, face
->gc
);
2407 row
->visible_height
= oldVH
;
2410 x_clip_to_row (w
, row
, -1, face
->gc
);
2413 if (p
->bx
>= 0 && !p
->overlay_p
)
2415 #if 0 /* MAC_TODO: stipple */
2416 /* In case the same realized face is used for fringes and
2417 for something displayed in the text (e.g. face `region' on
2418 mono-displays, the fill style may have been changed to
2419 FillSolid in x_draw_glyph_string_background. */
2421 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2423 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2426 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2428 #if 0 /* MAC_TODO: stipple */
2430 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2433 #endif /* !MAC_OSX */
2437 && p
->which
< max_fringe_bmp
2443 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2444 XSetForeground (display
, face
->gc
,
2446 ? (p
->overlay_p
? face
->background
2447 : f
->output_data
.mac
->cursor_pixel
)
2448 : face
->foreground
));
2450 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2451 p
->wd
, p
->h
, p
->x
, p
->y
, overlay_p
);
2453 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2454 p
->wd
, p
->h
, p
->bits
+ p
->dh
, overlay_p
);
2456 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2459 mac_reset_clip_rectangles (f
, face
->gc
);
2464 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2466 unsigned short *bits
;
2470 CGDataProviderRef provider
;
2472 if (which
>= max_fringe_bmp
)
2475 max_fringe_bmp
= which
+ 20;
2476 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2477 while (i
< max_fringe_bmp
)
2478 fringe_bmp
[i
++] = 0;
2481 for (i
= 0; i
< h
; i
++)
2486 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2487 sizeof (unsigned short) * h
, NULL
);
2490 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2491 sizeof (unsigned short),
2493 CGDataProviderRelease (provider
);
2500 mac_destroy_fringe_bitmap (which
)
2503 if (which
>= max_fringe_bmp
)
2506 if (fringe_bmp
[which
])
2509 CGImageRelease (fringe_bmp
[which
]);
2512 fringe_bmp
[which
] = 0;
2517 /* This is called when starting Emacs and when restarting after
2518 suspend. When starting Emacs, no window is mapped. And nothing
2519 must be done to Emacs's own window if it is suspended (though that
2523 XTset_terminal_modes (struct terminal
*t
)
2527 /* This is called when exiting or suspending Emacs. Exiting will make
2528 the windows go away, and suspending requires no action. */
2531 XTreset_terminal_modes (struct terminal
*t
)
2537 /***********************************************************************
2539 ***********************************************************************/
2541 /* Function prototypes of this page. */
2543 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2544 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
2545 struct charset
*, int *));
2549 pcm_init (pcm
, count
)
2553 bzero (pcm
, sizeof (XCharStruct
) * count
);
2554 while (--count
>= 0)
2556 pcm
->descent
= PCM_INVALID
;
2561 static enum pcm_status
2562 pcm_get_status (pcm
)
2563 const XCharStruct
*pcm
;
2565 int height
= pcm
->ascent
+ pcm
->descent
;
2567 /* Negative height means some special status. */
2568 return height
>= 0 ? PCM_VALID
: height
;
2571 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2572 is not contained in the font. */
2574 static INLINE XCharStruct
*
2575 x_per_char_metric (font
, char2b
)
2579 /* The result metric information. */
2580 XCharStruct
*pcm
= NULL
;
2582 xassert (font
&& char2b
);
2585 if (font
->mac_style
)
2587 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2591 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2592 pcm_init (*row
, 0x100);
2594 pcm
= *row
+ char2b
->byte2
;
2595 if (pcm_get_status (pcm
) != PCM_VALID
)
2598 mac_query_char_extents (font
->mac_style
,
2599 (char2b
->byte1
<< 8) + char2b
->byte2
,
2600 NULL
, NULL
, pcm
, NULL
);
2607 if (font
->bounds
.per_char
!= NULL
)
2609 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2611 /* min_char_or_byte2 specifies the linear character index
2612 corresponding to the first element of the per_char array,
2613 max_char_or_byte2 is the index of the last character. A
2614 character with non-zero CHAR2B->byte1 is not in the font.
2615 A character with byte2 less than min_char_or_byte2 or
2616 greater max_char_or_byte2 is not in the font. */
2617 if (char2b
->byte1
== 0
2618 && char2b
->byte2
>= font
->min_char_or_byte2
2619 && char2b
->byte2
<= font
->max_char_or_byte2
)
2620 pcm
= font
->bounds
.per_char
2621 + (char2b
->byte2
- font
->min_char_or_byte2
);
2625 /* If either min_byte1 or max_byte1 are nonzero, both
2626 min_char_or_byte2 and max_char_or_byte2 are less than
2627 256, and the 2-byte character index values corresponding
2628 to the per_char array element N (counting from 0) are:
2630 byte1 = N/D + min_byte1
2631 byte2 = N\D + min_char_or_byte2
2635 D = max_char_or_byte2 - min_char_or_byte2 + 1
2636 / = integer division
2637 \ = integer modulus */
2638 if (char2b
->byte1
>= font
->min_byte1
2639 && char2b
->byte1
<= font
->max_byte1
2640 && char2b
->byte2
>= font
->min_char_or_byte2
2641 && char2b
->byte2
<= font
->max_char_or_byte2
)
2643 pcm
= (font
->bounds
.per_char
2644 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2645 * (char2b
->byte1
- font
->min_byte1
))
2646 + (char2b
->byte2
- font
->min_char_or_byte2
));
2652 /* If the per_char pointer is null, all glyphs between the first
2653 and last character indexes inclusive have the same
2654 information, as given by both min_bounds and max_bounds. */
2655 if (char2b
->byte2
>= font
->min_char_or_byte2
2656 && char2b
->byte2
<= font
->max_char_or_byte2
)
2657 pcm
= &font
->max_bounds
;
2663 return ((pcm
== NULL
2665 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2666 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2675 static XCharStruct
*
2676 mac_per_char_metric (font
, char2b
, font_type
)
2681 return x_per_char_metric (font
, char2b
);
2685 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2686 the two-byte form of C. Encoding is returned in *CHAR2B. */
2689 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
2692 struct font_info
*font_info
;
2693 struct charset
*charset
;
2696 XFontStruct
*font
= font_info
->font
;
2698 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2699 This may be either a program in a special encoder language or a
2701 if (font_info
->font_encoder
)
2703 /* It's a program. */
2704 struct ccl_program
*ccl
= font_info
->font_encoder
;
2706 check_ccl_update (ccl
);
2707 if (CHARSET_DIMENSION (charset
) == 1)
2709 ccl
->reg
[0] = CHARSET_ID (charset
);
2710 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
2715 ccl
->reg
[0] = CHARSET_ID (charset
);
2716 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
2717 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
2720 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
2722 /* We assume that MSBs are appropriately set/reset by CCL
2724 if (font
->max_byte1
== 0) /* 1-byte font */
2725 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
2727 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
2729 else if (font_info
->encoding_type
)
2731 /* Fixed encoding scheme. See fontset.h for the meaning of the
2732 encoding numbers. */
2733 unsigned char enc
= font_info
->encoding_type
;
2735 if ((enc
== 1 || enc
== 2)
2736 && CHARSET_DIMENSION (charset
) == 2)
2737 char2b
->byte1
|= 0x80;
2739 if (enc
== 1 || enc
== 3)
2740 char2b
->byte2
|= 0x80;
2744 int code
= (char2b
->byte1
<< 8) | char2b
->byte2
;
2747 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
2752 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2754 return FONT_TYPE_UNKNOWN
;
2759 /***********************************************************************
2761 ***********************************************************************/
2765 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2766 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2767 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2769 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2770 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2771 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2772 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2773 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2774 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2775 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2776 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2777 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2778 unsigned long *, double, int));*/
2779 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2780 double, int, unsigned long));
2781 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2782 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2783 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2784 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2785 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2787 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2788 int, int, int, int, int, int,
2790 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2791 int, int, int, Rect
*));
2794 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2798 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2803 struct glyph_string
*s
;
2805 if (s
->font
== FRAME_FONT (s
->f
)
2806 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2807 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2809 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2812 /* Cursor on non-default face: must merge. */
2816 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2817 xgcv
.foreground
= s
->face
->background
;
2819 /* If the glyph would be invisible, try a different foreground. */
2820 if (xgcv
.foreground
== xgcv
.background
)
2821 xgcv
.foreground
= s
->face
->foreground
;
2822 if (xgcv
.foreground
== xgcv
.background
)
2823 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2824 if (xgcv
.foreground
== xgcv
.background
)
2825 xgcv
.foreground
= s
->face
->foreground
;
2827 /* Make sure the cursor is distinct from text in this face. */
2828 if (xgcv
.background
== s
->face
->background
2829 && xgcv
.foreground
== s
->face
->foreground
)
2831 xgcv
.background
= s
->face
->foreground
;
2832 xgcv
.foreground
= s
->face
->background
;
2835 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2836 xgcv
.font
= s
->font
;
2837 mask
= GCForeground
| GCBackground
| GCFont
;
2839 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2840 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2843 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2844 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2846 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2851 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2854 x_set_mouse_face_gc (s
)
2855 struct glyph_string
*s
;
2860 /* What face has to be used last for the mouse face? */
2861 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2862 face
= FACE_FROM_ID (s
->f
, face_id
);
2864 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2866 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2867 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
2869 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
2870 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2871 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2873 /* If font in this face is same as S->font, use it. */
2874 if (s
->font
== s
->face
->font
)
2875 s
->gc
= s
->face
->gc
;
2878 /* Otherwise construct scratch_cursor_gc with values from FACE
2883 xgcv
.background
= s
->face
->background
;
2884 xgcv
.foreground
= s
->face
->foreground
;
2885 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2886 xgcv
.font
= s
->font
;
2887 mask
= GCForeground
| GCBackground
| GCFont
;
2889 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2890 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2893 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2894 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2896 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2899 xassert (s
->gc
!= 0);
2903 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2904 Faces to use in the mode line have already been computed when the
2905 matrix was built, so there isn't much to do, here. */
2908 x_set_mode_line_face_gc (s
)
2909 struct glyph_string
*s
;
2911 s
->gc
= s
->face
->gc
;
2915 /* Set S->gc of glyph string S for drawing that glyph string. Set
2916 S->stippled_p to a non-zero value if the face of S has a stipple
2920 x_set_glyph_string_gc (s
)
2921 struct glyph_string
*s
;
2923 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2925 if (s
->hl
== DRAW_NORMAL_TEXT
)
2927 s
->gc
= s
->face
->gc
;
2928 s
->stippled_p
= s
->face
->stipple
!= 0;
2930 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2932 x_set_mode_line_face_gc (s
);
2933 s
->stippled_p
= s
->face
->stipple
!= 0;
2935 else if (s
->hl
== DRAW_CURSOR
)
2937 x_set_cursor_gc (s
);
2940 else if (s
->hl
== DRAW_MOUSE_FACE
)
2942 x_set_mouse_face_gc (s
);
2943 s
->stippled_p
= s
->face
->stipple
!= 0;
2945 else if (s
->hl
== DRAW_IMAGE_RAISED
2946 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2948 s
->gc
= s
->face
->gc
;
2949 s
->stippled_p
= s
->face
->stipple
!= 0;
2953 s
->gc
= s
->face
->gc
;
2954 s
->stippled_p
= s
->face
->stipple
!= 0;
2957 /* GC must have been set. */
2958 xassert (s
->gc
!= 0);
2962 /* Set clipping for output of glyph string S. S may be part of a mode
2963 line or menu if we don't have X toolkit support. */
2966 x_set_glyph_string_clipping (s
)
2967 struct glyph_string
*s
;
2969 Rect rects
[MAX_CLIP_RECTS
];
2972 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2973 mac_set_clip_rectangles (s
->f
, s
->gc
, rects
, n
);
2978 Compute left and right overhang of glyph string S. If S is a glyph
2979 string for a composition, assume overhangs don't exist. */
2982 mac_compute_glyph_string_overhangs (s
)
2983 struct glyph_string
*s
;
2985 if (!(s
->cmp
== NULL
2986 && s
->first_glyph
->type
== CHAR_GLYPH
))
2991 || s
->font
->mac_style
2997 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2998 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2999 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
3004 MacFontStruct
*font
= s
->font
;
3007 mac_prepare_for_quickdraw (s
->f
);
3009 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
3011 TextFont (font
->mac_fontnum
);
3012 TextSize (font
->mac_fontsize
);
3013 TextFace (font
->mac_fontface
);
3015 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
3017 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
3018 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
3023 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3026 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
3027 struct glyph_string
*s
;
3030 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
3034 /* Draw the background of glyph_string S. If S->background_filled_p
3035 is non-zero don't draw it. FORCE_P non-zero means draw the
3036 background even if it wouldn't be drawn normally. This is used
3037 when a string preceding S draws into the background of S, or S
3038 contains the first component of a composition. */
3041 x_draw_glyph_string_background (s
, force_p
)
3042 struct glyph_string
*s
;
3045 /* Nothing to do if background has already been drawn or if it
3046 shouldn't be drawn in the first place. */
3047 if (!s
->background_filled_p
)
3049 int box_line_width
= max (s
->face
->box_line_width
, 0);
3051 #if 0 /* MAC_TODO: stipple */
3054 /* Fill background with a stipple pattern. */
3055 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3056 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
3057 s
->y
+ box_line_width
,
3058 s
->background_width
,
3059 s
->height
- 2 * box_line_width
);
3060 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3061 s
->background_filled_p
= 1;
3065 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
3066 || s
->font_not_found_p
3067 || s
->extends_to_end_of_line_p
3070 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
3071 s
->background_width
,
3072 s
->height
- 2 * box_line_width
);
3073 s
->background_filled_p
= 1;
3079 /* Draw the foreground of glyph string S. */
3082 x_draw_glyph_string_foreground (s
)
3083 struct glyph_string
*s
;
3087 /* If first glyph of S has a left box line, start drawing the text
3088 of S to the right of that box line. */
3089 if (s
->face
->box
!= FACE_NO_BOX
3090 && s
->first_glyph
->left_box_line_p
)
3091 x
= s
->x
+ eabs (s
->face
->box_line_width
);
3095 /* Draw characters of S as rectangles if S's font could not be
3097 if (s
->font_not_found_p
)
3099 for (i
= 0; i
< s
->nchars
; ++i
)
3101 struct glyph
*g
= s
->first_glyph
+ i
;
3102 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3103 g
->pixel_width
- 1, s
->height
- 1);
3104 x
+= g
->pixel_width
;
3109 char *char1b
= (char *) s
->char2b
;
3110 int boff
= s
->font_info
->baseline_offset
;
3112 if (s
->font_info
->vertical_centering
)
3113 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3115 /* If we can use 8-bit functions, condense S->char2b. */
3118 && GC_FONT (s
->gc
)->mac_style
== NULL
3121 for (i
= 0; i
< s
->nchars
; ++i
)
3122 char1b
[i
] = s
->char2b
[i
].byte2
;
3124 /* Draw text with XDrawString if background has already been
3125 filled. Otherwise, use XDrawImageString. (Note that
3126 XDrawImageString is usually faster than XDrawString.) Always
3127 use XDrawImageString when drawing the cursor so that there is
3128 no chance that characters under a box cursor are invisible. */
3130 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3131 bg_width
= 0; /* Corresponds to XDrawString. */
3133 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
3137 || GC_FONT (s
->gc
)->mac_style
3140 #if USE_CG_TEXT_DRAWING
3142 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3143 s
->char2b
, s
->nchars
, bg_width
,
3144 s
->face
->overstrike
))
3148 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3149 s
->char2b
, s
->nchars
, bg_width
,
3150 s
->face
->overstrike
);
3152 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3153 char1b
, s
->nchars
, bg_width
,
3154 s
->face
->overstrike
);
3158 /* Draw the foreground of composite glyph string S. */
3161 x_draw_composite_glyph_string_foreground (s
)
3162 struct glyph_string
*s
;
3166 /* If first glyph of S has a left box line, start drawing the text
3167 of S to the right of that box line. */
3168 if (s
->face
->box
!= FACE_NO_BOX
3169 && s
->first_glyph
->left_box_line_p
)
3170 x
= s
->x
+ eabs (s
->face
->box_line_width
);
3174 /* S is a glyph string for a composition. S->gidx is the index of
3175 the first character drawn for glyphs of this composition.
3176 S->gidx == 0 means we are drawing the very first character of
3177 this composition. */
3179 /* Draw a rectangle for the composition if the font for the very
3180 first character of the composition could not be loaded. */
3181 if (s
->font_not_found_p
)
3184 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3185 s
->width
- 1, s
->height
- 1);
3189 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3190 if (mac_per_char_metric (GC_FONT (s
->gc
), s
->char2b
+ i
, 0) == NULL
)
3191 /* This is a nonexistent or zero-width glyph such as a
3192 combining diacritic. Draw a rectangle. */
3193 mac_draw_rectangle (s
->f
, s
->gc
,
3194 x
+ s
->cmp
->offsets
[s
->gidx
* 2], s
->y
,
3195 FONT_WIDTH (GC_FONT (s
->gc
)) - 1, s
->height
- 1);
3197 mac_draw_image_string_16 (s
->f
, s
->gc
,
3198 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3199 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3200 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3205 #ifdef USE_X_TOOLKIT
3207 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3210 /* Return the frame on which widget WIDGET is used.. Abort if frame
3211 cannot be determined. */
3213 static struct frame
*
3214 x_frame_of_widget (widget
)
3217 struct x_display_info
*dpyinfo
;
3221 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3223 /* Find the top-level shell of the widget. Note that this function
3224 can be called when the widget is not yet realized, so XtWindow
3225 (widget) == 0. That's the reason we can't simply use
3226 x_any_window_to_frame. */
3227 while (!XtIsTopLevelShell (widget
))
3228 widget
= XtParent (widget
);
3230 /* Look for a frame with that top-level widget. Allocate the color
3231 on that frame to get the right gamma correction value. */
3232 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
3233 if (FRAMEP (XCAR (tail
))
3234 && (f
= XFRAME (XCAR (tail
)),
3235 (f
->output_data
.nothing
!= 1
3236 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3237 && f
->output_data
.x
->widget
== widget
)
3244 /* Allocate the color COLOR->pixel on the screen and display of
3245 widget WIDGET in colormap CMAP. If an exact match cannot be
3246 allocated, try the nearest color available. Value is non-zero
3247 if successful. This is called from lwlib. */
3250 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3255 struct frame
*f
= x_frame_of_widget (widget
);
3256 return x_alloc_nearest_color (f
, cmap
, color
);
3260 #endif /* USE_X_TOOLKIT */
3262 #if 0 /* MAC_TODO */
3264 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3265 CMAP. If an exact match can't be allocated, try the nearest color
3266 available. Value is non-zero if successful. Set *COLOR to the
3270 x_alloc_nearest_color (f
, cmap
, color
)
3275 Display
*display
= FRAME_X_DISPLAY (f
);
3276 Screen
*screen
= FRAME_X_SCREEN (f
);
3279 gamma_correct (f
, color
);
3280 rc
= XAllocColor (display
, cmap
, color
);
3283 /* If we got to this point, the colormap is full, so we're going
3284 to try to get the next closest color. The algorithm used is
3285 a least-squares matching, which is what X uses for closest
3286 color matching with StaticColor visuals. */
3288 unsigned long nearest_delta
= ~0;
3289 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3290 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3292 for (i
= 0; i
< ncells
; ++i
)
3294 XQueryColors (display
, cmap
, cells
, ncells
);
3296 for (nearest
= i
= 0; i
< ncells
; ++i
)
3298 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3299 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3300 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3301 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3303 if (delta
< nearest_delta
)
3306 nearest_delta
= delta
;
3310 color
->red
= cells
[nearest
].red
;
3311 color
->green
= cells
[nearest
].green
;
3312 color
->blue
= cells
[nearest
].blue
;
3313 rc
= XAllocColor (display
, cmap
, color
);
3316 #ifdef DEBUG_X_COLORS
3318 register_color (color
->pixel
);
3319 #endif /* DEBUG_X_COLORS */
3325 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3326 It's necessary to do this instead of just using PIXEL directly to
3327 get color reference counts right. */
3330 x_copy_color (f
, pixel
)
3332 unsigned long pixel
;
3336 color
.pixel
= pixel
;
3338 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3339 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3341 #ifdef DEBUG_X_COLORS
3342 register_color (pixel
);
3348 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3349 It's necessary to do this instead of just using PIXEL directly to
3350 get color reference counts right. */
3353 x_copy_dpy_color (dpy
, cmap
, pixel
)
3356 unsigned long pixel
;
3360 color
.pixel
= pixel
;
3362 XQueryColor (dpy
, cmap
, &color
);
3363 XAllocColor (dpy
, cmap
, &color
);
3365 #ifdef DEBUG_X_COLORS
3366 register_color (pixel
);
3371 #endif /* MAC_TODO */
3374 /* Brightness beyond which a color won't have its highlight brightness
3377 Nominally, highlight colors for `3d' faces are calculated by
3378 brightening an object's color by a constant scale factor, but this
3379 doesn't yield good results for dark colors, so for colors who's
3380 brightness is less than this value (on a scale of 0-255) have to
3381 use an additional additive factor.
3383 The value here is set so that the default menu-bar/mode-line color
3384 (grey75) will not have its highlights changed at all. */
3385 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3388 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3389 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3390 If this produces the same color as COLOR, try a color where all RGB
3391 values have DELTA added. Return the allocated color in *COLOR.
3392 DISPLAY is the X display, CMAP is the colormap to operate on.
3393 Value is non-zero if successful. */
3396 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3398 unsigned long *color
;
3405 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3408 /* Change RGB values by specified FACTOR. Avoid overflow! */
3409 xassert (factor
>= 0);
3410 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3411 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3412 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3414 /* Calculate brightness of COLOR. */
3415 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3416 + BLUE_FROM_ULONG (*color
)) / 6;
3418 /* We only boost colors that are darker than
3419 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3420 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3421 /* Make an additive adjustment to NEW, because it's dark enough so
3422 that scaling by FACTOR alone isn't enough. */
3424 /* How far below the limit this color is (0 - 1, 1 being darker). */
3425 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3426 /* The additive adjustment. */
3427 int min_delta
= delta
* dimness
* factor
/ 2;
3430 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3431 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3432 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3434 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3435 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3436 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3440 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3441 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3442 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3444 /* MAC_TODO: Map to palette and retry with delta if same? */
3445 /* MAC_TODO: Free colors (if using palette)? */
3456 /* Set up the foreground color for drawing relief lines of glyph
3457 string S. RELIEF is a pointer to a struct relief containing the GC
3458 with which lines will be drawn. Use a color that is FACTOR or
3459 DELTA lighter or darker than the relief's background which is found
3460 in S->f->output_data.x->relief_background. If such a color cannot
3461 be allocated, use DEFAULT_PIXEL, instead. */
3464 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3466 struct relief
*relief
;
3469 unsigned long default_pixel
;
3472 struct mac_output
*di
= f
->output_data
.mac
;
3473 unsigned long mask
= GCForeground
;
3474 unsigned long pixel
;
3475 unsigned long background
= di
->relief_background
;
3476 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3478 /* MAC_TODO: Free colors (if using palette)? */
3480 /* Allocate new color. */
3481 xgcv
.foreground
= default_pixel
;
3483 if (dpyinfo
->n_planes
!= 1
3484 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3486 relief
->allocated_p
= 1;
3487 xgcv
.foreground
= relief
->pixel
= pixel
;
3490 if (relief
->gc
== 0)
3492 #if 0 /* MAC_TODO: stipple */
3493 xgcv
.stipple
= dpyinfo
->gray
;
3496 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3499 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3503 /* Set up colors for the relief lines around glyph string S. */
3506 x_setup_relief_colors (s
)
3507 struct glyph_string
*s
;
3509 struct mac_output
*di
= s
->f
->output_data
.mac
;
3510 unsigned long color
;
3512 if (s
->face
->use_box_color_for_shadows_p
)
3513 color
= s
->face
->box_color
;
3514 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3516 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3517 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3522 /* Get the background color of the face. */
3523 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3524 color
= xgcv
.background
;
3527 if (di
->white_relief
.gc
== 0
3528 || color
!= di
->relief_background
)
3530 di
->relief_background
= color
;
3531 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3532 WHITE_PIX_DEFAULT (s
->f
));
3533 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3534 BLACK_PIX_DEFAULT (s
->f
));
3539 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3540 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3541 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3542 relief. LEFT_P non-zero means draw a relief on the left side of
3543 the rectangle. RIGHT_P non-zero means draw a relief on the right
3544 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3548 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3549 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3551 int left_x
, top_y
, right_x
, bottom_y
, width
;
3552 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3555 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3560 gc
= f
->output_data
.mac
->white_relief
.gc
;
3562 gc
= f
->output_data
.mac
->black_relief
.gc
;
3563 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3567 for (i
= 0; i
< width
; ++i
)
3568 mac_draw_line (f
, gc
,
3569 left_x
+ i
* left_p
, top_y
+ i
,
3570 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3574 for (i
= 0; i
< width
; ++i
)
3575 mac_draw_line (f
, gc
,
3576 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3578 mac_reset_clip_rectangles (f
, gc
);
3580 gc
= f
->output_data
.mac
->black_relief
.gc
;
3582 gc
= f
->output_data
.mac
->white_relief
.gc
;
3583 mac_set_clip_rectangles (f
, gc
, clip_rect
, 1);
3587 for (i
= 0; i
< width
; ++i
)
3588 mac_draw_line (f
, gc
,
3589 left_x
+ i
* left_p
, bottom_y
- i
,
3590 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3594 for (i
= 0; i
< width
; ++i
)
3595 mac_draw_line (f
, gc
,
3596 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3598 mac_reset_clip_rectangles (f
, gc
);
3602 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3603 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3604 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3605 left side of the rectangle. RIGHT_P non-zero means draw a line
3606 on the right side of the rectangle. CLIP_RECT is the clipping
3607 rectangle to use when drawing. */
3610 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3611 left_p
, right_p
, clip_rect
)
3612 struct glyph_string
*s
;
3613 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3618 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3619 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3620 mac_set_clip_rectangles (s
->f
, s
->gc
, clip_rect
, 1);
3623 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3624 right_x
- left_x
+ 1, width
);
3628 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3629 width
, bottom_y
- top_y
+ 1);
3632 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3633 right_x
- left_x
+ 1, width
);
3637 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3638 top_y
, width
, bottom_y
- top_y
+ 1);
3640 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3641 mac_reset_clip_rectangles (s
->f
, s
->gc
);
3645 /* Draw a box around glyph string S. */
3648 x_draw_glyph_string_box (s
)
3649 struct glyph_string
*s
;
3651 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3652 int left_p
, right_p
;
3653 struct glyph
*last_glyph
;
3656 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3657 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3658 : window_box_right (s
->w
, s
->area
));
3660 /* The glyph that may have a right box line. */
3661 last_glyph
= (s
->cmp
|| s
->img
3663 : s
->first_glyph
+ s
->nchars
- 1);
3665 width
= eabs (s
->face
->box_line_width
);
3666 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3668 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3670 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3672 bottom_y
= top_y
+ s
->height
- 1;
3674 left_p
= (s
->first_glyph
->left_box_line_p
3675 || (s
->hl
== DRAW_MOUSE_FACE
3677 || s
->prev
->hl
!= s
->hl
)));
3678 right_p
= (last_glyph
->right_box_line_p
3679 || (s
->hl
== DRAW_MOUSE_FACE
3681 || s
->next
->hl
!= s
->hl
)));
3683 get_glyph_string_clip_rect (s
, &clip_rect
);
3685 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3686 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3687 left_p
, right_p
, &clip_rect
);
3690 x_setup_relief_colors (s
);
3691 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3692 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3697 /* Draw foreground of image glyph string S. */
3700 x_draw_image_foreground (s
)
3701 struct glyph_string
*s
;
3704 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3706 /* If first glyph of S has a left box line, start drawing it to the
3707 right of that line. */
3708 if (s
->face
->box
!= FACE_NO_BOX
3709 && s
->first_glyph
->left_box_line_p
3711 x
+= eabs (s
->face
->box_line_width
);
3713 /* If there is a margin around the image, adjust x- and y-position
3715 if (s
->slice
.x
== 0)
3716 x
+= s
->img
->hmargin
;
3717 if (s
->slice
.y
== 0)
3718 y
+= s
->img
->vmargin
;
3722 x_set_glyph_string_clipping (s
);
3725 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3726 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3727 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3731 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3732 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3733 s
->slice
.width
, s
->slice
.height
, x
, y
);
3740 mac_copy_area (s
->img
->pixmap
,
3741 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3742 s
->slice
.width
, s
->slice
.height
, x
, y
);
3745 /* When the image has a mask, we can expect that at
3746 least part of a mouse highlight or a block cursor will
3747 be visible. If the image doesn't have a mask, make
3748 a block cursor visible by drawing a rectangle around
3749 the image. I believe it's looking better if we do
3750 nothing here for mouse-face. */
3751 if (s
->hl
== DRAW_CURSOR
)
3753 int r
= s
->img
->relief
;
3755 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3756 s
->slice
.width
+ r
*2 - 1,
3757 s
->slice
.height
+ r
*2 - 1);
3762 /* Draw a rectangle if image could not be loaded. */
3763 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3764 s
->slice
.width
- 1, s
->slice
.height
- 1);
3768 /* Draw a relief around the image glyph string S. */
3771 x_draw_image_relief (s
)
3772 struct glyph_string
*s
;
3774 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3777 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3779 /* If first glyph of S has a left box line, start drawing it to the
3780 right of that line. */
3781 if (s
->face
->box
!= FACE_NO_BOX
3782 && s
->first_glyph
->left_box_line_p
3784 x
+= eabs (s
->face
->box_line_width
);
3786 /* If there is a margin around the image, adjust x- and y-position
3788 if (s
->slice
.x
== 0)
3789 x
+= s
->img
->hmargin
;
3790 if (s
->slice
.y
== 0)
3791 y
+= s
->img
->vmargin
;
3793 if (s
->hl
== DRAW_IMAGE_SUNKEN
3794 || s
->hl
== DRAW_IMAGE_RAISED
)
3796 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3797 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3801 thick
= eabs (s
->img
->relief
);
3802 raised_p
= s
->img
->relief
> 0;
3807 x1
= x
+ s
->slice
.width
+ thick
- 1;
3808 y1
= y
+ s
->slice
.height
+ thick
- 1;
3810 x_setup_relief_colors (s
);
3811 get_glyph_string_clip_rect (s
, &r
);
3812 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3814 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3816 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3821 /* Draw part of the background of glyph string S. X, Y, W, and H
3822 give the rectangle to draw. */
3825 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3826 struct glyph_string
*s
;
3829 #if 0 /* MAC_TODO: stipple */
3832 /* Fill background with a stipple pattern. */
3833 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3834 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3835 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3838 #endif /* MAC_TODO */
3839 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3843 /* Draw image glyph string S.
3846 s->x +-------------------------
3849 | +-------------------------
3852 | | +-------------------
3858 x_draw_image_glyph_string (s
)
3859 struct glyph_string
*s
;
3862 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
3863 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3866 height
= s
->height
- 2 * box_line_vwidth
;
3869 /* Fill background with face under the image. Do it only if row is
3870 taller than image or if image has a clip mask to reduce
3872 s
->stippled_p
= s
->face
->stipple
!= 0;
3873 if (height
> s
->slice
.height
3877 || s
->img
->pixmap
== 0
3878 || s
->width
!= s
->background_width
)
3881 if (s
->first_glyph
->left_box_line_p
3883 x
+= box_line_hwidth
;
3886 if (s
->slice
.y
== 0)
3887 y
+= box_line_vwidth
;
3889 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3891 s
->background_filled_p
= 1;
3894 /* Draw the foreground. */
3895 x_draw_image_foreground (s
);
3897 /* If we must draw a relief around the image, do it. */
3899 || s
->hl
== DRAW_IMAGE_RAISED
3900 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3901 x_draw_image_relief (s
);
3905 /* Draw stretch glyph string S. */
3908 x_draw_stretch_glyph_string (s
)
3909 struct glyph_string
*s
;
3911 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3913 if (s
->hl
== DRAW_CURSOR
3914 && !x_stretch_cursor_p
)
3916 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3917 as wide as the stretch glyph. */
3918 int width
, background_width
= s
->background_width
;
3919 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3923 background_width
-= left_x
- x
;
3926 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3929 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3931 /* Clear rest using the GC of the original non-cursor face. */
3932 if (width
< background_width
)
3935 int w
= background_width
- width
, h
= s
->height
;
3940 if (s
->row
->mouse_face_p
3941 && cursor_in_mouse_face_p (s
->w
))
3943 x_set_mouse_face_gc (s
);
3949 get_glyph_string_clip_rect (s
, &r
);
3950 mac_set_clip_rectangles (s
->f
, gc
, &r
, 1);
3952 #if 0 /* MAC_TODO: stipple */
3953 if (s
->face
->stipple
)
3955 /* Fill background with a stipple pattern. */
3956 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3957 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3958 XSetFillStyle (s
->display
, gc
, FillSolid
);
3961 #endif /* MAC_TODO */
3962 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3965 else if (!s
->background_filled_p
)
3967 int background_width
= s
->background_width
;
3968 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3970 /* Don't draw into left margin, fringe or scrollbar area
3971 except for header line and mode line. */
3972 if (x
< left_x
&& !s
->row
->mode_line_p
)
3974 background_width
-= left_x
- x
;
3977 if (background_width
> 0)
3978 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3981 s
->background_filled_p
= 1;
3985 /* Draw glyph string S. */
3988 x_draw_glyph_string (s
)
3989 struct glyph_string
*s
;
3991 int relief_drawn_p
= 0;
3993 /* If S draws into the background of its successor that does not
3994 draw a cursor, draw the background of the successor first so that
3995 S can draw into it. This makes S->next use XDrawString instead
3996 of XDrawImageString. */
3997 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3998 && s
->next
->hl
!= DRAW_CURSOR
)
4000 xassert (s
->next
->img
== NULL
);
4001 x_set_glyph_string_gc (s
->next
);
4002 x_set_glyph_string_clipping (s
->next
);
4003 x_draw_glyph_string_background (s
->next
, 1);
4006 /* Set up S->gc, set clipping and draw S. */
4007 x_set_glyph_string_gc (s
);
4009 /* Draw relief (if any) in advance for char/composition so that the
4010 glyph string can be drawn over it. */
4011 if (!s
->for_overlaps
4012 && s
->face
->box
!= FACE_NO_BOX
4013 && (s
->first_glyph
->type
== CHAR_GLYPH
4014 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
4017 x_set_glyph_string_clipping (s
);
4018 x_draw_glyph_string_background (s
, 1);
4019 x_draw_glyph_string_box (s
);
4020 x_set_glyph_string_clipping (s
);
4024 x_set_glyph_string_clipping (s
);
4026 switch (s
->first_glyph
->type
)
4029 x_draw_image_glyph_string (s
);
4033 x_draw_stretch_glyph_string (s
);
4037 if (s
->for_overlaps
)
4038 s
->background_filled_p
= 1;
4040 x_draw_glyph_string_background (s
, 0);
4041 x_draw_glyph_string_foreground (s
);
4044 case COMPOSITE_GLYPH
:
4045 if (s
->for_overlaps
|| s
->gidx
> 0)
4046 s
->background_filled_p
= 1;
4048 x_draw_glyph_string_background (s
, 1);
4049 x_draw_composite_glyph_string_foreground (s
);
4056 if (!s
->for_overlaps
)
4058 /* Draw underline. */
4059 if (s
->face
->underline_p
)
4061 unsigned long tem
, h
;
4065 /* Get the underline thickness. Default is 1 pixel. */
4066 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
4070 y
= s
->y
+ s
->height
- h
;
4071 if (!x_underline_at_descent_line
)
4073 /* Get the underline position. This is the recommended
4074 vertical offset in pixels from the baseline to the top of
4075 the underline. This is a signed value according to the
4076 specs, and its default is
4078 ROUND ((maximum descent) / 2), with
4079 ROUND(x) = floor (x + 0.5) */
4082 if (x_use_underline_position_properties
4083 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
4084 y
= s
->ybase
+ (long) tem
;
4088 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
4091 if (s
->face
->underline_defaulted_p
)
4092 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
4093 s
->background_width
, h
);
4097 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4098 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4099 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
4100 s
->background_width
, h
);
4101 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4105 /* Draw overline. */
4106 if (s
->face
->overline_p
)
4108 unsigned long dy
= 0, h
= 1;
4110 if (s
->face
->overline_color_defaulted_p
)
4111 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4112 s
->background_width
, h
);
4116 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4117 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4118 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4119 s
->background_width
, h
);
4120 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4124 /* Draw strike-through. */
4125 if (s
->face
->strike_through_p
)
4127 unsigned long h
= 1;
4128 unsigned long dy
= (s
->height
- h
) / 2;
4130 if (s
->face
->strike_through_color_defaulted_p
)
4131 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4136 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4137 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4138 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4140 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4144 /* Draw relief if not yet drawn. */
4145 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4146 x_draw_glyph_string_box (s
);
4149 /* Reset clipping. */
4150 mac_reset_clip_rectangles (s
->f
, s
->gc
);
4153 /* Shift display to make room for inserted glyphs. */
4156 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4158 int x
, y
, width
, height
, shift_by
;
4160 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4161 x
, y
, width
, height
,
4165 /* Delete N glyphs at the nominal cursor position. Not implemented
4176 /* Clear entire frame. If updating_frame is non-null, clear that
4177 frame. Otherwise clear the selected frame. */
4180 x_clear_frame (struct frame
*f
)
4182 /* Clearing the frame will erase any cursor, so mark them all as no
4184 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4185 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4186 output_cursor
.x
= -1;
4188 /* We don't set the output cursor here because there will always
4189 follow an explicit cursor_to. */
4191 mac_clear_window (f
);
4193 /* We have to clear the scroll bars, too. If we have changed
4194 colors or something like that, then they should be notified. */
4195 x_scroll_bar_clear (f
);
4197 XFlush (FRAME_MAC_DISPLAY (f
));
4203 /* Invert the middle quarter of the frame for .15 sec. */
4205 /* We use the select system call to do the waiting, so we have to make
4206 sure it's available. If it isn't, we just won't do visual bells. */
4208 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4211 /* Subtract the `struct timeval' values X and Y, storing the result in
4212 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4215 timeval_subtract (result
, x
, y
)
4216 struct timeval
*result
, x
, y
;
4218 /* Perform the carry for the later subtraction by updating y. This
4219 is safer because on some systems the tv_sec member is unsigned. */
4220 if (x
.tv_usec
< y
.tv_usec
)
4222 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4223 y
.tv_usec
-= 1000000 * nsec
;
4227 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4229 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4230 y
.tv_usec
+= 1000000 * nsec
;
4234 /* Compute the time remaining to wait. tv_usec is certainly
4236 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4237 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4239 /* Return indication of whether the result should be considered
4241 return x
.tv_sec
< y
.tv_sec
;
4248 /* Get the height not including a menu bar widget. */
4249 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4250 /* Height of each line to flash. */
4251 int flash_height
= FRAME_LINE_HEIGHT (f
);
4252 /* These will be the left and right margins of the rectangles. */
4253 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4254 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4258 /* Don't flash the area between a scroll bar and the frame
4259 edge it is next to. */
4260 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4262 case vertical_scroll_bar_left
:
4263 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4266 case vertical_scroll_bar_right
:
4267 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4274 width
= flash_right
- flash_left
;
4278 /* If window is tall, flash top and bottom line. */
4279 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4281 mac_invert_rectangle (f
, flash_left
,
4282 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4283 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4284 width
, flash_height
);
4285 mac_invert_rectangle (f
, flash_left
,
4286 (height
- flash_height
4287 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4288 width
, flash_height
);
4291 /* If it is short, flash it all. */
4292 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4293 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4298 struct timeval wakeup
;
4300 EMACS_GET_TIME (wakeup
);
4302 /* Compute time to wait until, propagating carry from usecs. */
4303 wakeup
.tv_usec
+= 150000;
4304 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4305 wakeup
.tv_usec
%= 1000000;
4307 /* Keep waiting until past the time wakeup or any input gets
4309 while (! detect_input_pending ())
4311 struct timeval current
;
4312 struct timeval timeout
;
4314 EMACS_GET_TIME (current
);
4316 /* Break if result would be negative. */
4317 if (timeval_subtract (¤t
, wakeup
, current
))
4320 /* How long `select' should wait. */
4322 timeout
.tv_usec
= 10000;
4324 /* Try to wait that long--but we might wake up sooner. */
4325 select (0, NULL
, NULL
, NULL
, &timeout
);
4329 /* If window is tall, flash top and bottom line. */
4330 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4332 mac_invert_rectangle (f
, flash_left
,
4333 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4334 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4335 width
, flash_height
);
4336 mac_invert_rectangle (f
, flash_left
,
4337 (height
- flash_height
4338 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4339 width
, flash_height
);
4342 /* If it is short, flash it all. */
4343 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4344 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4351 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4354 /* Make audible bell. */
4359 struct frame
*f
= SELECTED_FRAME ();
4361 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4369 XFlush (FRAME_MAC_DISPLAY (f
));
4375 /* Specify how many text lines, from the top of the window,
4376 should be affected by insert-lines and delete-lines operations.
4377 This, and those operations, are used only within an update
4378 that is bounded by calls to x_update_begin and x_update_end. */
4381 XTset_terminal_window (n
)
4384 /* This function intentionally left blank. */
4389 /***********************************************************************
4391 ***********************************************************************/
4393 /* Perform an insert-lines or delete-lines operation, inserting N
4394 lines or deleting -N lines at vertical position VPOS. */
4397 x_ins_del_lines (vpos
, n
)
4404 /* Scroll part of the display as described by RUN. */
4407 x_scroll_run (w
, run
)
4411 struct frame
*f
= XFRAME (w
->frame
);
4412 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4414 /* Get frame-relative bounding box of the text display area of W,
4415 without mode lines. Include in this box the left and right
4417 window_box (w
, -1, &x
, &y
, &width
, &height
);
4419 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4420 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4421 bottom_y
= y
+ height
;
4425 /* Scrolling up. Make sure we don't copy part of the mode
4426 line at the bottom. */
4427 if (from_y
+ run
->height
> bottom_y
)
4428 height
= bottom_y
- from_y
;
4430 height
= run
->height
;
4434 /* Scolling down. Make sure we don't copy over the mode line.
4436 if (to_y
+ run
->height
> bottom_y
)
4437 height
= bottom_y
- to_y
;
4439 height
= run
->height
;
4444 /* Cursor off. Will be switched on again in x_update_window_end. */
4448 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4458 /***********************************************************************
4460 ***********************************************************************/
4467 x_update_cursor (f
, 1);
4471 frame_unhighlight (f
)
4474 x_update_cursor (f
, 1);
4477 /* The focus has changed. Update the frames as necessary to reflect
4478 the new situation. Note that we can't change the selected frame
4479 here, because the Lisp code we are interrupting might become confused.
4480 Each event gets marked with the frame in which it occurred, so the
4481 Lisp code can tell when the switch took place by examining the events. */
4484 x_new_focus_frame (dpyinfo
, frame
)
4485 struct x_display_info
*dpyinfo
;
4486 struct frame
*frame
;
4488 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4490 if (frame
!= dpyinfo
->x_focus_frame
)
4492 /* Set this before calling other routines, so that they see
4493 the correct value of x_focus_frame. */
4494 dpyinfo
->x_focus_frame
= frame
;
4496 if (old_focus
&& old_focus
->auto_lower
)
4497 x_lower_frame (old_focus
);
4500 selected_frame
= frame
;
4501 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4503 Fselect_window (selected_frame
->selected_window
, Qnil
);
4504 choose_minibuf_frame ();
4507 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4508 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4510 pending_autoraise_frame
= 0;
4512 #if USE_MAC_FONT_PANEL
4514 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4518 x_frame_rehighlight (dpyinfo
);
4521 /* Handle FocusIn and FocusOut state changes for FRAME.
4522 If FRAME has focus and there exists more than one frame, puts
4523 a FOCUS_IN_EVENT into *BUFP. */
4526 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4528 struct mac_display_info
*dpyinfo
;
4529 struct frame
*frame
;
4530 struct input_event
*bufp
;
4532 if (type
== activeFlag
)
4534 if (dpyinfo
->x_focus_event_frame
!= frame
)
4536 x_new_focus_frame (dpyinfo
, frame
);
4537 dpyinfo
->x_focus_event_frame
= frame
;
4539 /* Don't stop displaying the initial startup message
4540 for a switch-frame event we don't need. */
4541 if (NILP (Vterminal_frame
)
4542 && CONSP (Vframe_list
)
4543 && !NILP (XCDR (Vframe_list
)))
4545 bufp
->kind
= FOCUS_IN_EVENT
;
4546 XSETFRAME (bufp
->frame_or_window
, frame
);
4552 if (dpyinfo
->x_focus_event_frame
== frame
)
4554 dpyinfo
->x_focus_event_frame
= 0;
4555 x_new_focus_frame (dpyinfo
, 0);
4560 /* The focus may have changed. Figure out if it is a real focus change,
4561 by checking both FocusIn/Out and Enter/LeaveNotify events.
4563 Returns FOCUS_IN_EVENT event in *BUFP. */
4566 x_detect_focus_change (dpyinfo
, event
, bufp
)
4567 struct mac_display_info
*dpyinfo
;
4568 const EventRecord
*event
;
4569 struct input_event
*bufp
;
4571 struct frame
*frame
;
4573 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4577 /* On Mac, this is only called from focus events, so no switch needed. */
4578 mac_focus_changed ((event
->modifiers
& activeFlag
),
4579 dpyinfo
, frame
, bufp
);
4583 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4586 x_mouse_leave (dpyinfo
)
4587 struct x_display_info
*dpyinfo
;
4589 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4592 /* The focus has changed, or we have redirected a frame's focus to
4593 another frame (this happens when a frame uses a surrogate
4594 mini-buffer frame). Shift the highlight as appropriate.
4596 The FRAME argument doesn't necessarily have anything to do with which
4597 frame is being highlighted or un-highlighted; we only use it to find
4598 the appropriate X display info. */
4601 XTframe_rehighlight (frame
)
4602 struct frame
*frame
;
4604 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4608 x_frame_rehighlight (dpyinfo
)
4609 struct x_display_info
*dpyinfo
;
4611 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4613 if (dpyinfo
->x_focus_frame
)
4615 dpyinfo
->x_highlight_frame
4616 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4617 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4618 : dpyinfo
->x_focus_frame
);
4619 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4621 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4622 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4626 dpyinfo
->x_highlight_frame
= 0;
4628 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4631 frame_unhighlight (old_highlight
);
4632 if (dpyinfo
->x_highlight_frame
)
4633 frame_highlight (dpyinfo
->x_highlight_frame
);
4639 /* Convert a keysym to its name. */
4642 x_get_keysym_name (keysym
)
4649 value
= XKeysymToString (keysym
);
4660 /* Function to report a mouse movement to the mainstream Emacs code.
4661 The input handler calls this.
4663 We have received a mouse movement event, which is given in *event.
4664 If the mouse is over a different glyph than it was last time, tell
4665 the mainstream emacs code by setting mouse_moved. If not, ask for
4666 another motion event, so we can check again the next time it moves. */
4668 static Point last_mouse_motion_position
;
4669 static Lisp_Object last_mouse_motion_frame
;
4672 note_mouse_movement (frame
, pos
)
4676 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4677 #if TARGET_API_MAC_CARBON
4681 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4682 last_mouse_motion_position
= *pos
;
4683 XSETFRAME (last_mouse_motion_frame
, frame
);
4685 if (frame
== dpyinfo
->mouse_face_mouse_frame
4686 #if TARGET_API_MAC_CARBON
4687 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4689 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4693 /* This case corresponds to LeaveNotify in X11. If we move
4694 outside the frame, then we're certainly no longer on any text
4696 clear_mouse_face (dpyinfo
);
4697 dpyinfo
->mouse_face_mouse_frame
= 0;
4698 if (!dpyinfo
->grabbed
)
4699 FRAME_RIF (frame
)->define_frame_cursor (frame
,
4700 frame
->output_data
.mac
->nontext_cursor
);
4703 /* Has the mouse moved off the glyph it was on at the last sighting? */
4704 if (frame
!= last_mouse_glyph_frame
4705 || !PtInRect (*pos
, &last_mouse_glyph
))
4707 frame
->mouse_moved
= 1;
4708 last_mouse_scroll_bar
= Qnil
;
4709 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4710 /* Remember which glyph we're now on. */
4711 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4712 last_mouse_glyph_frame
= frame
;
4720 /************************************************************************
4722 ************************************************************************/
4724 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4727 redo_mouse_highlight ()
4729 if (!NILP (last_mouse_motion_frame
)
4730 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4731 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4732 last_mouse_motion_position
.h
,
4733 last_mouse_motion_position
.v
);
4737 static struct frame
*
4738 mac_focus_frame (dpyinfo
)
4739 struct mac_display_info
*dpyinfo
;
4741 if (dpyinfo
->x_focus_frame
)
4742 return dpyinfo
->x_focus_frame
;
4744 /* Mac version may get events, such as a menu bar click, even when
4745 all the frames are invisible. In this case, we regard the
4746 event came to the selected frame. */
4747 return SELECTED_FRAME ();
4751 /* Return the current position of the mouse.
4752 *FP should be a frame which indicates which display to ask about.
4754 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4755 and *PART to the frame, window, and scroll bar part that the mouse
4756 is over. Set *X and *Y to the portion and whole of the mouse's
4757 position on the scroll bar.
4759 If the mouse movement started elsewhere, set *FP to the frame the
4760 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4763 Set *TIME to the server time-stamp for the time at which the mouse
4764 was at this position.
4766 Don't store anything if we don't have a valid set of values to report.
4768 This clears the mouse_moved flag, so we can wait for the next mouse
4772 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4775 Lisp_Object
*bar_window
;
4776 enum scroll_bar_part
*part
;
4778 unsigned long *time
;
4784 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4785 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4788 Lisp_Object frame
, tail
;
4790 /* Clear the mouse-moved flag for every frame on this display. */
4791 FOR_EACH_FRAME (tail
, frame
)
4792 XFRAME (frame
)->mouse_moved
= 0;
4794 last_mouse_scroll_bar
= Qnil
;
4796 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4797 && FRAME_LIVE_P (last_mouse_frame
))
4798 f1
= last_mouse_frame
;
4800 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4804 /* Ok, we found a frame. Store all the values.
4805 last_mouse_glyph is a rectangle used to reduce the
4806 generation of mouse events. To not miss any motion
4807 events, we must divide the frame into rectangles of the
4808 size of the smallest character that could be displayed
4809 on it, i.e. into the same rectangles that matrices on
4810 the frame are divided into. */
4813 #if TARGET_API_MAC_CARBON
4814 GetGlobalMouse (&mouse_pos
);
4815 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4816 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4818 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4819 GetMouse (&mouse_pos
);
4821 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4823 last_mouse_glyph_frame
= f1
;
4828 XSETINT (*x
, mouse_pos
.h
);
4829 XSETINT (*y
, mouse_pos
.v
);
4830 *time
= last_mouse_movement_time
;
4838 /************************************************************************
4840 ************************************************************************/
4842 #ifdef USE_TOOLKIT_SCROLL_BARS
4844 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4845 static OSStatus install_scroll_bar_timer
P_ ((void));
4846 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4847 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4848 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4849 struct input_event
*));
4850 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4852 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4853 ControlPartCode
, Point
,
4854 struct input_event
*));
4855 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4856 struct input_event
*));
4857 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4858 Point
, struct input_event
*));
4859 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4862 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4864 static int last_scroll_bar_part
;
4866 static EventLoopTimerRef scroll_bar_timer
;
4868 static int scroll_bar_timer_event_posted_p
;
4870 #define SCROLL_BAR_FIRST_DELAY 0.5
4871 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4874 scroll_bar_timer_callback (timer
, data
)
4875 EventLoopTimerRef timer
;
4880 err
= mac_post_mouse_moved_event ();
4882 scroll_bar_timer_event_posted_p
= 1;
4886 install_scroll_bar_timer ()
4888 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4890 if (scroll_bar_timer_callbackUPP
== NULL
)
4891 scroll_bar_timer_callbackUPP
=
4892 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4894 if (scroll_bar_timer
== NULL
)
4895 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4896 kEventDurationForever as delays. */
4898 InstallEventLoopTimer (GetCurrentEventLoop (),
4899 kEventDurationForever
, kEventDurationForever
,
4900 scroll_bar_timer_callbackUPP
, NULL
,
4905 set_scroll_bar_timer (delay
)
4906 EventTimerInterval delay
;
4908 if (scroll_bar_timer
== NULL
)
4909 install_scroll_bar_timer ();
4911 scroll_bar_timer_event_posted_p
= 0;
4913 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4917 control_part_code_to_scroll_bar_part (part_code
)
4918 ControlPartCode part_code
;
4922 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4923 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4924 case kControlPageUpPart
: return scroll_bar_above_handle
;
4925 case kControlPageDownPart
: return scroll_bar_below_handle
;
4926 case kControlIndicatorPart
: return scroll_bar_handle
;
4933 construct_scroll_bar_click (bar
, part
, bufp
)
4934 struct scroll_bar
*bar
;
4936 struct input_event
*bufp
;
4938 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4939 bufp
->frame_or_window
= bar
->window
;
4943 XSETINT (bufp
->x
, 0);
4944 XSETINT (bufp
->y
, 0);
4945 bufp
->modifiers
= 0;
4949 get_control_part_bounds (ch
, part_code
, rect
)
4951 ControlPartCode part_code
;
4954 RgnHandle region
= NewRgn ();
4957 err
= GetControlRegion (ch
, part_code
, region
);
4959 GetRegionBounds (region
, rect
);
4960 DisposeRgn (region
);
4966 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4967 struct scroll_bar
*bar
;
4968 ControlPartCode part_code
;
4970 struct input_event
*bufp
;
4972 int part
= control_part_code_to_scroll_bar_part (part_code
);
4977 if (part
!= scroll_bar_handle
)
4979 construct_scroll_bar_click (bar
, part
, bufp
);
4980 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4981 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4982 bar
->dragging
= Qnil
;
4988 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4989 kControlIndicatorPart
, &r
);
4990 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4993 last_scroll_bar_part
= part
;
4994 tracked_scroll_bar
= bar
;
4998 x_scroll_bar_handle_release (bar
, bufp
)
4999 struct scroll_bar
*bar
;
5000 struct input_event
*bufp
;
5002 if (last_scroll_bar_part
!= scroll_bar_handle
5003 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
5004 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
5006 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
5007 set_scroll_bar_timer (kEventDurationForever
);
5009 last_scroll_bar_part
= -1;
5010 bar
->dragging
= Qnil
;
5011 tracked_scroll_bar
= NULL
;
5015 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
5017 struct scroll_bar
*bar
;
5019 struct input_event
*bufp
;
5021 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5023 if (last_scroll_bar_part
== scroll_bar_handle
)
5028 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
5029 kControlIndicatorPart
, &r
);
5031 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
5032 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
5034 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
5035 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
5039 if (top
> top_range
)
5042 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
5043 XSETINT (bufp
->x
, top
);
5044 XSETINT (bufp
->y
, top_range
);
5048 ControlPartCode part_code
;
5049 int unhilite_p
= 0, part
;
5051 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
5055 part
= control_part_code_to_scroll_bar_part (part_code
);
5057 switch (last_scroll_bar_part
)
5059 case scroll_bar_above_handle
:
5060 case scroll_bar_below_handle
:
5061 if (part
!= scroll_bar_above_handle
5062 && part
!= scroll_bar_below_handle
)
5066 case scroll_bar_up_arrow
:
5067 case scroll_bar_down_arrow
:
5068 if (part
!= scroll_bar_up_arrow
5069 && part
!= scroll_bar_down_arrow
)
5076 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
5077 else if (part
!= last_scroll_bar_part
5078 || scroll_bar_timer_event_posted_p
)
5080 construct_scroll_bar_click (bar
, part
, bufp
);
5081 last_scroll_bar_part
= part
;
5082 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
5083 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
5088 /* Set the thumb size and position of scroll bar BAR. We are currently
5089 displaying PORTION out of a whole WHOLE, and our position POSITION. */
5092 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
5093 struct scroll_bar
*bar
;
5094 int portion
, position
, whole
;
5096 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5097 int value
, viewsize
, maximum
;
5099 if (XINT (bar
->track_height
) == 0)
5102 if (whole
<= portion
)
5103 value
= 0, viewsize
= 1, maximum
= 0;
5108 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
5109 scale
= (float) maximum
/ (whole
- portion
);
5110 value
= position
* scale
+ 0.5f
;
5111 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
5116 if (GetControlViewSize (ch
) != viewsize
5117 || GetControl32BitValue (ch
) != value
5118 || GetControl32BitMaximum (ch
) != maximum
)
5120 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5121 SetControlVisibility (ch
, false, false);
5123 SetControl32BitMaximum (ch
, maximum
);
5124 SetControl32BitValue (ch
, value
);
5125 SetControlViewSize (ch
, viewsize
);
5127 SetControlVisibility (ch
, true, true);
5133 #endif /* USE_TOOLKIT_SCROLL_BARS */
5137 /************************************************************************
5138 Scroll bars, general
5139 ************************************************************************/
5141 /* Create a scroll bar and return the scroll bar vector for it. W is
5142 the Emacs window on which to create the scroll bar. TOP, LEFT,
5143 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5146 static struct scroll_bar
*
5147 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5149 int top
, left
, width
, height
, disp_top
, disp_height
;
5151 struct frame
*f
= XFRAME (w
->frame
);
5152 struct scroll_bar
*bar
5153 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5161 r
.right
= left
+ width
;
5162 r
.bottom
= disp_top
+ disp_height
;
5165 mac_prepare_for_quickdraw (f
);
5167 #if TARGET_API_MAC_CARBON
5168 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5169 #ifdef USE_TOOLKIT_SCROLL_BARS
5172 width
< disp_height
,
5174 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5176 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5177 0, 0, 0, scrollBarProc
, (long) bar
);
5179 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5181 XSETWINDOW (bar
->window
, w
);
5182 XSETINT (bar
->top
, top
);
5183 XSETINT (bar
->left
, left
);
5184 XSETINT (bar
->width
, width
);
5185 XSETINT (bar
->height
, height
);
5186 XSETINT (bar
->start
, 0);
5187 XSETINT (bar
->end
, 0);
5188 bar
->dragging
= Qnil
;
5190 bar
->fringe_extended_p
= Qnil
;
5192 bar
->redraw_needed_p
= Qnil
;
5193 #ifdef USE_TOOLKIT_SCROLL_BARS
5194 bar
->track_top
= Qnil
;
5195 bar
->track_height
= Qnil
;
5196 bar
->min_handle
= Qnil
;
5199 /* Add bar to its frame's list of scroll bars. */
5200 bar
->next
= FRAME_SCROLL_BARS (f
);
5202 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5203 if (!NILP (bar
->next
))
5204 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5211 /* Draw BAR's handle in the proper position.
5213 If the handle is already drawn from START to END, don't bother
5214 redrawing it, unless REBUILD is non-zero; in that case, always
5215 redraw it. (REBUILD is handy for drawing the handle after expose
5218 Normally, we want to constrain the start and end of the handle to
5219 fit inside its rectangle, but if the user is dragging the scroll
5220 bar handle, we want to let them drag it down all the way, so that
5221 the bar's top is as far down as it goes; otherwise, there's no way
5222 to move to the very end of the buffer. */
5224 #ifndef USE_TOOLKIT_SCROLL_BARS
5227 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5228 struct scroll_bar
*bar
;
5232 int dragging
= ! NILP (bar
->dragging
);
5233 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5234 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5235 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5236 int length
= end
- start
;
5238 /* If the display is already accurate, do nothing. */
5240 && start
== XINT (bar
->start
)
5241 && end
== XINT (bar
->end
))
5246 /* Make sure the values are reasonable, and try to preserve the
5247 distance between start and end. */
5250 else if (start
> top_range
)
5252 end
= start
+ length
;
5256 else if (end
> top_range
&& ! dragging
)
5259 /* Store the adjusted setting in the scroll bar. */
5260 XSETINT (bar
->start
, start
);
5261 XSETINT (bar
->end
, end
);
5263 /* Clip the end position, just for display. */
5264 if (end
> top_range
)
5267 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5268 top positions, to make sure the handle is always at least that
5269 many pixels tall. */
5270 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5272 SetControlMinimum (ch
, 0);
5273 /* Don't inadvertently activate deactivated scroll bars */
5274 if (GetControlMaximum (ch
) != -1)
5275 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5277 SetControlValue (ch
, start
);
5278 #if TARGET_API_MAC_CARBON
5279 SetControlViewSize (ch
, end
- start
);
5285 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5287 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5291 x_scroll_bar_remove (bar
)
5292 struct scroll_bar
*bar
;
5294 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5299 mac_prepare_for_quickdraw (f
);
5301 /* Destroy the Mac scroll bar control */
5302 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5304 /* Disassociate this scroll bar from its window. */
5305 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5311 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5312 that we are displaying PORTION characters out of a total of WHOLE
5313 characters, starting at POSITION. If WINDOW has no scroll bar,
5317 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5319 int portion
, whole
, position
;
5321 struct frame
*f
= XFRAME (w
->frame
);
5322 struct scroll_bar
*bar
;
5323 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5324 int window_y
, window_height
;
5326 int fringe_extended_p
;
5329 /* Get window dimensions. */
5330 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5332 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5333 height
= window_height
;
5335 /* Compute the left edge of the scroll bar area. */
5336 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5338 /* Compute the width of the scroll bar which might be less than
5339 the width of the area reserved for the scroll bar. */
5340 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5341 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5345 /* Compute the left edge of the scroll bar. */
5346 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5347 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5349 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5351 /* Adjustments according to Inside Macintosh to make it look nice */
5353 disp_height
= height
;
5360 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5366 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5371 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5372 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5373 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5374 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5375 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5377 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5378 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5379 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5380 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5383 /* Does the scroll bar exist yet? */
5384 if (NILP (w
->vertical_scroll_bar
))
5388 if (fringe_extended_p
)
5389 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5392 mac_clear_area (f
, left
, top
, width
, height
);
5394 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5396 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5400 /* It may just need to be moved and resized. */
5403 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5404 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5408 /* If already correctly positioned, do nothing. */
5409 if (XINT (bar
->left
) == sb_left
5410 && XINT (bar
->top
) == top
5411 && XINT (bar
->width
) == sb_width
5412 && XINT (bar
->height
) == height
5414 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5418 if (!NILP (bar
->redraw_needed_p
))
5421 mac_prepare_for_quickdraw (f
);
5423 Draw1Control (SCROLL_BAR_CONTROL_REF (bar
));
5428 /* Since toolkit scroll bars are smaller than the space reserved
5429 for them on the frame, we have to clear "under" them. */
5431 if (fringe_extended_p
)
5432 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5435 mac_clear_area (f
, left
, top
, width
, height
);
5438 mac_prepare_for_quickdraw (f
);
5441 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5442 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5444 #ifndef USE_TOOLKIT_SCROLL_BARS
5445 if (sb_width
< disp_height
)
5449 /* Remember new settings. */
5450 XSETINT (bar
->left
, sb_left
);
5451 XSETINT (bar
->top
, top
);
5452 XSETINT (bar
->width
, sb_width
);
5453 XSETINT (bar
->height
, height
);
5454 #ifdef USE_TOOLKIT_SCROLL_BARS
5455 bar
->track_top
= Qnil
;
5456 bar
->track_height
= Qnil
;
5457 bar
->min_handle
= Qnil
;
5465 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5468 bar
->redraw_needed_p
= Qnil
;
5470 #ifdef USE_TOOLKIT_SCROLL_BARS
5471 if (NILP (bar
->track_top
))
5473 if (sb_width
>= disp_height
5475 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5479 XSETINT (bar
->track_top
, 0);
5480 XSETINT (bar
->track_height
, 0);
5481 XSETINT (bar
->min_handle
, 0);
5485 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5490 SetControl32BitMinimum (ch
, 0);
5491 SetControl32BitMaximum (ch
, 1 << 30);
5492 SetControlViewSize (ch
, 1);
5494 /* Move the scroll bar thumb to the top. */
5495 SetControl32BitValue (ch
, 0);
5496 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5498 /* Move the scroll bar thumb to the bottom. */
5499 SetControl32BitValue (ch
, 1 << 30);
5500 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5502 UnionRect (&r0
, &r1
, &r0
);
5503 XSETINT (bar
->track_top
, r0
.top
);
5504 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5505 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5507 /* Don't show the scroll bar if its height is not enough to
5508 display the scroll bar thumb. */
5509 if (r0
.bottom
- r0
.top
> 0)
5516 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5517 #else /* not USE_TOOLKIT_SCROLL_BARS */
5518 /* Set the scroll bar's current state, unless we're currently being
5520 if (NILP (bar
->dragging
))
5522 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5525 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5528 int start
= ((double) position
* top_range
) / whole
;
5529 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5530 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5533 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5537 /* The following three hooks are used when we're doing a thorough
5538 redisplay of the frame. We don't explicitly know which scroll bars
5539 are going to be deleted, because keeping track of when windows go
5540 away is a real pain - "Can you say set-window-configuration, boys
5541 and girls?" Instead, we just assert at the beginning of redisplay
5542 that *all* scroll bars are to be removed, and then save a scroll bar
5543 from the fiery pit when we actually redisplay its window. */
5545 /* Arrange for all scroll bars on FRAME to be removed at the next call
5546 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5547 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5550 XTcondemn_scroll_bars (frame
)
5553 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5554 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5557 bar
= FRAME_SCROLL_BARS (frame
);
5558 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5559 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5560 XSCROLL_BAR (bar
)->prev
= Qnil
;
5561 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5562 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5563 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5568 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5569 Note that WINDOW isn't necessarily condemned at all. */
5572 XTredeem_scroll_bar (window
)
5573 struct window
*window
;
5575 struct scroll_bar
*bar
;
5578 /* We can't redeem this window's scroll bar if it doesn't have one. */
5579 if (NILP (window
->vertical_scroll_bar
))
5582 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5584 /* Unlink it from the condemned list. */
5585 f
= XFRAME (WINDOW_FRAME (window
));
5586 if (NILP (bar
->prev
))
5588 /* If the prev pointer is nil, it must be the first in one of
5590 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5591 /* It's not condemned. Everything's fine. */
5593 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5594 window
->vertical_scroll_bar
))
5595 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5597 /* If its prev pointer is nil, it must be at the front of
5598 one or the other! */
5602 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5604 if (! NILP (bar
->next
))
5605 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5607 bar
->next
= FRAME_SCROLL_BARS (f
);
5609 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5610 if (! NILP (bar
->next
))
5611 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5614 /* Remove all scroll bars on FRAME that haven't been saved since the
5615 last call to `*condemn_scroll_bars_hook'. */
5618 XTjudge_scroll_bars (f
)
5621 Lisp_Object bar
, next
;
5623 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5625 /* Clear out the condemned list now so we won't try to process any
5626 more events on the hapless scroll bars. */
5627 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5629 for (; ! NILP (bar
); bar
= next
)
5631 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5633 x_scroll_bar_remove (b
);
5636 b
->next
= b
->prev
= Qnil
;
5639 /* Now there should be no references to the condemned scroll bars,
5640 and they should get garbage-collected. */
5644 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5645 is set to something other than NO_EVENT, it is enqueued.
5647 This may be called from a signal handler, so we have to ignore GC
5651 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5652 struct scroll_bar
*bar
;
5653 ControlPartCode part_code
;
5654 const EventRecord
*er
;
5655 struct input_event
*bufp
;
5657 int win_y
, top_range
;
5659 if (! WINDOWP (bar
->window
))
5662 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5663 bufp
->frame_or_window
= bar
->window
;
5666 bar
->dragging
= Qnil
;
5670 case kControlUpButtonPart
:
5671 bufp
->part
= scroll_bar_up_arrow
;
5673 case kControlDownButtonPart
:
5674 bufp
->part
= scroll_bar_down_arrow
;
5676 case kControlPageUpPart
:
5677 bufp
->part
= scroll_bar_above_handle
;
5679 case kControlPageDownPart
:
5680 bufp
->part
= scroll_bar_below_handle
;
5682 #if TARGET_API_MAC_CARBON
5685 case kControlIndicatorPart
:
5687 if (er
->what
== mouseDown
)
5688 bar
->dragging
= make_number (0);
5689 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5690 bufp
->part
= scroll_bar_handle
;
5694 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5695 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5697 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5701 if (! NILP (bar
->dragging
))
5702 win_y
-= XINT (bar
->dragging
);
5706 if (win_y
> top_range
)
5709 XSETINT (bufp
->x
, win_y
);
5710 XSETINT (bufp
->y
, top_range
);
5713 #ifndef USE_TOOLKIT_SCROLL_BARS
5715 /* Handle some mouse motion while someone is dragging the scroll bar.
5717 This may be called from a signal handler, so we have to ignore GC
5721 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5722 struct scroll_bar
*bar
;
5726 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5728 last_mouse_movement_time
= t
;
5731 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5733 /* If we're dragging the bar, display it. */
5734 if (! NILP (bar
->dragging
))
5736 /* Where should the handle be now? */
5737 int new_start
= y_pos
- 24;
5739 if (new_start
!= XINT (bar
->start
))
5741 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5743 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5748 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5750 /* Return information to the user about the current position of the mouse
5751 on the scroll bar. */
5754 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5756 Lisp_Object
*bar_window
;
5757 enum scroll_bar_part
*part
;
5759 unsigned long *time
;
5761 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5762 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5763 #if TARGET_API_MAC_CARBON
5764 WindowRef wp
= GetControlOwner (ch
);
5766 WindowRef wp
= (*ch
)->contrlOwner
;
5769 struct frame
*f
= mac_window_to_frame (wp
);
5770 int win_y
, top_range
;
5772 #if TARGET_API_MAC_CARBON
5773 GetGlobalMouse (&mouse_pos
);
5774 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5775 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5777 SetPortWindowPort (wp
);
5778 GetMouse (&mouse_pos
);
5781 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5782 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5784 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5788 if (! NILP (bar
->dragging
))
5789 win_y
-= XINT (bar
->dragging
);
5793 if (win_y
> top_range
)
5797 *bar_window
= bar
->window
;
5799 if (! NILP (bar
->dragging
))
5800 *part
= scroll_bar_handle
;
5801 else if (win_y
< XINT (bar
->start
))
5802 *part
= scroll_bar_above_handle
;
5803 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5804 *part
= scroll_bar_handle
;
5806 *part
= scroll_bar_below_handle
;
5808 XSETINT (*x
, win_y
);
5809 XSETINT (*y
, top_range
);
5812 last_mouse_scroll_bar
= Qnil
;
5814 *time
= last_mouse_movement_time
;
5818 /* The screen has been cleared so we may have changed foreground or
5819 background colors, and the scroll bars may need to be redrawn.
5820 Clear out the scroll bars, and ask for expose events, so we can
5824 x_scroll_bar_clear (f
)
5829 /* We can have scroll bars even if this is 0,
5830 if we just turned off scroll bar mode.
5831 But in that case we should not clear them. */
5832 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5833 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5834 bar
= XSCROLL_BAR (bar
)->next
)
5835 XSCROLL_BAR (bar
)->redraw_needed_p
= Qt
;
5839 /***********************************************************************
5841 ***********************************************************************/
5844 /* In identifiers such as function/variable names, Emacs tool bar is
5845 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5847 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5848 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5850 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5851 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5852 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5853 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5854 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5855 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5856 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5858 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5859 static void mac_handle_origin_change
P_ ((struct frame
*));
5860 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5864 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5871 mac_get_window_bounds (f
, &inner
, &outer
);
5873 switch (win_gravity
)
5875 case NorthWestGravity
:
5877 case SouthWestGravity
:
5878 left
+= inner
.left
- outer
.left
;
5884 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5887 case NorthEastGravity
:
5889 case SouthEastGravity
:
5890 left
+= inner
.right
- outer
.right
;
5894 switch (win_gravity
)
5896 case NorthWestGravity
:
5898 case NorthEastGravity
:
5899 top
+= inner
.top
- outer
.top
;
5905 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5908 case SouthWestGravity
:
5910 case SouthEastGravity
:
5911 top
+= inner
.bottom
- outer
.bottom
;
5915 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5919 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5926 mac_get_window_bounds (f
, &inner
, &outer
);
5928 switch (win_gravity
)
5930 case NorthWestGravity
:
5932 case SouthWestGravity
:
5939 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5940 - (inner
.right
- inner
.left
)) / 2;
5943 case NorthEastGravity
:
5945 case SouthEastGravity
:
5946 *left
= outer
.right
- (inner
.right
- inner
.left
);
5950 switch (win_gravity
)
5952 case NorthWestGravity
:
5954 case NorthEastGravity
:
5961 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5962 - (inner
.bottom
- inner
.top
)) / 2;
5965 case SouthWestGravity
:
5967 case SouthEastGravity
:
5968 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5974 mac_handle_toolbar_event (next_handler
, event
, data
)
5975 EventHandlerCallRef next_handler
;
5979 OSStatus err
, result
= eventNotHandledErr
;
5981 switch (GetEventKind (event
))
5983 case kEventToolbarGetDefaultIdentifiers
:
5987 case kEventToolbarGetAllowedIdentifiers
:
5989 CFMutableArrayRef array
;
5991 GetEventParameter (event
, kEventParamMutableArray
,
5992 typeCFMutableArrayRef
, NULL
,
5993 sizeof (CFMutableArrayRef
), NULL
, &array
);
5994 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5999 case kEventToolbarCreateItemWithIdentifier
:
6001 CFStringRef identifier
;
6002 HIToolbarItemRef item
= NULL
;
6004 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
6005 typeCFStringRef
, NULL
,
6006 sizeof (CFStringRef
), NULL
, &identifier
);
6008 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
6009 == kCFCompareEqualTo
)
6010 HIToolbarItemCreate (identifier
,
6011 kHIToolbarItemAllowDuplicates
6012 | kHIToolbarItemCantBeRemoved
, &item
);
6016 SetEventParameter (event
, kEventParamToolbarItem
,
6017 typeHIToolbarItemRef
,
6018 sizeof (HIToolbarItemRef
), &item
);
6032 mac_image_spec_to_cg_image (f
, image
)
6036 if (!valid_image_p (image
))
6040 int img_id
= lookup_image (f
, image
);
6041 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
6043 prepare_image_for_display (f
, img
);
6045 return img
->data
.ptr_val
;
6049 /* Create a tool bar for frame F. */
6052 mac_create_frame_tool_bar (f
)
6056 HIToolbarRef toolbar
;
6058 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
6062 static const EventTypeSpec specs
[] =
6063 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
6064 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
6065 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
6067 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
6068 mac_handle_toolbar_event
,
6069 GetEventTypeCount (specs
), specs
,
6074 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
6077 static const EventTypeSpec specs
[] =
6078 {{kEventClassCommand
, kEventCommandProcess
}};
6080 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
6081 mac_handle_toolbar_command_event
,
6082 GetEventTypeCount (specs
),
6086 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
6089 CFRelease (toolbar
);
6094 /* Update the tool bar for frame F. Add new buttons and remove old. */
6097 update_frame_tool_bar (f
)
6100 HIToolbarRef toolbar
= NULL
;
6102 CFArrayRef old_items
= NULL
;
6104 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
6105 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6109 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
6110 if (toolbar
== NULL
)
6112 mac_create_frame_tool_bar (f
);
6113 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
6114 if (toolbar
== NULL
)
6116 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6117 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
6120 HIToolbarCopyItems (toolbar
, &old_items
);
6121 if (old_items
== NULL
)
6124 old_count
= CFArrayGetCount (old_items
);
6126 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
6128 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
6130 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
6131 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
6134 CGImageRef cg_image
;
6136 HIToolbarItemRef item
;
6138 /* If image is a vector, choose the image according to the
6140 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6141 if (VECTORP (image
))
6145 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6146 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6149 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6150 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6152 xassert (ASIZE (image
) >= idx
);
6153 image
= AREF (image
, idx
);
6158 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6159 /* Ignore invalid image specifications. */
6160 if (cg_image
== NULL
)
6163 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6167 if (pos
< old_count
)
6169 CGImageRef old_cg_image
= NULL
;
6170 CFStringRef old_label
= NULL
;
6171 Boolean old_enabled_p
;
6173 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6175 HIToolbarItemCopyImage (item
, &old_cg_image
);
6176 if (cg_image
!= old_cg_image
)
6177 HIToolbarItemSetImage (item
, cg_image
);
6178 CGImageRelease (old_cg_image
);
6180 HIToolbarItemCopyLabel (item
, &old_label
);
6181 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6182 HIToolbarItemSetLabel (item
, label
);
6183 CFRelease (old_label
);
6185 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6186 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6187 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6192 HIToolbarCreateItemWithIdentifier (toolbar
,
6193 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6197 HIToolbarItemSetImage (item
, cg_image
);
6198 HIToolbarItemSetLabel (item
, label
);
6199 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6200 HIToolbarAppendItem (toolbar
, item
);
6208 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6213 CFRelease (old_items
);
6215 while (pos
< old_count
)
6216 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6218 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6219 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6220 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6221 toolbar visibility change. */
6222 mac_handle_origin_change (f
);
6223 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6225 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6226 /* If the title bar is completely outside the screen, adjust the
6228 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6229 kWindowConstrainMoveRegardlessOfFit
6230 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6231 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6238 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6239 doesn't deallocate the resources. */
6242 free_frame_tool_bar (f
)
6245 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6247 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6250 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6251 (NILP (Fsymbol_value
6252 (intern ("frame-notice-user-settings")))
6253 && f
== mac_focus_frame (dpyinfo
)));
6254 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6255 on toolbar visibility change. */
6256 mac_handle_origin_change (f
);
6262 mac_tool_bar_note_mouse_movement (f
, event
)
6267 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6269 HIViewRef item_view
;
6272 mouse_down_p
= (dpyinfo
->grabbed
6273 && f
== last_mouse_frame
6274 && FRAME_LIVE_P (f
));
6278 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6280 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6281 toolbar item view seems to have the same command ID with that of
6282 the toolbar item. */
6284 err
= GetControlCommandID (item_view
, &command_id
);
6285 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6287 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6289 if (i
< f
->n_tool_bar_items
)
6292 HIViewRef content_view
;
6294 err
= HIViewGetBounds (item_view
, &bounds
);
6296 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6297 kHIViewWindowContentID
, &content_view
);
6299 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6301 SetRect (&last_mouse_glyph
,
6302 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6303 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6305 help_echo_object
= help_echo_window
= Qnil
;
6307 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6308 if (NILP (help_echo_string
))
6309 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6315 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6316 EventHandlerCallRef next_handler
;
6320 OSStatus err
, result
= eventNotHandledErr
;
6321 struct frame
*f
= (struct frame
*) data
;
6324 err
= GetEventParameter (event
, kEventParamDirectObject
,
6325 typeHICommand
, NULL
,
6326 sizeof (HICommand
), NULL
, &command
);
6330 switch (GetEventKind (event
))
6332 case kEventCommandProcess
:
6333 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6334 result
= CallNextEventHandler (next_handler
, event
);
6337 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6339 if (i
< f
->n_tool_bar_items
6340 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6343 struct input_event buf
;
6347 XSETFRAME (frame
, f
);
6348 buf
.kind
= TOOL_BAR_EVENT
;
6349 buf
.frame_or_window
= frame
;
6351 kbd_buffer_store_event (&buf
);
6353 buf
.kind
= TOOL_BAR_EVENT
;
6354 buf
.frame_or_window
= frame
;
6355 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6356 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6357 kbd_buffer_store_event (&buf
);
6371 #endif /* USE_MAC_TOOLBAR */
6374 /***********************************************************************
6376 ***********************************************************************/
6378 /* Set clipping for output in glyph row ROW. W is the window in which
6379 we operate. GC is the graphics context to set clipping in.
6381 ROW may be a text row or, e.g., a mode line. Text rows must be
6382 clipped to the interior of the window dedicated to text display,
6383 mode lines must be clipped to the whole window. */
6386 x_clip_to_row (w
, row
, area
, gc
)
6388 struct glyph_row
*row
;
6392 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6394 int window_x
, window_y
, window_width
;
6396 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6398 clip_rect
.left
= window_x
;
6399 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6400 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6401 clip_rect
.right
= clip_rect
.left
+ window_width
;
6402 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6404 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6408 /* Draw a hollow box cursor on window W in glyph row ROW. */
6411 x_draw_hollow_cursor (w
, row
)
6413 struct glyph_row
*row
;
6415 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6416 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6417 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6420 struct glyph
*cursor_glyph
;
6423 /* Get the glyph the cursor is on. If we can't tell because
6424 the current matrix is invalid or such, give up. */
6425 cursor_glyph
= get_phys_cursor_glyph (w
);
6426 if (cursor_glyph
== NULL
)
6429 /* Compute frame-relative coordinates for phys cursor. */
6430 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6431 wd
= w
->phys_cursor_width
;
6433 /* The foreground of cursor_gc is typically the same as the normal
6434 background color, which can cause the cursor box to be invisible. */
6435 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6436 if (dpyinfo
->scratch_cursor_gc
)
6437 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6439 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6440 GCForeground
, &xgcv
);
6441 gc
= dpyinfo
->scratch_cursor_gc
;
6443 /* Set clipping, draw the rectangle, and reset clipping again. */
6444 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6445 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6446 mac_reset_clip_rectangles (dpy
, gc
);
6450 /* Draw a bar cursor on window W in glyph row ROW.
6452 Implementation note: One would like to draw a bar cursor with an
6453 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6454 Unfortunately, I didn't find a font yet that has this property set.
6458 x_draw_bar_cursor (w
, row
, width
, kind
)
6460 struct glyph_row
*row
;
6462 enum text_cursor_kinds kind
;
6464 struct frame
*f
= XFRAME (w
->frame
);
6465 struct glyph
*cursor_glyph
;
6467 /* If cursor is out of bounds, don't draw garbage. This can happen
6468 in mini-buffer windows when switching between echo area glyphs
6470 cursor_glyph
= get_phys_cursor_glyph (w
);
6471 if (cursor_glyph
== NULL
)
6474 /* If on an image, draw like a normal cursor. That's usually better
6475 visible than drawing a bar, esp. if the image is large so that
6476 the bar might not be in the window. */
6477 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6479 struct glyph_row
*row
;
6480 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6481 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6485 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6486 Window window
= FRAME_MAC_WINDOW (f
);
6487 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6488 unsigned long mask
= GCForeground
| GCBackground
;
6489 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6492 /* If the glyph's background equals the color we normally draw
6493 the bar cursor in, the bar cursor in its normal color is
6494 invisible. Use the glyph's foreground color instead in this
6495 case, on the assumption that the glyph's colors are chosen so
6496 that the glyph is legible. */
6497 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6498 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6500 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6503 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6506 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6507 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6511 width
= FRAME_CURSOR_WIDTH (f
);
6512 width
= min (cursor_glyph
->pixel_width
, width
);
6514 w
->phys_cursor_width
= width
;
6515 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6517 if (kind
== BAR_CURSOR
)
6518 mac_fill_rectangle (f
, gc
,
6519 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6520 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6521 width
, row
->height
);
6523 mac_fill_rectangle (f
, gc
,
6524 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6525 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6526 row
->height
- width
),
6527 cursor_glyph
->pixel_width
,
6530 mac_reset_clip_rectangles (f
, gc
);
6535 /* RIF: Define cursor CURSOR on frame F. */
6538 mac_define_frame_cursor (f
, cursor
)
6542 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6544 if (dpyinfo
->x_focus_frame
== f
)
6545 SetThemeCursor (cursor
);
6549 /* RIF: Clear area on frame F. */
6552 mac_clear_frame_area (f
, x
, y
, width
, height
)
6554 int x
, y
, width
, height
;
6556 mac_clear_area (f
, x
, y
, width
, height
);
6560 /* RIF: Draw cursor on window W. */
6563 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6565 struct glyph_row
*glyph_row
;
6567 int cursor_type
, cursor_width
;
6572 w
->phys_cursor_type
= cursor_type
;
6573 w
->phys_cursor_on_p
= 1;
6575 if (glyph_row
->exact_window_width_line_p
6576 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6578 glyph_row
->cursor_in_fringe_p
= 1;
6579 draw_fringe_bitmap (w
, glyph_row
, 0);
6582 switch (cursor_type
)
6584 case HOLLOW_BOX_CURSOR
:
6585 x_draw_hollow_cursor (w
, glyph_row
);
6588 case FILLED_BOX_CURSOR
:
6589 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6593 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6597 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6601 w
->phys_cursor_width
= 0;
6613 #if 0 /* MAC_TODO: no icon support yet. */
6615 x_bitmap_icon (f
, icon
)
6621 if (FRAME_W32_WINDOW (f
) == 0)
6625 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6626 else if (STRINGP (icon
))
6627 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6628 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6629 else if (SYMBOLP (icon
))
6633 if (EQ (icon
, intern ("application")))
6634 name
= (LPCTSTR
) IDI_APPLICATION
;
6635 else if (EQ (icon
, intern ("hand")))
6636 name
= (LPCTSTR
) IDI_HAND
;
6637 else if (EQ (icon
, intern ("question")))
6638 name
= (LPCTSTR
) IDI_QUESTION
;
6639 else if (EQ (icon
, intern ("exclamation")))
6640 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6641 else if (EQ (icon
, intern ("asterisk")))
6642 name
= (LPCTSTR
) IDI_ASTERISK
;
6643 else if (EQ (icon
, intern ("winlogo")))
6644 name
= (LPCTSTR
) IDI_WINLOGO
;
6648 hicon
= LoadIcon (NULL
, name
);
6656 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6661 #endif /* MAC_TODO */
6663 /************************************************************************
6665 ************************************************************************/
6667 /* Display Error Handling functions not used on W32. Listing them here
6668 helps diff stay in step when comparing w32term.c with xterm.c.
6670 x_error_catcher (display, error)
6671 x_catch_errors (dpy)
6672 x_catch_errors_unwind (old_val)
6673 x_check_errors (dpy, format)
6674 x_had_errors_p (dpy)
6675 x_clear_errors (dpy)
6676 x_uncatch_errors (dpy, count)
6678 x_connection_signal (signalnum)
6679 x_connection_closed (dpy, error_message)
6680 x_error_quitter (display, error)
6681 x_error_handler (display, error)
6682 x_io_error_quitter (display)
6687 /* Changing the font of the frame. */
6689 /* Give frame F the font named FONTNAME as its default font, and
6690 return the full name of that font. FONTNAME may be a wildcard
6691 pattern; in that case, we choose some font that fits the pattern.
6692 The return value shows which font we chose. */
6695 x_new_font (f
, fontname
)
6697 register char *fontname
;
6699 struct font_info
*fontp
6700 = FS_LOAD_FONT (f
, fontname
);
6705 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
6706 /* This font is already set in frame F. There's nothing more to
6708 return build_string (fontp
->full_name
);
6710 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6711 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6712 FRAME_FONTSET (f
) = -1;
6714 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6715 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6716 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6718 compute_fringe_widths (f
, 1);
6720 /* Compute the scroll bar width in character columns. */
6721 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6723 int wid
= FRAME_COLUMN_WIDTH (f
);
6724 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6725 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6729 int wid
= FRAME_COLUMN_WIDTH (f
);
6730 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6733 /* Now make the frame display the given font. */
6734 if (FRAME_MAC_WINDOW (f
) != 0)
6736 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6738 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6740 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6743 /* Don't change the size of a tip frame; there's no point in
6744 doing it because it's done in Fx_show_tip, and it leads to
6745 problems because the tip frame has no widget. */
6746 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6747 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6750 return build_string (fontp
->full_name
);
6753 /* Give frame F the fontset named FONTSETNAME as its default fontset,
6754 and return the full name of that fontset. FONTSETNAME may be a
6755 wildcard pattern; in that case, we choose some fontset that fits
6756 the pattern. FONTSETNAME may be a font name for ASCII characters;
6757 in that case, we create a fontset from that font name.
6759 The return value shows which fontset we chose.
6760 If FONTSETNAME specifies the default fontset, return Qt.
6761 If an ASCII font in the specified fontset can't be loaded, return
6765 x_new_fontset (f
, fontsetname
)
6767 Lisp_Object fontsetname
;
6769 int fontset
= fs_query_fontset (fontsetname
, 0);
6772 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
6773 /* This fontset is already set in frame F. There's nothing more
6775 return fontset_name (fontset
);
6776 else if (fontset
== 0)
6777 /* The default fontset can't be the default font. */
6781 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6783 result
= x_new_font (f
, SDATA (fontsetname
));
6785 if (!STRINGP (result
))
6786 /* Can't load ASCII font. */
6790 fontset
= new_fontset_from_font_name (result
);
6792 /* Since x_new_font doesn't update any fontset information, do it now. */
6793 FRAME_FONTSET (f
) = fontset
;
6795 return fontset_name (fontset
);
6799 /***********************************************************************
6800 TODO: W32 Input Methods
6801 ***********************************************************************/
6802 /* Listing missing functions from xterm.c helps diff stay in step.
6804 xim_destroy_callback (xim, client_data, call_data)
6805 xim_open_dpy (dpyinfo, resource_name)
6807 xim_instantiate_callback (display, client_data, call_data)
6808 xim_initialize (dpyinfo, resource_name)
6809 xim_close_dpy (dpyinfo)
6815 mac_get_window_bounds (f
, inner
, outer
)
6817 Rect
*inner
, *outer
;
6819 #if TARGET_API_MAC_CARBON
6820 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6821 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6822 #else /* not TARGET_API_MAC_CARBON */
6823 RgnHandle region
= NewRgn ();
6825 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6826 *inner
= (*region
)->rgnBBox
;
6827 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6828 *outer
= (*region
)->rgnBBox
;
6829 DisposeRgn (region
);
6830 #endif /* not TARGET_API_MAC_CARBON */
6834 mac_handle_origin_change (f
)
6837 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6841 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6843 int pixelwidth
, pixelheight
;
6847 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6848 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6850 if (cols
!= FRAME_COLS (f
)
6851 || rows
!= FRAME_LINES (f
)
6852 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6853 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6855 /* We pass 1 for DELAY since we can't run Lisp code inside of
6857 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6858 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6859 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6861 /* If cursor was outside the new size, mark it as off. */
6862 mark_window_cursors_off (XWINDOW (f
->root_window
));
6864 /* Clear out any recollection of where the mouse highlighting
6865 was, since it might be in a place that's outside the new
6866 frame size. Actually checking whether it is outside is a
6867 pain in the neck, so don't try--just let the highlighting be
6868 done afresh with new size. */
6869 cancel_mouse_face (f
);
6871 #if TARGET_API_MAC_CARBON
6872 if (f
->output_data
.mac
->hourglass_control
)
6875 mac_prepare_for_quickdraw (f
);
6877 MoveControl (f
->output_data
.mac
->hourglass_control
,
6878 pixelwidth
- HOURGLASS_WIDTH
, 0);
6885 /* Calculate the absolute position in frame F
6886 from its current recorded position values and gravity. */
6889 x_calc_absolute_position (f
)
6892 int flags
= f
->size_hint_flags
;
6895 /* We have nothing to do if the current position
6896 is already for the top-left corner. */
6897 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6900 /* Find the offsets of the outside upper-left corner of
6901 the inner window, with respect to the outer window. */
6903 mac_get_window_bounds (f
, &inner
, &outer
);
6906 /* Treat negative positions as relative to the leftmost bottommost
6907 position that fits on the screen. */
6908 if (flags
& XNegative
)
6909 f
->left_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->width
6910 - (outer
.right
- outer
.left
));
6912 if (flags
& YNegative
)
6913 f
->top_pos
+= (FRAME_MAC_DISPLAY_INFO (f
)->height
6914 - (outer
.bottom
- outer
.top
));
6916 /* The left_pos and top_pos
6917 are now relative to the top and left screen edges,
6918 so the flags should correspond. */
6919 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6922 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6923 to really change the position, and 0 when calling from
6924 x_make_frame_visible (in that case, XOFF and YOFF are the current
6925 position values). It is -1 when calling from x_set_frame_parameters,
6926 which means, do adjust for borders but don't change the gravity. */
6929 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6931 register int xoff
, yoff
;
6934 if (change_gravity
> 0)
6938 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6940 f
->size_hint_flags
|= XNegative
;
6942 f
->size_hint_flags
|= YNegative
;
6943 f
->win_gravity
= NorthWestGravity
;
6945 x_calc_absolute_position (f
);
6948 x_wm_set_size_hint (f
, (long) 0, 0);
6950 #if TARGET_API_MAC_CARBON
6951 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6952 /* If the title bar is completely outside the screen, adjust the
6954 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6955 kWindowConstrainMoveRegardlessOfFit
6956 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6957 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6958 mac_handle_origin_change (f
);
6961 Rect inner
, outer
, screen_rect
, dummy
;
6962 RgnHandle region
= NewRgn ();
6964 mac_get_window_bounds (f
, &inner
, &outer
);
6965 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6966 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6967 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6968 f
->top_pos
+ f
->y_pixels_diff
, false);
6970 /* If the title bar is completely outside the screen, adjust the
6971 position. The variable `outer' holds the title bar rectangle.
6972 The variable `inner' holds slightly smaller one than `outer',
6973 so that the calculation of overlapping may not become too
6975 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6976 outer
= (*region
)->rgnBBox
;
6977 DisposeRgn (region
);
6979 InsetRect (&inner
, 8, 8);
6980 screen_rect
= qd
.screenBits
.bounds
;
6981 screen_rect
.top
+= GetMBarHeight ();
6983 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6985 if (inner
.right
<= screen_rect
.left
)
6986 f
->left_pos
= screen_rect
.left
;
6987 else if (inner
.left
>= screen_rect
.right
)
6988 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6990 if (inner
.bottom
<= screen_rect
.top
)
6991 f
->top_pos
= screen_rect
.top
;
6992 else if (inner
.top
>= screen_rect
.bottom
)
6993 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6995 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6996 f
->top_pos
+ f
->y_pixels_diff
, false);
7004 /* Call this to change the size of frame F's x-window.
7005 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
7006 for this size change and subsequent size changes.
7007 Otherwise we leave the window gravity unchanged. */
7010 x_set_window_size (f
, change_gravity
, cols
, rows
)
7015 int pixelwidth
, pixelheight
;
7019 check_frame_size (f
, &rows
, &cols
);
7020 f
->scroll_bar_actual_width
7021 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
7023 compute_fringe_widths (f
, 0);
7025 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
7026 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7028 f
->win_gravity
= NorthWestGravity
;
7029 x_wm_set_size_hint (f
, (long) 0, 0);
7031 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
7033 #if TARGET_API_MAC_CARBON
7034 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
7036 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
7038 if (f
->output_data
.mac
->internal_border_width
7039 != FRAME_INTERNAL_BORDER_WIDTH (f
))
7041 mac_clear_window (f
);
7042 f
->output_data
.mac
->internal_border_width
7043 = FRAME_INTERNAL_BORDER_WIDTH (f
);
7046 SET_FRAME_GARBAGED (f
);
7051 /* Mouse warping. */
7053 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
7056 x_set_mouse_position (f
, x
, y
)
7062 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
7063 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
7065 if (pix_x
< 0) pix_x
= 0;
7066 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
7068 if (pix_y
< 0) pix_y
= 0;
7069 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
7071 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
7075 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
7080 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
7081 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
7084 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
7087 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
7090 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
7091 0, 0, 0, 0, pix_x
, pix_y
);
7097 /* focus shifting, raising and lowering. */
7100 x_focus_on_frame (f
)
7103 #if 0 /* This proves to be unpleasant. */
7107 /* I don't think that the ICCCM allows programs to do things like this
7108 without the interaction of the window manager. Whatever you end up
7109 doing with this code, do it to x_unfocus_frame too. */
7110 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7111 RevertToPointerRoot
, CurrentTime
);
7121 /* Raise frame F. */
7127 if (f
->async_visible
)
7130 BringToFront (FRAME_MAC_WINDOW (f
));
7135 /* Lower frame F. */
7141 if (f
->async_visible
)
7144 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7150 XTframe_raise_lower (f
, raise_flag
)
7160 /* Change of visibility. */
7163 mac_handle_visibility_change (f
)
7166 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7167 int visible
= 0, iconified
= 0;
7168 struct input_event buf
;
7170 if (IsWindowVisible (wp
))
7172 if (IsWindowCollapsed (wp
))
7178 if (!f
->async_visible
&& visible
)
7182 /* wait_reading_process_output will notice this and update
7183 the frame's display structures. If we were made
7184 invisible, we should not set garbaged, because that stops
7185 redrawing on Update events. */
7186 SET_FRAME_GARBAGED (f
);
7189 buf
.kind
= DEICONIFY_EVENT
;
7190 XSETFRAME (buf
.frame_or_window
, f
);
7192 kbd_buffer_store_event (&buf
);
7194 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7195 /* Force a redisplay sooner or later to update the
7196 frame titles in case this is the second frame. */
7197 record_asynch_buffer_change ();
7199 else if (f
->async_visible
&& !visible
)
7203 buf
.kind
= ICONIFY_EVENT
;
7204 XSETFRAME (buf
.frame_or_window
, f
);
7206 kbd_buffer_store_event (&buf
);
7209 f
->async_visible
= visible
;
7210 f
->async_iconified
= iconified
;
7213 /* This tries to wait until the frame is really visible.
7214 However, if the window manager asks the user where to position
7215 the frame, this will return before the user finishes doing that.
7216 The frame will not actually be visible at that time,
7217 but it will become visible later when the window manager
7218 finishes with it. */
7221 x_make_frame_visible (f
)
7226 if (! FRAME_VISIBLE_P (f
))
7228 /* We test FRAME_GARBAGED_P here to make sure we don't
7229 call x_set_offset a second time
7230 if we get to x_make_frame_visible a second time
7231 before the window gets really visible. */
7232 if (! FRAME_ICONIFIED_P (f
)
7233 && ! f
->output_data
.mac
->asked_for_visible
)
7234 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7236 f
->output_data
.mac
->asked_for_visible
= 1;
7238 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7239 ShowWindow (FRAME_MAC_WINDOW (f
));
7242 XFlush (FRAME_MAC_DISPLAY (f
));
7244 /* Synchronize to ensure Emacs knows the frame is visible
7245 before we do anything else. We do this loop with input not blocked
7246 so that incoming events are handled. */
7251 /* This must come after we set COUNT. */
7254 XSETFRAME (frame
, f
);
7256 /* Wait until the frame is visible. Process X events until a
7257 MapNotify event has been seen, or until we think we won't get a
7258 MapNotify at all.. */
7259 for (count
= input_signal_count
+ 10;
7260 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7262 /* Force processing of queued events. */
7265 /* Machines that do polling rather than SIGIO have been
7266 observed to go into a busy-wait here. So we'll fake an
7267 alarm signal to let the handler know that there's something
7268 to be read. We used to raise a real alarm, but it seems
7269 that the handler isn't always enabled here. This is
7271 if (input_polling_used ())
7273 /* It could be confusing if a real alarm arrives while
7274 processing the fake one. Turn it off and let the
7275 handler reset it. */
7276 extern void poll_for_input_1
P_ ((void));
7277 int old_poll_suppress_count
= poll_suppress_count
;
7278 poll_suppress_count
= 1;
7279 poll_for_input_1 ();
7280 poll_suppress_count
= old_poll_suppress_count
;
7283 /* See if a MapNotify event has been processed. */
7284 FRAME_SAMPLE_VISIBILITY (f
);
7289 /* Change from mapped state to withdrawn state. */
7291 /* Make the frame visible (mapped and not iconified). */
7294 x_make_frame_invisible (f
)
7297 /* A deactivate event does not occur when the last visible frame is
7298 made invisible. So if we clear the highlight here, it will not
7299 be rehighlighted when it is made visible. */
7301 /* Don't keep the highlight on an invisible frame. */
7302 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7303 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7308 #if !TARGET_API_MAC_CARBON
7309 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7310 that the current position of the window is user-specified, rather than
7311 program-specified, so that when the window is mapped again, it will be
7312 placed at the same location, without forcing the user to position it
7313 by hand again (they have already done that once for this window.) */
7314 x_wm_set_size_hint (f
, (long) 0, 1);
7317 HideWindow (FRAME_MAC_WINDOW (f
));
7321 #if !TARGET_API_MAC_CARBON
7322 mac_handle_visibility_change (f
);
7326 /* Change window state from mapped to iconified. */
7334 /* A deactivate event does not occur when the last visible frame is
7335 iconified. So if we clear the highlight here, it will not be
7336 rehighlighted when it is deiconified. */
7338 /* Don't keep the highlight on an invisible frame. */
7339 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7340 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7343 if (f
->async_iconified
)
7348 FRAME_SAMPLE_VISIBILITY (f
);
7350 if (! FRAME_VISIBLE_P (f
))
7351 ShowWindow (FRAME_MAC_WINDOW (f
));
7353 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7358 error ("Can't notify window manager of iconification");
7360 #if !TARGET_API_MAC_CARBON
7361 mac_handle_visibility_change (f
);
7366 /* Free X resources of frame F. */
7369 x_free_frame_resources (f
)
7372 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7373 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7377 if (wp
!= tip_window
)
7378 remove_window_handler (wp
);
7381 mac_prepare_for_quickdraw (f
);
7384 if (wp
== tip_window
)
7385 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7386 closed' event. So we reset tip_window here. */
7389 free_frame_menubar (f
);
7391 if (FRAME_FACE_CACHE (f
))
7392 free_frame_faces (f
);
7396 if (FRAME_SIZE_HINTS (f
))
7397 xfree (FRAME_SIZE_HINTS (f
));
7399 xfree (f
->output_data
.mac
);
7400 f
->output_data
.mac
= NULL
;
7402 if (f
== dpyinfo
->x_focus_frame
)
7404 dpyinfo
->x_focus_frame
= 0;
7405 #if USE_MAC_FONT_PANEL
7406 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7409 if (f
== dpyinfo
->x_focus_event_frame
)
7410 dpyinfo
->x_focus_event_frame
= 0;
7411 if (f
== dpyinfo
->x_highlight_frame
)
7412 dpyinfo
->x_highlight_frame
= 0;
7414 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7416 dpyinfo
->mouse_face_beg_row
7417 = dpyinfo
->mouse_face_beg_col
= -1;
7418 dpyinfo
->mouse_face_end_row
7419 = dpyinfo
->mouse_face_end_col
= -1;
7420 dpyinfo
->mouse_face_window
= Qnil
;
7421 dpyinfo
->mouse_face_deferred_gc
= 0;
7422 dpyinfo
->mouse_face_mouse_frame
= 0;
7429 /* Destroy the X window of frame F. */
7432 x_destroy_window (f
)
7435 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7437 x_free_frame_resources (f
);
7439 dpyinfo
->reference_count
--;
7443 /* Setting window manager hints. */
7445 /* Set the normal size hints for the window manager, for frame F.
7446 FLAGS is the flags word to use--or 0 meaning preserve the flags
7447 that the window now has.
7448 If USER_POSITION is nonzero, we set the USPosition
7449 flag (this is useful when FLAGS is 0). */
7451 x_wm_set_size_hint (f
, flags
, user_position
)
7456 int base_width
, base_height
, width_inc
, height_inc
;
7457 int min_rows
= 0, min_cols
= 0;
7458 XSizeHints
*size_hints
;
7460 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7461 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7462 width_inc
= FRAME_COLUMN_WIDTH (f
);
7463 height_inc
= FRAME_LINE_HEIGHT (f
);
7465 check_frame_size (f
, &min_rows
, &min_cols
);
7467 size_hints
= FRAME_SIZE_HINTS (f
);
7468 if (size_hints
== NULL
)
7470 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7471 bzero (size_hints
, sizeof (XSizeHints
));
7474 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7475 size_hints
->width_inc
= width_inc
;
7476 size_hints
->height_inc
= height_inc
;
7477 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7478 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7479 size_hints
->base_width
= base_width
;
7480 size_hints
->base_height
= base_height
;
7483 size_hints
->flags
= flags
;
7484 else if (user_position
)
7486 size_hints
->flags
&= ~ PPosition
;
7487 size_hints
->flags
|= USPosition
;
7491 #if 0 /* MAC_TODO: hide application instead of iconify? */
7492 /* Used for IconicState or NormalState */
7495 x_wm_set_window_state (f
, state
)
7499 #ifdef USE_X_TOOLKIT
7502 XtSetArg (al
[0], XtNinitialState
, state
);
7503 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7504 #else /* not USE_X_TOOLKIT */
7505 Window window
= FRAME_X_WINDOW (f
);
7507 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7508 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7510 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7511 #endif /* not USE_X_TOOLKIT */
7515 x_wm_set_icon_pixmap (f
, pixmap_id
)
7521 #ifndef USE_X_TOOLKIT
7522 Window window
= FRAME_X_WINDOW (f
);
7527 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7528 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7532 /* It seems there is no way to turn off use of an icon pixmap.
7533 The following line does it, only if no icon has yet been created,
7534 for some window managers. But with mwm it crashes.
7535 Some people say it should clear the IconPixmapHint bit in this case,
7536 but that doesn't work, and the X consortium said it isn't the
7537 right thing at all. Since there is no way to win,
7538 best to explicitly give up. */
7540 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7546 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7550 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7551 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7554 #else /* not USE_X_TOOLKIT */
7556 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7557 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7559 #endif /* not USE_X_TOOLKIT */
7562 #endif /* MAC_TODO */
7565 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7569 #if 0 /* MAC_TODO: no icons on Mac */
7570 #ifdef USE_X_TOOLKIT
7571 Window window
= XtWindow (f
->output_data
.x
->widget
);
7573 Window window
= FRAME_X_WINDOW (f
);
7576 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7577 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7578 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7580 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7581 #endif /* MAC_TODO */
7585 /***********************************************************************
7587 ***********************************************************************/
7589 /* An XLFD pattern is divided into blocks delimited by '*'. This
7590 structure holds information for each block. */
7591 struct xlfdpat_block
7593 /* Length of the pattern string in this block. Non-zero except for
7594 the first and the last blocks. */
7597 /* Pattern string except the last character in this block. The last
7598 character is replaced with NUL in order to use it as a
7600 unsigned char *pattern
;
7602 /* Last character of the pattern string. Must not be '?'. */
7603 unsigned char last_char
;
7605 /* One of the tables for the Boyer-Moore string search. It
7606 specifies the number of positions to proceed for each character
7607 with which the match fails. */
7610 /* The skip value for the last character in the above `skip' is
7611 assigned to `infinity' in order to simplify a loop condition.
7612 The original value is saved here. */
7618 /* Normalized pattern string. "Normalized" means that capital
7619 letters are lowered, blocks are not empty except the first and
7620 the last ones, and trailing '?'s in a block that is not the last
7621 one are moved to the next one. The last character in each block
7622 is replaced with NUL. */
7625 /* Number of characters except '*'s and trailing '?'s in the
7626 normalized pattern string. */
7629 /* Number of trailing '?'s in the normalized pattern string. */
7630 int trailing_anychars
;
7632 /* Number of blocks and information for each block. The latter is
7633 NULL if the pattern is exact (no '*' or '?' in it). */
7635 struct xlfdpat_block
*blocks
;
7639 xlfdpat_destroy (pat
)
7640 struct xlfdpat
*pat
;
7647 xfree (pat
->blocks
);
7654 static struct xlfdpat
*
7655 xlfdpat_create (pattern
)
7656 const char *pattern
;
7658 struct xlfdpat
*pat
;
7659 int nblocks
, i
, skip
;
7660 unsigned char last_char
, *p
, *q
, *anychar_head
;
7661 const unsigned char *ptr
;
7662 struct xlfdpat_block
*blk
;
7664 pat
= xmalloc (sizeof (struct xlfdpat
));
7665 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7667 /* Normalize the pattern string and store it to `pat->buf'. */
7669 anychar_head
= NULL
;
7672 for (ptr
= pattern
; *ptr
; ptr
++)
7674 unsigned char c
= *ptr
;
7677 if (last_char
== '*')
7678 /* ...a** -> ...a* */
7682 if (last_char
== '?')
7684 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7685 /* ...*??* -> ...*?? */
7688 /* ...a??* -> ...a*?? */
7690 *anychar_head
++ = '*';
7698 if (last_char
!= '?')
7702 /* On Mac OS X 10.3, tolower also converts non-ASCII
7703 characters for some locales. */
7707 *q
++ = last_char
= c
;
7711 pat
->nblocks
= nblocks
;
7712 if (last_char
!= '?')
7713 pat
->trailing_anychars
= 0;
7716 pat
->trailing_anychars
= q
- anychar_head
;
7719 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7721 if (anychar_head
== NULL
&& nblocks
== 1)
7723 /* The pattern is exact. */
7728 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7730 /* Divide the normalized pattern into blocks. */
7732 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7737 blk
->len
= p
- blk
->pattern
;
7741 blk
->len
= q
- blk
->pattern
;
7743 /* Setup a table for the Boyer-Moore string search. */
7744 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7747 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7748 blk
->pattern
[blk
->len
- 1] = '\0';
7750 for (skip
= 1; skip
< blk
->len
; skip
++)
7751 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7754 for (i
= 0; i
< 256; i
++)
7755 blk
->skip
[i
] = skip
;
7757 p
= blk
->pattern
+ (blk
->len
- skip
);
7759 blk
->skip
[*p
++] = skip
;
7761 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7768 xlfdpat_exact_p (pat
)
7769 struct xlfdpat
*pat
;
7771 return pat
->blocks
== NULL
;
7774 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7775 that the pattern in *BLK matches with its prefix. Return NULL
7776 there is no such strings. STRING must be lowered in advance. */
7779 xlfdpat_block_match_1 (blk
, string
, start_max
)
7780 struct xlfdpat_block
*blk
;
7781 const unsigned char *string
;
7784 int start
, infinity
;
7786 const unsigned char *s
;
7788 xassert (blk
->len
> 0);
7789 xassert (start_max
+ blk
->len
<= strlen (string
));
7790 xassert (blk
->last_char
!= '?');
7792 /* See the comments in the function `boyer_moore' (search.c) for the
7793 use of `infinity'. */
7794 infinity
= start_max
+ blk
->len
+ 1;
7795 blk
->skip
[blk
->last_char
] = infinity
;
7800 /* Check the last character of the pattern. */
7801 s
= string
+ blk
->len
- 1;
7804 start
+= blk
->skip
[*(s
+ start
)];
7806 while (start
<= start_max
);
7808 if (start
< infinity
)
7809 /* Couldn't find the last character. */
7812 /* No less than `infinity' means we could find the last
7813 character at `s[start - infinity]'. */
7816 /* Check the remaining characters. We prefer making no-'?'
7817 cases faster because the use of '?' is really rare. */
7822 while (*p
++ == *s
++)
7825 while (*(p
- 1) == '?');
7827 if (*(p
- 1) == '\0')
7829 return string
+ start
;
7832 start
+= blk
->last_char_skip
;
7834 while (start
<= start_max
);
7839 #define xlfdpat_block_match(b, s, m) \
7840 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7841 : xlfdpat_block_match_1 (b, s, m))
7843 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7844 matches with STRING. STRING must be lowered in advance. */
7847 xlfdpat_match (pat
, string
)
7848 struct xlfdpat
*pat
;
7849 const unsigned char *string
;
7851 int str_len
, nblocks
, i
, start_max
;
7852 struct xlfdpat_block
*blk
;
7853 const unsigned char *s
;
7855 xassert (pat
->nblocks
> 0);
7857 if (xlfdpat_exact_p (pat
))
7858 return strcmp (pat
->buf
, string
) == 0;
7860 /* The number of the characters in the string must not be smaller
7861 than that in the pattern. */
7862 str_len
= strlen (string
);
7863 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7866 /* Chop off the trailing '?'s. */
7867 str_len
-= pat
->trailing_anychars
;
7869 /* The last block. When it is non-empty, it must match at the end
7871 nblocks
= pat
->nblocks
;
7872 blk
= pat
->blocks
+ (nblocks
- 1);
7874 /* The last block is also the first one. */
7875 return (str_len
== blk
->len
7876 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7877 else if (blk
->len
!= 0)
7878 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7881 /* The first block. When it is non-empty, it must match at the
7882 beginning of the string. */
7886 s
= xlfdpat_block_match (blk
, string
, 0);
7889 string
= s
+ blk
->len
;
7892 /* The rest of the blocks. */
7893 start_max
= str_len
- pat
->nchars
;
7894 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7896 s
= xlfdpat_block_match (blk
, string
, start_max
);
7899 start_max
-= s
- string
;
7900 string
= s
+ blk
->len
;
7907 /***********************************************************************
7909 ***********************************************************************/
7911 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7914 x_get_font_info (f
, font_idx
)
7918 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7921 /* the global font name table */
7922 static char **font_name_table
= NULL
;
7923 static int font_name_table_size
= 0;
7924 static int font_name_count
= 0;
7926 /* Alist linking font family names to Font Manager font family
7927 references (which can also be used as QuickDraw font IDs). We use
7928 an alist because hash tables are not ready when the terminal frame
7929 for Mac OS Classic is created. */
7930 static Lisp_Object fm_font_family_alist
;
7932 /* Hash table linking font family names to ATSU font IDs. */
7933 static Lisp_Object atsu_font_id_hash
;
7934 /* Alist linking Font Manager style to face attributes. */
7935 static Lisp_Object fm_style_face_attributes_alist
;
7936 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7939 /* Alist linking character set strings to Mac text encoding and Emacs
7941 static Lisp_Object Vmac_charset_info_alist
;
7944 create_text_encoding_info_alist ()
7946 Lisp_Object result
= Qnil
, rest
;
7948 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7950 Lisp_Object charset_info
= XCAR (rest
);
7951 Lisp_Object charset
, coding_system
, text_encoding
;
7952 Lisp_Object existing_info
;
7954 if (!(CONSP (charset_info
)
7955 && (charset
= XCAR (charset_info
),
7957 && CONSP (XCDR (charset_info
))
7958 && (text_encoding
= XCAR (XCDR (charset_info
)),
7959 INTEGERP (text_encoding
))
7960 && CONSP (XCDR (XCDR (charset_info
)))
7961 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7962 SYMBOLP (coding_system
))))
7965 existing_info
= assq_no_quit (text_encoding
, result
);
7966 if (NILP (existing_info
))
7967 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7970 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7971 XSETCDR (XCDR (existing_info
),
7972 Fcons (charset
, XCDR (XCDR (existing_info
))));
7980 decode_mac_font_name (name
, size
, coding_system
)
7983 Lisp_Object coding_system
;
7985 struct coding_system coding
;
7988 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7990 for (p
= name
; *p
; p
++)
7991 if (!isascii (*p
) || iscntrl (*p
))
7996 setup_coding_system (coding_system
, &coding
);
7997 coding
.src_multibyte
= 0;
7998 coding
.dst_multibyte
= 1;
7999 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
8000 coding
.dst_bytes
= size
;
8001 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
8003 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
8004 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
8005 name
[min (coding
.produced
, size
)] = '\0';
8009 /* If there's just one occurrence of '-' in the family name, it is
8010 replaced with '_'. (More than one occurrence of '-' means a
8011 "FOUNDRY-FAMILY-CHARSET"-style name.) */
8012 p
= strchr (name
, '-');
8013 if (p
&& strchr (p
+ 1, '-') == NULL
)
8016 for (p
= name
; *p
; p
++)
8017 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8018 for some locales. */
8025 mac_to_x_fontname (name
, size
, style
, charset
)
8033 char xf
[256], *result
;
8036 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
8040 strcpy(foundry
, "Apple");
8041 strcpy(family
, name
);
8044 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
8045 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
8046 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
8048 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
8049 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
8050 for (p
= result
; *p
; p
++)
8051 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8052 for some locales. */
8059 /* Parse fully-specified and instantiated X11 font spec XF, and store
8060 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
8061 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
8062 caller must allocate at least 256 and 32 bytes respectively. For
8063 ordinary Mac fonts, the value stored to FAMILY should just be their
8064 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
8065 intlfonts collection contain their charset designation in their
8066 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
8067 types of font names are handled accordingly. */
8069 const int kDefaultFontSize
= 12;
8072 parse_x_font_name (xf
, family
, size
, style
, charset
)
8079 Str31 foundry
, weight
;
8080 int point_size
, avgwidth
;
8083 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
8084 foundry
, family
, weight
, slant
, size
,
8085 &point_size
, &avgwidth
, charset
) != 8
8086 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
8087 foundry
, family
, weight
, slant
, size
,
8088 &point_size
, &avgwidth
, charset
) != 8)
8094 *size
= point_size
/ 10;
8095 else if (avgwidth
> 0)
8096 *size
= avgwidth
/ 10;
8099 *size
= kDefaultFontSize
;
8102 if (strcmp (weight
, "bold") == 0)
8107 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
8109 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
8111 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
8113 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
8114 but take overlap into account. */
8115 memmove (family
+ foundry_len
+ 1, family
, family_len
);
8116 memcpy (family
, foundry
, foundry_len
);
8117 family
[foundry_len
] = '-';
8118 family
[foundry_len
+ 1 + family_len
] = '-';
8119 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
8125 for (p
= family
; *p
; p
++)
8126 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8127 for some locales. */
8136 add_font_name_table_entry (char *font_name
)
8138 if (font_name_table_size
== 0)
8140 font_name_table_size
= 256;
8141 font_name_table
= (char **)
8142 xmalloc (font_name_table_size
* sizeof (char *));
8144 else if (font_name_count
+ 1 >= font_name_table_size
)
8146 font_name_table_size
*= 2;
8147 font_name_table
= (char **)
8148 xrealloc (font_name_table
,
8149 font_name_table_size
* sizeof (char *));
8152 font_name_table
[font_name_count
++] = font_name
;
8156 add_mac_font_name (name
, size
, style
, charset
)
8160 const char *charset
;
8163 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8166 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8167 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8168 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8169 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8176 fm_get_style_from_font (font
)
8180 FMFontStyle style
= normal
;
8183 FMFontFamily font_family
;
8184 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8186 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8187 some font (e.g., Optima) even if it is `bold'. */
8188 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8189 sizeof (mac_style
), &mac_style
, &len
);
8191 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8192 style
= EndianU16_BtoN (mac_style
);
8194 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8200 atsu_find_font_from_family_name (family
)
8203 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8206 Lisp_Object rest
, best
;
8207 FMFontStyle min_style
, style
;
8209 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8212 return kATSUInvalidFontID
;
8214 rest
= HASH_VALUE (h
, i
);
8215 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8216 return cons_to_long (rest
);
8218 rest
= Fnreverse (rest
);
8222 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8225 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8226 if (style
< min_style
)
8229 if (style
== normal
)
8236 while (!NILP (rest
));
8238 HASH_VALUE (h
, i
) = best
;
8239 return cons_to_long (best
);
8243 fm_style_to_face_attributes (fm_style
)
8244 FMFontStyle fm_style
;
8248 fm_style
&= (bold
| italic
);
8249 tem
= assq_no_quit (make_number (fm_style
),
8250 fm_style_face_attributes_alist
);
8254 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8255 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8256 fm_style_face_attributes_alist
=
8257 Fcons (Fcons (make_number (fm_style
), tem
),
8258 fm_style_face_attributes_alist
);
8264 atsu_find_font_family_name (font_id
)
8269 Lisp_Object family
= Qnil
;
8271 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8272 kFontMacintoshPlatform
, kFontNoScript
,
8273 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8276 family
= make_uninit_string (len
);
8277 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8278 kFontMacintoshPlatform
, kFontNoScript
,
8279 kFontNoLanguage
, len
, SDATA (family
),
8283 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8289 mac_atsu_font_face_attributes (font_id
)
8292 Lisp_Object family
, style_attrs
;
8294 family
= atsu_find_font_family_name (font_id
);
8297 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8298 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8302 /* Sets up the table font_name_table to contain the list of all fonts
8303 in the system the first time the table is used so that the Resource
8304 Manager need not be accessed every time this information is
8308 init_font_name_table ()
8310 #if TARGET_API_MAC_CARBON
8311 FMFontFamilyIterator ffi
;
8312 FMFontFamilyInstanceIterator ffii
;
8314 Lisp_Object text_encoding_info_alist
;
8315 struct gcpro gcpro1
;
8317 text_encoding_info_alist
= create_text_encoding_info_alist ();
8320 #if USE_CG_TEXT_DRAWING
8321 init_cg_text_anti_aliasing_threshold ();
8323 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8324 text_encoding_info_alist
)))
8327 struct Lisp_Hash_Table
*h
;
8329 ItemCount nfonts
, i
;
8330 ATSUFontID
*font_ids
= NULL
;
8331 Lisp_Object prev_family
= Qnil
;
8335 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8336 make_float (DEFAULT_REHASH_SIZE
),
8337 make_float (DEFAULT_REHASH_THRESHOLD
),
8339 h
= XHASH_TABLE (atsu_font_id_hash
);
8341 err
= ATSUFontCount (&nfonts
);
8344 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8345 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8348 for (i
= 0; i
< nfonts
; i
++)
8352 family
= atsu_find_font_family_name (font_ids
[i
]);
8353 if (NILP (family
) || SREF (family
, 0) == '.')
8355 if (!NILP (Fequal (prev_family
, family
)))
8356 family
= prev_family
;
8358 j
= hash_lookup (h
, family
, &hash_code
);
8361 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8362 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8365 else if (EQ (prev_family
, family
))
8366 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8368 prev_family
= family
;
8375 /* Create a dummy instance iterator here to avoid creating and
8376 destroying it in the loop. */
8377 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8379 /* Create an iterator to enumerate the font families. */
8380 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8383 FMDisposeFontFamilyInstanceIterator (&ffii
);
8387 GCPRO1 (text_encoding_info_alist
);
8389 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8395 TextEncoding encoding
;
8396 TextEncodingBase sc
;
8397 Lisp_Object text_encoding_info
, family
;
8399 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8405 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8407 sc
= GetTextEncodingBase (encoding
);
8408 text_encoding_info
= assq_no_quit (make_number (sc
),
8409 text_encoding_info_alist
);
8410 if (NILP (text_encoding_info
))
8411 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8412 text_encoding_info_alist
);
8413 decode_mac_font_name (name
, sizeof (name
),
8414 XCAR (XCDR (text_encoding_info
)));
8415 family
= build_string (name
);
8416 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8418 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8419 fm_font_family_alist
);
8421 /* Point the instance iterator at the current font family. */
8422 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8425 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8428 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8430 if (size
> 0 || style
== normal
)
8431 for (; CONSP (rest
); rest
= XCDR (rest
))
8432 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8438 /* Dispose of the iterators. */
8439 FMDisposeFontFamilyIterator (&ffi
);
8440 FMDisposeFontFamilyInstanceIterator (&ffii
);
8441 #else /* !TARGET_API_MAC_CARBON */
8443 SInt16 fontnum
, old_fontnum
;
8444 int num_mac_fonts
= CountResources('FOND');
8446 Handle font_handle
, font_handle_2
;
8447 short id
, scriptcode
;
8450 struct FontAssoc
*fat
;
8451 struct AsscEntry
*assc_entry
;
8452 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8453 struct gcpro gcpro1
;
8455 GetPort (&port
); /* save the current font number used */
8456 old_fontnum
= port
->txFont
;
8458 text_encoding_info_alist
= create_text_encoding_info_alist ();
8460 GCPRO1 (text_encoding_info_alist
);
8462 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8464 font_handle
= GetIndResource ('FOND', i
);
8468 GetResInfo (font_handle
, &id
, &type
, name
);
8469 GetFNum (name
, &fontnum
);
8471 if (fontnum
== 0 || *name
== '.')
8475 scriptcode
= FontToScript (fontnum
);
8476 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8477 text_encoding_info_alist
);
8478 if (NILP (text_encoding_info
))
8479 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8480 text_encoding_info_alist
);
8481 decode_mac_font_name (name
, sizeof (name
),
8482 XCAR (XCDR (text_encoding_info
)));
8483 family
= build_string (name
);
8484 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8486 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8487 fm_font_family_alist
);
8490 HLock (font_handle
);
8492 if (GetResourceSizeOnDisk (font_handle
)
8493 >= sizeof (struct FamRec
))
8495 fat
= (struct FontAssoc
*) (*font_handle
8496 + sizeof (struct FamRec
));
8498 = (struct AsscEntry
*) (*font_handle
8499 + sizeof (struct FamRec
)
8500 + sizeof (struct FontAssoc
));
8502 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8504 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8506 for (; CONSP (rest
); rest
= XCDR (rest
))
8507 add_mac_font_name (name
, assc_entry
->fontSize
,
8508 assc_entry
->fontStyle
,
8509 SDATA (XCAR (rest
)));
8513 HUnlock (font_handle
);
8514 font_handle_2
= GetNextFOND (font_handle
);
8515 ReleaseResource (font_handle
);
8516 font_handle
= font_handle_2
;
8518 while (ResError () == noErr
&& font_handle
);
8523 TextFont (old_fontnum
);
8524 #endif /* !TARGET_API_MAC_CARBON */
8529 mac_clear_font_name_table ()
8533 for (i
= 0; i
< font_name_count
; i
++)
8534 xfree (font_name_table
[i
]);
8535 xfree (font_name_table
);
8536 font_name_table
= NULL
;
8537 font_name_table_size
= font_name_count
= 0;
8538 fm_font_family_alist
= Qnil
;
8542 enum xlfd_scalable_field_index
8544 XLFD_SCL_PIXEL_SIZE
,
8545 XLFD_SCL_POINT_SIZE
,
8550 static const int xlfd_scalable_fields
[] =
8559 mac_do_list_fonts (pattern
, maxnames
)
8560 const char *pattern
;
8564 Lisp_Object font_list
= Qnil
;
8565 struct xlfdpat
*pat
;
8568 int scl_val
[XLFD_SCL_LAST
], *val
;
8572 if (font_name_table
== NULL
) /* Initialize when first used. */
8573 init_font_name_table ();
8575 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8578 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8579 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8580 fonts are scaled according to the specified size. */
8583 field
= xlfd_scalable_fields
;
8591 if ('0' <= *ptr
&& *ptr
<= '9')
8593 *val
= *ptr
++ - '0';
8594 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8595 *val
= *val
* 10 + *ptr
++ - '0';
8602 ptr
= strchr (ptr
, '-');
8605 while (ptr
&& i
< 14);
8607 if (i
== 14 && ptr
== NULL
)
8609 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8610 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8611 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8612 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8614 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8615 scl_val
[XLFD_SCL_POINT_SIZE
] =
8616 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8617 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8619 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8620 scl_val
[XLFD_SCL_AVGWIDTH
] =
8621 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8622 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8626 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8628 pat
= xlfdpat_create (pattern
);
8632 exact
= xlfdpat_exact_p (pat
);
8634 for (i
= 0; i
< font_name_count
; i
++)
8636 if (xlfdpat_match (pat
, font_name_table
[i
]))
8638 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8639 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8642 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8643 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8645 int former_len
= ptr
- font_name_table
[i
];
8647 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8648 memcpy (scaled
, font_name_table
[i
], former_len
);
8649 sprintf (scaled
+ former_len
,
8650 "-%d-%d-72-72-m-%d-%s",
8651 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8652 scl_val
[XLFD_SCL_POINT_SIZE
],
8653 scl_val
[XLFD_SCL_AVGWIDTH
],
8654 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8656 if (xlfdpat_match (pat
, scaled
))
8658 font_list
= Fcons (build_string (scaled
), font_list
);
8660 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8668 xlfdpat_destroy (pat
);
8673 /* Return a list of names of available fonts matching PATTERN on frame F.
8675 Frame F null means we have not yet created any frame on Mac, and
8676 consult the first display in x_display_list. MAXNAMES sets a limit
8677 on how many fonts to match. */
8680 x_list_fonts (f
, pattern
, size
, maxnames
)
8682 Lisp_Object pattern
;
8685 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8686 struct mac_display_info
*dpyinfo
8687 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8689 xassert (size
<= 0);
8691 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8692 if (NILP (patterns
))
8693 patterns
= Fcons (pattern
, Qnil
);
8695 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8697 pattern
= XCAR (patterns
);
8699 if (!STRINGP (pattern
))
8702 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8703 key
= Fcons (pattern
, make_number (maxnames
));
8705 list
= Fassoc (key
, tem
);
8708 list
= Fcdr_safe (list
);
8709 /* We have a cashed list. Don't have to get the list again. */
8714 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8717 /* MAC_TODO: add code for matching outline fonts here */
8719 /* Now store the result in the cache. */
8720 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8721 Fcons (Fcons (key
, list
),
8722 XCAR (XCDR (dpyinfo
->name_list_element
))));
8725 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8734 /* Check that FONT is valid on frame F. It is if it can be found in F's
8738 x_check_font (f
, font
)
8743 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8745 xassert (font
!= NULL
);
8747 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8748 if (dpyinfo
->font_table
[i
].name
8749 && font
== dpyinfo
->font_table
[i
].font
)
8752 xassert (i
< dpyinfo
->n_fonts
);
8755 #endif /* GLYPH_DEBUG != 0 */
8757 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8758 Note: There are (broken) X fonts out there with invalid XFontStruct
8759 min_bounds contents. For example, handa@etl.go.jp reports that
8760 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8761 have font->min_bounds.width == 0. */
8764 x_font_min_bounds (font
, w
, h
)
8765 MacFontStruct
*font
;
8768 *h
= FONT_HEIGHT (font
);
8769 *w
= font
->min_bounds
.width
;
8773 /* Compute the smallest character width and smallest font height over
8774 all fonts available on frame F. Set the members smallest_char_width
8775 and smallest_font_height in F's x_display_info structure to
8776 the values computed. Value is non-zero if smallest_font_height or
8777 smallest_char_width become smaller than they were before. */
8780 x_compute_min_glyph_bounds (f
)
8784 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8785 MacFontStruct
*font
;
8786 int old_width
= dpyinfo
->smallest_char_width
;
8787 int old_height
= dpyinfo
->smallest_font_height
;
8789 dpyinfo
->smallest_font_height
= 100000;
8790 dpyinfo
->smallest_char_width
= 100000;
8792 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8793 if (dpyinfo
->font_table
[i
].name
)
8795 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8798 font
= (MacFontStruct
*) fontp
->font
;
8799 xassert (font
!= (MacFontStruct
*) ~0);
8800 x_font_min_bounds (font
, &w
, &h
);
8802 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8803 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8806 xassert (dpyinfo
->smallest_char_width
> 0
8807 && dpyinfo
->smallest_font_height
> 0);
8809 return (dpyinfo
->n_fonts
== 1
8810 || dpyinfo
->smallest_char_width
< old_width
8811 || dpyinfo
->smallest_font_height
< old_height
);
8815 /* Determine whether given string is a fully-specified XLFD: all 14
8816 fields are present, none is '*'. */
8819 is_fully_specified_xlfd (p
)
8828 for (i
= 0; i
< 13; i
++)
8830 q
= strchr (p
+ 1, '-');
8833 if (q
- p
== 2 && *(p
+ 1) == '*')
8838 if (strchr (p
+ 1, '-') != NULL
)
8841 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8848 /* mac_load_query_font creates and returns an internal representation
8849 for a font in a MacFontStruct struct. There is really no concept
8850 corresponding to "loading" a font on the Mac. But we check its
8851 existence and find the font number and all other information for it
8852 and store them in the returned MacFontStruct. */
8854 static MacFontStruct
*
8855 mac_load_query_font (f
, fontname
)
8865 static ATSUFontID font_id
;
8866 ATSUStyle mac_style
= NULL
;
8869 #if TARGET_API_MAC_CARBON
8870 TextEncoding encoding
;
8875 MacFontStruct
*font
;
8876 XCharStruct
*space_bounds
= NULL
, *pcm
;
8878 if (is_fully_specified_xlfd (fontname
))
8882 Lisp_Object matched_fonts
;
8884 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8885 if (NILP (matched_fonts
))
8887 name
= SDATA (XCAR (matched_fonts
));
8890 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8894 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8897 static const ATSUAttributeTag tags
[] =
8898 {kATSUFontTag
, kATSUSizeTag
,
8899 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8900 static const ByteCount sizes
[] =
8901 {sizeof (ATSUFontID
), sizeof (Fixed
),
8902 sizeof (Boolean
), sizeof (Boolean
)};
8903 static Fixed size_fixed
;
8904 static Boolean bold_p
, italic_p
;
8905 static const ATSUAttributeValuePtr values
[] =
8906 {&font_id
, &size_fixed
,
8907 &bold_p
, &italic_p
};
8908 static const ATSUFontFeatureType types
[] =
8909 {kAllTypographicFeaturesType
, kDiacriticsType
};
8910 static const ATSUFontFeatureSelector selectors
[] =
8911 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8914 font_id
= atsu_find_font_from_family_name (family
);
8915 if (font_id
== kATSUInvalidFontID
)
8917 size_fixed
= Long2Fix (size
);
8918 bold_p
= (fontface
& bold
) != 0;
8919 italic_p
= (fontface
& italic
) != 0;
8920 err
= ATSUCreateStyle (&mac_style
);
8923 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8927 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8928 tags
, sizes
, values
);
8931 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8934 scriptcode
= kTextEncodingMacUnicode
;
8939 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8943 fontnum
= XINT (XCDR (tmp
));
8944 #if TARGET_API_MAC_CARBON
8945 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8947 scriptcode
= GetTextEncodingBase (encoding
);
8949 scriptcode
= FontToScript (fontnum
);
8953 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8955 font
->mac_fontnum
= fontnum
;
8956 font
->mac_fontsize
= size
;
8957 font
->mac_fontface
= fontface
;
8958 font
->mac_scriptcode
= scriptcode
;
8960 font
->mac_style
= mac_style
;
8961 #if USE_CG_TEXT_DRAWING
8962 font
->cg_font
= NULL
;
8963 font
->cg_glyphs
= NULL
;
8967 /* Apple Japanese (SJIS) font is listed as both
8968 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8969 (Roman script) in init_font_name_table (). The latter should be
8970 treated as a one-byte font. */
8971 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8972 font
->mac_scriptcode
= smRoman
;
8974 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8977 if (font
->mac_style
)
8982 font
->min_byte1
= 0;
8983 font
->max_byte1
= 0xff;
8984 font
->min_char_or_byte2
= 0;
8985 font
->max_char_or_byte2
= 0xff;
8987 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8988 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8989 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8990 pcm_init (font
->bounds
.rows
[0], 0x100);
8992 #if USE_CG_TEXT_DRAWING
8996 ATSFontRef ats_font
;
8998 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
9000 /* Use CG text drawing if italic/bold is not synthesized. */
9001 if (err
== noErr
&& style
== fontface
)
9003 ats_font
= FMGetATSFontRefFromFont (font_id
);
9004 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
9010 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
9011 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
9014 space_bounds
= font
->bounds
.rows
[0] + 0x20;
9015 err
= mac_query_char_extents (font
->mac_style
, 0x20,
9016 &font
->ascent
, &font
->descent
,
9018 #if USE_CG_TEXT_DRAWING
9019 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
9026 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
9028 mac_unload_font (&one_mac_display_info
, font
);
9032 pcm
= font
->bounds
.rows
[0];
9033 for (c
= 0x21; c
<= 0xff; c
++)
9036 /* Soft hyphen is not supported in ATSUI. */
9040 #if USE_CG_TEXT_DRAWING
9041 if (font
->cg_glyphs
)
9051 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
9052 pcm
? pcm
+ c
: NULL
,
9053 #if USE_CG_TEXT_DRAWING
9054 (font
->cg_glyphs
? font
->cg_glyphs
+ c
9061 #if USE_CG_TEXT_DRAWING
9062 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
9064 /* Don't use CG text drawing if font substitution occurs in
9065 ASCII or Latin-1 characters. */
9066 CGFontRelease (font
->cg_font
);
9067 font
->cg_font
= NULL
;
9068 xfree (font
->cg_glyphs
);
9069 font
->cg_glyphs
= NULL
;
9080 FontInfo the_fontinfo
;
9081 int is_two_byte_font
;
9084 mac_prepare_for_quickdraw (f
);
9086 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
9090 TextFace (fontface
);
9092 GetFontInfo (&the_fontinfo
);
9094 font
->ascent
= the_fontinfo
.ascent
;
9095 font
->descent
= the_fontinfo
.descent
;
9097 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
9098 || font
->mac_scriptcode
== smTradChinese
9099 || font
->mac_scriptcode
== smSimpChinese
9100 || font
->mac_scriptcode
== smKorean
);
9102 if (is_two_byte_font
)
9106 font
->min_byte1
= 0xa1;
9107 font
->max_byte1
= 0xfe;
9108 font
->min_char_or_byte2
= 0xa1;
9109 font
->max_char_or_byte2
= 0xfe;
9111 /* Use the width of an "ideographic space" of that font
9112 because the_fontinfo.widMax returns the wrong width for
9114 switch (font
->mac_scriptcode
)
9117 font
->min_byte1
= 0x81;
9118 font
->max_byte1
= 0xfc;
9119 font
->min_char_or_byte2
= 0x40;
9120 font
->max_char_or_byte2
= 0xfc;
9121 char_width
= StringWidth("\p\x81\x40");
9124 font
->min_char_or_byte2
= 0x40;
9125 char_width
= StringWidth("\p\xa1\x40");
9128 char_width
= StringWidth("\p\xa1\xa1");
9131 char_width
= StringWidth("\p\xa1\xa1");
9135 font
->bounds
.per_char
= NULL
;
9137 if (fontface
& italic
)
9138 font
->max_bounds
.rbearing
= char_width
+ 1;
9140 font
->max_bounds
.rbearing
= char_width
;
9141 font
->max_bounds
.lbearing
= 0;
9142 font
->max_bounds
.width
= char_width
;
9143 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
9144 font
->max_bounds
.descent
= the_fontinfo
.descent
;
9146 font
->min_bounds
= font
->max_bounds
;
9152 font
->min_byte1
= font
->max_byte1
= 0;
9153 font
->min_char_or_byte2
= 0x20;
9154 font
->max_char_or_byte2
= 0xff;
9156 font
->bounds
.per_char
=
9157 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9158 bzero (font
->bounds
.per_char
,
9159 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9161 space_bounds
= font
->bounds
.per_char
;
9162 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9163 &font
->descent
, space_bounds
, NULL
);
9164 if (err
!= noErr
|| space_bounds
->width
<= 0)
9166 mac_unload_font (&one_mac_display_info
, font
);
9170 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9171 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9179 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9180 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9183 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9185 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9187 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9189 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9191 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9194 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9196 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9198 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9200 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9202 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9207 font
->mac_style
== NULL
&&
9209 font
->max_bounds
.width
== font
->min_bounds
.width
9210 && font
->min_bounds
.lbearing
>= 0
9211 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9213 /* Fixed width and no overhangs. */
9214 xfree (font
->bounds
.per_char
);
9215 font
->bounds
.per_char
= NULL
;
9219 #if !defined (MAC_OS8) || USE_ATSUI
9220 /* AppKit and WebKit do some adjustment to the heights of Courier,
9221 Helvetica, and Times. This only works on the environments where
9222 srcCopy text transfer mode is never used. */
9224 #ifdef MAC_OS8 /* implies USE_ATSUI */
9227 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9228 || strcmp (family
, "times") == 0))
9229 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9237 mac_unload_font (dpyinfo
, font
)
9238 struct mac_display_info
*dpyinfo
;
9241 xfree (font
->full_name
);
9243 if (font
->mac_style
)
9247 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9248 if (font
->bounds
.rows
[i
])
9249 xfree (font
->bounds
.rows
[i
]);
9250 xfree (font
->bounds
.rows
);
9251 ATSUDisposeStyle (font
->mac_style
);
9255 if (font
->bounds
.per_char
)
9256 xfree (font
->bounds
.per_char
);
9257 #if USE_CG_TEXT_DRAWING
9259 CGFontRelease (font
->cg_font
);
9260 if (font
->cg_glyphs
)
9261 xfree (font
->cg_glyphs
);
9267 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9268 pointer to the structure font_info while allocating it dynamically.
9269 If SIZE is 0, load any size of font.
9270 If loading is failed, return NULL. */
9273 x_load_font (f
, fontname
, size
)
9275 register char *fontname
;
9278 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9279 Lisp_Object font_names
;
9281 /* Get a list of all the fonts that match this name. Once we
9282 have a list of matching fonts, we compare them against the fonts
9283 we already have by comparing names. */
9284 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9286 if (!NILP (font_names
))
9291 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9292 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9293 if (dpyinfo
->font_table
[i
].name
9294 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9295 SDATA (XCAR (tail
)))
9296 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9297 SDATA (XCAR (tail
)))))
9298 return (dpyinfo
->font_table
+ i
);
9303 /* Load the font and add it to the table. */
9305 struct MacFontStruct
*font
;
9306 struct font_info
*fontp
;
9309 fontname
= (char *) SDATA (XCAR (font_names
));
9312 font
= mac_load_query_font (f
, fontname
);
9317 /* Find a free slot in the font table. */
9318 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9319 if (dpyinfo
->font_table
[i
].name
== NULL
)
9322 /* If no free slot found, maybe enlarge the font table. */
9323 if (i
== dpyinfo
->n_fonts
9324 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9327 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9328 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9330 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9333 fontp
= dpyinfo
->font_table
+ i
;
9334 if (i
== dpyinfo
->n_fonts
)
9337 /* Now fill in the slots of *FONTP. */
9339 bzero (fontp
, sizeof (*fontp
));
9341 fontp
->font_idx
= i
;
9342 fontp
->charset
= -1; /* fs_load_font sets it. */
9343 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9344 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9346 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9348 /* Fixed width font. */
9349 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9356 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9357 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9359 fontp
->space_width
= pcm
->width
;
9361 fontp
->space_width
= FONT_WIDTH (font
);
9365 int width
= pcm
->width
;
9366 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9367 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9368 width
+= pcm
->width
;
9369 fontp
->average_width
= width
/ 95;
9372 fontp
->average_width
= FONT_WIDTH (font
);
9375 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9376 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9378 fontp
->size
= font
->max_bounds
.width
;
9379 fontp
->height
= FONT_HEIGHT (font
);
9381 /* For some font, ascent and descent in max_bounds field is
9382 larger than the above value. */
9383 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9384 if (max_height
> fontp
->height
)
9385 fontp
->height
= max_height
;
9388 /* MAC_TODO: The script encoding is irrelevant in unicode? */
9389 /* The slot `encoding' specifies how to map a character
9390 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9391 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9392 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9393 2:0xA020..0xFF7F). For the moment, we don't know which charset
9394 uses this font. So, we set information in fontp->encoding_type
9395 which is never used by any charset. If mapping can't be
9396 decided, set FONT_ENCODING_NOT_DECIDED. */
9397 if (font
->mac_scriptcode
== smJapanese
)
9398 fontp
->encoding_type
= 4;
9401 fontp
->encoding_type
9402 = (font
->max_byte1
== 0
9404 ? (font
->min_char_or_byte2
< 0x80
9405 ? (font
->max_char_or_byte2
< 0x80
9406 ? 0 /* 0x20..0x7F */
9407 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9408 : 1) /* 0xA0..0xFF */
9410 : (font
->min_byte1
< 0x80
9411 ? (font
->max_byte1
< 0x80
9412 ? (font
->min_char_or_byte2
< 0x80
9413 ? (font
->max_char_or_byte2
< 0x80
9414 ? 0 /* 0x2020..0x7F7F */
9415 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9416 : 3) /* 0x20A0..0x7FFF */
9417 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9418 : (font
->min_char_or_byte2
< 0x80
9419 ? (font
->max_char_or_byte2
< 0x80
9420 ? 2 /* 0xA020..0xFF7F */
9421 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9422 : 1))); /* 0xA0A0..0xFFFF */
9425 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9426 fontp
->baseline_offset
9427 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9428 ? (long) value
: 0);
9429 fontp
->relative_compose
9430 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9431 ? (long) value
: 0);
9432 fontp
->default_ascent
9433 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9434 ? (long) value
: 0);
9436 fontp
->baseline_offset
= 0;
9437 fontp
->relative_compose
= 0;
9438 fontp
->default_ascent
= 0;
9441 /* Set global flag fonts_changed_p to non-zero if the font loaded
9442 has a character with a smaller width than any other character
9443 before, or if the font loaded has a smaller height than any
9444 other font loaded before. If this happens, it will make a
9445 glyph matrix reallocation necessary. */
9446 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9453 /* Return a pointer to struct font_info of a font named FONTNAME for
9454 frame F. If no such font is loaded, return NULL. */
9457 x_query_font (f
, fontname
)
9459 register char *fontname
;
9461 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9464 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9465 if (dpyinfo
->font_table
[i
].name
9466 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9467 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9468 return (dpyinfo
->font_table
+ i
);
9473 /* Find a CCL program for a font specified by FONTP, and set the member
9474 `encoder' of the structure. */
9477 x_find_ccl_program (fontp
)
9478 struct font_info
*fontp
;
9480 Lisp_Object list
, elt
;
9482 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9486 && STRINGP (XCAR (elt
))
9487 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9493 struct ccl_program
*ccl
9494 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9496 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9499 fontp
->font_encoder
= ccl
;
9503 #if USE_MAC_FONT_PANEL
9504 /* Whether Font Panel has been shown before. The first call to font
9505 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9506 slow. This variable is used for deferring such a call as much as
9508 static int font_panel_shown_p
= 0;
9510 extern Lisp_Object Qfont
;
9511 static Lisp_Object Qpanel_closed
, Qselection
;
9513 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9517 const EventParamName
*,
9518 const EventParamType
*));
9521 mac_font_panel_visible_p ()
9523 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9526 static pascal OSStatus
9527 mac_handle_font_event (next_handler
, event
, data
)
9528 EventHandlerCallRef next_handler
;
9532 OSStatus result
, err
;
9535 const EventParamName
*names
;
9536 const EventParamType
*types
;
9537 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9538 kEventParamATSUFontSize
,
9539 kEventParamFMFontFamily
,
9540 kEventParamFMFontStyle
,
9541 kEventParamFMFontSize
,
9542 kEventParamFontColor
};
9543 static const EventParamType types_sel
[] = {typeATSUFontID
,
9550 result
= CallNextEventHandler (next_handler
, event
);
9551 if (result
!= eventNotHandledErr
)
9554 switch (GetEventKind (event
))
9556 case kEventFontPanelClosed
:
9557 id_key
= Qpanel_closed
;
9563 case kEventFontSelection
:
9564 id_key
= Qselection
;
9565 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9571 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9581 mac_show_hide_font_panel ()
9583 if (!font_panel_shown_p
)
9587 static const EventTypeSpec specs
[] =
9588 {{kEventClassFont
, kEventFontPanelClosed
},
9589 {kEventClassFont
, kEventFontSelection
}};
9591 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9592 GetEventTypeCount (specs
),
9597 font_panel_shown_p
= 1;
9600 return FPShowHideFontPanel ();
9604 mac_set_font_info_for_selection (f
, face_id
, c
)
9609 EventTargetRef target
= NULL
;
9610 XFontStruct
*font
= NULL
;
9612 if (!mac_font_panel_visible_p ())
9617 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9619 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9623 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9624 face
= FACE_FROM_ID (f
, face_id
);
9630 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9633 if (font
->mac_fontnum
!= -1)
9635 FontSelectionQDStyle qd_style
;
9637 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9638 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9639 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9640 qd_style
.size
= font
->mac_fontsize
;
9641 qd_style
.hasColor
= false;
9643 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9644 1, &qd_style
, target
);
9647 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9648 1, &font
->mac_style
, target
);
9656 /* The Mac Event loop code */
9658 #if !TARGET_API_MAC_CARBON
9660 #include <Quickdraw.h>
9661 #include <Balloons.h>
9662 #include <Devices.h>
9664 #include <Gestalt.h>
9666 #include <Processes.h>
9668 #include <ToolUtils.h>
9669 #include <TextUtils.h>
9670 #include <Dialogs.h>
9673 #include <Resources.h>
9678 #endif /* ! TARGET_API_MAC_CARBON */
9683 #define DEFAULT_NUM_COLS 80
9685 #define MIN_DOC_SIZE 64
9686 #define MAX_DOC_SIZE 32767
9688 #define EXTRA_STACK_ALLOC (256 * 1024)
9690 #define ARGV_STRING_LIST_ID 129
9691 #define ABOUT_ALERT_ID 128
9692 #define RAM_TOO_LARGE_ALERT_ID 129
9694 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9695 Lisp_Object Qreverse
;
9698 /* Modifier associated with the control key, or nil to ignore. */
9699 Lisp_Object Vmac_control_modifier
;
9701 /* Modifier associated with the option key, or nil to ignore. */
9702 Lisp_Object Vmac_option_modifier
;
9704 /* Modifier associated with the command key, or nil to ignore. */
9705 Lisp_Object Vmac_command_modifier
;
9707 /* Modifier associated with the function key, or nil to ignore. */
9708 Lisp_Object Vmac_function_modifier
;
9710 /* True if the option and command modifiers should be used to emulate
9711 a three button mouse */
9712 Lisp_Object Vmac_emulate_three_button_mouse
;
9714 #if TARGET_API_MAC_CARBON
9715 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9716 mouse-2, instead of mouse-3. */
9717 int mac_wheel_button_is_mouse_2
;
9719 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9720 for processing before Emacs sees it. */
9721 int mac_pass_command_to_system
;
9723 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9724 for processing before Emacs sees it. */
9725 int mac_pass_control_to_system
;
9728 /* Points to the variable `inev' in the function XTread_socket. It is
9729 used for passing an input event to the function back from
9730 Carbon/Apple event handlers. */
9731 static struct input_event
*read_socket_inev
= NULL
;
9733 /* Whether or not the screen configuration has changed. */
9734 static int mac_screen_config_changed
= 0;
9736 Point saved_menu_event_location
;
9739 #if TARGET_API_MAC_CARBON
9740 static Lisp_Object Qhi_command
;
9742 extern Lisp_Object Qwindow
;
9743 static Lisp_Object Qtoolbar_switch_mode
;
9746 static TSMDocumentID tsm_document_id
;
9747 Lisp_Object Qtext_input
;
9748 Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9749 Lisp_Object Vmac_ts_active_input_overlay
, Vmac_ts_active_input_buf
;
9750 extern Lisp_Object Qbefore_string
;
9751 static Lisp_Object Vmac_ts_script_language_on_focus
;
9752 static Lisp_Object saved_ts_script_language_on_focus
;
9753 static ScriptLanguageRecord saved_ts_language
;
9754 static Component saved_ts_component
;
9756 #endif /* TARGET_API_MAC_CARBON */
9757 extern int mac_ready_for_apple_events
;
9758 extern Lisp_Object Qundefined
;
9759 extern void init_apple_event_handler
P_ ((void));
9760 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9761 Lisp_Object
*, Lisp_Object
*,
9763 extern OSErr init_coercion_handler
P_ ((void));
9766 extern OSErr install_drag_handler
P_ ((WindowRef
));
9767 extern void remove_drag_handler
P_ ((WindowRef
));
9769 #if TARGET_API_MAC_CARBON
9770 /* Showing help echo string during menu tracking */
9771 extern OSStatus install_menu_target_item_handler
P_ ((void));
9774 extern OSStatus
install_service_handler ();
9775 Lisp_Object Qservice
, Qpaste
, Qperform
;
9776 Lisp_Object Qmouse_drag_overlay
;
9780 extern void init_emacs_passwd_dir ();
9781 extern int emacs_main (int, char **, char **);
9783 extern void initialize_applescript();
9784 extern void terminate_applescript();
9786 /* Table for translating Mac keycode to X keysym values. Contributed
9788 Mapping for special keys is now identical to that in Apple X11
9789 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9790 on the right of the Cmd key on laptops, and fn + `enter' (->
9792 static const unsigned char keycode_to_xkeysym_table
[] = {
9793 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9794 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9795 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9797 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9798 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9799 /*0x38*/ 0, 0, 0, 0,
9800 /*0x3C*/ 0, 0, 0, 0,
9802 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9803 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9804 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9805 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9807 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9808 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9809 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9810 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9812 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9813 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9814 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9815 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9817 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9818 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9819 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9820 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9824 /* Table for translating Mac keycode with the laptop `fn' key to that
9825 without it. Destination symbols in comments are keys on US
9826 keyboard, and they may not be the same on other types of keyboards.
9827 If the destination is identical to the source (f1 ... f12), it
9828 doesn't map `fn' key to a modifier. */
9829 static const unsigned char fn_keycode_to_keycode_table
[] = {
9830 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9831 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9832 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9834 /*0x30*/ 0, 0, 0, 0,
9835 /*0x34*/ 0, 0, 0, 0,
9836 /*0x38*/ 0, 0, 0, 0,
9837 /*0x3C*/ 0, 0, 0, 0,
9839 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9840 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9841 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9842 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9844 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9845 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9846 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9847 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9849 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9850 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9851 /*0x68*/ 0, 0, 0, 0,
9852 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9854 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9855 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9856 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9859 #endif /* MAC_OSX */
9862 #if TARGET_API_MAC_CARBON
9863 mac_to_emacs_modifiers (UInt32 mods
)
9865 mac_to_emacs_modifiers (EventModifiers mods
)
9868 unsigned int result
= 0;
9869 if (mods
& shiftKey
)
9870 result
|= shift_modifier
;
9872 /* Deactivated to simplify configuration:
9873 if Vmac_option_modifier is non-NIL, we fully process the Option
9874 key. Otherwise, we only process it if an additional Ctrl or Command
9875 is pressed. That way the system may convert the character to a
9877 if ((mods & optionKey) &&
9878 (( !NILP(Vmac_option_modifier) ||
9879 ((mods & cmdKey) || (mods & controlKey))))) */
9881 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9882 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9884 result
|= XUINT(val
);
9886 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9887 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9889 result
|= XUINT(val
);
9891 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9892 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9894 result
|= XUINT(val
);
9898 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9899 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9901 result
|= XUINT(val
);
9909 mac_mapped_modifiers (modifiers
)
9912 UInt32 mapped_modifiers_all
=
9913 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9914 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9915 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9918 mapped_modifiers_all
|=
9919 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9922 return mapped_modifiers_all
& modifiers
;
9926 mac_get_emulated_btn ( UInt32 modifiers
)
9929 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9930 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9931 if (modifiers
& cmdKey
)
9932 result
= cmdIs3
? 2 : 1;
9933 else if (modifiers
& optionKey
)
9934 result
= cmdIs3
? 1 : 2;
9941 mac_get_selected_range (w
, range
)
9945 Lisp_Object overlay
= find_symbol_value (Qmouse_drag_overlay
);
9946 struct buffer
*b
= XBUFFER (w
->buffer
);
9947 int begv
= BUF_BEGV (b
), zv
= BUF_ZV (b
);
9950 if (OVERLAYP (overlay
)
9951 && EQ (Foverlay_buffer (overlay
), w
->buffer
)
9952 && (start
= XINT (Foverlay_start (overlay
)),
9953 end
= XINT (Foverlay_end (overlay
)),
9958 if (w
== XWINDOW (selected_window
) && b
== current_buffer
)
9961 start
= marker_position (w
->pointm
);
9963 if (NILP (Vtransient_mark_mode
) || NILP (b
->mark_active
))
9967 int mark_pos
= marker_position (b
->mark
);
9969 if (start
<= mark_pos
)
9983 else if (start
> zv
)
9992 range
->location
= start
- begv
;
9993 range
->length
= end
- start
;
9996 /* Store the text of the buffer BUF from START to END as Unicode
9997 characters in CHARACTERS. Return non-zero if successful. */
10000 mac_store_buffer_text_to_unicode_chars (buf
, start
, end
, characters
)
10001 struct buffer
*buf
;
10003 UniChar
*characters
;
10005 int start_byte
, end_byte
, char_count
, byte_count
;
10006 struct coding_system coding
;
10007 unsigned char *dst
= (unsigned char *) characters
;
10009 start_byte
= buf_charpos_to_bytepos (buf
, start
);
10010 end_byte
= buf_charpos_to_bytepos (buf
, end
);
10011 char_count
= end
- start
;
10012 byte_count
= end_byte
- start_byte
;
10014 if (setup_coding_system (
10015 #ifdef WORDS_BIG_ENDIAN
10016 intern ("utf-16be")
10018 intern ("utf-16le")
10023 coding
.src_multibyte
= !NILP (buf
->enable_multibyte_characters
);
10024 coding
.dst_multibyte
= 0;
10025 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
10026 coding
.composing
= COMPOSITION_DISABLED
;
10028 if (BUF_GPT_BYTE (buf
) <= start_byte
|| end_byte
<= BUF_GPT_BYTE (buf
))
10029 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
10030 byte_count
, char_count
* sizeof (UniChar
));
10033 int first_byte_count
= BUF_GPT_BYTE (buf
) - start_byte
;
10035 encode_coding (&coding
, BUF_BYTE_ADDRESS (buf
, start_byte
), dst
,
10036 first_byte_count
, char_count
* sizeof (UniChar
));
10037 if (coding
.result
== CODING_FINISH_NORMAL
)
10038 encode_coding (&coding
,
10039 BUF_BYTE_ADDRESS (buf
, start_byte
+ first_byte_count
),
10040 dst
+ coding
.produced
,
10041 byte_count
- first_byte_count
,
10042 char_count
* sizeof (UniChar
) - coding
.produced
);
10045 if (coding
.result
!= CODING_FINISH_NORMAL
)
10052 mac_ax_selected_text_range (f
, range
)
10056 mac_get_selected_range (XWINDOW (f
->selected_window
), range
);
10059 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
10061 mac_ax_number_of_characters (f
)
10064 struct buffer
*b
= XBUFFER (XWINDOW (f
->selected_window
)->buffer
);
10066 return BUF_ZV (b
) - BUF_BEGV (b
);
10073 mac_restore_keyboard_input_source ()
10075 OSStatus err
= noErr
;
10076 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10078 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10079 && EQ (saved_ts_script_language_on_focus
, Qt
))
10080 slptr
= &saved_ts_language
;
10081 else if (CONSP (Vmac_ts_script_language_on_focus
)
10082 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10083 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10084 && CONSP (saved_ts_script_language_on_focus
)
10085 && EQ (XCAR (saved_ts_script_language_on_focus
),
10086 XCAR (Vmac_ts_script_language_on_focus
))
10087 && EQ (XCDR (saved_ts_script_language_on_focus
),
10088 XCDR (Vmac_ts_script_language_on_focus
)))
10090 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10091 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10097 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10098 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10099 kKeyboardInputMethodClass
);
10101 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10104 err
= SetTextServiceLanguage (slptr
);
10106 /* Seems to be needed on Mac OS X 10.2. */
10108 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10115 mac_save_keyboard_input_source ()
10118 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10120 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10122 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10124 err
= GetTextServiceLanguage (&saved_ts_language
);
10126 slptr
= &saved_ts_language
;
10128 else if (CONSP (Vmac_ts_script_language_on_focus
)
10129 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10130 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10132 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10133 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10139 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10140 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10141 kKeyboardInputMethodClass
);
10143 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10149 #if TARGET_API_MAC_CARBON
10150 /***** Code to handle C-g testing *****/
10151 extern int quit_char
;
10152 extern int make_ctrl_char
P_ ((int));
10155 mac_quit_char_key_p (modifiers
, key_code
)
10156 UInt32 modifiers
, key_code
;
10159 unsigned long some_state
= 0;
10160 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10161 int c
, emacs_modifiers
;
10163 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
10164 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
10165 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
10166 if (char_code
& ~0xff)
10169 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
10170 if (emacs_modifiers
& ctrl_modifier
)
10171 c
= make_ctrl_char (char_code
);
10173 c
|= (emacs_modifiers
10174 & (meta_modifier
| alt_modifier
10175 | hyper_modifier
| super_modifier
));
10177 return c
== quit_char
;
10181 #if TARGET_API_MAC_CARBON
10182 /* Obtains the event modifiers from the event ref and then calls
10183 mac_to_emacs_modifiers. */
10185 mac_event_to_emacs_modifiers (EventRef eventRef
)
10187 UInt32 mods
= 0, class;
10189 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
10190 sizeof (UInt32
), NULL
, &mods
);
10191 class = GetEventClass (eventRef
);
10192 if (!NILP (Vmac_emulate_three_button_mouse
) &&
10193 (class == kEventClassMouse
|| class == kEventClassCommand
))
10195 mods
&= ~(optionKey
| cmdKey
);
10197 return mac_to_emacs_modifiers (mods
);
10200 /* Given an event ref, return the code to use for the mouse button
10201 code in the emacs input_event. */
10203 mac_get_mouse_btn (EventRef ref
)
10205 EventMouseButton result
= kEventMouseButtonPrimary
;
10206 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
10207 sizeof (EventMouseButton
), NULL
, &result
);
10210 case kEventMouseButtonPrimary
:
10211 if (NILP (Vmac_emulate_three_button_mouse
))
10215 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
10216 sizeof (UInt32
), NULL
, &mods
);
10217 return mac_get_emulated_btn(mods
);
10219 case kEventMouseButtonSecondary
:
10220 return mac_wheel_button_is_mouse_2
? 2 : 1;
10221 case kEventMouseButtonTertiary
:
10222 case 4: /* 4 is the number for the mouse wheel button */
10223 return mac_wheel_button_is_mouse_2
? 1 : 2;
10229 /* Normally, ConvertEventRefToEventRecord will correctly handle all
10230 events. However the click of the mouse wheel is not converted to a
10231 mouseDown or mouseUp event. Likewise for dead key events. This
10232 calls ConvertEventRefToEventRecord, but then checks to see if it is
10233 a mouse up/down, or a dead key Carbon event that has not been
10234 converted, and if so, converts it by hand (to be picked up in the
10235 XTread_socket loop). */
10236 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
10239 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
10245 switch (GetEventClass (eventRef
))
10247 case kEventClassMouse
:
10248 switch (GetEventKind (eventRef
))
10250 case kEventMouseDown
:
10251 eventRec
->what
= mouseDown
;
10255 case kEventMouseUp
:
10256 eventRec
->what
= mouseUp
;
10265 case kEventClassKeyboard
:
10266 switch (GetEventKind (eventRef
))
10268 case kEventRawKeyDown
:
10270 goto keystroke_common
;
10271 case kEventRawKeyRepeat
:
10273 goto keystroke_common
;
10274 case kEventRawKeyUp
:
10278 unsigned char char_codes
;
10281 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
10282 typeChar
, NULL
, sizeof (char),
10283 NULL
, &char_codes
);
10285 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
10286 typeUInt32
, NULL
, sizeof (UInt32
),
10290 eventRec
->what
= action
;
10291 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
10308 /* Need where and when. */
10311 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
10312 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
10313 /* Use two step process because new event modifiers are 32-bit
10314 and old are 16-bit. Currently, only loss is NumLock & Fn. */
10315 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
10316 NULL
, sizeof (UInt32
), NULL
, &mods
);
10317 eventRec
->modifiers
= mods
;
10319 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
10329 do_get_menus (void)
10331 Handle menubar_handle
;
10334 menubar_handle
= GetNewMBar (128);
10335 if(menubar_handle
== NULL
)
10337 SetMenuBar (menubar_handle
);
10340 #if !TARGET_API_MAC_CARBON
10341 menu
= GetMenuRef (M_APPLE
);
10343 AppendResMenu (menu
, 'DRVR');
10351 do_init_managers (void)
10353 #if !TARGET_API_MAC_CARBON
10354 InitGraf (&qd
.thePort
);
10356 FlushEvents (everyEvent
, 0);
10360 InitDialogs (NULL
);
10361 #endif /* !TARGET_API_MAC_CARBON */
10364 #if !TARGET_API_MAC_CARBON
10365 /* set up some extra stack space for use by emacs */
10366 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10368 /* MaxApplZone must be called for AppleScript to execute more
10369 complicated scripts */
10372 #endif /* !TARGET_API_MAC_CARBON */
10376 do_check_ram_size (void)
10378 SInt32 physical_ram_size
, logical_ram_size
;
10380 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10381 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10382 || physical_ram_size
> (1 << VALBITS
)
10383 || logical_ram_size
> (1 << VALBITS
))
10385 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10389 #endif /* MAC_OS8 */
10392 do_window_update (WindowRef win
)
10394 struct frame
*f
= mac_window_to_frame (win
);
10398 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10400 if (win
!= tip_window
)
10402 if (f
->async_visible
== 0)
10404 /* Update events may occur when a frame gets iconified. */
10406 f
->async_visible
= 1;
10407 f
->async_iconified
= 0;
10408 SET_FRAME_GARBAGED (f
);
10414 #if TARGET_API_MAC_CARBON
10415 RgnHandle region
= NewRgn ();
10417 GetPortVisibleRegion (GetWindowPort (win
), region
);
10418 GetRegionBounds (region
, &r
);
10419 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10421 mac_prepare_for_quickdraw (f
);
10423 UpdateControls (win
, region
);
10424 DisposeRgn (region
);
10426 r
= (*win
->visRgn
)->rgnBBox
;
10427 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10428 UpdateControls (win
, win
->visRgn
);
10437 is_emacs_window (WindowRef win
)
10439 Lisp_Object tail
, frame
;
10444 FOR_EACH_FRAME (tail
, frame
)
10445 if (FRAME_MAC_P (XFRAME (frame
)))
10446 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10457 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10459 err
= ActivateTSMDocument (tsm_document_id
);
10463 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10464 && EQ (saved_ts_script_language_on_focus
, Qt
))
10465 slptr
= &saved_ts_language
;
10466 else if (CONSP (Vmac_ts_script_language_on_focus
)
10467 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10468 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10469 && CONSP (saved_ts_script_language_on_focus
)
10470 && EQ (XCAR (saved_ts_script_language_on_focus
),
10471 XCAR (Vmac_ts_script_language_on_focus
))
10472 && EQ (XCDR (saved_ts_script_language_on_focus
),
10473 XCDR (Vmac_ts_script_language_on_focus
)))
10475 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10476 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10483 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10484 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10485 kKeyboardInputMethodClass
);
10487 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10490 err
= SetTextServiceLanguage (slptr
);
10492 /* Seems to be needed on Mac OS X 10.2. */
10494 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10504 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10506 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10508 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10510 err
= GetTextServiceLanguage (&saved_ts_language
);
10512 slptr
= &saved_ts_language
;
10514 else if (CONSP (Vmac_ts_script_language_on_focus
)
10515 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10516 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10518 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10519 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10525 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10526 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10527 kKeyboardInputMethodClass
);
10529 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10533 err
= DeactivateTSMDocument (tsm_document_id
);
10539 #if !TARGET_API_MAC_CARBON
10541 do_apple_menu (SInt16 menu_item
)
10544 SInt16 da_driver_refnum
;
10546 if (menu_item
== I_ABOUT
)
10547 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10550 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10551 da_driver_refnum
= OpenDeskAcc (item_name
);
10554 #endif /* !TARGET_API_MAC_CARBON */
10556 /* Handle drags in size box. Based on code contributed by Ben
10557 Mesander and IM - Window Manager A. */
10560 do_grow_window (w
, e
)
10562 const EventRecord
*e
;
10565 int rows
, columns
, width
, height
;
10566 struct frame
*f
= mac_window_to_frame (w
);
10567 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10568 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10569 #if TARGET_API_MAC_CARBON
10575 if (size_hints
->flags
& PMinSize
)
10577 min_width
= size_hints
->min_width
;
10578 min_height
= size_hints
->min_height
;
10580 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10582 #if TARGET_API_MAC_CARBON
10583 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10585 height
= new_rect
.bottom
- new_rect
.top
;
10586 width
= new_rect
.right
- new_rect
.left
;
10588 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10589 /* see if it really changed size */
10590 if (grow_size
== 0)
10592 height
= HiWord (grow_size
);
10593 width
= LoWord (grow_size
);
10596 if (width
!= FRAME_PIXEL_WIDTH (f
)
10597 || height
!= FRAME_PIXEL_HEIGHT (f
))
10599 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10600 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10602 x_set_window_size (f
, 0, columns
, rows
);
10607 #if TARGET_API_MAC_CARBON
10609 mac_get_ideal_size (f
)
10612 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10613 WindowRef w
= FRAME_MAC_WINDOW (f
);
10615 Rect standard_rect
;
10616 int height
, width
, columns
, rows
;
10618 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10619 ideal_size
.v
= dpyinfo
->height
;
10620 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10621 /* Adjust the standard size according to character boundaries. */
10622 width
= standard_rect
.right
- standard_rect
.left
;
10623 height
= standard_rect
.bottom
- standard_rect
.top
;
10624 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10625 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10626 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10627 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10633 /* Handle clicks in zoom box. Calculation of "standard state" based
10634 on code in IM - Window Manager A and code contributed by Ben
10635 Mesander. The standard state of an Emacs window is 80-characters
10636 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10639 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10641 Rect zoom_rect
, port_rect
;
10643 struct frame
*f
= mac_window_to_frame (w
);
10644 #if TARGET_API_MAC_CARBON
10645 Point ideal_size
= mac_get_ideal_size (f
);
10647 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10648 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10649 && port_rect
.left
== zoom_rect
.left
10650 && port_rect
.top
== zoom_rect
.top
)
10651 zoom_in_or_out
= inZoomIn
;
10653 zoom_in_or_out
= inZoomOut
;
10656 mac_clear_window (f
);
10658 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10659 #else /* not TARGET_API_MAC_CARBON */
10662 int w_title_height
, rows
;
10663 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10665 GetPort (&save_port
);
10667 SetPortWindowPort (w
);
10669 /* Clear window to avoid flicker. */
10670 EraseRect (&(w
->portRect
));
10671 if (zoom_in_or_out
== inZoomOut
)
10673 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10674 LocalToGlobal (&top_left
);
10676 /* calculate height of window's title bar */
10677 w_title_height
= top_left
.v
- 1
10678 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10680 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10681 zoom_rect
= qd
.screenBits
.bounds
;
10682 zoom_rect
.top
+= w_title_height
;
10683 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10685 zoom_rect
.right
= zoom_rect
.left
10686 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10688 /* Adjust the standard size according to character boundaries. */
10689 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10691 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10693 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10697 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10699 SetPort (save_port
);
10700 #endif /* not TARGET_API_MAC_CARBON */
10702 #if !TARGET_API_MAC_CARBON
10703 /* retrieve window size and update application values */
10704 port_rect
= w
->portRect
;
10705 height
= port_rect
.bottom
- port_rect
.top
;
10706 width
= port_rect
.right
- port_rect
.left
;
10708 mac_handle_size_change (f
, width
, height
);
10709 mac_handle_origin_change (f
);
10714 mac_set_unicode_keystroke_event (code
, buf
)
10716 struct input_event
*buf
;
10718 int charset_id
, c1
, c2
;
10722 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10725 else if (code
< 0x100)
10728 charset_id
= CHARSET_8_BIT_CONTROL
;
10730 charset_id
= charset_latin_iso8859_1
;
10731 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10732 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10737 charset_id
= charset_mule_unicode_0100_24ff
,
10739 else if (code
< 0x33FF)
10740 charset_id
= charset_mule_unicode_2500_33ff
,
10742 else if (code
>= 0xE000)
10743 charset_id
= charset_mule_unicode_e000_ffff
,
10745 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10746 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10747 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10752 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10754 unsigned char char_code
;
10755 UInt32 key_code
, modifiers
;
10756 unsigned long timestamp
;
10757 struct input_event
*buf
;
10759 static SInt16 last_key_script
= -1;
10760 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10761 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10764 if (mapped_modifiers
& kEventKeyModifierFnMask
10765 && key_code
<= 0x7f
10766 && fn_keycode_to_keycode_table
[key_code
])
10767 key_code
= fn_keycode_to_keycode_table
[key_code
];
10770 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10772 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10773 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10775 if (modifiers
& kEventKeyModifierFnMask
10776 && key_code
<= 0x7f
10777 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10778 modifiers
&= ~kEventKeyModifierFnMask
;
10781 else if (mapped_modifiers
)
10783 /* translate the keycode back to determine the original key */
10785 UCKeyboardLayout
*uchr_ptr
= NULL
;
10786 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10788 KeyboardLayoutRef layout
;
10790 err
= KLGetCurrentKeyboardLayout (&layout
);
10792 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10793 (const void **) &uchr_ptr
);
10795 static SInt16 last_key_layout_id
= 0;
10796 static Handle uchr_handle
= (Handle
)-1;
10797 SInt16 current_key_layout_id
=
10798 GetScriptVariable (current_key_script
, smScriptKeys
);
10800 if (uchr_handle
== (Handle
)-1
10801 || last_key_layout_id
!= current_key_layout_id
)
10803 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10804 last_key_layout_id
= current_key_layout_id
;
10807 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10813 UInt16 key_action
= action
- keyDown
;
10814 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10815 UInt32 keyboard_type
= LMGetKbdType ();
10816 SInt32 dead_key_state
= 0;
10818 UniCharCount actual_length
;
10820 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10821 modifier_key_state
, keyboard_type
,
10822 kUCKeyTranslateNoDeadKeysMask
,
10824 1, &actual_length
, &code
);
10825 if (status
== noErr
&& actual_length
== 1)
10826 mac_set_unicode_keystroke_event (code
, buf
);
10828 #endif /* MAC_OSX */
10830 if (buf
->kind
== NO_EVENT
)
10832 /* This code comes from Keyboard Resource, Appendix C of IM
10833 - Text. This is necessary since shift is ignored in KCHR
10834 table translation when option or command is pressed. It
10835 also does not translate correctly control-shift chars
10836 like C-% so mask off shift here also. */
10837 /* Mask off modifier keys that are mapped to some Emacs
10839 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10840 /* set high byte of keycode to modifier high byte*/
10841 int new_key_code
= key_code
| new_modifiers
;
10842 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10843 unsigned long some_state
= 0;
10844 UInt32 new_char_code
;
10846 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10847 if (new_char_code
== 0)
10848 /* Seems like a dead key. Append up-stroke. */
10849 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10853 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10854 buf
->code
= new_char_code
& 0xff;
10859 if (buf
->kind
== NO_EVENT
)
10861 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10862 buf
->code
= char_code
;
10865 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10866 buf
->modifiers
|= (extra_keyboard_modifiers
10867 & (meta_modifier
| alt_modifier
10868 | hyper_modifier
| super_modifier
));
10870 #if TARGET_API_MAC_CARBON
10871 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10872 && buf
->code
>= 0x80 && buf
->modifiers
)
10875 TextEncoding encoding
= kTextEncodingMacRoman
;
10876 TextToUnicodeInfo ttu_info
;
10878 UpgradeScriptInfoToTextEncoding (current_key_script
,
10879 kTextLanguageDontCare
,
10880 kTextRegionDontCare
,
10882 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10887 ByteCount unicode_len
;
10890 pstr
[1] = buf
->code
;
10891 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10893 &unicode_len
, &code
);
10894 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10895 mac_set_unicode_keystroke_event (code
, buf
);
10896 DisposeTextToUnicodeInfo (&ttu_info
);
10901 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10902 && buf
->code
>= 0x80
10903 && last_key_script
!= current_key_script
)
10905 struct input_event event
;
10907 EVENT_INIT (event
);
10908 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10910 event
.code
= current_key_script
;
10911 event
.timestamp
= timestamp
;
10912 kbd_buffer_store_event (&event
);
10913 last_key_script
= current_key_script
;
10918 mac_store_apple_event (class, id
, desc
)
10919 Lisp_Object
class, id
;
10920 const AEDesc
*desc
;
10922 struct input_event buf
;
10926 buf
.kind
= MAC_APPLE_EVENT
;
10929 XSETFRAME (buf
.frame_or_window
,
10930 mac_focus_frame (&one_mac_display_info
));
10931 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10932 is safe to use them during read_socket_hook. */
10933 buf
.arg
= mac_aedesc_to_lisp (desc
);
10934 kbd_buffer_store_event (&buf
);
10937 #if TARGET_API_MAC_CARBON
10939 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10940 event
, num_params
, names
, types
)
10941 AEEventClass
class;
10943 Lisp_Object class_key
, id_key
;
10946 const EventParamName
*names
;
10947 const EventParamType
*types
;
10949 OSStatus err
= eventNotHandledErr
;
10950 Lisp_Object binding
;
10952 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10953 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10955 if (INTEGERP (binding
))
10956 err
= XINT (binding
);
10959 AppleEvent apple_event
;
10960 err
= create_apple_event_from_event_ref (event
, num_params
,
10965 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10966 AEDisposeDesc (&apple_event
);
10967 mac_wakeup_from_rne ();
10976 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10980 const AEDesc
*desc
;
10982 struct input_event buf
;
10986 buf
.kind
= DRAG_N_DROP_EVENT
;
10987 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10988 buf
.timestamp
= TickCount () * (1000 / 60);
10989 XSETINT (buf
.x
, mouse_pos
.h
);
10990 XSETINT (buf
.y
, mouse_pos
.v
);
10991 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10992 buf
.arg
= mac_aedesc_to_lisp (desc
);
10993 kbd_buffer_store_event (&buf
);
10998 mac_store_service_event (event
)
11002 Lisp_Object id_key
;
11004 const EventParamName
*names
;
11005 const EventParamType
*types
;
11006 static const EventParamName names_pfm
[] =
11007 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
11008 static const EventParamType types_pfm
[] =
11009 {typeCFStringRef
, typeCFStringRef
};
11011 switch (GetEventKind (event
))
11013 case kEventServicePaste
:
11020 case kEventServicePerform
:
11022 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
11031 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
11037 #endif /* MAC_OSX */
11039 static pascal OSStatus
11040 mac_handle_window_event (next_handler
, event
, data
)
11041 EventHandlerCallRef next_handler
;
11046 OSStatus err
, result
= eventNotHandledErr
;
11049 XSizeHints
*size_hints
;
11051 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
11052 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11054 return eventNotHandledErr
;
11056 f
= mac_window_to_frame (wp
);
11057 switch (GetEventKind (event
))
11059 /* -- window refresh events -- */
11061 case kEventWindowUpdate
:
11062 result
= CallNextEventHandler (next_handler
, event
);
11063 if (result
!= eventNotHandledErr
)
11066 do_window_update (wp
);
11070 /* -- window state change events -- */
11072 case kEventWindowShowing
:
11073 size_hints
= FRAME_SIZE_HINTS (f
);
11074 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
11076 struct frame
*sf
= SELECTED_FRAME ();
11078 if (!(FRAME_MAC_P (sf
) && sf
->async_visible
))
11079 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
11082 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
11083 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11084 kWindowCascadeStartAtParentWindowScreen
11086 kWindowCascadeOnParentWindowScreen
11089 #if USE_MAC_TOOLBAR
11090 /* This is a workaround. RepositionWindow fails to put
11091 a window at the cascading position when its parent
11092 window has a Carbon HIToolbar. */
11093 if ((f
->left_pos
== sf
->left_pos
11094 && f
->top_pos
== sf
->top_pos
)
11095 || (f
->left_pos
== sf
->left_pos
+ 10 * 2
11096 && f
->top_pos
== sf
->top_pos
+ 32 * 2))
11097 MoveWindowStructure (wp
, sf
->left_pos
+ 10, sf
->top_pos
+ 32);
11104 case kEventWindowHiding
:
11105 /* Before unmapping the window, update the WM_SIZE_HINTS
11106 property to claim that the current position of the window is
11107 user-specified, rather than program-specified, so that when
11108 the window is mapped again, it will be placed at the same
11109 location, without forcing the user to position it by hand
11110 again (they have already done that once for this window.) */
11111 x_wm_set_size_hint (f
, (long) 0, 1);
11115 case kEventWindowShown
:
11116 case kEventWindowHidden
:
11117 case kEventWindowCollapsed
:
11118 case kEventWindowExpanded
:
11119 mac_handle_visibility_change (f
);
11123 case kEventWindowBoundsChanging
:
11124 result
= CallNextEventHandler (next_handler
, event
);
11125 if (result
!= eventNotHandledErr
)
11128 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
11129 NULL
, sizeof (UInt32
), NULL
, &attributes
);
11133 size_hints
= FRAME_SIZE_HINTS (f
);
11134 if ((attributes
& kWindowBoundsChangeUserResize
)
11135 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
11136 == (PResizeInc
| PBaseSize
| PMinSize
)))
11141 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
11142 typeQDRectangle
, NULL
, sizeof (Rect
),
11147 width
= bounds
.right
- bounds
.left
;
11148 height
= bounds
.bottom
- bounds
.top
;
11150 if (width
< size_hints
->min_width
)
11151 width
= size_hints
->min_width
;
11153 width
= size_hints
->base_width
11154 + (int) ((width
- size_hints
->base_width
)
11155 / (float) size_hints
->width_inc
+ .5)
11156 * size_hints
->width_inc
;
11158 if (height
< size_hints
->min_height
)
11159 height
= size_hints
->min_height
;
11161 height
= size_hints
->base_height
11162 + (int) ((height
- size_hints
->base_height
)
11163 / (float) size_hints
->height_inc
+ .5)
11164 * size_hints
->height_inc
;
11166 bounds
.right
= bounds
.left
+ width
;
11167 bounds
.bottom
= bounds
.top
+ height
;
11168 SetEventParameter (event
, kEventParamCurrentBounds
,
11169 typeQDRectangle
, sizeof (Rect
), &bounds
);
11174 case kEventWindowBoundsChanged
:
11175 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
11176 NULL
, sizeof (UInt32
), NULL
, &attributes
);
11180 if (attributes
& kWindowBoundsChangeSizeChanged
)
11184 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
11185 typeQDRectangle
, NULL
, sizeof (Rect
),
11191 width
= bounds
.right
- bounds
.left
;
11192 height
= bounds
.bottom
- bounds
.top
;
11193 mac_handle_size_change (f
, width
, height
);
11194 mac_wakeup_from_rne ();
11198 if (attributes
& kWindowBoundsChangeOriginChanged
)
11199 mac_handle_origin_change (f
);
11204 /* -- window action events -- */
11206 case kEventWindowClose
:
11208 struct input_event buf
;
11211 buf
.kind
= DELETE_WINDOW_EVENT
;
11212 XSETFRAME (buf
.frame_or_window
, f
);
11214 kbd_buffer_store_event (&buf
);
11219 case kEventWindowGetIdealSize
:
11220 result
= CallNextEventHandler (next_handler
, event
);
11221 if (result
!= eventNotHandledErr
)
11225 Point ideal_size
= mac_get_ideal_size (f
);
11227 err
= SetEventParameter (event
, kEventParamDimensions
,
11228 typeQDPoint
, sizeof (Point
), &ideal_size
);
11235 case kEventWindowToolbarSwitchMode
:
11237 static const EventParamName names
[] = {kEventParamDirectObject
,
11238 kEventParamWindowMouseLocation
,
11239 kEventParamKeyModifiers
,
11240 kEventParamMouseButton
,
11241 kEventParamClickCount
,
11242 kEventParamMouseChord
};
11243 static const EventParamType types
[] = {typeWindowRef
,
11249 int num_params
= sizeof (names
) / sizeof (names
[0]);
11251 err
= mac_store_event_ref_as_apple_event (0, 0,
11253 Qtoolbar_switch_mode
,
11263 /* -- window focus events -- */
11265 case kEventWindowFocusAcquired
:
11266 err
= mac_tsm_resume ();
11271 case kEventWindowFocusRelinquish
:
11272 err
= mac_tsm_suspend ();
11285 static pascal OSStatus
11286 mac_handle_application_event (next_handler
, event
, data
)
11287 EventHandlerCallRef next_handler
;
11291 OSStatus err
, result
= eventNotHandledErr
;
11293 switch (GetEventKind (event
))
11296 case kEventAppActivated
:
11297 err
= mac_tsm_resume ();
11300 case kEventAppDeactivated
:
11301 err
= mac_tsm_suspend ();
11315 static pascal OSStatus
11316 mac_handle_keyboard_event (next_handler
, event
, data
)
11317 EventHandlerCallRef next_handler
;
11321 OSStatus err
, result
= eventNotHandledErr
;
11322 UInt32 event_kind
, key_code
, modifiers
;
11323 unsigned char char_code
;
11325 event_kind
= GetEventKind (event
);
11326 switch (event_kind
)
11328 case kEventRawKeyDown
:
11329 case kEventRawKeyRepeat
:
11330 case kEventRawKeyUp
:
11331 /* When using Carbon Events, we need to pass raw keyboard events
11332 to the TSM ourselves. If TSM handles it, it will pass back
11333 noErr, otherwise it will pass back "eventNotHandledErr" and
11334 we can process it normally. */
11335 result
= CallNextEventHandler (next_handler
, event
);
11336 if (result
!= eventNotHandledErr
)
11339 if (read_socket_inev
== NULL
)
11343 if (read_socket_inev
->kind
!= NO_EVENT
)
11350 if (event_kind
== kEventRawKeyUp
)
11353 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11355 sizeof (char), NULL
, &char_code
);
11359 err
= GetEventParameter (event
, kEventParamKeyCode
,
11361 sizeof (UInt32
), NULL
, &key_code
);
11365 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
11367 sizeof (UInt32
), NULL
, &modifiers
);
11371 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11372 char_code
, key_code
, modifiers
,
11374 (GetEventTime (event
) / kEventDurationMillisecond
)),
11386 static pascal OSStatus
11387 mac_handle_command_event (next_handler
, event
, data
)
11388 EventHandlerCallRef next_handler
;
11392 OSStatus err
, result
= eventNotHandledErr
;
11394 static const EventParamName names
[] =
11395 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11396 static const EventParamType types
[] =
11397 {typeHICommand
, typeUInt32
};
11398 int num_params
= sizeof (names
) / sizeof (names
[0]);
11400 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11401 NULL
, sizeof (HICommand
), NULL
, &command
);
11403 return eventNotHandledErr
;
11405 switch (GetEventKind (event
))
11407 case kEventCommandProcess
:
11408 result
= CallNextEventHandler (next_handler
, event
);
11409 if (result
!= eventNotHandledErr
)
11412 err
= GetEventParameter (event
, kEventParamDirectObject
,
11413 typeHICommand
, NULL
,
11414 sizeof (HICommand
), NULL
, &command
);
11416 if (err
!= noErr
|| command
.commandID
== 0)
11419 /* A HI command event is mapped to an Apple event whose event
11420 class symbol is `hi-command' and event ID is its command
11422 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11437 static pascal OSStatus
11438 mac_handle_mouse_event (next_handler
, event
, data
)
11439 EventHandlerCallRef next_handler
;
11443 OSStatus err
, result
= eventNotHandledErr
;
11445 switch (GetEventKind (event
))
11447 case kEventMouseWheelMoved
:
11451 EventMouseWheelAxis axis
;
11455 result
= CallNextEventHandler (next_handler
, event
);
11456 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11459 f
= mac_focus_frame (&one_mac_display_info
);
11461 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11462 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11464 || wp
!= FRAME_MAC_WINDOW (f
))
11467 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11468 typeMouseWheelAxis
, NULL
,
11469 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11470 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11473 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11474 typeQDPoint
, NULL
, sizeof (Point
),
11479 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11480 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11481 if (point
.h
< 0 || point
.v
< 0
11482 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11483 f
->tool_bar_window
))
11486 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11487 typeSInt32
, NULL
, sizeof (SInt32
),
11492 read_socket_inev
->kind
= WHEEL_EVENT
;
11493 read_socket_inev
->code
= 0;
11494 read_socket_inev
->modifiers
=
11495 (mac_event_to_emacs_modifiers (event
)
11496 | ((delta
< 0) ? down_modifier
: up_modifier
));
11497 XSETINT (read_socket_inev
->x
, point
.h
);
11498 XSETINT (read_socket_inev
->y
, point
.v
);
11499 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11513 static pascal OSStatus
11514 mac_handle_text_input_event (next_handler
, event
, data
)
11515 EventHandlerCallRef next_handler
;
11519 OSStatus err
, result
;
11520 Lisp_Object id_key
= Qnil
;
11522 const EventParamName
*names
;
11523 const EventParamType
*types
;
11524 static UInt32 seqno_uaia
= 0;
11525 static const EventParamName names_uaia
[] =
11526 {kEventParamTextInputSendComponentInstance
,
11527 kEventParamTextInputSendRefCon
,
11528 kEventParamTextInputSendSLRec
,
11529 kEventParamTextInputSendFixLen
,
11530 kEventParamTextInputSendText
,
11531 kEventParamTextInputSendUpdateRng
,
11532 kEventParamTextInputSendHiliteRng
,
11533 kEventParamTextInputSendClauseRng
,
11534 kEventParamTextInputSendPinRng
,
11535 kEventParamTextInputSendTextServiceEncoding
,
11536 kEventParamTextInputSendTextServiceMacEncoding
,
11537 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11538 static const EventParamType types_uaia
[] =
11539 {typeComponentInstance
,
11541 typeIntlWritingCode
,
11548 typeTextRangeArray
,
11549 typeTextRangeArray
,
11555 static const EventParamName names_ufke
[] =
11556 {kEventParamTextInputSendComponentInstance
,
11557 kEventParamTextInputSendRefCon
,
11558 kEventParamTextInputSendSLRec
,
11559 kEventParamTextInputSendText
};
11560 static const EventParamType types_ufke
[] =
11561 {typeComponentInstance
,
11563 typeIntlWritingCode
,
11566 result
= CallNextEventHandler (next_handler
, event
);
11567 if (result
!= eventNotHandledErr
)
11570 switch (GetEventKind (event
))
11572 case kEventTextInputUpdateActiveInputArea
:
11573 id_key
= Qupdate_active_input_area
;
11574 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11575 names
= names_uaia
;
11576 types
= types_uaia
;
11577 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11578 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11583 case kEventTextInputUnicodeForKeyEvent
:
11585 EventRef kbd_event
;
11586 UInt32 actual_size
, modifiers
;
11588 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11589 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11592 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11594 sizeof (UInt32
), NULL
, &modifiers
);
11595 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11596 /* There're mapped modifier keys. Process it in
11600 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11601 typeUnicodeText
, NULL
, 0, &actual_size
,
11603 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11607 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11608 typeUnicodeText
, NULL
,
11609 sizeof (UniChar
), NULL
, &code
);
11610 if (err
== noErr
&& code
< 0x80)
11612 /* ASCII character. Process it in do_keystroke. */
11613 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11617 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11618 typeUInt32
, NULL
, sizeof (UInt32
),
11620 if (!(err
== noErr
&& key_code
<= 0x7f
11621 && keycode_to_xkeysym_table
[key_code
]))
11624 mac_focus_frame (&one_mac_display_info
);
11626 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11627 read_socket_inev
->code
= code
;
11628 read_socket_inev
->modifiers
=
11629 mac_to_emacs_modifiers (modifiers
);
11630 read_socket_inev
->modifiers
|=
11631 (extra_keyboard_modifiers
11632 & (meta_modifier
| alt_modifier
11633 | hyper_modifier
| super_modifier
));
11634 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11642 /* Non-ASCII keystrokes without mapped modifiers are
11643 processed at the Lisp level. */
11644 id_key
= Qunicode_for_key_event
;
11645 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11646 names
= names_ufke
;
11647 types
= types_ufke
;
11653 case kEventTextInputOffsetToPos
:
11659 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11662 /* Strictly speaking, this is not always correct because
11663 previous events may change some states about display. */
11664 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11666 /* Active input area is displayed around the current point. */
11667 f
= SELECTED_FRAME ();
11668 w
= XWINDOW (f
->selected_window
);
11670 else if (WINDOWP (echo_area_window
))
11672 /* Active input area is displayed in the echo area. */
11673 w
= XWINDOW (echo_area_window
);
11674 f
= WINDOW_XFRAME (w
);
11679 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11680 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11681 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11682 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11683 + FONT_BASE (FRAME_FONT (f
))
11684 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11685 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11686 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11696 if (!NILP (id_key
))
11697 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11703 #endif /* TARGET_API_MAC_CARBON */
11707 install_window_handler (window
)
11710 OSStatus err
= noErr
;
11712 #if TARGET_API_MAC_CARBON
11715 static const EventTypeSpec specs
[] =
11717 /* -- window refresh events -- */
11718 {kEventClassWindow
, kEventWindowUpdate
},
11719 /* -- window state change events -- */
11720 {kEventClassWindow
, kEventWindowShowing
},
11721 {kEventClassWindow
, kEventWindowHiding
},
11722 {kEventClassWindow
, kEventWindowShown
},
11723 {kEventClassWindow
, kEventWindowHidden
},
11724 {kEventClassWindow
, kEventWindowCollapsed
},
11725 {kEventClassWindow
, kEventWindowExpanded
},
11726 {kEventClassWindow
, kEventWindowBoundsChanging
},
11727 {kEventClassWindow
, kEventWindowBoundsChanged
},
11728 /* -- window action events -- */
11729 {kEventClassWindow
, kEventWindowClose
},
11730 {kEventClassWindow
, kEventWindowGetIdealSize
},
11732 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11735 /* -- window focus events -- */
11736 {kEventClassWindow
, kEventWindowFocusAcquired
},
11737 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11740 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11742 if (handle_window_eventUPP
== NULL
)
11743 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11745 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11746 GetEventTypeCount (specs
),
11747 specs
, NULL
, NULL
);
11752 err
= install_drag_handler (window
);
11758 remove_window_handler (window
)
11761 remove_drag_handler (window
);
11764 #if TARGET_API_MAC_CARBON
11766 install_application_handler ()
11768 OSStatus err
= noErr
;
11772 static const EventTypeSpec specs
[] = {
11774 {kEventClassApplication
, kEventAppActivated
},
11775 {kEventClassApplication
, kEventAppDeactivated
},
11779 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11780 (mac_handle_application_event
),
11781 GetEventTypeCount (specs
),
11782 specs
, NULL
, NULL
);
11787 static const EventTypeSpec specs
[] =
11788 {{kEventClassKeyboard
, kEventRawKeyDown
},
11789 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11790 {kEventClassKeyboard
, kEventRawKeyUp
}};
11792 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11793 (mac_handle_keyboard_event
),
11794 GetEventTypeCount (specs
),
11795 specs
, NULL
, NULL
);
11800 static const EventTypeSpec specs
[] =
11801 {{kEventClassCommand
, kEventCommandProcess
}};
11803 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11804 (mac_handle_command_event
),
11805 GetEventTypeCount (specs
),
11806 specs
, NULL
, NULL
);
11811 static const EventTypeSpec specs
[] =
11812 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11814 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11815 (mac_handle_mouse_event
),
11816 GetEventTypeCount (specs
),
11817 specs
, NULL
, NULL
);
11823 static const EventTypeSpec spec
[] =
11824 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11825 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11826 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11828 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11829 (mac_handle_text_input_event
),
11830 GetEventTypeCount (spec
),
11836 err
= install_menu_target_item_handler ();
11840 err
= install_service_handler ();
11848 mac_handle_dm_notification (event
)
11851 mac_screen_config_changed
= 1;
11854 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11856 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11857 CGDirectDisplayID display
;
11858 CGDisplayChangeSummaryFlags flags
;
11861 mac_screen_config_changed
= 1;
11866 init_dm_notification_handler ()
11870 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11871 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11872 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11875 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11878 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11879 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11881 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11882 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11884 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11885 ProcessSerialNumber psn
;
11887 if (handle_dm_notificationUPP
== NULL
)
11888 handle_dm_notificationUPP
=
11889 NewDMNotificationUPP (mac_handle_dm_notification
);
11891 err
= GetCurrentProcess (&psn
);
11893 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11901 mac_get_screen_info (dpyinfo
)
11902 struct mac_display_info
*dpyinfo
;
11905 /* HasDepth returns true if it is possible to have a 32 bit display,
11906 but this may not be what is actually used. Mac OSX can do better. */
11907 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11908 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11911 CGDisplayCount ndisps
;
11912 CGDirectDisplayID
*displays
;
11914 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11917 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11918 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11922 CGRect bounds
= CGRectZero
;
11924 while (ndisps
-- > 0)
11925 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11926 dpyinfo
->height
= CGRectGetHeight (bounds
);
11927 dpyinfo
->width
= CGRectGetWidth (bounds
);
11931 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11932 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11935 #else /* !MAC_OSX */
11937 GDHandle gdh
= GetMainDevice ();
11938 Rect rect
= (**gdh
).gdRect
;
11940 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11941 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11942 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11945 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11946 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11947 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11949 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11950 dpyinfo
->width
= rect
.right
- rect
.left
;
11952 #endif /* !MAC_OSX */
11958 profiler_exit_proc ()
11960 ProfilerDump ("\pEmacs.prof");
11965 /* These few functions implement Emacs as a normal Mac application
11966 (almost): set up the heap and the Toolbox, handle necessary system
11967 events plus a few simple menu events. They also set up Emacs's
11968 access to functions defined in the rest of this file. Emacs uses
11969 function hooks to perform all its terminal I/O. A complete list of
11970 these functions appear in termhooks.h. For what they do, read the
11971 comments there and see also w32term.c and xterm.c. What's
11972 noticeably missing here is the event loop, which is normally
11973 present in most Mac application. After performing the necessary
11974 Mac initializations, main passes off control to emacs_main
11975 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11976 (defined further below) to read input. This is where
11977 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11984 #if __profile__ /* is the profiler on? */
11985 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11990 /* set creator and type for files created by MSL */
11991 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11995 do_init_managers ();
11999 #ifndef USE_LSB_TAG
12000 do_check_ram_size ();
12003 init_emacs_passwd_dir ();
12007 init_coercion_handler ();
12009 initialize_applescript ();
12011 init_apple_event_handler ();
12013 init_dm_notification_handler ();
12019 /* set up argv array from STR# resource */
12020 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
12024 /* free up AppleScript resources on exit */
12025 atexit (terminate_applescript
);
12027 #if __profile__ /* is the profiler on? */
12028 atexit (profiler_exit_proc
);
12031 /* 3rd param "envp" never used in emacs_main */
12032 (void) emacs_main (argc
, argv
, 0);
12035 /* Never reached - real exit in Fkill_emacs */
12040 #if !TARGET_API_MAC_CARBON
12041 static RgnHandle mouse_region
= NULL
;
12044 mac_wait_next_event (er
, sleep_time
, dequeue
)
12049 static EventRecord er_buf
= {nullEvent
};
12050 UInt32 target_tick
, current_tick
;
12051 EventMask event_mask
;
12053 if (mouse_region
== NULL
)
12054 mouse_region
= NewRgn ();
12056 event_mask
= everyEvent
;
12057 if (!mac_ready_for_apple_events
)
12058 event_mask
-= highLevelEventMask
;
12060 current_tick
= TickCount ();
12061 target_tick
= current_tick
+ sleep_time
;
12063 if (er_buf
.what
== nullEvent
)
12064 while (!WaitNextEvent (event_mask
, &er_buf
,
12065 target_tick
- current_tick
, mouse_region
))
12067 current_tick
= TickCount ();
12068 if (target_tick
<= current_tick
)
12074 er_buf
.what
= nullEvent
;
12077 #endif /* not TARGET_API_MAC_CARBON */
12079 #if TARGET_API_MAC_CARBON
12081 mac_post_mouse_moved_event ()
12083 EventRef event
= NULL
;
12086 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
12087 kEventAttributeNone
, &event
);
12092 GetGlobalMouse (&mouse_pos
);
12093 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
12094 sizeof (Point
), &mouse_pos
);
12098 UInt32 modifiers
= GetCurrentKeyModifiers ();
12100 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
12101 sizeof (UInt32
), &modifiers
);
12104 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
12105 kEventPriorityStandard
);
12107 ReleaseEvent (event
);
12113 /* Emacs calls this whenever it wants to read an input event from the
12116 XTread_socket (sd
, expected
, hold_quit
)
12118 struct input_event
*hold_quit
;
12120 struct input_event inev
;
12122 #if TARGET_API_MAC_CARBON
12124 EventTargetRef toolbox_dispatcher
;
12127 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
12129 if (interrupt_input_blocked
)
12131 interrupt_input_pending
= 1;
12135 interrupt_input_pending
= 0;
12138 /* So people can tell when we have read the available input. */
12139 input_signal_count
++;
12143 #if TARGET_API_MAC_CARBON
12144 toolbox_dispatcher
= GetEventDispatcherTarget ();
12148 mac_prepare_for_quickdraw (NULL
),
12150 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
12151 kEventRemoveFromQueue
, &eventRef
))
12152 #else /* !TARGET_API_MAC_CARBON */
12153 while (mac_wait_next_event (&er
, 0, true))
12154 #endif /* !TARGET_API_MAC_CARBON */
12158 unsigned long timestamp
;
12161 inev
.kind
= NO_EVENT
;
12164 #if TARGET_API_MAC_CARBON
12165 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
12167 if (!mac_convert_event_ref (eventRef
, &er
))
12169 #else /* !TARGET_API_MAC_CARBON */
12170 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
12171 #endif /* !TARGET_API_MAC_CARBON */
12178 WindowRef window_ptr
;
12179 ControlPartCode part_code
;
12180 int tool_bar_p
= 0;
12182 #if TARGET_API_MAC_CARBON
12185 /* This is needed to send mouse events like aqua window
12186 buttons to the correct handler. */
12187 read_socket_inev
= &inev
;
12188 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12189 read_socket_inev
= NULL
;
12190 if (err
!= eventNotHandledErr
)
12193 last_mouse_glyph_frame
= 0;
12195 if (dpyinfo
->grabbed
&& last_mouse_frame
12196 && FRAME_LIVE_P (last_mouse_frame
))
12198 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
12199 part_code
= inContent
;
12203 part_code
= FindWindow (er
.where
, &window_ptr
);
12204 if (tip_window
&& window_ptr
== tip_window
)
12206 HideWindow (tip_window
);
12207 part_code
= FindWindow (er
.where
, &window_ptr
);
12211 if (er
.what
!= mouseDown
&&
12212 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
12218 f
= mac_focus_frame (dpyinfo
);
12219 saved_menu_event_location
= er
.where
;
12220 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
12221 XSETFRAME (inev
.frame_or_window
, f
);
12226 #if TARGET_API_MAC_CARBON
12227 FrontNonFloatingWindow ()
12232 || (mac_window_to_frame (window_ptr
)
12233 != dpyinfo
->x_focus_frame
))
12234 SelectWindow (window_ptr
);
12237 ControlPartCode control_part_code
;
12241 ControlKind control_kind
;
12244 f
= mac_window_to_frame (window_ptr
);
12245 /* convert to local coordinates of new window */
12246 mouse_loc
.h
= (er
.where
.h
12248 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12249 mouse_loc
.v
= (er
.where
.v
12251 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12252 #if TARGET_API_MAC_CARBON
12253 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
12254 &control_part_code
);
12257 GetControlKind (ch
, &control_kind
);
12260 control_part_code
= FindControl (mouse_loc
, window_ptr
,
12264 #if TARGET_API_MAC_CARBON
12265 inev
.code
= mac_get_mouse_btn (eventRef
);
12266 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12268 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
12269 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12271 XSETINT (inev
.x
, mouse_loc
.h
);
12272 XSETINT (inev
.y
, mouse_loc
.v
);
12274 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
12276 #ifndef USE_TOOLKIT_SCROLL_BARS
12277 /* control_part_code becomes kControlNoPart if
12278 a progress indicator is clicked. */
12279 && control_part_code
!= kControlNoPart
12280 #else /* USE_TOOLKIT_SCROLL_BARS */
12282 && control_kind
.kind
== kControlKindScrollBar
12283 #endif /* MAC_OSX */
12284 #endif /* USE_TOOLKIT_SCROLL_BARS */
12287 struct scroll_bar
*bar
;
12289 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12291 bar
= tracked_scroll_bar
;
12292 #ifndef USE_TOOLKIT_SCROLL_BARS
12293 control_part_code
= kControlIndicatorPart
;
12297 bar
= (struct scroll_bar
*) GetControlReference (ch
);
12298 #ifdef USE_TOOLKIT_SCROLL_BARS
12299 /* Make the "Ctrl-Mouse-2 splits window" work
12300 for toolkit scroll bars. */
12301 if (inev
.modifiers
& ctrl_modifier
)
12302 x_scroll_bar_handle_click (bar
, control_part_code
,
12304 else if (er
.what
== mouseDown
)
12305 x_scroll_bar_handle_press (bar
, control_part_code
,
12308 x_scroll_bar_handle_release (bar
, &inev
);
12309 #else /* not USE_TOOLKIT_SCROLL_BARS */
12310 x_scroll_bar_handle_click (bar
, control_part_code
,
12312 if (er
.what
== mouseDown
12313 && control_part_code
== kControlIndicatorPart
)
12314 tracked_scroll_bar
= bar
;
12316 tracked_scroll_bar
= NULL
;
12317 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12321 Lisp_Object window
;
12322 int x
= mouse_loc
.h
;
12323 int y
= mouse_loc
.v
;
12325 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
12326 if (EQ (window
, f
->tool_bar_window
))
12328 if (er
.what
== mouseDown
)
12329 handle_tool_bar_click (f
, x
, y
, 1, 0);
12331 handle_tool_bar_click (f
, x
, y
, 0,
12337 XSETFRAME (inev
.frame_or_window
, f
);
12338 inev
.kind
= MOUSE_CLICK_EVENT
;
12342 if (er
.what
== mouseDown
)
12344 dpyinfo
->grabbed
|= (1 << inev
.code
);
12345 last_mouse_frame
= f
;
12348 last_tool_bar_item
= -1;
12352 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
12353 /* If a button is released though it was not
12354 previously pressed, that would be because
12355 of multi-button emulation. */
12356 dpyinfo
->grabbed
= 0;
12358 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
12361 /* Ignore any mouse motion that happened before
12362 this event; any subsequent mouse-movement Emacs
12363 events should reflect only motion after the
12366 f
->mouse_moved
= 0;
12368 #ifdef USE_TOOLKIT_SCROLL_BARS
12369 if (inev
.kind
== MOUSE_CLICK_EVENT
12370 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12371 && (inev
.modifiers
& ctrl_modifier
)))
12376 inev
.modifiers
|= down_modifier
;
12379 inev
.modifiers
|= up_modifier
;
12386 #if TARGET_API_MAC_CARBON
12388 if (IsWindowPathSelectClick (window_ptr
, &er
))
12390 WindowPathSelect (window_ptr
, NULL
, NULL
);
12393 if (part_code
== inProxyIcon
12394 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12395 != errUserWantsToDragWindow
))
12397 DragWindow (window_ptr
, er
.where
, NULL
);
12398 #else /* not TARGET_API_MAC_CARBON */
12399 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12400 /* Update the frame parameters. */
12402 struct frame
*f
= mac_window_to_frame (window_ptr
);
12404 if (f
&& !f
->async_iconified
)
12405 mac_handle_origin_change (f
);
12407 #endif /* not TARGET_API_MAC_CARBON */
12411 if (TrackGoAway (window_ptr
, er
.where
))
12413 inev
.kind
= DELETE_WINDOW_EVENT
;
12414 XSETFRAME (inev
.frame_or_window
,
12415 mac_window_to_frame (window_ptr
));
12419 /* window resize handling added --ben */
12421 do_grow_window (window_ptr
, &er
);
12424 /* window zoom handling added --ben */
12427 if (TrackBox (window_ptr
, er
.where
, part_code
))
12428 do_zoom_window (window_ptr
, part_code
);
12431 #if USE_MAC_TOOLBAR
12437 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12439 /* This doesn't work on Mac OS X 10.2. */
12441 HIViewClick (ch
, eventRef
);
12444 #endif /* USE_MAC_TOOLBAR */
12452 #if !TARGET_API_MAC_CARBON
12454 do_window_update ((WindowRef
) er
.message
);
12459 switch ((er
.message
>> 24) & 0x000000FF)
12461 case mouseMovedMessage
:
12462 #if !TARGET_API_MAC_CARBON
12463 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12464 er
.where
.h
+ 1, er
.where
.v
+ 1);
12466 previous_help_echo_string
= help_echo_string
;
12467 help_echo_string
= Qnil
;
12469 if (dpyinfo
->grabbed
&& last_mouse_frame
12470 && FRAME_LIVE_P (last_mouse_frame
))
12471 f
= last_mouse_frame
;
12473 f
= dpyinfo
->x_focus_frame
;
12475 if (dpyinfo
->mouse_face_hidden
)
12477 dpyinfo
->mouse_face_hidden
= 0;
12478 clear_mouse_face (dpyinfo
);
12483 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12486 mouse_pos
.h
= (er
.where
.h
12488 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12489 mouse_pos
.v
= (er
.where
.v
12491 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12492 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12493 #ifdef USE_TOOLKIT_SCROLL_BARS
12494 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12496 #else /* not USE_TOOLKIT_SCROLL_BARS */
12497 x_scroll_bar_note_movement (tracked_scroll_bar
,
12499 - XINT (tracked_scroll_bar
->top
),
12500 er
.when
* (1000 / 60));
12501 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12504 /* Generate SELECT_WINDOW_EVENTs when needed. */
12505 if (!NILP (Vmouse_autoselect_window
))
12507 Lisp_Object window
;
12509 window
= window_from_coordinates (f
,
12514 /* Window will be selected only when it is
12515 not selected now and last mouse movement
12516 event was not in it. Minibuffer window
12517 will be selected only when it is active. */
12518 if (WINDOWP (window
)
12519 && !EQ (window
, last_window
)
12520 && !EQ (window
, selected_window
)
12521 /* For click-to-focus window managers
12522 create event iff we don't leave the
12524 && (focus_follows_mouse
12525 || (EQ (XWINDOW (window
)->frame
,
12526 XWINDOW (selected_window
)->frame
))))
12528 inev
.kind
= SELECT_WINDOW_EVENT
;
12529 inev
.frame_or_window
= window
;
12532 last_window
=window
;
12534 if (!note_mouse_movement (f
, &mouse_pos
))
12535 help_echo_string
= previous_help_echo_string
;
12536 #if USE_MAC_TOOLBAR
12538 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12543 /* If the contents of the global variable
12544 help_echo_string has changed, generate a
12546 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12557 WindowRef window_ptr
= (WindowRef
) er
.message
;
12559 ControlRef root_control
;
12561 if (window_ptr
== tip_window
)
12563 HideWindow (tip_window
);
12567 if (!is_emacs_window (window_ptr
))
12570 f
= mac_window_to_frame (window_ptr
);
12572 if ((er
.modifiers
& activeFlag
) != 0)
12574 /* A window has been activated */
12577 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12579 ActivateControl (root_control
);
12581 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12583 mouse_loc
.h
= (er
.where
.h
12585 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12586 mouse_loc
.v
= (er
.where
.v
12588 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12589 /* Window-activated event counts as mouse movement,
12590 so update things that depend on mouse position. */
12591 note_mouse_movement (f
, &mouse_loc
);
12595 /* A window has been deactivated */
12596 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12598 DeactivateControl (root_control
);
12600 #ifdef USE_TOOLKIT_SCROLL_BARS
12601 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12603 struct input_event event
;
12605 EVENT_INIT (event
);
12606 event
.kind
= NO_EVENT
;
12607 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12608 if (event
.kind
!= NO_EVENT
)
12610 event
.timestamp
= timestamp
;
12611 kbd_buffer_store_event_hold (&event
, hold_quit
);
12616 dpyinfo
->grabbed
= 0;
12618 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12620 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12622 /* If we move outside the frame, then we're
12623 certainly no longer on any text in the
12625 clear_mouse_face (dpyinfo
);
12626 dpyinfo
->mouse_face_mouse_frame
= 0;
12629 /* Generate a nil HELP_EVENT to cancel a help-echo.
12630 Do it only if there's something to cancel.
12631 Otherwise, the startup message is cleared when the
12632 mouse leaves the frame. */
12633 if (any_help_event_p
)
12644 f
= mac_focus_frame (dpyinfo
);
12645 XSETFRAME (inev
.frame_or_window
, f
);
12647 /* If mouse-highlight is an integer, input clears out mouse
12649 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12650 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12652 clear_mouse_face (dpyinfo
);
12653 dpyinfo
->mouse_face_hidden
= 1;
12657 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
12660 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
12662 sizeof (UInt32
), NULL
, &modifiers
);
12664 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
12666 #if TARGET_API_MAC_CARBON
12667 if (!(mapped_modifiers
12668 & ~(mac_pass_command_to_system
? cmdKey
: 0)
12669 & ~(mac_pass_control_to_system
? controlKey
: 0)))
12673 if (er
.what
!= keyUp
)
12674 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12675 (er
.message
& keyCodeMask
) >> 8,
12676 modifiers
, timestamp
, &inev
);
12680 case kHighLevelEvent
:
12681 AEProcessAppleEvent (&er
);
12686 #if TARGET_API_MAC_CARBON
12690 read_socket_inev
= &inev
;
12691 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12692 read_socket_inev
= NULL
;
12697 #if TARGET_API_MAC_CARBON
12698 ReleaseEvent (eventRef
);
12701 if (inev
.kind
!= NO_EVENT
)
12703 inev
.timestamp
= timestamp
;
12704 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12709 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12714 XSETFRAME (frame
, f
);
12720 any_help_event_p
= 1;
12721 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12722 help_echo_object
, help_echo_pos
);
12726 help_echo_string
= Qnil
;
12727 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12733 /* If the focus was just given to an autoraising frame,
12735 /* ??? This ought to be able to handle more than one such frame. */
12736 if (pending_autoraise_frame
)
12738 x_raise_frame (pending_autoraise_frame
);
12739 pending_autoraise_frame
= 0;
12742 if (mac_screen_config_changed
)
12744 mac_get_screen_info (dpyinfo
);
12745 mac_screen_config_changed
= 0;
12748 #if !TARGET_API_MAC_CARBON
12749 /* Check which frames are still visible. We do this here because
12750 there doesn't seem to be any direct notification from the Window
12751 Manager that the visibility of a window has changed (at least,
12752 not in all cases). */
12754 Lisp_Object tail
, frame
;
12756 FOR_EACH_FRAME (tail
, frame
)
12758 struct frame
*f
= XFRAME (frame
);
12760 /* The tooltip has been drawn already. Avoid the
12761 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12762 if (EQ (frame
, tip_frame
))
12765 if (FRAME_MAC_P (f
))
12766 mac_handle_visibility_change (f
);
12777 /* Need to override CodeWarrior's input function so no conversion is
12778 done on newlines Otherwise compiled functions in .elc files will be
12779 read incorrectly. Defined in ...:MSL C:MSL
12780 Common:Source:buffer_io.c. */
12783 __convert_to_newlines (unsigned char * p
, size_t * n
)
12785 #pragma unused(p,n)
12789 __convert_from_newlines (unsigned char * p
, size_t * n
)
12791 #pragma unused(p,n)
12797 make_mac_terminal_frame (struct frame
*f
)
12802 XSETFRAME (frame
, f
);
12804 f
->output_method
= output_mac
;
12805 f
->output_data
.mac
= (struct mac_output
*)
12806 xmalloc (sizeof (struct mac_output
));
12807 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12809 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12811 FRAME_COLS (f
) = 96;
12812 FRAME_LINES (f
) = 4;
12814 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12815 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12817 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12819 f
->output_data
.mac
->cursor_pixel
= 0;
12820 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12821 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12822 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12824 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12825 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12826 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12827 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12828 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12829 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12831 FRAME_FONTSET (f
) = -1;
12832 f
->output_data
.mac
->explicit_parent
= 0;
12835 f
->border_width
= 0;
12837 f
->internal_border_width
= 0;
12842 f
->new_text_cols
= 0;
12843 f
->new_text_lines
= 0;
12845 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12846 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12847 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12851 if (!(FRAME_MAC_WINDOW (f
) =
12852 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12853 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12855 /* so that update events can find this mac_output struct */
12856 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12862 /* Need to be initialized for unshow_buffer in window.c. */
12863 selected_window
= f
->selected_window
;
12865 Fmodify_frame_parameters (frame
,
12866 Fcons (Fcons (Qfont
,
12867 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12868 Fmodify_frame_parameters (frame
,
12869 Fcons (Fcons (Qforeground_color
,
12870 build_string ("black")), Qnil
));
12871 Fmodify_frame_parameters (frame
,
12872 Fcons (Fcons (Qbackground_color
,
12873 build_string ("white")), Qnil
));
12878 /***********************************************************************
12880 ***********************************************************************/
12882 static int mac_initialized
= 0;
12885 mac_make_rdb (xrm_option
)
12886 const char *xrm_option
;
12888 XrmDatabase database
;
12890 database
= xrm_get_preference_database (NULL
);
12892 xrm_merge_string_database (database
, xrm_option
);
12897 struct mac_display_info
*
12898 mac_term_init (display_name
, xrm_option
, resource_name
)
12899 Lisp_Object display_name
;
12901 char *resource_name
;
12903 struct mac_display_info
*dpyinfo
;
12904 struct terminal
*terminal
;
12908 if (!mac_initialized
)
12911 mac_initialized
= 1;
12914 if (x_display_list
)
12915 error ("Sorry, this version can only handle one display");
12917 dpyinfo
= &one_mac_display_info
;
12918 bzero (dpyinfo
, sizeof (*dpyinfo
));
12920 terminal
= mac_create_terminal (dpyinfo
);
12922 /* Set the name of the terminal. */
12923 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
12924 strncpy (terminal
->name
, SDATA (display_name
), SBYTES (display_name
));
12925 terminal
->name
[SBYTES (display_name
)] = 0;
12928 dpyinfo
->mac_id_name
12929 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12930 + SCHARS (Vsystem_name
)
12932 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12933 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12935 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12936 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12939 dpyinfo
->reference_count
= 0;
12940 dpyinfo
->resx
= 72.0;
12941 dpyinfo
->resy
= 72.0;
12943 mac_get_screen_info (dpyinfo
);
12945 dpyinfo
->grabbed
= 0;
12946 dpyinfo
->root_window
= NULL
;
12947 dpyinfo
->terminal
->image_cache
= make_image_cache ();
12949 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12950 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12951 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12952 dpyinfo
->mouse_face_window
= Qnil
;
12953 dpyinfo
->mouse_face_overlay
= Qnil
;
12954 dpyinfo
->mouse_face_hidden
= 0;
12956 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12958 /* Put this display on the chain. */
12959 dpyinfo
->next
= x_display_list
;
12960 x_display_list
= dpyinfo
;
12962 /* Put it on x_display_name_list. */
12963 x_display_name_list
= Fcons (Fcons (display_name
,
12964 Fcons (Qnil
, dpyinfo
->xrdb
)),
12965 x_display_name_list
);
12966 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12968 /* FIXME: Untested.
12969 Add the default keyboard. */
12970 add_keyboard_wait_descriptor (0);
12973 mac_init_fringe (terminal
->rif
);
12981 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12984 x_delete_display (dpyinfo
)
12985 struct mac_display_info
*dpyinfo
;
12989 /* Discard this display from x_display_name_list and x_display_list.
12990 We can't use Fdelq because that can quit. */
12991 if (! NILP (x_display_name_list
)
12992 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12993 x_display_name_list
= XCDR (x_display_name_list
);
12998 tail
= x_display_name_list
;
12999 while (CONSP (tail
) && CONSP (XCDR (tail
)))
13001 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
13003 XSETCDR (tail
, XCDR (XCDR (tail
)));
13006 tail
= XCDR (tail
);
13010 if (x_display_list
== dpyinfo
)
13011 x_display_list
= dpyinfo
->next
;
13014 struct x_display_info
*tail
;
13016 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
13017 if (tail
->next
== dpyinfo
)
13018 tail
->next
= tail
->next
->next
;
13021 /* Free the font names in the font table. */
13022 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
13023 if (dpyinfo
->font_table
[i
].name
)
13025 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
13026 xfree (dpyinfo
->font_table
[i
].full_name
);
13027 xfree (dpyinfo
->font_table
[i
].name
);
13030 if (dpyinfo
->font_table
)
13032 if (dpyinfo
->font_table
->font_encoder
)
13033 xfree (dpyinfo
->font_table
->font_encoder
);
13034 xfree (dpyinfo
->font_table
);
13036 if (dpyinfo
->mac_id_name
)
13037 xfree (dpyinfo
->mac_id_name
);
13039 if (x_display_list
== 0)
13041 mac_clear_font_name_table ();
13042 bzero (dpyinfo
, sizeof (*dpyinfo
));
13053 MenuItemIndex menu_index
;
13055 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
13056 &menu
, &menu_index
);
13058 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
13059 EnableMenuCommand (NULL
, kHICommandPreferences
);
13060 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
13061 &menu
, &menu_index
);
13064 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
13065 InsertMenuItemTextWithCFString (menu
, NULL
,
13066 0, kMenuItemAttrSeparator
, 0);
13067 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
13068 0, 0, kHICommandAbout
);
13070 #else /* !MAC_OSX */
13071 #if TARGET_API_MAC_CARBON
13072 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
13082 static InterfaceTypeList types
= {kUnicodeDocument
};
13084 static InterfaceTypeList types
= {kTextService
};
13087 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
13088 &tsm_document_id
, 0);
13092 /* Set up use of X before we make the first connection. */
13094 extern frame_parm_handler mac_frame_parm_handlers
[];
13096 static struct redisplay_interface x_redisplay_interface
=
13098 mac_frame_parm_handlers
,
13102 x_clear_end_of_line
,
13104 x_after_update_window_line
,
13105 x_update_window_begin
,
13106 x_update_window_end
,
13110 mac_flush_display_optional
,
13112 0, /* flush_display_optional */
13114 x_clear_window_mouse_face
,
13115 x_get_glyph_overhangs
,
13116 x_fix_overlapping_area
,
13117 x_draw_fringe_bitmap
,
13119 mac_define_fringe_bitmap
,
13120 mac_destroy_fringe_bitmap
,
13122 0, /* define_fringe_bitmap */
13123 0, /* destroy_fringe_bitmap */
13125 mac_per_char_metric
,
13127 mac_compute_glyph_string_overhangs
,
13128 x_draw_glyph_string
,
13129 mac_define_frame_cursor
,
13130 mac_clear_frame_area
,
13131 mac_draw_window_cursor
,
13132 mac_draw_vertical_window_border
,
13133 mac_shift_glyphs_for_insert
13136 static struct terminal
*
13137 mac_create_terminal (struct mac_display_info
*dpyinfo
)
13139 struct terminal
*terminal
;
13141 terminal
= create_terminal ();
13143 terminal
->type
= output_mac
;
13144 terminal
->display_info
.mac
= dpyinfo
;
13145 dpyinfo
->terminal
= terminal
;
13147 terminal
->clear_frame_hook
= x_clear_frame
;
13148 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
13149 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
13150 terminal
->ring_bell_hook
= XTring_bell
;
13151 terminal
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
13152 terminal
->set_terminal_modes_hook
= XTset_terminal_modes
;
13153 terminal
->update_begin_hook
= x_update_begin
;
13154 terminal
->update_end_hook
= x_update_end
;
13155 terminal
->set_terminal_window_hook
= XTset_terminal_window
;
13156 terminal
->read_socket_hook
= XTread_socket
;
13157 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
13158 terminal
->mouse_position_hook
= XTmouse_position
;
13159 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
13160 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
13161 /* terminal->fullscreen_hook = XTfullscreen_hook; */
13162 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13163 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13164 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13165 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13166 terminal
->delete_frame_hook
= x_destroy_window
;
13167 /* terminal->delete_terminal_hook = x_delete_terminal; */
13169 terminal
->rif
= &x_redisplay_interface
;
13171 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
13172 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
13173 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
13174 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
13175 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
13179 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
13180 terminal
->char_ins_del_ok
= 1;
13181 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
13182 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
13183 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
13188 /* FIXME: This keyboard setup is 100% untested, just copied from
13189 w32_create_terminal in order to set window-system now that it's
13190 a keyboard object. */
13191 /* We don't yet support separate terminals on Mac, so don't try to share
13192 keyboards between virtual terminals that are on the same physical
13193 terminal like X does. */
13194 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
13195 init_kboard (terminal
->kboard
);
13196 terminal
->kboard
->Vwindow_system
= intern ("mac");
13197 terminal
->kboard
->next_kboard
= all_kboards
;
13198 all_kboards
= terminal
->kboard
;
13199 /* Don't let the initial kboard remain current longer than necessary.
13200 That would cause problems if a file loaded on startup tries to
13201 prompt in the mini-buffer. */
13202 if (current_kboard
== initial_kboard
)
13203 current_kboard
= terminal
->kboard
;
13204 terminal
->kboard
->reference_count
++;
13215 last_tool_bar_item
= -1;
13216 any_help_event_p
= 0;
13218 /* Try to use interrupt input; if we can't, then start polling. */
13219 Fset_input_interrupt_mode (Qt
);
13223 #if TARGET_API_MAC_CARBON
13225 install_application_handler ();
13234 init_coercion_handler ();
13236 init_apple_event_handler ();
13238 init_dm_notification_handler ();
13240 if (!inhibit_window_system
)
13242 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
13244 SetFrontProcess (&psn
);
13262 staticpro (&x_error_message_string
);
13263 x_error_message_string
= Qnil
;
13266 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
13267 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
13268 Qalt
= intern ("alt"); staticpro (&Qalt
);
13269 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
13270 Qsuper
= intern ("super"); staticpro (&Qsuper
);
13271 Qmodifier_value
= intern ("modifier-value");
13272 staticpro (&Qmodifier_value
);
13274 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
13275 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
13276 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
13277 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
13278 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
13280 #if TARGET_API_MAC_CARBON
13281 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
13283 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
13284 staticpro (&Qtoolbar_switch_mode
);
13285 #if USE_MAC_FONT_PANEL
13286 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
13287 Qselection
= intern ("selection"); staticpro (&Qselection
);
13290 Qservice
= intern ("service"); staticpro (&Qservice
);
13291 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
13292 Qperform
= intern ("perform"); staticpro (&Qperform
);
13294 Qmouse_drag_overlay
= intern ("mouse-drag-overlay");
13295 staticpro (&Qmouse_drag_overlay
);
13298 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
13299 Qupdate_active_input_area
= intern ("update-active-input-area");
13300 staticpro (&Qupdate_active_input_area
);
13301 Qunicode_for_key_event
= intern ("unicode-for-key-event");
13302 staticpro (&Qunicode_for_key_event
);
13307 Fprovide (intern ("mac-carbon"), Qnil
);
13310 staticpro (&Qreverse
);
13311 Qreverse
= intern ("reverse");
13313 staticpro (&x_display_name_list
);
13314 x_display_name_list
= Qnil
;
13316 staticpro (&last_mouse_scroll_bar
);
13317 last_mouse_scroll_bar
= Qnil
;
13319 staticpro (&fm_font_family_alist
);
13320 fm_font_family_alist
= Qnil
;
13323 staticpro (&atsu_font_id_hash
);
13324 atsu_font_id_hash
= Qnil
;
13326 staticpro (&fm_style_face_attributes_alist
);
13327 fm_style_face_attributes_alist
= Qnil
;
13331 staticpro (&saved_ts_script_language_on_focus
);
13332 saved_ts_script_language_on_focus
= Qnil
;
13335 /* We don't yet support this, but defining this here avoids whining
13336 from cus-start.el and other places, like "M-x set-variable". */
13337 DEFVAR_BOOL ("x-use-underline-position-properties",
13338 &x_use_underline_position_properties
,
13339 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13340 A value of nil means ignore them. If you encounter fonts with bogus
13341 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13342 to 4.1, set this to nil.
13344 NOTE: Not supported on Mac yet. */);
13345 x_use_underline_position_properties
= 0;
13347 DEFVAR_BOOL ("x-underline-at-descent-line",
13348 &x_underline_at_descent_line
,
13349 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
13350 A value of nil means to draw the underline according to the value of the
13351 variable `x-use-underline-position-properties', which is usually at the
13352 baseline level. The default value is nil. */);
13353 x_underline_at_descent_line
= 0;
13355 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
13356 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
13357 #ifdef USE_TOOLKIT_SCROLL_BARS
13358 Vx_toolkit_scroll_bars
= Qt
;
13360 Vx_toolkit_scroll_bars
= Qnil
;
13363 staticpro (&last_mouse_motion_frame
);
13364 last_mouse_motion_frame
= Qnil
;
13366 /* Variables to configure modifier key assignment. */
13368 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
13369 doc
: /* *Modifier key assumed when the Mac control key is pressed.
13370 The value can be `control', `meta', `alt', `hyper', or `super' for the
13371 respective modifier. The default is `control'. */);
13372 Vmac_control_modifier
= Qcontrol
;
13374 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
13375 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
13376 The value can be `control', `meta', `alt', `hyper', or `super' for the
13377 respective modifier. If the value is nil then the key will act as the
13378 normal Mac control modifier, and the option key can be used to compose
13379 characters depending on the chosen Mac keyboard setting. */);
13380 Vmac_option_modifier
= Qnil
;
13382 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
13383 doc
: /* *Modifier key assumed when the Mac command key is pressed.
13384 The value can be `control', `meta', `alt', `hyper', or `super' for the
13385 respective modifier. The default is `meta'. */);
13386 Vmac_command_modifier
= Qmeta
;
13388 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
13389 doc
: /* *Modifier key assumed when the Mac function key is pressed.
13390 The value can be `control', `meta', `alt', `hyper', or `super' for the
13391 respective modifier. Note that remapping the function key may lead to
13392 unexpected results for some keys on non-US/GB keyboards. */);
13393 Vmac_function_modifier
= Qnil
;
13395 DEFVAR_LISP ("mac-emulate-three-button-mouse",
13396 &Vmac_emulate_three_button_mouse
,
13397 doc
: /* *Specify a way of three button mouse emulation.
13398 The value can be nil, t, or the symbol `reverse'.
13399 A value of nil means that no emulation should be done and the modifiers
13400 should be placed on the mouse-1 event.
13401 t means that when the option-key is held down while pressing the mouse
13402 button, the click will register as mouse-2 and while the command-key
13403 is held down, the click will register as mouse-3.
13404 The symbol `reverse' means that the option-key will register for
13405 mouse-3 and the command-key will register for mouse-2. */);
13406 Vmac_emulate_three_button_mouse
= Qnil
;
13408 #if TARGET_API_MAC_CARBON
13409 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
13410 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
13411 Otherwise, the right click will be treated as mouse-2 and the wheel
13412 button will be mouse-3. */);
13413 mac_wheel_button_is_mouse_2
= 1;
13415 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
13416 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
13417 mac_pass_command_to_system
= 1;
13419 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
13420 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13421 mac_pass_control_to_system
= 1;
13425 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
13426 doc
: /* *If non-nil, allow anti-aliasing.
13427 The text will be rendered using Core Graphics text rendering which
13428 may anti-alias the text. */);
13430 mac_use_core_graphics
= 1;
13432 mac_use_core_graphics
= 0;
13435 /* Register an entry for `mac-roman' so that it can be used when
13436 creating the terminal frame on Mac OS 9 before loading
13437 term/mac-win.elc. */
13438 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
13439 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
13440 Each entry should be of the form:
13442 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13444 where CHARSET-NAME is a string used in font names to identify the
13445 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13446 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13447 Vmac_charset_info_alist
=
13448 Fcons (list3 (build_string ("mac-roman"),
13449 make_number (smRoman
), Qnil
), Qnil
);
13452 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13453 doc
: /* Overlay used to display Mac TSM active input area. */);
13454 Vmac_ts_active_input_overlay
= Qnil
;
13456 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf
,
13457 doc
: /* Byte sequence of the current Mac TSM active input area. */);
13458 /* `empty_string' is not ready yet on Mac OS Classic. */
13459 Vmac_ts_active_input_buf
= build_string ("");
13461 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13462 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13463 If the value is t, the input script and language are restored to those
13464 used in the last focus frame. If the value is a pair of integers, the
13465 input script and language codes, which are defined in the Script
13466 Manager, are set to its car and cdr parts, respectively. Otherwise,
13467 Emacs doesn't set them and thus follows the system default behavior. */);
13468 Vmac_ts_script_language_on_focus
= Qnil
;
13472 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13473 (do not change this comment) */