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 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
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
;
2197 int overlay_p
= p
->overlay_p
;
2202 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2204 #if 0 /* MAC_TODO: stipple */
2205 /* In case the same realized face is used for fringes and
2206 for something displayed in the text (e.g. face `region' on
2207 mono-displays, the fill style may have been changed to
2208 FillSolid in x_draw_glyph_string_background. */
2210 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2212 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2215 /* If the fringe is adjacent to the left (right) scroll bar of a
2216 leftmost (rightmost, respectively) window, then extend its
2217 background to the gap between the fringe and the bar. */
2218 if ((WINDOW_LEFTMOST_P (w
)
2219 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2220 || (WINDOW_RIGHTMOST_P (w
)
2221 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2223 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2227 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2228 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2229 * FRAME_COLUMN_WIDTH (f
));
2232 && (left
+ width
== p
->x
2233 || p
->x
+ p
->wd
== left
))
2235 /* Bitmap fills the fringe and we need background
2237 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
2241 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
2243 ny
= row
->visible_height
;
2248 if (left
+ width
== bx
)
2250 bx
= left
+ sb_width
;
2251 nx
+= width
- sb_width
;
2253 else if (bx
+ nx
== left
)
2254 nx
+= width
- sb_width
;
2261 mac_erase_rectangle (f
, face
->gc
, bx
, by
, nx
, ny
);
2262 /* The fringe background has already been filled. */
2266 #if 0 /* MAC_TODO: stipple */
2268 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2271 #endif /* MAC_OSX */
2273 /* Must clip because of partially visible lines. */
2274 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2277 /* Adjust position of "bottom aligned" bitmap on partially
2278 visible last row. */
2280 int oldVH
= row
->visible_height
;
2281 row
->visible_height
= p
->h
;
2282 row
->y
-= rowY
- p
->y
;
2283 x_clip_to_row (w
, row
, -1, face
->gc
);
2285 row
->visible_height
= oldVH
;
2288 x_clip_to_row (w
, row
, -1, face
->gc
);
2291 if (p
->bx
>= 0 && !p
->overlay_p
)
2293 #if 0 /* MAC_TODO: stipple */
2294 /* In case the same realized face is used for fringes and
2295 for something displayed in the text (e.g. face `region' on
2296 mono-displays, the fill style may have been changed to
2297 FillSolid in x_draw_glyph_string_background. */
2299 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2301 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2304 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2306 #if 0 /* MAC_TODO: stipple */
2308 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2311 #endif /* !MAC_OSX */
2315 && p
->which
< max_fringe_bmp
2321 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2322 XSetForeground (display
, face
->gc
,
2324 ? (p
->overlay_p
? face
->background
2325 : f
->output_data
.mac
->cursor_pixel
)
2326 : face
->foreground
));
2328 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2329 p
->wd
, p
->h
, p
->x
, p
->y
, overlay_p
);
2331 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2332 p
->wd
, p
->h
, p
->bits
+ p
->dh
, overlay_p
);
2334 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2337 mac_reset_clip_rectangles (display
, face
->gc
);
2342 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2344 unsigned short *bits
;
2348 CGDataProviderRef provider
;
2350 if (which
>= max_fringe_bmp
)
2353 max_fringe_bmp
= which
+ 20;
2354 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2355 while (i
< max_fringe_bmp
)
2356 fringe_bmp
[i
++] = 0;
2359 for (i
= 0; i
< h
; i
++)
2361 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2362 sizeof (unsigned short) * h
, NULL
);
2365 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2366 sizeof (unsigned short),
2368 CGDataProviderRelease (provider
);
2373 mac_destroy_fringe_bitmap (which
)
2376 if (which
>= max_fringe_bmp
)
2379 if (fringe_bmp
[which
])
2380 CGImageRelease (fringe_bmp
[which
]);
2381 fringe_bmp
[which
] = 0;
2386 /* This is called when starting Emacs and when restarting after
2387 suspend. When starting Emacs, no window is mapped. And nothing
2388 must be done to Emacs's own window if it is suspended (though that
2392 XTset_terminal_modes ()
2396 /* This is called when exiting or suspending Emacs. Exiting will make
2397 the windows go away, and suspending requires no action. */
2400 XTreset_terminal_modes ()
2406 /***********************************************************************
2408 ***********************************************************************/
2410 /* Function prototypes of this page. */
2412 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2413 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2417 pcm_init (pcm
, count
)
2421 bzero (pcm
, sizeof (XCharStruct
) * count
);
2422 while (--count
>= 0)
2424 pcm
->descent
= PCM_INVALID
;
2429 static enum pcm_status
2430 pcm_get_status (pcm
)
2431 const XCharStruct
*pcm
;
2433 int height
= pcm
->ascent
+ pcm
->descent
;
2435 /* Negative height means some special status. */
2436 return height
>= 0 ? PCM_VALID
: height
;
2439 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2440 is not contained in the font. */
2442 static INLINE XCharStruct
*
2443 x_per_char_metric (font
, char2b
)
2447 /* The result metric information. */
2448 XCharStruct
*pcm
= NULL
;
2450 xassert (font
&& char2b
);
2453 if (font
->mac_style
)
2455 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2459 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2460 pcm_init (*row
, 0x100);
2462 pcm
= *row
+ char2b
->byte2
;
2463 if (pcm_get_status (pcm
) != PCM_VALID
)
2466 mac_query_char_extents (font
->mac_style
,
2467 (char2b
->byte1
<< 8) + char2b
->byte2
,
2468 NULL
, NULL
, pcm
, NULL
);
2475 if (font
->bounds
.per_char
!= NULL
)
2477 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2479 /* min_char_or_byte2 specifies the linear character index
2480 corresponding to the first element of the per_char array,
2481 max_char_or_byte2 is the index of the last character. A
2482 character with non-zero CHAR2B->byte1 is not in the font.
2483 A character with byte2 less than min_char_or_byte2 or
2484 greater max_char_or_byte2 is not in the font. */
2485 if (char2b
->byte1
== 0
2486 && char2b
->byte2
>= font
->min_char_or_byte2
2487 && char2b
->byte2
<= font
->max_char_or_byte2
)
2488 pcm
= font
->bounds
.per_char
2489 + (char2b
->byte2
- font
->min_char_or_byte2
);
2493 /* If either min_byte1 or max_byte1 are nonzero, both
2494 min_char_or_byte2 and max_char_or_byte2 are less than
2495 256, and the 2-byte character index values corresponding
2496 to the per_char array element N (counting from 0) are:
2498 byte1 = N/D + min_byte1
2499 byte2 = N\D + min_char_or_byte2
2503 D = max_char_or_byte2 - min_char_or_byte2 + 1
2504 / = integer division
2505 \ = integer modulus */
2506 if (char2b
->byte1
>= font
->min_byte1
2507 && char2b
->byte1
<= font
->max_byte1
2508 && char2b
->byte2
>= font
->min_char_or_byte2
2509 && char2b
->byte2
<= font
->max_char_or_byte2
)
2511 pcm
= (font
->bounds
.per_char
2512 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2513 * (char2b
->byte1
- font
->min_byte1
))
2514 + (char2b
->byte2
- font
->min_char_or_byte2
));
2520 /* If the per_char pointer is null, all glyphs between the first
2521 and last character indexes inclusive have the same
2522 information, as given by both min_bounds and max_bounds. */
2523 if (char2b
->byte2
>= font
->min_char_or_byte2
2524 && char2b
->byte2
<= font
->max_char_or_byte2
)
2525 pcm
= &font
->max_bounds
;
2531 return ((pcm
== NULL
2533 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2534 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2543 static XCharStruct
*
2544 mac_per_char_metric (font
, char2b
, font_type
)
2549 return x_per_char_metric (font
, char2b
);
2553 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2554 the two-byte form of C. Encoding is returned in *CHAR2B. */
2557 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2560 struct font_info
*font_info
;
2563 int charset
= CHAR_CHARSET (c
);
2564 XFontStruct
*font
= font_info
->font
;
2566 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2567 This may be either a program in a special encoder language or a
2569 if (font_info
->font_encoder
)
2571 /* It's a program. */
2572 struct ccl_program
*ccl
= font_info
->font_encoder
;
2574 check_ccl_update (ccl
);
2575 if (CHARSET_DIMENSION (charset
) == 1)
2577 ccl
->reg
[0] = charset
;
2578 ccl
->reg
[1] = char2b
->byte2
;
2583 ccl
->reg
[0] = charset
;
2584 ccl
->reg
[1] = char2b
->byte1
;
2585 ccl
->reg
[2] = char2b
->byte2
;
2588 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2590 /* We assume that MSBs are appropriately set/reset by CCL
2592 if (font
->max_byte1
== 0) /* 1-byte font */
2593 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2595 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2597 else if (font_info
->encoding
[charset
])
2599 /* Fixed encoding scheme. See fontset.h for the meaning of the
2600 encoding numbers. */
2601 int enc
= font_info
->encoding
[charset
];
2603 if ((enc
== 1 || enc
== 2)
2604 && CHARSET_DIMENSION (charset
) == 2)
2605 char2b
->byte1
|= 0x80;
2607 if (enc
== 1 || enc
== 3)
2608 char2b
->byte2
|= 0x80;
2614 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2615 char2b
->byte1
= sjis1
;
2616 char2b
->byte2
= sjis2
;
2621 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2623 return FONT_TYPE_UNKNOWN
;
2628 /***********************************************************************
2630 ***********************************************************************/
2634 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2635 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2636 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2638 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2639 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2640 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2641 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2642 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2643 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2644 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2645 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2646 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2647 unsigned long *, double, int));*/
2648 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2649 double, int, unsigned long));
2650 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2651 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2652 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2653 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2654 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2656 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2657 int, int, int, int, int, int,
2659 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2660 int, int, int, Rect
*));
2663 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2667 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2672 struct glyph_string
*s
;
2674 if (s
->font
== FRAME_FONT (s
->f
)
2675 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2676 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2678 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2681 /* Cursor on non-default face: must merge. */
2685 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2686 xgcv
.foreground
= s
->face
->background
;
2688 /* If the glyph would be invisible, try a different foreground. */
2689 if (xgcv
.foreground
== xgcv
.background
)
2690 xgcv
.foreground
= s
->face
->foreground
;
2691 if (xgcv
.foreground
== xgcv
.background
)
2692 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2693 if (xgcv
.foreground
== xgcv
.background
)
2694 xgcv
.foreground
= s
->face
->foreground
;
2696 /* Make sure the cursor is distinct from text in this face. */
2697 if (xgcv
.background
== s
->face
->background
2698 && xgcv
.foreground
== s
->face
->foreground
)
2700 xgcv
.background
= s
->face
->foreground
;
2701 xgcv
.foreground
= s
->face
->background
;
2704 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2705 xgcv
.font
= s
->font
;
2706 mask
= GCForeground
| GCBackground
| GCFont
;
2708 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2709 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2712 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2713 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2715 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2720 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2723 x_set_mouse_face_gc (s
)
2724 struct glyph_string
*s
;
2729 /* What face has to be used last for the mouse face? */
2730 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2731 face
= FACE_FROM_ID (s
->f
, face_id
);
2733 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2735 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2736 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2738 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2739 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2740 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2742 /* If font in this face is same as S->font, use it. */
2743 if (s
->font
== s
->face
->font
)
2744 s
->gc
= s
->face
->gc
;
2747 /* Otherwise construct scratch_cursor_gc with values from FACE
2752 xgcv
.background
= s
->face
->background
;
2753 xgcv
.foreground
= s
->face
->foreground
;
2754 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2755 xgcv
.font
= s
->font
;
2756 mask
= GCForeground
| GCBackground
| GCFont
;
2758 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2759 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2762 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2763 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2765 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2768 xassert (s
->gc
!= 0);
2772 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2773 Faces to use in the mode line have already been computed when the
2774 matrix was built, so there isn't much to do, here. */
2777 x_set_mode_line_face_gc (s
)
2778 struct glyph_string
*s
;
2780 s
->gc
= s
->face
->gc
;
2784 /* Set S->gc of glyph string S for drawing that glyph string. Set
2785 S->stippled_p to a non-zero value if the face of S has a stipple
2789 x_set_glyph_string_gc (s
)
2790 struct glyph_string
*s
;
2792 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2794 if (s
->hl
== DRAW_NORMAL_TEXT
)
2796 s
->gc
= s
->face
->gc
;
2797 s
->stippled_p
= s
->face
->stipple
!= 0;
2799 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2801 x_set_mode_line_face_gc (s
);
2802 s
->stippled_p
= s
->face
->stipple
!= 0;
2804 else if (s
->hl
== DRAW_CURSOR
)
2806 x_set_cursor_gc (s
);
2809 else if (s
->hl
== DRAW_MOUSE_FACE
)
2811 x_set_mouse_face_gc (s
);
2812 s
->stippled_p
= s
->face
->stipple
!= 0;
2814 else if (s
->hl
== DRAW_IMAGE_RAISED
2815 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2817 s
->gc
= s
->face
->gc
;
2818 s
->stippled_p
= s
->face
->stipple
!= 0;
2822 s
->gc
= s
->face
->gc
;
2823 s
->stippled_p
= s
->face
->stipple
!= 0;
2826 /* GC must have been set. */
2827 xassert (s
->gc
!= 0);
2831 /* Set clipping for output of glyph string S. S may be part of a mode
2832 line or menu if we don't have X toolkit support. */
2835 x_set_glyph_string_clipping (s
)
2836 struct glyph_string
*s
;
2838 Rect rects
[MAX_CLIP_RECTS
];
2841 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2842 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2847 Compute left and right overhang of glyph string S. If S is a glyph
2848 string for a composition, assume overhangs don't exist. */
2851 mac_compute_glyph_string_overhangs (s
)
2852 struct glyph_string
*s
;
2854 if (!(s
->cmp
== NULL
2855 && s
->first_glyph
->type
== CHAR_GLYPH
))
2860 || s
->font
->mac_style
2866 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2867 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2868 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2873 MacFontStruct
*font
= s
->font
;
2876 mac_prepare_for_quickdraw (s
->f
);
2878 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2880 TextFont (font
->mac_fontnum
);
2881 TextSize (font
->mac_fontsize
);
2882 TextFace (font
->mac_fontface
);
2884 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2886 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2887 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2892 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2895 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2896 struct glyph_string
*s
;
2899 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2903 /* Draw the background of glyph_string S. If S->background_filled_p
2904 is non-zero don't draw it. FORCE_P non-zero means draw the
2905 background even if it wouldn't be drawn normally. This is used
2906 when a string preceding S draws into the background of S, or S
2907 contains the first component of a composition. */
2910 x_draw_glyph_string_background (s
, force_p
)
2911 struct glyph_string
*s
;
2914 /* Nothing to do if background has already been drawn or if it
2915 shouldn't be drawn in the first place. */
2916 if (!s
->background_filled_p
)
2918 int box_line_width
= max (s
->face
->box_line_width
, 0);
2920 #if 0 /* MAC_TODO: stipple */
2923 /* Fill background with a stipple pattern. */
2924 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2925 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2926 s
->y
+ box_line_width
,
2927 s
->background_width
,
2928 s
->height
- 2 * box_line_width
);
2929 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2930 s
->background_filled_p
= 1;
2934 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2935 || s
->font_not_found_p
2936 || s
->extends_to_end_of_line_p
2939 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2940 s
->background_width
,
2941 s
->height
- 2 * box_line_width
);
2942 s
->background_filled_p
= 1;
2948 /* Draw the foreground of glyph string S. */
2951 x_draw_glyph_string_foreground (s
)
2952 struct glyph_string
*s
;
2956 /* If first glyph of S has a left box line, start drawing the text
2957 of S to the right of that box line. */
2958 if (s
->face
->box
!= FACE_NO_BOX
2959 && s
->first_glyph
->left_box_line_p
)
2960 x
= s
->x
+ abs (s
->face
->box_line_width
);
2964 /* Draw characters of S as rectangles if S's font could not be
2966 if (s
->font_not_found_p
)
2968 for (i
= 0; i
< s
->nchars
; ++i
)
2970 struct glyph
*g
= s
->first_glyph
+ i
;
2971 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2972 g
->pixel_width
- 1, s
->height
- 1);
2973 x
+= g
->pixel_width
;
2978 char *char1b
= (char *) s
->char2b
;
2979 int boff
= s
->font_info
->baseline_offset
;
2981 if (s
->font_info
->vertical_centering
)
2982 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2984 /* If we can use 8-bit functions, condense S->char2b. */
2987 && GC_FONT (s
->gc
)->mac_style
== NULL
2990 for (i
= 0; i
< s
->nchars
; ++i
)
2991 char1b
[i
] = s
->char2b
[i
].byte2
;
2993 /* Draw text with XDrawString if background has already been
2994 filled. Otherwise, use XDrawImageString. (Note that
2995 XDrawImageString is usually faster than XDrawString.) Always
2996 use XDrawImageString when drawing the cursor so that there is
2997 no chance that characters under a box cursor are invisible. */
2999 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3000 bg_width
= 0; /* Corresponds to XDrawString. */
3002 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
3006 || GC_FONT (s
->gc
)->mac_style
3009 #if USE_CG_TEXT_DRAWING
3011 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3012 s
->char2b
, s
->nchars
, bg_width
,
3013 s
->face
->overstrike
))
3017 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3018 s
->char2b
, s
->nchars
, bg_width
,
3019 s
->face
->overstrike
);
3021 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3022 char1b
, s
->nchars
, bg_width
,
3023 s
->face
->overstrike
);
3027 /* Draw the foreground of composite glyph string S. */
3030 x_draw_composite_glyph_string_foreground (s
)
3031 struct glyph_string
*s
;
3035 /* If first glyph of S has a left box line, start drawing the text
3036 of S to the right of that box line. */
3037 if (s
->face
->box
!= FACE_NO_BOX
3038 && s
->first_glyph
->left_box_line_p
)
3039 x
= s
->x
+ abs (s
->face
->box_line_width
);
3043 /* S is a glyph string for a composition. S->gidx is the index of
3044 the first character drawn for glyphs of this composition.
3045 S->gidx == 0 means we are drawing the very first character of
3046 this composition. */
3048 /* Draw a rectangle for the composition if the font for the very
3049 first character of the composition could not be loaded. */
3050 if (s
->font_not_found_p
)
3053 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3054 s
->width
- 1, s
->height
- 1);
3058 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3059 mac_draw_image_string_16 (s
->f
, s
->gc
,
3060 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3061 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3062 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3067 #ifdef USE_X_TOOLKIT
3069 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3072 /* Return the frame on which widget WIDGET is used.. Abort if frame
3073 cannot be determined. */
3075 static struct frame
*
3076 x_frame_of_widget (widget
)
3079 struct x_display_info
*dpyinfo
;
3083 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3085 /* Find the top-level shell of the widget. Note that this function
3086 can be called when the widget is not yet realized, so XtWindow
3087 (widget) == 0. That's the reason we can't simply use
3088 x_any_window_to_frame. */
3089 while (!XtIsTopLevelShell (widget
))
3090 widget
= XtParent (widget
);
3092 /* Look for a frame with that top-level widget. Allocate the color
3093 on that frame to get the right gamma correction value. */
3094 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3095 if (GC_FRAMEP (XCAR (tail
))
3096 && (f
= XFRAME (XCAR (tail
)),
3097 (f
->output_data
.nothing
!= 1
3098 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3099 && f
->output_data
.x
->widget
== widget
)
3106 /* Allocate the color COLOR->pixel on the screen and display of
3107 widget WIDGET in colormap CMAP. If an exact match cannot be
3108 allocated, try the nearest color available. Value is non-zero
3109 if successful. This is called from lwlib. */
3112 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3117 struct frame
*f
= x_frame_of_widget (widget
);
3118 return x_alloc_nearest_color (f
, cmap
, color
);
3122 #endif /* USE_X_TOOLKIT */
3124 #if 0 /* MAC_TODO */
3126 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3127 CMAP. If an exact match can't be allocated, try the nearest color
3128 available. Value is non-zero if successful. Set *COLOR to the
3132 x_alloc_nearest_color (f
, cmap
, color
)
3137 Display
*display
= FRAME_X_DISPLAY (f
);
3138 Screen
*screen
= FRAME_X_SCREEN (f
);
3141 gamma_correct (f
, color
);
3142 rc
= XAllocColor (display
, cmap
, color
);
3145 /* If we got to this point, the colormap is full, so we're going
3146 to try to get the next closest color. The algorithm used is
3147 a least-squares matching, which is what X uses for closest
3148 color matching with StaticColor visuals. */
3150 unsigned long nearest_delta
= ~0;
3151 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3152 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3154 for (i
= 0; i
< ncells
; ++i
)
3156 XQueryColors (display
, cmap
, cells
, ncells
);
3158 for (nearest
= i
= 0; i
< ncells
; ++i
)
3160 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3161 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3162 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3163 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3165 if (delta
< nearest_delta
)
3168 nearest_delta
= delta
;
3172 color
->red
= cells
[nearest
].red
;
3173 color
->green
= cells
[nearest
].green
;
3174 color
->blue
= cells
[nearest
].blue
;
3175 rc
= XAllocColor (display
, cmap
, color
);
3178 #ifdef DEBUG_X_COLORS
3180 register_color (color
->pixel
);
3181 #endif /* DEBUG_X_COLORS */
3187 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3188 It's necessary to do this instead of just using PIXEL directly to
3189 get color reference counts right. */
3192 x_copy_color (f
, pixel
)
3194 unsigned long pixel
;
3198 color
.pixel
= pixel
;
3200 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3201 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3203 #ifdef DEBUG_X_COLORS
3204 register_color (pixel
);
3210 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3211 It's necessary to do this instead of just using PIXEL directly to
3212 get color reference counts right. */
3215 x_copy_dpy_color (dpy
, cmap
, pixel
)
3218 unsigned long pixel
;
3222 color
.pixel
= pixel
;
3224 XQueryColor (dpy
, cmap
, &color
);
3225 XAllocColor (dpy
, cmap
, &color
);
3227 #ifdef DEBUG_X_COLORS
3228 register_color (pixel
);
3233 #endif /* MAC_TODO */
3236 /* Brightness beyond which a color won't have its highlight brightness
3239 Nominally, highlight colors for `3d' faces are calculated by
3240 brightening an object's color by a constant scale factor, but this
3241 doesn't yield good results for dark colors, so for colors who's
3242 brightness is less than this value (on a scale of 0-255) have to
3243 use an additional additive factor.
3245 The value here is set so that the default menu-bar/mode-line color
3246 (grey75) will not have its highlights changed at all. */
3247 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3250 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3251 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3252 If this produces the same color as COLOR, try a color where all RGB
3253 values have DELTA added. Return the allocated color in *COLOR.
3254 DISPLAY is the X display, CMAP is the colormap to operate on.
3255 Value is non-zero if successful. */
3258 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3260 unsigned long *color
;
3267 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3270 /* Change RGB values by specified FACTOR. Avoid overflow! */
3271 xassert (factor
>= 0);
3272 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3273 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3274 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3276 /* Calculate brightness of COLOR. */
3277 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3278 + BLUE_FROM_ULONG (*color
)) / 6;
3280 /* We only boost colors that are darker than
3281 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3282 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3283 /* Make an additive adjustment to NEW, because it's dark enough so
3284 that scaling by FACTOR alone isn't enough. */
3286 /* How far below the limit this color is (0 - 1, 1 being darker). */
3287 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3288 /* The additive adjustment. */
3289 int min_delta
= delta
* dimness
* factor
/ 2;
3292 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3293 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3294 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3296 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3297 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3298 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3302 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3303 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3304 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3306 /* MAC_TODO: Map to palette and retry with delta if same? */
3307 /* MAC_TODO: Free colors (if using palette)? */
3318 /* Set up the foreground color for drawing relief lines of glyph
3319 string S. RELIEF is a pointer to a struct relief containing the GC
3320 with which lines will be drawn. Use a color that is FACTOR or
3321 DELTA lighter or darker than the relief's background which is found
3322 in S->f->output_data.x->relief_background. If such a color cannot
3323 be allocated, use DEFAULT_PIXEL, instead. */
3326 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3328 struct relief
*relief
;
3331 unsigned long default_pixel
;
3334 struct mac_output
*di
= f
->output_data
.mac
;
3335 unsigned long mask
= GCForeground
;
3336 unsigned long pixel
;
3337 unsigned long background
= di
->relief_background
;
3338 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3340 /* MAC_TODO: Free colors (if using palette)? */
3342 /* Allocate new color. */
3343 xgcv
.foreground
= default_pixel
;
3345 if (dpyinfo
->n_planes
!= 1
3346 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3348 relief
->allocated_p
= 1;
3349 xgcv
.foreground
= relief
->pixel
= pixel
;
3352 if (relief
->gc
== 0)
3354 #if 0 /* MAC_TODO: stipple */
3355 xgcv
.stipple
= dpyinfo
->gray
;
3358 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3361 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3365 /* Set up colors for the relief lines around glyph string S. */
3368 x_setup_relief_colors (s
)
3369 struct glyph_string
*s
;
3371 struct mac_output
*di
= s
->f
->output_data
.mac
;
3372 unsigned long color
;
3374 if (s
->face
->use_box_color_for_shadows_p
)
3375 color
= s
->face
->box_color
;
3376 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3378 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3379 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3384 /* Get the background color of the face. */
3385 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3386 color
= xgcv
.background
;
3389 if (di
->white_relief
.gc
== 0
3390 || color
!= di
->relief_background
)
3392 di
->relief_background
= color
;
3393 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3394 WHITE_PIX_DEFAULT (s
->f
));
3395 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3396 BLACK_PIX_DEFAULT (s
->f
));
3401 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3402 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3403 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3404 relief. LEFT_P non-zero means draw a relief on the left side of
3405 the rectangle. RIGHT_P non-zero means draw a relief on the right
3406 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3410 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3411 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3413 int left_x
, top_y
, right_x
, bottom_y
, width
;
3414 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3417 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3422 gc
= f
->output_data
.mac
->white_relief
.gc
;
3424 gc
= f
->output_data
.mac
->black_relief
.gc
;
3425 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3429 for (i
= 0; i
< width
; ++i
)
3430 mac_draw_line (f
, gc
,
3431 left_x
+ i
* left_p
, top_y
+ i
,
3432 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3436 for (i
= 0; i
< width
; ++i
)
3437 mac_draw_line (f
, gc
,
3438 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3440 mac_reset_clip_rectangles (dpy
, gc
);
3442 gc
= f
->output_data
.mac
->black_relief
.gc
;
3444 gc
= f
->output_data
.mac
->white_relief
.gc
;
3445 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3449 for (i
= 0; i
< width
; ++i
)
3450 mac_draw_line (f
, gc
,
3451 left_x
+ i
* left_p
, bottom_y
- i
,
3452 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3456 for (i
= 0; i
< width
; ++i
)
3457 mac_draw_line (f
, gc
,
3458 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3460 mac_reset_clip_rectangles (dpy
, gc
);
3464 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3465 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3466 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3467 left side of the rectangle. RIGHT_P non-zero means draw a line
3468 on the right side of the rectangle. CLIP_RECT is the clipping
3469 rectangle to use when drawing. */
3472 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3473 left_p
, right_p
, clip_rect
)
3474 struct glyph_string
*s
;
3475 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3480 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3481 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3482 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3485 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3486 right_x
- left_x
+ 1, width
);
3490 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3491 width
, bottom_y
- top_y
+ 1);
3494 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3495 right_x
- left_x
+ 1, width
);
3499 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3500 top_y
, width
, bottom_y
- top_y
+ 1);
3502 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3503 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3507 /* Draw a box around glyph string S. */
3510 x_draw_glyph_string_box (s
)
3511 struct glyph_string
*s
;
3513 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3514 int left_p
, right_p
;
3515 struct glyph
*last_glyph
;
3518 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3519 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3520 : window_box_right (s
->w
, s
->area
));
3522 /* The glyph that may have a right box line. */
3523 last_glyph
= (s
->cmp
|| s
->img
3525 : s
->first_glyph
+ s
->nchars
- 1);
3527 width
= abs (s
->face
->box_line_width
);
3528 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3530 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3532 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3534 bottom_y
= top_y
+ s
->height
- 1;
3536 left_p
= (s
->first_glyph
->left_box_line_p
3537 || (s
->hl
== DRAW_MOUSE_FACE
3539 || s
->prev
->hl
!= s
->hl
)));
3540 right_p
= (last_glyph
->right_box_line_p
3541 || (s
->hl
== DRAW_MOUSE_FACE
3543 || s
->next
->hl
!= s
->hl
)));
3545 get_glyph_string_clip_rect (s
, &clip_rect
);
3547 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3548 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3549 left_p
, right_p
, &clip_rect
);
3552 x_setup_relief_colors (s
);
3553 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3554 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3559 /* Draw foreground of image glyph string S. */
3562 x_draw_image_foreground (s
)
3563 struct glyph_string
*s
;
3566 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3568 /* If first glyph of S has a left box line, start drawing it to the
3569 right of that line. */
3570 if (s
->face
->box
!= FACE_NO_BOX
3571 && s
->first_glyph
->left_box_line_p
3573 x
+= abs (s
->face
->box_line_width
);
3575 /* If there is a margin around the image, adjust x- and y-position
3577 if (s
->slice
.x
== 0)
3578 x
+= s
->img
->hmargin
;
3579 if (s
->slice
.y
== 0)
3580 y
+= s
->img
->vmargin
;
3584 x_set_glyph_string_clipping (s
);
3587 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3588 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3589 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3593 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3594 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3595 s
->slice
.width
, s
->slice
.height
, x
, y
);
3602 mac_copy_area (s
->img
->pixmap
,
3603 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3604 s
->slice
.width
, s
->slice
.height
, x
, y
);
3607 /* When the image has a mask, we can expect that at
3608 least part of a mouse highlight or a block cursor will
3609 be visible. If the image doesn't have a mask, make
3610 a block cursor visible by drawing a rectangle around
3611 the image. I believe it's looking better if we do
3612 nothing here for mouse-face. */
3613 if (s
->hl
== DRAW_CURSOR
)
3615 int r
= s
->img
->relief
;
3617 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3618 s
->slice
.width
+ r
*2 - 1,
3619 s
->slice
.height
+ r
*2 - 1);
3624 /* Draw a rectangle if image could not be loaded. */
3625 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3626 s
->slice
.width
- 1, s
->slice
.height
- 1);
3630 /* Draw a relief around the image glyph string S. */
3633 x_draw_image_relief (s
)
3634 struct glyph_string
*s
;
3636 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3639 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3641 /* If first glyph of S has a left box line, start drawing it to the
3642 right of that line. */
3643 if (s
->face
->box
!= FACE_NO_BOX
3644 && s
->first_glyph
->left_box_line_p
3646 x
+= abs (s
->face
->box_line_width
);
3648 /* If there is a margin around the image, adjust x- and y-position
3650 if (s
->slice
.x
== 0)
3651 x
+= s
->img
->hmargin
;
3652 if (s
->slice
.y
== 0)
3653 y
+= s
->img
->vmargin
;
3655 if (s
->hl
== DRAW_IMAGE_SUNKEN
3656 || s
->hl
== DRAW_IMAGE_RAISED
)
3658 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3659 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3663 thick
= abs (s
->img
->relief
);
3664 raised_p
= s
->img
->relief
> 0;
3669 x1
= x
+ s
->slice
.width
+ thick
- 1;
3670 y1
= y
+ s
->slice
.height
+ thick
- 1;
3672 x_setup_relief_colors (s
);
3673 get_glyph_string_clip_rect (s
, &r
);
3674 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3676 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3678 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3683 /* Draw part of the background of glyph string S. X, Y, W, and H
3684 give the rectangle to draw. */
3687 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3688 struct glyph_string
*s
;
3691 #if 0 /* MAC_TODO: stipple */
3694 /* Fill background with a stipple pattern. */
3695 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3696 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3697 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3700 #endif /* MAC_TODO */
3701 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3705 /* Draw image glyph string S.
3708 s->x +-------------------------
3711 | +-------------------------
3714 | | +-------------------
3720 x_draw_image_glyph_string (s
)
3721 struct glyph_string
*s
;
3724 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3725 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3728 height
= s
->height
- 2 * box_line_vwidth
;
3731 /* Fill background with face under the image. Do it only if row is
3732 taller than image or if image has a clip mask to reduce
3734 s
->stippled_p
= s
->face
->stipple
!= 0;
3735 if (height
> s
->slice
.height
3739 || s
->img
->pixmap
== 0
3740 || s
->width
!= s
->background_width
)
3743 if (s
->first_glyph
->left_box_line_p
3745 x
+= box_line_hwidth
;
3748 if (s
->slice
.y
== 0)
3749 y
+= box_line_vwidth
;
3751 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3753 s
->background_filled_p
= 1;
3756 /* Draw the foreground. */
3757 x_draw_image_foreground (s
);
3759 /* If we must draw a relief around the image, do it. */
3761 || s
->hl
== DRAW_IMAGE_RAISED
3762 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3763 x_draw_image_relief (s
);
3767 /* Draw stretch glyph string S. */
3770 x_draw_stretch_glyph_string (s
)
3771 struct glyph_string
*s
;
3773 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3774 s
->stippled_p
= s
->face
->stipple
!= 0;
3776 if (s
->hl
== DRAW_CURSOR
3777 && !x_stretch_cursor_p
)
3779 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3780 as wide as the stretch glyph. */
3781 int width
, background_width
= s
->background_width
;
3782 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3786 background_width
-= left_x
- x
;
3789 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3792 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3794 /* Clear rest using the GC of the original non-cursor face. */
3795 if (width
< background_width
)
3798 int w
= background_width
- width
, h
= s
->height
;
3803 if (s
->row
->mouse_face_p
3804 && cursor_in_mouse_face_p (s
->w
))
3806 x_set_mouse_face_gc (s
);
3812 get_glyph_string_clip_rect (s
, &r
);
3813 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3815 #if 0 /* MAC_TODO: stipple */
3816 if (s
->face
->stipple
)
3818 /* Fill background with a stipple pattern. */
3819 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3820 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3821 XSetFillStyle (s
->display
, gc
, FillSolid
);
3824 #endif /* MAC_TODO */
3825 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3828 else if (!s
->background_filled_p
)
3830 int background_width
= s
->background_width
;
3831 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3833 /* Don't draw into left margin, fringe or scrollbar area
3834 except for header line and mode line. */
3835 if (x
< left_x
&& !s
->row
->mode_line_p
)
3837 background_width
-= left_x
- x
;
3840 if (background_width
> 0)
3841 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3844 s
->background_filled_p
= 1;
3848 /* Draw glyph string S. */
3851 x_draw_glyph_string (s
)
3852 struct glyph_string
*s
;
3854 int relief_drawn_p
= 0;
3856 /* If S draws into the background of its successor that does not
3857 draw a cursor, draw the background of the successor first so that
3858 S can draw into it. This makes S->next use XDrawString instead
3859 of XDrawImageString. */
3860 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3861 && s
->next
->hl
!= DRAW_CURSOR
)
3863 xassert (s
->next
->img
== NULL
);
3864 x_set_glyph_string_gc (s
->next
);
3865 x_set_glyph_string_clipping (s
->next
);
3866 x_draw_glyph_string_background (s
->next
, 1);
3869 /* Set up S->gc, set clipping and draw S. */
3870 x_set_glyph_string_gc (s
);
3872 /* Draw relief (if any) in advance for char/composition so that the
3873 glyph string can be drawn over it. */
3874 if (!s
->for_overlaps
3875 && s
->face
->box
!= FACE_NO_BOX
3876 && (s
->first_glyph
->type
== CHAR_GLYPH
3877 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3880 x_set_glyph_string_clipping (s
);
3881 x_draw_glyph_string_background (s
, 1);
3882 x_draw_glyph_string_box (s
);
3883 x_set_glyph_string_clipping (s
);
3887 x_set_glyph_string_clipping (s
);
3889 switch (s
->first_glyph
->type
)
3892 x_draw_image_glyph_string (s
);
3896 x_draw_stretch_glyph_string (s
);
3900 if (s
->for_overlaps
)
3901 s
->background_filled_p
= 1;
3903 x_draw_glyph_string_background (s
, 0);
3904 x_draw_glyph_string_foreground (s
);
3907 case COMPOSITE_GLYPH
:
3908 if (s
->for_overlaps
|| s
->gidx
> 0)
3909 s
->background_filled_p
= 1;
3911 x_draw_glyph_string_background (s
, 1);
3912 x_draw_composite_glyph_string_foreground (s
);
3919 if (!s
->for_overlaps
)
3921 /* Draw underline. */
3922 if (s
->face
->underline_p
)
3924 unsigned long tem
, h
;
3928 /* Get the underline thickness. Default is 1 pixel. */
3929 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3933 y
= s
->y
+ s
->height
- h
;
3934 if (!x_underline_at_descent_line
)
3936 /* Get the underline position. This is the recommended
3937 vertical offset in pixels from the baseline to the top of
3938 the underline. This is a signed value according to the
3939 specs, and its default is
3941 ROUND ((maximum descent) / 2), with
3942 ROUND(x) = floor (x + 0.5) */
3945 if (x_use_underline_position_properties
3946 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3947 y
= s
->ybase
+ (long) tem
;
3951 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3954 if (s
->face
->underline_defaulted_p
)
3955 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3956 s
->background_width
, h
);
3960 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3961 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3962 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3963 s
->background_width
, h
);
3964 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3968 /* Draw overline. */
3969 if (s
->face
->overline_p
)
3971 unsigned long dy
= 0, h
= 1;
3973 if (s
->face
->overline_color_defaulted_p
)
3974 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3975 s
->background_width
, h
);
3979 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3980 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3981 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3982 s
->background_width
, h
);
3983 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3987 /* Draw strike-through. */
3988 if (s
->face
->strike_through_p
)
3990 unsigned long h
= 1;
3991 unsigned long dy
= (s
->height
- h
) / 2;
3993 if (s
->face
->strike_through_color_defaulted_p
)
3994 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3999 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4000 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4001 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4003 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4007 /* Draw relief if not yet drawn. */
4008 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4009 x_draw_glyph_string_box (s
);
4012 /* Reset clipping. */
4013 mac_reset_clip_rectangles (s
->display
, s
->gc
);
4016 /* Shift display to make room for inserted glyphs. */
4019 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4021 int x
, y
, width
, height
, shift_by
;
4023 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4024 x
, y
, width
, height
,
4028 /* Delete N glyphs at the nominal cursor position. Not implemented
4039 /* Clear entire frame. If updating_frame is non-null, clear that
4040 frame. Otherwise clear the selected frame. */
4050 f
= SELECTED_FRAME ();
4052 /* Clearing the frame will erase any cursor, so mark them all as no
4054 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4055 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4056 output_cursor
.x
= -1;
4058 /* We don't set the output cursor here because there will always
4059 follow an explicit cursor_to. */
4061 mac_clear_window (f
);
4063 /* We have to clear the scroll bars, too. If we have changed
4064 colors or something like that, then they should be notified. */
4065 x_scroll_bar_clear (f
);
4067 XFlush (FRAME_MAC_DISPLAY (f
));
4073 /* Invert the middle quarter of the frame for .15 sec. */
4075 /* We use the select system call to do the waiting, so we have to make
4076 sure it's available. If it isn't, we just won't do visual bells. */
4078 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4081 /* Subtract the `struct timeval' values X and Y, storing the result in
4082 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4085 timeval_subtract (result
, x
, y
)
4086 struct timeval
*result
, x
, y
;
4088 /* Perform the carry for the later subtraction by updating y. This
4089 is safer because on some systems the tv_sec member is unsigned. */
4090 if (x
.tv_usec
< y
.tv_usec
)
4092 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4093 y
.tv_usec
-= 1000000 * nsec
;
4097 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4099 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4100 y
.tv_usec
+= 1000000 * nsec
;
4104 /* Compute the time remaining to wait. tv_usec is certainly
4106 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4107 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4109 /* Return indication of whether the result should be considered
4111 return x
.tv_sec
< y
.tv_sec
;
4118 /* Get the height not including a menu bar widget. */
4119 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4120 /* Height of each line to flash. */
4121 int flash_height
= FRAME_LINE_HEIGHT (f
);
4122 /* These will be the left and right margins of the rectangles. */
4123 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4124 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4128 /* Don't flash the area between a scroll bar and the frame
4129 edge it is next to. */
4130 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4132 case vertical_scroll_bar_left
:
4133 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4136 case vertical_scroll_bar_right
:
4137 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4144 width
= flash_right
- flash_left
;
4148 /* If window is tall, flash top and bottom line. */
4149 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4151 mac_invert_rectangle (f
, flash_left
,
4152 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4153 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4154 width
, flash_height
);
4155 mac_invert_rectangle (f
, flash_left
,
4156 (height
- flash_height
4157 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4158 width
, flash_height
);
4161 /* If it is short, flash it all. */
4162 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4163 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4168 struct timeval wakeup
;
4170 EMACS_GET_TIME (wakeup
);
4172 /* Compute time to wait until, propagating carry from usecs. */
4173 wakeup
.tv_usec
+= 150000;
4174 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4175 wakeup
.tv_usec
%= 1000000;
4177 /* Keep waiting until past the time wakeup or any input gets
4179 while (! detect_input_pending ())
4181 struct timeval current
;
4182 struct timeval timeout
;
4184 EMACS_GET_TIME (current
);
4186 /* Break if result would be negative. */
4187 if (timeval_subtract (¤t
, wakeup
, current
))
4190 /* How long `select' should wait. */
4192 timeout
.tv_usec
= 10000;
4194 /* Try to wait that long--but we might wake up sooner. */
4195 select (0, NULL
, NULL
, NULL
, &timeout
);
4199 /* If window is tall, flash top and bottom line. */
4200 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4202 mac_invert_rectangle (f
, flash_left
,
4203 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4204 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4205 width
, flash_height
);
4206 mac_invert_rectangle (f
, flash_left
,
4207 (height
- flash_height
4208 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4209 width
, flash_height
);
4212 /* If it is short, flash it all. */
4213 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4214 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4221 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4224 /* Make audible bell. */
4229 struct frame
*f
= SELECTED_FRAME ();
4231 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4239 XFlush (FRAME_MAC_DISPLAY (f
));
4245 /* Specify how many text lines, from the top of the window,
4246 should be affected by insert-lines and delete-lines operations.
4247 This, and those operations, are used only within an update
4248 that is bounded by calls to x_update_begin and x_update_end. */
4251 XTset_terminal_window (n
)
4254 /* This function intentionally left blank. */
4259 /***********************************************************************
4261 ***********************************************************************/
4263 /* Perform an insert-lines or delete-lines operation, inserting N
4264 lines or deleting -N lines at vertical position VPOS. */
4267 x_ins_del_lines (vpos
, n
)
4274 /* Scroll part of the display as described by RUN. */
4277 x_scroll_run (w
, run
)
4281 struct frame
*f
= XFRAME (w
->frame
);
4282 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4284 /* Get frame-relative bounding box of the text display area of W,
4285 without mode lines. Include in this box the left and right
4287 window_box (w
, -1, &x
, &y
, &width
, &height
);
4289 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4290 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4291 bottom_y
= y
+ height
;
4295 /* Scrolling up. Make sure we don't copy part of the mode
4296 line at the bottom. */
4297 if (from_y
+ run
->height
> bottom_y
)
4298 height
= bottom_y
- from_y
;
4300 height
= run
->height
;
4304 /* Scolling down. Make sure we don't copy over the mode line.
4306 if (to_y
+ run
->height
> bottom_y
)
4307 height
= bottom_y
- to_y
;
4309 height
= run
->height
;
4314 /* Cursor off. Will be switched on again in x_update_window_end. */
4318 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4328 /***********************************************************************
4330 ***********************************************************************/
4337 x_update_cursor (f
, 1);
4341 frame_unhighlight (f
)
4344 x_update_cursor (f
, 1);
4347 /* The focus has changed. Update the frames as necessary to reflect
4348 the new situation. Note that we can't change the selected frame
4349 here, because the Lisp code we are interrupting might become confused.
4350 Each event gets marked with the frame in which it occurred, so the
4351 Lisp code can tell when the switch took place by examining the events. */
4354 x_new_focus_frame (dpyinfo
, frame
)
4355 struct x_display_info
*dpyinfo
;
4356 struct frame
*frame
;
4358 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4360 if (frame
!= dpyinfo
->x_focus_frame
)
4362 /* Set this before calling other routines, so that they see
4363 the correct value of x_focus_frame. */
4364 dpyinfo
->x_focus_frame
= frame
;
4366 if (old_focus
&& old_focus
->auto_lower
)
4367 x_lower_frame (old_focus
);
4370 selected_frame
= frame
;
4371 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4373 Fselect_window (selected_frame
->selected_window
, Qnil
);
4374 choose_minibuf_frame ();
4377 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4378 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4380 pending_autoraise_frame
= 0;
4382 #if USE_MAC_FONT_PANEL
4384 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4388 x_frame_rehighlight (dpyinfo
);
4391 /* Handle FocusIn and FocusOut state changes for FRAME.
4392 If FRAME has focus and there exists more than one frame, puts
4393 a FOCUS_IN_EVENT into *BUFP. */
4396 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4398 struct mac_display_info
*dpyinfo
;
4399 struct frame
*frame
;
4400 struct input_event
*bufp
;
4402 if (type
== activeFlag
)
4404 if (dpyinfo
->x_focus_event_frame
!= frame
)
4406 x_new_focus_frame (dpyinfo
, frame
);
4407 dpyinfo
->x_focus_event_frame
= frame
;
4409 /* Don't stop displaying the initial startup message
4410 for a switch-frame event we don't need. */
4411 if (GC_NILP (Vterminal_frame
)
4412 && GC_CONSP (Vframe_list
)
4413 && !GC_NILP (XCDR (Vframe_list
)))
4415 bufp
->kind
= FOCUS_IN_EVENT
;
4416 XSETFRAME (bufp
->frame_or_window
, frame
);
4422 if (dpyinfo
->x_focus_event_frame
== frame
)
4424 dpyinfo
->x_focus_event_frame
= 0;
4425 x_new_focus_frame (dpyinfo
, 0);
4430 /* The focus may have changed. Figure out if it is a real focus change,
4431 by checking both FocusIn/Out and Enter/LeaveNotify events.
4433 Returns FOCUS_IN_EVENT event in *BUFP. */
4436 x_detect_focus_change (dpyinfo
, event
, bufp
)
4437 struct mac_display_info
*dpyinfo
;
4438 const EventRecord
*event
;
4439 struct input_event
*bufp
;
4441 struct frame
*frame
;
4443 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4447 /* On Mac, this is only called from focus events, so no switch needed. */
4448 mac_focus_changed ((event
->modifiers
& activeFlag
),
4449 dpyinfo
, frame
, bufp
);
4453 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4456 x_mouse_leave (dpyinfo
)
4457 struct x_display_info
*dpyinfo
;
4459 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4462 /* The focus has changed, or we have redirected a frame's focus to
4463 another frame (this happens when a frame uses a surrogate
4464 mini-buffer frame). Shift the highlight as appropriate.
4466 The FRAME argument doesn't necessarily have anything to do with which
4467 frame is being highlighted or un-highlighted; we only use it to find
4468 the appropriate X display info. */
4471 XTframe_rehighlight (frame
)
4472 struct frame
*frame
;
4474 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4478 x_frame_rehighlight (dpyinfo
)
4479 struct x_display_info
*dpyinfo
;
4481 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4483 if (dpyinfo
->x_focus_frame
)
4485 dpyinfo
->x_highlight_frame
4486 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4487 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4488 : dpyinfo
->x_focus_frame
);
4489 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4491 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4492 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4496 dpyinfo
->x_highlight_frame
= 0;
4498 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4501 frame_unhighlight (old_highlight
);
4502 if (dpyinfo
->x_highlight_frame
)
4503 frame_highlight (dpyinfo
->x_highlight_frame
);
4509 /* Convert a keysym to its name. */
4512 x_get_keysym_name (keysym
)
4519 value
= XKeysymToString (keysym
);
4530 /* Function to report a mouse movement to the mainstream Emacs code.
4531 The input handler calls this.
4533 We have received a mouse movement event, which is given in *event.
4534 If the mouse is over a different glyph than it was last time, tell
4535 the mainstream emacs code by setting mouse_moved. If not, ask for
4536 another motion event, so we can check again the next time it moves. */
4538 static Point last_mouse_motion_position
;
4539 static Lisp_Object last_mouse_motion_frame
;
4542 note_mouse_movement (frame
, pos
)
4546 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4547 #if TARGET_API_MAC_CARBON
4551 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4552 last_mouse_motion_position
= *pos
;
4553 XSETFRAME (last_mouse_motion_frame
, frame
);
4555 if (frame
== dpyinfo
->mouse_face_mouse_frame
4556 #if TARGET_API_MAC_CARBON
4557 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4559 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4563 /* This case corresponds to LeaveNotify in X11. If we move
4564 outside the frame, then we're certainly no longer on any text
4566 clear_mouse_face (dpyinfo
);
4567 dpyinfo
->mouse_face_mouse_frame
= 0;
4568 if (!dpyinfo
->grabbed
)
4569 rif
->define_frame_cursor (frame
,
4570 frame
->output_data
.mac
->nontext_cursor
);
4573 /* Has the mouse moved off the glyph it was on at the last sighting? */
4574 if (frame
!= last_mouse_glyph_frame
4575 || !PtInRect (*pos
, &last_mouse_glyph
))
4577 frame
->mouse_moved
= 1;
4578 last_mouse_scroll_bar
= Qnil
;
4579 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4580 /* Remember which glyph we're now on. */
4581 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4582 last_mouse_glyph_frame
= frame
;
4590 /************************************************************************
4592 ************************************************************************/
4594 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4597 redo_mouse_highlight ()
4599 if (!NILP (last_mouse_motion_frame
)
4600 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4601 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4602 last_mouse_motion_position
.h
,
4603 last_mouse_motion_position
.v
);
4607 static struct frame
*
4608 mac_focus_frame (dpyinfo
)
4609 struct mac_display_info
*dpyinfo
;
4611 if (dpyinfo
->x_focus_frame
)
4612 return dpyinfo
->x_focus_frame
;
4614 /* Mac version may get events, such as a menu bar click, even when
4615 all the frames are invisible. In this case, we regard the
4616 event came to the selected frame. */
4617 return SELECTED_FRAME ();
4621 /* Return the current position of the mouse.
4622 *FP should be a frame which indicates which display to ask about.
4624 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4625 and *PART to the frame, window, and scroll bar part that the mouse
4626 is over. Set *X and *Y to the portion and whole of the mouse's
4627 position on the scroll bar.
4629 If the mouse movement started elsewhere, set *FP to the frame the
4630 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4633 Set *TIME to the server time-stamp for the time at which the mouse
4634 was at this position.
4636 Don't store anything if we don't have a valid set of values to report.
4638 This clears the mouse_moved flag, so we can wait for the next mouse
4642 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4645 Lisp_Object
*bar_window
;
4646 enum scroll_bar_part
*part
;
4648 unsigned long *time
;
4654 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4655 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4658 Lisp_Object frame
, tail
;
4660 /* Clear the mouse-moved flag for every frame on this display. */
4661 FOR_EACH_FRAME (tail
, frame
)
4662 XFRAME (frame
)->mouse_moved
= 0;
4664 last_mouse_scroll_bar
= Qnil
;
4666 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4667 && FRAME_LIVE_P (last_mouse_frame
))
4668 f1
= last_mouse_frame
;
4670 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4674 /* Ok, we found a frame. Store all the values.
4675 last_mouse_glyph is a rectangle used to reduce the
4676 generation of mouse events. To not miss any motion
4677 events, we must divide the frame into rectangles of the
4678 size of the smallest character that could be displayed
4679 on it, i.e. into the same rectangles that matrices on
4680 the frame are divided into. */
4683 #if TARGET_API_MAC_CARBON
4684 GetGlobalMouse (&mouse_pos
);
4685 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4686 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4688 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4689 GetMouse (&mouse_pos
);
4691 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4693 last_mouse_glyph_frame
= f1
;
4698 XSETINT (*x
, mouse_pos
.h
);
4699 XSETINT (*y
, mouse_pos
.v
);
4700 *time
= last_mouse_movement_time
;
4708 /************************************************************************
4710 ************************************************************************/
4712 #ifdef USE_TOOLKIT_SCROLL_BARS
4714 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4715 static OSStatus install_scroll_bar_timer
P_ ((void));
4716 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4717 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4718 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4719 struct input_event
*));
4720 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4722 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4723 ControlPartCode
, Point
,
4724 struct input_event
*));
4725 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4726 struct input_event
*));
4727 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4728 Point
, struct input_event
*));
4729 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4732 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4734 static int last_scroll_bar_part
;
4736 static EventLoopTimerRef scroll_bar_timer
;
4738 static int scroll_bar_timer_event_posted_p
;
4740 #define SCROLL_BAR_FIRST_DELAY 0.5
4741 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4744 scroll_bar_timer_callback (timer
, data
)
4745 EventLoopTimerRef timer
;
4750 err
= mac_post_mouse_moved_event ();
4752 scroll_bar_timer_event_posted_p
= 1;
4756 install_scroll_bar_timer ()
4758 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4760 if (scroll_bar_timer_callbackUPP
== NULL
)
4761 scroll_bar_timer_callbackUPP
=
4762 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4764 if (scroll_bar_timer
== NULL
)
4765 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4766 kEventDurationForever as delays. */
4768 InstallEventLoopTimer (GetCurrentEventLoop (),
4769 kEventDurationForever
, kEventDurationForever
,
4770 scroll_bar_timer_callbackUPP
, NULL
,
4775 set_scroll_bar_timer (delay
)
4776 EventTimerInterval delay
;
4778 if (scroll_bar_timer
== NULL
)
4779 install_scroll_bar_timer ();
4781 scroll_bar_timer_event_posted_p
= 0;
4783 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4787 control_part_code_to_scroll_bar_part (part_code
)
4788 ControlPartCode part_code
;
4792 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4793 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4794 case kControlPageUpPart
: return scroll_bar_above_handle
;
4795 case kControlPageDownPart
: return scroll_bar_below_handle
;
4796 case kControlIndicatorPart
: return scroll_bar_handle
;
4803 construct_scroll_bar_click (bar
, part
, bufp
)
4804 struct scroll_bar
*bar
;
4806 struct input_event
*bufp
;
4808 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4809 bufp
->frame_or_window
= bar
->window
;
4813 XSETINT (bufp
->x
, 0);
4814 XSETINT (bufp
->y
, 0);
4815 bufp
->modifiers
= 0;
4819 get_control_part_bounds (ch
, part_code
, rect
)
4821 ControlPartCode part_code
;
4824 RgnHandle region
= NewRgn ();
4827 err
= GetControlRegion (ch
, part_code
, region
);
4829 GetRegionBounds (region
, rect
);
4830 DisposeRgn (region
);
4836 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4837 struct scroll_bar
*bar
;
4838 ControlPartCode part_code
;
4840 struct input_event
*bufp
;
4842 int part
= control_part_code_to_scroll_bar_part (part_code
);
4847 if (part
!= scroll_bar_handle
)
4849 construct_scroll_bar_click (bar
, part
, bufp
);
4850 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4851 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4852 bar
->dragging
= Qnil
;
4858 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4859 kControlIndicatorPart
, &r
);
4860 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4863 last_scroll_bar_part
= part
;
4864 tracked_scroll_bar
= bar
;
4868 x_scroll_bar_handle_release (bar
, bufp
)
4869 struct scroll_bar
*bar
;
4870 struct input_event
*bufp
;
4872 if (last_scroll_bar_part
!= scroll_bar_handle
4873 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4874 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4876 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4877 set_scroll_bar_timer (kEventDurationForever
);
4879 last_scroll_bar_part
= -1;
4880 bar
->dragging
= Qnil
;
4881 tracked_scroll_bar
= NULL
;
4885 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4887 struct scroll_bar
*bar
;
4889 struct input_event
*bufp
;
4891 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4893 if (last_scroll_bar_part
== scroll_bar_handle
)
4898 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4899 kControlIndicatorPart
, &r
);
4901 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4902 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4904 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4905 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4909 if (top
> top_range
)
4912 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4913 XSETINT (bufp
->x
, top
);
4914 XSETINT (bufp
->y
, top_range
);
4918 ControlPartCode part_code
;
4919 int unhilite_p
= 0, part
;
4921 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4925 part
= control_part_code_to_scroll_bar_part (part_code
);
4927 switch (last_scroll_bar_part
)
4929 case scroll_bar_above_handle
:
4930 case scroll_bar_below_handle
:
4931 if (part
!= scroll_bar_above_handle
4932 && part
!= scroll_bar_below_handle
)
4936 case scroll_bar_up_arrow
:
4937 case scroll_bar_down_arrow
:
4938 if (part
!= scroll_bar_up_arrow
4939 && part
!= scroll_bar_down_arrow
)
4946 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4947 else if (part
!= last_scroll_bar_part
4948 || scroll_bar_timer_event_posted_p
)
4950 construct_scroll_bar_click (bar
, part
, bufp
);
4951 last_scroll_bar_part
= part
;
4952 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4953 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4958 /* Set the thumb size and position of scroll bar BAR. We are currently
4959 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4962 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4963 struct scroll_bar
*bar
;
4964 int portion
, position
, whole
;
4966 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4967 int value
, viewsize
, maximum
;
4969 if (XINT (bar
->track_height
) == 0)
4972 if (whole
<= portion
)
4973 value
= 0, viewsize
= 1, maximum
= 0;
4978 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4979 scale
= (float) maximum
/ (whole
- portion
);
4980 value
= position
* scale
+ 0.5f
;
4981 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
4986 if (GetControlViewSize (ch
) != viewsize
4987 || GetControl32BitValue (ch
) != value
4988 || GetControl32BitMaximum (ch
) != maximum
)
4990 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4991 SetControlVisibility (ch
, false, false);
4993 SetControl32BitMaximum (ch
, maximum
);
4994 SetControl32BitValue (ch
, value
);
4995 SetControlViewSize (ch
, viewsize
);
4997 SetControlVisibility (ch
, true, true);
5003 #endif /* USE_TOOLKIT_SCROLL_BARS */
5007 /************************************************************************
5008 Scroll bars, general
5009 ************************************************************************/
5011 /* Create a scroll bar and return the scroll bar vector for it. W is
5012 the Emacs window on which to create the scroll bar. TOP, LEFT,
5013 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5016 static struct scroll_bar
*
5017 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5019 int top
, left
, width
, height
, disp_top
, disp_height
;
5021 struct frame
*f
= XFRAME (w
->frame
);
5022 struct scroll_bar
*bar
5023 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5031 r
.right
= left
+ width
;
5032 r
.bottom
= disp_top
+ disp_height
;
5035 mac_prepare_for_quickdraw (f
);
5037 #if TARGET_API_MAC_CARBON
5038 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5039 #ifdef USE_TOOLKIT_SCROLL_BARS
5042 width
< disp_height
,
5044 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5046 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5047 0, 0, 0, scrollBarProc
, (long) bar
);
5049 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5051 XSETWINDOW (bar
->window
, w
);
5052 XSETINT (bar
->top
, top
);
5053 XSETINT (bar
->left
, left
);
5054 XSETINT (bar
->width
, width
);
5055 XSETINT (bar
->height
, height
);
5056 XSETINT (bar
->start
, 0);
5057 XSETINT (bar
->end
, 0);
5058 bar
->dragging
= Qnil
;
5060 bar
->fringe_extended_p
= Qnil
;
5062 #ifdef USE_TOOLKIT_SCROLL_BARS
5063 bar
->track_top
= Qnil
;
5064 bar
->track_height
= Qnil
;
5065 bar
->min_handle
= Qnil
;
5068 /* Add bar to its frame's list of scroll bars. */
5069 bar
->next
= FRAME_SCROLL_BARS (f
);
5071 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5072 if (!NILP (bar
->next
))
5073 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5080 /* Draw BAR's handle in the proper position.
5082 If the handle is already drawn from START to END, don't bother
5083 redrawing it, unless REBUILD is non-zero; in that case, always
5084 redraw it. (REBUILD is handy for drawing the handle after expose
5087 Normally, we want to constrain the start and end of the handle to
5088 fit inside its rectangle, but if the user is dragging the scroll
5089 bar handle, we want to let them drag it down all the way, so that
5090 the bar's top is as far down as it goes; otherwise, there's no way
5091 to move to the very end of the buffer. */
5093 #ifndef USE_TOOLKIT_SCROLL_BARS
5096 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5097 struct scroll_bar
*bar
;
5101 int dragging
= ! NILP (bar
->dragging
);
5102 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5103 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5104 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5105 int length
= end
- start
;
5107 /* If the display is already accurate, do nothing. */
5109 && start
== XINT (bar
->start
)
5110 && end
== XINT (bar
->end
))
5115 /* Make sure the values are reasonable, and try to preserve the
5116 distance between start and end. */
5119 else if (start
> top_range
)
5121 end
= start
+ length
;
5125 else if (end
> top_range
&& ! dragging
)
5128 /* Store the adjusted setting in the scroll bar. */
5129 XSETINT (bar
->start
, start
);
5130 XSETINT (bar
->end
, end
);
5132 /* Clip the end position, just for display. */
5133 if (end
> top_range
)
5136 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5137 top positions, to make sure the handle is always at least that
5138 many pixels tall. */
5139 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5141 SetControlMinimum (ch
, 0);
5142 /* Don't inadvertently activate deactivated scroll bars */
5143 if (GetControlMaximum (ch
) != -1)
5144 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5146 SetControlValue (ch
, start
);
5147 #if TARGET_API_MAC_CARBON
5148 SetControlViewSize (ch
, end
- start
);
5154 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5156 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5160 x_scroll_bar_remove (bar
)
5161 struct scroll_bar
*bar
;
5163 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5168 mac_prepare_for_quickdraw (f
);
5170 /* Destroy the Mac scroll bar control */
5171 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5173 /* Disassociate this scroll bar from its window. */
5174 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5180 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5181 that we are displaying PORTION characters out of a total of WHOLE
5182 characters, starting at POSITION. If WINDOW has no scroll bar,
5186 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5188 int portion
, whole
, position
;
5190 struct frame
*f
= XFRAME (w
->frame
);
5191 struct scroll_bar
*bar
;
5192 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5193 int window_y
, window_height
;
5195 int fringe_extended_p
;
5198 /* Get window dimensions. */
5199 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5201 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5202 height
= window_height
;
5204 /* Compute the left edge of the scroll bar area. */
5205 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5207 /* Compute the width of the scroll bar which might be less than
5208 the width of the area reserved for the scroll bar. */
5209 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5210 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5214 /* Compute the left edge of the scroll bar. */
5215 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5216 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5218 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5220 /* Adjustments according to Inside Macintosh to make it look nice */
5222 disp_height
= height
;
5229 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5235 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5240 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5241 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5242 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5243 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5244 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5246 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5247 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5248 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5249 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5252 /* Does the scroll bar exist yet? */
5253 if (NILP (w
->vertical_scroll_bar
))
5257 if (fringe_extended_p
)
5258 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5261 mac_clear_area (f
, left
, top
, width
, height
);
5263 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5265 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5269 /* It may just need to be moved and resized. */
5272 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5273 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5277 /* If already correctly positioned, do nothing. */
5278 if (!(XINT (bar
->left
) == sb_left
5279 && XINT (bar
->top
) == top
5280 && XINT (bar
->width
) == sb_width
5281 && XINT (bar
->height
) == height
5283 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5287 /* Since toolkit scroll bars are smaller than the space reserved
5288 for them on the frame, we have to clear "under" them. */
5290 if (fringe_extended_p
)
5291 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5294 mac_clear_area (f
, left
, top
, width
, height
);
5297 mac_prepare_for_quickdraw (f
);
5300 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5301 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5303 #ifndef USE_TOOLKIT_SCROLL_BARS
5304 if (sb_width
< disp_height
)
5308 /* Remember new settings. */
5309 XSETINT (bar
->left
, sb_left
);
5310 XSETINT (bar
->top
, top
);
5311 XSETINT (bar
->width
, sb_width
);
5312 XSETINT (bar
->height
, height
);
5313 #ifdef USE_TOOLKIT_SCROLL_BARS
5314 bar
->track_top
= Qnil
;
5315 bar
->track_height
= Qnil
;
5316 bar
->min_handle
= Qnil
;
5324 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5327 #ifdef USE_TOOLKIT_SCROLL_BARS
5328 if (NILP (bar
->track_top
))
5330 if (sb_width
>= disp_height
5332 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5336 XSETINT (bar
->track_top
, 0);
5337 XSETINT (bar
->track_height
, 0);
5338 XSETINT (bar
->min_handle
, 0);
5342 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5347 SetControl32BitMinimum (ch
, 0);
5348 SetControl32BitMaximum (ch
, 1 << 30);
5349 SetControlViewSize (ch
, 1);
5351 /* Move the scroll bar thumb to the top. */
5352 SetControl32BitValue (ch
, 0);
5353 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5355 /* Move the scroll bar thumb to the bottom. */
5356 SetControl32BitValue (ch
, 1 << 30);
5357 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5359 UnionRect (&r0
, &r1
, &r0
);
5360 XSETINT (bar
->track_top
, r0
.top
);
5361 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5362 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5364 /* Don't show the scroll bar if its height is not enough to
5365 display the scroll bar thumb. */
5366 if (r0
.bottom
- r0
.top
> 0)
5373 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5374 #else /* not USE_TOOLKIT_SCROLL_BARS */
5375 /* Set the scroll bar's current state, unless we're currently being
5377 if (NILP (bar
->dragging
))
5379 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5382 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5385 int start
= ((double) position
* top_range
) / whole
;
5386 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5387 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5390 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5394 /* The following three hooks are used when we're doing a thorough
5395 redisplay of the frame. We don't explicitly know which scroll bars
5396 are going to be deleted, because keeping track of when windows go
5397 away is a real pain - "Can you say set-window-configuration, boys
5398 and girls?" Instead, we just assert at the beginning of redisplay
5399 that *all* scroll bars are to be removed, and then save a scroll bar
5400 from the fiery pit when we actually redisplay its window. */
5402 /* Arrange for all scroll bars on FRAME to be removed at the next call
5403 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5404 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5407 XTcondemn_scroll_bars (frame
)
5410 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5411 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5414 bar
= FRAME_SCROLL_BARS (frame
);
5415 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5416 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5417 XSCROLL_BAR (bar
)->prev
= Qnil
;
5418 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5419 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5420 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5425 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5426 Note that WINDOW isn't necessarily condemned at all. */
5429 XTredeem_scroll_bar (window
)
5430 struct window
*window
;
5432 struct scroll_bar
*bar
;
5435 /* We can't redeem this window's scroll bar if it doesn't have one. */
5436 if (NILP (window
->vertical_scroll_bar
))
5439 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5441 /* Unlink it from the condemned list. */
5442 f
= XFRAME (WINDOW_FRAME (window
));
5443 if (NILP (bar
->prev
))
5445 /* If the prev pointer is nil, it must be the first in one of
5447 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5448 /* It's not condemned. Everything's fine. */
5450 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5451 window
->vertical_scroll_bar
))
5452 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5454 /* If its prev pointer is nil, it must be at the front of
5455 one or the other! */
5459 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5461 if (! NILP (bar
->next
))
5462 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5464 bar
->next
= FRAME_SCROLL_BARS (f
);
5466 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5467 if (! NILP (bar
->next
))
5468 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5471 /* Remove all scroll bars on FRAME that haven't been saved since the
5472 last call to `*condemn_scroll_bars_hook'. */
5475 XTjudge_scroll_bars (f
)
5478 Lisp_Object bar
, next
;
5480 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5482 /* Clear out the condemned list now so we won't try to process any
5483 more events on the hapless scroll bars. */
5484 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5486 for (; ! NILP (bar
); bar
= next
)
5488 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5490 x_scroll_bar_remove (b
);
5493 b
->next
= b
->prev
= Qnil
;
5496 /* Now there should be no references to the condemned scroll bars,
5497 and they should get garbage-collected. */
5501 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5502 is set to something other than NO_EVENT, it is enqueued.
5504 This may be called from a signal handler, so we have to ignore GC
5508 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5509 struct scroll_bar
*bar
;
5510 ControlPartCode part_code
;
5511 const EventRecord
*er
;
5512 struct input_event
*bufp
;
5514 int win_y
, top_range
;
5516 if (! GC_WINDOWP (bar
->window
))
5519 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5520 bufp
->frame_or_window
= bar
->window
;
5523 bar
->dragging
= Qnil
;
5527 case kControlUpButtonPart
:
5528 bufp
->part
= scroll_bar_up_arrow
;
5530 case kControlDownButtonPart
:
5531 bufp
->part
= scroll_bar_down_arrow
;
5533 case kControlPageUpPart
:
5534 bufp
->part
= scroll_bar_above_handle
;
5536 case kControlPageDownPart
:
5537 bufp
->part
= scroll_bar_below_handle
;
5539 #if TARGET_API_MAC_CARBON
5542 case kControlIndicatorPart
:
5544 if (er
->what
== mouseDown
)
5545 bar
->dragging
= make_number (0);
5546 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5547 bufp
->part
= scroll_bar_handle
;
5551 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5552 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5554 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5558 if (! NILP (bar
->dragging
))
5559 win_y
-= XINT (bar
->dragging
);
5563 if (win_y
> top_range
)
5566 XSETINT (bufp
->x
, win_y
);
5567 XSETINT (bufp
->y
, top_range
);
5570 #ifndef USE_TOOLKIT_SCROLL_BARS
5572 /* Handle some mouse motion while someone is dragging the scroll bar.
5574 This may be called from a signal handler, so we have to ignore GC
5578 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5579 struct scroll_bar
*bar
;
5583 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5585 last_mouse_movement_time
= t
;
5588 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5590 /* If we're dragging the bar, display it. */
5591 if (! GC_NILP (bar
->dragging
))
5593 /* Where should the handle be now? */
5594 int new_start
= y_pos
- 24;
5596 if (new_start
!= XINT (bar
->start
))
5598 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5600 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5605 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5607 /* Return information to the user about the current position of the mouse
5608 on the scroll bar. */
5611 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5613 Lisp_Object
*bar_window
;
5614 enum scroll_bar_part
*part
;
5616 unsigned long *time
;
5618 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5619 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5620 #if TARGET_API_MAC_CARBON
5621 WindowRef wp
= GetControlOwner (ch
);
5623 WindowRef wp
= (*ch
)->contrlOwner
;
5626 struct frame
*f
= mac_window_to_frame (wp
);
5627 int win_y
, top_range
;
5629 #if TARGET_API_MAC_CARBON
5630 GetGlobalMouse (&mouse_pos
);
5631 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5632 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5634 SetPortWindowPort (wp
);
5635 GetMouse (&mouse_pos
);
5638 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5639 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5641 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5645 if (! NILP (bar
->dragging
))
5646 win_y
-= XINT (bar
->dragging
);
5650 if (win_y
> top_range
)
5654 *bar_window
= bar
->window
;
5656 if (! NILP (bar
->dragging
))
5657 *part
= scroll_bar_handle
;
5658 else if (win_y
< XINT (bar
->start
))
5659 *part
= scroll_bar_above_handle
;
5660 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5661 *part
= scroll_bar_handle
;
5663 *part
= scroll_bar_below_handle
;
5665 XSETINT (*x
, win_y
);
5666 XSETINT (*y
, top_range
);
5669 last_mouse_scroll_bar
= Qnil
;
5671 *time
= last_mouse_movement_time
;
5675 /* The screen has been cleared so we may have changed foreground or
5676 background colors, and the scroll bars may need to be redrawn.
5677 Clear out the scroll bars, and ask for expose events, so we can
5681 x_scroll_bar_clear (f
)
5684 XTcondemn_scroll_bars (f
);
5685 XTjudge_scroll_bars (f
);
5689 /***********************************************************************
5691 ***********************************************************************/
5694 /* In identifiers such as function/variable names, Emacs tool bar is
5695 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5697 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5698 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5700 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5701 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5702 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5703 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5704 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5705 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5706 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5708 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5709 static void mac_handle_origin_change
P_ ((struct frame
*));
5710 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5714 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5721 mac_get_window_bounds (f
, &inner
, &outer
);
5723 switch (win_gravity
)
5725 case NorthWestGravity
:
5727 case SouthWestGravity
:
5728 left
+= inner
.left
- outer
.left
;
5734 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5737 case NorthEastGravity
:
5739 case SouthEastGravity
:
5740 left
+= inner
.right
- outer
.right
;
5744 switch (win_gravity
)
5746 case NorthWestGravity
:
5748 case NorthEastGravity
:
5749 top
+= inner
.top
- outer
.top
;
5755 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5758 case SouthWestGravity
:
5760 case SouthEastGravity
:
5761 top
+= inner
.bottom
- outer
.bottom
;
5765 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5769 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5776 mac_get_window_bounds (f
, &inner
, &outer
);
5778 switch (win_gravity
)
5780 case NorthWestGravity
:
5782 case SouthWestGravity
:
5789 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5790 - (inner
.right
- inner
.left
)) / 2;
5793 case NorthEastGravity
:
5795 case SouthEastGravity
:
5796 *left
= outer
.right
- (inner
.right
- inner
.left
);
5800 switch (win_gravity
)
5802 case NorthWestGravity
:
5804 case NorthEastGravity
:
5811 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5812 - (inner
.bottom
- inner
.top
)) / 2;
5815 case SouthWestGravity
:
5817 case SouthEastGravity
:
5818 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5824 mac_handle_toolbar_event (next_handler
, event
, data
)
5825 EventHandlerCallRef next_handler
;
5829 OSStatus err
, result
= eventNotHandledErr
;
5831 switch (GetEventKind (event
))
5833 case kEventToolbarGetDefaultIdentifiers
:
5837 case kEventToolbarGetAllowedIdentifiers
:
5839 CFMutableArrayRef array
;
5841 GetEventParameter (event
, kEventParamMutableArray
,
5842 typeCFMutableArrayRef
, NULL
,
5843 sizeof (CFMutableArrayRef
), NULL
, &array
);
5844 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5849 case kEventToolbarCreateItemWithIdentifier
:
5851 CFStringRef identifier
;
5852 HIToolbarItemRef item
= NULL
;
5854 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
5855 typeCFStringRef
, NULL
,
5856 sizeof (CFStringRef
), NULL
, &identifier
);
5858 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
5859 == kCFCompareEqualTo
)
5860 HIToolbarItemCreate (identifier
,
5861 kHIToolbarItemAllowDuplicates
5862 | kHIToolbarItemCantBeRemoved
, &item
);
5866 SetEventParameter (event
, kEventParamToolbarItem
,
5867 typeHIToolbarItemRef
,
5868 sizeof (HIToolbarItemRef
), &item
);
5882 mac_image_spec_to_cg_image (f
, image
)
5886 if (!valid_image_p (image
))
5890 int img_id
= lookup_image (f
, image
);
5891 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
5893 prepare_image_for_display (f
, img
);
5895 return img
->data
.ptr_val
;
5899 /* Create a tool bar for frame F. */
5902 mac_create_frame_tool_bar (f
)
5906 HIToolbarRef toolbar
;
5908 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
5912 static const EventTypeSpec specs
[] =
5913 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
5914 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
5915 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
5917 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
5918 mac_handle_toolbar_event
,
5919 GetEventTypeCount (specs
), specs
,
5924 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
5927 static const EventTypeSpec specs
[] =
5928 {{kEventClassCommand
, kEventCommandProcess
}};
5930 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
5931 mac_handle_toolbar_command_event
,
5932 GetEventTypeCount (specs
),
5936 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
5939 CFRelease (toolbar
);
5944 /* Update the tool bar for frame F. Add new buttons and remove old. */
5947 update_frame_tool_bar (f
)
5950 HIToolbarRef toolbar
= NULL
;
5952 CFArrayRef old_items
= NULL
;
5954 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
5955 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5959 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5960 if (toolbar
== NULL
)
5962 mac_create_frame_tool_bar (f
);
5963 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5964 if (toolbar
== NULL
)
5966 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
5967 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
5970 HIToolbarCopyItems (toolbar
, &old_items
);
5971 if (old_items
== NULL
)
5974 old_count
= CFArrayGetCount (old_items
);
5976 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
5978 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5980 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
5981 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
5984 CGImageRef cg_image
;
5986 HIToolbarItemRef item
;
5988 /* If image is a vector, choose the image according to the
5990 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
5991 if (VECTORP (image
))
5995 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
5996 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
5999 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6000 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6002 xassert (ASIZE (image
) >= idx
);
6003 image
= AREF (image
, idx
);
6008 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6009 /* Ignore invalid image specifications. */
6010 if (cg_image
== NULL
)
6013 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6017 if (pos
< old_count
)
6019 CGImageRef old_cg_image
= NULL
;
6020 CFStringRef old_label
= NULL
;
6021 Boolean old_enabled_p
;
6023 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6025 HIToolbarItemCopyImage (item
, &old_cg_image
);
6026 if (cg_image
!= old_cg_image
)
6027 HIToolbarItemSetImage (item
, cg_image
);
6028 CGImageRelease (old_cg_image
);
6030 HIToolbarItemCopyLabel (item
, &old_label
);
6031 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6032 HIToolbarItemSetLabel (item
, label
);
6033 CFRelease (old_label
);
6035 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6036 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6037 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6042 HIToolbarCreateItemWithIdentifier (toolbar
,
6043 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6047 HIToolbarItemSetImage (item
, cg_image
);
6048 HIToolbarItemSetLabel (item
, label
);
6049 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6050 HIToolbarAppendItem (toolbar
, item
);
6058 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6063 CFRelease (old_items
);
6065 while (pos
< old_count
)
6066 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6068 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6069 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6070 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6071 toolbar visibility change. */
6072 mac_handle_origin_change (f
);
6073 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6075 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6076 /* If the title bar is completely outside the screen, adjust the
6078 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6079 kWindowConstrainMoveRegardlessOfFit
6080 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6081 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6088 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6089 doesn't deallocate the resources. */
6092 free_frame_tool_bar (f
)
6095 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6097 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6100 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6101 (NILP (Fsymbol_value
6102 (intern ("frame-notice-user-settings")))
6103 && f
== mac_focus_frame (dpyinfo
)));
6104 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6105 on toolbar visibility change. */
6106 mac_handle_origin_change (f
);
6112 mac_tool_bar_note_mouse_movement (f
, event
)
6117 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6119 HIViewRef item_view
;
6122 mouse_down_p
= (dpyinfo
->grabbed
6123 && f
== last_mouse_frame
6124 && FRAME_LIVE_P (f
));
6128 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6130 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6131 toolbar item view seems to have the same command ID with that of
6132 the toolbar item. */
6134 err
= GetControlCommandID (item_view
, &command_id
);
6135 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6137 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6139 if (i
< f
->n_tool_bar_items
)
6142 HIViewRef content_view
;
6144 err
= HIViewGetBounds (item_view
, &bounds
);
6146 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6147 kHIViewWindowContentID
, &content_view
);
6149 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6151 SetRect (&last_mouse_glyph
,
6152 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6153 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6155 help_echo_object
= help_echo_window
= Qnil
;
6157 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6158 if (NILP (help_echo_string
))
6159 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6165 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6166 EventHandlerCallRef next_handler
;
6170 OSStatus err
, result
= eventNotHandledErr
;
6171 struct frame
*f
= (struct frame
*) data
;
6174 err
= GetEventParameter (event
, kEventParamDirectObject
,
6175 typeHICommand
, NULL
,
6176 sizeof (HICommand
), NULL
, &command
);
6180 switch (GetEventKind (event
))
6182 case kEventCommandProcess
:
6183 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6184 result
= CallNextEventHandler (next_handler
, event
);
6187 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6189 if (i
< f
->n_tool_bar_items
6190 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6193 struct input_event buf
;
6197 XSETFRAME (frame
, f
);
6198 buf
.kind
= TOOL_BAR_EVENT
;
6199 buf
.frame_or_window
= frame
;
6201 kbd_buffer_store_event (&buf
);
6203 buf
.kind
= TOOL_BAR_EVENT
;
6204 buf
.frame_or_window
= frame
;
6205 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6206 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6207 kbd_buffer_store_event (&buf
);
6221 #endif /* USE_MAC_TOOLBAR */
6224 /***********************************************************************
6226 ***********************************************************************/
6228 /* Set clipping for output in glyph row ROW. W is the window in which
6229 we operate. GC is the graphics context to set clipping in.
6231 ROW may be a text row or, e.g., a mode line. Text rows must be
6232 clipped to the interior of the window dedicated to text display,
6233 mode lines must be clipped to the whole window. */
6236 x_clip_to_row (w
, row
, area
, gc
)
6238 struct glyph_row
*row
;
6242 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6244 int window_x
, window_y
, window_width
;
6246 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6248 clip_rect
.left
= window_x
;
6249 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6250 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6251 clip_rect
.right
= clip_rect
.left
+ window_width
;
6252 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6254 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6258 /* Draw a hollow box cursor on window W in glyph row ROW. */
6261 x_draw_hollow_cursor (w
, row
)
6263 struct glyph_row
*row
;
6265 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6266 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6267 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6270 struct glyph
*cursor_glyph
;
6273 /* Get the glyph the cursor is on. If we can't tell because
6274 the current matrix is invalid or such, give up. */
6275 cursor_glyph
= get_phys_cursor_glyph (w
);
6276 if (cursor_glyph
== NULL
)
6279 /* Compute frame-relative coordinates for phys cursor. */
6280 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6281 wd
= w
->phys_cursor_width
;
6283 /* The foreground of cursor_gc is typically the same as the normal
6284 background color, which can cause the cursor box to be invisible. */
6285 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6286 if (dpyinfo
->scratch_cursor_gc
)
6287 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6289 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6290 GCForeground
, &xgcv
);
6291 gc
= dpyinfo
->scratch_cursor_gc
;
6293 /* Set clipping, draw the rectangle, and reset clipping again. */
6294 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6295 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6296 mac_reset_clip_rectangles (dpy
, gc
);
6300 /* Draw a bar cursor on window W in glyph row ROW.
6302 Implementation note: One would like to draw a bar cursor with an
6303 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6304 Unfortunately, I didn't find a font yet that has this property set.
6308 x_draw_bar_cursor (w
, row
, width
, kind
)
6310 struct glyph_row
*row
;
6312 enum text_cursor_kinds kind
;
6314 struct frame
*f
= XFRAME (w
->frame
);
6315 struct glyph
*cursor_glyph
;
6317 /* If cursor is out of bounds, don't draw garbage. This can happen
6318 in mini-buffer windows when switching between echo area glyphs
6320 cursor_glyph
= get_phys_cursor_glyph (w
);
6321 if (cursor_glyph
== NULL
)
6324 /* If on an image, draw like a normal cursor. That's usually better
6325 visible than drawing a bar, esp. if the image is large so that
6326 the bar might not be in the window. */
6327 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6329 struct glyph_row
*row
;
6330 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6331 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6335 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6336 Window window
= FRAME_MAC_WINDOW (f
);
6337 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6338 unsigned long mask
= GCForeground
| GCBackground
;
6339 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6342 /* If the glyph's background equals the color we normally draw
6343 the bar cursor in, the bar cursor in its normal color is
6344 invisible. Use the glyph's foreground color instead in this
6345 case, on the assumption that the glyph's colors are chosen so
6346 that the glyph is legible. */
6347 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6348 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6350 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6353 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6356 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6357 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6361 width
= FRAME_CURSOR_WIDTH (f
);
6362 width
= min (cursor_glyph
->pixel_width
, width
);
6364 w
->phys_cursor_width
= width
;
6365 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6367 if (kind
== BAR_CURSOR
)
6368 mac_fill_rectangle (f
, gc
,
6369 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6370 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6371 width
, row
->height
);
6373 mac_fill_rectangle (f
, gc
,
6374 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6375 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6376 row
->height
- width
),
6377 cursor_glyph
->pixel_width
,
6380 mac_reset_clip_rectangles (dpy
, gc
);
6385 /* RIF: Define cursor CURSOR on frame F. */
6388 mac_define_frame_cursor (f
, cursor
)
6392 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6394 if (dpyinfo
->x_focus_frame
== f
)
6395 SetThemeCursor (cursor
);
6399 /* RIF: Clear area on frame F. */
6402 mac_clear_frame_area (f
, x
, y
, width
, height
)
6404 int x
, y
, width
, height
;
6406 mac_clear_area (f
, x
, y
, width
, height
);
6410 /* RIF: Draw cursor on window W. */
6413 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6415 struct glyph_row
*glyph_row
;
6417 int cursor_type
, cursor_width
;
6422 w
->phys_cursor_type
= cursor_type
;
6423 w
->phys_cursor_on_p
= 1;
6425 if (glyph_row
->exact_window_width_line_p
6426 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6428 glyph_row
->cursor_in_fringe_p
= 1;
6429 draw_fringe_bitmap (w
, glyph_row
, 0);
6432 switch (cursor_type
)
6434 case HOLLOW_BOX_CURSOR
:
6435 x_draw_hollow_cursor (w
, glyph_row
);
6438 case FILLED_BOX_CURSOR
:
6439 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6443 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6447 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6451 w
->phys_cursor_width
= 0;
6463 #if 0 /* MAC_TODO: no icon support yet. */
6465 x_bitmap_icon (f
, icon
)
6471 if (FRAME_W32_WINDOW (f
) == 0)
6475 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6476 else if (STRINGP (icon
))
6477 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6478 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6479 else if (SYMBOLP (icon
))
6483 if (EQ (icon
, intern ("application")))
6484 name
= (LPCTSTR
) IDI_APPLICATION
;
6485 else if (EQ (icon
, intern ("hand")))
6486 name
= (LPCTSTR
) IDI_HAND
;
6487 else if (EQ (icon
, intern ("question")))
6488 name
= (LPCTSTR
) IDI_QUESTION
;
6489 else if (EQ (icon
, intern ("exclamation")))
6490 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6491 else if (EQ (icon
, intern ("asterisk")))
6492 name
= (LPCTSTR
) IDI_ASTERISK
;
6493 else if (EQ (icon
, intern ("winlogo")))
6494 name
= (LPCTSTR
) IDI_WINLOGO
;
6498 hicon
= LoadIcon (NULL
, name
);
6506 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6511 #endif /* MAC_TODO */
6513 /************************************************************************
6515 ************************************************************************/
6517 /* Display Error Handling functions not used on W32. Listing them here
6518 helps diff stay in step when comparing w32term.c with xterm.c.
6520 x_error_catcher (display, error)
6521 x_catch_errors (dpy)
6522 x_catch_errors_unwind (old_val)
6523 x_check_errors (dpy, format)
6524 x_had_errors_p (dpy)
6525 x_clear_errors (dpy)
6526 x_uncatch_errors (dpy, count)
6528 x_connection_signal (signalnum)
6529 x_connection_closed (dpy, error_message)
6530 x_error_quitter (display, error)
6531 x_error_handler (display, error)
6532 x_io_error_quitter (display)
6537 /* Changing the font of the frame. */
6539 /* Give frame F the font named FONTNAME as its default font, and
6540 return the full name of that font. FONTNAME may be a wildcard
6541 pattern; in that case, we choose some font that fits the pattern.
6542 The return value shows which font we chose. */
6545 x_new_font (f
, fontname
)
6547 register char *fontname
;
6549 struct font_info
*fontp
6550 = FS_LOAD_FONT (f
, 0, fontname
, -1);
6555 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6556 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6557 FRAME_FONTSET (f
) = -1;
6559 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6560 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6561 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6563 compute_fringe_widths (f
, 1);
6565 /* Compute the scroll bar width in character columns. */
6566 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6568 int wid
= FRAME_COLUMN_WIDTH (f
);
6569 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6570 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6574 int wid
= FRAME_COLUMN_WIDTH (f
);
6575 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6578 /* Now make the frame display the given font. */
6579 if (FRAME_MAC_WINDOW (f
) != 0)
6581 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6583 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6585 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6588 /* Don't change the size of a tip frame; there's no point in
6589 doing it because it's done in Fx_show_tip, and it leads to
6590 problems because the tip frame has no widget. */
6591 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6592 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6595 return build_string (fontp
->full_name
);
6598 /* Give frame F the fontset named FONTSETNAME as its default font, and
6599 return the full name of that fontset. FONTSETNAME may be a wildcard
6600 pattern; in that case, we choose some fontset that fits the pattern.
6601 The return value shows which fontset we chose. */
6604 x_new_fontset (f
, fontsetname
)
6608 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
6614 if (FRAME_FONTSET (f
) == fontset
)
6615 /* This fontset is already set in frame F. There's nothing more
6617 return fontset_name (fontset
);
6619 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6621 if (!STRINGP (result
))
6622 /* Can't load ASCII font. */
6625 /* Since x_new_font doesn't update any fontset information, do it now. */
6626 FRAME_FONTSET (f
) = fontset
;
6628 return build_string (fontsetname
);
6632 /***********************************************************************
6633 TODO: W32 Input Methods
6634 ***********************************************************************/
6635 /* Listing missing functions from xterm.c helps diff stay in step.
6637 xim_destroy_callback (xim, client_data, call_data)
6638 xim_open_dpy (dpyinfo, resource_name)
6640 xim_instantiate_callback (display, client_data, call_data)
6641 xim_initialize (dpyinfo, resource_name)
6642 xim_close_dpy (dpyinfo)
6648 mac_get_window_bounds (f
, inner
, outer
)
6650 Rect
*inner
, *outer
;
6652 #if TARGET_API_MAC_CARBON
6653 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6654 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6655 #else /* not TARGET_API_MAC_CARBON */
6656 RgnHandle region
= NewRgn ();
6658 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6659 *inner
= (*region
)->rgnBBox
;
6660 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6661 *outer
= (*region
)->rgnBBox
;
6662 DisposeRgn (region
);
6663 #endif /* not TARGET_API_MAC_CARBON */
6667 mac_handle_origin_change (f
)
6670 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6674 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6676 int pixelwidth
, pixelheight
;
6680 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6681 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6683 if (cols
!= FRAME_COLS (f
)
6684 || rows
!= FRAME_LINES (f
)
6685 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6686 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6688 /* We pass 1 for DELAY since we can't run Lisp code inside of
6690 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6691 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6692 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6693 SET_FRAME_GARBAGED (f
);
6695 /* If cursor was outside the new size, mark it as off. */
6696 mark_window_cursors_off (XWINDOW (f
->root_window
));
6698 /* Clear out any recollection of where the mouse highlighting
6699 was, since it might be in a place that's outside the new
6700 frame size. Actually checking whether it is outside is a
6701 pain in the neck, so don't try--just let the highlighting be
6702 done afresh with new size. */
6703 cancel_mouse_face (f
);
6705 #if TARGET_API_MAC_CARBON
6706 if (f
->output_data
.mac
->hourglass_control
)
6709 mac_prepare_for_quickdraw (f
);
6711 MoveControl (f
->output_data
.mac
->hourglass_control
,
6712 pixelwidth
- HOURGLASS_WIDTH
, 0);
6719 /* Calculate the absolute position in frame F
6720 from its current recorded position values and gravity. */
6723 x_calc_absolute_position (f
)
6726 int width_diff
= 0, height_diff
= 0;
6727 int flags
= f
->size_hint_flags
;
6730 /* We have nothing to do if the current position
6731 is already for the top-left corner. */
6732 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6735 /* Find the offsets of the outside upper-left corner of
6736 the inner window, with respect to the outer window. */
6738 mac_get_window_bounds (f
, &inner
, &outer
);
6741 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6742 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6744 /* Treat negative positions as relative to the leftmost bottommost
6745 position that fits on the screen. */
6746 if (flags
& XNegative
)
6747 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6749 - FRAME_PIXEL_WIDTH (f
)
6752 if (flags
& YNegative
)
6753 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6755 - FRAME_PIXEL_HEIGHT (f
)
6758 /* The left_pos and top_pos
6759 are now relative to the top and left screen edges,
6760 so the flags should correspond. */
6761 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6764 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6765 to really change the position, and 0 when calling from
6766 x_make_frame_visible (in that case, XOFF and YOFF are the current
6767 position values). It is -1 when calling from x_set_frame_parameters,
6768 which means, do adjust for borders but don't change the gravity. */
6771 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6773 register int xoff
, yoff
;
6776 if (change_gravity
> 0)
6780 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6782 f
->size_hint_flags
|= XNegative
;
6784 f
->size_hint_flags
|= YNegative
;
6785 f
->win_gravity
= NorthWestGravity
;
6787 x_calc_absolute_position (f
);
6790 x_wm_set_size_hint (f
, (long) 0, 0);
6792 #if TARGET_API_MAC_CARBON
6793 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6794 /* If the title bar is completely outside the screen, adjust the
6796 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6797 kWindowConstrainMoveRegardlessOfFit
6798 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6799 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6800 mac_handle_origin_change (f
);
6803 Rect inner
, outer
, screen_rect
, dummy
;
6804 RgnHandle region
= NewRgn ();
6806 mac_get_window_bounds (f
, &inner
, &outer
);
6807 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6808 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6809 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6810 f
->top_pos
+ f
->y_pixels_diff
, false);
6812 /* If the title bar is completely outside the screen, adjust the
6813 position. The variable `outer' holds the title bar rectangle.
6814 The variable `inner' holds slightly smaller one than `outer',
6815 so that the calculation of overlapping may not become too
6817 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6818 outer
= (*region
)->rgnBBox
;
6819 DisposeRgn (region
);
6821 InsetRect (&inner
, 8, 8);
6822 screen_rect
= qd
.screenBits
.bounds
;
6823 screen_rect
.top
+= GetMBarHeight ();
6825 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6827 if (inner
.right
<= screen_rect
.left
)
6828 f
->left_pos
= screen_rect
.left
;
6829 else if (inner
.left
>= screen_rect
.right
)
6830 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6832 if (inner
.bottom
<= screen_rect
.top
)
6833 f
->top_pos
= screen_rect
.top
;
6834 else if (inner
.top
>= screen_rect
.bottom
)
6835 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6837 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6838 f
->top_pos
+ f
->y_pixels_diff
, false);
6846 /* Call this to change the size of frame F's x-window.
6847 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6848 for this size change and subsequent size changes.
6849 Otherwise we leave the window gravity unchanged. */
6852 x_set_window_size (f
, change_gravity
, cols
, rows
)
6857 int pixelwidth
, pixelheight
;
6861 check_frame_size (f
, &rows
, &cols
);
6862 f
->scroll_bar_actual_width
6863 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6865 compute_fringe_widths (f
, 0);
6867 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6868 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6870 f
->win_gravity
= NorthWestGravity
;
6871 x_wm_set_size_hint (f
, (long) 0, 0);
6873 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6875 #if TARGET_API_MAC_CARBON
6876 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6878 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6880 if (f
->output_data
.mac
->internal_border_width
6881 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6883 mac_clear_window (f
);
6884 f
->output_data
.mac
->internal_border_width
6885 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6888 SET_FRAME_GARBAGED (f
);
6893 /* Mouse warping. */
6895 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6898 x_set_mouse_position (f
, x
, y
)
6904 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6905 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6907 if (pix_x
< 0) pix_x
= 0;
6908 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6910 if (pix_y
< 0) pix_y
= 0;
6911 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6913 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6917 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6922 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
6923 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
6926 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
6929 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6932 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6933 0, 0, 0, 0, pix_x
, pix_y
);
6939 /* focus shifting, raising and lowering. */
6942 x_focus_on_frame (f
)
6945 #if 0 /* This proves to be unpleasant. */
6949 /* I don't think that the ICCCM allows programs to do things like this
6950 without the interaction of the window manager. Whatever you end up
6951 doing with this code, do it to x_unfocus_frame too. */
6952 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6953 RevertToPointerRoot
, CurrentTime
);
6963 /* Raise frame F. */
6969 if (f
->async_visible
)
6972 BringToFront (FRAME_MAC_WINDOW (f
));
6977 /* Lower frame F. */
6983 if (f
->async_visible
)
6986 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6992 XTframe_raise_lower (f
, raise_flag
)
7002 /* Change of visibility. */
7005 mac_handle_visibility_change (f
)
7008 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7009 int visible
= 0, iconified
= 0;
7010 struct input_event buf
;
7012 if (IsWindowVisible (wp
))
7014 if (IsWindowCollapsed (wp
))
7020 if (!f
->async_visible
&& visible
)
7024 /* wait_reading_process_output will notice this and update
7025 the frame's display structures. If we were made
7026 invisible, we should not set garbaged, because that stops
7027 redrawing on Update events. */
7028 SET_FRAME_GARBAGED (f
);
7031 buf
.kind
= DEICONIFY_EVENT
;
7032 XSETFRAME (buf
.frame_or_window
, f
);
7034 kbd_buffer_store_event (&buf
);
7036 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7037 /* Force a redisplay sooner or later to update the
7038 frame titles in case this is the second frame. */
7039 record_asynch_buffer_change ();
7041 else if (f
->async_visible
&& !visible
)
7045 buf
.kind
= ICONIFY_EVENT
;
7046 XSETFRAME (buf
.frame_or_window
, f
);
7048 kbd_buffer_store_event (&buf
);
7051 f
->async_visible
= visible
;
7052 f
->async_iconified
= iconified
;
7055 /* This tries to wait until the frame is really visible.
7056 However, if the window manager asks the user where to position
7057 the frame, this will return before the user finishes doing that.
7058 The frame will not actually be visible at that time,
7059 but it will become visible later when the window manager
7060 finishes with it. */
7063 x_make_frame_visible (f
)
7068 if (! FRAME_VISIBLE_P (f
))
7070 /* We test FRAME_GARBAGED_P here to make sure we don't
7071 call x_set_offset a second time
7072 if we get to x_make_frame_visible a second time
7073 before the window gets really visible. */
7074 if (! FRAME_ICONIFIED_P (f
)
7075 && ! f
->output_data
.mac
->asked_for_visible
)
7076 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7078 f
->output_data
.mac
->asked_for_visible
= 1;
7080 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7081 ShowWindow (FRAME_MAC_WINDOW (f
));
7084 XFlush (FRAME_MAC_DISPLAY (f
));
7086 /* Synchronize to ensure Emacs knows the frame is visible
7087 before we do anything else. We do this loop with input not blocked
7088 so that incoming events are handled. */
7093 /* This must come after we set COUNT. */
7096 XSETFRAME (frame
, f
);
7098 /* Wait until the frame is visible. Process X events until a
7099 MapNotify event has been seen, or until we think we won't get a
7100 MapNotify at all.. */
7101 for (count
= input_signal_count
+ 10;
7102 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7104 /* Force processing of queued events. */
7107 /* Machines that do polling rather than SIGIO have been
7108 observed to go into a busy-wait here. So we'll fake an
7109 alarm signal to let the handler know that there's something
7110 to be read. We used to raise a real alarm, but it seems
7111 that the handler isn't always enabled here. This is
7113 if (input_polling_used ())
7115 /* It could be confusing if a real alarm arrives while
7116 processing the fake one. Turn it off and let the
7117 handler reset it. */
7118 extern void poll_for_input_1
P_ ((void));
7119 int old_poll_suppress_count
= poll_suppress_count
;
7120 poll_suppress_count
= 1;
7121 poll_for_input_1 ();
7122 poll_suppress_count
= old_poll_suppress_count
;
7125 /* See if a MapNotify event has been processed. */
7126 FRAME_SAMPLE_VISIBILITY (f
);
7131 /* Change from mapped state to withdrawn state. */
7133 /* Make the frame visible (mapped and not iconified). */
7136 x_make_frame_invisible (f
)
7139 /* A deactivate event does not occur when the last visible frame is
7140 made invisible. So if we clear the highlight here, it will not
7141 be rehighlighted when it is made visible. */
7143 /* Don't keep the highlight on an invisible frame. */
7144 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7145 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7150 #if !TARGET_API_MAC_CARBON
7151 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7152 that the current position of the window is user-specified, rather than
7153 program-specified, so that when the window is mapped again, it will be
7154 placed at the same location, without forcing the user to position it
7155 by hand again (they have already done that once for this window.) */
7156 x_wm_set_size_hint (f
, (long) 0, 1);
7159 HideWindow (FRAME_MAC_WINDOW (f
));
7163 #if !TARGET_API_MAC_CARBON
7164 mac_handle_visibility_change (f
);
7168 /* Change window state from mapped to iconified. */
7176 /* A deactivate event does not occur when the last visible frame is
7177 iconified. So if we clear the highlight here, it will not be
7178 rehighlighted when it is deiconified. */
7180 /* Don't keep the highlight on an invisible frame. */
7181 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7182 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7185 if (f
->async_iconified
)
7190 FRAME_SAMPLE_VISIBILITY (f
);
7192 if (! FRAME_VISIBLE_P (f
))
7193 ShowWindow (FRAME_MAC_WINDOW (f
));
7195 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7200 error ("Can't notify window manager of iconification");
7202 #if !TARGET_API_MAC_CARBON
7203 mac_handle_visibility_change (f
);
7208 /* Free X resources of frame F. */
7211 x_free_frame_resources (f
)
7214 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7215 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7219 if (wp
!= tip_window
)
7220 remove_window_handler (wp
);
7223 mac_prepare_for_quickdraw (f
);
7226 if (wp
== tip_window
)
7227 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7228 closed' event. So we reset tip_window here. */
7231 free_frame_menubar (f
);
7233 if (FRAME_FACE_CACHE (f
))
7234 free_frame_faces (f
);
7238 if (FRAME_SIZE_HINTS (f
))
7239 xfree (FRAME_SIZE_HINTS (f
));
7241 xfree (f
->output_data
.mac
);
7242 f
->output_data
.mac
= NULL
;
7244 if (f
== dpyinfo
->x_focus_frame
)
7246 dpyinfo
->x_focus_frame
= 0;
7247 #if USE_MAC_FONT_PANEL
7248 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7251 if (f
== dpyinfo
->x_focus_event_frame
)
7252 dpyinfo
->x_focus_event_frame
= 0;
7253 if (f
== dpyinfo
->x_highlight_frame
)
7254 dpyinfo
->x_highlight_frame
= 0;
7256 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7258 dpyinfo
->mouse_face_beg_row
7259 = dpyinfo
->mouse_face_beg_col
= -1;
7260 dpyinfo
->mouse_face_end_row
7261 = dpyinfo
->mouse_face_end_col
= -1;
7262 dpyinfo
->mouse_face_window
= Qnil
;
7263 dpyinfo
->mouse_face_deferred_gc
= 0;
7264 dpyinfo
->mouse_face_mouse_frame
= 0;
7271 /* Destroy the X window of frame F. */
7274 x_destroy_window (f
)
7277 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7279 x_free_frame_resources (f
);
7281 dpyinfo
->reference_count
--;
7285 /* Setting window manager hints. */
7287 /* Set the normal size hints for the window manager, for frame F.
7288 FLAGS is the flags word to use--or 0 meaning preserve the flags
7289 that the window now has.
7290 If USER_POSITION is nonzero, we set the USPosition
7291 flag (this is useful when FLAGS is 0). */
7293 x_wm_set_size_hint (f
, flags
, user_position
)
7298 int base_width
, base_height
, width_inc
, height_inc
;
7299 int min_rows
= 0, min_cols
= 0;
7300 XSizeHints
*size_hints
;
7302 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7303 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7304 width_inc
= FRAME_COLUMN_WIDTH (f
);
7305 height_inc
= FRAME_LINE_HEIGHT (f
);
7307 check_frame_size (f
, &min_rows
, &min_cols
);
7309 size_hints
= FRAME_SIZE_HINTS (f
);
7310 if (size_hints
== NULL
)
7312 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7313 bzero (size_hints
, sizeof (XSizeHints
));
7316 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7317 size_hints
->width_inc
= width_inc
;
7318 size_hints
->height_inc
= height_inc
;
7319 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7320 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7321 size_hints
->base_width
= base_width
;
7322 size_hints
->base_height
= base_height
;
7325 size_hints
->flags
= flags
;
7326 else if (user_position
)
7328 size_hints
->flags
&= ~ PPosition
;
7329 size_hints
->flags
|= USPosition
;
7333 #if 0 /* MAC_TODO: hide application instead of iconify? */
7334 /* Used for IconicState or NormalState */
7337 x_wm_set_window_state (f
, state
)
7341 #ifdef USE_X_TOOLKIT
7344 XtSetArg (al
[0], XtNinitialState
, state
);
7345 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7346 #else /* not USE_X_TOOLKIT */
7347 Window window
= FRAME_X_WINDOW (f
);
7349 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7350 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7352 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7353 #endif /* not USE_X_TOOLKIT */
7357 x_wm_set_icon_pixmap (f
, pixmap_id
)
7363 #ifndef USE_X_TOOLKIT
7364 Window window
= FRAME_X_WINDOW (f
);
7369 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7370 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7374 /* It seems there is no way to turn off use of an icon pixmap.
7375 The following line does it, only if no icon has yet been created,
7376 for some window managers. But with mwm it crashes.
7377 Some people say it should clear the IconPixmapHint bit in this case,
7378 but that doesn't work, and the X consortium said it isn't the
7379 right thing at all. Since there is no way to win,
7380 best to explicitly give up. */
7382 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7388 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7392 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7393 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7396 #else /* not USE_X_TOOLKIT */
7398 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7399 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7401 #endif /* not USE_X_TOOLKIT */
7404 #endif /* MAC_TODO */
7407 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7411 #if 0 /* MAC_TODO: no icons on Mac */
7412 #ifdef USE_X_TOOLKIT
7413 Window window
= XtWindow (f
->output_data
.x
->widget
);
7415 Window window
= FRAME_X_WINDOW (f
);
7418 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7419 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7420 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7422 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7423 #endif /* MAC_TODO */
7427 /***********************************************************************
7429 ***********************************************************************/
7431 /* An XLFD pattern is divided into blocks delimited by '*'. This
7432 structure holds information for each block. */
7433 struct xlfdpat_block
7435 /* Length of the pattern string in this block. Non-zero except for
7436 the first and the last blocks. */
7439 /* Pattern string except the last character in this block. The last
7440 character is replaced with NUL in order to use it as a
7442 unsigned char *pattern
;
7444 /* Last character of the pattern string. Must not be '?'. */
7445 unsigned char last_char
;
7447 /* One of the tables for the Boyer-Moore string search. It
7448 specifies the number of positions to proceed for each character
7449 with which the match fails. */
7452 /* The skip value for the last character in the above `skip' is
7453 assigned to `infinity' in order to simplify a loop condition.
7454 The original value is saved here. */
7460 /* Normalized pattern string. "Normalized" means that capital
7461 letters are lowered, blocks are not empty except the first and
7462 the last ones, and trailing '?'s in a block that is not the last
7463 one are moved to the next one. The last character in each block
7464 is replaced with NUL. */
7467 /* Number of characters except '*'s and trailing '?'s in the
7468 normalized pattern string. */
7471 /* Number of trailing '?'s in the normalized pattern string. */
7472 int trailing_anychars
;
7474 /* Number of blocks and information for each block. The latter is
7475 NULL if the pattern is exact (no '*' or '?' in it). */
7477 struct xlfdpat_block
*blocks
;
7481 xlfdpat_destroy (pat
)
7482 struct xlfdpat
*pat
;
7489 xfree (pat
->blocks
);
7496 static struct xlfdpat
*
7497 xlfdpat_create (pattern
)
7498 const char *pattern
;
7500 struct xlfdpat
*pat
;
7501 int nblocks
, i
, skip
;
7502 unsigned char last_char
, *p
, *q
, *anychar_head
;
7503 const unsigned char *ptr
;
7504 struct xlfdpat_block
*blk
;
7506 pat
= xmalloc (sizeof (struct xlfdpat
));
7507 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7509 /* Normalize the pattern string and store it to `pat->buf'. */
7511 anychar_head
= NULL
;
7514 for (ptr
= pattern
; *ptr
; ptr
++)
7516 unsigned char c
= *ptr
;
7519 if (last_char
== '*')
7520 /* ...a** -> ...a* */
7524 if (last_char
== '?')
7526 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7527 /* ...*??* -> ...*?? */
7530 /* ...a??* -> ...a*?? */
7532 *anychar_head
++ = '*';
7540 if (last_char
!= '?')
7544 /* On Mac OS X 10.3, tolower also converts non-ASCII
7545 characters for some locales. */
7549 *q
++ = last_char
= c
;
7553 pat
->nblocks
= nblocks
;
7554 if (last_char
!= '?')
7555 pat
->trailing_anychars
= 0;
7558 pat
->trailing_anychars
= q
- anychar_head
;
7561 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7563 if (anychar_head
== NULL
&& nblocks
== 1)
7565 /* The pattern is exact. */
7570 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7572 /* Divide the normalized pattern into blocks. */
7574 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7579 blk
->len
= p
- blk
->pattern
;
7583 blk
->len
= q
- blk
->pattern
;
7585 /* Setup a table for the Boyer-Moore string search. */
7586 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7589 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7590 blk
->pattern
[blk
->len
- 1] = '\0';
7592 for (skip
= 1; skip
< blk
->len
; skip
++)
7593 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7596 for (i
= 0; i
< 256; i
++)
7597 blk
->skip
[i
] = skip
;
7599 p
= blk
->pattern
+ (blk
->len
- skip
);
7601 blk
->skip
[*p
++] = skip
;
7603 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7610 xlfdpat_exact_p (pat
)
7611 struct xlfdpat
*pat
;
7613 return pat
->blocks
== NULL
;
7616 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7617 that the pattern in *BLK matches with its prefix. Return NULL
7618 there is no such strings. STRING must be lowered in advance. */
7621 xlfdpat_block_match_1 (blk
, string
, start_max
)
7622 struct xlfdpat_block
*blk
;
7623 const unsigned char *string
;
7626 int start
, infinity
;
7628 const unsigned char *s
;
7630 xassert (blk
->len
> 0);
7631 xassert (start_max
+ blk
->len
<= strlen (string
));
7632 xassert (blk
->last_char
!= '?');
7634 /* See the comments in the function `boyer_moore' (search.c) for the
7635 use of `infinity'. */
7636 infinity
= start_max
+ blk
->len
+ 1;
7637 blk
->skip
[blk
->last_char
] = infinity
;
7642 /* Check the last character of the pattern. */
7643 s
= string
+ blk
->len
- 1;
7646 start
+= blk
->skip
[*(s
+ start
)];
7648 while (start
<= start_max
);
7650 if (start
< infinity
)
7651 /* Couldn't find the last character. */
7654 /* No less than `infinity' means we could find the last
7655 character at `s[start - infinity]'. */
7658 /* Check the remaining characters. We prefer making no-'?'
7659 cases faster because the use of '?' is really rare. */
7664 while (*p
++ == *s
++)
7667 while (*(p
- 1) == '?');
7669 if (*(p
- 1) == '\0')
7671 return string
+ start
;
7674 start
+= blk
->last_char_skip
;
7676 while (start
<= start_max
);
7681 #define xlfdpat_block_match(b, s, m) \
7682 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7683 : xlfdpat_block_match_1 (b, s, m))
7685 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7686 matches with STRING. STRING must be lowered in advance. */
7689 xlfdpat_match (pat
, string
)
7690 struct xlfdpat
*pat
;
7691 const unsigned char *string
;
7693 int str_len
, nblocks
, i
, start_max
;
7694 struct xlfdpat_block
*blk
;
7695 const unsigned char *s
;
7697 xassert (pat
->nblocks
> 0);
7699 if (xlfdpat_exact_p (pat
))
7700 return strcmp (pat
->buf
, string
) == 0;
7702 /* The number of the characters in the string must not be smaller
7703 than that in the pattern. */
7704 str_len
= strlen (string
);
7705 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7708 /* Chop off the trailing '?'s. */
7709 str_len
-= pat
->trailing_anychars
;
7711 /* The last block. When it is non-empty, it must match at the end
7713 nblocks
= pat
->nblocks
;
7714 blk
= pat
->blocks
+ (nblocks
- 1);
7716 /* The last block is also the first one. */
7717 return (str_len
== blk
->len
7718 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7719 else if (blk
->len
!= 0)
7720 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7723 /* The first block. When it is non-empty, it must match at the
7724 beginning of the string. */
7728 s
= xlfdpat_block_match (blk
, string
, 0);
7731 string
= s
+ blk
->len
;
7734 /* The rest of the blocks. */
7735 start_max
= str_len
- pat
->nchars
;
7736 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7738 s
= xlfdpat_block_match (blk
, string
, start_max
);
7741 start_max
-= s
- string
;
7742 string
= s
+ blk
->len
;
7749 /***********************************************************************
7751 ***********************************************************************/
7753 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7756 x_get_font_info (f
, font_idx
)
7760 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7763 /* the global font name table */
7764 static char **font_name_table
= NULL
;
7765 static int font_name_table_size
= 0;
7766 static int font_name_count
= 0;
7768 /* Alist linking font family names to Font Manager font family
7769 references (which can also be used as QuickDraw font IDs). We use
7770 an alist because hash tables are not ready when the terminal frame
7771 for Mac OS Classic is created. */
7772 static Lisp_Object fm_font_family_alist
;
7774 /* Hash table linking font family names to ATSU font IDs. */
7775 static Lisp_Object atsu_font_id_hash
;
7776 /* Alist linking Font Manager style to face attributes. */
7777 static Lisp_Object fm_style_face_attributes_alist
;
7778 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7781 /* Alist linking character set strings to Mac text encoding and Emacs
7783 static Lisp_Object Vmac_charset_info_alist
;
7786 create_text_encoding_info_alist ()
7788 Lisp_Object result
= Qnil
, rest
;
7790 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7792 Lisp_Object charset_info
= XCAR (rest
);
7793 Lisp_Object charset
, coding_system
, text_encoding
;
7794 Lisp_Object existing_info
;
7796 if (!(CONSP (charset_info
)
7797 && (charset
= XCAR (charset_info
),
7799 && CONSP (XCDR (charset_info
))
7800 && (text_encoding
= XCAR (XCDR (charset_info
)),
7801 INTEGERP (text_encoding
))
7802 && CONSP (XCDR (XCDR (charset_info
)))
7803 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7804 SYMBOLP (coding_system
))))
7807 existing_info
= assq_no_quit (text_encoding
, result
);
7808 if (NILP (existing_info
))
7809 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7812 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7813 XSETCDR (XCDR (existing_info
),
7814 Fcons (charset
, XCDR (XCDR (existing_info
))));
7822 decode_mac_font_name (name
, size
, coding_system
)
7825 Lisp_Object coding_system
;
7827 struct coding_system coding
;
7830 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7832 for (p
= name
; *p
; p
++)
7833 if (!isascii (*p
) || iscntrl (*p
))
7838 setup_coding_system (coding_system
, &coding
);
7839 coding
.src_multibyte
= 0;
7840 coding
.dst_multibyte
= 1;
7841 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7842 coding
.composing
= COMPOSITION_DISABLED
;
7843 buf
= (char *) alloca (size
);
7845 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7846 bcopy (buf
, name
, coding
.produced
);
7847 name
[coding
.produced
] = '\0';
7851 /* If there's just one occurrence of '-' in the family name, it is
7852 replaced with '_'. (More than one occurrence of '-' means a
7853 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7854 p
= strchr (name
, '-');
7855 if (p
&& strchr (p
+ 1, '-') == NULL
)
7858 for (p
= name
; *p
; p
++)
7859 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7860 for some locales. */
7867 mac_to_x_fontname (name
, size
, style
, charset
)
7875 char xf
[256], *result
;
7878 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7882 strcpy(foundry
, "Apple");
7883 strcpy(family
, name
);
7886 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7887 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7888 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7890 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7891 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7892 for (p
= result
; *p
; p
++)
7893 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7894 for some locales. */
7901 /* Parse fully-specified and instantiated X11 font spec XF, and store
7902 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7903 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7904 caller must allocate at least 256 and 32 bytes respectively. For
7905 ordinary Mac fonts, the value stored to FAMILY should just be their
7906 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7907 intlfonts collection contain their charset designation in their
7908 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7909 types of font names are handled accordingly. */
7911 const int kDefaultFontSize
= 12;
7914 parse_x_font_name (xf
, family
, size
, style
, charset
)
7921 Str31 foundry
, weight
;
7922 int point_size
, avgwidth
;
7925 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7926 foundry
, family
, weight
, slant
, size
,
7927 &point_size
, &avgwidth
, charset
) != 8
7928 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7929 foundry
, family
, weight
, slant
, size
,
7930 &point_size
, &avgwidth
, charset
) != 8)
7936 *size
= point_size
/ 10;
7937 else if (avgwidth
> 0)
7938 *size
= avgwidth
/ 10;
7941 *size
= kDefaultFontSize
;
7944 if (strcmp (weight
, "bold") == 0)
7949 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7951 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7953 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7955 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7956 but take overlap into account. */
7957 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7958 memcpy (family
, foundry
, foundry_len
);
7959 family
[foundry_len
] = '-';
7960 family
[foundry_len
+ 1 + family_len
] = '-';
7961 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7967 for (p
= family
; *p
; p
++)
7968 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7969 for some locales. */
7978 add_font_name_table_entry (char *font_name
)
7980 if (font_name_table_size
== 0)
7982 font_name_table_size
= 256;
7983 font_name_table
= (char **)
7984 xmalloc (font_name_table_size
* sizeof (char *));
7986 else if (font_name_count
+ 1 >= font_name_table_size
)
7988 font_name_table_size
*= 2;
7989 font_name_table
= (char **)
7990 xrealloc (font_name_table
,
7991 font_name_table_size
* sizeof (char *));
7994 font_name_table
[font_name_count
++] = font_name
;
7998 add_mac_font_name (name
, size
, style
, charset
)
8002 const char *charset
;
8005 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8008 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8009 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8010 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8011 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8018 fm_get_style_from_font (font
)
8022 FMFontStyle style
= normal
;
8025 FMFontFamily font_family
;
8026 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8028 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8029 some font (e.g., Optima) even if it is `bold'. */
8030 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8031 sizeof (mac_style
), &mac_style
, &len
);
8033 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8034 style
= EndianU16_BtoN (mac_style
);
8036 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8042 atsu_find_font_from_family_name (family
)
8045 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8048 Lisp_Object rest
, best
;
8049 FMFontStyle min_style
, style
;
8051 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8054 return kATSUInvalidFontID
;
8056 rest
= HASH_VALUE (h
, i
);
8057 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8058 return cons_to_long (rest
);
8060 rest
= Fnreverse (rest
);
8064 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8067 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8068 if (style
< min_style
)
8071 if (style
== normal
)
8078 while (!NILP (rest
));
8080 HASH_VALUE (h
, i
) = best
;
8081 return cons_to_long (best
);
8085 fm_style_to_face_attributes (fm_style
)
8086 FMFontStyle fm_style
;
8090 fm_style
&= (bold
| italic
);
8091 tem
= assq_no_quit (make_number (fm_style
),
8092 fm_style_face_attributes_alist
);
8096 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8097 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8098 fm_style_face_attributes_alist
=
8099 Fcons (Fcons (make_number (fm_style
), tem
),
8100 fm_style_face_attributes_alist
);
8106 atsu_find_font_family_name (font_id
)
8111 Lisp_Object family
= Qnil
;
8113 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8114 kFontMacintoshPlatform
, kFontNoScript
,
8115 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8118 family
= make_uninit_string (len
);
8119 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8120 kFontMacintoshPlatform
, kFontNoScript
,
8121 kFontNoLanguage
, len
, SDATA (family
),
8125 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8131 mac_atsu_font_face_attributes (font_id
)
8134 Lisp_Object family
, style_attrs
;
8136 family
= atsu_find_font_family_name (font_id
);
8139 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8140 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8144 /* Sets up the table font_name_table to contain the list of all fonts
8145 in the system the first time the table is used so that the Resource
8146 Manager need not be accessed every time this information is
8150 init_font_name_table ()
8152 #if TARGET_API_MAC_CARBON
8153 FMFontFamilyIterator ffi
;
8154 FMFontFamilyInstanceIterator ffii
;
8156 Lisp_Object text_encoding_info_alist
;
8157 struct gcpro gcpro1
;
8159 text_encoding_info_alist
= create_text_encoding_info_alist ();
8162 #if USE_CG_TEXT_DRAWING
8163 init_cg_text_anti_aliasing_threshold ();
8165 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8166 text_encoding_info_alist
)))
8169 struct Lisp_Hash_Table
*h
;
8171 ItemCount nfonts
, i
;
8172 ATSUFontID
*font_ids
= NULL
;
8173 Lisp_Object prev_family
= Qnil
;
8177 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8178 make_float (DEFAULT_REHASH_SIZE
),
8179 make_float (DEFAULT_REHASH_THRESHOLD
),
8181 h
= XHASH_TABLE (atsu_font_id_hash
);
8183 err
= ATSUFontCount (&nfonts
);
8186 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8187 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8190 for (i
= 0; i
< nfonts
; i
++)
8194 family
= atsu_find_font_family_name (font_ids
[i
]);
8195 if (NILP (family
) || SREF (family
, 0) == '.')
8197 if (!NILP (Fequal (prev_family
, family
)))
8198 family
= prev_family
;
8200 j
= hash_lookup (h
, family
, &hash_code
);
8203 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8204 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8207 else if (EQ (prev_family
, family
))
8208 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8210 prev_family
= family
;
8217 /* Create a dummy instance iterator here to avoid creating and
8218 destroying it in the loop. */
8219 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8221 /* Create an iterator to enumerate the font families. */
8222 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8225 FMDisposeFontFamilyInstanceIterator (&ffii
);
8229 GCPRO1 (text_encoding_info_alist
);
8231 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8237 TextEncoding encoding
;
8238 TextEncodingBase sc
;
8239 Lisp_Object text_encoding_info
, family
;
8241 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8247 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8249 sc
= GetTextEncodingBase (encoding
);
8250 text_encoding_info
= assq_no_quit (make_number (sc
),
8251 text_encoding_info_alist
);
8252 if (NILP (text_encoding_info
))
8253 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8254 text_encoding_info_alist
);
8255 decode_mac_font_name (name
, sizeof (name
),
8256 XCAR (XCDR (text_encoding_info
)));
8257 family
= build_string (name
);
8258 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8260 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8261 fm_font_family_alist
);
8263 /* Point the instance iterator at the current font family. */
8264 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8267 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8270 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8272 if (size
> 0 || style
== normal
)
8273 for (; !NILP (rest
); rest
= XCDR (rest
))
8274 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8280 /* Dispose of the iterators. */
8281 FMDisposeFontFamilyIterator (&ffi
);
8282 FMDisposeFontFamilyInstanceIterator (&ffii
);
8283 #else /* !TARGET_API_MAC_CARBON */
8285 SInt16 fontnum
, old_fontnum
;
8286 int num_mac_fonts
= CountResources('FOND');
8288 Handle font_handle
, font_handle_2
;
8289 short id
, scriptcode
;
8292 struct FontAssoc
*fat
;
8293 struct AsscEntry
*assc_entry
;
8294 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8295 struct gcpro gcpro1
;
8297 GetPort (&port
); /* save the current font number used */
8298 old_fontnum
= port
->txFont
;
8300 text_encoding_info_alist
= create_text_encoding_info_alist ();
8302 GCPRO1 (text_encoding_info_alist
);
8304 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8306 font_handle
= GetIndResource ('FOND', i
);
8310 GetResInfo (font_handle
, &id
, &type
, name
);
8311 GetFNum (name
, &fontnum
);
8313 if (fontnum
== 0 || *name
== '.')
8317 scriptcode
= FontToScript (fontnum
);
8318 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8319 text_encoding_info_alist
);
8320 if (NILP (text_encoding_info
))
8321 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8322 text_encoding_info_alist
);
8323 decode_mac_font_name (name
, sizeof (name
),
8324 XCAR (XCDR (text_encoding_info
)));
8325 family
= build_string (name
);
8326 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8328 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8329 fm_font_family_alist
);
8332 HLock (font_handle
);
8334 if (GetResourceSizeOnDisk (font_handle
)
8335 >= sizeof (struct FamRec
))
8337 fat
= (struct FontAssoc
*) (*font_handle
8338 + sizeof (struct FamRec
));
8340 = (struct AsscEntry
*) (*font_handle
8341 + sizeof (struct FamRec
)
8342 + sizeof (struct FontAssoc
));
8344 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8346 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8348 for (; !NILP (rest
); rest
= XCDR (rest
))
8349 add_mac_font_name (name
, assc_entry
->fontSize
,
8350 assc_entry
->fontStyle
,
8351 SDATA (XCAR (rest
)));
8355 HUnlock (font_handle
);
8356 font_handle_2
= GetNextFOND (font_handle
);
8357 ReleaseResource (font_handle
);
8358 font_handle
= font_handle_2
;
8360 while (ResError () == noErr
&& font_handle
);
8365 TextFont (old_fontnum
);
8366 #endif /* !TARGET_API_MAC_CARBON */
8371 mac_clear_font_name_table ()
8375 for (i
= 0; i
< font_name_count
; i
++)
8376 xfree (font_name_table
[i
]);
8377 xfree (font_name_table
);
8378 font_name_table
= NULL
;
8379 font_name_table_size
= font_name_count
= 0;
8380 fm_font_family_alist
= Qnil
;
8384 enum xlfd_scalable_field_index
8386 XLFD_SCL_PIXEL_SIZE
,
8387 XLFD_SCL_POINT_SIZE
,
8392 static const int xlfd_scalable_fields
[] =
8401 mac_do_list_fonts (pattern
, maxnames
)
8402 const char *pattern
;
8406 Lisp_Object font_list
= Qnil
;
8407 struct xlfdpat
*pat
;
8410 int scl_val
[XLFD_SCL_LAST
], *val
;
8414 if (font_name_table
== NULL
) /* Initialize when first used. */
8415 init_font_name_table ();
8417 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8420 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8421 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8422 fonts are scaled according to the specified size. */
8425 field
= xlfd_scalable_fields
;
8433 if ('0' <= *ptr
&& *ptr
<= '9')
8435 *val
= *ptr
++ - '0';
8436 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8437 *val
= *val
* 10 + *ptr
++ - '0';
8444 ptr
= strchr (ptr
, '-');
8447 while (ptr
&& i
< 14);
8449 if (i
== 14 && ptr
== NULL
)
8451 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8452 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8453 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8454 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8456 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8457 scl_val
[XLFD_SCL_POINT_SIZE
] =
8458 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8459 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8461 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8462 scl_val
[XLFD_SCL_AVGWIDTH
] =
8463 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8464 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8468 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8470 pat
= xlfdpat_create (pattern
);
8474 exact
= xlfdpat_exact_p (pat
);
8476 for (i
= 0; i
< font_name_count
; i
++)
8478 if (xlfdpat_match (pat
, font_name_table
[i
]))
8480 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8481 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8484 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8485 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8487 int former_len
= ptr
- font_name_table
[i
];
8489 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8490 memcpy (scaled
, font_name_table
[i
], former_len
);
8491 sprintf (scaled
+ former_len
,
8492 "-%d-%d-72-72-m-%d-%s",
8493 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8494 scl_val
[XLFD_SCL_POINT_SIZE
],
8495 scl_val
[XLFD_SCL_AVGWIDTH
],
8496 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8498 if (xlfdpat_match (pat
, scaled
))
8500 font_list
= Fcons (build_string (scaled
), font_list
);
8502 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8510 xlfdpat_destroy (pat
);
8515 /* Return a list of names of available fonts matching PATTERN on frame F.
8517 Frame F null means we have not yet created any frame on Mac, and
8518 consult the first display in x_display_list. MAXNAMES sets a limit
8519 on how many fonts to match. */
8522 x_list_fonts (f
, pattern
, size
, maxnames
)
8524 Lisp_Object pattern
;
8527 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8528 struct mac_display_info
*dpyinfo
8529 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8531 xassert (size
<= 0);
8533 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8534 if (NILP (patterns
))
8535 patterns
= Fcons (pattern
, Qnil
);
8537 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8539 pattern
= XCAR (patterns
);
8541 if (!STRINGP (pattern
))
8544 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8545 key
= Fcons (pattern
, make_number (maxnames
));
8547 list
= Fassoc (key
, tem
);
8550 list
= Fcdr_safe (list
);
8551 /* We have a cashed list. Don't have to get the list again. */
8556 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8559 /* MAC_TODO: add code for matching outline fonts here */
8561 /* Now store the result in the cache. */
8562 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8563 Fcons (Fcons (key
, list
),
8564 XCAR (XCDR (dpyinfo
->name_list_element
))));
8567 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8576 /* Check that FONT is valid on frame F. It is if it can be found in F's
8580 x_check_font (f
, font
)
8585 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8587 xassert (font
!= NULL
);
8589 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8590 if (dpyinfo
->font_table
[i
].name
8591 && font
== dpyinfo
->font_table
[i
].font
)
8594 xassert (i
< dpyinfo
->n_fonts
);
8597 #endif /* GLYPH_DEBUG != 0 */
8599 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8600 Note: There are (broken) X fonts out there with invalid XFontStruct
8601 min_bounds contents. For example, handa@etl.go.jp reports that
8602 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8603 have font->min_bounds.width == 0. */
8606 x_font_min_bounds (font
, w
, h
)
8607 MacFontStruct
*font
;
8610 *h
= FONT_HEIGHT (font
);
8611 *w
= font
->min_bounds
.width
;
8615 /* Compute the smallest character width and smallest font height over
8616 all fonts available on frame F. Set the members smallest_char_width
8617 and smallest_font_height in F's x_display_info structure to
8618 the values computed. Value is non-zero if smallest_font_height or
8619 smallest_char_width become smaller than they were before. */
8622 x_compute_min_glyph_bounds (f
)
8626 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8627 MacFontStruct
*font
;
8628 int old_width
= dpyinfo
->smallest_char_width
;
8629 int old_height
= dpyinfo
->smallest_font_height
;
8631 dpyinfo
->smallest_font_height
= 100000;
8632 dpyinfo
->smallest_char_width
= 100000;
8634 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8635 if (dpyinfo
->font_table
[i
].name
)
8637 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8640 font
= (MacFontStruct
*) fontp
->font
;
8641 xassert (font
!= (MacFontStruct
*) ~0);
8642 x_font_min_bounds (font
, &w
, &h
);
8644 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8645 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8648 xassert (dpyinfo
->smallest_char_width
> 0
8649 && dpyinfo
->smallest_font_height
> 0);
8651 return (dpyinfo
->n_fonts
== 1
8652 || dpyinfo
->smallest_char_width
< old_width
8653 || dpyinfo
->smallest_font_height
< old_height
);
8657 /* Determine whether given string is a fully-specified XLFD: all 14
8658 fields are present, none is '*'. */
8661 is_fully_specified_xlfd (p
)
8670 for (i
= 0; i
< 13; i
++)
8672 q
= strchr (p
+ 1, '-');
8675 if (q
- p
== 2 && *(p
+ 1) == '*')
8680 if (strchr (p
+ 1, '-') != NULL
)
8683 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8690 /* mac_load_query_font creates and returns an internal representation
8691 for a font in a MacFontStruct struct. There is really no concept
8692 corresponding to "loading" a font on the Mac. But we check its
8693 existence and find the font number and all other information for it
8694 and store them in the returned MacFontStruct. */
8696 static MacFontStruct
*
8697 mac_load_query_font (f
, fontname
)
8707 static ATSUFontID font_id
;
8708 ATSUStyle mac_style
= NULL
;
8711 #if TARGET_API_MAC_CARBON
8712 TextEncoding encoding
;
8717 MacFontStruct
*font
;
8718 XCharStruct
*space_bounds
= NULL
, *pcm
;
8720 if (is_fully_specified_xlfd (fontname
))
8724 Lisp_Object matched_fonts
;
8726 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8727 if (NILP (matched_fonts
))
8729 name
= SDATA (XCAR (matched_fonts
));
8732 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8736 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8739 static const ATSUAttributeTag tags
[] =
8740 {kATSUFontTag
, kATSUSizeTag
,
8741 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8742 static const ByteCount sizes
[] =
8743 {sizeof (ATSUFontID
), sizeof (Fixed
),
8744 sizeof (Boolean
), sizeof (Boolean
)};
8745 static Fixed size_fixed
;
8746 static Boolean bold_p
, italic_p
;
8747 static const ATSUAttributeValuePtr values
[] =
8748 {&font_id
, &size_fixed
,
8749 &bold_p
, &italic_p
};
8750 static const ATSUFontFeatureType types
[] =
8751 {kAllTypographicFeaturesType
, kDiacriticsType
};
8752 static const ATSUFontFeatureSelector selectors
[] =
8753 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8756 font_id
= atsu_find_font_from_family_name (family
);
8757 if (font_id
== kATSUInvalidFontID
)
8759 size_fixed
= Long2Fix (size
);
8760 bold_p
= (fontface
& bold
) != 0;
8761 italic_p
= (fontface
& italic
) != 0;
8762 err
= ATSUCreateStyle (&mac_style
);
8765 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8769 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8770 tags
, sizes
, values
);
8773 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8776 scriptcode
= kTextEncodingMacUnicode
;
8781 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8785 fontnum
= XINT (XCDR (tmp
));
8786 #if TARGET_API_MAC_CARBON
8787 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8789 scriptcode
= GetTextEncodingBase (encoding
);
8791 scriptcode
= FontToScript (fontnum
);
8795 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8797 font
->mac_fontnum
= fontnum
;
8798 font
->mac_fontsize
= size
;
8799 font
->mac_fontface
= fontface
;
8800 font
->mac_scriptcode
= scriptcode
;
8802 font
->mac_style
= mac_style
;
8803 #if USE_CG_TEXT_DRAWING
8804 font
->cg_font
= NULL
;
8805 font
->cg_glyphs
= NULL
;
8809 /* Apple Japanese (SJIS) font is listed as both
8810 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8811 (Roman script) in init_font_name_table (). The latter should be
8812 treated as a one-byte font. */
8813 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8814 font
->mac_scriptcode
= smRoman
;
8816 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8819 if (font
->mac_style
)
8824 font
->min_byte1
= 0;
8825 font
->max_byte1
= 0xff;
8826 font
->min_char_or_byte2
= 0;
8827 font
->max_char_or_byte2
= 0xff;
8829 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8830 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8831 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8832 pcm_init (font
->bounds
.rows
[0], 0x100);
8834 #if USE_CG_TEXT_DRAWING
8838 ATSFontRef ats_font
;
8840 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8842 /* Use CG text drawing if italic/bold is not synthesized. */
8843 if (err
== noErr
&& style
== fontface
)
8845 ats_font
= FMGetATSFontRefFromFont (font_id
);
8846 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8852 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8853 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8856 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8857 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8858 &font
->ascent
, &font
->descent
,
8860 #if USE_CG_TEXT_DRAWING
8861 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8868 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8870 mac_unload_font (&one_mac_display_info
, font
);
8874 pcm
= font
->bounds
.rows
[0];
8875 for (c
= 0x21; c
<= 0xff; c
++)
8878 /* Soft hyphen is not supported in ATSUI. */
8882 #if USE_CG_TEXT_DRAWING
8883 if (font
->cg_glyphs
)
8893 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8894 pcm
? pcm
+ c
: NULL
,
8895 #if USE_CG_TEXT_DRAWING
8896 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8903 #if USE_CG_TEXT_DRAWING
8904 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8906 /* Don't use CG text drawing if font substitution occurs in
8907 ASCII or Latin-1 characters. */
8908 CGFontRelease (font
->cg_font
);
8909 font
->cg_font
= NULL
;
8910 xfree (font
->cg_glyphs
);
8911 font
->cg_glyphs
= NULL
;
8922 FontInfo the_fontinfo
;
8923 int is_two_byte_font
;
8926 mac_prepare_for_quickdraw (f
);
8928 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8932 TextFace (fontface
);
8934 GetFontInfo (&the_fontinfo
);
8936 font
->ascent
= the_fontinfo
.ascent
;
8937 font
->descent
= the_fontinfo
.descent
;
8939 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8940 || font
->mac_scriptcode
== smTradChinese
8941 || font
->mac_scriptcode
== smSimpChinese
8942 || font
->mac_scriptcode
== smKorean
);
8944 if (is_two_byte_font
)
8948 font
->min_byte1
= 0xa1;
8949 font
->max_byte1
= 0xfe;
8950 font
->min_char_or_byte2
= 0xa1;
8951 font
->max_char_or_byte2
= 0xfe;
8953 /* Use the width of an "ideographic space" of that font
8954 because the_fontinfo.widMax returns the wrong width for
8956 switch (font
->mac_scriptcode
)
8959 font
->min_byte1
= 0x81;
8960 font
->max_byte1
= 0xfc;
8961 font
->min_char_or_byte2
= 0x40;
8962 font
->max_char_or_byte2
= 0xfc;
8963 char_width
= StringWidth("\p\x81\x40");
8966 font
->min_char_or_byte2
= 0x40;
8967 char_width
= StringWidth("\p\xa1\x40");
8970 char_width
= StringWidth("\p\xa1\xa1");
8973 char_width
= StringWidth("\p\xa1\xa1");
8977 font
->bounds
.per_char
= NULL
;
8979 if (fontface
& italic
)
8980 font
->max_bounds
.rbearing
= char_width
+ 1;
8982 font
->max_bounds
.rbearing
= char_width
;
8983 font
->max_bounds
.lbearing
= 0;
8984 font
->max_bounds
.width
= char_width
;
8985 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8986 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8988 font
->min_bounds
= font
->max_bounds
;
8994 font
->min_byte1
= font
->max_byte1
= 0;
8995 font
->min_char_or_byte2
= 0x20;
8996 font
->max_char_or_byte2
= 0xff;
8998 font
->bounds
.per_char
=
8999 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9000 bzero (font
->bounds
.per_char
,
9001 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9003 space_bounds
= font
->bounds
.per_char
;
9004 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9005 &font
->descent
, space_bounds
, NULL
);
9006 if (err
!= noErr
|| space_bounds
->width
<= 0)
9008 mac_unload_font (&one_mac_display_info
, font
);
9012 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9013 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9021 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9022 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9025 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9027 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9029 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9031 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9033 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9036 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9038 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9040 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9042 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9044 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9049 font
->mac_style
== NULL
&&
9051 font
->max_bounds
.width
== font
->min_bounds
.width
9052 && font
->min_bounds
.lbearing
>= 0
9053 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9055 /* Fixed width and no overhangs. */
9056 xfree (font
->bounds
.per_char
);
9057 font
->bounds
.per_char
= NULL
;
9061 #if !defined (MAC_OS8) || USE_ATSUI
9062 /* AppKit and WebKit do some adjustment to the heights of Courier,
9063 Helvetica, and Times. This only works on the environments where
9064 srcCopy text transfer mode is never used. */
9066 #ifdef MAC_OS8 /* implies USE_ATSUI */
9069 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9070 || strcmp (family
, "times") == 0))
9071 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9079 mac_unload_font (dpyinfo
, font
)
9080 struct mac_display_info
*dpyinfo
;
9083 xfree (font
->full_name
);
9085 if (font
->mac_style
)
9089 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9090 if (font
->bounds
.rows
[i
])
9091 xfree (font
->bounds
.rows
[i
]);
9092 xfree (font
->bounds
.rows
);
9093 ATSUDisposeStyle (font
->mac_style
);
9097 if (font
->bounds
.per_char
)
9098 xfree (font
->bounds
.per_char
);
9099 #if USE_CG_TEXT_DRAWING
9101 CGFontRelease (font
->cg_font
);
9102 if (font
->cg_glyphs
)
9103 xfree (font
->cg_glyphs
);
9109 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9110 pointer to the structure font_info while allocating it dynamically.
9111 If SIZE is 0, load any size of font.
9112 If loading is failed, return NULL. */
9115 x_load_font (f
, fontname
, size
)
9117 register char *fontname
;
9120 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9121 Lisp_Object font_names
;
9123 /* Get a list of all the fonts that match this name. Once we
9124 have a list of matching fonts, we compare them against the fonts
9125 we already have by comparing names. */
9126 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9128 if (!NILP (font_names
))
9133 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9134 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9135 if (dpyinfo
->font_table
[i
].name
9136 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9137 SDATA (XCAR (tail
)))
9138 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9139 SDATA (XCAR (tail
)))))
9140 return (dpyinfo
->font_table
+ i
);
9145 /* Load the font and add it to the table. */
9147 struct MacFontStruct
*font
;
9148 struct font_info
*fontp
;
9151 fontname
= (char *) SDATA (XCAR (font_names
));
9154 font
= mac_load_query_font (f
, fontname
);
9159 /* Find a free slot in the font table. */
9160 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9161 if (dpyinfo
->font_table
[i
].name
== NULL
)
9164 /* If no free slot found, maybe enlarge the font table. */
9165 if (i
== dpyinfo
->n_fonts
9166 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9169 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9170 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9172 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9175 fontp
= dpyinfo
->font_table
+ i
;
9176 if (i
== dpyinfo
->n_fonts
)
9179 /* Now fill in the slots of *FONTP. */
9181 bzero (fontp
, sizeof (*fontp
));
9183 fontp
->font_idx
= i
;
9184 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9185 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9187 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9189 /* Fixed width font. */
9190 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9197 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9198 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9200 fontp
->space_width
= pcm
->width
;
9202 fontp
->space_width
= FONT_WIDTH (font
);
9206 int width
= pcm
->width
;
9207 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9208 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9209 width
+= pcm
->width
;
9210 fontp
->average_width
= width
/ 95;
9213 fontp
->average_width
= FONT_WIDTH (font
);
9216 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9217 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9219 fontp
->size
= font
->max_bounds
.width
;
9220 fontp
->height
= FONT_HEIGHT (font
);
9222 /* For some font, ascent and descent in max_bounds field is
9223 larger than the above value. */
9224 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9225 if (max_height
> fontp
->height
)
9226 fontp
->height
= max_height
;
9229 /* The slot `encoding' specifies how to map a character
9230 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9231 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9232 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9233 2:0xA020..0xFF7F). For the moment, we don't know which charset
9234 uses this font. So, we set information in fontp->encoding[1]
9235 which is never used by any charset. If mapping can't be
9236 decided, set FONT_ENCODING_NOT_DECIDED. */
9237 if (font
->mac_scriptcode
== smJapanese
)
9238 fontp
->encoding
[1] = 4;
9242 = (font
->max_byte1
== 0
9244 ? (font
->min_char_or_byte2
< 0x80
9245 ? (font
->max_char_or_byte2
< 0x80
9246 ? 0 /* 0x20..0x7F */
9247 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9248 : 1) /* 0xA0..0xFF */
9250 : (font
->min_byte1
< 0x80
9251 ? (font
->max_byte1
< 0x80
9252 ? (font
->min_char_or_byte2
< 0x80
9253 ? (font
->max_char_or_byte2
< 0x80
9254 ? 0 /* 0x2020..0x7F7F */
9255 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9256 : 3) /* 0x20A0..0x7FFF */
9257 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9258 : (font
->min_char_or_byte2
< 0x80
9259 ? (font
->max_char_or_byte2
< 0x80
9260 ? 2 /* 0xA020..0xFF7F */
9261 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9262 : 1))); /* 0xA0A0..0xFFFF */
9265 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9266 fontp
->baseline_offset
9267 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9268 ? (long) value
: 0);
9269 fontp
->relative_compose
9270 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9271 ? (long) value
: 0);
9272 fontp
->default_ascent
9273 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9274 ? (long) value
: 0);
9276 fontp
->baseline_offset
= 0;
9277 fontp
->relative_compose
= 0;
9278 fontp
->default_ascent
= 0;
9281 /* Set global flag fonts_changed_p to non-zero if the font loaded
9282 has a character with a smaller width than any other character
9283 before, or if the font loaded has a smaller height than any
9284 other font loaded before. If this happens, it will make a
9285 glyph matrix reallocation necessary. */
9286 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9293 /* Return a pointer to struct font_info of a font named FONTNAME for
9294 frame F. If no such font is loaded, return NULL. */
9297 x_query_font (f
, fontname
)
9299 register char *fontname
;
9301 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9304 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9305 if (dpyinfo
->font_table
[i
].name
9306 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9307 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9308 return (dpyinfo
->font_table
+ i
);
9313 /* Find a CCL program for a font specified by FONTP, and set the member
9314 `encoder' of the structure. */
9317 x_find_ccl_program (fontp
)
9318 struct font_info
*fontp
;
9320 Lisp_Object list
, elt
;
9322 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9326 && STRINGP (XCAR (elt
))
9327 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9333 struct ccl_program
*ccl
9334 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9336 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9339 fontp
->font_encoder
= ccl
;
9343 #if USE_MAC_FONT_PANEL
9344 /* Whether Font Panel has been shown before. The first call to font
9345 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9346 slow. This variable is used for deferring such a call as much as
9348 static int font_panel_shown_p
= 0;
9350 extern Lisp_Object Qfont
;
9351 static Lisp_Object Qpanel_closed
, Qselection
;
9353 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9357 const EventParamName
*,
9358 const EventParamType
*));
9361 mac_font_panel_visible_p ()
9363 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9366 static pascal OSStatus
9367 mac_handle_font_event (next_handler
, event
, data
)
9368 EventHandlerCallRef next_handler
;
9372 OSStatus result
, err
;
9375 const EventParamName
*names
;
9376 const EventParamType
*types
;
9377 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9378 kEventParamATSUFontSize
,
9379 kEventParamFMFontFamily
,
9380 kEventParamFMFontStyle
,
9381 kEventParamFMFontSize
,
9382 kEventParamFontColor
};
9383 static const EventParamType types_sel
[] = {typeATSUFontID
,
9390 result
= CallNextEventHandler (next_handler
, event
);
9391 if (result
!= eventNotHandledErr
)
9394 switch (GetEventKind (event
))
9396 case kEventFontPanelClosed
:
9397 id_key
= Qpanel_closed
;
9403 case kEventFontSelection
:
9404 id_key
= Qselection
;
9405 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9411 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9421 mac_show_hide_font_panel ()
9423 if (!font_panel_shown_p
)
9427 static const EventTypeSpec specs
[] =
9428 {{kEventClassFont
, kEventFontPanelClosed
},
9429 {kEventClassFont
, kEventFontSelection
}};
9431 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9432 GetEventTypeCount (specs
),
9437 font_panel_shown_p
= 1;
9440 return FPShowHideFontPanel ();
9444 mac_set_font_info_for_selection (f
, face_id
, c
)
9449 EventTargetRef target
= NULL
;
9450 XFontStruct
*font
= NULL
;
9452 if (!mac_font_panel_visible_p ())
9457 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9459 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9463 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9464 face
= FACE_FROM_ID (f
, face_id
);
9470 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9473 if (font
->mac_fontnum
!= -1)
9475 FontSelectionQDStyle qd_style
;
9477 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9478 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9479 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9480 qd_style
.size
= font
->mac_fontsize
;
9481 qd_style
.hasColor
= false;
9483 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9484 1, &qd_style
, target
);
9487 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9488 1, &font
->mac_style
, target
);
9496 /* The Mac Event loop code */
9498 #if !TARGET_API_MAC_CARBON
9500 #include <Quickdraw.h>
9501 #include <Balloons.h>
9502 #include <Devices.h>
9504 #include <Gestalt.h>
9506 #include <Processes.h>
9508 #include <ToolUtils.h>
9509 #include <TextUtils.h>
9510 #include <Dialogs.h>
9513 #include <Resources.h>
9518 #endif /* ! TARGET_API_MAC_CARBON */
9523 #define DEFAULT_NUM_COLS 80
9525 #define MIN_DOC_SIZE 64
9526 #define MAX_DOC_SIZE 32767
9528 #define EXTRA_STACK_ALLOC (256 * 1024)
9530 #define ARGV_STRING_LIST_ID 129
9531 #define ABOUT_ALERT_ID 128
9532 #define RAM_TOO_LARGE_ALERT_ID 129
9534 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9535 Lisp_Object Qreverse
;
9538 /* Modifier associated with the control key, or nil to ignore. */
9539 Lisp_Object Vmac_control_modifier
;
9541 /* Modifier associated with the option key, or nil to ignore. */
9542 Lisp_Object Vmac_option_modifier
;
9544 /* Modifier associated with the command key, or nil to ignore. */
9545 Lisp_Object Vmac_command_modifier
;
9547 /* Modifier associated with the function key, or nil to ignore. */
9548 Lisp_Object Vmac_function_modifier
;
9550 /* True if the option and command modifiers should be used to emulate
9551 a three button mouse */
9552 Lisp_Object Vmac_emulate_three_button_mouse
;
9554 #if TARGET_API_MAC_CARBON
9555 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9556 mouse-2, instead of mouse-3. */
9557 int mac_wheel_button_is_mouse_2
;
9559 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9560 for processing before Emacs sees it. */
9561 int mac_pass_command_to_system
;
9563 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9564 for processing before Emacs sees it. */
9565 int mac_pass_control_to_system
;
9568 /* Points to the variable `inev' in the function XTread_socket. It is
9569 used for passing an input event to the function back from
9570 Carbon/Apple event handlers. */
9571 static struct input_event
*read_socket_inev
= NULL
;
9573 /* Whether or not the screen configuration has changed. */
9574 static int mac_screen_config_changed
= 0;
9576 Point saved_menu_event_location
;
9579 #if TARGET_API_MAC_CARBON
9580 static Lisp_Object Qhi_command
;
9582 extern Lisp_Object Qwindow
;
9583 static Lisp_Object Qtoolbar_switch_mode
;
9586 static TSMDocumentID tsm_document_id
;
9587 static Lisp_Object Qtext_input
;
9588 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9589 static Lisp_Object Vmac_ts_active_input_overlay
;
9590 extern Lisp_Object Qbefore_string
;
9591 static Lisp_Object Vmac_ts_script_language_on_focus
;
9592 static Lisp_Object saved_ts_script_language_on_focus
;
9593 static ScriptLanguageRecord saved_ts_language
;
9594 static Component saved_ts_component
;
9596 #endif /* TARGET_API_MAC_CARBON */
9597 extern int mac_ready_for_apple_events
;
9598 extern Lisp_Object Qundefined
;
9599 extern void init_apple_event_handler
P_ ((void));
9600 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9601 Lisp_Object
*, Lisp_Object
*,
9603 extern OSErr init_coercion_handler
P_ ((void));
9606 extern OSErr install_drag_handler
P_ ((WindowRef
));
9607 extern void remove_drag_handler
P_ ((WindowRef
));
9609 #if TARGET_API_MAC_CARBON
9610 /* Showing help echo string during menu tracking */
9611 extern OSStatus install_menu_target_item_handler
P_ ((void));
9614 extern OSStatus
install_service_handler ();
9615 static Lisp_Object Qservice
, Qpaste
, Qperform
;
9619 extern void init_emacs_passwd_dir ();
9620 extern int emacs_main (int, char **, char **);
9622 extern void initialize_applescript();
9623 extern void terminate_applescript();
9625 /* Table for translating Mac keycode to X keysym values. Contributed
9627 Mapping for special keys is now identical to that in Apple X11
9628 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9629 on the right of the Cmd key on laptops, and fn + `enter' (->
9631 static const unsigned char keycode_to_xkeysym_table
[] = {
9632 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9633 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9634 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9636 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9637 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9638 /*0x38*/ 0, 0, 0, 0,
9639 /*0x3C*/ 0, 0, 0, 0,
9641 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9642 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9643 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9644 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9646 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9647 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9648 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9649 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9651 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9652 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9653 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9654 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9656 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9657 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9658 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9659 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9663 /* Table for translating Mac keycode with the laptop `fn' key to that
9664 without it. Destination symbols in comments are keys on US
9665 keyboard, and they may not be the same on other types of keyboards.
9666 If the destination is identical to the source (f1 ... f12), it
9667 doesn't map `fn' key to a modifier. */
9668 static const unsigned char fn_keycode_to_keycode_table
[] = {
9669 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9670 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9671 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9673 /*0x30*/ 0, 0, 0, 0,
9674 /*0x34*/ 0, 0, 0, 0,
9675 /*0x38*/ 0, 0, 0, 0,
9676 /*0x3C*/ 0, 0, 0, 0,
9678 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9679 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9680 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9681 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9683 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9684 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9685 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9686 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9688 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9689 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9690 /*0x68*/ 0, 0, 0, 0,
9691 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9693 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9694 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9695 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9698 #endif /* MAC_OSX */
9701 #if TARGET_API_MAC_CARBON
9702 mac_to_emacs_modifiers (UInt32 mods
)
9704 mac_to_emacs_modifiers (EventModifiers mods
)
9707 unsigned int result
= 0;
9708 if (mods
& shiftKey
)
9709 result
|= shift_modifier
;
9711 /* Deactivated to simplify configuration:
9712 if Vmac_option_modifier is non-NIL, we fully process the Option
9713 key. Otherwise, we only process it if an additional Ctrl or Command
9714 is pressed. That way the system may convert the character to a
9716 if ((mods & optionKey) &&
9717 (( !NILP(Vmac_option_modifier) ||
9718 ((mods & cmdKey) || (mods & controlKey))))) */
9720 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9721 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9723 result
|= XUINT(val
);
9725 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9726 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9728 result
|= XUINT(val
);
9730 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9731 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9733 result
|= XUINT(val
);
9737 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9738 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9740 result
|= XUINT(val
);
9748 mac_mapped_modifiers (modifiers
)
9751 UInt32 mapped_modifiers_all
=
9752 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9753 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9754 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9757 mapped_modifiers_all
|=
9758 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9761 return mapped_modifiers_all
& modifiers
;
9765 mac_get_emulated_btn ( UInt32 modifiers
)
9768 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9769 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9770 if (modifiers
& cmdKey
)
9771 result
= cmdIs3
? 2 : 1;
9772 else if (modifiers
& optionKey
)
9773 result
= cmdIs3
? 1 : 2;
9778 #if TARGET_API_MAC_CARBON
9779 /***** Code to handle C-g testing *****/
9780 extern int quit_char
;
9781 extern int make_ctrl_char
P_ ((int));
9784 mac_quit_char_key_p (modifiers
, key_code
)
9785 UInt32 modifiers
, key_code
;
9788 unsigned long some_state
= 0;
9789 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9790 int c
, emacs_modifiers
;
9792 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9793 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9794 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9795 if (char_code
& ~0xff)
9798 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9799 if (emacs_modifiers
& ctrl_modifier
)
9800 c
= make_ctrl_char (char_code
);
9802 c
|= (emacs_modifiers
9803 & (meta_modifier
| alt_modifier
9804 | hyper_modifier
| super_modifier
));
9806 return c
== quit_char
;
9810 #if TARGET_API_MAC_CARBON
9811 /* Obtains the event modifiers from the event ref and then calls
9812 mac_to_emacs_modifiers. */
9814 mac_event_to_emacs_modifiers (EventRef eventRef
)
9816 UInt32 mods
= 0, class;
9818 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9819 sizeof (UInt32
), NULL
, &mods
);
9820 class = GetEventClass (eventRef
);
9821 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9822 (class == kEventClassMouse
|| class == kEventClassCommand
))
9824 mods
&= ~(optionKey
| cmdKey
);
9826 return mac_to_emacs_modifiers (mods
);
9829 /* Given an event ref, return the code to use for the mouse button
9830 code in the emacs input_event. */
9832 mac_get_mouse_btn (EventRef ref
)
9834 EventMouseButton result
= kEventMouseButtonPrimary
;
9835 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9836 sizeof (EventMouseButton
), NULL
, &result
);
9839 case kEventMouseButtonPrimary
:
9840 if (NILP (Vmac_emulate_three_button_mouse
))
9844 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9845 sizeof (UInt32
), NULL
, &mods
);
9846 return mac_get_emulated_btn(mods
);
9848 case kEventMouseButtonSecondary
:
9849 return mac_wheel_button_is_mouse_2
? 2 : 1;
9850 case kEventMouseButtonTertiary
:
9851 case 4: /* 4 is the number for the mouse wheel button */
9852 return mac_wheel_button_is_mouse_2
? 1 : 2;
9858 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9859 events. However the click of the mouse wheel is not converted to a
9860 mouseDown or mouseUp event. Likewise for dead key events. This
9861 calls ConvertEventRefToEventRecord, but then checks to see if it is
9862 a mouse up/down, or a dead key Carbon event that has not been
9863 converted, and if so, converts it by hand (to be picked up in the
9864 XTread_socket loop). */
9865 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9868 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9874 switch (GetEventClass (eventRef
))
9876 case kEventClassMouse
:
9877 switch (GetEventKind (eventRef
))
9879 case kEventMouseDown
:
9880 eventRec
->what
= mouseDown
;
9885 eventRec
->what
= mouseUp
;
9894 case kEventClassKeyboard
:
9895 switch (GetEventKind (eventRef
))
9897 case kEventRawKeyDown
:
9899 goto keystroke_common
;
9900 case kEventRawKeyRepeat
:
9902 goto keystroke_common
;
9903 case kEventRawKeyUp
:
9907 unsigned char char_codes
;
9910 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9911 typeChar
, NULL
, sizeof (char),
9914 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9915 typeUInt32
, NULL
, sizeof (UInt32
),
9919 eventRec
->what
= action
;
9920 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9937 /* Need where and when. */
9940 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9941 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9942 /* Use two step process because new event modifiers are 32-bit
9943 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9944 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9945 NULL
, sizeof (UInt32
), NULL
, &mods
);
9946 eventRec
->modifiers
= mods
;
9948 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9960 Handle menubar_handle
;
9963 menubar_handle
= GetNewMBar (128);
9964 if(menubar_handle
== NULL
)
9966 SetMenuBar (menubar_handle
);
9969 #if !TARGET_API_MAC_CARBON
9970 menu
= GetMenuRef (M_APPLE
);
9972 AppendResMenu (menu
, 'DRVR');
9980 do_init_managers (void)
9982 #if !TARGET_API_MAC_CARBON
9983 InitGraf (&qd
.thePort
);
9985 FlushEvents (everyEvent
, 0);
9990 #endif /* !TARGET_API_MAC_CARBON */
9993 #if !TARGET_API_MAC_CARBON
9994 /* set up some extra stack space for use by emacs */
9995 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9997 /* MaxApplZone must be called for AppleScript to execute more
9998 complicated scripts */
10001 #endif /* !TARGET_API_MAC_CARBON */
10005 do_check_ram_size (void)
10007 SInt32 physical_ram_size
, logical_ram_size
;
10009 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10010 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10011 || physical_ram_size
> (1 << VALBITS
)
10012 || logical_ram_size
> (1 << VALBITS
))
10014 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10018 #endif /* MAC_OS8 */
10021 do_window_update (WindowRef win
)
10023 struct frame
*f
= mac_window_to_frame (win
);
10027 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10029 if (win
!= tip_window
)
10031 if (f
->async_visible
== 0)
10033 /* Update events may occur when a frame gets iconified. */
10035 f
->async_visible
= 1;
10036 f
->async_iconified
= 0;
10037 SET_FRAME_GARBAGED (f
);
10043 #if TARGET_API_MAC_CARBON
10044 RgnHandle region
= NewRgn ();
10046 GetPortVisibleRegion (GetWindowPort (win
), region
);
10047 GetRegionBounds (region
, &r
);
10048 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10050 mac_prepare_for_quickdraw (f
);
10052 UpdateControls (win
, region
);
10053 DisposeRgn (region
);
10055 r
= (*win
->visRgn
)->rgnBBox
;
10056 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10057 UpdateControls (win
, win
->visRgn
);
10066 is_emacs_window (WindowRef win
)
10068 Lisp_Object tail
, frame
;
10073 FOR_EACH_FRAME (tail
, frame
)
10074 if (FRAME_MAC_P (XFRAME (frame
)))
10075 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10086 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10088 err
= ActivateTSMDocument (tsm_document_id
);
10092 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10093 && EQ (saved_ts_script_language_on_focus
, Qt
))
10094 slptr
= &saved_ts_language
;
10095 else if (CONSP (Vmac_ts_script_language_on_focus
)
10096 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10097 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10098 && CONSP (saved_ts_script_language_on_focus
)
10099 && EQ (XCAR (saved_ts_script_language_on_focus
),
10100 XCAR (Vmac_ts_script_language_on_focus
))
10101 && EQ (XCDR (saved_ts_script_language_on_focus
),
10102 XCDR (Vmac_ts_script_language_on_focus
)))
10104 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10105 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10112 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10113 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10114 kKeyboardInputMethodClass
);
10116 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10119 err
= SetTextServiceLanguage (slptr
);
10121 /* Seems to be needed on Mac OS X 10.2. */
10123 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10133 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10135 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10137 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10139 err
= GetTextServiceLanguage (&saved_ts_language
);
10141 slptr
= &saved_ts_language
;
10143 else if (CONSP (Vmac_ts_script_language_on_focus
)
10144 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10145 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10147 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10148 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10154 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10155 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10156 kKeyboardInputMethodClass
);
10158 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10162 err
= DeactivateTSMDocument (tsm_document_id
);
10168 #if !TARGET_API_MAC_CARBON
10170 do_apple_menu (SInt16 menu_item
)
10173 SInt16 da_driver_refnum
;
10175 if (menu_item
== I_ABOUT
)
10176 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10179 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10180 da_driver_refnum
= OpenDeskAcc (item_name
);
10183 #endif /* !TARGET_API_MAC_CARBON */
10185 /* Handle drags in size box. Based on code contributed by Ben
10186 Mesander and IM - Window Manager A. */
10189 do_grow_window (w
, e
)
10191 const EventRecord
*e
;
10194 int rows
, columns
, width
, height
;
10195 struct frame
*f
= mac_window_to_frame (w
);
10196 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10197 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10198 #if TARGET_API_MAC_CARBON
10204 if (size_hints
->flags
& PMinSize
)
10206 min_width
= size_hints
->min_width
;
10207 min_height
= size_hints
->min_height
;
10209 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10211 #if TARGET_API_MAC_CARBON
10212 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10214 height
= new_rect
.bottom
- new_rect
.top
;
10215 width
= new_rect
.right
- new_rect
.left
;
10217 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10218 /* see if it really changed size */
10219 if (grow_size
== 0)
10221 height
= HiWord (grow_size
);
10222 width
= LoWord (grow_size
);
10225 if (width
!= FRAME_PIXEL_WIDTH (f
)
10226 || height
!= FRAME_PIXEL_HEIGHT (f
))
10228 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10229 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10231 x_set_window_size (f
, 0, columns
, rows
);
10236 #if TARGET_API_MAC_CARBON
10238 mac_get_ideal_size (f
)
10241 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10242 WindowRef w
= FRAME_MAC_WINDOW (f
);
10244 Rect standard_rect
;
10245 int height
, width
, columns
, rows
;
10247 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10248 ideal_size
.v
= dpyinfo
->height
;
10249 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10250 /* Adjust the standard size according to character boundaries. */
10251 width
= standard_rect
.right
- standard_rect
.left
;
10252 height
= standard_rect
.bottom
- standard_rect
.top
;
10253 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10254 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10255 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10256 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10262 /* Handle clicks in zoom box. Calculation of "standard state" based
10263 on code in IM - Window Manager A and code contributed by Ben
10264 Mesander. The standard state of an Emacs window is 80-characters
10265 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10268 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10270 Rect zoom_rect
, port_rect
;
10272 struct frame
*f
= mac_window_to_frame (w
);
10273 #if TARGET_API_MAC_CARBON
10274 Point ideal_size
= mac_get_ideal_size (f
);
10276 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10277 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10278 && port_rect
.left
== zoom_rect
.left
10279 && port_rect
.top
== zoom_rect
.top
)
10280 zoom_in_or_out
= inZoomIn
;
10282 zoom_in_or_out
= inZoomOut
;
10285 mac_clear_window (f
);
10287 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10288 #else /* not TARGET_API_MAC_CARBON */
10291 int w_title_height
, rows
;
10292 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10294 GetPort (&save_port
);
10296 SetPortWindowPort (w
);
10298 /* Clear window to avoid flicker. */
10299 EraseRect (&(w
->portRect
));
10300 if (zoom_in_or_out
== inZoomOut
)
10302 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10303 LocalToGlobal (&top_left
);
10305 /* calculate height of window's title bar */
10306 w_title_height
= top_left
.v
- 1
10307 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10309 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10310 zoom_rect
= qd
.screenBits
.bounds
;
10311 zoom_rect
.top
+= w_title_height
;
10312 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10314 zoom_rect
.right
= zoom_rect
.left
10315 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10317 /* Adjust the standard size according to character boundaries. */
10318 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10320 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10322 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10326 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10328 SetPort (save_port
);
10329 #endif /* not TARGET_API_MAC_CARBON */
10331 #if !TARGET_API_MAC_CARBON
10332 /* retrieve window size and update application values */
10333 port_rect
= w
->portRect
;
10334 height
= port_rect
.bottom
- port_rect
.top
;
10335 width
= port_rect
.right
- port_rect
.left
;
10337 mac_handle_size_change (f
, width
, height
);
10338 mac_handle_origin_change (f
);
10343 mac_set_unicode_keystroke_event (code
, buf
)
10345 struct input_event
*buf
;
10347 int charset_id
, c1
, c2
;
10351 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10354 else if (code
< 0x100)
10357 charset_id
= CHARSET_8_BIT_CONTROL
;
10359 charset_id
= charset_latin_iso8859_1
;
10360 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10361 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10366 charset_id
= charset_mule_unicode_0100_24ff
,
10368 else if (code
< 0x33FF)
10369 charset_id
= charset_mule_unicode_2500_33ff
,
10371 else if (code
>= 0xE000)
10372 charset_id
= charset_mule_unicode_e000_ffff
,
10374 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10375 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10376 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10381 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10383 unsigned char char_code
;
10384 UInt32 key_code
, modifiers
;
10385 unsigned long timestamp
;
10386 struct input_event
*buf
;
10388 static SInt16 last_key_script
= -1;
10389 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10390 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10393 if (mapped_modifiers
& kEventKeyModifierFnMask
10394 && key_code
<= 0x7f
10395 && fn_keycode_to_keycode_table
[key_code
])
10396 key_code
= fn_keycode_to_keycode_table
[key_code
];
10399 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10401 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10402 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10404 if (modifiers
& kEventKeyModifierFnMask
10405 && key_code
<= 0x7f
10406 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10407 modifiers
&= ~kEventKeyModifierFnMask
;
10410 else if (mapped_modifiers
)
10412 /* translate the keycode back to determine the original key */
10414 UCKeyboardLayout
*uchr_ptr
= NULL
;
10415 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10417 KeyboardLayoutRef layout
;
10419 err
= KLGetCurrentKeyboardLayout (&layout
);
10421 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10422 (const void **) &uchr_ptr
);
10424 static SInt16 last_key_layout_id
= 0;
10425 static Handle uchr_handle
= (Handle
)-1;
10426 SInt16 current_key_layout_id
=
10427 GetScriptVariable (current_key_script
, smScriptKeys
);
10429 if (uchr_handle
== (Handle
)-1
10430 || last_key_layout_id
!= current_key_layout_id
)
10432 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10433 last_key_layout_id
= current_key_layout_id
;
10436 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10442 UInt16 key_action
= action
- keyDown
;
10443 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10444 UInt32 keyboard_type
= LMGetKbdType ();
10445 SInt32 dead_key_state
= 0;
10447 UniCharCount actual_length
;
10449 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10450 modifier_key_state
, keyboard_type
,
10451 kUCKeyTranslateNoDeadKeysMask
,
10453 1, &actual_length
, &code
);
10454 if (status
== noErr
&& actual_length
== 1)
10455 mac_set_unicode_keystroke_event (code
, buf
);
10457 #endif /* MAC_OSX */
10459 if (buf
->kind
== NO_EVENT
)
10461 /* This code comes from Keyboard Resource, Appendix C of IM
10462 - Text. This is necessary since shift is ignored in KCHR
10463 table translation when option or command is pressed. It
10464 also does not translate correctly control-shift chars
10465 like C-% so mask off shift here also. */
10466 /* Mask off modifier keys that are mapped to some Emacs
10468 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10469 /* set high byte of keycode to modifier high byte*/
10470 int new_key_code
= key_code
| new_modifiers
;
10471 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10472 unsigned long some_state
= 0;
10473 UInt32 new_char_code
;
10475 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10476 if (new_char_code
== 0)
10477 /* Seems like a dead key. Append up-stroke. */
10478 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10482 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10483 buf
->code
= new_char_code
& 0xff;
10488 if (buf
->kind
== NO_EVENT
)
10490 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10491 buf
->code
= char_code
;
10494 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10495 buf
->modifiers
|= (extra_keyboard_modifiers
10496 & (meta_modifier
| alt_modifier
10497 | hyper_modifier
| super_modifier
));
10499 #if TARGET_API_MAC_CARBON
10500 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10501 && buf
->code
>= 0x80 && buf
->modifiers
)
10504 TextEncoding encoding
= kTextEncodingMacRoman
;
10505 TextToUnicodeInfo ttu_info
;
10507 UpgradeScriptInfoToTextEncoding (current_key_script
,
10508 kTextLanguageDontCare
,
10509 kTextRegionDontCare
,
10511 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10516 ByteCount unicode_len
;
10519 pstr
[1] = buf
->code
;
10520 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10522 &unicode_len
, &code
);
10523 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10524 mac_set_unicode_keystroke_event (code
, buf
);
10525 DisposeTextToUnicodeInfo (&ttu_info
);
10530 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10531 && buf
->code
>= 0x80
10532 && last_key_script
!= current_key_script
)
10534 struct input_event event
;
10536 EVENT_INIT (event
);
10537 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10539 event
.code
= current_key_script
;
10540 event
.timestamp
= timestamp
;
10541 kbd_buffer_store_event (&event
);
10542 last_key_script
= current_key_script
;
10547 mac_store_apple_event (class, id
, desc
)
10548 Lisp_Object
class, id
;
10549 const AEDesc
*desc
;
10551 struct input_event buf
;
10555 buf
.kind
= MAC_APPLE_EVENT
;
10558 XSETFRAME (buf
.frame_or_window
,
10559 mac_focus_frame (&one_mac_display_info
));
10560 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10561 is safe to use them during read_socket_hook. */
10562 buf
.arg
= mac_aedesc_to_lisp (desc
);
10563 kbd_buffer_store_event (&buf
);
10566 #if TARGET_API_MAC_CARBON
10568 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10569 event
, num_params
, names
, types
)
10570 AEEventClass
class;
10572 Lisp_Object class_key
, id_key
;
10575 const EventParamName
*names
;
10576 const EventParamType
*types
;
10578 OSStatus err
= eventNotHandledErr
;
10579 Lisp_Object binding
;
10581 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10582 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10584 if (INTEGERP (binding
))
10585 err
= XINT (binding
);
10588 AppleEvent apple_event
;
10589 err
= create_apple_event_from_event_ref (event
, num_params
,
10594 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10595 AEDisposeDesc (&apple_event
);
10596 mac_wakeup_from_rne ();
10605 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10609 const AEDesc
*desc
;
10611 struct input_event buf
;
10615 buf
.kind
= DRAG_N_DROP_EVENT
;
10616 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10617 buf
.timestamp
= TickCount () * (1000 / 60);
10618 XSETINT (buf
.x
, mouse_pos
.h
);
10619 XSETINT (buf
.y
, mouse_pos
.v
);
10620 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10621 buf
.arg
= mac_aedesc_to_lisp (desc
);
10622 kbd_buffer_store_event (&buf
);
10627 mac_store_service_event (event
)
10631 Lisp_Object id_key
;
10633 const EventParamName
*names
;
10634 const EventParamType
*types
;
10635 static const EventParamName names_pfm
[] =
10636 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10637 static const EventParamType types_pfm
[] =
10638 {typeCFStringRef
, typeCFStringRef
};
10640 switch (GetEventKind (event
))
10642 case kEventServicePaste
:
10649 case kEventServicePerform
:
10651 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10660 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10666 #endif /* MAC_OSX */
10668 static pascal OSStatus
10669 mac_handle_window_event (next_handler
, event
, data
)
10670 EventHandlerCallRef next_handler
;
10675 OSStatus err
, result
= eventNotHandledErr
;
10678 XSizeHints
*size_hints
;
10680 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
10681 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10683 return eventNotHandledErr
;
10685 f
= mac_window_to_frame (wp
);
10686 switch (GetEventKind (event
))
10688 /* -- window refresh events -- */
10690 case kEventWindowUpdate
:
10691 result
= CallNextEventHandler (next_handler
, event
);
10692 if (result
!= eventNotHandledErr
)
10695 do_window_update (wp
);
10699 /* -- window state change events -- */
10701 case kEventWindowShowing
:
10702 size_hints
= FRAME_SIZE_HINTS (f
);
10703 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
10705 struct frame
*sf
= SELECTED_FRAME ();
10707 if (!(FRAME_MAC_P (sf
) && sf
->async_visible
))
10708 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
10711 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
10712 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10713 kWindowCascadeStartAtParentWindowScreen
10715 kWindowCascadeOnParentWindowScreen
10718 #if USE_MAC_TOOLBAR
10719 /* This is a workaround. RepositionWindow fails to put
10720 a window at the cascading position when its parent
10721 window has a Carbon HIToolbar. */
10722 if ((f
->left_pos
== sf
->left_pos
10723 && f
->top_pos
== sf
->top_pos
)
10724 || (f
->left_pos
== sf
->left_pos
+ 10 * 2
10725 && f
->top_pos
== sf
->top_pos
+ 32 * 2))
10726 MoveWindowStructure (wp
, sf
->left_pos
+ 10, sf
->top_pos
+ 32);
10733 case kEventWindowHiding
:
10734 /* Before unmapping the window, update the WM_SIZE_HINTS
10735 property to claim that the current position of the window is
10736 user-specified, rather than program-specified, so that when
10737 the window is mapped again, it will be placed at the same
10738 location, without forcing the user to position it by hand
10739 again (they have already done that once for this window.) */
10740 x_wm_set_size_hint (f
, (long) 0, 1);
10744 case kEventWindowShown
:
10745 case kEventWindowHidden
:
10746 case kEventWindowCollapsed
:
10747 case kEventWindowExpanded
:
10748 mac_handle_visibility_change (f
);
10752 case kEventWindowBoundsChanging
:
10753 result
= CallNextEventHandler (next_handler
, event
);
10754 if (result
!= eventNotHandledErr
)
10757 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10758 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10762 size_hints
= FRAME_SIZE_HINTS (f
);
10763 if ((attributes
& kWindowBoundsChangeUserResize
)
10764 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
10765 == (PResizeInc
| PBaseSize
| PMinSize
)))
10770 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10771 typeQDRectangle
, NULL
, sizeof (Rect
),
10776 width
= bounds
.right
- bounds
.left
;
10777 height
= bounds
.bottom
- bounds
.top
;
10779 if (width
< size_hints
->min_width
)
10780 width
= size_hints
->min_width
;
10782 width
= size_hints
->base_width
10783 + (int) ((width
- size_hints
->base_width
)
10784 / (float) size_hints
->width_inc
+ .5)
10785 * size_hints
->width_inc
;
10787 if (height
< size_hints
->min_height
)
10788 height
= size_hints
->min_height
;
10790 height
= size_hints
->base_height
10791 + (int) ((height
- size_hints
->base_height
)
10792 / (float) size_hints
->height_inc
+ .5)
10793 * size_hints
->height_inc
;
10795 bounds
.right
= bounds
.left
+ width
;
10796 bounds
.bottom
= bounds
.top
+ height
;
10797 SetEventParameter (event
, kEventParamCurrentBounds
,
10798 typeQDRectangle
, sizeof (Rect
), &bounds
);
10803 case kEventWindowBoundsChanged
:
10804 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10805 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10809 if (attributes
& kWindowBoundsChangeSizeChanged
)
10813 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10814 typeQDRectangle
, NULL
, sizeof (Rect
),
10820 width
= bounds
.right
- bounds
.left
;
10821 height
= bounds
.bottom
- bounds
.top
;
10822 mac_handle_size_change (f
, width
, height
);
10823 mac_wakeup_from_rne ();
10827 if (attributes
& kWindowBoundsChangeOriginChanged
)
10828 mac_handle_origin_change (f
);
10833 /* -- window action events -- */
10835 case kEventWindowClose
:
10837 struct input_event buf
;
10840 buf
.kind
= DELETE_WINDOW_EVENT
;
10841 XSETFRAME (buf
.frame_or_window
, f
);
10843 kbd_buffer_store_event (&buf
);
10848 case kEventWindowGetIdealSize
:
10849 result
= CallNextEventHandler (next_handler
, event
);
10850 if (result
!= eventNotHandledErr
)
10854 Point ideal_size
= mac_get_ideal_size (f
);
10856 err
= SetEventParameter (event
, kEventParamDimensions
,
10857 typeQDPoint
, sizeof (Point
), &ideal_size
);
10864 case kEventWindowToolbarSwitchMode
:
10866 static const EventParamName names
[] = {kEventParamDirectObject
,
10867 kEventParamWindowMouseLocation
,
10868 kEventParamKeyModifiers
,
10869 kEventParamMouseButton
,
10870 kEventParamClickCount
,
10871 kEventParamMouseChord
};
10872 static const EventParamType types
[] = {typeWindowRef
,
10878 int num_params
= sizeof (names
) / sizeof (names
[0]);
10880 err
= mac_store_event_ref_as_apple_event (0, 0,
10882 Qtoolbar_switch_mode
,
10892 /* -- window focus events -- */
10894 case kEventWindowFocusAcquired
:
10895 err
= mac_tsm_resume ();
10900 case kEventWindowFocusRelinquish
:
10901 err
= mac_tsm_suspend ();
10914 static pascal OSStatus
10915 mac_handle_application_event (next_handler
, event
, data
)
10916 EventHandlerCallRef next_handler
;
10920 OSStatus err
, result
= eventNotHandledErr
;
10922 switch (GetEventKind (event
))
10925 case kEventAppActivated
:
10926 err
= mac_tsm_resume ();
10929 case kEventAppDeactivated
:
10930 err
= mac_tsm_suspend ();
10944 static pascal OSStatus
10945 mac_handle_keyboard_event (next_handler
, event
, data
)
10946 EventHandlerCallRef next_handler
;
10950 OSStatus err
, result
= eventNotHandledErr
;
10951 UInt32 event_kind
, key_code
, modifiers
;
10952 unsigned char char_code
;
10954 event_kind
= GetEventKind (event
);
10955 switch (event_kind
)
10957 case kEventRawKeyDown
:
10958 case kEventRawKeyRepeat
:
10959 case kEventRawKeyUp
:
10960 /* When using Carbon Events, we need to pass raw keyboard events
10961 to the TSM ourselves. If TSM handles it, it will pass back
10962 noErr, otherwise it will pass back "eventNotHandledErr" and
10963 we can process it normally. */
10964 result
= CallNextEventHandler (next_handler
, event
);
10965 if (result
!= eventNotHandledErr
)
10968 if (read_socket_inev
== NULL
)
10972 if (read_socket_inev
->kind
!= NO_EVENT
)
10979 if (event_kind
== kEventRawKeyUp
)
10982 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
10984 sizeof (char), NULL
, &char_code
);
10988 err
= GetEventParameter (event
, kEventParamKeyCode
,
10990 sizeof (UInt32
), NULL
, &key_code
);
10994 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
10996 sizeof (UInt32
), NULL
, &modifiers
);
11000 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11001 char_code
, key_code
, modifiers
,
11003 (GetEventTime (event
) / kEventDurationMillisecond
)),
11015 static pascal OSStatus
11016 mac_handle_command_event (next_handler
, event
, data
)
11017 EventHandlerCallRef next_handler
;
11021 OSStatus err
, result
= eventNotHandledErr
;
11023 static const EventParamName names
[] =
11024 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11025 static const EventParamType types
[] =
11026 {typeHICommand
, typeUInt32
};
11027 int num_params
= sizeof (names
) / sizeof (names
[0]);
11029 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11030 NULL
, sizeof (HICommand
), NULL
, &command
);
11032 return eventNotHandledErr
;
11034 switch (GetEventKind (event
))
11036 case kEventCommandProcess
:
11037 result
= CallNextEventHandler (next_handler
, event
);
11038 if (result
!= eventNotHandledErr
)
11041 err
= GetEventParameter (event
, kEventParamDirectObject
,
11042 typeHICommand
, NULL
,
11043 sizeof (HICommand
), NULL
, &command
);
11045 if (err
!= noErr
|| command
.commandID
== 0)
11048 /* A HI command event is mapped to an Apple event whose event
11049 class symbol is `hi-command' and event ID is its command
11051 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11066 static pascal OSStatus
11067 mac_handle_mouse_event (next_handler
, event
, data
)
11068 EventHandlerCallRef next_handler
;
11072 OSStatus err
, result
= eventNotHandledErr
;
11074 switch (GetEventKind (event
))
11076 case kEventMouseWheelMoved
:
11080 EventMouseWheelAxis axis
;
11084 result
= CallNextEventHandler (next_handler
, event
);
11085 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11088 f
= mac_focus_frame (&one_mac_display_info
);
11090 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11091 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11093 || wp
!= FRAME_MAC_WINDOW (f
))
11096 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11097 typeMouseWheelAxis
, NULL
,
11098 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11099 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11102 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11103 typeQDPoint
, NULL
, sizeof (Point
),
11108 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11109 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11110 if (point
.h
< 0 || point
.v
< 0
11111 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11112 f
->tool_bar_window
))
11115 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11116 typeSInt32
, NULL
, sizeof (SInt32
),
11121 read_socket_inev
->kind
= WHEEL_EVENT
;
11122 read_socket_inev
->code
= 0;
11123 read_socket_inev
->modifiers
=
11124 (mac_event_to_emacs_modifiers (event
)
11125 | ((delta
< 0) ? down_modifier
: up_modifier
));
11126 XSETINT (read_socket_inev
->x
, point
.h
);
11127 XSETINT (read_socket_inev
->y
, point
.v
);
11128 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11142 static pascal OSStatus
11143 mac_handle_text_input_event (next_handler
, event
, data
)
11144 EventHandlerCallRef next_handler
;
11148 OSStatus err
, result
;
11149 Lisp_Object id_key
= Qnil
;
11151 const EventParamName
*names
;
11152 const EventParamType
*types
;
11153 static UInt32 seqno_uaia
= 0;
11154 static const EventParamName names_uaia
[] =
11155 {kEventParamTextInputSendComponentInstance
,
11156 kEventParamTextInputSendRefCon
,
11157 kEventParamTextInputSendSLRec
,
11158 kEventParamTextInputSendFixLen
,
11159 kEventParamTextInputSendText
,
11160 kEventParamTextInputSendUpdateRng
,
11161 kEventParamTextInputSendHiliteRng
,
11162 kEventParamTextInputSendClauseRng
,
11163 kEventParamTextInputSendPinRng
,
11164 kEventParamTextInputSendTextServiceEncoding
,
11165 kEventParamTextInputSendTextServiceMacEncoding
,
11166 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11167 static const EventParamType types_uaia
[] =
11168 {typeComponentInstance
,
11170 typeIntlWritingCode
,
11177 typeTextRangeArray
,
11178 typeTextRangeArray
,
11184 static const EventParamName names_ufke
[] =
11185 {kEventParamTextInputSendComponentInstance
,
11186 kEventParamTextInputSendRefCon
,
11187 kEventParamTextInputSendSLRec
,
11188 kEventParamTextInputSendText
};
11189 static const EventParamType types_ufke
[] =
11190 {typeComponentInstance
,
11192 typeIntlWritingCode
,
11195 result
= CallNextEventHandler (next_handler
, event
);
11196 if (result
!= eventNotHandledErr
)
11199 switch (GetEventKind (event
))
11201 case kEventTextInputUpdateActiveInputArea
:
11202 id_key
= Qupdate_active_input_area
;
11203 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11204 names
= names_uaia
;
11205 types
= types_uaia
;
11206 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11207 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11212 case kEventTextInputUnicodeForKeyEvent
:
11214 EventRef kbd_event
;
11215 UInt32 actual_size
, modifiers
;
11217 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11218 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11221 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11223 sizeof (UInt32
), NULL
, &modifiers
);
11224 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11225 /* There're mapped modifier keys. Process it in
11229 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11230 typeUnicodeText
, NULL
, 0, &actual_size
,
11232 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11236 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11237 typeUnicodeText
, NULL
,
11238 sizeof (UniChar
), NULL
, &code
);
11239 if (err
== noErr
&& code
< 0x80)
11241 /* ASCII character. Process it in do_keystroke. */
11242 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11246 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11247 typeUInt32
, NULL
, sizeof (UInt32
),
11249 if (!(err
== noErr
&& key_code
<= 0x7f
11250 && keycode_to_xkeysym_table
[key_code
]))
11253 mac_focus_frame (&one_mac_display_info
);
11255 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11256 read_socket_inev
->code
= code
;
11257 read_socket_inev
->modifiers
=
11258 mac_to_emacs_modifiers (modifiers
);
11259 read_socket_inev
->modifiers
|=
11260 (extra_keyboard_modifiers
11261 & (meta_modifier
| alt_modifier
11262 | hyper_modifier
| super_modifier
));
11263 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11271 /* Non-ASCII keystrokes without mapped modifiers are
11272 processed at the Lisp level. */
11273 id_key
= Qunicode_for_key_event
;
11274 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11275 names
= names_ufke
;
11276 types
= types_ufke
;
11282 case kEventTextInputOffsetToPos
:
11288 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11291 /* Strictly speaking, this is not always correct because
11292 previous events may change some states about display. */
11293 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11295 /* Active input area is displayed around the current point. */
11296 f
= SELECTED_FRAME ();
11297 w
= XWINDOW (f
->selected_window
);
11299 else if (WINDOWP (echo_area_window
))
11301 /* Active input area is displayed in the echo area. */
11302 w
= XWINDOW (echo_area_window
);
11303 f
= WINDOW_XFRAME (w
);
11308 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11309 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11310 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11311 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11312 + FONT_BASE (FRAME_FONT (f
))
11313 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11314 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11315 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11325 if (!NILP (id_key
))
11326 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11332 #endif /* TARGET_API_MAC_CARBON */
11336 install_window_handler (window
)
11339 OSStatus err
= noErr
;
11341 #if TARGET_API_MAC_CARBON
11344 static const EventTypeSpec specs
[] =
11346 /* -- window refresh events -- */
11347 {kEventClassWindow
, kEventWindowUpdate
},
11348 /* -- window state change events -- */
11349 {kEventClassWindow
, kEventWindowShowing
},
11350 {kEventClassWindow
, kEventWindowHiding
},
11351 {kEventClassWindow
, kEventWindowShown
},
11352 {kEventClassWindow
, kEventWindowHidden
},
11353 {kEventClassWindow
, kEventWindowCollapsed
},
11354 {kEventClassWindow
, kEventWindowExpanded
},
11355 {kEventClassWindow
, kEventWindowBoundsChanging
},
11356 {kEventClassWindow
, kEventWindowBoundsChanged
},
11357 /* -- window action events -- */
11358 {kEventClassWindow
, kEventWindowClose
},
11359 {kEventClassWindow
, kEventWindowGetIdealSize
},
11361 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11364 /* -- window focus events -- */
11365 {kEventClassWindow
, kEventWindowFocusAcquired
},
11366 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11369 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11371 if (handle_window_eventUPP
== NULL
)
11372 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11374 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11375 GetEventTypeCount (specs
),
11376 specs
, NULL
, NULL
);
11381 err
= install_drag_handler (window
);
11387 remove_window_handler (window
)
11390 remove_drag_handler (window
);
11393 #if TARGET_API_MAC_CARBON
11395 install_application_handler ()
11397 OSStatus err
= noErr
;
11401 static const EventTypeSpec specs
[] = {
11403 {kEventClassApplication
, kEventAppActivated
},
11404 {kEventClassApplication
, kEventAppDeactivated
},
11408 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11409 (mac_handle_application_event
),
11410 GetEventTypeCount (specs
),
11411 specs
, NULL
, NULL
);
11416 static const EventTypeSpec specs
[] =
11417 {{kEventClassKeyboard
, kEventRawKeyDown
},
11418 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11419 {kEventClassKeyboard
, kEventRawKeyUp
}};
11421 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11422 (mac_handle_keyboard_event
),
11423 GetEventTypeCount (specs
),
11424 specs
, NULL
, NULL
);
11429 static const EventTypeSpec specs
[] =
11430 {{kEventClassCommand
, kEventCommandProcess
}};
11432 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11433 (mac_handle_command_event
),
11434 GetEventTypeCount (specs
),
11435 specs
, NULL
, NULL
);
11440 static const EventTypeSpec specs
[] =
11441 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11443 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11444 (mac_handle_mouse_event
),
11445 GetEventTypeCount (specs
),
11446 specs
, NULL
, NULL
);
11452 static const EventTypeSpec spec
[] =
11453 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11454 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11455 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11457 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11458 (mac_handle_text_input_event
),
11459 GetEventTypeCount (spec
),
11465 err
= install_menu_target_item_handler ();
11469 err
= install_service_handler ();
11477 mac_handle_dm_notification (event
)
11480 mac_screen_config_changed
= 1;
11483 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11485 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11486 CGDirectDisplayID display
;
11487 CGDisplayChangeSummaryFlags flags
;
11490 mac_screen_config_changed
= 1;
11495 init_dm_notification_handler ()
11499 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11500 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11501 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11504 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11507 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11508 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11510 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11511 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11513 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11514 ProcessSerialNumber psn
;
11516 if (handle_dm_notificationUPP
== NULL
)
11517 handle_dm_notificationUPP
=
11518 NewDMNotificationUPP (mac_handle_dm_notification
);
11520 err
= GetCurrentProcess (&psn
);
11522 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11530 mac_get_screen_info (dpyinfo
)
11531 struct mac_display_info
*dpyinfo
;
11534 /* HasDepth returns true if it is possible to have a 32 bit display,
11535 but this may not be what is actually used. Mac OSX can do better. */
11536 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11537 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11540 CGDisplayCount ndisps
;
11541 CGDirectDisplayID
*displays
;
11543 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11546 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11547 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11551 CGRect bounds
= CGRectZero
;
11553 while (ndisps
-- > 0)
11554 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11555 dpyinfo
->height
= CGRectGetHeight (bounds
);
11556 dpyinfo
->width
= CGRectGetWidth (bounds
);
11560 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11561 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11564 #else /* !MAC_OSX */
11566 GDHandle gdh
= GetMainDevice ();
11567 Rect rect
= (**gdh
).gdRect
;
11569 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11570 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11571 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11574 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11575 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11576 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11578 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11579 dpyinfo
->width
= rect
.right
- rect
.left
;
11581 #endif /* !MAC_OSX */
11587 profiler_exit_proc ()
11589 ProfilerDump ("\pEmacs.prof");
11594 /* These few functions implement Emacs as a normal Mac application
11595 (almost): set up the heap and the Toolbox, handle necessary system
11596 events plus a few simple menu events. They also set up Emacs's
11597 access to functions defined in the rest of this file. Emacs uses
11598 function hooks to perform all its terminal I/O. A complete list of
11599 these functions appear in termhooks.h. For what they do, read the
11600 comments there and see also w32term.c and xterm.c. What's
11601 noticeably missing here is the event loop, which is normally
11602 present in most Mac application. After performing the necessary
11603 Mac initializations, main passes off control to emacs_main
11604 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11605 (defined further below) to read input. This is where
11606 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11613 #if __profile__ /* is the profiler on? */
11614 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11619 /* set creator and type for files created by MSL */
11620 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11624 do_init_managers ();
11628 #ifndef USE_LSB_TAG
11629 do_check_ram_size ();
11632 init_emacs_passwd_dir ();
11636 init_coercion_handler ();
11638 initialize_applescript ();
11640 init_apple_event_handler ();
11642 init_dm_notification_handler ();
11648 /* set up argv array from STR# resource */
11649 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
11653 /* free up AppleScript resources on exit */
11654 atexit (terminate_applescript
);
11656 #if __profile__ /* is the profiler on? */
11657 atexit (profiler_exit_proc
);
11660 /* 3rd param "envp" never used in emacs_main */
11661 (void) emacs_main (argc
, argv
, 0);
11664 /* Never reached - real exit in Fkill_emacs */
11669 #if !TARGET_API_MAC_CARBON
11670 static RgnHandle mouse_region
= NULL
;
11673 mac_wait_next_event (er
, sleep_time
, dequeue
)
11678 static EventRecord er_buf
= {nullEvent
};
11679 UInt32 target_tick
, current_tick
;
11680 EventMask event_mask
;
11682 if (mouse_region
== NULL
)
11683 mouse_region
= NewRgn ();
11685 event_mask
= everyEvent
;
11686 if (!mac_ready_for_apple_events
)
11687 event_mask
-= highLevelEventMask
;
11689 current_tick
= TickCount ();
11690 target_tick
= current_tick
+ sleep_time
;
11692 if (er_buf
.what
== nullEvent
)
11693 while (!WaitNextEvent (event_mask
, &er_buf
,
11694 target_tick
- current_tick
, mouse_region
))
11696 current_tick
= TickCount ();
11697 if (target_tick
<= current_tick
)
11703 er_buf
.what
= nullEvent
;
11706 #endif /* not TARGET_API_MAC_CARBON */
11708 #if TARGET_API_MAC_CARBON
11710 mac_post_mouse_moved_event ()
11712 EventRef event
= NULL
;
11715 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
11716 kEventAttributeNone
, &event
);
11721 GetGlobalMouse (&mouse_pos
);
11722 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
11723 sizeof (Point
), &mouse_pos
);
11727 UInt32 modifiers
= GetCurrentKeyModifiers ();
11729 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
11730 sizeof (UInt32
), &modifiers
);
11733 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
11734 kEventPriorityStandard
);
11736 ReleaseEvent (event
);
11742 /* Emacs calls this whenever it wants to read an input event from the
11745 XTread_socket (sd
, expected
, hold_quit
)
11747 struct input_event
*hold_quit
;
11749 struct input_event inev
;
11751 #if TARGET_API_MAC_CARBON
11753 EventTargetRef toolbox_dispatcher
;
11756 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11758 if (interrupt_input_blocked
)
11760 interrupt_input_pending
= 1;
11764 interrupt_input_pending
= 0;
11767 /* So people can tell when we have read the available input. */
11768 input_signal_count
++;
11772 #if TARGET_API_MAC_CARBON
11773 toolbox_dispatcher
= GetEventDispatcherTarget ();
11777 mac_prepare_for_quickdraw (NULL
),
11779 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
11780 kEventRemoveFromQueue
, &eventRef
))
11781 #else /* !TARGET_API_MAC_CARBON */
11782 while (mac_wait_next_event (&er
, 0, true))
11783 #endif /* !TARGET_API_MAC_CARBON */
11787 unsigned long timestamp
;
11790 inev
.kind
= NO_EVENT
;
11793 #if TARGET_API_MAC_CARBON
11794 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
11796 if (!mac_convert_event_ref (eventRef
, &er
))
11798 #else /* !TARGET_API_MAC_CARBON */
11799 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
11800 #endif /* !TARGET_API_MAC_CARBON */
11807 WindowRef window_ptr
;
11808 ControlPartCode part_code
;
11809 int tool_bar_p
= 0;
11811 #if TARGET_API_MAC_CARBON
11814 /* This is needed to send mouse events like aqua window
11815 buttons to the correct handler. */
11816 read_socket_inev
= &inev
;
11817 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11818 read_socket_inev
= NULL
;
11819 if (err
!= eventNotHandledErr
)
11822 last_mouse_glyph_frame
= 0;
11824 if (dpyinfo
->grabbed
&& last_mouse_frame
11825 && FRAME_LIVE_P (last_mouse_frame
))
11827 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
11828 part_code
= inContent
;
11832 part_code
= FindWindow (er
.where
, &window_ptr
);
11833 if (tip_window
&& window_ptr
== tip_window
)
11835 HideWindow (tip_window
);
11836 part_code
= FindWindow (er
.where
, &window_ptr
);
11840 if (er
.what
!= mouseDown
&&
11841 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
11847 f
= mac_focus_frame (dpyinfo
);
11848 saved_menu_event_location
= er
.where
;
11849 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
11850 XSETFRAME (inev
.frame_or_window
, f
);
11855 #if TARGET_API_MAC_CARBON
11856 FrontNonFloatingWindow ()
11861 || (mac_window_to_frame (window_ptr
)
11862 != dpyinfo
->x_focus_frame
))
11863 SelectWindow (window_ptr
);
11866 ControlPartCode control_part_code
;
11870 ControlKind control_kind
;
11873 f
= mac_window_to_frame (window_ptr
);
11874 /* convert to local coordinates of new window */
11875 mouse_loc
.h
= (er
.where
.h
11877 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
11878 mouse_loc
.v
= (er
.where
.v
11880 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
11881 #if TARGET_API_MAC_CARBON
11882 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
11883 &control_part_code
);
11886 GetControlKind (ch
, &control_kind
);
11889 control_part_code
= FindControl (mouse_loc
, window_ptr
,
11893 #if TARGET_API_MAC_CARBON
11894 inev
.code
= mac_get_mouse_btn (eventRef
);
11895 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
11897 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
11898 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
11900 XSETINT (inev
.x
, mouse_loc
.h
);
11901 XSETINT (inev
.y
, mouse_loc
.v
);
11903 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
11905 #ifndef USE_TOOLKIT_SCROLL_BARS
11906 /* control_part_code becomes kControlNoPart if
11907 a progress indicator is clicked. */
11908 && control_part_code
!= kControlNoPart
11909 #else /* USE_TOOLKIT_SCROLL_BARS */
11911 && control_kind
.kind
== kControlKindScrollBar
11912 #endif /* MAC_OSX */
11913 #endif /* USE_TOOLKIT_SCROLL_BARS */
11916 struct scroll_bar
*bar
;
11918 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11920 bar
= tracked_scroll_bar
;
11921 #ifndef USE_TOOLKIT_SCROLL_BARS
11922 control_part_code
= kControlIndicatorPart
;
11926 bar
= (struct scroll_bar
*) GetControlReference (ch
);
11927 #ifdef USE_TOOLKIT_SCROLL_BARS
11928 /* Make the "Ctrl-Mouse-2 splits window" work
11929 for toolkit scroll bars. */
11930 if (inev
.modifiers
& ctrl_modifier
)
11931 x_scroll_bar_handle_click (bar
, control_part_code
,
11933 else if (er
.what
== mouseDown
)
11934 x_scroll_bar_handle_press (bar
, control_part_code
,
11937 x_scroll_bar_handle_release (bar
, &inev
);
11938 #else /* not USE_TOOLKIT_SCROLL_BARS */
11939 x_scroll_bar_handle_click (bar
, control_part_code
,
11941 if (er
.what
== mouseDown
11942 && control_part_code
== kControlIndicatorPart
)
11943 tracked_scroll_bar
= bar
;
11945 tracked_scroll_bar
= NULL
;
11946 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11950 Lisp_Object window
;
11951 int x
= mouse_loc
.h
;
11952 int y
= mouse_loc
.v
;
11954 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
11955 if (EQ (window
, f
->tool_bar_window
))
11957 if (er
.what
== mouseDown
)
11958 handle_tool_bar_click (f
, x
, y
, 1, 0);
11960 handle_tool_bar_click (f
, x
, y
, 0,
11966 XSETFRAME (inev
.frame_or_window
, f
);
11967 inev
.kind
= MOUSE_CLICK_EVENT
;
11971 if (er
.what
== mouseDown
)
11973 dpyinfo
->grabbed
|= (1 << inev
.code
);
11974 last_mouse_frame
= f
;
11977 last_tool_bar_item
= -1;
11981 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
11982 /* If a button is released though it was not
11983 previously pressed, that would be because
11984 of multi-button emulation. */
11985 dpyinfo
->grabbed
= 0;
11987 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
11990 /* Ignore any mouse motion that happened before
11991 this event; any subsequent mouse-movement Emacs
11992 events should reflect only motion after the
11995 f
->mouse_moved
= 0;
11997 #ifdef USE_TOOLKIT_SCROLL_BARS
11998 if (inev
.kind
== MOUSE_CLICK_EVENT
11999 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12000 && (inev
.modifiers
& ctrl_modifier
)))
12005 inev
.modifiers
|= down_modifier
;
12008 inev
.modifiers
|= up_modifier
;
12015 #if TARGET_API_MAC_CARBON
12017 if (IsWindowPathSelectClick (window_ptr
, &er
))
12019 WindowPathSelect (window_ptr
, NULL
, NULL
);
12022 if (part_code
== inProxyIcon
12023 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12024 != errUserWantsToDragWindow
))
12026 DragWindow (window_ptr
, er
.where
, NULL
);
12027 #else /* not TARGET_API_MAC_CARBON */
12028 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12029 /* Update the frame parameters. */
12031 struct frame
*f
= mac_window_to_frame (window_ptr
);
12033 if (f
&& !f
->async_iconified
)
12034 mac_handle_origin_change (f
);
12036 #endif /* not TARGET_API_MAC_CARBON */
12040 if (TrackGoAway (window_ptr
, er
.where
))
12042 inev
.kind
= DELETE_WINDOW_EVENT
;
12043 XSETFRAME (inev
.frame_or_window
,
12044 mac_window_to_frame (window_ptr
));
12048 /* window resize handling added --ben */
12050 do_grow_window (window_ptr
, &er
);
12053 /* window zoom handling added --ben */
12056 if (TrackBox (window_ptr
, er
.where
, part_code
))
12057 do_zoom_window (window_ptr
, part_code
);
12060 #if USE_MAC_TOOLBAR
12066 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12068 /* This doesn't work on Mac OS X 10.2. */
12070 HIViewClick (ch
, eventRef
);
12073 #endif /* USE_MAC_TOOLBAR */
12081 #if !TARGET_API_MAC_CARBON
12083 do_window_update ((WindowRef
) er
.message
);
12088 switch ((er
.message
>> 24) & 0x000000FF)
12090 case mouseMovedMessage
:
12091 #if !TARGET_API_MAC_CARBON
12092 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12093 er
.where
.h
+ 1, er
.where
.v
+ 1);
12095 previous_help_echo_string
= help_echo_string
;
12096 help_echo_string
= Qnil
;
12098 if (dpyinfo
->grabbed
&& last_mouse_frame
12099 && FRAME_LIVE_P (last_mouse_frame
))
12100 f
= last_mouse_frame
;
12102 f
= dpyinfo
->x_focus_frame
;
12104 if (dpyinfo
->mouse_face_hidden
)
12106 dpyinfo
->mouse_face_hidden
= 0;
12107 clear_mouse_face (dpyinfo
);
12112 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12115 mouse_pos
.h
= (er
.where
.h
12117 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12118 mouse_pos
.v
= (er
.where
.v
12120 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12121 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12122 #ifdef USE_TOOLKIT_SCROLL_BARS
12123 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12125 #else /* not USE_TOOLKIT_SCROLL_BARS */
12126 x_scroll_bar_note_movement (tracked_scroll_bar
,
12128 - XINT (tracked_scroll_bar
->top
),
12129 er
.when
* (1000 / 60));
12130 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12133 /* Generate SELECT_WINDOW_EVENTs when needed. */
12134 if (!NILP (Vmouse_autoselect_window
))
12136 Lisp_Object window
;
12138 window
= window_from_coordinates (f
,
12143 /* Window will be selected only when it is
12144 not selected now and last mouse movement
12145 event was not in it. Minibuffer window
12146 will be selected only when it is active. */
12147 if (WINDOWP (window
)
12148 && !EQ (window
, last_window
)
12149 && !EQ (window
, selected_window
))
12151 inev
.kind
= SELECT_WINDOW_EVENT
;
12152 inev
.frame_or_window
= window
;
12155 last_window
=window
;
12157 if (!note_mouse_movement (f
, &mouse_pos
))
12158 help_echo_string
= previous_help_echo_string
;
12159 #if USE_MAC_TOOLBAR
12161 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12166 /* If the contents of the global variable
12167 help_echo_string has changed, generate a
12169 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12180 WindowRef window_ptr
= (WindowRef
) er
.message
;
12182 ControlRef root_control
;
12184 if (window_ptr
== tip_window
)
12186 HideWindow (tip_window
);
12190 if (!is_emacs_window (window_ptr
))
12193 f
= mac_window_to_frame (window_ptr
);
12195 if ((er
.modifiers
& activeFlag
) != 0)
12197 /* A window has been activated */
12200 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12202 ActivateControl (root_control
);
12204 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12206 mouse_loc
.h
= (er
.where
.h
12208 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12209 mouse_loc
.v
= (er
.where
.v
12211 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12212 /* Window-activated event counts as mouse movement,
12213 so update things that depend on mouse position. */
12214 note_mouse_movement (f
, &mouse_loc
);
12218 /* A window has been deactivated */
12219 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12221 DeactivateControl (root_control
);
12223 #ifdef USE_TOOLKIT_SCROLL_BARS
12224 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12226 struct input_event event
;
12228 EVENT_INIT (event
);
12229 event
.kind
= NO_EVENT
;
12230 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12231 if (event
.kind
!= NO_EVENT
)
12233 event
.timestamp
= timestamp
;
12234 kbd_buffer_store_event_hold (&event
, hold_quit
);
12239 dpyinfo
->grabbed
= 0;
12241 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12243 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12245 /* If we move outside the frame, then we're
12246 certainly no longer on any text in the
12248 clear_mouse_face (dpyinfo
);
12249 dpyinfo
->mouse_face_mouse_frame
= 0;
12252 /* Generate a nil HELP_EVENT to cancel a help-echo.
12253 Do it only if there's something to cancel.
12254 Otherwise, the startup message is cleared when the
12255 mouse leaves the frame. */
12256 if (any_help_event_p
)
12267 f
= mac_focus_frame (dpyinfo
);
12268 XSETFRAME (inev
.frame_or_window
, f
);
12270 /* If mouse-highlight is an integer, input clears out mouse
12272 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12273 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12275 clear_mouse_face (dpyinfo
);
12276 dpyinfo
->mouse_face_hidden
= 1;
12280 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
12283 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
12285 sizeof (UInt32
), NULL
, &modifiers
);
12287 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
12289 #if TARGET_API_MAC_CARBON
12290 if (!(mapped_modifiers
12291 & ~(mac_pass_command_to_system
? cmdKey
: 0)
12292 & ~(mac_pass_control_to_system
? controlKey
: 0)))
12296 if (er
.what
!= keyUp
)
12297 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12298 (er
.message
& keyCodeMask
) >> 8,
12299 modifiers
, timestamp
, &inev
);
12303 case kHighLevelEvent
:
12304 AEProcessAppleEvent (&er
);
12309 #if TARGET_API_MAC_CARBON
12313 read_socket_inev
= &inev
;
12314 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12315 read_socket_inev
= NULL
;
12320 #if TARGET_API_MAC_CARBON
12321 ReleaseEvent (eventRef
);
12324 if (inev
.kind
!= NO_EVENT
)
12326 inev
.timestamp
= timestamp
;
12327 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12332 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12337 XSETFRAME (frame
, f
);
12343 any_help_event_p
= 1;
12344 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12345 help_echo_object
, help_echo_pos
);
12349 help_echo_string
= Qnil
;
12350 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12356 /* If the focus was just given to an autoraising frame,
12358 /* ??? This ought to be able to handle more than one such frame. */
12359 if (pending_autoraise_frame
)
12361 x_raise_frame (pending_autoraise_frame
);
12362 pending_autoraise_frame
= 0;
12365 if (mac_screen_config_changed
)
12367 mac_get_screen_info (dpyinfo
);
12368 mac_screen_config_changed
= 0;
12371 #if !TARGET_API_MAC_CARBON
12372 /* Check which frames are still visible. We do this here because
12373 there doesn't seem to be any direct notification from the Window
12374 Manager that the visibility of a window has changed (at least,
12375 not in all cases). */
12377 Lisp_Object tail
, frame
;
12379 FOR_EACH_FRAME (tail
, frame
)
12381 struct frame
*f
= XFRAME (frame
);
12383 /* The tooltip has been drawn already. Avoid the
12384 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12385 if (EQ (frame
, tip_frame
))
12388 if (FRAME_MAC_P (f
))
12389 mac_handle_visibility_change (f
);
12400 /* Need to override CodeWarrior's input function so no conversion is
12401 done on newlines Otherwise compiled functions in .elc files will be
12402 read incorrectly. Defined in ...:MSL C:MSL
12403 Common:Source:buffer_io.c. */
12406 __convert_to_newlines (unsigned char * p
, size_t * n
)
12408 #pragma unused(p,n)
12412 __convert_from_newlines (unsigned char * p
, size_t * n
)
12414 #pragma unused(p,n)
12420 make_mac_terminal_frame (struct frame
*f
)
12425 XSETFRAME (frame
, f
);
12427 f
->output_method
= output_mac
;
12428 f
->output_data
.mac
= (struct mac_output
*)
12429 xmalloc (sizeof (struct mac_output
));
12430 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12432 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12434 FRAME_COLS (f
) = 96;
12435 FRAME_LINES (f
) = 4;
12437 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12438 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12440 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12442 f
->output_data
.mac
->cursor_pixel
= 0;
12443 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12444 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12445 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12447 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12448 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12449 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12450 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12451 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12452 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12454 FRAME_FONTSET (f
) = -1;
12455 f
->output_data
.mac
->explicit_parent
= 0;
12458 f
->border_width
= 0;
12460 f
->internal_border_width
= 0;
12465 f
->new_text_cols
= 0;
12466 f
->new_text_lines
= 0;
12468 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12469 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12470 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12474 if (!(FRAME_MAC_WINDOW (f
) =
12475 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12476 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12478 /* so that update events can find this mac_output struct */
12479 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12485 /* Need to be initialized for unshow_buffer in window.c. */
12486 selected_window
= f
->selected_window
;
12488 Fmodify_frame_parameters (frame
,
12489 Fcons (Fcons (Qfont
,
12490 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12491 Fmodify_frame_parameters (frame
,
12492 Fcons (Fcons (Qforeground_color
,
12493 build_string ("black")), Qnil
));
12494 Fmodify_frame_parameters (frame
,
12495 Fcons (Fcons (Qbackground_color
,
12496 build_string ("white")), Qnil
));
12501 /***********************************************************************
12503 ***********************************************************************/
12505 static int mac_initialized
= 0;
12508 mac_make_rdb (xrm_option
)
12509 const char *xrm_option
;
12511 XrmDatabase database
;
12513 database
= xrm_get_preference_database (NULL
);
12515 xrm_merge_string_database (database
, xrm_option
);
12520 struct mac_display_info
*
12521 mac_term_init (display_name
, xrm_option
, resource_name
)
12522 Lisp_Object display_name
;
12524 char *resource_name
;
12526 struct mac_display_info
*dpyinfo
;
12530 if (!mac_initialized
)
12533 mac_initialized
= 1;
12536 if (x_display_list
)
12537 error ("Sorry, this version can only handle one display");
12539 dpyinfo
= &one_mac_display_info
;
12540 bzero (dpyinfo
, sizeof (*dpyinfo
));
12543 dpyinfo
->mac_id_name
12544 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12545 + SCHARS (Vsystem_name
)
12547 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12548 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12550 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12551 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12554 dpyinfo
->reference_count
= 0;
12555 dpyinfo
->resx
= 72.0;
12556 dpyinfo
->resy
= 72.0;
12558 mac_get_screen_info (dpyinfo
);
12560 dpyinfo
->grabbed
= 0;
12561 dpyinfo
->root_window
= NULL
;
12562 dpyinfo
->image_cache
= make_image_cache ();
12564 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12565 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12566 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12567 dpyinfo
->mouse_face_window
= Qnil
;
12568 dpyinfo
->mouse_face_overlay
= Qnil
;
12569 dpyinfo
->mouse_face_hidden
= 0;
12571 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12573 /* Put this display on the chain. */
12574 dpyinfo
->next
= x_display_list
;
12575 x_display_list
= dpyinfo
;
12577 /* Put it on x_display_name_list. */
12578 x_display_name_list
= Fcons (Fcons (display_name
,
12579 Fcons (Qnil
, dpyinfo
->xrdb
)),
12580 x_display_name_list
);
12581 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12588 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12591 x_delete_display (dpyinfo
)
12592 struct mac_display_info
*dpyinfo
;
12596 /* Discard this display from x_display_name_list and x_display_list.
12597 We can't use Fdelq because that can quit. */
12598 if (! NILP (x_display_name_list
)
12599 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12600 x_display_name_list
= XCDR (x_display_name_list
);
12605 tail
= x_display_name_list
;
12606 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12608 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
12610 XSETCDR (tail
, XCDR (XCDR (tail
)));
12613 tail
= XCDR (tail
);
12617 if (x_display_list
== dpyinfo
)
12618 x_display_list
= dpyinfo
->next
;
12621 struct x_display_info
*tail
;
12623 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12624 if (tail
->next
== dpyinfo
)
12625 tail
->next
= tail
->next
->next
;
12628 /* Free the font names in the font table. */
12629 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12630 if (dpyinfo
->font_table
[i
].name
)
12632 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
12633 xfree (dpyinfo
->font_table
[i
].full_name
);
12634 xfree (dpyinfo
->font_table
[i
].name
);
12637 if (dpyinfo
->font_table
)
12639 if (dpyinfo
->font_table
->font_encoder
)
12640 xfree (dpyinfo
->font_table
->font_encoder
);
12641 xfree (dpyinfo
->font_table
);
12643 if (dpyinfo
->mac_id_name
)
12644 xfree (dpyinfo
->mac_id_name
);
12646 if (x_display_list
== 0)
12648 mac_clear_font_name_table ();
12649 bzero (dpyinfo
, sizeof (*dpyinfo
));
12660 MenuItemIndex menu_index
;
12662 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
12663 &menu
, &menu_index
);
12665 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12666 EnableMenuCommand (NULL
, kHICommandPreferences
);
12667 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
12668 &menu
, &menu_index
);
12671 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12672 InsertMenuItemTextWithCFString (menu
, NULL
,
12673 0, kMenuItemAttrSeparator
, 0);
12674 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
12675 0, 0, kHICommandAbout
);
12677 #else /* !MAC_OSX */
12678 #if TARGET_API_MAC_CARBON
12679 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
12689 static InterfaceTypeList types
= {kUnicodeDocument
};
12691 static InterfaceTypeList types
= {kTextService
};
12694 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
12695 &tsm_document_id
, 0);
12699 /* Set up use of X before we make the first connection. */
12701 extern frame_parm_handler mac_frame_parm_handlers
[];
12703 static struct redisplay_interface x_redisplay_interface
=
12705 mac_frame_parm_handlers
,
12709 x_clear_end_of_line
,
12711 x_after_update_window_line
,
12712 x_update_window_begin
,
12713 x_update_window_end
,
12717 mac_flush_display_optional
,
12719 0, /* flush_display_optional */
12721 x_clear_window_mouse_face
,
12722 x_get_glyph_overhangs
,
12723 x_fix_overlapping_area
,
12724 x_draw_fringe_bitmap
,
12726 mac_define_fringe_bitmap
,
12727 mac_destroy_fringe_bitmap
,
12729 0, /* define_fringe_bitmap */
12730 0, /* destroy_fringe_bitmap */
12732 mac_per_char_metric
,
12734 mac_compute_glyph_string_overhangs
,
12735 x_draw_glyph_string
,
12736 mac_define_frame_cursor
,
12737 mac_clear_frame_area
,
12738 mac_draw_window_cursor
,
12739 mac_draw_vertical_window_border
,
12740 mac_shift_glyphs_for_insert
12746 rif
= &x_redisplay_interface
;
12748 clear_frame_hook
= x_clear_frame
;
12749 ins_del_lines_hook
= x_ins_del_lines
;
12750 delete_glyphs_hook
= x_delete_glyphs
;
12751 ring_bell_hook
= XTring_bell
;
12752 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12753 set_terminal_modes_hook
= XTset_terminal_modes
;
12754 update_begin_hook
= x_update_begin
;
12755 update_end_hook
= x_update_end
;
12756 set_terminal_window_hook
= XTset_terminal_window
;
12757 read_socket_hook
= XTread_socket
;
12758 frame_up_to_date_hook
= XTframe_up_to_date
;
12759 mouse_position_hook
= XTmouse_position
;
12760 frame_rehighlight_hook
= XTframe_rehighlight
;
12761 frame_raise_lower_hook
= XTframe_raise_lower
;
12763 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12764 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12765 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12766 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12768 scroll_region_ok
= 1; /* we'll scroll partial frames */
12769 char_ins_del_ok
= 1;
12770 line_ins_del_ok
= 1; /* we'll just blt 'em */
12771 fast_clear_end_of_line
= 1; /* X does this well */
12772 memory_below_frame
= 0; /* we don't remember what scrolls
12776 last_tool_bar_item
= -1;
12777 any_help_event_p
= 0;
12779 /* Try to use interrupt input; if we can't, then start polling. */
12780 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
12784 #if TARGET_API_MAC_CARBON
12786 install_application_handler ();
12795 init_coercion_handler ();
12797 init_apple_event_handler ();
12799 init_dm_notification_handler ();
12801 if (!inhibit_window_system
)
12803 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
12805 SetFrontProcess (&psn
);
12813 mac_init_fringe ();
12824 staticpro (&x_error_message_string
);
12825 x_error_message_string
= Qnil
;
12828 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
12829 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
12830 Qalt
= intern ("alt"); staticpro (&Qalt
);
12831 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
12832 Qsuper
= intern ("super"); staticpro (&Qsuper
);
12833 Qmodifier_value
= intern ("modifier-value");
12834 staticpro (&Qmodifier_value
);
12836 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
12837 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12838 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12839 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12840 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12842 #if TARGET_API_MAC_CARBON
12843 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
12845 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
12846 staticpro (&Qtoolbar_switch_mode
);
12847 #if USE_MAC_FONT_PANEL
12848 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12849 Qselection
= intern ("selection"); staticpro (&Qselection
);
12852 Qservice
= intern ("service"); staticpro (&Qservice
);
12853 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12854 Qperform
= intern ("perform"); staticpro (&Qperform
);
12857 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12858 Qupdate_active_input_area
= intern ("update-active-input-area");
12859 staticpro (&Qupdate_active_input_area
);
12860 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12861 staticpro (&Qunicode_for_key_event
);
12866 Fprovide (intern ("mac-carbon"), Qnil
);
12869 staticpro (&Qreverse
);
12870 Qreverse
= intern ("reverse");
12872 staticpro (&x_display_name_list
);
12873 x_display_name_list
= Qnil
;
12875 staticpro (&last_mouse_scroll_bar
);
12876 last_mouse_scroll_bar
= Qnil
;
12878 staticpro (&fm_font_family_alist
);
12879 fm_font_family_alist
= Qnil
;
12882 staticpro (&atsu_font_id_hash
);
12883 atsu_font_id_hash
= Qnil
;
12885 staticpro (&fm_style_face_attributes_alist
);
12886 fm_style_face_attributes_alist
= Qnil
;
12890 staticpro (&saved_ts_script_language_on_focus
);
12891 saved_ts_script_language_on_focus
= Qnil
;
12894 /* We don't yet support this, but defining this here avoids whining
12895 from cus-start.el and other places, like "M-x set-variable". */
12896 DEFVAR_BOOL ("x-use-underline-position-properties",
12897 &x_use_underline_position_properties
,
12898 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12899 A value of nil means ignore them. If you encounter fonts with bogus
12900 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12901 to 4.1, set this to nil.
12903 NOTE: Not supported on Mac yet. */);
12904 x_use_underline_position_properties
= 0;
12906 DEFVAR_BOOL ("x-underline-at-descent-line",
12907 &x_underline_at_descent_line
,
12908 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12909 A value of nil means to draw the underline according to the value of the
12910 variable `x-use-underline-position-properties', which is usually at the
12911 baseline level. The default value is nil. */);
12912 x_underline_at_descent_line
= 0;
12914 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12915 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12916 #ifdef USE_TOOLKIT_SCROLL_BARS
12917 Vx_toolkit_scroll_bars
= Qt
;
12919 Vx_toolkit_scroll_bars
= Qnil
;
12922 staticpro (&last_mouse_motion_frame
);
12923 last_mouse_motion_frame
= Qnil
;
12925 /* Variables to configure modifier key assignment. */
12927 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12928 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12929 The value can be `control', `meta', `alt', `hyper', or `super' for the
12930 respective modifier. The default is `control'. */);
12931 Vmac_control_modifier
= Qcontrol
;
12933 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12934 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12935 The value can be `control', `meta', `alt', `hyper', or `super' for the
12936 respective modifier. If the value is nil then the key will act as the
12937 normal Mac control modifier, and the option key can be used to compose
12938 characters depending on the chosen Mac keyboard setting. */);
12939 Vmac_option_modifier
= Qnil
;
12941 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12942 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12943 The value can be `control', `meta', `alt', `hyper', or `super' for the
12944 respective modifier. The default is `meta'. */);
12945 Vmac_command_modifier
= Qmeta
;
12947 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12948 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12949 The value can be `control', `meta', `alt', `hyper', or `super' for the
12950 respective modifier. Note that remapping the function key may lead to
12951 unexpected results for some keys on non-US/GB keyboards. */);
12952 Vmac_function_modifier
= Qnil
;
12954 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12955 &Vmac_emulate_three_button_mouse
,
12956 doc
: /* *Specify a way of three button mouse emulation.
12957 The value can be nil, t, or the symbol `reverse'.
12958 A value of nil means that no emulation should be done and the modifiers
12959 should be placed on the mouse-1 event.
12960 t means that when the option-key is held down while pressing the mouse
12961 button, the click will register as mouse-2 and while the command-key
12962 is held down, the click will register as mouse-3.
12963 The symbol `reverse' means that the option-key will register for
12964 mouse-3 and the command-key will register for mouse-2. */);
12965 Vmac_emulate_three_button_mouse
= Qnil
;
12967 #if TARGET_API_MAC_CARBON
12968 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12969 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12970 Otherwise, the right click will be treated as mouse-2 and the wheel
12971 button will be mouse-3. */);
12972 mac_wheel_button_is_mouse_2
= 1;
12974 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12975 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12976 mac_pass_command_to_system
= 1;
12978 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12979 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12980 mac_pass_control_to_system
= 1;
12984 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
12985 doc
: /* *If non-nil, allow anti-aliasing.
12986 The text will be rendered using Core Graphics text rendering which
12987 may anti-alias the text. */);
12989 mac_use_core_graphics
= 1;
12991 mac_use_core_graphics
= 0;
12994 /* Register an entry for `mac-roman' so that it can be used when
12995 creating the terminal frame on Mac OS 9 before loading
12996 term/mac-win.elc. */
12997 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
12998 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
12999 Each entry should be of the form:
13001 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13003 where CHARSET-NAME is a string used in font names to identify the
13004 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13005 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13006 Vmac_charset_info_alist
=
13007 Fcons (list3 (build_string ("mac-roman"),
13008 make_number (smRoman
), Qnil
), Qnil
);
13011 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13012 doc
: /* Overlay used to display Mac TSM active input area. */);
13013 Vmac_ts_active_input_overlay
= Qnil
;
13015 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13016 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13017 If the value is t, the input script and language are restored to those
13018 used in the last focus frame. If the value is a pair of integers, the
13019 input script and language codes, which are defined in the Script
13020 Manager, are set to its car and cdr parts, respectively. Otherwise,
13021 Emacs doesn't set them and thus follows the system default behavior. */);
13022 Vmac_ts_script_language_on_focus
= Qnil
;
13026 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13027 (do not change this comment) */