1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 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 2, 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"
86 /* Non-nil means Emacs uses toolkit scroll bars. */
88 Lisp_Object Vx_toolkit_scroll_bars
;
90 /* If non-zero, the text will be rendered using Core Graphics text
91 rendering which may anti-alias the text. */
92 int mac_use_core_graphics
;
95 /* Non-zero means that a HELP_EVENT has been generated since Emacs
98 static int any_help_event_p
;
100 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
101 static Lisp_Object last_window
;
103 /* Non-zero means make use of UNDERLINE_POSITION font properties.
104 (Not yet supported.) */
105 int x_use_underline_position_properties
;
107 /* Non-zero means to draw the underline at the same place as the descent line. */
109 int x_underline_at_descent_line
;
111 /* This is a chain of structures for all the X displays currently in
114 struct x_display_info
*x_display_list
;
116 /* This is a list of cons cells, each of the form (NAME
117 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
118 x_display_list and in the same order. NAME is the name of the
119 frame. FONT-LIST-CACHE records previous values returned by
120 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
121 equivalent, which is implemented with a Lisp object, for the
124 Lisp_Object x_display_name_list
;
126 /* This is display since Mac does not support multiple ones. */
127 struct mac_display_info one_mac_display_info
;
129 /* Frame being updated by update_frame. This is declared in term.c.
130 This is set by update_begin and looked at by all the XT functions.
131 It is zero while not inside an update. In that case, the XT
132 functions assume that `selected_frame' is the frame to apply to. */
134 extern struct frame
*updating_frame
;
136 /* This is a frame waiting to be auto-raised, within XTread_socket. */
138 struct frame
*pending_autoraise_frame
;
142 Formerly, we used PointerMotionHintMask (in standard_event_mask)
143 so that we would have to call XQueryPointer after each MotionNotify
144 event to ask for another such event. However, this made mouse tracking
145 slow, and there was a bug that made it eventually stop.
147 Simply asking for MotionNotify all the time seems to work better.
149 In order to avoid asking for motion events and then throwing most
150 of them away or busy-polling the server for mouse positions, we ask
151 the server for pointer motion hints. This means that we get only
152 one event per group of mouse movements. "Groups" are delimited by
153 other kinds of events (focus changes and button clicks, for
154 example), or by XQueryPointer calls; when one of these happens, we
155 get another MotionNotify event the next time the mouse moves. This
156 is at least as efficient as getting motion events when mouse
157 tracking is on, and I suspect only negligibly worse when tracking
160 /* Where the mouse was last time we reported a mouse event. */
162 static Rect last_mouse_glyph
;
163 static FRAME_PTR last_mouse_glyph_frame
;
165 /* The scroll bar in which the last X motion event occurred.
167 If the last X motion event occurred in a scroll bar, we set this so
168 XTmouse_position can know whether to report a scroll bar motion or
171 If the last X motion event didn't occur in a scroll bar, we set
172 this to Qnil, to tell XTmouse_position to return an ordinary motion
175 static Lisp_Object last_mouse_scroll_bar
;
177 /* This is a hack. We would really prefer that XTmouse_position would
178 return the time associated with the position it returns, but there
179 doesn't seem to be any way to wrest the time-stamp from the server
180 along with the position query. So, we just keep track of the time
181 of the last movement we received, and return that in hopes that
182 it's somewhat accurate. */
184 static Time last_mouse_movement_time
;
186 struct scroll_bar
*tracked_scroll_bar
= NULL
;
188 /* Incremented by XTread_socket whenever it really tries to read
192 static int volatile input_signal_count
;
194 static int input_signal_count
;
197 extern Lisp_Object Vsystem_name
;
199 extern Lisp_Object Qeql
;
201 /* A mask of extra modifier bits to put into every keyboard char. */
203 extern EMACS_INT extra_keyboard_modifiers
;
205 /* The keysyms to use for the various modifiers. */
207 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
209 extern int inhibit_window_system
;
211 #if __MRC__ && !TARGET_API_MAC_CARBON
212 QDGlobals qd
; /* QuickDraw global information structure. */
215 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
217 struct mac_display_info
*mac_display_info_for_display (Display
*);
218 static void x_update_window_end
P_ ((struct window
*, int, int));
219 int x_catch_errors
P_ ((Display
*));
220 void x_uncatch_errors
P_ ((Display
*, int));
221 void x_lower_frame
P_ ((struct frame
*));
222 void x_scroll_bar_clear
P_ ((struct frame
*));
223 int x_had_errors_p
P_ ((Display
*));
224 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
225 void x_raise_frame
P_ ((struct frame
*));
226 void x_set_window_size
P_ ((struct frame
*, int, int, int));
227 void x_wm_set_window_state
P_ ((struct frame
*, int));
228 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
229 void mac_initialize
P_ ((void));
230 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
231 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
232 static void x_update_end
P_ ((struct frame
*));
233 static void XTframe_up_to_date
P_ ((struct frame
*));
234 static void XTset_terminal_modes
P_ ((void));
235 static void XTreset_terminal_modes
P_ ((void));
236 static void x_clear_frame
P_ ((void));
237 static void frame_highlight
P_ ((struct frame
*));
238 static void frame_unhighlight
P_ ((struct frame
*));
239 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
240 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
241 struct frame
*, struct input_event
*));
242 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
244 struct input_event
*));
245 static void XTframe_rehighlight
P_ ((struct frame
*));
246 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
247 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
248 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
249 enum text_cursor_kinds
));
251 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
252 static void x_flush
P_ ((struct frame
*f
));
253 static void x_update_begin
P_ ((struct frame
*));
254 static void x_update_window_begin
P_ ((struct window
*));
255 static void x_after_update_window_line
P_ ((struct glyph_row
*));
256 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
257 enum scroll_bar_part
*,
258 Lisp_Object
*, Lisp_Object
*,
261 static int is_emacs_window
P_ ((WindowRef
));
262 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
263 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
265 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
266 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
267 #define GC_FONT(gc) ((gc)->xgcv.font)
268 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
270 #define CG_SET_FILL_COLOR(context, color) \
271 CGContextSetRGBFillColor (context, \
272 RED_FROM_ULONG (color) / 255.0f, \
273 GREEN_FROM_ULONG (color) / 255.0f, \
274 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
275 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
276 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
277 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
279 if (CGColorGetTypeID != NULL) \
280 CGContextSetFillColorWithColor (context, cg_color); \
282 CG_SET_FILL_COLOR (context, color); \
285 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
286 CGContextSetFillColorWithColor (context, cg_color)
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CG_SET_FILL_COLOR (context, color)
292 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
293 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
295 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
296 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
300 #define CG_SET_STROKE_COLOR(context, color) \
301 CGContextSetRGBStrokeColor (context, \
302 RED_FROM_ULONG (color) / 255.0f, \
303 GREEN_FROM_ULONG (color) / 255.0f, \
304 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
305 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
306 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
307 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
309 if (CGColorGetTypeID != NULL) \
310 CGContextSetStrokeColorWithColor (context, cg_color); \
312 CG_SET_STROKE_COLOR (context, color); \
315 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
316 CGContextSetStrokeColorWithColor (context, cg_color)
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CG_SET_STROKE_COLOR (context, color)
322 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
323 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
327 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
329 /* Fringe bitmaps. */
331 static int max_fringe_bmp
= 0;
332 static CGImageRef
*fringe_bmp
= 0;
334 static CGColorSpaceRef mac_cg_color_space_rgb
;
335 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
336 static CGColorRef mac_cg_color_black
;
342 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
343 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
344 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
345 /* Don't check the availability of CGColorCreate; this symbol is
346 defined even in Mac OS X 10.1. */
347 if (CGColorGetTypeID
!= NULL
)
350 float rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
352 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
358 mac_begin_cg_clip (f
, gc
)
362 CGContextRef context
= FRAME_CG_CONTEXT (f
);
366 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
367 FRAME_CG_CONTEXT (f
) = context
;
370 CGContextSaveGState (context
);
371 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
372 CGContextScaleCTM (context
, 1, -1);
373 if (gc
&& gc
->n_clip_rects
)
374 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
383 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
387 mac_prepare_for_quickdraw (f
)
392 Lisp_Object rest
, frame
;
393 FOR_EACH_FRAME (rest
, frame
)
394 if (FRAME_MAC_P (XFRAME (frame
)))
395 mac_prepare_for_quickdraw (XFRAME (frame
));
399 CGContextRef context
= FRAME_CG_CONTEXT (f
);
403 CGContextSynchronize (context
);
404 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
405 &FRAME_CG_CONTEXT (f
));
411 static RgnHandle saved_port_clip_region
= NULL
;
414 mac_begin_clip (f
, gc
)
418 static RgnHandle new_region
= NULL
;
420 if (saved_port_clip_region
== NULL
)
421 saved_port_clip_region
= NewRgn ();
422 if (new_region
== NULL
)
423 new_region
= NewRgn ();
426 mac_prepare_for_quickdraw (f
);
428 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
430 if (gc
->n_clip_rects
)
432 GetClip (saved_port_clip_region
);
433 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
434 SetClip (new_region
);
442 if (gc
->n_clip_rects
)
443 SetClip (saved_port_clip_region
);
447 /* X display function emulation */
449 /* Mac version of XDrawLine. */
452 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
458 CGContextRef context
;
459 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
462 gx1
+= 0.5f
, gx2
+= 0.5f
;
464 gy1
+= 0.5f
, gy2
+= 0.5f
;
466 context
= mac_begin_cg_clip (f
, gc
);
467 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
468 CGContextBeginPath (context
);
469 CGContextMoveToPoint (context
, gx1
, gy1
);
470 CGContextAddLineToPoint (context
, gx2
, gy2
);
471 CGContextClosePath (context
);
472 CGContextStrokePath (context
);
490 mac_begin_clip (f
, gc
);
491 RGBForeColor (GC_FORE_COLOR (gc
));
498 /* Mac version of XDrawLine (to Pixmap). */
501 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
525 GetGWorld (&old_port
, &old_gdh
);
528 RGBForeColor (GC_FORE_COLOR (gc
));
530 LockPixels (GetGWorldPixMap (p
));
533 UnlockPixels (GetGWorldPixMap (p
));
535 SetGWorld (old_port
, old_gdh
);
540 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
544 unsigned int width
, height
;
548 CGContextRef context
;
550 context
= mac_begin_cg_clip (f
, gc
);
551 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
552 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
559 mac_begin_clip (f
, gc
);
560 RGBBackColor (GC_BACK_COLOR (gc
));
561 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
563 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
570 /* Mac version of XClearArea. */
573 mac_clear_area (f
, x
, y
, width
, height
)
576 unsigned int width
, height
;
578 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
581 /* Mac version of XClearWindow. */
589 CGContextRef context
;
590 GC gc
= FRAME_NORMAL_GC (f
);
592 context
= mac_begin_cg_clip (f
, NULL
);
593 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
594 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
595 FRAME_PIXEL_HEIGHT (f
)));
598 #else /* !USE_CG_DRAWING */
599 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
601 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
603 #if TARGET_API_MAC_CARBON
607 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
610 #else /* not TARGET_API_MAC_CARBON */
611 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
612 #endif /* not TARGET_API_MAC_CARBON */
617 /* Mac replacement for XCopyArea. */
621 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
622 dest_x
, dest_y
, overlay_p
)
627 unsigned int width
, height
;
628 int dest_x
, dest_y
, overlay_p
;
630 CGContextRef context
;
631 float port_height
= FRAME_PIXEL_HEIGHT (f
);
632 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
634 context
= mac_begin_cg_clip (f
, gc
);
637 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
638 CGContextFillRect (context
, dest_rect
);
640 CGContextClipToRect (context
, dest_rect
);
641 CGContextScaleCTM (context
, 1, -1);
642 CGContextTranslateCTM (context
, 0, -port_height
);
643 if (CGImageIsMask (image
))
644 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
645 CGContextDrawImage (context
,
646 CGRectMake (dest_x
- src_x
,
647 port_height
- (dest_y
- src_y
648 + CGImageGetHeight (image
)),
649 CGImageGetWidth (image
),
650 CGImageGetHeight (image
)),
655 #else /* !USE_CG_DRAWING */
658 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
661 int x
, y
, width
, height
;
662 unsigned short *bits
;
668 bitmap
.rowBytes
= sizeof(unsigned short);
669 bitmap
.baseAddr
= (char *)bits
;
670 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
672 mac_begin_clip (f
, gc
);
673 RGBForeColor (GC_FORE_COLOR (gc
));
674 RGBBackColor (GC_BACK_COLOR (gc
));
675 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
676 #if TARGET_API_MAC_CARBON
682 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
683 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
684 UnlockPortBits (port
);
686 #else /* not TARGET_API_MAC_CARBON */
687 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
688 overlay_p
? srcOr
: srcCopy
, 0);
689 #endif /* not TARGET_API_MAC_CARBON */
690 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
693 #endif /* !USE_CG_DRAWING */
696 /* Mac replacement for XCreateBitmapFromBitmapData. */
699 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
704 static const unsigned char swap_nibble
[16]
705 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
706 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
707 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
708 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
712 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
713 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
714 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
715 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
716 for (i
= 0; i
< h
; i
++)
718 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
719 for (j
= 0; j
< w1
; j
++)
721 /* Bitswap XBM bytes to match how Mac does things. */
722 unsigned char c
= *bits
++;
723 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
724 | (swap_nibble
[(c
>>4) & 0xf]));
728 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
733 mac_free_bitmap (bitmap
)
736 xfree (bitmap
->baseAddr
);
741 XCreatePixmap (display
, w
, width
, height
, depth
)
744 unsigned int width
, height
;
751 SetPortWindowPort (w
);
753 SetRect (&r
, 0, 0, width
, height
);
754 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
757 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
758 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
760 /* CreateCGImageFromPixMaps requires ARGB format. */
761 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
770 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
774 unsigned int width
, height
;
775 unsigned long fg
, bg
;
785 gc
= XCreateGC (display
, w
, 0, NULL
);
787 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
791 GetGWorld (&old_port
, &old_gdh
);
792 SetGWorld (pixmap
, NULL
);
793 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
794 XSetForeground (display
, gc
, fg
);
795 XSetBackground (display
, gc
, bg
);
796 RGBForeColor (GC_FORE_COLOR (gc
));
797 RGBBackColor (GC_BACK_COLOR (gc
));
798 LockPixels (GetGWorldPixMap (pixmap
));
799 #if TARGET_API_MAC_CARBON
800 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
801 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
802 #else /* not TARGET_API_MAC_CARBON */
803 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
804 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
805 #endif /* not TARGET_API_MAC_CARBON */
806 UnlockPixels (GetGWorldPixMap (pixmap
));
807 SetGWorld (old_port
, old_gdh
);
808 mac_free_bitmap (&bitmap
);
815 XFreePixmap (display
, pixmap
)
819 DisposeGWorld (pixmap
);
823 /* Mac replacement for XFillRectangle. */
826 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
830 unsigned int width
, height
;
833 CGContextRef context
;
835 context
= mac_begin_cg_clip (f
, gc
);
836 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
837 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
842 mac_begin_clip (f
, gc
);
843 RGBForeColor (GC_FORE_COLOR (gc
));
844 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
845 PaintRect (&r
); /* using foreground color of gc */
851 /* Mac replacement for XDrawRectangle: dest is a window. */
854 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
858 unsigned int width
, height
;
861 CGContextRef context
;
863 context
= mac_begin_cg_clip (f
, gc
);
864 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
865 CGContextStrokeRect (context
,
866 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
871 mac_begin_clip (f
, gc
);
872 RGBForeColor (GC_FORE_COLOR (gc
));
873 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
874 FrameRect (&r
); /* using foreground color of gc */
881 mac_invert_rectangle (f
, x
, y
, width
, height
)
884 unsigned int width
, height
;
889 mac_prepare_for_quickdraw (f
);
891 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
893 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
901 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
902 ConstUniCharArrayPtr text
;
903 UniCharCount text_length
;
905 ATSUTextLayout
*text_layout
;
908 static ATSUTextLayout saved_text_layout
= NULL
;
910 if (saved_text_layout
== NULL
)
912 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
913 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
914 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
915 static ATSLineLayoutOptions line_layout
=
916 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
917 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
918 | kATSLineUseQDRendering
920 kATSLineIsDisplayOnly
| kATSLineFractDisable
923 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
925 err
= ATSUCreateTextLayoutWithTextPtr (text
,
926 kATSUFromTextBeginning
,
932 err
= ATSUSetLayoutControls (saved_text_layout
,
933 sizeof (tags
) / sizeof (tags
[0]),
934 tags
, sizes
, values
);
936 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
940 err
= ATSUSetRunStyle (saved_text_layout
, style
,
941 kATSUFromTextBeginning
, kATSUToTextEnd
);
943 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
944 kATSUFromTextBeginning
,
950 *text_layout
= saved_text_layout
;
956 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
957 overstrike_p
, bytes_per_char
)
962 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
965 ATSUTextLayout text_layout
;
967 xassert (bytes_per_char
== 2);
969 #ifndef WORDS_BIG_ENDIAN
972 UniChar
*text
= (UniChar
*)buf
;
974 for (i
= 0; i
< nchars
; i
++)
975 text
[i
] = EndianU16_BtoN (text
[i
]);
978 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
980 GC_FONT (gc
)->mac_style
,
985 if (!mac_use_core_graphics
)
988 mac_begin_clip (f
, gc
);
989 RGBForeColor (GC_FORE_COLOR (gc
));
994 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
995 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
996 RGBBackColor (GC_BACK_COLOR (gc
));
998 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1001 ATSUDrawText (text_layout
,
1002 kATSUFromTextBeginning
, kATSUToTextEnd
,
1003 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1007 ATSUDrawText (text_layout
,
1008 kATSUFromTextBeginning
, kATSUToTextEnd
,
1009 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1016 static CGContextRef context
;
1017 float port_height
= FRAME_PIXEL_HEIGHT (f
);
1018 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1019 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1020 static const ATSUAttributeValuePtr values
[] = {&context
};
1023 context
= mac_begin_cg_clip (f
, gc
);
1028 QDBeginCGContext (port
, &context
);
1029 if (gc
->n_clip_rects
|| bg_width
)
1031 CGContextTranslateCTM (context
, 0, port_height
);
1032 CGContextScaleCTM (context
, 1, -1);
1033 if (gc
->n_clip_rects
)
1034 CGContextClipToRects (context
, gc
->clip_rects
,
1039 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1040 CGContextFillRect (context
,
1041 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
1043 FONT_HEIGHT (GC_FONT (gc
))));
1045 CGContextScaleCTM (context
, 1, -1);
1046 CGContextTranslateCTM (context
, 0, -port_height
);
1050 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1051 err
= ATSUSetLayoutControls (text_layout
,
1052 sizeof (tags
) / sizeof (tags
[0]),
1053 tags
, sizes
, values
);
1056 ATSUDrawText (text_layout
,
1057 kATSUFromTextBeginning
, kATSUToTextEnd
,
1058 Long2Fix (x
), Long2Fix (port_height
- y
));
1060 ATSUDrawText (text_layout
,
1061 kATSUFromTextBeginning
, kATSUToTextEnd
,
1062 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1065 mac_end_cg_clip (f
);
1068 CGContextSynchronize (context
);
1069 QDEndCGContext (port
, &context
);
1072 /* This doesn't work on Mac OS X 10.1. */
1073 ATSUClearLayoutControls (text_layout
,
1074 sizeof (tags
) / sizeof (tags
[0]), tags
);
1076 ATSUSetLayoutControls (text_layout
,
1077 sizeof (tags
) / sizeof (tags
[0]),
1078 tags
, sizes
, values
);
1081 #endif /* MAC_OSX */
1083 #endif /* USE_ATSUI */
1087 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1088 overstrike_p
, bytes_per_char
)
1093 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1095 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1099 mac_begin_clip (f
, gc
);
1100 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1101 if (mac_use_core_graphics
)
1102 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1104 RGBForeColor (GC_FORE_COLOR (gc
));
1108 RGBBackColor (GC_BACK_COLOR (gc
));
1114 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1116 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1117 into an offscreen graphics world first. So performance gain
1118 cannot be expected.)
1119 - It lowers rendering quality.
1120 - Some fonts leave garbage on cursor movement. */
1125 RGBBackColor (GC_BACK_COLOR (gc
));
1126 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1127 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1132 TextFont (GC_FONT (gc
)->mac_fontnum
);
1133 TextSize (GC_FONT (gc
)->mac_fontsize
);
1134 TextFace (GC_FONT (gc
)->mac_fontface
);
1136 DrawText (buf
, 0, nchars
* bytes_per_char
);
1141 DrawText (buf
, 0, nchars
* bytes_per_char
);
1144 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1147 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1148 if (mac_use_core_graphics
)
1149 SwapQDTextFlags(savedFlags
);
1155 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1156 overstrike_p
, bytes_per_char
)
1161 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1164 if (GC_FONT (gc
)->mac_style
)
1165 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1166 overstrike_p
, bytes_per_char
);
1168 #endif /* USE_ATSUI */
1169 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1170 overstrike_p
, bytes_per_char
);
1174 /* Mac replacement for XDrawImageString. */
1177 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1182 int nchars
, bg_width
, overstrike_p
;
1184 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1189 /* Mac replacement for XDrawImageString16. */
1192 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1197 int nchars
, bg_width
, overstrike_p
;
1199 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1204 /* Mac replacement for XQueryTextExtents, but takes a character. If
1205 STYLE is NULL, measurement is done by QuickDraw Text routines for
1206 the font of the current graphics port. If CG_GLYPH is not NULL,
1207 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1210 mac_query_char_extents (style
, c
,
1211 font_ascent_return
, font_descent_return
,
1212 overall_return
, cg_glyph
)
1219 int *font_ascent_return
, *font_descent_return
;
1220 XCharStruct
*overall_return
;
1221 #if USE_CG_TEXT_DRAWING
1227 OSStatus err
= noErr
;
1234 ATSUTextLayout text_layout
;
1237 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1239 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1241 ATSTrapezoid glyph_bounds
;
1243 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1244 kATSUFromTextBeginning
, kATSUToTextEnd
,
1245 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1246 kATSUseFractionalOrigins
,
1248 kATSUseDeviceOrigins
,
1250 1, &glyph_bounds
, NULL
);
1253 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1254 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1256 width
= Fix2Long (glyph_bounds
.upperRight
.x
1257 - glyph_bounds
.upperLeft
.x
);
1258 if (font_ascent_return
)
1259 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1260 if (font_descent_return
)
1261 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1264 if (err
== noErr
&& overall_return
)
1266 err
= ATSUMeasureTextImage (text_layout
,
1267 kATSUFromTextBeginning
, kATSUToTextEnd
,
1268 0, 0, &char_bounds
);
1270 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1271 #if USE_CG_TEXT_DRAWING
1272 if (err
== noErr
&& cg_glyph
)
1275 ATSUGlyphInfoArray glyph_info_array
;
1276 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1278 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1279 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1281 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1282 kATSUToTextEnd
, &count
,
1285 /* Make sure that we don't have to make layout
1287 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1288 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1289 && glyph_info_array
.glyphs
[0].screenX
== 0)
1291 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1292 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1303 if (font_ascent_return
|| font_descent_return
)
1307 GetFontInfo (&font_info
);
1308 if (font_ascent_return
)
1309 *font_ascent_return
= font_info
.ascent
;
1310 if (font_descent_return
)
1311 *font_descent_return
= font_info
.descent
;
1317 width
= CharWidth (ch
);
1318 QDTextBounds (1, &ch
, &char_bounds
);
1319 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1327 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1330 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1331 XFontStruct
*font_struct
;
1334 XCharStruct
*overall_return
;
1337 short width
= 0, lbearing
= 0, rbearing
= 0;
1340 for (i
= 0; i
< nchars
; i
++)
1342 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1344 width
+= FONT_WIDTH (font_struct
);
1347 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1348 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1349 width
+= pcm
->width
;
1354 overall_return
->lbearing
= lbearing
;
1355 overall_return
->rbearing
= rbearing
;
1356 overall_return
->width
= width
;
1358 /* What's the meaning of the return value of XTextExtents16? */
1362 #if USE_CG_TEXT_DRAWING
1363 static int cg_text_anti_aliasing_threshold
= 8;
1366 init_cg_text_anti_aliasing_threshold ()
1372 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1373 kCFPreferencesCurrentApplication
,
1376 cg_text_anti_aliasing_threshold
= threshold
;
1380 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1385 int nchars
, bg_width
, overstrike_p
;
1387 float port_height
, gx
, gy
;
1389 CGContextRef context
;
1393 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1396 port_height
= FRAME_PIXEL_HEIGHT (f
);
1398 gy
= port_height
- y
;
1399 glyphs
= (CGGlyph
*)buf
;
1400 advances
= alloca (sizeof (CGSize
) * nchars
);
1401 if (advances
== NULL
)
1403 for (i
= 0; i
< nchars
; i
++)
1405 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1407 advances
[i
].width
= pcm
->width
;
1408 advances
[i
].height
= 0;
1409 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1414 context
= mac_begin_cg_clip (f
, gc
);
1416 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1417 if (gc
->n_clip_rects
|| bg_width
)
1419 CGContextTranslateCTM (context
, 0, port_height
);
1420 CGContextScaleCTM (context
, 1, -1);
1421 if (gc
->n_clip_rects
)
1422 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1426 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1429 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1430 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1432 CGContextScaleCTM (context
, 1, -1);
1433 CGContextTranslateCTM (context
, 0, -port_height
);
1437 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1438 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1439 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1440 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1441 CGContextSetShouldAntialias (context
, false);
1442 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1443 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1444 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1447 CGContextSetTextPosition (context
, gx
, gy
);
1448 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1451 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1452 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1455 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1456 else /* CGContextShowGlyphsWithAdvances == NULL */
1458 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1459 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1461 for (i
= 0; i
< nchars
; i
++)
1463 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1465 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1466 gx
+= advances
[i
].width
;
1471 mac_end_cg_clip (f
);
1473 CGContextSynchronize (context
);
1474 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1483 /* Mac replacement for XCopyArea: dest must be window. */
1486 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1491 unsigned int width
, height
;
1496 mac_begin_clip (f
, gc
);
1498 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1499 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1501 ForeColor (blackColor
);
1502 BackColor (whiteColor
);
1504 LockPixels (GetGWorldPixMap (src
));
1505 #if TARGET_API_MAC_CARBON
1510 LockPortBits (port
);
1511 CopyBits (GetPortBitMapForCopyBits (src
),
1512 GetPortBitMapForCopyBits (port
),
1513 &src_r
, &dest_r
, srcCopy
, 0);
1514 UnlockPortBits (port
);
1516 #else /* not TARGET_API_MAC_CARBON */
1517 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1518 &src_r
, &dest_r
, srcCopy
, 0);
1519 #endif /* not TARGET_API_MAC_CARBON */
1520 UnlockPixels (GetGWorldPixMap (src
));
1522 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1529 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1530 width
, height
, dest_x
, dest_y
)
1535 unsigned int width
, height
;
1540 mac_begin_clip (f
, gc
);
1542 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1543 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1545 ForeColor (blackColor
);
1546 BackColor (whiteColor
);
1548 LockPixels (GetGWorldPixMap (src
));
1549 LockPixels (GetGWorldPixMap (mask
));
1550 #if TARGET_API_MAC_CARBON
1555 LockPortBits (port
);
1556 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1557 GetPortBitMapForCopyBits (port
),
1558 &src_r
, &src_r
, &dest_r
);
1559 UnlockPortBits (port
);
1561 #else /* not TARGET_API_MAC_CARBON */
1562 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1563 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1564 #endif /* not TARGET_API_MAC_CARBON */
1565 UnlockPixels (GetGWorldPixMap (mask
));
1566 UnlockPixels (GetGWorldPixMap (src
));
1568 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1572 #endif /* !USE_CG_DRAWING */
1575 /* Mac replacement for XCopyArea: used only for scrolling. */
1578 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1582 unsigned int width
, height
;
1585 #if TARGET_API_MAC_CARBON
1587 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1589 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1591 mac_prepare_for_quickdraw (f
);
1593 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1594 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1595 kScrollWindowNoOptions
, dummy
);
1597 #else /* not TARGET_API_MAC_CARBON */
1599 WindowRef w
= FRAME_MAC_WINDOW (f
);
1601 mac_begin_clip (f
, gc
);
1603 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1604 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1606 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1607 color mapping in CopyBits. Otherwise, it will be slow. */
1608 ForeColor (blackColor
);
1609 BackColor (whiteColor
);
1610 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1612 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1615 #endif /* not TARGET_API_MAC_CARBON */
1619 /* Mac replacement for XChangeGC. */
1622 XChangeGC (display
, gc
, mask
, xgcv
)
1628 if (mask
& GCForeground
)
1629 XSetForeground (display
, gc
, xgcv
->foreground
);
1630 if (mask
& GCBackground
)
1631 XSetBackground (display
, gc
, xgcv
->background
);
1633 XSetFont (display
, gc
, xgcv
->font
);
1637 /* Mac replacement for XCreateGC. */
1640 XCreateGC (display
, d
, mask
, xgcv
)
1646 GC gc
= xmalloc (sizeof (*gc
));
1648 bzero (gc
, sizeof (*gc
));
1649 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1650 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1651 if (CGColorGetTypeID
!= NULL
)
1654 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1655 CGColorRetain (gc
->cg_fore_color
);
1656 CGColorRetain (gc
->cg_back_color
);
1659 XChangeGC (display
, gc
, mask
, xgcv
);
1665 /* Used in xfaces.c. */
1668 XFreeGC (display
, gc
)
1672 if (gc
->clip_region
)
1673 DisposeRgn (gc
->clip_region
);
1674 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1675 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1676 if (CGColorGetTypeID
!= NULL
)
1679 CGColorRelease (gc
->cg_fore_color
);
1680 CGColorRelease (gc
->cg_back_color
);
1687 /* Mac replacement for XGetGCValues. */
1690 XGetGCValues (display
, gc
, mask
, xgcv
)
1696 if (mask
& GCForeground
)
1697 xgcv
->foreground
= gc
->xgcv
.foreground
;
1698 if (mask
& GCBackground
)
1699 xgcv
->background
= gc
->xgcv
.background
;
1701 xgcv
->font
= gc
->xgcv
.font
;
1705 /* Mac replacement for XSetForeground. */
1708 XSetForeground (display
, gc
, color
)
1711 unsigned long color
;
1713 if (gc
->xgcv
.foreground
!= color
)
1715 gc
->xgcv
.foreground
= color
;
1716 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1717 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1718 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1719 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1720 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1721 if (CGColorGetTypeID
!= NULL
)
1724 CGColorRelease (gc
->cg_fore_color
);
1727 gc
->cg_fore_color
= mac_cg_color_black
;
1728 CGColorRetain (gc
->cg_fore_color
);
1734 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1735 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1736 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1738 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1746 /* Mac replacement for XSetBackground. */
1749 XSetBackground (display
, gc
, color
)
1752 unsigned long color
;
1754 if (gc
->xgcv
.background
!= color
)
1756 gc
->xgcv
.background
= color
;
1757 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1758 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1759 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1760 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1761 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1762 if (CGColorGetTypeID
!= NULL
)
1765 CGColorRelease (gc
->cg_back_color
);
1768 gc
->cg_back_color
= mac_cg_color_black
;
1769 CGColorRetain (gc
->cg_back_color
);
1775 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1776 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1777 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1779 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1787 /* Mac replacement for XSetFont. */
1790 XSetFont (display
, gc
, font
)
1795 gc
->xgcv
.font
= font
;
1799 /* Mac replacement for XSetClipRectangles. */
1802 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1810 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1812 gc
->n_clip_rects
= n
;
1815 if (gc
->clip_region
== NULL
)
1816 gc
->clip_region
= NewRgn ();
1817 RectRgn (gc
->clip_region
, rectangles
);
1820 RgnHandle region
= NewRgn ();
1822 for (i
= 1; i
< n
; i
++)
1824 RectRgn (region
, rectangles
+ i
);
1825 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1827 DisposeRgn (region
);
1830 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1831 for (i
= 0; i
< n
; i
++)
1833 Rect
*rect
= rectangles
+ i
;
1835 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1836 rect
->right
- rect
->left
,
1837 rect
->bottom
- rect
->top
);
1843 /* Mac replacement for XSetClipMask. */
1846 mac_reset_clip_rectangles (display
, gc
)
1850 gc
->n_clip_rects
= 0;
1854 /* Mac replacement for XSetWindowBackground. */
1857 XSetWindowBackground (display
, w
, color
)
1860 unsigned long color
;
1862 #if !TARGET_API_MAC_CARBON
1863 AuxWinHandle aw_handle
;
1864 CTabHandle ctab_handle
;
1865 ColorSpecPtr ct_table
;
1870 bg_color
.red
= RED16_FROM_ULONG (color
);
1871 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1872 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1874 #if TARGET_API_MAC_CARBON
1875 SetWindowContentColor (w
, &bg_color
);
1877 if (GetAuxWin (w
, &aw_handle
))
1879 ctab_handle
= (*aw_handle
)->awCTable
;
1880 HandToHand ((Handle
*) &ctab_handle
);
1881 ct_table
= (*ctab_handle
)->ctTable
;
1882 ct_size
= (*ctab_handle
)->ctSize
;
1883 while (ct_size
> -1)
1885 if (ct_table
->value
== 0)
1887 ct_table
->rgb
= bg_color
;
1888 CTabChanged (ctab_handle
);
1889 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1897 /* Flush display of frame F, or of all frames if F is null. */
1903 #if TARGET_API_MAC_CARBON
1906 mac_prepare_for_quickdraw (f
);
1909 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1911 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1917 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1918 Calls to XFlush should be unnecessary because the X output buffer
1919 is flushed automatically as needed by calls to XPending,
1920 XNextEvent, or XWindowEvent according to the XFlush man page.
1921 XTread_socket calls XPending. Removing XFlush improves
1924 #define XFlush(DISPLAY) (void) 0
1928 mac_flush_display_optional (f
)
1932 mac_prepare_for_quickdraw (f
);
1937 /***********************************************************************
1938 Starting and ending an update
1939 ***********************************************************************/
1941 /* Start an update of frame F. This function is installed as a hook
1942 for update_begin, i.e. it is called when update_begin is called.
1943 This function is called prior to calls to x_update_window_begin for
1944 each window being updated. */
1950 #if TARGET_API_MAC_CARBON
1951 /* During update of a frame, availability of input events is
1952 periodically checked with ReceiveNextEvent if
1953 redisplay-dont-pause is nil. That normally flushes window buffer
1954 changes for every check, and thus screen update looks waving even
1955 if no input is available. So we disable screen updates during
1956 update of a frame. */
1958 DisableScreenUpdates ();
1964 /* Start update of window W. Set the global variable updated_window
1965 to the window being updated and set output_cursor to the cursor
1969 x_update_window_begin (w
)
1972 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1973 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1976 set_output_cursor (&w
->cursor
);
1980 if (f
== display_info
->mouse_face_mouse_frame
)
1982 /* Don't do highlighting for mouse motion during the update. */
1983 display_info
->mouse_face_defer
= 1;
1985 /* If F needs to be redrawn, simply forget about any prior mouse
1987 if (FRAME_GARBAGED_P (f
))
1988 display_info
->mouse_face_window
= Qnil
;
1990 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1991 their mouse_face_p flag set, which means that they are always
1992 unequal to rows in a desired matrix which never have that
1993 flag set. So, rows containing mouse-face glyphs are never
1994 scrolled, and we don't have to switch the mouse highlight off
1995 here to prevent it from being scrolled. */
1997 /* Can we tell that this update does not affect the window
1998 where the mouse highlight is? If so, no need to turn off.
1999 Likewise, don't do anything if the frame is garbaged;
2000 in that case, the frame's current matrix that we would use
2001 is all wrong, and we will redisplay that line anyway. */
2002 if (!NILP (display_info
->mouse_face_window
)
2003 && w
== XWINDOW (display_info
->mouse_face_window
))
2007 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2008 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2011 if (i
< w
->desired_matrix
->nrows
)
2012 clear_mouse_face (display_info
);
2021 /* Draw a vertical window border from (x,y0) to (x,y1) */
2024 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2028 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2031 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2033 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2036 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2039 /* End update of window W (which is equal to updated_window).
2041 Draw vertical borders between horizontally adjacent windows, and
2042 display W's cursor if CURSOR_ON_P is non-zero.
2044 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2045 glyphs in mouse-face were overwritten. In that case we have to
2046 make sure that the mouse-highlight is properly redrawn.
2048 W may be a menu bar pseudo-window in case we don't have X toolkit
2049 support. Such windows don't have a cursor, so don't display it
2053 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2055 int cursor_on_p
, mouse_face_overwritten_p
;
2057 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2059 if (!w
->pseudo_window_p
)
2064 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2066 output_cursor
.x
, output_cursor
.y
);
2068 if (draw_window_fringes (w
, 1))
2069 x_draw_vertical_border (w
);
2074 /* If a row with mouse-face was overwritten, arrange for
2075 XTframe_up_to_date to redisplay the mouse highlight. */
2076 if (mouse_face_overwritten_p
)
2078 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2079 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2080 dpyinfo
->mouse_face_window
= Qnil
;
2083 updated_window
= NULL
;
2087 /* End update of frame F. This function is installed as a hook in
2094 /* Mouse highlight may be displayed again. */
2095 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2098 #if TARGET_API_MAC_CARBON
2099 EnableScreenUpdates ();
2101 XFlush (FRAME_MAC_DISPLAY (f
));
2106 /* This function is called from various places in xdisp.c whenever a
2107 complete update has been performed. The global variable
2108 updated_window is not available here. */
2111 XTframe_up_to_date (f
)
2114 if (FRAME_MAC_P (f
))
2116 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2118 if (dpyinfo
->mouse_face_deferred_gc
2119 || f
== dpyinfo
->mouse_face_mouse_frame
)
2122 if (dpyinfo
->mouse_face_mouse_frame
)
2123 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2124 dpyinfo
->mouse_face_mouse_x
,
2125 dpyinfo
->mouse_face_mouse_y
);
2126 dpyinfo
->mouse_face_deferred_gc
= 0;
2133 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2134 arrow bitmaps, or clear the fringes if no bitmaps are required
2135 before DESIRED_ROW is made current. The window being updated is
2136 found in updated_window. This function is called from
2137 update_window_line only if it is known that there are differences
2138 between bitmaps to be drawn between current row and DESIRED_ROW. */
2141 x_after_update_window_line (desired_row
)
2142 struct glyph_row
*desired_row
;
2144 struct window
*w
= updated_window
;
2150 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2151 desired_row
->redraw_fringe_bitmaps_p
= 1;
2153 /* When a window has disappeared, make sure that no rest of
2154 full-width rows stays visible in the internal border. Could
2155 check here if updated_window is the leftmost/rightmost window,
2156 but I guess it's not worth doing since vertically split windows
2157 are almost never used, internal border is rarely set, and the
2158 overhead is very small. */
2159 if (windows_or_buffers_changed
2160 && desired_row
->full_width_p
2161 && (f
= XFRAME (w
->frame
),
2162 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2164 && (height
= desired_row
->visible_height
,
2167 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2169 /* Internal border is drawn below the tool bar. */
2170 if (WINDOWP (f
->tool_bar_window
)
2171 && w
== XWINDOW (f
->tool_bar_window
))
2175 mac_clear_area (f
, 0, y
, width
, height
);
2176 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2182 /* Draw the bitmap WHICH in one of the left or right fringes of
2183 window W. ROW is the glyph row for which to display the bitmap; it
2184 determines the vertical position at which the bitmap has to be
2188 x_draw_fringe_bitmap (w
, row
, p
)
2190 struct glyph_row
*row
;
2191 struct draw_fringe_bitmap_params
*p
;
2193 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2194 Display
*display
= FRAME_MAC_DISPLAY (f
);
2195 struct face
*face
= p
->face
;
2199 if (p
->bx
>= 0 && !p
->overlay_p
)
2201 int bx
= p
->bx
, nx
= p
->nx
;
2203 #if 0 /* MAC_TODO: stipple */
2204 /* In case the same realized face is used for fringes and
2205 for something displayed in the text (e.g. face `region' on
2206 mono-displays, the fill style may have been changed to
2207 FillSolid in x_draw_glyph_string_background. */
2209 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2211 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2214 /* If the fringe is adjacent to the left (right) scroll bar of a
2215 leftmost (rightmost, respectively) window, then extend its
2216 background to the gap between the fringe and the bar. */
2217 if ((WINDOW_LEFTMOST_P (w
)
2218 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2219 || (WINDOW_RIGHTMOST_P (w
)
2220 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2222 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2226 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2227 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2228 * FRAME_COLUMN_WIDTH (f
));
2230 if (left
+ width
== bx
)
2232 bx
= left
+ sb_width
;
2233 nx
+= width
- sb_width
;
2235 else if (bx
+ nx
== left
)
2236 nx
+= width
- sb_width
;
2240 mac_erase_rectangle (f
, face
->gc
, bx
, p
->by
, nx
, p
->ny
);
2242 #if 0 /* MAC_TODO: stipple */
2244 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2247 #endif /* MAC_OSX */
2249 /* Must clip because of partially visible lines. */
2250 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2253 /* Adjust position of "bottom aligned" bitmap on partially
2254 visible last row. */
2256 int oldVH
= row
->visible_height
;
2257 row
->visible_height
= p
->h
;
2258 row
->y
-= rowY
- p
->y
;
2259 x_clip_to_row (w
, row
, -1, face
->gc
);
2261 row
->visible_height
= oldVH
;
2264 x_clip_to_row (w
, row
, -1, face
->gc
);
2267 if (p
->bx
>= 0 && !p
->overlay_p
)
2269 #if 0 /* MAC_TODO: stipple */
2270 /* In case the same realized face is used for fringes and
2271 for something displayed in the text (e.g. face `region' on
2272 mono-displays, the fill style may have been changed to
2273 FillSolid in x_draw_glyph_string_background. */
2275 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2277 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2280 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2282 #if 0 /* MAC_TODO: stipple */
2284 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2287 #endif /* !MAC_OSX */
2291 && p
->which
< max_fringe_bmp
2297 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2298 XSetForeground (display
, face
->gc
,
2300 ? (p
->overlay_p
? face
->background
2301 : f
->output_data
.mac
->cursor_pixel
)
2302 : face
->foreground
));
2304 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2305 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
2307 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2308 p
->wd
, p
->h
, p
->bits
+ p
->dh
, p
->overlay_p
);
2310 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2313 mac_reset_clip_rectangles (display
, face
->gc
);
2318 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2320 unsigned short *bits
;
2324 CGDataProviderRef provider
;
2326 if (which
>= max_fringe_bmp
)
2329 max_fringe_bmp
= which
+ 20;
2330 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2331 while (i
< max_fringe_bmp
)
2332 fringe_bmp
[i
++] = 0;
2335 for (i
= 0; i
< h
; i
++)
2337 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2338 sizeof (unsigned short) * h
, NULL
);
2341 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2342 sizeof (unsigned short),
2344 CGDataProviderRelease (provider
);
2349 mac_destroy_fringe_bitmap (which
)
2352 if (which
>= max_fringe_bmp
)
2355 if (fringe_bmp
[which
])
2356 CGImageRelease (fringe_bmp
[which
]);
2357 fringe_bmp
[which
] = 0;
2362 /* This is called when starting Emacs and when restarting after
2363 suspend. When starting Emacs, no window is mapped. And nothing
2364 must be done to Emacs's own window if it is suspended (though that
2368 XTset_terminal_modes ()
2372 /* This is called when exiting or suspending Emacs. Exiting will make
2373 the windows go away, and suspending requires no action. */
2376 XTreset_terminal_modes ()
2382 /***********************************************************************
2384 ***********************************************************************/
2386 /* Function prototypes of this page. */
2388 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2389 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2393 pcm_init (pcm
, count
)
2397 bzero (pcm
, sizeof (XCharStruct
) * count
);
2398 while (--count
>= 0)
2400 pcm
->descent
= PCM_INVALID
;
2405 static enum pcm_status
2406 pcm_get_status (pcm
)
2407 const XCharStruct
*pcm
;
2409 int height
= pcm
->ascent
+ pcm
->descent
;
2411 /* Negative height means some special status. */
2412 return height
>= 0 ? PCM_VALID
: height
;
2415 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2416 is not contained in the font. */
2418 static INLINE XCharStruct
*
2419 x_per_char_metric (font
, char2b
)
2423 /* The result metric information. */
2424 XCharStruct
*pcm
= NULL
;
2426 xassert (font
&& char2b
);
2429 if (font
->mac_style
)
2431 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2435 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2436 pcm_init (*row
, 0x100);
2438 pcm
= *row
+ char2b
->byte2
;
2439 if (pcm_get_status (pcm
) != PCM_VALID
)
2442 mac_query_char_extents (font
->mac_style
,
2443 (char2b
->byte1
<< 8) + char2b
->byte2
,
2444 NULL
, NULL
, pcm
, NULL
);
2451 if (font
->bounds
.per_char
!= NULL
)
2453 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2455 /* min_char_or_byte2 specifies the linear character index
2456 corresponding to the first element of the per_char array,
2457 max_char_or_byte2 is the index of the last character. A
2458 character with non-zero CHAR2B->byte1 is not in the font.
2459 A character with byte2 less than min_char_or_byte2 or
2460 greater max_char_or_byte2 is not in the font. */
2461 if (char2b
->byte1
== 0
2462 && char2b
->byte2
>= font
->min_char_or_byte2
2463 && char2b
->byte2
<= font
->max_char_or_byte2
)
2464 pcm
= font
->bounds
.per_char
2465 + (char2b
->byte2
- font
->min_char_or_byte2
);
2469 /* If either min_byte1 or max_byte1 are nonzero, both
2470 min_char_or_byte2 and max_char_or_byte2 are less than
2471 256, and the 2-byte character index values corresponding
2472 to the per_char array element N (counting from 0) are:
2474 byte1 = N/D + min_byte1
2475 byte2 = N\D + min_char_or_byte2
2479 D = max_char_or_byte2 - min_char_or_byte2 + 1
2480 / = integer division
2481 \ = integer modulus */
2482 if (char2b
->byte1
>= font
->min_byte1
2483 && char2b
->byte1
<= font
->max_byte1
2484 && char2b
->byte2
>= font
->min_char_or_byte2
2485 && char2b
->byte2
<= font
->max_char_or_byte2
)
2487 pcm
= (font
->bounds
.per_char
2488 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2489 * (char2b
->byte1
- font
->min_byte1
))
2490 + (char2b
->byte2
- font
->min_char_or_byte2
));
2496 /* If the per_char pointer is null, all glyphs between the first
2497 and last character indexes inclusive have the same
2498 information, as given by both min_bounds and max_bounds. */
2499 if (char2b
->byte2
>= font
->min_char_or_byte2
2500 && char2b
->byte2
<= font
->max_char_or_byte2
)
2501 pcm
= &font
->max_bounds
;
2507 return ((pcm
== NULL
2509 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2510 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2519 static XCharStruct
*
2520 mac_per_char_metric (font
, char2b
, font_type
)
2525 return x_per_char_metric (font
, char2b
);
2529 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2530 the two-byte form of C. Encoding is returned in *CHAR2B. */
2533 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2536 struct font_info
*font_info
;
2539 int charset
= CHAR_CHARSET (c
);
2540 XFontStruct
*font
= font_info
->font
;
2542 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2543 This may be either a program in a special encoder language or a
2545 if (font_info
->font_encoder
)
2547 /* It's a program. */
2548 struct ccl_program
*ccl
= font_info
->font_encoder
;
2550 check_ccl_update (ccl
);
2551 if (CHARSET_DIMENSION (charset
) == 1)
2553 ccl
->reg
[0] = charset
;
2554 ccl
->reg
[1] = char2b
->byte2
;
2559 ccl
->reg
[0] = charset
;
2560 ccl
->reg
[1] = char2b
->byte1
;
2561 ccl
->reg
[2] = char2b
->byte2
;
2564 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2566 /* We assume that MSBs are appropriately set/reset by CCL
2568 if (font
->max_byte1
== 0) /* 1-byte font */
2569 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2571 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2573 else if (font_info
->encoding
[charset
])
2575 /* Fixed encoding scheme. See fontset.h for the meaning of the
2576 encoding numbers. */
2577 int enc
= font_info
->encoding
[charset
];
2579 if ((enc
== 1 || enc
== 2)
2580 && CHARSET_DIMENSION (charset
) == 2)
2581 char2b
->byte1
|= 0x80;
2583 if (enc
== 1 || enc
== 3)
2584 char2b
->byte2
|= 0x80;
2590 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2591 char2b
->byte1
= sjis1
;
2592 char2b
->byte2
= sjis2
;
2597 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2599 return FONT_TYPE_UNKNOWN
;
2604 /***********************************************************************
2606 ***********************************************************************/
2610 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2611 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2612 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2614 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2615 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2616 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2617 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2618 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2619 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2620 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2621 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2622 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2623 unsigned long *, double, int));*/
2624 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2625 double, int, unsigned long));
2626 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2627 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2628 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2629 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2630 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2632 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2633 int, int, int, int, int, int,
2635 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2636 int, int, int, Rect
*));
2639 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2643 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2648 struct glyph_string
*s
;
2650 if (s
->font
== FRAME_FONT (s
->f
)
2651 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2652 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2654 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2657 /* Cursor on non-default face: must merge. */
2661 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2662 xgcv
.foreground
= s
->face
->background
;
2664 /* If the glyph would be invisible, try a different foreground. */
2665 if (xgcv
.foreground
== xgcv
.background
)
2666 xgcv
.foreground
= s
->face
->foreground
;
2667 if (xgcv
.foreground
== xgcv
.background
)
2668 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2669 if (xgcv
.foreground
== xgcv
.background
)
2670 xgcv
.foreground
= s
->face
->foreground
;
2672 /* Make sure the cursor is distinct from text in this face. */
2673 if (xgcv
.background
== s
->face
->background
2674 && xgcv
.foreground
== s
->face
->foreground
)
2676 xgcv
.background
= s
->face
->foreground
;
2677 xgcv
.foreground
= s
->face
->background
;
2680 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2681 xgcv
.font
= s
->font
;
2682 mask
= GCForeground
| GCBackground
| GCFont
;
2684 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2685 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2688 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2689 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2691 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2696 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2699 x_set_mouse_face_gc (s
)
2700 struct glyph_string
*s
;
2705 /* What face has to be used last for the mouse face? */
2706 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2707 face
= FACE_FROM_ID (s
->f
, face_id
);
2709 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2711 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2712 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2714 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2715 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2716 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2718 /* If font in this face is same as S->font, use it. */
2719 if (s
->font
== s
->face
->font
)
2720 s
->gc
= s
->face
->gc
;
2723 /* Otherwise construct scratch_cursor_gc with values from FACE
2728 xgcv
.background
= s
->face
->background
;
2729 xgcv
.foreground
= s
->face
->foreground
;
2730 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2731 xgcv
.font
= s
->font
;
2732 mask
= GCForeground
| GCBackground
| GCFont
;
2734 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2735 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2738 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2739 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2741 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2744 xassert (s
->gc
!= 0);
2748 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2749 Faces to use in the mode line have already been computed when the
2750 matrix was built, so there isn't much to do, here. */
2753 x_set_mode_line_face_gc (s
)
2754 struct glyph_string
*s
;
2756 s
->gc
= s
->face
->gc
;
2760 /* Set S->gc of glyph string S for drawing that glyph string. Set
2761 S->stippled_p to a non-zero value if the face of S has a stipple
2765 x_set_glyph_string_gc (s
)
2766 struct glyph_string
*s
;
2768 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2770 if (s
->hl
== DRAW_NORMAL_TEXT
)
2772 s
->gc
= s
->face
->gc
;
2773 s
->stippled_p
= s
->face
->stipple
!= 0;
2775 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2777 x_set_mode_line_face_gc (s
);
2778 s
->stippled_p
= s
->face
->stipple
!= 0;
2780 else if (s
->hl
== DRAW_CURSOR
)
2782 x_set_cursor_gc (s
);
2785 else if (s
->hl
== DRAW_MOUSE_FACE
)
2787 x_set_mouse_face_gc (s
);
2788 s
->stippled_p
= s
->face
->stipple
!= 0;
2790 else if (s
->hl
== DRAW_IMAGE_RAISED
2791 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2793 s
->gc
= s
->face
->gc
;
2794 s
->stippled_p
= s
->face
->stipple
!= 0;
2798 s
->gc
= s
->face
->gc
;
2799 s
->stippled_p
= s
->face
->stipple
!= 0;
2802 /* GC must have been set. */
2803 xassert (s
->gc
!= 0);
2807 /* Set clipping for output of glyph string S. S may be part of a mode
2808 line or menu if we don't have X toolkit support. */
2811 x_set_glyph_string_clipping (s
)
2812 struct glyph_string
*s
;
2814 Rect rects
[MAX_CLIP_RECTS
];
2817 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2818 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2823 Compute left and right overhang of glyph string S. If S is a glyph
2824 string for a composition, assume overhangs don't exist. */
2827 mac_compute_glyph_string_overhangs (s
)
2828 struct glyph_string
*s
;
2830 if (!(s
->cmp
== NULL
2831 && s
->first_glyph
->type
== CHAR_GLYPH
))
2836 || s
->font
->mac_style
2842 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2843 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2844 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2849 MacFontStruct
*font
= s
->font
;
2852 mac_prepare_for_quickdraw (s
->f
);
2854 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2856 TextFont (font
->mac_fontnum
);
2857 TextSize (font
->mac_fontsize
);
2858 TextFace (font
->mac_fontface
);
2860 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2862 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2863 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2868 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2871 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2872 struct glyph_string
*s
;
2875 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2879 /* Draw the background of glyph_string S. If S->background_filled_p
2880 is non-zero don't draw it. FORCE_P non-zero means draw the
2881 background even if it wouldn't be drawn normally. This is used
2882 when a string preceding S draws into the background of S, or S
2883 contains the first component of a composition. */
2886 x_draw_glyph_string_background (s
, force_p
)
2887 struct glyph_string
*s
;
2890 /* Nothing to do if background has already been drawn or if it
2891 shouldn't be drawn in the first place. */
2892 if (!s
->background_filled_p
)
2894 int box_line_width
= max (s
->face
->box_line_width
, 0);
2896 #if 0 /* MAC_TODO: stipple */
2899 /* Fill background with a stipple pattern. */
2900 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2901 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2902 s
->y
+ box_line_width
,
2903 s
->background_width
,
2904 s
->height
- 2 * box_line_width
);
2905 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2906 s
->background_filled_p
= 1;
2910 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2911 || s
->font_not_found_p
2912 || s
->extends_to_end_of_line_p
2915 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2916 s
->background_width
,
2917 s
->height
- 2 * box_line_width
);
2918 s
->background_filled_p
= 1;
2924 /* Draw the foreground of glyph string S. */
2927 x_draw_glyph_string_foreground (s
)
2928 struct glyph_string
*s
;
2932 /* If first glyph of S has a left box line, start drawing the text
2933 of S to the right of that box line. */
2934 if (s
->face
->box
!= FACE_NO_BOX
2935 && s
->first_glyph
->left_box_line_p
)
2936 x
= s
->x
+ abs (s
->face
->box_line_width
);
2940 /* Draw characters of S as rectangles if S's font could not be
2942 if (s
->font_not_found_p
)
2944 for (i
= 0; i
< s
->nchars
; ++i
)
2946 struct glyph
*g
= s
->first_glyph
+ i
;
2947 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2948 g
->pixel_width
- 1, s
->height
- 1);
2949 x
+= g
->pixel_width
;
2954 char *char1b
= (char *) s
->char2b
;
2955 int boff
= s
->font_info
->baseline_offset
;
2957 if (s
->font_info
->vertical_centering
)
2958 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2960 /* If we can use 8-bit functions, condense S->char2b. */
2963 && GC_FONT (s
->gc
)->mac_style
== NULL
2966 for (i
= 0; i
< s
->nchars
; ++i
)
2967 char1b
[i
] = s
->char2b
[i
].byte2
;
2969 /* Draw text with XDrawString if background has already been
2970 filled. Otherwise, use XDrawImageString. (Note that
2971 XDrawImageString is usually faster than XDrawString.) Always
2972 use XDrawImageString when drawing the cursor so that there is
2973 no chance that characters under a box cursor are invisible. */
2975 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2976 bg_width
= 0; /* Corresponds to XDrawString. */
2978 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2982 || GC_FONT (s
->gc
)->mac_style
2985 #if USE_CG_TEXT_DRAWING
2987 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2988 s
->char2b
, s
->nchars
, bg_width
,
2989 s
->face
->overstrike
))
2993 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2994 s
->char2b
, s
->nchars
, bg_width
,
2995 s
->face
->overstrike
);
2997 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2998 char1b
, s
->nchars
, bg_width
,
2999 s
->face
->overstrike
);
3003 /* Draw the foreground of composite glyph string S. */
3006 x_draw_composite_glyph_string_foreground (s
)
3007 struct glyph_string
*s
;
3011 /* If first glyph of S has a left box line, start drawing the text
3012 of S to the right of that box line. */
3013 if (s
->face
->box
!= FACE_NO_BOX
3014 && s
->first_glyph
->left_box_line_p
)
3015 x
= s
->x
+ abs (s
->face
->box_line_width
);
3019 /* S is a glyph string for a composition. S->gidx is the index of
3020 the first character drawn for glyphs of this composition.
3021 S->gidx == 0 means we are drawing the very first character of
3022 this composition. */
3024 /* Draw a rectangle for the composition if the font for the very
3025 first character of the composition could not be loaded. */
3026 if (s
->font_not_found_p
)
3029 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3030 s
->width
- 1, s
->height
- 1);
3034 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3035 mac_draw_image_string_16 (s
->f
, s
->gc
,
3036 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3037 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3038 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3043 #ifdef USE_X_TOOLKIT
3045 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3048 /* Return the frame on which widget WIDGET is used.. Abort if frame
3049 cannot be determined. */
3051 static struct frame
*
3052 x_frame_of_widget (widget
)
3055 struct x_display_info
*dpyinfo
;
3059 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3061 /* Find the top-level shell of the widget. Note that this function
3062 can be called when the widget is not yet realized, so XtWindow
3063 (widget) == 0. That's the reason we can't simply use
3064 x_any_window_to_frame. */
3065 while (!XtIsTopLevelShell (widget
))
3066 widget
= XtParent (widget
);
3068 /* Look for a frame with that top-level widget. Allocate the color
3069 on that frame to get the right gamma correction value. */
3070 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3071 if (GC_FRAMEP (XCAR (tail
))
3072 && (f
= XFRAME (XCAR (tail
)),
3073 (f
->output_data
.nothing
!= 1
3074 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3075 && f
->output_data
.x
->widget
== widget
)
3082 /* Allocate the color COLOR->pixel on the screen and display of
3083 widget WIDGET in colormap CMAP. If an exact match cannot be
3084 allocated, try the nearest color available. Value is non-zero
3085 if successful. This is called from lwlib. */
3088 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3093 struct frame
*f
= x_frame_of_widget (widget
);
3094 return x_alloc_nearest_color (f
, cmap
, color
);
3098 #endif /* USE_X_TOOLKIT */
3100 #if 0 /* MAC_TODO */
3102 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3103 CMAP. If an exact match can't be allocated, try the nearest color
3104 available. Value is non-zero if successful. Set *COLOR to the
3108 x_alloc_nearest_color (f
, cmap
, color
)
3113 Display
*display
= FRAME_X_DISPLAY (f
);
3114 Screen
*screen
= FRAME_X_SCREEN (f
);
3117 gamma_correct (f
, color
);
3118 rc
= XAllocColor (display
, cmap
, color
);
3121 /* If we got to this point, the colormap is full, so we're going
3122 to try to get the next closest color. The algorithm used is
3123 a least-squares matching, which is what X uses for closest
3124 color matching with StaticColor visuals. */
3126 unsigned long nearest_delta
= ~0;
3127 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3128 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3130 for (i
= 0; i
< ncells
; ++i
)
3132 XQueryColors (display
, cmap
, cells
, ncells
);
3134 for (nearest
= i
= 0; i
< ncells
; ++i
)
3136 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3137 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3138 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3139 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3141 if (delta
< nearest_delta
)
3144 nearest_delta
= delta
;
3148 color
->red
= cells
[nearest
].red
;
3149 color
->green
= cells
[nearest
].green
;
3150 color
->blue
= cells
[nearest
].blue
;
3151 rc
= XAllocColor (display
, cmap
, color
);
3154 #ifdef DEBUG_X_COLORS
3156 register_color (color
->pixel
);
3157 #endif /* DEBUG_X_COLORS */
3163 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3164 It's necessary to do this instead of just using PIXEL directly to
3165 get color reference counts right. */
3168 x_copy_color (f
, pixel
)
3170 unsigned long pixel
;
3174 color
.pixel
= pixel
;
3176 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3177 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3179 #ifdef DEBUG_X_COLORS
3180 register_color (pixel
);
3186 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3187 It's necessary to do this instead of just using PIXEL directly to
3188 get color reference counts right. */
3191 x_copy_dpy_color (dpy
, cmap
, pixel
)
3194 unsigned long pixel
;
3198 color
.pixel
= pixel
;
3200 XQueryColor (dpy
, cmap
, &color
);
3201 XAllocColor (dpy
, cmap
, &color
);
3203 #ifdef DEBUG_X_COLORS
3204 register_color (pixel
);
3209 #endif /* MAC_TODO */
3212 /* Brightness beyond which a color won't have its highlight brightness
3215 Nominally, highlight colors for `3d' faces are calculated by
3216 brightening an object's color by a constant scale factor, but this
3217 doesn't yield good results for dark colors, so for colors who's
3218 brightness is less than this value (on a scale of 0-255) have to
3219 use an additional additive factor.
3221 The value here is set so that the default menu-bar/mode-line color
3222 (grey75) will not have its highlights changed at all. */
3223 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3226 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3227 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3228 If this produces the same color as COLOR, try a color where all RGB
3229 values have DELTA added. Return the allocated color in *COLOR.
3230 DISPLAY is the X display, CMAP is the colormap to operate on.
3231 Value is non-zero if successful. */
3234 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3236 unsigned long *color
;
3243 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3246 /* Change RGB values by specified FACTOR. Avoid overflow! */
3247 xassert (factor
>= 0);
3248 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3249 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3250 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3252 /* Calculate brightness of COLOR. */
3253 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3254 + BLUE_FROM_ULONG (*color
)) / 6;
3256 /* We only boost colors that are darker than
3257 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3258 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3259 /* Make an additive adjustment to NEW, because it's dark enough so
3260 that scaling by FACTOR alone isn't enough. */
3262 /* How far below the limit this color is (0 - 1, 1 being darker). */
3263 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3264 /* The additive adjustment. */
3265 int min_delta
= delta
* dimness
* factor
/ 2;
3268 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3269 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3270 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3272 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3273 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3274 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3278 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3279 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3280 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3282 /* MAC_TODO: Map to palette and retry with delta if same? */
3283 /* MAC_TODO: Free colors (if using palette)? */
3294 /* Set up the foreground color for drawing relief lines of glyph
3295 string S. RELIEF is a pointer to a struct relief containing the GC
3296 with which lines will be drawn. Use a color that is FACTOR or
3297 DELTA lighter or darker than the relief's background which is found
3298 in S->f->output_data.x->relief_background. If such a color cannot
3299 be allocated, use DEFAULT_PIXEL, instead. */
3302 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3304 struct relief
*relief
;
3307 unsigned long default_pixel
;
3310 struct mac_output
*di
= f
->output_data
.mac
;
3311 unsigned long mask
= GCForeground
;
3312 unsigned long pixel
;
3313 unsigned long background
= di
->relief_background
;
3314 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3316 /* MAC_TODO: Free colors (if using palette)? */
3318 /* Allocate new color. */
3319 xgcv
.foreground
= default_pixel
;
3321 if (dpyinfo
->n_planes
!= 1
3322 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3324 relief
->allocated_p
= 1;
3325 xgcv
.foreground
= relief
->pixel
= pixel
;
3328 if (relief
->gc
== 0)
3330 #if 0 /* MAC_TODO: stipple */
3331 xgcv
.stipple
= dpyinfo
->gray
;
3334 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3337 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3341 /* Set up colors for the relief lines around glyph string S. */
3344 x_setup_relief_colors (s
)
3345 struct glyph_string
*s
;
3347 struct mac_output
*di
= s
->f
->output_data
.mac
;
3348 unsigned long color
;
3350 if (s
->face
->use_box_color_for_shadows_p
)
3351 color
= s
->face
->box_color
;
3352 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3354 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3355 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3360 /* Get the background color of the face. */
3361 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3362 color
= xgcv
.background
;
3365 if (di
->white_relief
.gc
== 0
3366 || color
!= di
->relief_background
)
3368 di
->relief_background
= color
;
3369 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3370 WHITE_PIX_DEFAULT (s
->f
));
3371 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3372 BLACK_PIX_DEFAULT (s
->f
));
3377 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3378 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3379 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3380 relief. LEFT_P non-zero means draw a relief on the left side of
3381 the rectangle. RIGHT_P non-zero means draw a relief on the right
3382 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3386 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3387 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3389 int left_x
, top_y
, right_x
, bottom_y
, width
;
3390 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3393 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3398 gc
= f
->output_data
.mac
->white_relief
.gc
;
3400 gc
= f
->output_data
.mac
->black_relief
.gc
;
3401 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3405 for (i
= 0; i
< width
; ++i
)
3406 mac_draw_line (f
, gc
,
3407 left_x
+ i
* left_p
, top_y
+ i
,
3408 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3412 for (i
= 0; i
< width
; ++i
)
3413 mac_draw_line (f
, gc
,
3414 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3416 mac_reset_clip_rectangles (dpy
, gc
);
3418 gc
= f
->output_data
.mac
->black_relief
.gc
;
3420 gc
= f
->output_data
.mac
->white_relief
.gc
;
3421 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3425 for (i
= 0; i
< width
; ++i
)
3426 mac_draw_line (f
, gc
,
3427 left_x
+ i
* left_p
, bottom_y
- i
,
3428 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3432 for (i
= 0; i
< width
; ++i
)
3433 mac_draw_line (f
, gc
,
3434 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3436 mac_reset_clip_rectangles (dpy
, gc
);
3440 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3441 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3442 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3443 left side of the rectangle. RIGHT_P non-zero means draw a line
3444 on the right side of the rectangle. CLIP_RECT is the clipping
3445 rectangle to use when drawing. */
3448 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3449 left_p
, right_p
, clip_rect
)
3450 struct glyph_string
*s
;
3451 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3456 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3457 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3458 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3461 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3462 right_x
- left_x
+ 1, width
);
3466 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3467 width
, bottom_y
- top_y
+ 1);
3470 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3471 right_x
- left_x
+ 1, width
);
3475 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3476 top_y
, width
, bottom_y
- top_y
+ 1);
3478 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3479 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3483 /* Draw a box around glyph string S. */
3486 x_draw_glyph_string_box (s
)
3487 struct glyph_string
*s
;
3489 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3490 int left_p
, right_p
;
3491 struct glyph
*last_glyph
;
3494 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3495 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3496 : window_box_right (s
->w
, s
->area
));
3498 /* The glyph that may have a right box line. */
3499 last_glyph
= (s
->cmp
|| s
->img
3501 : s
->first_glyph
+ s
->nchars
- 1);
3503 width
= abs (s
->face
->box_line_width
);
3504 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3506 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3508 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3510 bottom_y
= top_y
+ s
->height
- 1;
3512 left_p
= (s
->first_glyph
->left_box_line_p
3513 || (s
->hl
== DRAW_MOUSE_FACE
3515 || s
->prev
->hl
!= s
->hl
)));
3516 right_p
= (last_glyph
->right_box_line_p
3517 || (s
->hl
== DRAW_MOUSE_FACE
3519 || s
->next
->hl
!= s
->hl
)));
3521 get_glyph_string_clip_rect (s
, &clip_rect
);
3523 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3524 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3525 left_p
, right_p
, &clip_rect
);
3528 x_setup_relief_colors (s
);
3529 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3530 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3535 /* Draw foreground of image glyph string S. */
3538 x_draw_image_foreground (s
)
3539 struct glyph_string
*s
;
3542 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3544 /* If first glyph of S has a left box line, start drawing it to the
3545 right of that line. */
3546 if (s
->face
->box
!= FACE_NO_BOX
3547 && s
->first_glyph
->left_box_line_p
3549 x
+= abs (s
->face
->box_line_width
);
3551 /* If there is a margin around the image, adjust x- and y-position
3553 if (s
->slice
.x
== 0)
3554 x
+= s
->img
->hmargin
;
3555 if (s
->slice
.y
== 0)
3556 y
+= s
->img
->vmargin
;
3560 x_set_glyph_string_clipping (s
);
3563 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3564 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3565 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3569 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3570 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3571 s
->slice
.width
, s
->slice
.height
, x
, y
);
3578 mac_copy_area (s
->img
->pixmap
,
3579 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3580 s
->slice
.width
, s
->slice
.height
, x
, y
);
3583 /* When the image has a mask, we can expect that at
3584 least part of a mouse highlight or a block cursor will
3585 be visible. If the image doesn't have a mask, make
3586 a block cursor visible by drawing a rectangle around
3587 the image. I believe it's looking better if we do
3588 nothing here for mouse-face. */
3589 if (s
->hl
== DRAW_CURSOR
)
3591 int r
= s
->img
->relief
;
3593 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3594 s
->slice
.width
+ r
*2 - 1,
3595 s
->slice
.height
+ r
*2 - 1);
3600 /* Draw a rectangle if image could not be loaded. */
3601 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3602 s
->slice
.width
- 1, s
->slice
.height
- 1);
3606 /* Draw a relief around the image glyph string S. */
3609 x_draw_image_relief (s
)
3610 struct glyph_string
*s
;
3612 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3615 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3617 /* If first glyph of S has a left box line, start drawing it to the
3618 right of that line. */
3619 if (s
->face
->box
!= FACE_NO_BOX
3620 && s
->first_glyph
->left_box_line_p
3622 x
+= abs (s
->face
->box_line_width
);
3624 /* If there is a margin around the image, adjust x- and y-position
3626 if (s
->slice
.x
== 0)
3627 x
+= s
->img
->hmargin
;
3628 if (s
->slice
.y
== 0)
3629 y
+= s
->img
->vmargin
;
3631 if (s
->hl
== DRAW_IMAGE_SUNKEN
3632 || s
->hl
== DRAW_IMAGE_RAISED
)
3634 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3635 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3639 thick
= abs (s
->img
->relief
);
3640 raised_p
= s
->img
->relief
> 0;
3645 x1
= x
+ s
->slice
.width
+ thick
- 1;
3646 y1
= y
+ s
->slice
.height
+ thick
- 1;
3648 x_setup_relief_colors (s
);
3649 get_glyph_string_clip_rect (s
, &r
);
3650 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3652 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3654 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3659 /* Draw part of the background of glyph string S. X, Y, W, and H
3660 give the rectangle to draw. */
3663 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3664 struct glyph_string
*s
;
3667 #if 0 /* MAC_TODO: stipple */
3670 /* Fill background with a stipple pattern. */
3671 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3672 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3673 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3676 #endif /* MAC_TODO */
3677 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3681 /* Draw image glyph string S.
3684 s->x +-------------------------
3687 | +-------------------------
3690 | | +-------------------
3696 x_draw_image_glyph_string (s
)
3697 struct glyph_string
*s
;
3700 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3701 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3704 height
= s
->height
- 2 * box_line_vwidth
;
3707 /* Fill background with face under the image. Do it only if row is
3708 taller than image or if image has a clip mask to reduce
3710 s
->stippled_p
= s
->face
->stipple
!= 0;
3711 if (height
> s
->slice
.height
3715 || s
->img
->pixmap
== 0
3716 || s
->width
!= s
->background_width
)
3719 if (s
->first_glyph
->left_box_line_p
3721 x
+= box_line_hwidth
;
3724 if (s
->slice
.y
== 0)
3725 y
+= box_line_vwidth
;
3727 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3729 s
->background_filled_p
= 1;
3732 /* Draw the foreground. */
3733 x_draw_image_foreground (s
);
3735 /* If we must draw a relief around the image, do it. */
3737 || s
->hl
== DRAW_IMAGE_RAISED
3738 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3739 x_draw_image_relief (s
);
3743 /* Draw stretch glyph string S. */
3746 x_draw_stretch_glyph_string (s
)
3747 struct glyph_string
*s
;
3749 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3750 s
->stippled_p
= s
->face
->stipple
!= 0;
3752 if (s
->hl
== DRAW_CURSOR
3753 && !x_stretch_cursor_p
)
3755 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3756 as wide as the stretch glyph. */
3757 int width
, background_width
= s
->background_width
;
3758 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3762 background_width
-= left_x
- x
;
3765 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3768 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3770 /* Clear rest using the GC of the original non-cursor face. */
3771 if (width
< background_width
)
3774 int w
= background_width
- width
, h
= s
->height
;
3779 if (s
->row
->mouse_face_p
3780 && cursor_in_mouse_face_p (s
->w
))
3782 x_set_mouse_face_gc (s
);
3788 get_glyph_string_clip_rect (s
, &r
);
3789 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3791 #if 0 /* MAC_TODO: stipple */
3792 if (s
->face
->stipple
)
3794 /* Fill background with a stipple pattern. */
3795 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3796 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3797 XSetFillStyle (s
->display
, gc
, FillSolid
);
3800 #endif /* MAC_TODO */
3801 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3804 else if (!s
->background_filled_p
)
3806 int background_width
= s
->background_width
;
3807 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3809 /* Don't draw into left margin, fringe or scrollbar area
3810 except for header line and mode line. */
3811 if (x
< left_x
&& !s
->row
->mode_line_p
)
3813 background_width
-= left_x
- x
;
3816 if (background_width
> 0)
3817 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3820 s
->background_filled_p
= 1;
3824 /* Draw glyph string S. */
3827 x_draw_glyph_string (s
)
3828 struct glyph_string
*s
;
3830 int relief_drawn_p
= 0;
3832 /* If S draws into the background of its successor that does not
3833 draw a cursor, draw the background of the successor first so that
3834 S can draw into it. This makes S->next use XDrawString instead
3835 of XDrawImageString. */
3836 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3837 && s
->next
->hl
!= DRAW_CURSOR
)
3839 xassert (s
->next
->img
== NULL
);
3840 x_set_glyph_string_gc (s
->next
);
3841 x_set_glyph_string_clipping (s
->next
);
3842 x_draw_glyph_string_background (s
->next
, 1);
3845 /* Set up S->gc, set clipping and draw S. */
3846 x_set_glyph_string_gc (s
);
3848 /* Draw relief (if any) in advance for char/composition so that the
3849 glyph string can be drawn over it. */
3850 if (!s
->for_overlaps
3851 && s
->face
->box
!= FACE_NO_BOX
3852 && (s
->first_glyph
->type
== CHAR_GLYPH
3853 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3856 x_set_glyph_string_clipping (s
);
3857 x_draw_glyph_string_background (s
, 1);
3858 x_draw_glyph_string_box (s
);
3859 x_set_glyph_string_clipping (s
);
3863 x_set_glyph_string_clipping (s
);
3865 switch (s
->first_glyph
->type
)
3868 x_draw_image_glyph_string (s
);
3872 x_draw_stretch_glyph_string (s
);
3876 if (s
->for_overlaps
)
3877 s
->background_filled_p
= 1;
3879 x_draw_glyph_string_background (s
, 0);
3880 x_draw_glyph_string_foreground (s
);
3883 case COMPOSITE_GLYPH
:
3884 if (s
->for_overlaps
|| s
->gidx
> 0)
3885 s
->background_filled_p
= 1;
3887 x_draw_glyph_string_background (s
, 1);
3888 x_draw_composite_glyph_string_foreground (s
);
3895 if (!s
->for_overlaps
)
3897 /* Draw underline. */
3898 if (s
->face
->underline_p
)
3900 unsigned long tem
, h
;
3904 /* Get the underline thickness. Default is 1 pixel. */
3905 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3909 y
= s
->y
+ s
->height
- h
;
3910 if (!x_underline_at_descent_line
)
3912 /* Get the underline position. This is the recommended
3913 vertical offset in pixels from the baseline to the top of
3914 the underline. This is a signed value according to the
3915 specs, and its default is
3917 ROUND ((maximum descent) / 2), with
3918 ROUND(x) = floor (x + 0.5) */
3921 if (x_use_underline_position_properties
3922 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3923 y
= s
->ybase
+ (long) tem
;
3927 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3930 if (s
->face
->underline_defaulted_p
)
3931 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3932 s
->background_width
, h
);
3936 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3937 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3938 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3939 s
->background_width
, h
);
3940 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3944 /* Draw overline. */
3945 if (s
->face
->overline_p
)
3947 unsigned long dy
= 0, h
= 1;
3949 if (s
->face
->overline_color_defaulted_p
)
3950 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3951 s
->background_width
, h
);
3955 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3956 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3957 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3958 s
->background_width
, h
);
3959 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3963 /* Draw strike-through. */
3964 if (s
->face
->strike_through_p
)
3966 unsigned long h
= 1;
3967 unsigned long dy
= (s
->height
- h
) / 2;
3969 if (s
->face
->strike_through_color_defaulted_p
)
3970 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3975 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3976 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3977 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3979 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3983 /* Draw relief if not yet drawn. */
3984 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3985 x_draw_glyph_string_box (s
);
3988 /* Reset clipping. */
3989 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3992 /* Shift display to make room for inserted glyphs. */
3995 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3997 int x
, y
, width
, height
, shift_by
;
3999 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4000 x
, y
, width
, height
,
4004 /* Delete N glyphs at the nominal cursor position. Not implemented
4015 /* Clear entire frame. If updating_frame is non-null, clear that
4016 frame. Otherwise clear the selected frame. */
4026 f
= SELECTED_FRAME ();
4028 /* Clearing the frame will erase any cursor, so mark them all as no
4030 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4031 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4032 output_cursor
.x
= -1;
4034 /* We don't set the output cursor here because there will always
4035 follow an explicit cursor_to. */
4037 mac_clear_window (f
);
4039 /* We have to clear the scroll bars, too. If we have changed
4040 colors or something like that, then they should be notified. */
4041 x_scroll_bar_clear (f
);
4043 XFlush (FRAME_MAC_DISPLAY (f
));
4049 /* Invert the middle quarter of the frame for .15 sec. */
4051 /* We use the select system call to do the waiting, so we have to make
4052 sure it's available. If it isn't, we just won't do visual bells. */
4054 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4057 /* Subtract the `struct timeval' values X and Y, storing the result in
4058 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4061 timeval_subtract (result
, x
, y
)
4062 struct timeval
*result
, x
, y
;
4064 /* Perform the carry for the later subtraction by updating y. This
4065 is safer because on some systems the tv_sec member is unsigned. */
4066 if (x
.tv_usec
< y
.tv_usec
)
4068 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4069 y
.tv_usec
-= 1000000 * nsec
;
4073 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4075 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4076 y
.tv_usec
+= 1000000 * nsec
;
4080 /* Compute the time remaining to wait. tv_usec is certainly
4082 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4083 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4085 /* Return indication of whether the result should be considered
4087 return x
.tv_sec
< y
.tv_sec
;
4094 /* Get the height not including a menu bar widget. */
4095 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4096 /* Height of each line to flash. */
4097 int flash_height
= FRAME_LINE_HEIGHT (f
);
4098 /* These will be the left and right margins of the rectangles. */
4099 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4100 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4104 /* Don't flash the area between a scroll bar and the frame
4105 edge it is next to. */
4106 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4108 case vertical_scroll_bar_left
:
4109 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4112 case vertical_scroll_bar_right
:
4113 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4120 width
= flash_right
- flash_left
;
4124 /* If window is tall, flash top and bottom line. */
4125 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4127 mac_invert_rectangle (f
, flash_left
,
4128 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4129 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4130 width
, flash_height
);
4131 mac_invert_rectangle (f
, flash_left
,
4132 (height
- flash_height
4133 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4134 width
, flash_height
);
4137 /* If it is short, flash it all. */
4138 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4139 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4144 struct timeval wakeup
;
4146 EMACS_GET_TIME (wakeup
);
4148 /* Compute time to wait until, propagating carry from usecs. */
4149 wakeup
.tv_usec
+= 150000;
4150 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4151 wakeup
.tv_usec
%= 1000000;
4153 /* Keep waiting until past the time wakeup or any input gets
4155 while (! detect_input_pending ())
4157 struct timeval current
;
4158 struct timeval timeout
;
4160 EMACS_GET_TIME (current
);
4162 /* Break if result would be negative. */
4163 if (timeval_subtract (¤t
, wakeup
, current
))
4166 /* How long `select' should wait. */
4168 timeout
.tv_usec
= 10000;
4170 /* Try to wait that long--but we might wake up sooner. */
4171 select (0, NULL
, NULL
, NULL
, &timeout
);
4175 /* If window is tall, flash top and bottom line. */
4176 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4178 mac_invert_rectangle (f
, flash_left
,
4179 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4180 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4181 width
, flash_height
);
4182 mac_invert_rectangle (f
, flash_left
,
4183 (height
- flash_height
4184 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4185 width
, flash_height
);
4188 /* If it is short, flash it all. */
4189 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4190 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4197 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4200 /* Make audible bell. */
4205 struct frame
*f
= SELECTED_FRAME ();
4207 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4215 XFlush (FRAME_MAC_DISPLAY (f
));
4221 /* Specify how many text lines, from the top of the window,
4222 should be affected by insert-lines and delete-lines operations.
4223 This, and those operations, are used only within an update
4224 that is bounded by calls to x_update_begin and x_update_end. */
4227 XTset_terminal_window (n
)
4230 /* This function intentionally left blank. */
4235 /***********************************************************************
4237 ***********************************************************************/
4239 /* Perform an insert-lines or delete-lines operation, inserting N
4240 lines or deleting -N lines at vertical position VPOS. */
4243 x_ins_del_lines (vpos
, n
)
4250 /* Scroll part of the display as described by RUN. */
4253 x_scroll_run (w
, run
)
4257 struct frame
*f
= XFRAME (w
->frame
);
4258 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4260 /* Get frame-relative bounding box of the text display area of W,
4261 without mode lines. Include in this box the left and right
4263 window_box (w
, -1, &x
, &y
, &width
, &height
);
4265 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4266 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4267 bottom_y
= y
+ height
;
4271 /* Scrolling up. Make sure we don't copy part of the mode
4272 line at the bottom. */
4273 if (from_y
+ run
->height
> bottom_y
)
4274 height
= bottom_y
- from_y
;
4276 height
= run
->height
;
4280 /* Scolling down. Make sure we don't copy over the mode line.
4282 if (to_y
+ run
->height
> bottom_y
)
4283 height
= bottom_y
- to_y
;
4285 height
= run
->height
;
4290 /* Cursor off. Will be switched on again in x_update_window_end. */
4294 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4304 /***********************************************************************
4306 ***********************************************************************/
4314 ControlRef root_control
;
4317 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4319 ActivateControl (root_control
);
4321 x_update_cursor (f
, 1);
4325 frame_unhighlight (f
)
4329 ControlRef root_control
;
4332 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4334 DeactivateControl (root_control
);
4336 x_update_cursor (f
, 1);
4339 /* The focus has changed. Update the frames as necessary to reflect
4340 the new situation. Note that we can't change the selected frame
4341 here, because the Lisp code we are interrupting might become confused.
4342 Each event gets marked with the frame in which it occurred, so the
4343 Lisp code can tell when the switch took place by examining the events. */
4346 x_new_focus_frame (dpyinfo
, frame
)
4347 struct x_display_info
*dpyinfo
;
4348 struct frame
*frame
;
4350 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4352 if (frame
!= dpyinfo
->x_focus_frame
)
4354 /* Set this before calling other routines, so that they see
4355 the correct value of x_focus_frame. */
4356 dpyinfo
->x_focus_frame
= frame
;
4358 if (old_focus
&& old_focus
->auto_lower
)
4359 x_lower_frame (old_focus
);
4362 selected_frame
= frame
;
4363 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4365 Fselect_window (selected_frame
->selected_window
, Qnil
);
4366 choose_minibuf_frame ();
4369 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4370 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4372 pending_autoraise_frame
= 0;
4374 #if USE_MAC_FONT_PANEL
4376 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4380 x_frame_rehighlight (dpyinfo
);
4383 /* Handle FocusIn and FocusOut state changes for FRAME.
4384 If FRAME has focus and there exists more than one frame, puts
4385 a FOCUS_IN_EVENT into *BUFP. */
4388 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4390 struct mac_display_info
*dpyinfo
;
4391 struct frame
*frame
;
4392 struct input_event
*bufp
;
4394 if (type
== activeFlag
)
4396 if (dpyinfo
->x_focus_event_frame
!= frame
)
4398 x_new_focus_frame (dpyinfo
, frame
);
4399 dpyinfo
->x_focus_event_frame
= frame
;
4401 /* Don't stop displaying the initial startup message
4402 for a switch-frame event we don't need. */
4403 if (GC_NILP (Vterminal_frame
)
4404 && GC_CONSP (Vframe_list
)
4405 && !GC_NILP (XCDR (Vframe_list
)))
4407 bufp
->kind
= FOCUS_IN_EVENT
;
4408 XSETFRAME (bufp
->frame_or_window
, frame
);
4414 if (dpyinfo
->x_focus_event_frame
== frame
)
4416 dpyinfo
->x_focus_event_frame
= 0;
4417 x_new_focus_frame (dpyinfo
, 0);
4422 /* The focus may have changed. Figure out if it is a real focus change,
4423 by checking both FocusIn/Out and Enter/LeaveNotify events.
4425 Returns FOCUS_IN_EVENT event in *BUFP. */
4428 x_detect_focus_change (dpyinfo
, event
, bufp
)
4429 struct mac_display_info
*dpyinfo
;
4430 const EventRecord
*event
;
4431 struct input_event
*bufp
;
4433 struct frame
*frame
;
4435 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4439 /* On Mac, this is only called from focus events, so no switch needed. */
4440 mac_focus_changed ((event
->modifiers
& activeFlag
),
4441 dpyinfo
, frame
, bufp
);
4445 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4448 x_mouse_leave (dpyinfo
)
4449 struct x_display_info
*dpyinfo
;
4451 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4454 /* The focus has changed, or we have redirected a frame's focus to
4455 another frame (this happens when a frame uses a surrogate
4456 mini-buffer frame). Shift the highlight as appropriate.
4458 The FRAME argument doesn't necessarily have anything to do with which
4459 frame is being highlighted or un-highlighted; we only use it to find
4460 the appropriate X display info. */
4463 XTframe_rehighlight (frame
)
4464 struct frame
*frame
;
4466 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4470 x_frame_rehighlight (dpyinfo
)
4471 struct x_display_info
*dpyinfo
;
4473 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4475 if (dpyinfo
->x_focus_frame
)
4477 dpyinfo
->x_highlight_frame
4478 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4479 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4480 : dpyinfo
->x_focus_frame
);
4481 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4483 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4484 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4488 dpyinfo
->x_highlight_frame
= 0;
4490 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4493 frame_unhighlight (old_highlight
);
4494 if (dpyinfo
->x_highlight_frame
)
4495 frame_highlight (dpyinfo
->x_highlight_frame
);
4501 /* Convert a keysym to its name. */
4504 x_get_keysym_name (keysym
)
4511 value
= XKeysymToString (keysym
);
4522 /* Function to report a mouse movement to the mainstream Emacs code.
4523 The input handler calls this.
4525 We have received a mouse movement event, which is given in *event.
4526 If the mouse is over a different glyph than it was last time, tell
4527 the mainstream emacs code by setting mouse_moved. If not, ask for
4528 another motion event, so we can check again the next time it moves. */
4530 static Point last_mouse_motion_position
;
4531 static Lisp_Object last_mouse_motion_frame
;
4534 note_mouse_movement (frame
, pos
)
4538 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4539 #if TARGET_API_MAC_CARBON
4543 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4544 last_mouse_motion_position
= *pos
;
4545 XSETFRAME (last_mouse_motion_frame
, frame
);
4547 if (frame
== dpyinfo
->mouse_face_mouse_frame
4548 #if TARGET_API_MAC_CARBON
4549 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4551 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4555 /* This case corresponds to LeaveNotify in X11. If we move
4556 outside the frame, then we're certainly no longer on any text
4558 clear_mouse_face (dpyinfo
);
4559 dpyinfo
->mouse_face_mouse_frame
= 0;
4560 if (!dpyinfo
->grabbed
)
4561 rif
->define_frame_cursor (frame
,
4562 frame
->output_data
.mac
->nontext_cursor
);
4565 /* Has the mouse moved off the glyph it was on at the last sighting? */
4566 if (frame
!= last_mouse_glyph_frame
4567 || !PtInRect (*pos
, &last_mouse_glyph
))
4569 frame
->mouse_moved
= 1;
4570 last_mouse_scroll_bar
= Qnil
;
4571 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4572 /* Remember which glyph we're now on. */
4573 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4574 last_mouse_glyph_frame
= frame
;
4582 /************************************************************************
4584 ************************************************************************/
4586 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4589 redo_mouse_highlight ()
4591 if (!NILP (last_mouse_motion_frame
)
4592 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4593 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4594 last_mouse_motion_position
.h
,
4595 last_mouse_motion_position
.v
);
4599 static struct frame
*
4600 mac_focus_frame (dpyinfo
)
4601 struct mac_display_info
*dpyinfo
;
4603 if (dpyinfo
->x_focus_frame
)
4604 return dpyinfo
->x_focus_frame
;
4606 /* Mac version may get events, such as a menu bar click, even when
4607 all the frames are invisible. In this case, we regard the
4608 event came to the selected frame. */
4609 return SELECTED_FRAME ();
4613 /* Return the current position of the mouse.
4614 *FP should be a frame which indicates which display to ask about.
4616 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4617 and *PART to the frame, window, and scroll bar part that the mouse
4618 is over. Set *X and *Y to the portion and whole of the mouse's
4619 position on the scroll bar.
4621 If the mouse movement started elsewhere, set *FP to the frame the
4622 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4625 Set *TIME to the server time-stamp for the time at which the mouse
4626 was at this position.
4628 Don't store anything if we don't have a valid set of values to report.
4630 This clears the mouse_moved flag, so we can wait for the next mouse
4634 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4637 Lisp_Object
*bar_window
;
4638 enum scroll_bar_part
*part
;
4640 unsigned long *time
;
4646 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4647 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4650 Lisp_Object frame
, tail
;
4652 /* Clear the mouse-moved flag for every frame on this display. */
4653 FOR_EACH_FRAME (tail
, frame
)
4654 XFRAME (frame
)->mouse_moved
= 0;
4656 last_mouse_scroll_bar
= Qnil
;
4658 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4659 && FRAME_LIVE_P (last_mouse_frame
))
4660 f1
= last_mouse_frame
;
4662 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4666 /* Ok, we found a frame. Store all the values.
4667 last_mouse_glyph is a rectangle used to reduce the
4668 generation of mouse events. To not miss any motion
4669 events, we must divide the frame into rectangles of the
4670 size of the smallest character that could be displayed
4671 on it, i.e. into the same rectangles that matrices on
4672 the frame are divided into. */
4675 #if TARGET_API_MAC_CARBON
4676 GetGlobalMouse (&mouse_pos
);
4677 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4678 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4680 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4681 GetMouse (&mouse_pos
);
4683 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4685 last_mouse_glyph_frame
= f1
;
4690 XSETINT (*x
, mouse_pos
.h
);
4691 XSETINT (*y
, mouse_pos
.v
);
4692 *time
= last_mouse_movement_time
;
4700 /************************************************************************
4702 ************************************************************************/
4704 #ifdef USE_TOOLKIT_SCROLL_BARS
4706 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4707 static OSStatus install_scroll_bar_timer
P_ ((void));
4708 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4709 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4710 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4711 struct input_event
*));
4712 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4714 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4715 ControlPartCode
, Point
,
4716 struct input_event
*));
4717 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4718 struct input_event
*));
4719 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4720 Point
, struct input_event
*));
4721 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4724 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4726 static int last_scroll_bar_part
;
4728 static EventLoopTimerRef scroll_bar_timer
;
4730 static int scroll_bar_timer_event_posted_p
;
4732 #define SCROLL_BAR_FIRST_DELAY 0.5
4733 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4736 scroll_bar_timer_callback (timer
, data
)
4737 EventLoopTimerRef timer
;
4742 err
= mac_post_mouse_moved_event ();
4744 scroll_bar_timer_event_posted_p
= 1;
4748 install_scroll_bar_timer ()
4750 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4752 if (scroll_bar_timer_callbackUPP
== NULL
)
4753 scroll_bar_timer_callbackUPP
=
4754 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4756 if (scroll_bar_timer
== NULL
)
4757 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4758 kEventDurationForever as delays. */
4760 InstallEventLoopTimer (GetCurrentEventLoop (),
4761 kEventDurationForever
, kEventDurationForever
,
4762 scroll_bar_timer_callbackUPP
, NULL
,
4767 set_scroll_bar_timer (delay
)
4768 EventTimerInterval delay
;
4770 if (scroll_bar_timer
== NULL
)
4771 install_scroll_bar_timer ();
4773 scroll_bar_timer_event_posted_p
= 0;
4775 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4779 control_part_code_to_scroll_bar_part (part_code
)
4780 ControlPartCode part_code
;
4784 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4785 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4786 case kControlPageUpPart
: return scroll_bar_above_handle
;
4787 case kControlPageDownPart
: return scroll_bar_below_handle
;
4788 case kControlIndicatorPart
: return scroll_bar_handle
;
4795 construct_scroll_bar_click (bar
, part
, bufp
)
4796 struct scroll_bar
*bar
;
4798 struct input_event
*bufp
;
4800 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4801 bufp
->frame_or_window
= bar
->window
;
4805 XSETINT (bufp
->x
, 0);
4806 XSETINT (bufp
->y
, 0);
4807 bufp
->modifiers
= 0;
4811 get_control_part_bounds (ch
, part_code
, rect
)
4813 ControlPartCode part_code
;
4816 RgnHandle region
= NewRgn ();
4819 err
= GetControlRegion (ch
, part_code
, region
);
4821 GetRegionBounds (region
, rect
);
4822 DisposeRgn (region
);
4828 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4829 struct scroll_bar
*bar
;
4830 ControlPartCode part_code
;
4832 struct input_event
*bufp
;
4834 int part
= control_part_code_to_scroll_bar_part (part_code
);
4839 if (part
!= scroll_bar_handle
)
4841 construct_scroll_bar_click (bar
, part
, bufp
);
4842 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4843 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4844 bar
->dragging
= Qnil
;
4850 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4851 kControlIndicatorPart
, &r
);
4852 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4855 last_scroll_bar_part
= part
;
4856 tracked_scroll_bar
= bar
;
4860 x_scroll_bar_handle_release (bar
, bufp
)
4861 struct scroll_bar
*bar
;
4862 struct input_event
*bufp
;
4864 if (last_scroll_bar_part
!= scroll_bar_handle
4865 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4866 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4868 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4869 set_scroll_bar_timer (kEventDurationForever
);
4871 last_scroll_bar_part
= -1;
4872 bar
->dragging
= Qnil
;
4873 tracked_scroll_bar
= NULL
;
4877 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4879 struct scroll_bar
*bar
;
4881 struct input_event
*bufp
;
4883 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4885 if (last_scroll_bar_part
== scroll_bar_handle
)
4890 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4891 kControlIndicatorPart
, &r
);
4893 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4894 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4896 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4897 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4901 if (top
> top_range
)
4904 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4905 XSETINT (bufp
->x
, top
);
4906 XSETINT (bufp
->y
, top_range
);
4910 ControlPartCode part_code
;
4911 int unhilite_p
= 0, part
;
4913 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4917 part
= control_part_code_to_scroll_bar_part (part_code
);
4919 switch (last_scroll_bar_part
)
4921 case scroll_bar_above_handle
:
4922 case scroll_bar_below_handle
:
4923 if (part
!= scroll_bar_above_handle
4924 && part
!= scroll_bar_below_handle
)
4928 case scroll_bar_up_arrow
:
4929 case scroll_bar_down_arrow
:
4930 if (part
!= scroll_bar_up_arrow
4931 && part
!= scroll_bar_down_arrow
)
4938 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4939 else if (part
!= last_scroll_bar_part
4940 || scroll_bar_timer_event_posted_p
)
4942 construct_scroll_bar_click (bar
, part
, bufp
);
4943 last_scroll_bar_part
= part
;
4944 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4945 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4950 /* Set the thumb size and position of scroll bar BAR. We are currently
4951 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4954 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4955 struct scroll_bar
*bar
;
4956 int portion
, position
, whole
;
4958 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4959 int value
, viewsize
, maximum
;
4961 if (XINT (bar
->track_height
) == 0)
4964 if (whole
<= portion
)
4965 value
= 0, viewsize
= 1, maximum
= 0;
4970 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4971 scale
= (float) maximum
/ (whole
- portion
);
4972 value
= position
* scale
+ 0.5f
;
4973 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
4978 if (GetControlViewSize (ch
) != viewsize
4979 || GetControl32BitValue (ch
) != value
4980 || GetControl32BitMaximum (ch
) != maximum
)
4982 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4983 SetControlVisibility (ch
, false, false);
4985 SetControl32BitMaximum (ch
, maximum
);
4986 SetControl32BitValue (ch
, value
);
4987 SetControlViewSize (ch
, viewsize
);
4989 SetControlVisibility (ch
, true, true);
4995 #endif /* USE_TOOLKIT_SCROLL_BARS */
4999 /************************************************************************
5000 Scroll bars, general
5001 ************************************************************************/
5003 /* Create a scroll bar and return the scroll bar vector for it. W is
5004 the Emacs window on which to create the scroll bar. TOP, LEFT,
5005 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5008 static struct scroll_bar
*
5009 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5011 int top
, left
, width
, height
, disp_top
, disp_height
;
5013 struct frame
*f
= XFRAME (w
->frame
);
5014 struct scroll_bar
*bar
5015 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5023 r
.right
= left
+ width
;
5024 r
.bottom
= disp_top
+ disp_height
;
5027 mac_prepare_for_quickdraw (f
);
5029 #if TARGET_API_MAC_CARBON
5030 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5031 #ifdef USE_TOOLKIT_SCROLL_BARS
5034 width
< disp_height
,
5036 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5038 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5039 0, 0, 0, scrollBarProc
, (long) bar
);
5041 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5043 XSETWINDOW (bar
->window
, w
);
5044 XSETINT (bar
->top
, top
);
5045 XSETINT (bar
->left
, left
);
5046 XSETINT (bar
->width
, width
);
5047 XSETINT (bar
->height
, height
);
5048 XSETINT (bar
->start
, 0);
5049 XSETINT (bar
->end
, 0);
5050 bar
->dragging
= Qnil
;
5052 bar
->fringe_extended_p
= Qnil
;
5054 #ifdef USE_TOOLKIT_SCROLL_BARS
5055 bar
->track_top
= Qnil
;
5056 bar
->track_height
= Qnil
;
5057 bar
->min_handle
= Qnil
;
5060 /* Add bar to its frame's list of scroll bars. */
5061 bar
->next
= FRAME_SCROLL_BARS (f
);
5063 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5064 if (!NILP (bar
->next
))
5065 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5072 /* Draw BAR's handle in the proper position.
5074 If the handle is already drawn from START to END, don't bother
5075 redrawing it, unless REBUILD is non-zero; in that case, always
5076 redraw it. (REBUILD is handy for drawing the handle after expose
5079 Normally, we want to constrain the start and end of the handle to
5080 fit inside its rectangle, but if the user is dragging the scroll
5081 bar handle, we want to let them drag it down all the way, so that
5082 the bar's top is as far down as it goes; otherwise, there's no way
5083 to move to the very end of the buffer. */
5085 #ifndef USE_TOOLKIT_SCROLL_BARS
5088 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5089 struct scroll_bar
*bar
;
5093 int dragging
= ! NILP (bar
->dragging
);
5094 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5095 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5096 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5097 int length
= end
- start
;
5099 /* If the display is already accurate, do nothing. */
5101 && start
== XINT (bar
->start
)
5102 && end
== XINT (bar
->end
))
5107 /* Make sure the values are reasonable, and try to preserve the
5108 distance between start and end. */
5111 else if (start
> top_range
)
5113 end
= start
+ length
;
5117 else if (end
> top_range
&& ! dragging
)
5120 /* Store the adjusted setting in the scroll bar. */
5121 XSETINT (bar
->start
, start
);
5122 XSETINT (bar
->end
, end
);
5124 /* Clip the end position, just for display. */
5125 if (end
> top_range
)
5128 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5129 top positions, to make sure the handle is always at least that
5130 many pixels tall. */
5131 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5133 SetControlMinimum (ch
, 0);
5134 /* Don't inadvertently activate deactivated scroll bars */
5135 if (GetControlMaximum (ch
) != -1)
5136 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5138 SetControlValue (ch
, start
);
5139 #if TARGET_API_MAC_CARBON
5140 SetControlViewSize (ch
, end
- start
);
5146 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5148 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5152 x_scroll_bar_remove (bar
)
5153 struct scroll_bar
*bar
;
5155 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5160 mac_prepare_for_quickdraw (f
);
5162 /* Destroy the Mac scroll bar control */
5163 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5165 /* Disassociate this scroll bar from its window. */
5166 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5172 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5173 that we are displaying PORTION characters out of a total of WHOLE
5174 characters, starting at POSITION. If WINDOW has no scroll bar,
5178 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5180 int portion
, whole
, position
;
5182 struct frame
*f
= XFRAME (w
->frame
);
5183 struct scroll_bar
*bar
;
5184 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5185 int window_y
, window_height
;
5187 int fringe_extended_p
;
5190 /* Get window dimensions. */
5191 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5193 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5194 height
= window_height
;
5196 /* Compute the left edge of the scroll bar area. */
5197 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5199 /* Compute the width of the scroll bar which might be less than
5200 the width of the area reserved for the scroll bar. */
5201 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5202 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5206 /* Compute the left edge of the scroll bar. */
5207 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5208 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5210 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5212 /* Adjustments according to Inside Macintosh to make it look nice */
5214 disp_height
= height
;
5221 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5227 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5232 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5233 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5234 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5235 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5236 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5238 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5239 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5240 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5241 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5244 /* Does the scroll bar exist yet? */
5245 if (NILP (w
->vertical_scroll_bar
))
5249 if (fringe_extended_p
)
5250 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5253 mac_clear_area (f
, left
, top
, width
, height
);
5255 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5257 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5261 /* It may just need to be moved and resized. */
5264 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5265 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5269 /* If already correctly positioned, do nothing. */
5270 if (!(XINT (bar
->left
) == sb_left
5271 && XINT (bar
->top
) == top
5272 && XINT (bar
->width
) == sb_width
5273 && XINT (bar
->height
) == height
5275 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5279 /* Since toolkit scroll bars are smaller than the space reserved
5280 for them on the frame, we have to clear "under" them. */
5282 if (fringe_extended_p
)
5283 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5286 mac_clear_area (f
, left
, top
, width
, height
);
5289 mac_prepare_for_quickdraw (f
);
5292 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5293 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5295 #ifndef USE_TOOLKIT_SCROLL_BARS
5296 if (sb_width
< disp_height
)
5300 /* Remember new settings. */
5301 XSETINT (bar
->left
, sb_left
);
5302 XSETINT (bar
->top
, top
);
5303 XSETINT (bar
->width
, sb_width
);
5304 XSETINT (bar
->height
, height
);
5305 #ifdef USE_TOOLKIT_SCROLL_BARS
5306 bar
->track_top
= Qnil
;
5307 bar
->track_height
= Qnil
;
5308 bar
->min_handle
= Qnil
;
5316 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5319 #ifdef USE_TOOLKIT_SCROLL_BARS
5320 if (NILP (bar
->track_top
))
5322 if (sb_width
>= disp_height
5324 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5328 XSETINT (bar
->track_top
, 0);
5329 XSETINT (bar
->track_height
, 0);
5330 XSETINT (bar
->min_handle
, 0);
5334 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5339 SetControl32BitMinimum (ch
, 0);
5340 SetControl32BitMaximum (ch
, 1 << 30);
5341 SetControlViewSize (ch
, 1);
5343 /* Move the scroll bar thumb to the top. */
5344 SetControl32BitValue (ch
, 0);
5345 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5347 /* Move the scroll bar thumb to the bottom. */
5348 SetControl32BitValue (ch
, 1 << 30);
5349 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5351 UnionRect (&r0
, &r1
, &r0
);
5352 XSETINT (bar
->track_top
, r0
.top
);
5353 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5354 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5356 /* Don't show the scroll bar if its height is not enough to
5357 display the scroll bar thumb. */
5358 if (r0
.bottom
- r0
.top
> 0)
5365 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5366 #else /* not USE_TOOLKIT_SCROLL_BARS */
5367 /* Set the scroll bar's current state, unless we're currently being
5369 if (NILP (bar
->dragging
))
5371 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5374 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5377 int start
= ((double) position
* top_range
) / whole
;
5378 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5379 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5382 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5386 /* The following three hooks are used when we're doing a thorough
5387 redisplay of the frame. We don't explicitly know which scroll bars
5388 are going to be deleted, because keeping track of when windows go
5389 away is a real pain - "Can you say set-window-configuration, boys
5390 and girls?" Instead, we just assert at the beginning of redisplay
5391 that *all* scroll bars are to be removed, and then save a scroll bar
5392 from the fiery pit when we actually redisplay its window. */
5394 /* Arrange for all scroll bars on FRAME to be removed at the next call
5395 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5396 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5399 XTcondemn_scroll_bars (frame
)
5402 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5403 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5406 bar
= FRAME_SCROLL_BARS (frame
);
5407 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5408 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5409 XSCROLL_BAR (bar
)->prev
= Qnil
;
5410 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5411 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5412 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5417 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5418 Note that WINDOW isn't necessarily condemned at all. */
5421 XTredeem_scroll_bar (window
)
5422 struct window
*window
;
5424 struct scroll_bar
*bar
;
5427 /* We can't redeem this window's scroll bar if it doesn't have one. */
5428 if (NILP (window
->vertical_scroll_bar
))
5431 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5433 /* Unlink it from the condemned list. */
5434 f
= XFRAME (WINDOW_FRAME (window
));
5435 if (NILP (bar
->prev
))
5437 /* If the prev pointer is nil, it must be the first in one of
5439 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5440 /* It's not condemned. Everything's fine. */
5442 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5443 window
->vertical_scroll_bar
))
5444 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5446 /* If its prev pointer is nil, it must be at the front of
5447 one or the other! */
5451 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5453 if (! NILP (bar
->next
))
5454 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5456 bar
->next
= FRAME_SCROLL_BARS (f
);
5458 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5459 if (! NILP (bar
->next
))
5460 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5463 /* Remove all scroll bars on FRAME that haven't been saved since the
5464 last call to `*condemn_scroll_bars_hook'. */
5467 XTjudge_scroll_bars (f
)
5470 Lisp_Object bar
, next
;
5472 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5474 /* Clear out the condemned list now so we won't try to process any
5475 more events on the hapless scroll bars. */
5476 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5478 for (; ! NILP (bar
); bar
= next
)
5480 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5482 x_scroll_bar_remove (b
);
5485 b
->next
= b
->prev
= Qnil
;
5488 /* Now there should be no references to the condemned scroll bars,
5489 and they should get garbage-collected. */
5493 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5494 is set to something other than NO_EVENT, it is enqueued.
5496 This may be called from a signal handler, so we have to ignore GC
5500 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5501 struct scroll_bar
*bar
;
5502 ControlPartCode part_code
;
5503 const EventRecord
*er
;
5504 struct input_event
*bufp
;
5506 int win_y
, top_range
;
5508 if (! GC_WINDOWP (bar
->window
))
5511 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5512 bufp
->frame_or_window
= bar
->window
;
5515 bar
->dragging
= Qnil
;
5519 case kControlUpButtonPart
:
5520 bufp
->part
= scroll_bar_up_arrow
;
5522 case kControlDownButtonPart
:
5523 bufp
->part
= scroll_bar_down_arrow
;
5525 case kControlPageUpPart
:
5526 bufp
->part
= scroll_bar_above_handle
;
5528 case kControlPageDownPart
:
5529 bufp
->part
= scroll_bar_below_handle
;
5531 #if TARGET_API_MAC_CARBON
5534 case kControlIndicatorPart
:
5536 if (er
->what
== mouseDown
)
5537 bar
->dragging
= make_number (0);
5538 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5539 bufp
->part
= scroll_bar_handle
;
5543 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5544 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5546 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5550 if (! NILP (bar
->dragging
))
5551 win_y
-= XINT (bar
->dragging
);
5555 if (win_y
> top_range
)
5558 XSETINT (bufp
->x
, win_y
);
5559 XSETINT (bufp
->y
, top_range
);
5562 #ifndef USE_TOOLKIT_SCROLL_BARS
5564 /* Handle some mouse motion while someone is dragging the scroll bar.
5566 This may be called from a signal handler, so we have to ignore GC
5570 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5571 struct scroll_bar
*bar
;
5575 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5577 last_mouse_movement_time
= t
;
5580 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5582 /* If we're dragging the bar, display it. */
5583 if (! GC_NILP (bar
->dragging
))
5585 /* Where should the handle be now? */
5586 int new_start
= y_pos
- 24;
5588 if (new_start
!= XINT (bar
->start
))
5590 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5592 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5597 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5599 /* Return information to the user about the current position of the mouse
5600 on the scroll bar. */
5603 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5605 Lisp_Object
*bar_window
;
5606 enum scroll_bar_part
*part
;
5608 unsigned long *time
;
5610 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5611 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5612 #if TARGET_API_MAC_CARBON
5613 WindowRef wp
= GetControlOwner (ch
);
5615 WindowRef wp
= (*ch
)->contrlOwner
;
5618 struct frame
*f
= mac_window_to_frame (wp
);
5619 int win_y
, top_range
;
5621 #if TARGET_API_MAC_CARBON
5622 GetGlobalMouse (&mouse_pos
);
5623 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5624 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5626 SetPortWindowPort (wp
);
5627 GetMouse (&mouse_pos
);
5630 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5631 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5633 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5637 if (! NILP (bar
->dragging
))
5638 win_y
-= XINT (bar
->dragging
);
5642 if (win_y
> top_range
)
5646 *bar_window
= bar
->window
;
5648 if (! NILP (bar
->dragging
))
5649 *part
= scroll_bar_handle
;
5650 else if (win_y
< XINT (bar
->start
))
5651 *part
= scroll_bar_above_handle
;
5652 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5653 *part
= scroll_bar_handle
;
5655 *part
= scroll_bar_below_handle
;
5657 XSETINT (*x
, win_y
);
5658 XSETINT (*y
, top_range
);
5661 last_mouse_scroll_bar
= Qnil
;
5663 *time
= last_mouse_movement_time
;
5667 /* The screen has been cleared so we may have changed foreground or
5668 background colors, and the scroll bars may need to be redrawn.
5669 Clear out the scroll bars, and ask for expose events, so we can
5673 x_scroll_bar_clear (f
)
5676 XTcondemn_scroll_bars (f
);
5677 XTjudge_scroll_bars (f
);
5681 /***********************************************************************
5683 ***********************************************************************/
5686 /* In identifiers such as function/variable names, Emacs tool bar is
5687 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5689 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5690 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5692 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5693 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5694 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5695 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5696 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5697 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5698 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5700 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5701 static void mac_handle_origin_change
P_ ((struct frame
*));
5702 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5706 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5713 mac_get_window_bounds (f
, &inner
, &outer
);
5715 switch (win_gravity
)
5717 case NorthWestGravity
:
5719 case SouthWestGravity
:
5720 left
+= inner
.left
- outer
.left
;
5726 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5729 case NorthEastGravity
:
5731 case SouthEastGravity
:
5732 left
+= inner
.right
- outer
.right
;
5736 switch (win_gravity
)
5738 case NorthWestGravity
:
5740 case NorthEastGravity
:
5741 top
+= inner
.top
- outer
.top
;
5747 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5750 case SouthWestGravity
:
5752 case SouthEastGravity
:
5753 top
+= inner
.bottom
- outer
.bottom
;
5757 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5761 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5768 mac_get_window_bounds (f
, &inner
, &outer
);
5770 switch (win_gravity
)
5772 case NorthWestGravity
:
5774 case SouthWestGravity
:
5781 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5782 - (inner
.right
- inner
.left
)) / 2;
5785 case NorthEastGravity
:
5787 case SouthEastGravity
:
5788 *left
= outer
.right
- (inner
.right
- inner
.left
);
5792 switch (win_gravity
)
5794 case NorthWestGravity
:
5796 case NorthEastGravity
:
5803 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5804 - (inner
.bottom
- inner
.top
)) / 2;
5807 case SouthWestGravity
:
5809 case SouthEastGravity
:
5810 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5816 mac_handle_toolbar_event (next_handler
, event
, data
)
5817 EventHandlerCallRef next_handler
;
5821 OSStatus err
, result
= eventNotHandledErr
;
5823 switch (GetEventKind (event
))
5825 case kEventToolbarGetDefaultIdentifiers
:
5829 case kEventToolbarGetAllowedIdentifiers
:
5831 CFMutableArrayRef array
;
5833 GetEventParameter (event
, kEventParamMutableArray
,
5834 typeCFMutableArrayRef
, NULL
,
5835 sizeof (CFMutableArrayRef
), NULL
, &array
);
5836 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5841 case kEventToolbarCreateItemWithIdentifier
:
5843 CFStringRef identifier
;
5844 HIToolbarItemRef item
= NULL
;
5846 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
5847 typeCFStringRef
, NULL
,
5848 sizeof (CFStringRef
), NULL
, &identifier
);
5850 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
5851 == kCFCompareEqualTo
)
5852 HIToolbarItemCreate (identifier
,
5853 kHIToolbarItemAllowDuplicates
5854 | kHIToolbarItemCantBeRemoved
, &item
);
5858 SetEventParameter (event
, kEventParamToolbarItem
,
5859 typeHIToolbarItemRef
,
5860 sizeof (HIToolbarItemRef
), &item
);
5874 mac_image_spec_to_cg_image (f
, image
)
5878 if (!valid_image_p (image
))
5882 int img_id
= lookup_image (f
, image
);
5883 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
5885 prepare_image_for_display (f
, img
);
5887 return img
->data
.ptr_val
;
5891 /* Create a tool bar for frame F. */
5894 mac_create_frame_tool_bar (f
)
5898 HIToolbarRef toolbar
;
5900 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
5904 static const EventTypeSpec specs
[] =
5905 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
5906 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
5907 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
5909 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
5910 mac_handle_toolbar_event
,
5911 GetEventTypeCount (specs
), specs
,
5916 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
5919 static const EventTypeSpec specs
[] =
5920 {{kEventClassCommand
, kEventCommandProcess
}};
5922 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
5923 mac_handle_toolbar_command_event
,
5924 GetEventTypeCount (specs
),
5928 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
5931 CFRelease (toolbar
);
5936 /* Update the tool bar for frame F. Add new buttons and remove old. */
5939 update_frame_tool_bar (f
)
5942 HIToolbarRef toolbar
= NULL
;
5944 CFArrayRef old_items
= NULL
;
5946 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
5947 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5951 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5952 if (toolbar
== NULL
)
5954 mac_create_frame_tool_bar (f
);
5955 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5956 if (toolbar
== NULL
)
5958 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
5959 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
5962 HIToolbarCopyItems (toolbar
, &old_items
);
5963 if (old_items
== NULL
)
5966 old_count
= CFArrayGetCount (old_items
);
5968 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
5970 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5972 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
5973 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
5976 CGImageRef cg_image
;
5978 HIToolbarItemRef item
;
5980 /* If image is a vector, choose the image according to the
5982 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
5983 if (VECTORP (image
))
5987 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
5988 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
5991 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
5992 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
5994 xassert (ASIZE (image
) >= idx
);
5995 image
= AREF (image
, idx
);
6000 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6001 /* Ignore invalid image specifications. */
6002 if (cg_image
== NULL
)
6005 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6009 if (pos
< old_count
)
6011 CGImageRef old_cg_image
= NULL
;
6012 CFStringRef old_label
= NULL
;
6013 Boolean old_enabled_p
;
6015 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6017 HIToolbarItemCopyImage (item
, &old_cg_image
);
6018 if (cg_image
!= old_cg_image
)
6019 HIToolbarItemSetImage (item
, cg_image
);
6020 CGImageRelease (old_cg_image
);
6022 HIToolbarItemCopyLabel (item
, &old_label
);
6023 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6024 HIToolbarItemSetLabel (item
, label
);
6025 CFRelease (old_label
);
6027 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6028 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6029 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6034 HIToolbarCreateItemWithIdentifier (toolbar
,
6035 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6039 HIToolbarItemSetImage (item
, cg_image
);
6040 HIToolbarItemSetLabel (item
, label
);
6041 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6042 HIToolbarAppendItem (toolbar
, item
);
6050 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6055 CFRelease (old_items
);
6057 while (pos
< old_count
)
6058 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6060 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6061 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6062 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6063 toolbar visibility change. */
6064 mac_handle_origin_change (f
);
6065 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6067 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6068 /* If the title bar is completely outside the screen, adjust the
6070 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6071 kWindowConstrainMoveRegardlessOfFit
6072 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6073 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6080 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6081 doesn't deallocate the resources. */
6084 free_frame_tool_bar (f
)
6087 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6089 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6092 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6093 f
== mac_focus_frame (dpyinfo
));
6094 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6095 on toolbar visibility change. */
6096 mac_handle_origin_change (f
);
6102 mac_tool_bar_note_mouse_movement (f
, event
)
6107 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6109 HIViewRef item_view
;
6112 mouse_down_p
= (dpyinfo
->grabbed
6113 && f
== last_mouse_frame
6114 && FRAME_LIVE_P (f
));
6118 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6120 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6121 toolbar item view seems to have the same command ID with that of
6122 the toolbar item. */
6124 err
= GetControlCommandID (item_view
, &command_id
);
6125 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6127 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6129 if (i
< f
->n_tool_bar_items
)
6132 HIViewRef content_view
;
6134 err
= HIViewGetBounds (item_view
, &bounds
);
6136 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6137 kHIViewWindowContentID
, &content_view
);
6139 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6141 SetRect (&last_mouse_glyph
,
6142 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6143 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6145 help_echo_object
= help_echo_window
= Qnil
;
6147 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6148 if (NILP (help_echo_string
))
6149 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6155 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6156 EventHandlerCallRef next_handler
;
6160 OSStatus err
, result
= eventNotHandledErr
;
6161 struct frame
*f
= (struct frame
*) data
;
6164 err
= GetEventParameter (event
, kEventParamDirectObject
,
6165 typeHICommand
, NULL
,
6166 sizeof (HICommand
), NULL
, &command
);
6170 switch (GetEventKind (event
))
6172 case kEventCommandProcess
:
6173 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6174 result
= CallNextEventHandler (next_handler
, event
);
6177 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6179 if (i
< f
->n_tool_bar_items
6180 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6183 struct input_event buf
;
6187 XSETFRAME (frame
, f
);
6188 buf
.kind
= TOOL_BAR_EVENT
;
6189 buf
.frame_or_window
= frame
;
6191 kbd_buffer_store_event (&buf
);
6193 buf
.kind
= TOOL_BAR_EVENT
;
6194 buf
.frame_or_window
= frame
;
6195 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6196 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6197 kbd_buffer_store_event (&buf
);
6211 #endif /* USE_MAC_TOOLBAR */
6214 /***********************************************************************
6216 ***********************************************************************/
6218 /* Set clipping for output in glyph row ROW. W is the window in which
6219 we operate. GC is the graphics context to set clipping in.
6221 ROW may be a text row or, e.g., a mode line. Text rows must be
6222 clipped to the interior of the window dedicated to text display,
6223 mode lines must be clipped to the whole window. */
6226 x_clip_to_row (w
, row
, area
, gc
)
6228 struct glyph_row
*row
;
6232 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6234 int window_x
, window_y
, window_width
;
6236 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6238 clip_rect
.left
= window_x
;
6239 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6240 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6241 clip_rect
.right
= clip_rect
.left
+ window_width
;
6242 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6244 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6248 /* Draw a hollow box cursor on window W in glyph row ROW. */
6251 x_draw_hollow_cursor (w
, row
)
6253 struct glyph_row
*row
;
6255 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6256 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6257 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6260 struct glyph
*cursor_glyph
;
6263 /* Get the glyph the cursor is on. If we can't tell because
6264 the current matrix is invalid or such, give up. */
6265 cursor_glyph
= get_phys_cursor_glyph (w
);
6266 if (cursor_glyph
== NULL
)
6269 /* Compute frame-relative coordinates for phys cursor. */
6270 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6271 wd
= w
->phys_cursor_width
;
6273 /* The foreground of cursor_gc is typically the same as the normal
6274 background color, which can cause the cursor box to be invisible. */
6275 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6276 if (dpyinfo
->scratch_cursor_gc
)
6277 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6279 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6280 GCForeground
, &xgcv
);
6281 gc
= dpyinfo
->scratch_cursor_gc
;
6283 /* Set clipping, draw the rectangle, and reset clipping again. */
6284 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6285 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6286 mac_reset_clip_rectangles (dpy
, gc
);
6290 /* Draw a bar cursor on window W in glyph row ROW.
6292 Implementation note: One would like to draw a bar cursor with an
6293 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6294 Unfortunately, I didn't find a font yet that has this property set.
6298 x_draw_bar_cursor (w
, row
, width
, kind
)
6300 struct glyph_row
*row
;
6302 enum text_cursor_kinds kind
;
6304 struct frame
*f
= XFRAME (w
->frame
);
6305 struct glyph
*cursor_glyph
;
6307 /* If cursor is out of bounds, don't draw garbage. This can happen
6308 in mini-buffer windows when switching between echo area glyphs
6310 cursor_glyph
= get_phys_cursor_glyph (w
);
6311 if (cursor_glyph
== NULL
)
6314 /* If on an image, draw like a normal cursor. That's usually better
6315 visible than drawing a bar, esp. if the image is large so that
6316 the bar might not be in the window. */
6317 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6319 struct glyph_row
*row
;
6320 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6321 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6325 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6326 Window window
= FRAME_MAC_WINDOW (f
);
6327 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6328 unsigned long mask
= GCForeground
| GCBackground
;
6329 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6332 /* If the glyph's background equals the color we normally draw
6333 the bar cursor in, the bar cursor in its normal color is
6334 invisible. Use the glyph's foreground color instead in this
6335 case, on the assumption that the glyph's colors are chosen so
6336 that the glyph is legible. */
6337 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6338 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6340 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6343 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6346 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6347 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6351 width
= FRAME_CURSOR_WIDTH (f
);
6352 width
= min (cursor_glyph
->pixel_width
, width
);
6354 w
->phys_cursor_width
= width
;
6355 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6357 if (kind
== BAR_CURSOR
)
6358 mac_fill_rectangle (f
, gc
,
6359 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6360 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6361 width
, row
->height
);
6363 mac_fill_rectangle (f
, gc
,
6364 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6365 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6366 row
->height
- width
),
6367 cursor_glyph
->pixel_width
,
6370 mac_reset_clip_rectangles (dpy
, gc
);
6375 /* RIF: Define cursor CURSOR on frame F. */
6378 mac_define_frame_cursor (f
, cursor
)
6382 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6384 if (dpyinfo
->x_focus_frame
== f
)
6385 SetThemeCursor (cursor
);
6389 /* RIF: Clear area on frame F. */
6392 mac_clear_frame_area (f
, x
, y
, width
, height
)
6394 int x
, y
, width
, height
;
6396 mac_clear_area (f
, x
, y
, width
, height
);
6400 /* RIF: Draw cursor on window W. */
6403 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6405 struct glyph_row
*glyph_row
;
6407 int cursor_type
, cursor_width
;
6412 w
->phys_cursor_type
= cursor_type
;
6413 w
->phys_cursor_on_p
= 1;
6415 if (glyph_row
->exact_window_width_line_p
6416 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6418 glyph_row
->cursor_in_fringe_p
= 1;
6419 draw_fringe_bitmap (w
, glyph_row
, 0);
6422 switch (cursor_type
)
6424 case HOLLOW_BOX_CURSOR
:
6425 x_draw_hollow_cursor (w
, glyph_row
);
6428 case FILLED_BOX_CURSOR
:
6429 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6433 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6437 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6441 w
->phys_cursor_width
= 0;
6453 #if 0 /* MAC_TODO: no icon support yet. */
6455 x_bitmap_icon (f
, icon
)
6461 if (FRAME_W32_WINDOW (f
) == 0)
6465 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6466 else if (STRINGP (icon
))
6467 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6468 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6469 else if (SYMBOLP (icon
))
6473 if (EQ (icon
, intern ("application")))
6474 name
= (LPCTSTR
) IDI_APPLICATION
;
6475 else if (EQ (icon
, intern ("hand")))
6476 name
= (LPCTSTR
) IDI_HAND
;
6477 else if (EQ (icon
, intern ("question")))
6478 name
= (LPCTSTR
) IDI_QUESTION
;
6479 else if (EQ (icon
, intern ("exclamation")))
6480 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6481 else if (EQ (icon
, intern ("asterisk")))
6482 name
= (LPCTSTR
) IDI_ASTERISK
;
6483 else if (EQ (icon
, intern ("winlogo")))
6484 name
= (LPCTSTR
) IDI_WINLOGO
;
6488 hicon
= LoadIcon (NULL
, name
);
6496 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6501 #endif /* MAC_TODO */
6503 /************************************************************************
6505 ************************************************************************/
6507 /* Display Error Handling functions not used on W32. Listing them here
6508 helps diff stay in step when comparing w32term.c with xterm.c.
6510 x_error_catcher (display, error)
6511 x_catch_errors (dpy)
6512 x_catch_errors_unwind (old_val)
6513 x_check_errors (dpy, format)
6514 x_had_errors_p (dpy)
6515 x_clear_errors (dpy)
6516 x_uncatch_errors (dpy, count)
6518 x_connection_signal (signalnum)
6519 x_connection_closed (dpy, error_message)
6520 x_error_quitter (display, error)
6521 x_error_handler (display, error)
6522 x_io_error_quitter (display)
6527 /* Changing the font of the frame. */
6529 /* Give frame F the font named FONTNAME as its default font, and
6530 return the full name of that font. FONTNAME may be a wildcard
6531 pattern; in that case, we choose some font that fits the pattern.
6532 The return value shows which font we chose. */
6535 x_new_font (f
, fontname
)
6537 register char *fontname
;
6539 struct font_info
*fontp
6540 = FS_LOAD_FONT (f
, 0, fontname
, -1);
6545 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6546 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6547 FRAME_FONTSET (f
) = -1;
6549 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6550 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6551 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6553 compute_fringe_widths (f
, 1);
6555 /* Compute the scroll bar width in character columns. */
6556 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6558 int wid
= FRAME_COLUMN_WIDTH (f
);
6559 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6560 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6564 int wid
= FRAME_COLUMN_WIDTH (f
);
6565 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6568 /* Now make the frame display the given font. */
6569 if (FRAME_MAC_WINDOW (f
) != 0)
6571 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6573 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6575 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6578 /* Don't change the size of a tip frame; there's no point in
6579 doing it because it's done in Fx_show_tip, and it leads to
6580 problems because the tip frame has no widget. */
6581 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6582 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6585 return build_string (fontp
->full_name
);
6588 /* Give frame F the fontset named FONTSETNAME as its default font, and
6589 return the full name of that fontset. FONTSETNAME may be a wildcard
6590 pattern; in that case, we choose some fontset that fits the pattern.
6591 The return value shows which fontset we chose. */
6594 x_new_fontset (f
, fontsetname
)
6598 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
6604 if (FRAME_FONTSET (f
) == fontset
)
6605 /* This fontset is already set in frame F. There's nothing more
6607 return fontset_name (fontset
);
6609 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6611 if (!STRINGP (result
))
6612 /* Can't load ASCII font. */
6615 /* Since x_new_font doesn't update any fontset information, do it now. */
6616 FRAME_FONTSET (f
) = fontset
;
6618 return build_string (fontsetname
);
6622 /***********************************************************************
6623 TODO: W32 Input Methods
6624 ***********************************************************************/
6625 /* Listing missing functions from xterm.c helps diff stay in step.
6627 xim_destroy_callback (xim, client_data, call_data)
6628 xim_open_dpy (dpyinfo, resource_name)
6630 xim_instantiate_callback (display, client_data, call_data)
6631 xim_initialize (dpyinfo, resource_name)
6632 xim_close_dpy (dpyinfo)
6638 mac_get_window_bounds (f
, inner
, outer
)
6640 Rect
*inner
, *outer
;
6642 #if TARGET_API_MAC_CARBON
6643 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6644 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6645 #else /* not TARGET_API_MAC_CARBON */
6646 RgnHandle region
= NewRgn ();
6648 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6649 *inner
= (*region
)->rgnBBox
;
6650 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6651 *outer
= (*region
)->rgnBBox
;
6652 DisposeRgn (region
);
6653 #endif /* not TARGET_API_MAC_CARBON */
6657 mac_handle_origin_change (f
)
6660 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6664 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6666 int pixelwidth
, pixelheight
;
6670 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6671 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6673 if (cols
!= FRAME_COLS (f
)
6674 || rows
!= FRAME_LINES (f
)
6675 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6676 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6678 /* We pass 1 for DELAY since we can't run Lisp code inside of
6680 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6681 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6682 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6683 SET_FRAME_GARBAGED (f
);
6685 /* If cursor was outside the new size, mark it as off. */
6686 mark_window_cursors_off (XWINDOW (f
->root_window
));
6688 /* Clear out any recollection of where the mouse highlighting
6689 was, since it might be in a place that's outside the new
6690 frame size. Actually checking whether it is outside is a
6691 pain in the neck, so don't try--just let the highlighting be
6692 done afresh with new size. */
6693 cancel_mouse_face (f
);
6695 #if TARGET_API_MAC_CARBON
6696 if (f
->output_data
.mac
->hourglass_control
)
6699 mac_prepare_for_quickdraw (f
);
6701 MoveControl (f
->output_data
.mac
->hourglass_control
,
6702 pixelwidth
- HOURGLASS_WIDTH
, 0);
6709 /* Calculate the absolute position in frame F
6710 from its current recorded position values and gravity. */
6713 x_calc_absolute_position (f
)
6716 int width_diff
= 0, height_diff
= 0;
6717 int flags
= f
->size_hint_flags
;
6720 /* We have nothing to do if the current position
6721 is already for the top-left corner. */
6722 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6725 /* Find the offsets of the outside upper-left corner of
6726 the inner window, with respect to the outer window. */
6728 mac_get_window_bounds (f
, &inner
, &outer
);
6731 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6732 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6734 /* Treat negative positions as relative to the leftmost bottommost
6735 position that fits on the screen. */
6736 if (flags
& XNegative
)
6737 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6739 - FRAME_PIXEL_WIDTH (f
)
6742 if (flags
& YNegative
)
6743 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6745 - FRAME_PIXEL_HEIGHT (f
)
6748 /* The left_pos and top_pos
6749 are now relative to the top and left screen edges,
6750 so the flags should correspond. */
6751 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6754 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6755 to really change the position, and 0 when calling from
6756 x_make_frame_visible (in that case, XOFF and YOFF are the current
6757 position values). It is -1 when calling from x_set_frame_parameters,
6758 which means, do adjust for borders but don't change the gravity. */
6761 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6763 register int xoff
, yoff
;
6766 if (change_gravity
> 0)
6770 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6772 f
->size_hint_flags
|= XNegative
;
6774 f
->size_hint_flags
|= YNegative
;
6775 f
->win_gravity
= NorthWestGravity
;
6777 x_calc_absolute_position (f
);
6780 x_wm_set_size_hint (f
, (long) 0, 0);
6782 #if TARGET_API_MAC_CARBON
6783 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6784 /* If the title bar is completely outside the screen, adjust the
6786 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6787 kWindowConstrainMoveRegardlessOfFit
6788 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6789 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6790 mac_handle_origin_change (f
);
6793 Rect inner
, outer
, screen_rect
, dummy
;
6794 RgnHandle region
= NewRgn ();
6796 mac_get_window_bounds (f
, &inner
, &outer
);
6797 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6798 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6799 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6800 f
->top_pos
+ f
->y_pixels_diff
, false);
6802 /* If the title bar is completely outside the screen, adjust the
6803 position. The variable `outer' holds the title bar rectangle.
6804 The variable `inner' holds slightly smaller one than `outer',
6805 so that the calculation of overlapping may not become too
6807 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6808 outer
= (*region
)->rgnBBox
;
6809 DisposeRgn (region
);
6811 InsetRect (&inner
, 8, 8);
6812 screen_rect
= qd
.screenBits
.bounds
;
6813 screen_rect
.top
+= GetMBarHeight ();
6815 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6817 if (inner
.right
<= screen_rect
.left
)
6818 f
->left_pos
= screen_rect
.left
;
6819 else if (inner
.left
>= screen_rect
.right
)
6820 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6822 if (inner
.bottom
<= screen_rect
.top
)
6823 f
->top_pos
= screen_rect
.top
;
6824 else if (inner
.top
>= screen_rect
.bottom
)
6825 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6827 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6828 f
->top_pos
+ f
->y_pixels_diff
, false);
6836 /* Call this to change the size of frame F's x-window.
6837 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6838 for this size change and subsequent size changes.
6839 Otherwise we leave the window gravity unchanged. */
6842 x_set_window_size (f
, change_gravity
, cols
, rows
)
6847 int pixelwidth
, pixelheight
;
6851 check_frame_size (f
, &rows
, &cols
);
6852 f
->scroll_bar_actual_width
6853 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6855 compute_fringe_widths (f
, 0);
6857 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6858 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6860 f
->win_gravity
= NorthWestGravity
;
6861 x_wm_set_size_hint (f
, (long) 0, 0);
6863 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6865 #if TARGET_API_MAC_CARBON
6866 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6868 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6870 if (f
->output_data
.mac
->internal_border_width
6871 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6873 mac_clear_window (f
);
6874 f
->output_data
.mac
->internal_border_width
6875 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6878 SET_FRAME_GARBAGED (f
);
6883 /* Mouse warping. */
6885 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6888 x_set_mouse_position (f
, x
, y
)
6894 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6895 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6897 if (pix_x
< 0) pix_x
= 0;
6898 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6900 if (pix_y
< 0) pix_y
= 0;
6901 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6903 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6907 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6912 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
6913 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
6916 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
6919 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6922 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6923 0, 0, 0, 0, pix_x
, pix_y
);
6929 /* focus shifting, raising and lowering. */
6932 x_focus_on_frame (f
)
6935 #if 0 /* This proves to be unpleasant. */
6939 /* I don't think that the ICCCM allows programs to do things like this
6940 without the interaction of the window manager. Whatever you end up
6941 doing with this code, do it to x_unfocus_frame too. */
6942 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6943 RevertToPointerRoot
, CurrentTime
);
6953 /* Raise frame F. */
6959 if (f
->async_visible
)
6962 BringToFront (FRAME_MAC_WINDOW (f
));
6967 /* Lower frame F. */
6973 if (f
->async_visible
)
6976 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6982 XTframe_raise_lower (f
, raise_flag
)
6992 /* Change of visibility. */
6995 mac_handle_visibility_change (f
)
6998 WindowRef wp
= FRAME_MAC_WINDOW (f
);
6999 int visible
= 0, iconified
= 0;
7000 struct input_event buf
;
7002 if (IsWindowVisible (wp
))
7004 if (IsWindowCollapsed (wp
))
7010 if (!f
->async_visible
&& visible
)
7014 /* wait_reading_process_output will notice this and update
7015 the frame's display structures. If we were made
7016 invisible, we should not set garbaged, because that stops
7017 redrawing on Update events. */
7018 SET_FRAME_GARBAGED (f
);
7021 buf
.kind
= DEICONIFY_EVENT
;
7022 XSETFRAME (buf
.frame_or_window
, f
);
7024 kbd_buffer_store_event (&buf
);
7026 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7027 /* Force a redisplay sooner or later to update the
7028 frame titles in case this is the second frame. */
7029 record_asynch_buffer_change ();
7031 else if (f
->async_visible
&& !visible
)
7035 buf
.kind
= ICONIFY_EVENT
;
7036 XSETFRAME (buf
.frame_or_window
, f
);
7038 kbd_buffer_store_event (&buf
);
7041 f
->async_visible
= visible
;
7042 f
->async_iconified
= iconified
;
7045 /* This tries to wait until the frame is really visible.
7046 However, if the window manager asks the user where to position
7047 the frame, this will return before the user finishes doing that.
7048 The frame will not actually be visible at that time,
7049 but it will become visible later when the window manager
7050 finishes with it. */
7053 x_make_frame_visible (f
)
7058 if (! FRAME_VISIBLE_P (f
))
7060 /* We test FRAME_GARBAGED_P here to make sure we don't
7061 call x_set_offset a second time
7062 if we get to x_make_frame_visible a second time
7063 before the window gets really visible. */
7064 if (! FRAME_ICONIFIED_P (f
)
7065 && ! f
->output_data
.mac
->asked_for_visible
)
7066 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7068 f
->output_data
.mac
->asked_for_visible
= 1;
7070 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7071 ShowWindow (FRAME_MAC_WINDOW (f
));
7074 XFlush (FRAME_MAC_DISPLAY (f
));
7076 /* Synchronize to ensure Emacs knows the frame is visible
7077 before we do anything else. We do this loop with input not blocked
7078 so that incoming events are handled. */
7083 /* This must come after we set COUNT. */
7086 XSETFRAME (frame
, f
);
7088 /* Wait until the frame is visible. Process X events until a
7089 MapNotify event has been seen, or until we think we won't get a
7090 MapNotify at all.. */
7091 for (count
= input_signal_count
+ 10;
7092 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7094 /* Force processing of queued events. */
7097 /* Machines that do polling rather than SIGIO have been
7098 observed to go into a busy-wait here. So we'll fake an
7099 alarm signal to let the handler know that there's something
7100 to be read. We used to raise a real alarm, but it seems
7101 that the handler isn't always enabled here. This is
7103 if (input_polling_used ())
7105 /* It could be confusing if a real alarm arrives while
7106 processing the fake one. Turn it off and let the
7107 handler reset it. */
7108 extern void poll_for_input_1
P_ ((void));
7109 int old_poll_suppress_count
= poll_suppress_count
;
7110 poll_suppress_count
= 1;
7111 poll_for_input_1 ();
7112 poll_suppress_count
= old_poll_suppress_count
;
7115 /* See if a MapNotify event has been processed. */
7116 FRAME_SAMPLE_VISIBILITY (f
);
7121 /* Change from mapped state to withdrawn state. */
7123 /* Make the frame visible (mapped and not iconified). */
7126 x_make_frame_invisible (f
)
7129 /* A deactivate event does not occur when the last visible frame is
7130 made invisible. So if we clear the highlight here, it will not
7131 be rehighlighted when it is made visible. */
7133 /* Don't keep the highlight on an invisible frame. */
7134 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7135 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7140 #if !TARGET_API_MAC_CARBON
7141 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7142 that the current position of the window is user-specified, rather than
7143 program-specified, so that when the window is mapped again, it will be
7144 placed at the same location, without forcing the user to position it
7145 by hand again (they have already done that once for this window.) */
7146 x_wm_set_size_hint (f
, (long) 0, 1);
7149 HideWindow (FRAME_MAC_WINDOW (f
));
7153 #if !TARGET_API_MAC_CARBON
7154 mac_handle_visibility_change (f
);
7158 /* Change window state from mapped to iconified. */
7166 /* A deactivate event does not occur when the last visible frame is
7167 iconified. So if we clear the highlight here, it will not be
7168 rehighlighted when it is deiconified. */
7170 /* Don't keep the highlight on an invisible frame. */
7171 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7172 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7175 if (f
->async_iconified
)
7180 FRAME_SAMPLE_VISIBILITY (f
);
7182 if (! FRAME_VISIBLE_P (f
))
7183 ShowWindow (FRAME_MAC_WINDOW (f
));
7185 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7190 error ("Can't notify window manager of iconification");
7192 #if !TARGET_API_MAC_CARBON
7193 mac_handle_visibility_change (f
);
7198 /* Free X resources of frame F. */
7201 x_free_frame_resources (f
)
7204 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7205 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7209 if (wp
!= tip_window
)
7210 remove_window_handler (wp
);
7213 mac_prepare_for_quickdraw (f
);
7216 if (wp
== tip_window
)
7217 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7218 closed' event. So we reset tip_window here. */
7221 free_frame_menubar (f
);
7223 if (FRAME_FACE_CACHE (f
))
7224 free_frame_faces (f
);
7228 if (FRAME_SIZE_HINTS (f
))
7229 xfree (FRAME_SIZE_HINTS (f
));
7231 xfree (f
->output_data
.mac
);
7232 f
->output_data
.mac
= NULL
;
7234 if (f
== dpyinfo
->x_focus_frame
)
7236 dpyinfo
->x_focus_frame
= 0;
7237 #if USE_MAC_FONT_PANEL
7238 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7241 if (f
== dpyinfo
->x_focus_event_frame
)
7242 dpyinfo
->x_focus_event_frame
= 0;
7243 if (f
== dpyinfo
->x_highlight_frame
)
7244 dpyinfo
->x_highlight_frame
= 0;
7246 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7248 dpyinfo
->mouse_face_beg_row
7249 = dpyinfo
->mouse_face_beg_col
= -1;
7250 dpyinfo
->mouse_face_end_row
7251 = dpyinfo
->mouse_face_end_col
= -1;
7252 dpyinfo
->mouse_face_window
= Qnil
;
7253 dpyinfo
->mouse_face_deferred_gc
= 0;
7254 dpyinfo
->mouse_face_mouse_frame
= 0;
7261 /* Destroy the X window of frame F. */
7264 x_destroy_window (f
)
7267 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7269 x_free_frame_resources (f
);
7271 dpyinfo
->reference_count
--;
7275 /* Setting window manager hints. */
7277 /* Set the normal size hints for the window manager, for frame F.
7278 FLAGS is the flags word to use--or 0 meaning preserve the flags
7279 that the window now has.
7280 If USER_POSITION is nonzero, we set the USPosition
7281 flag (this is useful when FLAGS is 0). */
7283 x_wm_set_size_hint (f
, flags
, user_position
)
7288 int base_width
, base_height
, width_inc
, height_inc
;
7289 int min_rows
= 0, min_cols
= 0;
7290 XSizeHints
*size_hints
;
7292 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7293 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7294 width_inc
= FRAME_COLUMN_WIDTH (f
);
7295 height_inc
= FRAME_LINE_HEIGHT (f
);
7297 check_frame_size (f
, &min_rows
, &min_cols
);
7299 size_hints
= FRAME_SIZE_HINTS (f
);
7300 if (size_hints
== NULL
)
7302 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7303 bzero (size_hints
, sizeof (XSizeHints
));
7306 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7307 size_hints
->width_inc
= width_inc
;
7308 size_hints
->height_inc
= height_inc
;
7309 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7310 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7311 size_hints
->base_width
= base_width
;
7312 size_hints
->base_height
= base_height
;
7315 size_hints
->flags
= flags
;
7316 else if (user_position
)
7318 size_hints
->flags
&= ~ PPosition
;
7319 size_hints
->flags
|= USPosition
;
7323 #if 0 /* MAC_TODO: hide application instead of iconify? */
7324 /* Used for IconicState or NormalState */
7327 x_wm_set_window_state (f
, state
)
7331 #ifdef USE_X_TOOLKIT
7334 XtSetArg (al
[0], XtNinitialState
, state
);
7335 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7336 #else /* not USE_X_TOOLKIT */
7337 Window window
= FRAME_X_WINDOW (f
);
7339 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7340 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7342 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7343 #endif /* not USE_X_TOOLKIT */
7347 x_wm_set_icon_pixmap (f
, pixmap_id
)
7353 #ifndef USE_X_TOOLKIT
7354 Window window
= FRAME_X_WINDOW (f
);
7359 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7360 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7364 /* It seems there is no way to turn off use of an icon pixmap.
7365 The following line does it, only if no icon has yet been created,
7366 for some window managers. But with mwm it crashes.
7367 Some people say it should clear the IconPixmapHint bit in this case,
7368 but that doesn't work, and the X consortium said it isn't the
7369 right thing at all. Since there is no way to win,
7370 best to explicitly give up. */
7372 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7378 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7382 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7383 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7386 #else /* not USE_X_TOOLKIT */
7388 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7389 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7391 #endif /* not USE_X_TOOLKIT */
7394 #endif /* MAC_TODO */
7397 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7401 #if 0 /* MAC_TODO: no icons on Mac */
7402 #ifdef USE_X_TOOLKIT
7403 Window window
= XtWindow (f
->output_data
.x
->widget
);
7405 Window window
= FRAME_X_WINDOW (f
);
7408 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7409 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7410 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7412 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7413 #endif /* MAC_TODO */
7417 /***********************************************************************
7419 ***********************************************************************/
7421 /* An XLFD pattern is divided into blocks delimited by '*'. This
7422 structure holds information for each block. */
7423 struct xlfdpat_block
7425 /* Length of the pattern string in this block. Non-zero except for
7426 the first and the last blocks. */
7429 /* Pattern string except the last character in this block. The last
7430 character is replaced with NUL in order to use it as a
7432 unsigned char *pattern
;
7434 /* Last character of the pattern string. Must not be '?'. */
7435 unsigned char last_char
;
7437 /* One of the tables for the Boyer-Moore string search. It
7438 specifies the number of positions to proceed for each character
7439 with which the match fails. */
7442 /* The skip value for the last character in the above `skip' is
7443 assigned to `infinity' in order to simplify a loop condition.
7444 The original value is saved here. */
7450 /* Normalized pattern string. "Normalized" means that capital
7451 letters are lowered, blocks are not empty except the first and
7452 the last ones, and trailing '?'s in a block that is not the last
7453 one are moved to the next one. The last character in each block
7454 is replaced with NUL. */
7457 /* Number of characters except '*'s and trailing '?'s in the
7458 normalized pattern string. */
7461 /* Number of trailing '?'s in the normalized pattern string. */
7462 int trailing_anychars
;
7464 /* Number of blocks and information for each block. The latter is
7465 NULL if the pattern is exact (no '*' or '?' in it). */
7467 struct xlfdpat_block
*blocks
;
7471 xlfdpat_destroy (pat
)
7472 struct xlfdpat
*pat
;
7479 xfree (pat
->blocks
);
7486 static struct xlfdpat
*
7487 xlfdpat_create (pattern
)
7488 const char *pattern
;
7490 struct xlfdpat
*pat
;
7491 int nblocks
, i
, skip
;
7492 unsigned char last_char
, *p
, *q
, *anychar_head
;
7493 const unsigned char *ptr
;
7494 struct xlfdpat_block
*blk
;
7496 pat
= xmalloc (sizeof (struct xlfdpat
));
7497 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7499 /* Normalize the pattern string and store it to `pat->buf'. */
7501 anychar_head
= NULL
;
7504 for (ptr
= pattern
; *ptr
; ptr
++)
7506 unsigned char c
= *ptr
;
7509 if (last_char
== '*')
7510 /* ...a** -> ...a* */
7514 if (last_char
== '?')
7516 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7517 /* ...*??* -> ...*?? */
7520 /* ...a??* -> ...a*?? */
7522 *anychar_head
++ = '*';
7530 if (last_char
!= '?')
7534 /* On Mac OS X 10.3, tolower also converts non-ASCII
7535 characters for some locales. */
7539 *q
++ = last_char
= c
;
7543 pat
->nblocks
= nblocks
;
7544 if (last_char
!= '?')
7545 pat
->trailing_anychars
= 0;
7548 pat
->trailing_anychars
= q
- anychar_head
;
7551 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7553 if (anychar_head
== NULL
&& nblocks
== 1)
7555 /* The pattern is exact. */
7560 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7562 /* Divide the normalized pattern into blocks. */
7564 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7569 blk
->len
= p
- blk
->pattern
;
7573 blk
->len
= q
- blk
->pattern
;
7575 /* Setup a table for the Boyer-Moore string search. */
7576 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7579 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7580 blk
->pattern
[blk
->len
- 1] = '\0';
7582 for (skip
= 1; skip
< blk
->len
; skip
++)
7583 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7586 for (i
= 0; i
< 256; i
++)
7587 blk
->skip
[i
] = skip
;
7589 p
= blk
->pattern
+ (blk
->len
- skip
);
7591 blk
->skip
[*p
++] = skip
;
7593 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7600 xlfdpat_exact_p (pat
)
7601 struct xlfdpat
*pat
;
7603 return pat
->blocks
== NULL
;
7606 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7607 that the pattern in *BLK matches with its prefix. Return NULL
7608 there is no such strings. STRING must be lowered in advance. */
7611 xlfdpat_block_match_1 (blk
, string
, start_max
)
7612 struct xlfdpat_block
*blk
;
7613 const unsigned char *string
;
7616 int start
, infinity
;
7618 const unsigned char *s
;
7620 xassert (blk
->len
> 0);
7621 xassert (start_max
+ blk
->len
<= strlen (string
));
7622 xassert (blk
->last_char
!= '?');
7624 /* See the comments in the function `boyer_moore' (search.c) for the
7625 use of `infinity'. */
7626 infinity
= start_max
+ blk
->len
+ 1;
7627 blk
->skip
[blk
->last_char
] = infinity
;
7632 /* Check the last character of the pattern. */
7633 s
= string
+ blk
->len
- 1;
7636 start
+= blk
->skip
[*(s
+ start
)];
7638 while (start
<= start_max
);
7640 if (start
< infinity
)
7641 /* Couldn't find the last character. */
7644 /* No less than `infinity' means we could find the last
7645 character at `s[start - infinity]'. */
7648 /* Check the remaining characters. We prefer making no-'?'
7649 cases faster because the use of '?' is really rare. */
7654 while (*p
++ == *s
++)
7657 while (*(p
- 1) == '?');
7659 if (*(p
- 1) == '\0')
7661 return string
+ start
;
7664 start
+= blk
->last_char_skip
;
7666 while (start
<= start_max
);
7671 #define xlfdpat_block_match(b, s, m) \
7672 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7673 : xlfdpat_block_match_1 (b, s, m))
7675 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7676 matches with STRING. STRING must be lowered in advance. */
7679 xlfdpat_match (pat
, string
)
7680 struct xlfdpat
*pat
;
7681 const unsigned char *string
;
7683 int str_len
, nblocks
, i
, start_max
;
7684 struct xlfdpat_block
*blk
;
7685 const unsigned char *s
;
7687 xassert (pat
->nblocks
> 0);
7689 if (xlfdpat_exact_p (pat
))
7690 return strcmp (pat
->buf
, string
) == 0;
7692 /* The number of the characters in the string must not be smaller
7693 than that in the pattern. */
7694 str_len
= strlen (string
);
7695 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7698 /* Chop off the trailing '?'s. */
7699 str_len
-= pat
->trailing_anychars
;
7701 /* The last block. When it is non-empty, it must match at the end
7703 nblocks
= pat
->nblocks
;
7704 blk
= pat
->blocks
+ (nblocks
- 1);
7706 /* The last block is also the first one. */
7707 return (str_len
== blk
->len
7708 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7709 else if (blk
->len
!= 0)
7710 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7713 /* The first block. When it is non-empty, it must match at the
7714 beginning of the string. */
7718 s
= xlfdpat_block_match (blk
, string
, 0);
7721 string
= s
+ blk
->len
;
7724 /* The rest of the blocks. */
7725 start_max
= str_len
- pat
->nchars
;
7726 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7728 s
= xlfdpat_block_match (blk
, string
, start_max
);
7731 start_max
-= s
- string
;
7732 string
= s
+ blk
->len
;
7739 /***********************************************************************
7741 ***********************************************************************/
7743 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7746 x_get_font_info (f
, font_idx
)
7750 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7753 /* the global font name table */
7754 static char **font_name_table
= NULL
;
7755 static int font_name_table_size
= 0;
7756 static int font_name_count
= 0;
7758 /* Alist linking font family names to Font Manager font family
7759 references (which can also be used as QuickDraw font IDs). We use
7760 an alist because hash tables are not ready when the terminal frame
7761 for Mac OS Classic is created. */
7762 static Lisp_Object fm_font_family_alist
;
7764 /* Hash table linking font family names to ATSU font IDs. */
7765 static Lisp_Object atsu_font_id_hash
;
7766 /* Alist linking Font Manager style to face attributes. */
7767 static Lisp_Object fm_style_face_attributes_alist
;
7768 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7771 /* Alist linking character set strings to Mac text encoding and Emacs
7773 static Lisp_Object Vmac_charset_info_alist
;
7776 create_text_encoding_info_alist ()
7778 Lisp_Object result
= Qnil
, rest
;
7780 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7782 Lisp_Object charset_info
= XCAR (rest
);
7783 Lisp_Object charset
, coding_system
, text_encoding
;
7784 Lisp_Object existing_info
;
7786 if (!(CONSP (charset_info
)
7787 && (charset
= XCAR (charset_info
),
7789 && CONSP (XCDR (charset_info
))
7790 && (text_encoding
= XCAR (XCDR (charset_info
)),
7791 INTEGERP (text_encoding
))
7792 && CONSP (XCDR (XCDR (charset_info
)))
7793 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7794 SYMBOLP (coding_system
))))
7797 existing_info
= assq_no_quit (text_encoding
, result
);
7798 if (NILP (existing_info
))
7799 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7802 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7803 XSETCDR (XCDR (existing_info
),
7804 Fcons (charset
, XCDR (XCDR (existing_info
))));
7812 decode_mac_font_name (name
, size
, coding_system
)
7815 Lisp_Object coding_system
;
7817 struct coding_system coding
;
7820 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7822 for (p
= name
; *p
; p
++)
7823 if (!isascii (*p
) || iscntrl (*p
))
7828 setup_coding_system (coding_system
, &coding
);
7829 coding
.src_multibyte
= 0;
7830 coding
.dst_multibyte
= 1;
7831 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7832 coding
.composing
= COMPOSITION_DISABLED
;
7833 buf
= (char *) alloca (size
);
7835 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7836 bcopy (buf
, name
, coding
.produced
);
7837 name
[coding
.produced
] = '\0';
7841 /* If there's just one occurrence of '-' in the family name, it is
7842 replaced with '_'. (More than one occurrence of '-' means a
7843 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7844 p
= strchr (name
, '-');
7845 if (p
&& strchr (p
+ 1, '-') == NULL
)
7848 for (p
= name
; *p
; p
++)
7849 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7850 for some locales. */
7857 mac_to_x_fontname (name
, size
, style
, charset
)
7865 char xf
[256], *result
;
7868 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7872 strcpy(foundry
, "Apple");
7873 strcpy(family
, name
);
7876 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7877 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7878 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7880 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7881 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7882 for (p
= result
; *p
; p
++)
7883 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7884 for some locales. */
7891 /* Parse fully-specified and instantiated X11 font spec XF, and store
7892 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7893 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7894 caller must allocate at least 256 and 32 bytes respectively. For
7895 ordinary Mac fonts, the value stored to FAMILY should just be their
7896 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7897 intlfonts collection contain their charset designation in their
7898 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7899 types of font names are handled accordingly. */
7901 const int kDefaultFontSize
= 12;
7904 parse_x_font_name (xf
, family
, size
, style
, charset
)
7911 Str31 foundry
, weight
;
7912 int point_size
, avgwidth
;
7915 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7916 foundry
, family
, weight
, slant
, size
,
7917 &point_size
, &avgwidth
, charset
) != 8
7918 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7919 foundry
, family
, weight
, slant
, size
,
7920 &point_size
, &avgwidth
, charset
) != 8)
7926 *size
= point_size
/ 10;
7927 else if (avgwidth
> 0)
7928 *size
= avgwidth
/ 10;
7931 *size
= kDefaultFontSize
;
7934 if (strcmp (weight
, "bold") == 0)
7939 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7941 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7943 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7945 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7946 but take overlap into account. */
7947 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7948 memcpy (family
, foundry
, foundry_len
);
7949 family
[foundry_len
] = '-';
7950 family
[foundry_len
+ 1 + family_len
] = '-';
7951 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7957 for (p
= family
; *p
; p
++)
7958 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7959 for some locales. */
7968 add_font_name_table_entry (char *font_name
)
7970 if (font_name_table_size
== 0)
7972 font_name_table_size
= 256;
7973 font_name_table
= (char **)
7974 xmalloc (font_name_table_size
* sizeof (char *));
7976 else if (font_name_count
+ 1 >= font_name_table_size
)
7978 font_name_table_size
*= 2;
7979 font_name_table
= (char **)
7980 xrealloc (font_name_table
,
7981 font_name_table_size
* sizeof (char *));
7984 font_name_table
[font_name_count
++] = font_name
;
7988 add_mac_font_name (name
, size
, style
, charset
)
7992 const char *charset
;
7995 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7998 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7999 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8000 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8001 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8008 fm_get_style_from_font (font
)
8012 FMFontStyle style
= normal
;
8015 FMFontFamily font_family
;
8016 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8018 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8019 some font (e.g., Optima) even if it is `bold'. */
8020 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8021 sizeof (mac_style
), &mac_style
, &len
);
8023 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8024 style
= EndianU16_BtoN (mac_style
);
8026 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8032 atsu_find_font_from_family_name (family
)
8035 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8038 Lisp_Object rest
, best
;
8039 FMFontStyle min_style
, style
;
8041 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8044 return kATSUInvalidFontID
;
8046 rest
= HASH_VALUE (h
, i
);
8047 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8048 return cons_to_long (rest
);
8050 rest
= Fnreverse (rest
);
8054 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8057 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8058 if (style
< min_style
)
8061 if (style
== normal
)
8068 while (!NILP (rest
));
8070 HASH_VALUE (h
, i
) = best
;
8071 return cons_to_long (best
);
8075 fm_style_to_face_attributes (fm_style
)
8076 FMFontStyle fm_style
;
8080 fm_style
&= (bold
| italic
);
8081 tem
= assq_no_quit (make_number (fm_style
),
8082 fm_style_face_attributes_alist
);
8086 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8087 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8088 fm_style_face_attributes_alist
=
8089 Fcons (Fcons (make_number (fm_style
), tem
),
8090 fm_style_face_attributes_alist
);
8096 atsu_find_font_family_name (font_id
)
8101 Lisp_Object family
= Qnil
;
8103 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8104 kFontMacintoshPlatform
, kFontNoScript
,
8105 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8108 family
= make_uninit_string (len
);
8109 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8110 kFontMacintoshPlatform
, kFontNoScript
,
8111 kFontNoLanguage
, len
, SDATA (family
),
8115 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8121 mac_atsu_font_face_attributes (font_id
)
8124 Lisp_Object family
, style_attrs
;
8126 family
= atsu_find_font_family_name (font_id
);
8129 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8130 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8134 /* Sets up the table font_name_table to contain the list of all fonts
8135 in the system the first time the table is used so that the Resource
8136 Manager need not be accessed every time this information is
8140 init_font_name_table ()
8142 #if TARGET_API_MAC_CARBON
8143 FMFontFamilyIterator ffi
;
8144 FMFontFamilyInstanceIterator ffii
;
8146 Lisp_Object text_encoding_info_alist
;
8147 struct gcpro gcpro1
;
8149 text_encoding_info_alist
= create_text_encoding_info_alist ();
8152 #if USE_CG_TEXT_DRAWING
8153 init_cg_text_anti_aliasing_threshold ();
8155 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8156 text_encoding_info_alist
)))
8159 struct Lisp_Hash_Table
*h
;
8161 ItemCount nfonts
, i
;
8162 ATSUFontID
*font_ids
= NULL
;
8163 Lisp_Object prev_family
= Qnil
;
8167 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8168 make_float (DEFAULT_REHASH_SIZE
),
8169 make_float (DEFAULT_REHASH_THRESHOLD
),
8171 h
= XHASH_TABLE (atsu_font_id_hash
);
8173 err
= ATSUFontCount (&nfonts
);
8176 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8177 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8180 for (i
= 0; i
< nfonts
; i
++)
8184 family
= atsu_find_font_family_name (font_ids
[i
]);
8185 if (NILP (family
) || SREF (family
, 0) == '.')
8187 if (!NILP (Fequal (prev_family
, family
)))
8188 family
= prev_family
;
8190 j
= hash_lookup (h
, family
, &hash_code
);
8193 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8194 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8197 else if (EQ (prev_family
, family
))
8198 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8200 prev_family
= family
;
8207 /* Create a dummy instance iterator here to avoid creating and
8208 destroying it in the loop. */
8209 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8211 /* Create an iterator to enumerate the font families. */
8212 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8215 FMDisposeFontFamilyInstanceIterator (&ffii
);
8219 GCPRO1 (text_encoding_info_alist
);
8221 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8227 TextEncoding encoding
;
8228 TextEncodingBase sc
;
8229 Lisp_Object text_encoding_info
, family
;
8231 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8237 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8239 sc
= GetTextEncodingBase (encoding
);
8240 text_encoding_info
= assq_no_quit (make_number (sc
),
8241 text_encoding_info_alist
);
8242 if (NILP (text_encoding_info
))
8243 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8244 text_encoding_info_alist
);
8245 decode_mac_font_name (name
, sizeof (name
),
8246 XCAR (XCDR (text_encoding_info
)));
8247 family
= build_string (name
);
8248 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8250 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8251 fm_font_family_alist
);
8253 /* Point the instance iterator at the current font family. */
8254 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8257 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8260 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8262 if (size
> 0 || style
== normal
)
8263 for (; !NILP (rest
); rest
= XCDR (rest
))
8264 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8270 /* Dispose of the iterators. */
8271 FMDisposeFontFamilyIterator (&ffi
);
8272 FMDisposeFontFamilyInstanceIterator (&ffii
);
8273 #else /* !TARGET_API_MAC_CARBON */
8275 SInt16 fontnum
, old_fontnum
;
8276 int num_mac_fonts
= CountResources('FOND');
8278 Handle font_handle
, font_handle_2
;
8279 short id
, scriptcode
;
8282 struct FontAssoc
*fat
;
8283 struct AsscEntry
*assc_entry
;
8284 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8285 struct gcpro gcpro1
;
8287 GetPort (&port
); /* save the current font number used */
8288 old_fontnum
= port
->txFont
;
8290 text_encoding_info_alist
= create_text_encoding_info_alist ();
8292 GCPRO1 (text_encoding_info_alist
);
8294 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8296 font_handle
= GetIndResource ('FOND', i
);
8300 GetResInfo (font_handle
, &id
, &type
, name
);
8301 GetFNum (name
, &fontnum
);
8303 if (fontnum
== 0 || *name
== '.')
8307 scriptcode
= FontToScript (fontnum
);
8308 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8309 text_encoding_info_alist
);
8310 if (NILP (text_encoding_info
))
8311 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8312 text_encoding_info_alist
);
8313 decode_mac_font_name (name
, sizeof (name
),
8314 XCAR (XCDR (text_encoding_info
)));
8315 family
= build_string (name
);
8316 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8318 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8319 fm_font_family_alist
);
8322 HLock (font_handle
);
8324 if (GetResourceSizeOnDisk (font_handle
)
8325 >= sizeof (struct FamRec
))
8327 fat
= (struct FontAssoc
*) (*font_handle
8328 + sizeof (struct FamRec
));
8330 = (struct AsscEntry
*) (*font_handle
8331 + sizeof (struct FamRec
)
8332 + sizeof (struct FontAssoc
));
8334 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8336 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8338 for (; !NILP (rest
); rest
= XCDR (rest
))
8339 add_mac_font_name (name
, assc_entry
->fontSize
,
8340 assc_entry
->fontStyle
,
8341 SDATA (XCAR (rest
)));
8345 HUnlock (font_handle
);
8346 font_handle_2
= GetNextFOND (font_handle
);
8347 ReleaseResource (font_handle
);
8348 font_handle
= font_handle_2
;
8350 while (ResError () == noErr
&& font_handle
);
8355 TextFont (old_fontnum
);
8356 #endif /* !TARGET_API_MAC_CARBON */
8361 mac_clear_font_name_table ()
8365 for (i
= 0; i
< font_name_count
; i
++)
8366 xfree (font_name_table
[i
]);
8367 xfree (font_name_table
);
8368 font_name_table
= NULL
;
8369 font_name_table_size
= font_name_count
= 0;
8370 fm_font_family_alist
= Qnil
;
8374 enum xlfd_scalable_field_index
8376 XLFD_SCL_PIXEL_SIZE
,
8377 XLFD_SCL_POINT_SIZE
,
8382 static const int xlfd_scalable_fields
[] =
8391 mac_do_list_fonts (pattern
, maxnames
)
8392 const char *pattern
;
8396 Lisp_Object font_list
= Qnil
;
8397 struct xlfdpat
*pat
;
8400 int scl_val
[XLFD_SCL_LAST
], *val
;
8404 if (font_name_table
== NULL
) /* Initialize when first used. */
8405 init_font_name_table ();
8407 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8410 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8411 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8412 fonts are scaled according to the specified size. */
8415 field
= xlfd_scalable_fields
;
8423 if ('0' <= *ptr
&& *ptr
<= '9')
8425 *val
= *ptr
++ - '0';
8426 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8427 *val
= *val
* 10 + *ptr
++ - '0';
8434 ptr
= strchr (ptr
, '-');
8437 while (ptr
&& i
< 14);
8439 if (i
== 14 && ptr
== NULL
)
8441 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8442 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8443 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8444 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8446 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8447 scl_val
[XLFD_SCL_POINT_SIZE
] =
8448 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8449 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8451 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8452 scl_val
[XLFD_SCL_AVGWIDTH
] =
8453 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8454 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8458 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8460 pat
= xlfdpat_create (pattern
);
8464 exact
= xlfdpat_exact_p (pat
);
8466 for (i
= 0; i
< font_name_count
; i
++)
8468 if (xlfdpat_match (pat
, font_name_table
[i
]))
8470 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8471 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8474 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8475 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8477 int former_len
= ptr
- font_name_table
[i
];
8479 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8480 memcpy (scaled
, font_name_table
[i
], former_len
);
8481 sprintf (scaled
+ former_len
,
8482 "-%d-%d-72-72-m-%d-%s",
8483 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8484 scl_val
[XLFD_SCL_POINT_SIZE
],
8485 scl_val
[XLFD_SCL_AVGWIDTH
],
8486 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8488 if (xlfdpat_match (pat
, scaled
))
8490 font_list
= Fcons (build_string (scaled
), font_list
);
8492 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8500 xlfdpat_destroy (pat
);
8505 /* Return a list of names of available fonts matching PATTERN on frame F.
8507 Frame F null means we have not yet created any frame on Mac, and
8508 consult the first display in x_display_list. MAXNAMES sets a limit
8509 on how many fonts to match. */
8512 x_list_fonts (f
, pattern
, size
, maxnames
)
8514 Lisp_Object pattern
;
8517 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8518 struct mac_display_info
*dpyinfo
8519 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8521 xassert (size
<= 0);
8523 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8524 if (NILP (patterns
))
8525 patterns
= Fcons (pattern
, Qnil
);
8527 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8529 pattern
= XCAR (patterns
);
8531 if (!STRINGP (pattern
))
8534 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8535 key
= Fcons (pattern
, make_number (maxnames
));
8537 list
= Fassoc (key
, tem
);
8540 list
= Fcdr_safe (list
);
8541 /* We have a cashed list. Don't have to get the list again. */
8546 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8549 /* MAC_TODO: add code for matching outline fonts here */
8551 /* Now store the result in the cache. */
8552 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8553 Fcons (Fcons (key
, list
),
8554 XCAR (XCDR (dpyinfo
->name_list_element
))));
8557 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8566 /* Check that FONT is valid on frame F. It is if it can be found in F's
8570 x_check_font (f
, font
)
8575 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8577 xassert (font
!= NULL
);
8579 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8580 if (dpyinfo
->font_table
[i
].name
8581 && font
== dpyinfo
->font_table
[i
].font
)
8584 xassert (i
< dpyinfo
->n_fonts
);
8587 #endif /* GLYPH_DEBUG != 0 */
8589 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8590 Note: There are (broken) X fonts out there with invalid XFontStruct
8591 min_bounds contents. For example, handa@etl.go.jp reports that
8592 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8593 have font->min_bounds.width == 0. */
8596 x_font_min_bounds (font
, w
, h
)
8597 MacFontStruct
*font
;
8600 *h
= FONT_HEIGHT (font
);
8601 *w
= font
->min_bounds
.width
;
8605 /* Compute the smallest character width and smallest font height over
8606 all fonts available on frame F. Set the members smallest_char_width
8607 and smallest_font_height in F's x_display_info structure to
8608 the values computed. Value is non-zero if smallest_font_height or
8609 smallest_char_width become smaller than they were before. */
8612 x_compute_min_glyph_bounds (f
)
8616 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8617 MacFontStruct
*font
;
8618 int old_width
= dpyinfo
->smallest_char_width
;
8619 int old_height
= dpyinfo
->smallest_font_height
;
8621 dpyinfo
->smallest_font_height
= 100000;
8622 dpyinfo
->smallest_char_width
= 100000;
8624 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8625 if (dpyinfo
->font_table
[i
].name
)
8627 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8630 font
= (MacFontStruct
*) fontp
->font
;
8631 xassert (font
!= (MacFontStruct
*) ~0);
8632 x_font_min_bounds (font
, &w
, &h
);
8634 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8635 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8638 xassert (dpyinfo
->smallest_char_width
> 0
8639 && dpyinfo
->smallest_font_height
> 0);
8641 return (dpyinfo
->n_fonts
== 1
8642 || dpyinfo
->smallest_char_width
< old_width
8643 || dpyinfo
->smallest_font_height
< old_height
);
8647 /* Determine whether given string is a fully-specified XLFD: all 14
8648 fields are present, none is '*'. */
8651 is_fully_specified_xlfd (p
)
8660 for (i
= 0; i
< 13; i
++)
8662 q
= strchr (p
+ 1, '-');
8665 if (q
- p
== 2 && *(p
+ 1) == '*')
8670 if (strchr (p
+ 1, '-') != NULL
)
8673 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8680 /* mac_load_query_font creates and returns an internal representation
8681 for a font in a MacFontStruct struct. There is really no concept
8682 corresponding to "loading" a font on the Mac. But we check its
8683 existence and find the font number and all other information for it
8684 and store them in the returned MacFontStruct. */
8686 static MacFontStruct
*
8687 mac_load_query_font (f
, fontname
)
8697 static ATSUFontID font_id
;
8698 ATSUStyle mac_style
= NULL
;
8701 #if TARGET_API_MAC_CARBON
8702 TextEncoding encoding
;
8707 MacFontStruct
*font
;
8708 XCharStruct
*space_bounds
= NULL
, *pcm
;
8710 if (is_fully_specified_xlfd (fontname
))
8714 Lisp_Object matched_fonts
;
8716 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8717 if (NILP (matched_fonts
))
8719 name
= SDATA (XCAR (matched_fonts
));
8722 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8726 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8729 static const ATSUAttributeTag tags
[] =
8730 {kATSUFontTag
, kATSUSizeTag
,
8731 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8732 static const ByteCount sizes
[] =
8733 {sizeof (ATSUFontID
), sizeof (Fixed
),
8734 sizeof (Boolean
), sizeof (Boolean
)};
8735 static Fixed size_fixed
;
8736 static Boolean bold_p
, italic_p
;
8737 static const ATSUAttributeValuePtr values
[] =
8738 {&font_id
, &size_fixed
,
8739 &bold_p
, &italic_p
};
8740 static const ATSUFontFeatureType types
[] =
8741 {kAllTypographicFeaturesType
, kDiacriticsType
};
8742 static const ATSUFontFeatureSelector selectors
[] =
8743 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8746 font_id
= atsu_find_font_from_family_name (family
);
8747 if (font_id
== kATSUInvalidFontID
)
8749 size_fixed
= Long2Fix (size
);
8750 bold_p
= (fontface
& bold
) != 0;
8751 italic_p
= (fontface
& italic
) != 0;
8752 err
= ATSUCreateStyle (&mac_style
);
8755 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8759 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8760 tags
, sizes
, values
);
8763 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8766 scriptcode
= kTextEncodingMacUnicode
;
8771 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8775 fontnum
= XINT (XCDR (tmp
));
8776 #if TARGET_API_MAC_CARBON
8777 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8779 scriptcode
= GetTextEncodingBase (encoding
);
8781 scriptcode
= FontToScript (fontnum
);
8785 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8787 font
->mac_fontnum
= fontnum
;
8788 font
->mac_fontsize
= size
;
8789 font
->mac_fontface
= fontface
;
8790 font
->mac_scriptcode
= scriptcode
;
8792 font
->mac_style
= mac_style
;
8793 #if USE_CG_TEXT_DRAWING
8794 font
->cg_font
= NULL
;
8795 font
->cg_glyphs
= NULL
;
8799 /* Apple Japanese (SJIS) font is listed as both
8800 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8801 (Roman script) in init_font_name_table (). The latter should be
8802 treated as a one-byte font. */
8803 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8804 font
->mac_scriptcode
= smRoman
;
8806 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8809 if (font
->mac_style
)
8814 font
->min_byte1
= 0;
8815 font
->max_byte1
= 0xff;
8816 font
->min_char_or_byte2
= 0;
8817 font
->max_char_or_byte2
= 0xff;
8819 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8820 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8821 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8822 pcm_init (font
->bounds
.rows
[0], 0x100);
8824 #if USE_CG_TEXT_DRAWING
8828 ATSFontRef ats_font
;
8830 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8832 /* Use CG text drawing if italic/bold is not synthesized. */
8833 if (err
== noErr
&& style
== fontface
)
8835 ats_font
= FMGetATSFontRefFromFont (font_id
);
8836 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8842 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8843 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8846 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8847 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8848 &font
->ascent
, &font
->descent
,
8850 #if USE_CG_TEXT_DRAWING
8851 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8858 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8860 mac_unload_font (&one_mac_display_info
, font
);
8864 pcm
= font
->bounds
.rows
[0];
8865 for (c
= 0x21; c
<= 0xff; c
++)
8868 /* Soft hyphen is not supported in ATSUI. */
8872 #if USE_CG_TEXT_DRAWING
8873 if (font
->cg_glyphs
)
8883 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8884 pcm
? pcm
+ c
: NULL
,
8885 #if USE_CG_TEXT_DRAWING
8886 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8893 #if USE_CG_TEXT_DRAWING
8894 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8896 /* Don't use CG text drawing if font substitution occurs in
8897 ASCII or Latin-1 characters. */
8898 CGFontRelease (font
->cg_font
);
8899 font
->cg_font
= NULL
;
8900 xfree (font
->cg_glyphs
);
8901 font
->cg_glyphs
= NULL
;
8912 FontInfo the_fontinfo
;
8913 int is_two_byte_font
;
8916 mac_prepare_for_quickdraw (f
);
8918 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8922 TextFace (fontface
);
8924 GetFontInfo (&the_fontinfo
);
8926 font
->ascent
= the_fontinfo
.ascent
;
8927 font
->descent
= the_fontinfo
.descent
;
8929 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8930 || font
->mac_scriptcode
== smTradChinese
8931 || font
->mac_scriptcode
== smSimpChinese
8932 || font
->mac_scriptcode
== smKorean
);
8934 if (is_two_byte_font
)
8938 font
->min_byte1
= 0xa1;
8939 font
->max_byte1
= 0xfe;
8940 font
->min_char_or_byte2
= 0xa1;
8941 font
->max_char_or_byte2
= 0xfe;
8943 /* Use the width of an "ideographic space" of that font
8944 because the_fontinfo.widMax returns the wrong width for
8946 switch (font
->mac_scriptcode
)
8949 font
->min_byte1
= 0x81;
8950 font
->max_byte1
= 0xfc;
8951 font
->min_char_or_byte2
= 0x40;
8952 font
->max_char_or_byte2
= 0xfc;
8953 char_width
= StringWidth("\p\x81\x40");
8956 font
->min_char_or_byte2
= 0x40;
8957 char_width
= StringWidth("\p\xa1\x40");
8960 char_width
= StringWidth("\p\xa1\xa1");
8963 char_width
= StringWidth("\p\xa1\xa1");
8967 font
->bounds
.per_char
= NULL
;
8969 if (fontface
& italic
)
8970 font
->max_bounds
.rbearing
= char_width
+ 1;
8972 font
->max_bounds
.rbearing
= char_width
;
8973 font
->max_bounds
.lbearing
= 0;
8974 font
->max_bounds
.width
= char_width
;
8975 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8976 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8978 font
->min_bounds
= font
->max_bounds
;
8984 font
->min_byte1
= font
->max_byte1
= 0;
8985 font
->min_char_or_byte2
= 0x20;
8986 font
->max_char_or_byte2
= 0xff;
8988 font
->bounds
.per_char
=
8989 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8990 bzero (font
->bounds
.per_char
,
8991 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8993 space_bounds
= font
->bounds
.per_char
;
8994 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
8995 &font
->descent
, space_bounds
, NULL
);
8996 if (err
!= noErr
|| space_bounds
->width
<= 0)
8998 mac_unload_font (&one_mac_display_info
, font
);
9002 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9003 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9011 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9012 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9015 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9017 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9019 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9021 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9023 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9026 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9028 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9030 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9032 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9034 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9039 font
->mac_style
== NULL
&&
9041 font
->max_bounds
.width
== font
->min_bounds
.width
9042 && font
->min_bounds
.lbearing
>= 0
9043 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9045 /* Fixed width and no overhangs. */
9046 xfree (font
->bounds
.per_char
);
9047 font
->bounds
.per_char
= NULL
;
9051 #if !defined (MAC_OS8) || USE_ATSUI
9052 /* AppKit and WebKit do some adjustment to the heights of Courier,
9053 Helvetica, and Times. This only works on the environments where
9054 srcCopy text transfer mode is never used. */
9056 #ifdef MAC_OS8 /* implies USE_ATSUI */
9059 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9060 || strcmp (family
, "times") == 0))
9061 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9069 mac_unload_font (dpyinfo
, font
)
9070 struct mac_display_info
*dpyinfo
;
9073 xfree (font
->full_name
);
9075 if (font
->mac_style
)
9079 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9080 if (font
->bounds
.rows
[i
])
9081 xfree (font
->bounds
.rows
[i
]);
9082 xfree (font
->bounds
.rows
);
9083 ATSUDisposeStyle (font
->mac_style
);
9087 if (font
->bounds
.per_char
)
9088 xfree (font
->bounds
.per_char
);
9089 #if USE_CG_TEXT_DRAWING
9091 CGFontRelease (font
->cg_font
);
9092 if (font
->cg_glyphs
)
9093 xfree (font
->cg_glyphs
);
9099 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9100 pointer to the structure font_info while allocating it dynamically.
9101 If SIZE is 0, load any size of font.
9102 If loading is failed, return NULL. */
9105 x_load_font (f
, fontname
, size
)
9107 register char *fontname
;
9110 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9111 Lisp_Object font_names
;
9113 /* Get a list of all the fonts that match this name. Once we
9114 have a list of matching fonts, we compare them against the fonts
9115 we already have by comparing names. */
9116 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9118 if (!NILP (font_names
))
9123 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9124 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9125 if (dpyinfo
->font_table
[i
].name
9126 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9127 SDATA (XCAR (tail
)))
9128 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9129 SDATA (XCAR (tail
)))))
9130 return (dpyinfo
->font_table
+ i
);
9135 /* Load the font and add it to the table. */
9137 struct MacFontStruct
*font
;
9138 struct font_info
*fontp
;
9141 fontname
= (char *) SDATA (XCAR (font_names
));
9144 font
= mac_load_query_font (f
, fontname
);
9149 /* Find a free slot in the font table. */
9150 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9151 if (dpyinfo
->font_table
[i
].name
== NULL
)
9154 /* If no free slot found, maybe enlarge the font table. */
9155 if (i
== dpyinfo
->n_fonts
9156 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9159 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9160 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9162 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9165 fontp
= dpyinfo
->font_table
+ i
;
9166 if (i
== dpyinfo
->n_fonts
)
9169 /* Now fill in the slots of *FONTP. */
9171 bzero (fontp
, sizeof (*fontp
));
9173 fontp
->font_idx
= i
;
9174 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9175 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9177 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9179 /* Fixed width font. */
9180 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9187 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9188 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9190 fontp
->space_width
= pcm
->width
;
9192 fontp
->space_width
= FONT_WIDTH (font
);
9196 int width
= pcm
->width
;
9197 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9198 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9199 width
+= pcm
->width
;
9200 fontp
->average_width
= width
/ 95;
9203 fontp
->average_width
= FONT_WIDTH (font
);
9206 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9207 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9209 fontp
->size
= font
->max_bounds
.width
;
9210 fontp
->height
= FONT_HEIGHT (font
);
9212 /* For some font, ascent and descent in max_bounds field is
9213 larger than the above value. */
9214 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9215 if (max_height
> fontp
->height
)
9216 fontp
->height
= max_height
;
9219 /* The slot `encoding' specifies how to map a character
9220 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9221 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9222 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9223 2:0xA020..0xFF7F). For the moment, we don't know which charset
9224 uses this font. So, we set information in fontp->encoding[1]
9225 which is never used by any charset. If mapping can't be
9226 decided, set FONT_ENCODING_NOT_DECIDED. */
9227 if (font
->mac_scriptcode
== smJapanese
)
9228 fontp
->encoding
[1] = 4;
9232 = (font
->max_byte1
== 0
9234 ? (font
->min_char_or_byte2
< 0x80
9235 ? (font
->max_char_or_byte2
< 0x80
9236 ? 0 /* 0x20..0x7F */
9237 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9238 : 1) /* 0xA0..0xFF */
9240 : (font
->min_byte1
< 0x80
9241 ? (font
->max_byte1
< 0x80
9242 ? (font
->min_char_or_byte2
< 0x80
9243 ? (font
->max_char_or_byte2
< 0x80
9244 ? 0 /* 0x2020..0x7F7F */
9245 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9246 : 3) /* 0x20A0..0x7FFF */
9247 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9248 : (font
->min_char_or_byte2
< 0x80
9249 ? (font
->max_char_or_byte2
< 0x80
9250 ? 2 /* 0xA020..0xFF7F */
9251 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9252 : 1))); /* 0xA0A0..0xFFFF */
9255 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9256 fontp
->baseline_offset
9257 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9258 ? (long) value
: 0);
9259 fontp
->relative_compose
9260 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9261 ? (long) value
: 0);
9262 fontp
->default_ascent
9263 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9264 ? (long) value
: 0);
9266 fontp
->baseline_offset
= 0;
9267 fontp
->relative_compose
= 0;
9268 fontp
->default_ascent
= 0;
9271 /* Set global flag fonts_changed_p to non-zero if the font loaded
9272 has a character with a smaller width than any other character
9273 before, or if the font loaded has a smaller height than any
9274 other font loaded before. If this happens, it will make a
9275 glyph matrix reallocation necessary. */
9276 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9283 /* Return a pointer to struct font_info of a font named FONTNAME for
9284 frame F. If no such font is loaded, return NULL. */
9287 x_query_font (f
, fontname
)
9289 register char *fontname
;
9291 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9294 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9295 if (dpyinfo
->font_table
[i
].name
9296 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9297 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9298 return (dpyinfo
->font_table
+ i
);
9303 /* Find a CCL program for a font specified by FONTP, and set the member
9304 `encoder' of the structure. */
9307 x_find_ccl_program (fontp
)
9308 struct font_info
*fontp
;
9310 Lisp_Object list
, elt
;
9312 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9316 && STRINGP (XCAR (elt
))
9317 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9323 struct ccl_program
*ccl
9324 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9326 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9329 fontp
->font_encoder
= ccl
;
9333 #if USE_MAC_FONT_PANEL
9334 /* Whether Font Panel has been shown before. The first call to font
9335 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9336 slow. This variable is used for deferring such a call as much as
9338 static int font_panel_shown_p
= 0;
9340 extern Lisp_Object Qfont
;
9341 static Lisp_Object Qpanel_closed
, Qselection
;
9343 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9347 const EventParamName
*,
9348 const EventParamType
*));
9351 mac_font_panel_visible_p ()
9353 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9356 static pascal OSStatus
9357 mac_handle_font_event (next_handler
, event
, data
)
9358 EventHandlerCallRef next_handler
;
9362 OSStatus result
, err
;
9365 const EventParamName
*names
;
9366 const EventParamType
*types
;
9367 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9368 kEventParamATSUFontSize
,
9369 kEventParamFMFontFamily
,
9370 kEventParamFMFontSize
,
9371 kEventParamFontColor
};
9372 static const EventParamType types_sel
[] = {typeATSUFontID
,
9378 result
= CallNextEventHandler (next_handler
, event
);
9379 if (result
!= eventNotHandledErr
)
9382 switch (GetEventKind (event
))
9384 case kEventFontPanelClosed
:
9385 id_key
= Qpanel_closed
;
9391 case kEventFontSelection
:
9392 id_key
= Qselection
;
9393 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9399 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9409 mac_show_hide_font_panel ()
9411 if (!font_panel_shown_p
)
9415 static const EventTypeSpec specs
[] =
9416 {{kEventClassFont
, kEventFontPanelClosed
},
9417 {kEventClassFont
, kEventFontSelection
}};
9419 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9420 GetEventTypeCount (specs
),
9425 font_panel_shown_p
= 1;
9428 return FPShowHideFontPanel ();
9432 mac_set_font_info_for_selection (f
, face_id
, c
)
9437 EventTargetRef target
= NULL
;
9438 XFontStruct
*font
= NULL
;
9440 if (!mac_font_panel_visible_p ())
9445 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9447 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9451 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9452 face
= FACE_FROM_ID (f
, face_id
);
9458 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9461 if (font
->mac_fontnum
!= -1)
9463 FontSelectionQDStyle qd_style
;
9465 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9466 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9467 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9468 qd_style
.size
= font
->mac_fontsize
;
9469 qd_style
.hasColor
= false;
9471 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9472 1, &qd_style
, target
);
9475 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9476 1, &font
->mac_style
, target
);
9484 /* The Mac Event loop code */
9486 #if !TARGET_API_MAC_CARBON
9488 #include <Quickdraw.h>
9489 #include <Balloons.h>
9490 #include <Devices.h>
9492 #include <Gestalt.h>
9494 #include <Processes.h>
9496 #include <ToolUtils.h>
9497 #include <TextUtils.h>
9498 #include <Dialogs.h>
9501 #include <Resources.h>
9506 #endif /* ! TARGET_API_MAC_CARBON */
9511 #define DEFAULT_NUM_COLS 80
9513 #define MIN_DOC_SIZE 64
9514 #define MAX_DOC_SIZE 32767
9516 #define EXTRA_STACK_ALLOC (256 * 1024)
9518 #define ARGV_STRING_LIST_ID 129
9519 #define ABOUT_ALERT_ID 128
9520 #define RAM_TOO_LARGE_ALERT_ID 129
9522 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9523 Lisp_Object Qreverse
;
9526 /* Modifier associated with the control key, or nil to ignore. */
9527 Lisp_Object Vmac_control_modifier
;
9529 /* Modifier associated with the option key, or nil to ignore. */
9530 Lisp_Object Vmac_option_modifier
;
9532 /* Modifier associated with the command key, or nil to ignore. */
9533 Lisp_Object Vmac_command_modifier
;
9535 /* Modifier associated with the function key, or nil to ignore. */
9536 Lisp_Object Vmac_function_modifier
;
9538 /* True if the option and command modifiers should be used to emulate
9539 a three button mouse */
9540 Lisp_Object Vmac_emulate_three_button_mouse
;
9542 #if TARGET_API_MAC_CARBON
9543 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9544 mouse-2, instead of mouse-3. */
9545 int mac_wheel_button_is_mouse_2
;
9547 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9548 for processing before Emacs sees it. */
9549 int mac_pass_command_to_system
;
9551 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9552 for processing before Emacs sees it. */
9553 int mac_pass_control_to_system
;
9556 /* Points to the variable `inev' in the function XTread_socket. It is
9557 used for passing an input event to the function back from
9558 Carbon/Apple event handlers. */
9559 static struct input_event
*read_socket_inev
= NULL
;
9561 /* Whether or not the screen configuration has changed. */
9562 static int mac_screen_config_changed
= 0;
9564 Point saved_menu_event_location
;
9567 #if TARGET_API_MAC_CARBON
9568 static Lisp_Object Qhi_command
;
9570 extern Lisp_Object Qwindow
;
9571 static Lisp_Object Qtoolbar_switch_mode
;
9574 static TSMDocumentID tsm_document_id
;
9575 static Lisp_Object Qtext_input
;
9576 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9577 static Lisp_Object Vmac_ts_active_input_overlay
;
9578 extern Lisp_Object Qbefore_string
;
9579 static Lisp_Object Vmac_ts_script_language_on_focus
;
9580 static Lisp_Object saved_ts_script_language_on_focus
;
9581 static ScriptLanguageRecord saved_ts_language
;
9582 static Component saved_ts_component
;
9584 #endif /* TARGET_API_MAC_CARBON */
9585 extern int mac_ready_for_apple_events
;
9586 extern Lisp_Object Qundefined
;
9587 extern void init_apple_event_handler
P_ ((void));
9588 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9589 Lisp_Object
*, Lisp_Object
*,
9591 extern OSErr init_coercion_handler
P_ ((void));
9594 extern OSErr install_drag_handler
P_ ((WindowRef
));
9595 extern void remove_drag_handler
P_ ((WindowRef
));
9597 #if TARGET_API_MAC_CARBON
9598 /* Showing help echo string during menu tracking */
9599 extern OSStatus install_menu_target_item_handler
P_ ((void));
9602 extern OSStatus
install_service_handler ();
9603 static Lisp_Object Qservice
, Qpaste
, Qperform
;
9607 extern void init_emacs_passwd_dir ();
9608 extern int emacs_main (int, char **, char **);
9610 extern void initialize_applescript();
9611 extern void terminate_applescript();
9613 /* Table for translating Mac keycode to X keysym values. Contributed
9615 Mapping for special keys is now identical to that in Apple X11
9616 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9617 on the right of the Cmd key on laptops, and fn + `enter' (->
9619 static const unsigned char keycode_to_xkeysym_table
[] = {
9620 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9621 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9622 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9624 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9625 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9626 /*0x38*/ 0, 0, 0, 0,
9627 /*0x3C*/ 0, 0, 0, 0,
9629 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9630 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9631 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9632 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9634 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9635 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9636 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9637 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9639 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9640 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9641 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9642 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9644 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9645 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9646 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9647 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9651 /* Table for translating Mac keycode with the laptop `fn' key to that
9652 without it. Destination symbols in comments are keys on US
9653 keyboard, and they may not be the same on other types of keyboards.
9654 If the destination is identical to the source (f1 ... f12), it
9655 doesn't map `fn' key to a modifier. */
9656 static const unsigned char fn_keycode_to_keycode_table
[] = {
9657 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9658 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9659 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9661 /*0x30*/ 0, 0, 0, 0,
9662 /*0x34*/ 0, 0, 0, 0,
9663 /*0x38*/ 0, 0, 0, 0,
9664 /*0x3C*/ 0, 0, 0, 0,
9666 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9667 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9668 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9669 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9671 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9672 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9673 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9674 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9676 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9677 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9678 /*0x68*/ 0, 0, 0, 0,
9679 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9681 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9682 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9683 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9686 #endif /* MAC_OSX */
9689 #if TARGET_API_MAC_CARBON
9690 mac_to_emacs_modifiers (UInt32 mods
)
9692 mac_to_emacs_modifiers (EventModifiers mods
)
9695 unsigned int result
= 0;
9696 if (mods
& shiftKey
)
9697 result
|= shift_modifier
;
9699 /* Deactivated to simplify configuration:
9700 if Vmac_option_modifier is non-NIL, we fully process the Option
9701 key. Otherwise, we only process it if an additional Ctrl or Command
9702 is pressed. That way the system may convert the character to a
9704 if ((mods & optionKey) &&
9705 (( !NILP(Vmac_option_modifier) ||
9706 ((mods & cmdKey) || (mods & controlKey))))) */
9708 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9709 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9711 result
|= XUINT(val
);
9713 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9714 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9716 result
|= XUINT(val
);
9718 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9719 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9721 result
|= XUINT(val
);
9725 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9726 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9728 result
|= XUINT(val
);
9736 mac_mapped_modifiers (modifiers
)
9739 UInt32 mapped_modifiers_all
=
9740 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9741 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9742 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9745 mapped_modifiers_all
|=
9746 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9749 return mapped_modifiers_all
& modifiers
;
9753 mac_get_emulated_btn ( UInt32 modifiers
)
9756 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9757 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9758 if (modifiers
& cmdKey
)
9759 result
= cmdIs3
? 2 : 1;
9760 else if (modifiers
& optionKey
)
9761 result
= cmdIs3
? 1 : 2;
9766 #if TARGET_API_MAC_CARBON
9767 /***** Code to handle C-g testing *****/
9768 extern int quit_char
;
9769 extern int make_ctrl_char
P_ ((int));
9772 mac_quit_char_key_p (modifiers
, key_code
)
9773 UInt32 modifiers
, key_code
;
9776 unsigned long some_state
= 0;
9777 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9778 int c
, emacs_modifiers
;
9780 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9781 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9782 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9783 if (char_code
& ~0xff)
9786 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9787 if (emacs_modifiers
& ctrl_modifier
)
9788 c
= make_ctrl_char (char_code
);
9790 c
|= (emacs_modifiers
9791 & (meta_modifier
| alt_modifier
9792 | hyper_modifier
| super_modifier
));
9794 return c
== quit_char
;
9798 #if TARGET_API_MAC_CARBON
9799 /* Obtains the event modifiers from the event ref and then calls
9800 mac_to_emacs_modifiers. */
9802 mac_event_to_emacs_modifiers (EventRef eventRef
)
9804 UInt32 mods
= 0, class;
9806 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9807 sizeof (UInt32
), NULL
, &mods
);
9808 class = GetEventClass (eventRef
);
9809 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9810 (class == kEventClassMouse
|| class == kEventClassCommand
))
9812 mods
&= ~(optionKey
| cmdKey
);
9814 return mac_to_emacs_modifiers (mods
);
9817 /* Given an event ref, return the code to use for the mouse button
9818 code in the emacs input_event. */
9820 mac_get_mouse_btn (EventRef ref
)
9822 EventMouseButton result
= kEventMouseButtonPrimary
;
9823 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9824 sizeof (EventMouseButton
), NULL
, &result
);
9827 case kEventMouseButtonPrimary
:
9828 if (NILP (Vmac_emulate_three_button_mouse
))
9832 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9833 sizeof (UInt32
), NULL
, &mods
);
9834 return mac_get_emulated_btn(mods
);
9836 case kEventMouseButtonSecondary
:
9837 return mac_wheel_button_is_mouse_2
? 2 : 1;
9838 case kEventMouseButtonTertiary
:
9839 case 4: /* 4 is the number for the mouse wheel button */
9840 return mac_wheel_button_is_mouse_2
? 1 : 2;
9846 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9847 events. However the click of the mouse wheel is not converted to a
9848 mouseDown or mouseUp event. Likewise for dead key events. This
9849 calls ConvertEventRefToEventRecord, but then checks to see if it is
9850 a mouse up/down, or a dead key Carbon event that has not been
9851 converted, and if so, converts it by hand (to be picked up in the
9852 XTread_socket loop). */
9853 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9856 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9862 switch (GetEventClass (eventRef
))
9864 case kEventClassMouse
:
9865 switch (GetEventKind (eventRef
))
9867 case kEventMouseDown
:
9868 eventRec
->what
= mouseDown
;
9873 eventRec
->what
= mouseUp
;
9882 case kEventClassKeyboard
:
9883 switch (GetEventKind (eventRef
))
9885 case kEventRawKeyDown
:
9887 goto keystroke_common
;
9888 case kEventRawKeyRepeat
:
9890 goto keystroke_common
;
9891 case kEventRawKeyUp
:
9895 unsigned char char_codes
;
9898 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9899 typeChar
, NULL
, sizeof (char),
9902 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9903 typeUInt32
, NULL
, sizeof (UInt32
),
9907 eventRec
->what
= action
;
9908 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9925 /* Need where and when. */
9928 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9929 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9930 /* Use two step process because new event modifiers are 32-bit
9931 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9932 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9933 NULL
, sizeof (UInt32
), NULL
, &mods
);
9934 eventRec
->modifiers
= mods
;
9936 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9948 Handle menubar_handle
;
9951 menubar_handle
= GetNewMBar (128);
9952 if(menubar_handle
== NULL
)
9954 SetMenuBar (menubar_handle
);
9957 #if !TARGET_API_MAC_CARBON
9958 menu
= GetMenuRef (M_APPLE
);
9960 AppendResMenu (menu
, 'DRVR');
9968 do_init_managers (void)
9970 #if !TARGET_API_MAC_CARBON
9971 InitGraf (&qd
.thePort
);
9973 FlushEvents (everyEvent
, 0);
9978 #endif /* !TARGET_API_MAC_CARBON */
9981 #if !TARGET_API_MAC_CARBON
9982 /* set up some extra stack space for use by emacs */
9983 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9985 /* MaxApplZone must be called for AppleScript to execute more
9986 complicated scripts */
9989 #endif /* !TARGET_API_MAC_CARBON */
9993 do_check_ram_size (void)
9995 SInt32 physical_ram_size
, logical_ram_size
;
9997 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
9998 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
9999 || physical_ram_size
> (1 << VALBITS
)
10000 || logical_ram_size
> (1 << VALBITS
))
10002 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10006 #endif /* MAC_OS8 */
10009 do_window_update (WindowRef win
)
10011 struct frame
*f
= mac_window_to_frame (win
);
10015 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10017 if (win
!= tip_window
)
10019 if (f
->async_visible
== 0)
10021 /* Update events may occur when a frame gets iconified. */
10023 f
->async_visible
= 1;
10024 f
->async_iconified
= 0;
10025 SET_FRAME_GARBAGED (f
);
10031 #if TARGET_API_MAC_CARBON
10032 RgnHandle region
= NewRgn ();
10034 GetPortVisibleRegion (GetWindowPort (win
), region
);
10035 GetRegionBounds (region
, &r
);
10036 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10038 mac_prepare_for_quickdraw (f
);
10040 UpdateControls (win
, region
);
10041 DisposeRgn (region
);
10043 r
= (*win
->visRgn
)->rgnBBox
;
10044 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10045 UpdateControls (win
, win
->visRgn
);
10054 is_emacs_window (WindowRef win
)
10056 Lisp_Object tail
, frame
;
10061 FOR_EACH_FRAME (tail
, frame
)
10062 if (FRAME_MAC_P (XFRAME (frame
)))
10063 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10074 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10076 err
= ActivateTSMDocument (tsm_document_id
);
10080 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10081 && EQ (saved_ts_script_language_on_focus
, Qt
))
10082 slptr
= &saved_ts_language
;
10083 else if (CONSP (Vmac_ts_script_language_on_focus
)
10084 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10085 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10086 && CONSP (saved_ts_script_language_on_focus
)
10087 && EQ (XCAR (saved_ts_script_language_on_focus
),
10088 XCAR (Vmac_ts_script_language_on_focus
))
10089 && EQ (XCDR (saved_ts_script_language_on_focus
),
10090 XCDR (Vmac_ts_script_language_on_focus
)))
10092 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10093 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10100 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10101 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10102 kKeyboardInputMethodClass
);
10104 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10107 err
= SetTextServiceLanguage (slptr
);
10109 /* Seems to be needed on Mac OS X 10.2. */
10111 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10121 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10123 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10125 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10127 err
= GetTextServiceLanguage (&saved_ts_language
);
10129 slptr
= &saved_ts_language
;
10131 else if (CONSP (Vmac_ts_script_language_on_focus
)
10132 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10133 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10135 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10136 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10142 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10143 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10144 kKeyboardInputMethodClass
);
10146 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10150 err
= DeactivateTSMDocument (tsm_document_id
);
10156 #if !TARGET_API_MAC_CARBON
10158 do_apple_menu (SInt16 menu_item
)
10161 SInt16 da_driver_refnum
;
10163 if (menu_item
== I_ABOUT
)
10164 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10167 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10168 da_driver_refnum
= OpenDeskAcc (item_name
);
10171 #endif /* !TARGET_API_MAC_CARBON */
10173 /* Handle drags in size box. Based on code contributed by Ben
10174 Mesander and IM - Window Manager A. */
10177 do_grow_window (w
, e
)
10179 const EventRecord
*e
;
10182 int rows
, columns
, width
, height
;
10183 struct frame
*f
= mac_window_to_frame (w
);
10184 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10185 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10186 #if TARGET_API_MAC_CARBON
10192 if (size_hints
->flags
& PMinSize
)
10194 min_width
= size_hints
->min_width
;
10195 min_height
= size_hints
->min_height
;
10197 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10199 #if TARGET_API_MAC_CARBON
10200 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10202 height
= new_rect
.bottom
- new_rect
.top
;
10203 width
= new_rect
.right
- new_rect
.left
;
10205 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10206 /* see if it really changed size */
10207 if (grow_size
== 0)
10209 height
= HiWord (grow_size
);
10210 width
= LoWord (grow_size
);
10213 if (width
!= FRAME_PIXEL_WIDTH (f
)
10214 || height
!= FRAME_PIXEL_HEIGHT (f
))
10216 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10217 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10219 x_set_window_size (f
, 0, columns
, rows
);
10224 #if TARGET_API_MAC_CARBON
10226 mac_get_ideal_size (f
)
10229 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10230 WindowRef w
= FRAME_MAC_WINDOW (f
);
10232 Rect standard_rect
;
10233 int height
, width
, columns
, rows
;
10235 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10236 ideal_size
.v
= dpyinfo
->height
;
10237 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10238 /* Adjust the standard size according to character boundaries. */
10239 width
= standard_rect
.right
- standard_rect
.left
;
10240 height
= standard_rect
.bottom
- standard_rect
.top
;
10241 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10242 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10243 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10244 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10250 /* Handle clicks in zoom box. Calculation of "standard state" based
10251 on code in IM - Window Manager A and code contributed by Ben
10252 Mesander. The standard state of an Emacs window is 80-characters
10253 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10256 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10258 Rect zoom_rect
, port_rect
;
10260 struct frame
*f
= mac_window_to_frame (w
);
10261 #if TARGET_API_MAC_CARBON
10262 Point ideal_size
= mac_get_ideal_size (f
);
10264 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10265 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10266 && port_rect
.left
== zoom_rect
.left
10267 && port_rect
.top
== zoom_rect
.top
)
10268 zoom_in_or_out
= inZoomIn
;
10270 zoom_in_or_out
= inZoomOut
;
10273 mac_clear_window (f
);
10275 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10276 #else /* not TARGET_API_MAC_CARBON */
10279 int w_title_height
, rows
;
10280 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10282 GetPort (&save_port
);
10284 SetPortWindowPort (w
);
10286 /* Clear window to avoid flicker. */
10287 EraseRect (&(w
->portRect
));
10288 if (zoom_in_or_out
== inZoomOut
)
10290 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10291 LocalToGlobal (&top_left
);
10293 /* calculate height of window's title bar */
10294 w_title_height
= top_left
.v
- 1
10295 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10297 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10298 zoom_rect
= qd
.screenBits
.bounds
;
10299 zoom_rect
.top
+= w_title_height
;
10300 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10302 zoom_rect
.right
= zoom_rect
.left
10303 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10305 /* Adjust the standard size according to character boundaries. */
10306 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10308 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10310 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10314 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10316 SetPort (save_port
);
10317 #endif /* not TARGET_API_MAC_CARBON */
10319 #if !TARGET_API_MAC_CARBON
10320 /* retrieve window size and update application values */
10321 port_rect
= w
->portRect
;
10322 height
= port_rect
.bottom
- port_rect
.top
;
10323 width
= port_rect
.right
- port_rect
.left
;
10325 mac_handle_size_change (f
, width
, height
);
10326 mac_handle_origin_change (f
);
10331 mac_set_unicode_keystroke_event (code
, buf
)
10333 struct input_event
*buf
;
10335 int charset_id
, c1
, c2
;
10339 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10342 else if (code
< 0x100)
10345 charset_id
= CHARSET_8_BIT_CONTROL
;
10347 charset_id
= charset_latin_iso8859_1
;
10348 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10349 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10354 charset_id
= charset_mule_unicode_0100_24ff
,
10356 else if (code
< 0x33FF)
10357 charset_id
= charset_mule_unicode_2500_33ff
,
10359 else if (code
>= 0xE000)
10360 charset_id
= charset_mule_unicode_e000_ffff
,
10362 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10363 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10364 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10369 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10371 unsigned char char_code
;
10372 UInt32 key_code
, modifiers
;
10373 unsigned long timestamp
;
10374 struct input_event
*buf
;
10376 static SInt16 last_key_script
= -1;
10377 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10378 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10381 if (mapped_modifiers
& kEventKeyModifierFnMask
10382 && key_code
<= 0x7f
10383 && fn_keycode_to_keycode_table
[key_code
])
10384 key_code
= fn_keycode_to_keycode_table
[key_code
];
10387 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10389 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10390 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10392 if (modifiers
& kEventKeyModifierFnMask
10393 && key_code
<= 0x7f
10394 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10395 modifiers
&= ~kEventKeyModifierFnMask
;
10398 else if (mapped_modifiers
)
10400 /* translate the keycode back to determine the original key */
10402 UCKeyboardLayout
*uchr_ptr
= NULL
;
10403 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10405 KeyboardLayoutRef layout
;
10407 err
= KLGetCurrentKeyboardLayout (&layout
);
10409 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10410 (const void **) &uchr_ptr
);
10412 static SInt16 last_key_layout_id
= 0;
10413 static Handle uchr_handle
= (Handle
)-1;
10414 SInt16 current_key_layout_id
=
10415 GetScriptVariable (current_key_script
, smScriptKeys
);
10417 if (uchr_handle
== (Handle
)-1
10418 || last_key_layout_id
!= current_key_layout_id
)
10420 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10421 last_key_layout_id
= current_key_layout_id
;
10424 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10430 UInt16 key_action
= action
- keyDown
;
10431 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10432 UInt32 keyboard_type
= LMGetKbdType ();
10433 SInt32 dead_key_state
= 0;
10435 UniCharCount actual_length
;
10437 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10438 modifier_key_state
, keyboard_type
,
10439 kUCKeyTranslateNoDeadKeysMask
,
10441 1, &actual_length
, &code
);
10442 if (status
== noErr
&& actual_length
== 1)
10443 mac_set_unicode_keystroke_event (code
, buf
);
10445 #endif /* MAC_OSX */
10447 if (buf
->kind
== NO_EVENT
)
10449 /* This code comes from Keyboard Resource, Appendix C of IM
10450 - Text. This is necessary since shift is ignored in KCHR
10451 table translation when option or command is pressed. It
10452 also does not translate correctly control-shift chars
10453 like C-% so mask off shift here also. */
10454 /* Mask off modifier keys that are mapped to some Emacs
10456 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10457 /* set high byte of keycode to modifier high byte*/
10458 int new_key_code
= key_code
| new_modifiers
;
10459 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10460 unsigned long some_state
= 0;
10461 UInt32 new_char_code
;
10463 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10464 if (new_char_code
== 0)
10465 /* Seems like a dead key. Append up-stroke. */
10466 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10470 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10471 buf
->code
= new_char_code
& 0xff;
10476 if (buf
->kind
== NO_EVENT
)
10478 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10479 buf
->code
= char_code
;
10482 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10483 buf
->modifiers
|= (extra_keyboard_modifiers
10484 & (meta_modifier
| alt_modifier
10485 | hyper_modifier
| super_modifier
));
10487 #if TARGET_API_MAC_CARBON
10488 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10489 && buf
->code
>= 0x80 && buf
->modifiers
)
10492 TextEncoding encoding
= kTextEncodingMacRoman
;
10493 TextToUnicodeInfo ttu_info
;
10495 UpgradeScriptInfoToTextEncoding (current_key_script
,
10496 kTextLanguageDontCare
,
10497 kTextRegionDontCare
,
10499 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10504 ByteCount unicode_len
;
10507 pstr
[1] = buf
->code
;
10508 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10510 &unicode_len
, &code
);
10511 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10512 mac_set_unicode_keystroke_event (code
, buf
);
10513 DisposeTextToUnicodeInfo (&ttu_info
);
10518 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10519 && buf
->code
>= 0x80
10520 && last_key_script
!= current_key_script
)
10522 struct input_event event
;
10524 EVENT_INIT (event
);
10525 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10527 event
.code
= current_key_script
;
10528 event
.timestamp
= timestamp
;
10529 kbd_buffer_store_event (&event
);
10530 last_key_script
= current_key_script
;
10535 mac_store_apple_event (class, id
, desc
)
10536 Lisp_Object
class, id
;
10537 const AEDesc
*desc
;
10539 struct input_event buf
;
10543 buf
.kind
= MAC_APPLE_EVENT
;
10546 XSETFRAME (buf
.frame_or_window
,
10547 mac_focus_frame (&one_mac_display_info
));
10548 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10549 is safe to use them during read_socket_hook. */
10550 buf
.arg
= mac_aedesc_to_lisp (desc
);
10551 kbd_buffer_store_event (&buf
);
10554 #if TARGET_API_MAC_CARBON
10556 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10557 event
, num_params
, names
, types
)
10558 AEEventClass
class;
10560 Lisp_Object class_key
, id_key
;
10563 const EventParamName
*names
;
10564 const EventParamType
*types
;
10566 OSStatus err
= eventNotHandledErr
;
10567 Lisp_Object binding
;
10569 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10570 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10572 if (INTEGERP (binding
))
10573 err
= XINT (binding
);
10576 AppleEvent apple_event
;
10577 err
= create_apple_event_from_event_ref (event
, num_params
,
10582 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10583 AEDisposeDesc (&apple_event
);
10584 mac_wakeup_from_rne ();
10593 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10597 const AEDesc
*desc
;
10599 struct input_event buf
;
10603 buf
.kind
= DRAG_N_DROP_EVENT
;
10604 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10605 buf
.timestamp
= TickCount () * (1000 / 60);
10606 XSETINT (buf
.x
, mouse_pos
.h
);
10607 XSETINT (buf
.y
, mouse_pos
.v
);
10608 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10609 buf
.arg
= mac_aedesc_to_lisp (desc
);
10610 kbd_buffer_store_event (&buf
);
10615 mac_store_service_event (event
)
10619 Lisp_Object id_key
;
10621 const EventParamName
*names
;
10622 const EventParamType
*types
;
10623 static const EventParamName names_pfm
[] =
10624 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10625 static const EventParamType types_pfm
[] =
10626 {typeCFStringRef
, typeCFStringRef
};
10628 switch (GetEventKind (event
))
10630 case kEventServicePaste
:
10637 case kEventServicePerform
:
10639 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10648 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10654 #endif /* MAC_OSX */
10656 static pascal OSStatus
10657 mac_handle_window_event (next_handler
, event
, data
)
10658 EventHandlerCallRef next_handler
;
10663 OSStatus err
, result
= eventNotHandledErr
;
10666 XSizeHints
*size_hints
;
10668 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
10669 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10671 return eventNotHandledErr
;
10673 f
= mac_window_to_frame (wp
);
10674 switch (GetEventKind (event
))
10676 /* -- window refresh events -- */
10678 case kEventWindowUpdate
:
10679 result
= CallNextEventHandler (next_handler
, event
);
10680 if (result
!= eventNotHandledErr
)
10683 do_window_update (wp
);
10687 /* -- window state change events -- */
10689 case kEventWindowShowing
:
10690 size_hints
= FRAME_SIZE_HINTS (f
);
10691 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
10693 struct frame
*sf
= SELECTED_FRAME ();
10695 if (!(FRAME_MAC_P (sf
)))
10696 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
10699 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
10700 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10701 kWindowCascadeStartAtParentWindowScreen
10703 kWindowCascadeOnParentWindowScreen
10706 #if USE_MAC_TOOLBAR
10707 /* This is a workaround. RepositionWindow fails to put
10708 a window at the cascading position when its parent
10709 window has a Carbon HIToolbar. */
10710 if (f
->top_pos
== sf
->top_pos
&& f
->left_pos
== sf
->left_pos
)
10711 MoveWindowStructure (wp
, f
->left_pos
+ 10, f
->top_pos
+ 32);
10718 case kEventWindowHiding
:
10719 /* Before unmapping the window, update the WM_SIZE_HINTS
10720 property to claim that the current position of the window is
10721 user-specified, rather than program-specified, so that when
10722 the window is mapped again, it will be placed at the same
10723 location, without forcing the user to position it by hand
10724 again (they have already done that once for this window.) */
10725 x_wm_set_size_hint (f
, (long) 0, 1);
10729 case kEventWindowShown
:
10730 case kEventWindowHidden
:
10731 case kEventWindowCollapsed
:
10732 case kEventWindowExpanded
:
10733 mac_handle_visibility_change (f
);
10737 case kEventWindowBoundsChanging
:
10738 result
= CallNextEventHandler (next_handler
, event
);
10739 if (result
!= eventNotHandledErr
)
10742 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10743 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10747 size_hints
= FRAME_SIZE_HINTS (f
);
10748 if ((attributes
& kWindowBoundsChangeUserResize
)
10749 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
10750 == (PResizeInc
| PBaseSize
| PMinSize
)))
10755 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10756 typeQDRectangle
, NULL
, sizeof (Rect
),
10761 width
= bounds
.right
- bounds
.left
;
10762 height
= bounds
.bottom
- bounds
.top
;
10764 if (width
< size_hints
->min_width
)
10765 width
= size_hints
->min_width
;
10767 width
= size_hints
->base_width
10768 + (int) ((width
- size_hints
->base_width
)
10769 / (float) size_hints
->width_inc
+ .5)
10770 * size_hints
->width_inc
;
10772 if (height
< size_hints
->min_height
)
10773 height
= size_hints
->min_height
;
10775 height
= size_hints
->base_height
10776 + (int) ((height
- size_hints
->base_height
)
10777 / (float) size_hints
->height_inc
+ .5)
10778 * size_hints
->height_inc
;
10780 bounds
.right
= bounds
.left
+ width
;
10781 bounds
.bottom
= bounds
.top
+ height
;
10782 SetEventParameter (event
, kEventParamCurrentBounds
,
10783 typeQDRectangle
, sizeof (Rect
), &bounds
);
10788 case kEventWindowBoundsChanged
:
10789 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10790 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10794 if (attributes
& kWindowBoundsChangeSizeChanged
)
10798 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10799 typeQDRectangle
, NULL
, sizeof (Rect
),
10805 width
= bounds
.right
- bounds
.left
;
10806 height
= bounds
.bottom
- bounds
.top
;
10807 mac_handle_size_change (f
, width
, height
);
10808 mac_wakeup_from_rne ();
10812 if (attributes
& kWindowBoundsChangeOriginChanged
)
10813 mac_handle_origin_change (f
);
10818 /* -- window action events -- */
10820 case kEventWindowClose
:
10822 struct input_event buf
;
10825 buf
.kind
= DELETE_WINDOW_EVENT
;
10826 XSETFRAME (buf
.frame_or_window
, f
);
10828 kbd_buffer_store_event (&buf
);
10833 case kEventWindowGetIdealSize
:
10834 result
= CallNextEventHandler (next_handler
, event
);
10835 if (result
!= eventNotHandledErr
)
10839 Point ideal_size
= mac_get_ideal_size (f
);
10841 err
= SetEventParameter (event
, kEventParamDimensions
,
10842 typeQDPoint
, sizeof (Point
), &ideal_size
);
10849 case kEventWindowToolbarSwitchMode
:
10851 static const EventParamName names
[] = {kEventParamDirectObject
,
10852 kEventParamWindowMouseLocation
,
10853 kEventParamKeyModifiers
,
10854 kEventParamMouseButton
,
10855 kEventParamClickCount
,
10856 kEventParamMouseChord
};
10857 static const EventParamType types
[] = {typeWindowRef
,
10863 int num_params
= sizeof (names
) / sizeof (names
[0]);
10865 err
= mac_store_event_ref_as_apple_event (0, 0,
10867 Qtoolbar_switch_mode
,
10877 /* -- window focus events -- */
10879 case kEventWindowFocusAcquired
:
10880 err
= mac_tsm_resume ();
10885 case kEventWindowFocusRelinquish
:
10886 err
= mac_tsm_suspend ();
10899 static pascal OSStatus
10900 mac_handle_application_event (next_handler
, event
, data
)
10901 EventHandlerCallRef next_handler
;
10905 OSStatus err
, result
= eventNotHandledErr
;
10907 switch (GetEventKind (event
))
10910 case kEventAppActivated
:
10911 err
= mac_tsm_resume ();
10914 case kEventAppDeactivated
:
10915 err
= mac_tsm_suspend ();
10929 static pascal OSStatus
10930 mac_handle_keyboard_event (next_handler
, event
, data
)
10931 EventHandlerCallRef next_handler
;
10935 OSStatus err
, result
= eventNotHandledErr
;
10936 UInt32 event_kind
, key_code
, modifiers
, mapped_modifiers
;
10937 unsigned char char_code
;
10939 event_kind
= GetEventKind (event
);
10940 switch (event_kind
)
10942 case kEventRawKeyDown
:
10943 case kEventRawKeyRepeat
:
10944 case kEventRawKeyUp
:
10945 if (read_socket_inev
== NULL
)
10947 result
= CallNextEventHandler (next_handler
, event
);
10951 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
10953 sizeof (UInt32
), NULL
, &modifiers
);
10957 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10959 /* When using Carbon Events, we need to pass raw keyboard events
10960 to the TSM ourselves. If TSM handles it, it will pass back
10961 noErr, otherwise it will pass back "eventNotHandledErr" and
10962 we can process it normally. */
10963 if (!(mapped_modifiers
10964 & ~(mac_pass_command_to_system
? cmdKey
: 0)
10965 & ~(mac_pass_control_to_system
? controlKey
: 0)))
10967 result
= CallNextEventHandler (next_handler
, event
);
10968 if (result
!= eventNotHandledErr
)
10973 if (read_socket_inev
->kind
!= NO_EVENT
)
10980 if (event_kind
== kEventRawKeyUp
)
10983 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
10985 sizeof (char), NULL
, &char_code
);
10989 err
= GetEventParameter (event
, kEventParamKeyCode
,
10991 sizeof (UInt32
), NULL
, &key_code
);
10995 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
10996 char_code
, key_code
, modifiers
,
10998 (GetEventTime (event
) / kEventDurationMillisecond
)),
11010 static pascal OSStatus
11011 mac_handle_command_event (next_handler
, event
, data
)
11012 EventHandlerCallRef next_handler
;
11016 OSStatus err
, result
= eventNotHandledErr
;
11018 static const EventParamName names
[] =
11019 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11020 static const EventParamType types
[] =
11021 {typeHICommand
, typeUInt32
};
11022 int num_params
= sizeof (names
) / sizeof (names
[0]);
11024 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11025 NULL
, sizeof (HICommand
), NULL
, &command
);
11027 return eventNotHandledErr
;
11029 switch (GetEventKind (event
))
11031 case kEventCommandProcess
:
11032 result
= CallNextEventHandler (next_handler
, event
);
11033 if (result
!= eventNotHandledErr
)
11036 err
= GetEventParameter (event
, kEventParamDirectObject
,
11037 typeHICommand
, NULL
,
11038 sizeof (HICommand
), NULL
, &command
);
11040 if (err
!= noErr
|| command
.commandID
== 0)
11043 /* A HI command event is mapped to an Apple event whose event
11044 class symbol is `hi-command' and event ID is its command
11046 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11061 static pascal OSStatus
11062 mac_handle_mouse_event (next_handler
, event
, data
)
11063 EventHandlerCallRef next_handler
;
11067 OSStatus err
, result
= eventNotHandledErr
;
11069 switch (GetEventKind (event
))
11071 case kEventMouseWheelMoved
:
11075 EventMouseWheelAxis axis
;
11079 result
= CallNextEventHandler (next_handler
, event
);
11080 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11083 f
= mac_focus_frame (&one_mac_display_info
);
11085 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11086 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11088 || wp
!= FRAME_MAC_WINDOW (f
))
11091 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11092 typeMouseWheelAxis
, NULL
,
11093 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11094 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11097 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11098 typeQDPoint
, NULL
, sizeof (Point
),
11103 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11104 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11105 if (point
.h
< 0 || point
.v
< 0
11106 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11107 f
->tool_bar_window
))
11110 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11111 typeSInt32
, NULL
, sizeof (SInt32
),
11116 read_socket_inev
->kind
= WHEEL_EVENT
;
11117 read_socket_inev
->code
= 0;
11118 read_socket_inev
->modifiers
=
11119 (mac_event_to_emacs_modifiers (event
)
11120 | ((delta
< 0) ? down_modifier
: up_modifier
));
11121 XSETINT (read_socket_inev
->x
, point
.h
);
11122 XSETINT (read_socket_inev
->y
, point
.v
);
11123 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11137 static pascal OSStatus
11138 mac_handle_text_input_event (next_handler
, event
, data
)
11139 EventHandlerCallRef next_handler
;
11143 OSStatus result
, err
= noErr
;
11144 Lisp_Object id_key
= Qnil
;
11146 const EventParamName
*names
;
11147 const EventParamType
*types
;
11148 static UInt32 seqno_uaia
= 0;
11149 static const EventParamName names_uaia
[] =
11150 {kEventParamTextInputSendComponentInstance
,
11151 kEventParamTextInputSendRefCon
,
11152 kEventParamTextInputSendSLRec
,
11153 kEventParamTextInputSendFixLen
,
11154 kEventParamTextInputSendText
,
11155 kEventParamTextInputSendUpdateRng
,
11156 kEventParamTextInputSendHiliteRng
,
11157 kEventParamTextInputSendClauseRng
,
11158 kEventParamTextInputSendPinRng
,
11159 kEventParamTextInputSendTextServiceEncoding
,
11160 kEventParamTextInputSendTextServiceMacEncoding
,
11161 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11162 static const EventParamType types_uaia
[] =
11163 {typeComponentInstance
,
11165 typeIntlWritingCode
,
11172 typeTextRangeArray
,
11173 typeTextRangeArray
,
11179 static const EventParamName names_ufke
[] =
11180 {kEventParamTextInputSendComponentInstance
,
11181 kEventParamTextInputSendRefCon
,
11182 kEventParamTextInputSendSLRec
,
11183 kEventParamTextInputSendText
};
11184 static const EventParamType types_ufke
[] =
11185 {typeComponentInstance
,
11187 typeIntlWritingCode
,
11190 result
= CallNextEventHandler (next_handler
, event
);
11191 if (result
!= eventNotHandledErr
)
11194 switch (GetEventKind (event
))
11196 case kEventTextInputUpdateActiveInputArea
:
11197 id_key
= Qupdate_active_input_area
;
11198 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11199 names
= names_uaia
;
11200 types
= types_uaia
;
11201 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11202 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11206 case kEventTextInputUnicodeForKeyEvent
:
11208 EventRef kbd_event
;
11209 UInt32 actual_size
, modifiers
;
11211 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11212 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11215 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11217 sizeof (UInt32
), NULL
, &modifiers
);
11218 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11219 /* There're mapped modifier keys. Process it in
11221 return eventNotHandledErr
;
11223 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11224 typeUnicodeText
, NULL
, 0, &actual_size
,
11226 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11230 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11231 typeUnicodeText
, NULL
,
11232 sizeof (UniChar
), NULL
, &code
);
11233 if (err
== noErr
&& code
< 0x80)
11235 /* ASCII character. Process it in do_keystroke. */
11236 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11240 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11241 typeUInt32
, NULL
, sizeof (UInt32
),
11243 if (!(err
== noErr
&& key_code
<= 0x7f
11244 && keycode_to_xkeysym_table
[key_code
]))
11247 mac_focus_frame (&one_mac_display_info
);
11249 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11250 read_socket_inev
->code
= code
;
11251 read_socket_inev
->modifiers
=
11252 mac_to_emacs_modifiers (modifiers
);
11253 read_socket_inev
->modifiers
|=
11254 (extra_keyboard_modifiers
11255 & (meta_modifier
| alt_modifier
11256 | hyper_modifier
| super_modifier
));
11257 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11260 return eventNotHandledErr
;
11264 /* Non-ASCII keystrokes without mapped modifiers are processed
11265 at the Lisp level. */
11266 id_key
= Qunicode_for_key_event
;
11267 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11268 names
= names_ufke
;
11269 types
= types_ufke
;
11272 case kEventTextInputOffsetToPos
:
11278 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11279 return eventNotHandledErr
;
11281 /* Strictly speaking, this is not always correct because
11282 previous events may change some states about display. */
11283 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11285 /* Active input area is displayed in the echo area. */
11286 w
= XWINDOW (echo_area_window
);
11287 f
= WINDOW_XFRAME (w
);
11291 /* Active input area is displayed around the current point. */
11292 f
= SELECTED_FRAME ();
11293 w
= XWINDOW (f
->selected_window
);
11296 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11297 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11298 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11299 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11300 + FONT_BASE (FRAME_FONT (f
))
11301 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11302 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11303 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11311 if (!NILP (id_key
))
11312 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11321 #endif /* TARGET_API_MAC_CARBON */
11325 install_window_handler (window
)
11328 OSStatus err
= noErr
;
11330 #if TARGET_API_MAC_CARBON
11333 static const EventTypeSpec specs
[] =
11335 /* -- window refresh events -- */
11336 {kEventClassWindow
, kEventWindowUpdate
},
11337 /* -- window state change events -- */
11338 {kEventClassWindow
, kEventWindowShowing
},
11339 {kEventClassWindow
, kEventWindowHiding
},
11340 {kEventClassWindow
, kEventWindowShown
},
11341 {kEventClassWindow
, kEventWindowHidden
},
11342 {kEventClassWindow
, kEventWindowCollapsed
},
11343 {kEventClassWindow
, kEventWindowExpanded
},
11344 {kEventClassWindow
, kEventWindowBoundsChanging
},
11345 {kEventClassWindow
, kEventWindowBoundsChanged
},
11346 /* -- window action events -- */
11347 {kEventClassWindow
, kEventWindowClose
},
11348 {kEventClassWindow
, kEventWindowGetIdealSize
},
11350 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11353 /* -- window focus events -- */
11354 {kEventClassWindow
, kEventWindowFocusAcquired
},
11355 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11358 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11360 if (handle_window_eventUPP
== NULL
)
11361 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11363 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11364 GetEventTypeCount (specs
),
11365 specs
, NULL
, NULL
);
11370 err
= install_drag_handler (window
);
11376 remove_window_handler (window
)
11379 remove_drag_handler (window
);
11382 #if TARGET_API_MAC_CARBON
11384 install_application_handler ()
11386 OSStatus err
= noErr
;
11390 static const EventTypeSpec specs
[] = {
11392 {kEventClassApplication
, kEventAppActivated
},
11393 {kEventClassApplication
, kEventAppDeactivated
},
11397 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11398 (mac_handle_application_event
),
11399 GetEventTypeCount (specs
),
11400 specs
, NULL
, NULL
);
11405 static const EventTypeSpec specs
[] =
11406 {{kEventClassKeyboard
, kEventRawKeyDown
},
11407 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11408 {kEventClassKeyboard
, kEventRawKeyUp
}};
11410 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11411 (mac_handle_keyboard_event
),
11412 GetEventTypeCount (specs
),
11413 specs
, NULL
, NULL
);
11418 static const EventTypeSpec specs
[] =
11419 {{kEventClassCommand
, kEventCommandProcess
}};
11421 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11422 (mac_handle_command_event
),
11423 GetEventTypeCount (specs
),
11424 specs
, NULL
, NULL
);
11429 static const EventTypeSpec specs
[] =
11430 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11432 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11433 (mac_handle_mouse_event
),
11434 GetEventTypeCount (specs
),
11435 specs
, NULL
, NULL
);
11441 static const EventTypeSpec spec
[] =
11442 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11443 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11444 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11446 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11447 (mac_handle_text_input_event
),
11448 GetEventTypeCount (spec
),
11454 err
= install_menu_target_item_handler ();
11458 err
= install_service_handler ();
11466 mac_handle_dm_notification (event
)
11469 mac_screen_config_changed
= 1;
11472 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11474 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11475 CGDirectDisplayID display
;
11476 CGDisplayChangeSummaryFlags flags
;
11479 mac_screen_config_changed
= 1;
11484 init_dm_notification_handler ()
11488 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11489 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11490 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11493 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11496 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11497 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11499 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11500 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11502 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11503 ProcessSerialNumber psn
;
11505 if (handle_dm_notificationUPP
== NULL
)
11506 handle_dm_notificationUPP
=
11507 NewDMNotificationUPP (mac_handle_dm_notification
);
11509 err
= GetCurrentProcess (&psn
);
11511 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11519 mac_get_screen_info (dpyinfo
)
11520 struct mac_display_info
*dpyinfo
;
11523 /* HasDepth returns true if it is possible to have a 32 bit display,
11524 but this may not be what is actually used. Mac OSX can do better. */
11525 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11526 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11529 CGDisplayCount ndisps
;
11530 CGDirectDisplayID
*displays
;
11532 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11535 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11536 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11540 CGRect bounds
= CGRectZero
;
11542 while (ndisps
-- > 0)
11543 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11544 dpyinfo
->height
= CGRectGetHeight (bounds
);
11545 dpyinfo
->width
= CGRectGetWidth (bounds
);
11549 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11550 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11553 #else /* !MAC_OSX */
11555 GDHandle gdh
= GetMainDevice ();
11556 Rect rect
= (**gdh
).gdRect
;
11558 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11559 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11560 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11563 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11564 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11565 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11567 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11568 dpyinfo
->width
= rect
.right
- rect
.left
;
11570 #endif /* !MAC_OSX */
11576 profiler_exit_proc ()
11578 ProfilerDump ("\pEmacs.prof");
11583 /* These few functions implement Emacs as a normal Mac application
11584 (almost): set up the heap and the Toolbox, handle necessary system
11585 events plus a few simple menu events. They also set up Emacs's
11586 access to functions defined in the rest of this file. Emacs uses
11587 function hooks to perform all its terminal I/O. A complete list of
11588 these functions appear in termhooks.h. For what they do, read the
11589 comments there and see also w32term.c and xterm.c. What's
11590 noticeably missing here is the event loop, which is normally
11591 present in most Mac application. After performing the necessary
11592 Mac initializations, main passes off control to emacs_main
11593 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11594 (defined further below) to read input. This is where
11595 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11602 #if __profile__ /* is the profiler on? */
11603 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11608 /* set creator and type for files created by MSL */
11609 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11613 do_init_managers ();
11617 #ifndef USE_LSB_TAG
11618 do_check_ram_size ();
11621 init_emacs_passwd_dir ();
11625 init_coercion_handler ();
11627 initialize_applescript ();
11629 init_apple_event_handler ();
11631 init_dm_notification_handler ();
11637 /* set up argv array from STR# resource */
11638 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
11642 /* free up AppleScript resources on exit */
11643 atexit (terminate_applescript
);
11645 #if __profile__ /* is the profiler on? */
11646 atexit (profiler_exit_proc
);
11649 /* 3rd param "envp" never used in emacs_main */
11650 (void) emacs_main (argc
, argv
, 0);
11653 /* Never reached - real exit in Fkill_emacs */
11658 #if !TARGET_API_MAC_CARBON
11659 static RgnHandle mouse_region
= NULL
;
11662 mac_wait_next_event (er
, sleep_time
, dequeue
)
11667 static EventRecord er_buf
= {nullEvent
};
11668 UInt32 target_tick
, current_tick
;
11669 EventMask event_mask
;
11671 if (mouse_region
== NULL
)
11672 mouse_region
= NewRgn ();
11674 event_mask
= everyEvent
;
11675 if (!mac_ready_for_apple_events
)
11676 event_mask
-= highLevelEventMask
;
11678 current_tick
= TickCount ();
11679 target_tick
= current_tick
+ sleep_time
;
11681 if (er_buf
.what
== nullEvent
)
11682 while (!WaitNextEvent (event_mask
, &er_buf
,
11683 target_tick
- current_tick
, mouse_region
))
11685 current_tick
= TickCount ();
11686 if (target_tick
<= current_tick
)
11692 er_buf
.what
= nullEvent
;
11695 #endif /* not TARGET_API_MAC_CARBON */
11697 #if TARGET_API_MAC_CARBON
11699 mac_post_mouse_moved_event ()
11701 EventRef event
= NULL
;
11704 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
11705 kEventAttributeNone
, &event
);
11710 GetGlobalMouse (&mouse_pos
);
11711 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
11712 sizeof (Point
), &mouse_pos
);
11716 UInt32 modifiers
= GetCurrentKeyModifiers ();
11718 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
11719 sizeof (UInt32
), &modifiers
);
11722 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
11723 kEventPriorityStandard
);
11725 ReleaseEvent (event
);
11731 /* Emacs calls this whenever it wants to read an input event from the
11734 XTread_socket (sd
, expected
, hold_quit
)
11736 struct input_event
*hold_quit
;
11738 struct input_event inev
;
11740 #if TARGET_API_MAC_CARBON
11742 EventTargetRef toolbox_dispatcher
;
11745 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11747 if (interrupt_input_blocked
)
11749 interrupt_input_pending
= 1;
11753 interrupt_input_pending
= 0;
11756 /* So people can tell when we have read the available input. */
11757 input_signal_count
++;
11761 #if TARGET_API_MAC_CARBON
11762 toolbox_dispatcher
= GetEventDispatcherTarget ();
11766 mac_prepare_for_quickdraw (NULL
),
11768 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
11769 kEventRemoveFromQueue
, &eventRef
))
11770 #else /* !TARGET_API_MAC_CARBON */
11771 while (mac_wait_next_event (&er
, 0, true))
11772 #endif /* !TARGET_API_MAC_CARBON */
11776 unsigned long timestamp
;
11779 inev
.kind
= NO_EVENT
;
11782 #if TARGET_API_MAC_CARBON
11783 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
11785 if (!mac_convert_event_ref (eventRef
, &er
))
11787 #else /* !TARGET_API_MAC_CARBON */
11788 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
11789 #endif /* !TARGET_API_MAC_CARBON */
11796 WindowRef window_ptr
;
11797 ControlPartCode part_code
;
11798 int tool_bar_p
= 0;
11800 #if TARGET_API_MAC_CARBON
11803 /* This is needed to send mouse events like aqua window
11804 buttons to the correct handler. */
11805 read_socket_inev
= &inev
;
11806 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11807 read_socket_inev
= NULL
;
11808 if (err
!= eventNotHandledErr
)
11811 last_mouse_glyph_frame
= 0;
11813 if (dpyinfo
->grabbed
&& last_mouse_frame
11814 && FRAME_LIVE_P (last_mouse_frame
))
11816 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
11817 part_code
= inContent
;
11821 part_code
= FindWindow (er
.where
, &window_ptr
);
11822 if (tip_window
&& window_ptr
== tip_window
)
11824 HideWindow (tip_window
);
11825 part_code
= FindWindow (er
.where
, &window_ptr
);
11829 if (er
.what
!= mouseDown
&&
11830 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
11836 f
= mac_focus_frame (dpyinfo
);
11837 saved_menu_event_location
= er
.where
;
11838 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
11839 XSETFRAME (inev
.frame_or_window
, f
);
11844 #if TARGET_API_MAC_CARBON
11845 FrontNonFloatingWindow ()
11850 || (mac_window_to_frame (window_ptr
)
11851 != dpyinfo
->x_focus_frame
))
11852 SelectWindow (window_ptr
);
11855 ControlPartCode control_part_code
;
11859 ControlKind control_kind
;
11862 f
= mac_window_to_frame (window_ptr
);
11863 /* convert to local coordinates of new window */
11864 mouse_loc
.h
= (er
.where
.h
11866 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
11867 mouse_loc
.v
= (er
.where
.v
11869 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
11870 #if TARGET_API_MAC_CARBON
11871 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
11872 &control_part_code
);
11875 GetControlKind (ch
, &control_kind
);
11878 control_part_code
= FindControl (mouse_loc
, window_ptr
,
11882 #if TARGET_API_MAC_CARBON
11883 inev
.code
= mac_get_mouse_btn (eventRef
);
11884 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
11886 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
11887 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
11889 XSETINT (inev
.x
, mouse_loc
.h
);
11890 XSETINT (inev
.y
, mouse_loc
.v
);
11892 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
11894 #ifndef USE_TOOLKIT_SCROLL_BARS
11895 /* control_part_code becomes kControlNoPart if
11896 a progress indicator is clicked. */
11897 && control_part_code
!= kControlNoPart
11898 #else /* USE_TOOLKIT_SCROLL_BARS */
11900 && control_kind
.kind
== kControlKindScrollBar
11901 #endif /* MAC_OSX */
11902 #endif /* USE_TOOLKIT_SCROLL_BARS */
11905 struct scroll_bar
*bar
;
11907 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11909 bar
= tracked_scroll_bar
;
11910 #ifndef USE_TOOLKIT_SCROLL_BARS
11911 control_part_code
= kControlIndicatorPart
;
11915 bar
= (struct scroll_bar
*) GetControlReference (ch
);
11916 #ifdef USE_TOOLKIT_SCROLL_BARS
11917 /* Make the "Ctrl-Mouse-2 splits window" work
11918 for toolkit scroll bars. */
11919 if (inev
.modifiers
& ctrl_modifier
)
11920 x_scroll_bar_handle_click (bar
, control_part_code
,
11922 else if (er
.what
== mouseDown
)
11923 x_scroll_bar_handle_press (bar
, control_part_code
,
11926 x_scroll_bar_handle_release (bar
, &inev
);
11927 #else /* not USE_TOOLKIT_SCROLL_BARS */
11928 x_scroll_bar_handle_click (bar
, control_part_code
,
11930 if (er
.what
== mouseDown
11931 && control_part_code
== kControlIndicatorPart
)
11932 tracked_scroll_bar
= bar
;
11934 tracked_scroll_bar
= NULL
;
11935 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11939 Lisp_Object window
;
11940 int x
= mouse_loc
.h
;
11941 int y
= mouse_loc
.v
;
11943 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
11944 if (EQ (window
, f
->tool_bar_window
))
11946 if (er
.what
== mouseDown
)
11947 handle_tool_bar_click (f
, x
, y
, 1, 0);
11949 handle_tool_bar_click (f
, x
, y
, 0,
11955 XSETFRAME (inev
.frame_or_window
, f
);
11956 inev
.kind
= MOUSE_CLICK_EVENT
;
11960 if (er
.what
== mouseDown
)
11962 dpyinfo
->grabbed
|= (1 << inev
.code
);
11963 last_mouse_frame
= f
;
11966 last_tool_bar_item
= -1;
11970 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
11971 /* If a button is released though it was not
11972 previously pressed, that would be because
11973 of multi-button emulation. */
11974 dpyinfo
->grabbed
= 0;
11976 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
11979 /* Ignore any mouse motion that happened before
11980 this event; any subsequent mouse-movement Emacs
11981 events should reflect only motion after the
11984 f
->mouse_moved
= 0;
11986 #ifdef USE_TOOLKIT_SCROLL_BARS
11987 if (inev
.kind
== MOUSE_CLICK_EVENT
11988 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
11989 && (inev
.modifiers
& ctrl_modifier
)))
11994 inev
.modifiers
|= down_modifier
;
11997 inev
.modifiers
|= up_modifier
;
12004 #if TARGET_API_MAC_CARBON
12006 if (IsWindowPathSelectClick (window_ptr
, &er
))
12008 WindowPathSelect (window_ptr
, NULL
, NULL
);
12011 if (part_code
== inProxyIcon
12012 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12013 != errUserWantsToDragWindow
))
12015 DragWindow (window_ptr
, er
.where
, NULL
);
12016 #else /* not TARGET_API_MAC_CARBON */
12017 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12018 /* Update the frame parameters. */
12020 struct frame
*f
= mac_window_to_frame (window_ptr
);
12022 if (f
&& !f
->async_iconified
)
12023 mac_handle_origin_change (f
);
12025 #endif /* not TARGET_API_MAC_CARBON */
12029 if (TrackGoAway (window_ptr
, er
.where
))
12031 inev
.kind
= DELETE_WINDOW_EVENT
;
12032 XSETFRAME (inev
.frame_or_window
,
12033 mac_window_to_frame (window_ptr
));
12037 /* window resize handling added --ben */
12039 do_grow_window (window_ptr
, &er
);
12042 /* window zoom handling added --ben */
12045 if (TrackBox (window_ptr
, er
.where
, part_code
))
12046 do_zoom_window (window_ptr
, part_code
);
12049 #if USE_MAC_TOOLBAR
12055 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12057 /* This doesn't work on Mac OS X 10.2. */
12059 HIViewClick (ch
, eventRef
);
12062 #endif /* USE_MAC_TOOLBAR */
12070 #if !TARGET_API_MAC_CARBON
12072 do_window_update ((WindowRef
) er
.message
);
12077 switch ((er
.message
>> 24) & 0x000000FF)
12079 case mouseMovedMessage
:
12080 #if !TARGET_API_MAC_CARBON
12081 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12082 er
.where
.h
+ 1, er
.where
.v
+ 1);
12084 previous_help_echo_string
= help_echo_string
;
12085 help_echo_string
= Qnil
;
12087 if (dpyinfo
->grabbed
&& last_mouse_frame
12088 && FRAME_LIVE_P (last_mouse_frame
))
12089 f
= last_mouse_frame
;
12091 f
= dpyinfo
->x_focus_frame
;
12093 if (dpyinfo
->mouse_face_hidden
)
12095 dpyinfo
->mouse_face_hidden
= 0;
12096 clear_mouse_face (dpyinfo
);
12101 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12104 mouse_pos
.h
= (er
.where
.h
12106 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12107 mouse_pos
.v
= (er
.where
.v
12109 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12110 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12111 #ifdef USE_TOOLKIT_SCROLL_BARS
12112 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12114 #else /* not USE_TOOLKIT_SCROLL_BARS */
12115 x_scroll_bar_note_movement (tracked_scroll_bar
,
12117 - XINT (tracked_scroll_bar
->top
),
12118 er
.when
* (1000 / 60));
12119 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12122 /* Generate SELECT_WINDOW_EVENTs when needed. */
12123 if (!NILP (Vmouse_autoselect_window
))
12125 Lisp_Object window
;
12127 window
= window_from_coordinates (f
,
12132 /* Window will be selected only when it is
12133 not selected now and last mouse movement
12134 event was not in it. Minibuffer window
12135 will be selected iff it is active. */
12136 if (WINDOWP (window
)
12137 && !EQ (window
, last_window
)
12138 && !EQ (window
, selected_window
))
12140 inev
.kind
= SELECT_WINDOW_EVENT
;
12141 inev
.frame_or_window
= window
;
12144 last_window
=window
;
12146 if (!note_mouse_movement (f
, &mouse_pos
))
12147 help_echo_string
= previous_help_echo_string
;
12148 #if USE_MAC_TOOLBAR
12150 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12155 /* If the contents of the global variable
12156 help_echo_string has changed, generate a
12158 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12169 WindowRef window_ptr
= (WindowRef
) er
.message
;
12171 if (window_ptr
== tip_window
)
12173 HideWindow (tip_window
);
12177 if (!is_emacs_window (window_ptr
))
12180 f
= mac_window_to_frame (window_ptr
);
12182 if ((er
.modifiers
& activeFlag
) != 0)
12184 /* A window has been activated */
12187 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12189 mouse_loc
.h
= (er
.where
.h
12191 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12192 mouse_loc
.v
= (er
.where
.v
12194 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12195 /* Window-activated event counts as mouse movement,
12196 so update things that depend on mouse position. */
12197 note_mouse_movement (f
, &mouse_loc
);
12201 /* A window has been deactivated */
12202 #ifdef USE_TOOLKIT_SCROLL_BARS
12203 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12205 struct input_event event
;
12207 EVENT_INIT (event
);
12208 event
.kind
= NO_EVENT
;
12209 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12210 if (event
.kind
!= NO_EVENT
)
12212 event
.timestamp
= timestamp
;
12213 kbd_buffer_store_event_hold (&event
, hold_quit
);
12218 dpyinfo
->grabbed
= 0;
12220 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12222 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12224 /* If we move outside the frame, then we're
12225 certainly no longer on any text in the
12227 clear_mouse_face (dpyinfo
);
12228 dpyinfo
->mouse_face_mouse_frame
= 0;
12231 /* Generate a nil HELP_EVENT to cancel a help-echo.
12232 Do it only if there's something to cancel.
12233 Otherwise, the startup message is cleared when the
12234 mouse leaves the frame. */
12235 if (any_help_event_p
)
12246 f
= mac_focus_frame (dpyinfo
);
12247 XSETFRAME (inev
.frame_or_window
, f
);
12249 /* If mouse-highlight is an integer, input clears out mouse
12251 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12252 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12254 clear_mouse_face (dpyinfo
);
12255 dpyinfo
->mouse_face_hidden
= 1;
12257 #if TARGET_API_MAC_CARBON
12260 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12261 (er
.message
& keyCodeMask
) >> 8,
12262 er
.modifiers
, timestamp
, &inev
);
12266 case kHighLevelEvent
:
12267 AEProcessAppleEvent (&er
);
12272 #if TARGET_API_MAC_CARBON
12276 read_socket_inev
= &inev
;
12277 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12278 read_socket_inev
= NULL
;
12283 #if TARGET_API_MAC_CARBON
12284 ReleaseEvent (eventRef
);
12287 if (inev
.kind
!= NO_EVENT
)
12289 inev
.timestamp
= timestamp
;
12290 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12295 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12300 XSETFRAME (frame
, f
);
12306 any_help_event_p
= 1;
12307 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12308 help_echo_object
, help_echo_pos
);
12312 help_echo_string
= Qnil
;
12313 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12320 /* If the focus was just given to an autoraising frame,
12322 /* ??? This ought to be able to handle more than one such frame. */
12323 if (pending_autoraise_frame
)
12325 x_raise_frame (pending_autoraise_frame
);
12326 pending_autoraise_frame
= 0;
12329 if (mac_screen_config_changed
)
12331 mac_get_screen_info (dpyinfo
);
12332 mac_screen_config_changed
= 0;
12335 #if !TARGET_API_MAC_CARBON
12336 /* Check which frames are still visible. We do this here because
12337 there doesn't seem to be any direct notification from the Window
12338 Manager that the visibility of a window has changed (at least,
12339 not in all cases). */
12341 Lisp_Object tail
, frame
;
12343 FOR_EACH_FRAME (tail
, frame
)
12345 struct frame
*f
= XFRAME (frame
);
12347 /* The tooltip has been drawn already. Avoid the
12348 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12349 if (EQ (frame
, tip_frame
))
12352 if (FRAME_MAC_P (f
))
12353 mac_handle_visibility_change (f
);
12364 /* Need to override CodeWarrior's input function so no conversion is
12365 done on newlines Otherwise compiled functions in .elc files will be
12366 read incorrectly. Defined in ...:MSL C:MSL
12367 Common:Source:buffer_io.c. */
12370 __convert_to_newlines (unsigned char * p
, size_t * n
)
12372 #pragma unused(p,n)
12376 __convert_from_newlines (unsigned char * p
, size_t * n
)
12378 #pragma unused(p,n)
12384 make_mac_terminal_frame (struct frame
*f
)
12389 XSETFRAME (frame
, f
);
12391 f
->output_method
= output_mac
;
12392 f
->output_data
.mac
= (struct mac_output
*)
12393 xmalloc (sizeof (struct mac_output
));
12394 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12396 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12398 FRAME_COLS (f
) = 96;
12399 FRAME_LINES (f
) = 4;
12401 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12402 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12404 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12406 f
->output_data
.mac
->cursor_pixel
= 0;
12407 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12408 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12409 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12411 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12412 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12413 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12414 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12415 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12416 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12418 FRAME_FONTSET (f
) = -1;
12419 f
->output_data
.mac
->explicit_parent
= 0;
12422 f
->border_width
= 0;
12424 f
->internal_border_width
= 0;
12429 f
->new_text_cols
= 0;
12430 f
->new_text_lines
= 0;
12432 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12433 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12434 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12438 if (!(FRAME_MAC_WINDOW (f
) =
12439 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12440 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12442 /* so that update events can find this mac_output struct */
12443 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12449 /* Need to be initialized for unshow_buffer in window.c. */
12450 selected_window
= f
->selected_window
;
12452 Fmodify_frame_parameters (frame
,
12453 Fcons (Fcons (Qfont
,
12454 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12455 Fmodify_frame_parameters (frame
,
12456 Fcons (Fcons (Qforeground_color
,
12457 build_string ("black")), Qnil
));
12458 Fmodify_frame_parameters (frame
,
12459 Fcons (Fcons (Qbackground_color
,
12460 build_string ("white")), Qnil
));
12465 /***********************************************************************
12467 ***********************************************************************/
12469 static int mac_initialized
= 0;
12472 mac_make_rdb (xrm_option
)
12473 const char *xrm_option
;
12475 XrmDatabase database
;
12477 database
= xrm_get_preference_database (NULL
);
12479 xrm_merge_string_database (database
, xrm_option
);
12484 struct mac_display_info
*
12485 mac_term_init (display_name
, xrm_option
, resource_name
)
12486 Lisp_Object display_name
;
12488 char *resource_name
;
12490 struct mac_display_info
*dpyinfo
;
12494 if (!mac_initialized
)
12497 mac_initialized
= 1;
12500 if (x_display_list
)
12501 error ("Sorry, this version can only handle one display");
12503 dpyinfo
= &one_mac_display_info
;
12504 bzero (dpyinfo
, sizeof (*dpyinfo
));
12507 dpyinfo
->mac_id_name
12508 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12509 + SCHARS (Vsystem_name
)
12511 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12512 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12514 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12515 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12518 dpyinfo
->reference_count
= 0;
12519 dpyinfo
->resx
= 72.0;
12520 dpyinfo
->resy
= 72.0;
12522 mac_get_screen_info (dpyinfo
);
12524 dpyinfo
->grabbed
= 0;
12525 dpyinfo
->root_window
= NULL
;
12526 dpyinfo
->image_cache
= make_image_cache ();
12528 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12529 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12530 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12531 dpyinfo
->mouse_face_window
= Qnil
;
12532 dpyinfo
->mouse_face_overlay
= Qnil
;
12533 dpyinfo
->mouse_face_hidden
= 0;
12535 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12537 /* Put this display on the chain. */
12538 dpyinfo
->next
= x_display_list
;
12539 x_display_list
= dpyinfo
;
12541 /* Put it on x_display_name_list. */
12542 x_display_name_list
= Fcons (Fcons (display_name
,
12543 Fcons (Qnil
, dpyinfo
->xrdb
)),
12544 x_display_name_list
);
12545 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12552 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12555 x_delete_display (dpyinfo
)
12556 struct mac_display_info
*dpyinfo
;
12560 /* Discard this display from x_display_name_list and x_display_list.
12561 We can't use Fdelq because that can quit. */
12562 if (! NILP (x_display_name_list
)
12563 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12564 x_display_name_list
= XCDR (x_display_name_list
);
12569 tail
= x_display_name_list
;
12570 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12572 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
12574 XSETCDR (tail
, XCDR (XCDR (tail
)));
12577 tail
= XCDR (tail
);
12581 if (x_display_list
== dpyinfo
)
12582 x_display_list
= dpyinfo
->next
;
12585 struct x_display_info
*tail
;
12587 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12588 if (tail
->next
== dpyinfo
)
12589 tail
->next
= tail
->next
->next
;
12592 /* Free the font names in the font table. */
12593 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12594 if (dpyinfo
->font_table
[i
].name
)
12596 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
12597 xfree (dpyinfo
->font_table
[i
].full_name
);
12598 xfree (dpyinfo
->font_table
[i
].name
);
12601 if (dpyinfo
->font_table
)
12603 if (dpyinfo
->font_table
->font_encoder
)
12604 xfree (dpyinfo
->font_table
->font_encoder
);
12605 xfree (dpyinfo
->font_table
);
12607 if (dpyinfo
->mac_id_name
)
12608 xfree (dpyinfo
->mac_id_name
);
12610 if (x_display_list
== 0)
12612 mac_clear_font_name_table ();
12613 bzero (dpyinfo
, sizeof (*dpyinfo
));
12624 MenuItemIndex menu_index
;
12626 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
12627 &menu
, &menu_index
);
12629 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12630 EnableMenuCommand (NULL
, kHICommandPreferences
);
12631 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
12632 &menu
, &menu_index
);
12635 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12636 InsertMenuItemTextWithCFString (menu
, NULL
,
12637 0, kMenuItemAttrSeparator
, 0);
12638 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
12639 0, 0, kHICommandAbout
);
12641 #else /* !MAC_OSX */
12642 #if TARGET_API_MAC_CARBON
12643 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
12653 static InterfaceTypeList types
= {kUnicodeDocument
};
12655 static InterfaceTypeList types
= {kTextService
};
12658 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
12659 &tsm_document_id
, 0);
12663 /* Set up use of X before we make the first connection. */
12665 extern frame_parm_handler mac_frame_parm_handlers
[];
12667 static struct redisplay_interface x_redisplay_interface
=
12669 mac_frame_parm_handlers
,
12673 x_clear_end_of_line
,
12675 x_after_update_window_line
,
12676 x_update_window_begin
,
12677 x_update_window_end
,
12681 mac_flush_display_optional
,
12683 0, /* flush_display_optional */
12685 x_clear_window_mouse_face
,
12686 x_get_glyph_overhangs
,
12687 x_fix_overlapping_area
,
12688 x_draw_fringe_bitmap
,
12690 mac_define_fringe_bitmap
,
12691 mac_destroy_fringe_bitmap
,
12693 0, /* define_fringe_bitmap */
12694 0, /* destroy_fringe_bitmap */
12696 mac_per_char_metric
,
12698 mac_compute_glyph_string_overhangs
,
12699 x_draw_glyph_string
,
12700 mac_define_frame_cursor
,
12701 mac_clear_frame_area
,
12702 mac_draw_window_cursor
,
12703 mac_draw_vertical_window_border
,
12704 mac_shift_glyphs_for_insert
12710 rif
= &x_redisplay_interface
;
12712 clear_frame_hook
= x_clear_frame
;
12713 ins_del_lines_hook
= x_ins_del_lines
;
12714 delete_glyphs_hook
= x_delete_glyphs
;
12715 ring_bell_hook
= XTring_bell
;
12716 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12717 set_terminal_modes_hook
= XTset_terminal_modes
;
12718 update_begin_hook
= x_update_begin
;
12719 update_end_hook
= x_update_end
;
12720 set_terminal_window_hook
= XTset_terminal_window
;
12721 read_socket_hook
= XTread_socket
;
12722 frame_up_to_date_hook
= XTframe_up_to_date
;
12723 mouse_position_hook
= XTmouse_position
;
12724 frame_rehighlight_hook
= XTframe_rehighlight
;
12725 frame_raise_lower_hook
= XTframe_raise_lower
;
12727 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12728 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12729 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12730 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12732 scroll_region_ok
= 1; /* we'll scroll partial frames */
12733 char_ins_del_ok
= 1;
12734 line_ins_del_ok
= 1; /* we'll just blt 'em */
12735 fast_clear_end_of_line
= 1; /* X does this well */
12736 memory_below_frame
= 0; /* we don't remember what scrolls
12740 last_tool_bar_item
= -1;
12741 any_help_event_p
= 0;
12743 /* Try to use interrupt input; if we can't, then start polling. */
12744 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
12748 #if TARGET_API_MAC_CARBON
12750 install_application_handler ();
12759 init_coercion_handler ();
12761 init_apple_event_handler ();
12763 init_dm_notification_handler ();
12765 if (!inhibit_window_system
)
12767 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
12769 SetFrontProcess (&psn
);
12777 mac_init_fringe ();
12788 staticpro (&x_error_message_string
);
12789 x_error_message_string
= Qnil
;
12792 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
12793 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
12794 Qalt
= intern ("alt"); staticpro (&Qalt
);
12795 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
12796 Qsuper
= intern ("super"); staticpro (&Qsuper
);
12797 Qmodifier_value
= intern ("modifier-value");
12798 staticpro (&Qmodifier_value
);
12800 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
12801 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12802 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12803 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12804 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12806 #if TARGET_API_MAC_CARBON
12807 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
12809 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
12810 staticpro (&Qtoolbar_switch_mode
);
12811 #if USE_MAC_FONT_PANEL
12812 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12813 Qselection
= intern ("selection"); staticpro (&Qselection
);
12816 Qservice
= intern ("service"); staticpro (&Qservice
);
12817 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12818 Qperform
= intern ("perform"); staticpro (&Qperform
);
12821 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12822 Qupdate_active_input_area
= intern ("update-active-input-area");
12823 staticpro (&Qupdate_active_input_area
);
12824 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12825 staticpro (&Qunicode_for_key_event
);
12830 Fprovide (intern ("mac-carbon"), Qnil
);
12833 staticpro (&Qreverse
);
12834 Qreverse
= intern ("reverse");
12836 staticpro (&x_display_name_list
);
12837 x_display_name_list
= Qnil
;
12839 staticpro (&last_mouse_scroll_bar
);
12840 last_mouse_scroll_bar
= Qnil
;
12842 staticpro (&fm_font_family_alist
);
12843 fm_font_family_alist
= Qnil
;
12846 staticpro (&atsu_font_id_hash
);
12847 atsu_font_id_hash
= Qnil
;
12849 staticpro (&fm_style_face_attributes_alist
);
12850 fm_style_face_attributes_alist
= Qnil
;
12854 staticpro (&saved_ts_script_language_on_focus
);
12855 saved_ts_script_language_on_focus
= Qnil
;
12858 /* We don't yet support this, but defining this here avoids whining
12859 from cus-start.el and other places, like "M-x set-variable". */
12860 DEFVAR_BOOL ("x-use-underline-position-properties",
12861 &x_use_underline_position_properties
,
12862 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12863 A value of nil means ignore them. If you encounter fonts with bogus
12864 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12865 to 4.1, set this to nil.
12867 NOTE: Not supported on Mac yet. */);
12868 x_use_underline_position_properties
= 0;
12870 DEFVAR_BOOL ("x-underline-at-descent-line",
12871 &x_underline_at_descent_line
,
12872 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12873 A value of nil means to draw the underline according to the value of the
12874 variable `x-use-underline-position-properties', which is usually at the
12875 baseline level. The default value is nil. */);
12876 x_underline_at_descent_line
= 0;
12878 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12879 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12880 #ifdef USE_TOOLKIT_SCROLL_BARS
12881 Vx_toolkit_scroll_bars
= Qt
;
12883 Vx_toolkit_scroll_bars
= Qnil
;
12886 staticpro (&last_mouse_motion_frame
);
12887 last_mouse_motion_frame
= Qnil
;
12889 /* Variables to configure modifier key assignment. */
12891 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12892 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12893 The value can be `control', `meta', `alt', `hyper', or `super' for the
12894 respective modifier. The default is `control'. */);
12895 Vmac_control_modifier
= Qcontrol
;
12897 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12898 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12899 The value can be `control', `meta', `alt', `hyper', or `super' for the
12900 respective modifier. If the value is nil then the key will act as the
12901 normal Mac control modifier, and the option key can be used to compose
12902 characters depending on the chosen Mac keyboard setting. */);
12903 Vmac_option_modifier
= Qnil
;
12905 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12906 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12907 The value can be `control', `meta', `alt', `hyper', or `super' for the
12908 respective modifier. The default is `meta'. */);
12909 Vmac_command_modifier
= Qmeta
;
12911 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12912 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12913 The value can be `control', `meta', `alt', `hyper', or `super' for the
12914 respective modifier. Note that remapping the function key may lead to
12915 unexpected results for some keys on non-US/GB keyboards. */);
12916 Vmac_function_modifier
= Qnil
;
12918 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12919 &Vmac_emulate_three_button_mouse
,
12920 doc
: /* *Specify a way of three button mouse emulation.
12921 The value can be nil, t, or the symbol `reverse'.
12922 A value of nil means that no emulation should be done and the modifiers
12923 should be placed on the mouse-1 event.
12924 t means that when the option-key is held down while pressing the mouse
12925 button, the click will register as mouse-2 and while the command-key
12926 is held down, the click will register as mouse-3.
12927 The symbol `reverse' means that the option-key will register for
12928 mouse-3 and the command-key will register for mouse-2. */);
12929 Vmac_emulate_three_button_mouse
= Qnil
;
12931 #if TARGET_API_MAC_CARBON
12932 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12933 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12934 Otherwise, the right click will be treated as mouse-2 and the wheel
12935 button will be mouse-3. */);
12936 mac_wheel_button_is_mouse_2
= 1;
12938 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12939 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12940 mac_pass_command_to_system
= 1;
12942 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12943 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12944 mac_pass_control_to_system
= 1;
12948 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
12949 doc
: /* *If non-nil, allow anti-aliasing.
12950 The text will be rendered using Core Graphics text rendering which
12951 may anti-alias the text. */);
12953 mac_use_core_graphics
= 1;
12955 mac_use_core_graphics
= 0;
12958 /* Register an entry for `mac-roman' so that it can be used when
12959 creating the terminal frame on Mac OS 9 before loading
12960 term/mac-win.elc. */
12961 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
12962 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
12963 Each entry should be of the form:
12965 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12967 where CHARSET-NAME is a string used in font names to identify the
12968 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12969 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12970 Vmac_charset_info_alist
=
12971 Fcons (list3 (build_string ("mac-roman"),
12972 make_number (smRoman
), Qnil
), Qnil
);
12975 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
12976 doc
: /* Overlay used to display Mac TSM active input area. */);
12977 Vmac_ts_active_input_overlay
= Qnil
;
12979 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
12980 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
12981 If the value is t, the input script and language are restored to those
12982 used in the last focus frame. If the value is a pair of integers, the
12983 input script and language codes, which are defined in the Script
12984 Manager, are set to its car and cdr parts, respectively. Otherwise,
12985 Emacs doesn't set them and thus follows the system default behavior. */);
12986 Vmac_ts_script_language_on_focus
= Qnil
;
12990 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12991 (do not change this comment) */