1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
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
++)
2364 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2365 sizeof (unsigned short) * h
, NULL
);
2368 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2369 sizeof (unsigned short),
2371 CGDataProviderRelease (provider
);
2378 mac_destroy_fringe_bitmap (which
)
2381 if (which
>= max_fringe_bmp
)
2384 if (fringe_bmp
[which
])
2387 CGImageRelease (fringe_bmp
[which
]);
2390 fringe_bmp
[which
] = 0;
2395 /* This is called when starting Emacs and when restarting after
2396 suspend. When starting Emacs, no window is mapped. And nothing
2397 must be done to Emacs's own window if it is suspended (though that
2401 XTset_terminal_modes ()
2405 /* This is called when exiting or suspending Emacs. Exiting will make
2406 the windows go away, and suspending requires no action. */
2409 XTreset_terminal_modes ()
2415 /***********************************************************************
2417 ***********************************************************************/
2419 /* Function prototypes of this page. */
2421 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2422 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2426 pcm_init (pcm
, count
)
2430 bzero (pcm
, sizeof (XCharStruct
) * count
);
2431 while (--count
>= 0)
2433 pcm
->descent
= PCM_INVALID
;
2438 static enum pcm_status
2439 pcm_get_status (pcm
)
2440 const XCharStruct
*pcm
;
2442 int height
= pcm
->ascent
+ pcm
->descent
;
2444 /* Negative height means some special status. */
2445 return height
>= 0 ? PCM_VALID
: height
;
2448 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2449 is not contained in the font. */
2451 static INLINE XCharStruct
*
2452 x_per_char_metric (font
, char2b
)
2456 /* The result metric information. */
2457 XCharStruct
*pcm
= NULL
;
2459 xassert (font
&& char2b
);
2462 if (font
->mac_style
)
2464 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2468 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2469 pcm_init (*row
, 0x100);
2471 pcm
= *row
+ char2b
->byte2
;
2472 if (pcm_get_status (pcm
) != PCM_VALID
)
2475 mac_query_char_extents (font
->mac_style
,
2476 (char2b
->byte1
<< 8) + char2b
->byte2
,
2477 NULL
, NULL
, pcm
, NULL
);
2484 if (font
->bounds
.per_char
!= NULL
)
2486 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2488 /* min_char_or_byte2 specifies the linear character index
2489 corresponding to the first element of the per_char array,
2490 max_char_or_byte2 is the index of the last character. A
2491 character with non-zero CHAR2B->byte1 is not in the font.
2492 A character with byte2 less than min_char_or_byte2 or
2493 greater max_char_or_byte2 is not in the font. */
2494 if (char2b
->byte1
== 0
2495 && char2b
->byte2
>= font
->min_char_or_byte2
2496 && char2b
->byte2
<= font
->max_char_or_byte2
)
2497 pcm
= font
->bounds
.per_char
2498 + (char2b
->byte2
- font
->min_char_or_byte2
);
2502 /* If either min_byte1 or max_byte1 are nonzero, both
2503 min_char_or_byte2 and max_char_or_byte2 are less than
2504 256, and the 2-byte character index values corresponding
2505 to the per_char array element N (counting from 0) are:
2507 byte1 = N/D + min_byte1
2508 byte2 = N\D + min_char_or_byte2
2512 D = max_char_or_byte2 - min_char_or_byte2 + 1
2513 / = integer division
2514 \ = integer modulus */
2515 if (char2b
->byte1
>= font
->min_byte1
2516 && char2b
->byte1
<= font
->max_byte1
2517 && char2b
->byte2
>= font
->min_char_or_byte2
2518 && char2b
->byte2
<= font
->max_char_or_byte2
)
2520 pcm
= (font
->bounds
.per_char
2521 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2522 * (char2b
->byte1
- font
->min_byte1
))
2523 + (char2b
->byte2
- font
->min_char_or_byte2
));
2529 /* If the per_char pointer is null, all glyphs between the first
2530 and last character indexes inclusive have the same
2531 information, as given by both min_bounds and max_bounds. */
2532 if (char2b
->byte2
>= font
->min_char_or_byte2
2533 && char2b
->byte2
<= font
->max_char_or_byte2
)
2534 pcm
= &font
->max_bounds
;
2540 return ((pcm
== NULL
2542 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2543 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2552 static XCharStruct
*
2553 mac_per_char_metric (font
, char2b
, font_type
)
2558 return x_per_char_metric (font
, char2b
);
2562 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2563 the two-byte form of C. Encoding is returned in *CHAR2B. */
2566 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2569 struct font_info
*font_info
;
2572 int charset
= CHAR_CHARSET (c
);
2573 XFontStruct
*font
= font_info
->font
;
2575 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2576 This may be either a program in a special encoder language or a
2578 if (font_info
->font_encoder
)
2580 /* It's a program. */
2581 struct ccl_program
*ccl
= font_info
->font_encoder
;
2583 check_ccl_update (ccl
);
2584 if (CHARSET_DIMENSION (charset
) == 1)
2586 ccl
->reg
[0] = charset
;
2587 ccl
->reg
[1] = char2b
->byte2
;
2592 ccl
->reg
[0] = charset
;
2593 ccl
->reg
[1] = char2b
->byte1
;
2594 ccl
->reg
[2] = char2b
->byte2
;
2597 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2599 /* We assume that MSBs are appropriately set/reset by CCL
2601 if (font
->max_byte1
== 0) /* 1-byte font */
2602 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2604 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2606 else if (font_info
->encoding
[charset
])
2608 /* Fixed encoding scheme. See fontset.h for the meaning of the
2609 encoding numbers. */
2610 int enc
= font_info
->encoding
[charset
];
2612 if ((enc
== 1 || enc
== 2)
2613 && CHARSET_DIMENSION (charset
) == 2)
2614 char2b
->byte1
|= 0x80;
2616 if (enc
== 1 || enc
== 3)
2617 char2b
->byte2
|= 0x80;
2623 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2624 char2b
->byte1
= sjis1
;
2625 char2b
->byte2
= sjis2
;
2630 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2632 return FONT_TYPE_UNKNOWN
;
2637 /***********************************************************************
2639 ***********************************************************************/
2643 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2644 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2645 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2647 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2648 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2649 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2650 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2651 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2652 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2653 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2654 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2655 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2656 unsigned long *, double, int));*/
2657 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2658 double, int, unsigned long));
2659 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2660 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2661 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2662 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2663 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2665 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2666 int, int, int, int, int, int,
2668 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2669 int, int, int, Rect
*));
2672 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2676 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2681 struct glyph_string
*s
;
2683 if (s
->font
== FRAME_FONT (s
->f
)
2684 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2685 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2687 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2690 /* Cursor on non-default face: must merge. */
2694 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2695 xgcv
.foreground
= s
->face
->background
;
2697 /* If the glyph would be invisible, try a different foreground. */
2698 if (xgcv
.foreground
== xgcv
.background
)
2699 xgcv
.foreground
= s
->face
->foreground
;
2700 if (xgcv
.foreground
== xgcv
.background
)
2701 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2702 if (xgcv
.foreground
== xgcv
.background
)
2703 xgcv
.foreground
= s
->face
->foreground
;
2705 /* Make sure the cursor is distinct from text in this face. */
2706 if (xgcv
.background
== s
->face
->background
2707 && xgcv
.foreground
== s
->face
->foreground
)
2709 xgcv
.background
= s
->face
->foreground
;
2710 xgcv
.foreground
= s
->face
->background
;
2713 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2714 xgcv
.font
= s
->font
;
2715 mask
= GCForeground
| GCBackground
| GCFont
;
2717 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2718 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2721 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2722 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2724 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2729 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2732 x_set_mouse_face_gc (s
)
2733 struct glyph_string
*s
;
2738 /* What face has to be used last for the mouse face? */
2739 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2740 face
= FACE_FROM_ID (s
->f
, face_id
);
2742 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2744 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2745 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2747 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2748 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2749 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2751 /* If font in this face is same as S->font, use it. */
2752 if (s
->font
== s
->face
->font
)
2753 s
->gc
= s
->face
->gc
;
2756 /* Otherwise construct scratch_cursor_gc with values from FACE
2761 xgcv
.background
= s
->face
->background
;
2762 xgcv
.foreground
= s
->face
->foreground
;
2763 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2764 xgcv
.font
= s
->font
;
2765 mask
= GCForeground
| GCBackground
| GCFont
;
2767 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2768 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2771 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2772 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2774 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2777 xassert (s
->gc
!= 0);
2781 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2782 Faces to use in the mode line have already been computed when the
2783 matrix was built, so there isn't much to do, here. */
2786 x_set_mode_line_face_gc (s
)
2787 struct glyph_string
*s
;
2789 s
->gc
= s
->face
->gc
;
2793 /* Set S->gc of glyph string S for drawing that glyph string. Set
2794 S->stippled_p to a non-zero value if the face of S has a stipple
2798 x_set_glyph_string_gc (s
)
2799 struct glyph_string
*s
;
2801 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2803 if (s
->hl
== DRAW_NORMAL_TEXT
)
2805 s
->gc
= s
->face
->gc
;
2806 s
->stippled_p
= s
->face
->stipple
!= 0;
2808 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2810 x_set_mode_line_face_gc (s
);
2811 s
->stippled_p
= s
->face
->stipple
!= 0;
2813 else if (s
->hl
== DRAW_CURSOR
)
2815 x_set_cursor_gc (s
);
2818 else if (s
->hl
== DRAW_MOUSE_FACE
)
2820 x_set_mouse_face_gc (s
);
2821 s
->stippled_p
= s
->face
->stipple
!= 0;
2823 else if (s
->hl
== DRAW_IMAGE_RAISED
2824 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2826 s
->gc
= s
->face
->gc
;
2827 s
->stippled_p
= s
->face
->stipple
!= 0;
2831 s
->gc
= s
->face
->gc
;
2832 s
->stippled_p
= s
->face
->stipple
!= 0;
2835 /* GC must have been set. */
2836 xassert (s
->gc
!= 0);
2840 /* Set clipping for output of glyph string S. S may be part of a mode
2841 line or menu if we don't have X toolkit support. */
2844 x_set_glyph_string_clipping (s
)
2845 struct glyph_string
*s
;
2847 Rect rects
[MAX_CLIP_RECTS
];
2850 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2851 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2856 Compute left and right overhang of glyph string S. If S is a glyph
2857 string for a composition, assume overhangs don't exist. */
2860 mac_compute_glyph_string_overhangs (s
)
2861 struct glyph_string
*s
;
2863 if (!(s
->cmp
== NULL
2864 && s
->first_glyph
->type
== CHAR_GLYPH
))
2869 || s
->font
->mac_style
2875 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2876 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2877 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2882 MacFontStruct
*font
= s
->font
;
2885 mac_prepare_for_quickdraw (s
->f
);
2887 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2889 TextFont (font
->mac_fontnum
);
2890 TextSize (font
->mac_fontsize
);
2891 TextFace (font
->mac_fontface
);
2893 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2895 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2896 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2901 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2904 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2905 struct glyph_string
*s
;
2908 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2912 /* Draw the background of glyph_string S. If S->background_filled_p
2913 is non-zero don't draw it. FORCE_P non-zero means draw the
2914 background even if it wouldn't be drawn normally. This is used
2915 when a string preceding S draws into the background of S, or S
2916 contains the first component of a composition. */
2919 x_draw_glyph_string_background (s
, force_p
)
2920 struct glyph_string
*s
;
2923 /* Nothing to do if background has already been drawn or if it
2924 shouldn't be drawn in the first place. */
2925 if (!s
->background_filled_p
)
2927 int box_line_width
= max (s
->face
->box_line_width
, 0);
2929 #if 0 /* MAC_TODO: stipple */
2932 /* Fill background with a stipple pattern. */
2933 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2934 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2935 s
->y
+ box_line_width
,
2936 s
->background_width
,
2937 s
->height
- 2 * box_line_width
);
2938 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2939 s
->background_filled_p
= 1;
2943 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2944 || s
->font_not_found_p
2945 || s
->extends_to_end_of_line_p
2948 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2949 s
->background_width
,
2950 s
->height
- 2 * box_line_width
);
2951 s
->background_filled_p
= 1;
2957 /* Draw the foreground of glyph string S. */
2960 x_draw_glyph_string_foreground (s
)
2961 struct glyph_string
*s
;
2965 /* If first glyph of S has a left box line, start drawing the text
2966 of S to the right of that box line. */
2967 if (s
->face
->box
!= FACE_NO_BOX
2968 && s
->first_glyph
->left_box_line_p
)
2969 x
= s
->x
+ abs (s
->face
->box_line_width
);
2973 /* Draw characters of S as rectangles if S's font could not be
2975 if (s
->font_not_found_p
)
2977 for (i
= 0; i
< s
->nchars
; ++i
)
2979 struct glyph
*g
= s
->first_glyph
+ i
;
2980 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2981 g
->pixel_width
- 1, s
->height
- 1);
2982 x
+= g
->pixel_width
;
2987 char *char1b
= (char *) s
->char2b
;
2988 int boff
= s
->font_info
->baseline_offset
;
2990 if (s
->font_info
->vertical_centering
)
2991 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2993 /* If we can use 8-bit functions, condense S->char2b. */
2996 && GC_FONT (s
->gc
)->mac_style
== NULL
2999 for (i
= 0; i
< s
->nchars
; ++i
)
3000 char1b
[i
] = s
->char2b
[i
].byte2
;
3002 /* Draw text with XDrawString if background has already been
3003 filled. Otherwise, use XDrawImageString. (Note that
3004 XDrawImageString is usually faster than XDrawString.) Always
3005 use XDrawImageString when drawing the cursor so that there is
3006 no chance that characters under a box cursor are invisible. */
3008 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3009 bg_width
= 0; /* Corresponds to XDrawString. */
3011 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
3015 || GC_FONT (s
->gc
)->mac_style
3018 #if USE_CG_TEXT_DRAWING
3020 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3021 s
->char2b
, s
->nchars
, bg_width
,
3022 s
->face
->overstrike
))
3026 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3027 s
->char2b
, s
->nchars
, bg_width
,
3028 s
->face
->overstrike
);
3030 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3031 char1b
, s
->nchars
, bg_width
,
3032 s
->face
->overstrike
);
3036 /* Draw the foreground of composite glyph string S. */
3039 x_draw_composite_glyph_string_foreground (s
)
3040 struct glyph_string
*s
;
3044 /* If first glyph of S has a left box line, start drawing the text
3045 of S to the right of that box line. */
3046 if (s
->face
->box
!= FACE_NO_BOX
3047 && s
->first_glyph
->left_box_line_p
)
3048 x
= s
->x
+ abs (s
->face
->box_line_width
);
3052 /* S is a glyph string for a composition. S->gidx is the index of
3053 the first character drawn for glyphs of this composition.
3054 S->gidx == 0 means we are drawing the very first character of
3055 this composition. */
3057 /* Draw a rectangle for the composition if the font for the very
3058 first character of the composition could not be loaded. */
3059 if (s
->font_not_found_p
)
3062 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3063 s
->width
- 1, s
->height
- 1);
3067 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3068 if (mac_per_char_metric (GC_FONT (s
->gc
), s
->char2b
+ i
, 0) == NULL
)
3069 /* This is a nonexistent or zero-width glyph such as a
3070 combining diacritic. Draw a rectangle. */
3071 mac_draw_rectangle (s
->f
, s
->gc
,
3072 x
+ s
->cmp
->offsets
[s
->gidx
* 2], s
->y
,
3073 FONT_WIDTH (GC_FONT (s
->gc
)) - 1, s
->height
- 1);
3075 mac_draw_image_string_16 (s
->f
, s
->gc
,
3076 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3077 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3078 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3083 #ifdef USE_X_TOOLKIT
3085 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3088 /* Return the frame on which widget WIDGET is used.. Abort if frame
3089 cannot be determined. */
3091 static struct frame
*
3092 x_frame_of_widget (widget
)
3095 struct x_display_info
*dpyinfo
;
3099 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3101 /* Find the top-level shell of the widget. Note that this function
3102 can be called when the widget is not yet realized, so XtWindow
3103 (widget) == 0. That's the reason we can't simply use
3104 x_any_window_to_frame. */
3105 while (!XtIsTopLevelShell (widget
))
3106 widget
= XtParent (widget
);
3108 /* Look for a frame with that top-level widget. Allocate the color
3109 on that frame to get the right gamma correction value. */
3110 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3111 if (GC_FRAMEP (XCAR (tail
))
3112 && (f
= XFRAME (XCAR (tail
)),
3113 (f
->output_data
.nothing
!= 1
3114 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3115 && f
->output_data
.x
->widget
== widget
)
3122 /* Allocate the color COLOR->pixel on the screen and display of
3123 widget WIDGET in colormap CMAP. If an exact match cannot be
3124 allocated, try the nearest color available. Value is non-zero
3125 if successful. This is called from lwlib. */
3128 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3133 struct frame
*f
= x_frame_of_widget (widget
);
3134 return x_alloc_nearest_color (f
, cmap
, color
);
3138 #endif /* USE_X_TOOLKIT */
3140 #if 0 /* MAC_TODO */
3142 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3143 CMAP. If an exact match can't be allocated, try the nearest color
3144 available. Value is non-zero if successful. Set *COLOR to the
3148 x_alloc_nearest_color (f
, cmap
, color
)
3153 Display
*display
= FRAME_X_DISPLAY (f
);
3154 Screen
*screen
= FRAME_X_SCREEN (f
);
3157 gamma_correct (f
, color
);
3158 rc
= XAllocColor (display
, cmap
, color
);
3161 /* If we got to this point, the colormap is full, so we're going
3162 to try to get the next closest color. The algorithm used is
3163 a least-squares matching, which is what X uses for closest
3164 color matching with StaticColor visuals. */
3166 unsigned long nearest_delta
= ~0;
3167 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3168 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3170 for (i
= 0; i
< ncells
; ++i
)
3172 XQueryColors (display
, cmap
, cells
, ncells
);
3174 for (nearest
= i
= 0; i
< ncells
; ++i
)
3176 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3177 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3178 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3179 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3181 if (delta
< nearest_delta
)
3184 nearest_delta
= delta
;
3188 color
->red
= cells
[nearest
].red
;
3189 color
->green
= cells
[nearest
].green
;
3190 color
->blue
= cells
[nearest
].blue
;
3191 rc
= XAllocColor (display
, cmap
, color
);
3194 #ifdef DEBUG_X_COLORS
3196 register_color (color
->pixel
);
3197 #endif /* DEBUG_X_COLORS */
3203 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3204 It's necessary to do this instead of just using PIXEL directly to
3205 get color reference counts right. */
3208 x_copy_color (f
, pixel
)
3210 unsigned long pixel
;
3214 color
.pixel
= pixel
;
3216 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3217 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3219 #ifdef DEBUG_X_COLORS
3220 register_color (pixel
);
3226 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3227 It's necessary to do this instead of just using PIXEL directly to
3228 get color reference counts right. */
3231 x_copy_dpy_color (dpy
, cmap
, pixel
)
3234 unsigned long pixel
;
3238 color
.pixel
= pixel
;
3240 XQueryColor (dpy
, cmap
, &color
);
3241 XAllocColor (dpy
, cmap
, &color
);
3243 #ifdef DEBUG_X_COLORS
3244 register_color (pixel
);
3249 #endif /* MAC_TODO */
3252 /* Brightness beyond which a color won't have its highlight brightness
3255 Nominally, highlight colors for `3d' faces are calculated by
3256 brightening an object's color by a constant scale factor, but this
3257 doesn't yield good results for dark colors, so for colors who's
3258 brightness is less than this value (on a scale of 0-255) have to
3259 use an additional additive factor.
3261 The value here is set so that the default menu-bar/mode-line color
3262 (grey75) will not have its highlights changed at all. */
3263 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3266 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3267 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3268 If this produces the same color as COLOR, try a color where all RGB
3269 values have DELTA added. Return the allocated color in *COLOR.
3270 DISPLAY is the X display, CMAP is the colormap to operate on.
3271 Value is non-zero if successful. */
3274 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3276 unsigned long *color
;
3283 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3286 /* Change RGB values by specified FACTOR. Avoid overflow! */
3287 xassert (factor
>= 0);
3288 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3289 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3290 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3292 /* Calculate brightness of COLOR. */
3293 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3294 + BLUE_FROM_ULONG (*color
)) / 6;
3296 /* We only boost colors that are darker than
3297 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3298 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3299 /* Make an additive adjustment to NEW, because it's dark enough so
3300 that scaling by FACTOR alone isn't enough. */
3302 /* How far below the limit this color is (0 - 1, 1 being darker). */
3303 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3304 /* The additive adjustment. */
3305 int min_delta
= delta
* dimness
* factor
/ 2;
3308 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3309 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3310 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3312 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3313 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3314 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3318 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3319 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3320 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3322 /* MAC_TODO: Map to palette and retry with delta if same? */
3323 /* MAC_TODO: Free colors (if using palette)? */
3334 /* Set up the foreground color for drawing relief lines of glyph
3335 string S. RELIEF is a pointer to a struct relief containing the GC
3336 with which lines will be drawn. Use a color that is FACTOR or
3337 DELTA lighter or darker than the relief's background which is found
3338 in S->f->output_data.x->relief_background. If such a color cannot
3339 be allocated, use DEFAULT_PIXEL, instead. */
3342 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3344 struct relief
*relief
;
3347 unsigned long default_pixel
;
3350 struct mac_output
*di
= f
->output_data
.mac
;
3351 unsigned long mask
= GCForeground
;
3352 unsigned long pixel
;
3353 unsigned long background
= di
->relief_background
;
3354 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3356 /* MAC_TODO: Free colors (if using palette)? */
3358 /* Allocate new color. */
3359 xgcv
.foreground
= default_pixel
;
3361 if (dpyinfo
->n_planes
!= 1
3362 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3364 relief
->allocated_p
= 1;
3365 xgcv
.foreground
= relief
->pixel
= pixel
;
3368 if (relief
->gc
== 0)
3370 #if 0 /* MAC_TODO: stipple */
3371 xgcv
.stipple
= dpyinfo
->gray
;
3374 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3377 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3381 /* Set up colors for the relief lines around glyph string S. */
3384 x_setup_relief_colors (s
)
3385 struct glyph_string
*s
;
3387 struct mac_output
*di
= s
->f
->output_data
.mac
;
3388 unsigned long color
;
3390 if (s
->face
->use_box_color_for_shadows_p
)
3391 color
= s
->face
->box_color
;
3392 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3394 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3395 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3400 /* Get the background color of the face. */
3401 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3402 color
= xgcv
.background
;
3405 if (di
->white_relief
.gc
== 0
3406 || color
!= di
->relief_background
)
3408 di
->relief_background
= color
;
3409 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3410 WHITE_PIX_DEFAULT (s
->f
));
3411 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3412 BLACK_PIX_DEFAULT (s
->f
));
3417 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3418 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3419 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3420 relief. LEFT_P non-zero means draw a relief on the left side of
3421 the rectangle. RIGHT_P non-zero means draw a relief on the right
3422 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3426 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3427 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3429 int left_x
, top_y
, right_x
, bottom_y
, width
;
3430 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3433 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3438 gc
= f
->output_data
.mac
->white_relief
.gc
;
3440 gc
= f
->output_data
.mac
->black_relief
.gc
;
3441 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3445 for (i
= 0; i
< width
; ++i
)
3446 mac_draw_line (f
, gc
,
3447 left_x
+ i
* left_p
, top_y
+ i
,
3448 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3452 for (i
= 0; i
< width
; ++i
)
3453 mac_draw_line (f
, gc
,
3454 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3456 mac_reset_clip_rectangles (dpy
, gc
);
3458 gc
= f
->output_data
.mac
->black_relief
.gc
;
3460 gc
= f
->output_data
.mac
->white_relief
.gc
;
3461 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3465 for (i
= 0; i
< width
; ++i
)
3466 mac_draw_line (f
, gc
,
3467 left_x
+ i
* left_p
, bottom_y
- i
,
3468 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3472 for (i
= 0; i
< width
; ++i
)
3473 mac_draw_line (f
, gc
,
3474 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3476 mac_reset_clip_rectangles (dpy
, gc
);
3480 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3481 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3482 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3483 left side of the rectangle. RIGHT_P non-zero means draw a line
3484 on the right side of the rectangle. CLIP_RECT is the clipping
3485 rectangle to use when drawing. */
3488 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3489 left_p
, right_p
, clip_rect
)
3490 struct glyph_string
*s
;
3491 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3496 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3497 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3498 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3501 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3502 right_x
- left_x
+ 1, width
);
3506 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3507 width
, bottom_y
- top_y
+ 1);
3510 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3511 right_x
- left_x
+ 1, width
);
3515 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3516 top_y
, width
, bottom_y
- top_y
+ 1);
3518 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3519 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3523 /* Draw a box around glyph string S. */
3526 x_draw_glyph_string_box (s
)
3527 struct glyph_string
*s
;
3529 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3530 int left_p
, right_p
;
3531 struct glyph
*last_glyph
;
3534 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3535 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3536 : window_box_right (s
->w
, s
->area
));
3538 /* The glyph that may have a right box line. */
3539 last_glyph
= (s
->cmp
|| s
->img
3541 : s
->first_glyph
+ s
->nchars
- 1);
3543 width
= abs (s
->face
->box_line_width
);
3544 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3546 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3548 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3550 bottom_y
= top_y
+ s
->height
- 1;
3552 left_p
= (s
->first_glyph
->left_box_line_p
3553 || (s
->hl
== DRAW_MOUSE_FACE
3555 || s
->prev
->hl
!= s
->hl
)));
3556 right_p
= (last_glyph
->right_box_line_p
3557 || (s
->hl
== DRAW_MOUSE_FACE
3559 || s
->next
->hl
!= s
->hl
)));
3561 get_glyph_string_clip_rect (s
, &clip_rect
);
3563 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3564 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3565 left_p
, right_p
, &clip_rect
);
3568 x_setup_relief_colors (s
);
3569 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3570 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3575 /* Draw foreground of image glyph string S. */
3578 x_draw_image_foreground (s
)
3579 struct glyph_string
*s
;
3582 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3584 /* If first glyph of S has a left box line, start drawing it to the
3585 right of that line. */
3586 if (s
->face
->box
!= FACE_NO_BOX
3587 && s
->first_glyph
->left_box_line_p
3589 x
+= abs (s
->face
->box_line_width
);
3591 /* If there is a margin around the image, adjust x- and y-position
3593 if (s
->slice
.x
== 0)
3594 x
+= s
->img
->hmargin
;
3595 if (s
->slice
.y
== 0)
3596 y
+= s
->img
->vmargin
;
3600 x_set_glyph_string_clipping (s
);
3603 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3604 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3605 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3609 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3610 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3611 s
->slice
.width
, s
->slice
.height
, x
, y
);
3618 mac_copy_area (s
->img
->pixmap
,
3619 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3620 s
->slice
.width
, s
->slice
.height
, x
, y
);
3623 /* When the image has a mask, we can expect that at
3624 least part of a mouse highlight or a block cursor will
3625 be visible. If the image doesn't have a mask, make
3626 a block cursor visible by drawing a rectangle around
3627 the image. I believe it's looking better if we do
3628 nothing here for mouse-face. */
3629 if (s
->hl
== DRAW_CURSOR
)
3631 int r
= s
->img
->relief
;
3633 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3634 s
->slice
.width
+ r
*2 - 1,
3635 s
->slice
.height
+ r
*2 - 1);
3640 /* Draw a rectangle if image could not be loaded. */
3641 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3642 s
->slice
.width
- 1, s
->slice
.height
- 1);
3646 /* Draw a relief around the image glyph string S. */
3649 x_draw_image_relief (s
)
3650 struct glyph_string
*s
;
3652 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3655 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3657 /* If first glyph of S has a left box line, start drawing it to the
3658 right of that line. */
3659 if (s
->face
->box
!= FACE_NO_BOX
3660 && s
->first_glyph
->left_box_line_p
3662 x
+= abs (s
->face
->box_line_width
);
3664 /* If there is a margin around the image, adjust x- and y-position
3666 if (s
->slice
.x
== 0)
3667 x
+= s
->img
->hmargin
;
3668 if (s
->slice
.y
== 0)
3669 y
+= s
->img
->vmargin
;
3671 if (s
->hl
== DRAW_IMAGE_SUNKEN
3672 || s
->hl
== DRAW_IMAGE_RAISED
)
3674 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3675 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3679 thick
= abs (s
->img
->relief
);
3680 raised_p
= s
->img
->relief
> 0;
3685 x1
= x
+ s
->slice
.width
+ thick
- 1;
3686 y1
= y
+ s
->slice
.height
+ thick
- 1;
3688 x_setup_relief_colors (s
);
3689 get_glyph_string_clip_rect (s
, &r
);
3690 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3692 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3694 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3699 /* Draw part of the background of glyph string S. X, Y, W, and H
3700 give the rectangle to draw. */
3703 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3704 struct glyph_string
*s
;
3707 #if 0 /* MAC_TODO: stipple */
3710 /* Fill background with a stipple pattern. */
3711 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3712 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3713 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3716 #endif /* MAC_TODO */
3717 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3721 /* Draw image glyph string S.
3724 s->x +-------------------------
3727 | +-------------------------
3730 | | +-------------------
3736 x_draw_image_glyph_string (s
)
3737 struct glyph_string
*s
;
3740 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3741 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3744 height
= s
->height
- 2 * box_line_vwidth
;
3747 /* Fill background with face under the image. Do it only if row is
3748 taller than image or if image has a clip mask to reduce
3750 s
->stippled_p
= s
->face
->stipple
!= 0;
3751 if (height
> s
->slice
.height
3755 || s
->img
->pixmap
== 0
3756 || s
->width
!= s
->background_width
)
3759 if (s
->first_glyph
->left_box_line_p
3761 x
+= box_line_hwidth
;
3764 if (s
->slice
.y
== 0)
3765 y
+= box_line_vwidth
;
3767 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3769 s
->background_filled_p
= 1;
3772 /* Draw the foreground. */
3773 x_draw_image_foreground (s
);
3775 /* If we must draw a relief around the image, do it. */
3777 || s
->hl
== DRAW_IMAGE_RAISED
3778 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3779 x_draw_image_relief (s
);
3783 /* Draw stretch glyph string S. */
3786 x_draw_stretch_glyph_string (s
)
3787 struct glyph_string
*s
;
3789 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3791 if (s
->hl
== DRAW_CURSOR
3792 && !x_stretch_cursor_p
)
3794 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3795 as wide as the stretch glyph. */
3796 int width
, background_width
= s
->background_width
;
3797 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3801 background_width
-= left_x
- x
;
3804 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3807 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3809 /* Clear rest using the GC of the original non-cursor face. */
3810 if (width
< background_width
)
3813 int w
= background_width
- width
, h
= s
->height
;
3818 if (s
->row
->mouse_face_p
3819 && cursor_in_mouse_face_p (s
->w
))
3821 x_set_mouse_face_gc (s
);
3827 get_glyph_string_clip_rect (s
, &r
);
3828 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3830 #if 0 /* MAC_TODO: stipple */
3831 if (s
->face
->stipple
)
3833 /* Fill background with a stipple pattern. */
3834 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3835 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3836 XSetFillStyle (s
->display
, gc
, FillSolid
);
3839 #endif /* MAC_TODO */
3840 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3843 else if (!s
->background_filled_p
)
3845 int background_width
= s
->background_width
;
3846 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3848 /* Don't draw into left margin, fringe or scrollbar area
3849 except for header line and mode line. */
3850 if (x
< left_x
&& !s
->row
->mode_line_p
)
3852 background_width
-= left_x
- x
;
3855 if (background_width
> 0)
3856 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3859 s
->background_filled_p
= 1;
3863 /* Draw glyph string S. */
3866 x_draw_glyph_string (s
)
3867 struct glyph_string
*s
;
3869 int relief_drawn_p
= 0;
3871 /* If S draws into the background of its successor that does not
3872 draw a cursor, draw the background of the successor first so that
3873 S can draw into it. This makes S->next use XDrawString instead
3874 of XDrawImageString. */
3875 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3876 && s
->next
->hl
!= DRAW_CURSOR
)
3878 xassert (s
->next
->img
== NULL
);
3879 x_set_glyph_string_gc (s
->next
);
3880 x_set_glyph_string_clipping (s
->next
);
3881 x_draw_glyph_string_background (s
->next
, 1);
3884 /* Set up S->gc, set clipping and draw S. */
3885 x_set_glyph_string_gc (s
);
3887 /* Draw relief (if any) in advance for char/composition so that the
3888 glyph string can be drawn over it. */
3889 if (!s
->for_overlaps
3890 && s
->face
->box
!= FACE_NO_BOX
3891 && (s
->first_glyph
->type
== CHAR_GLYPH
3892 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3895 x_set_glyph_string_clipping (s
);
3896 x_draw_glyph_string_background (s
, 1);
3897 x_draw_glyph_string_box (s
);
3898 x_set_glyph_string_clipping (s
);
3902 x_set_glyph_string_clipping (s
);
3904 switch (s
->first_glyph
->type
)
3907 x_draw_image_glyph_string (s
);
3911 x_draw_stretch_glyph_string (s
);
3915 if (s
->for_overlaps
)
3916 s
->background_filled_p
= 1;
3918 x_draw_glyph_string_background (s
, 0);
3919 x_draw_glyph_string_foreground (s
);
3922 case COMPOSITE_GLYPH
:
3923 if (s
->for_overlaps
|| s
->gidx
> 0)
3924 s
->background_filled_p
= 1;
3926 x_draw_glyph_string_background (s
, 1);
3927 x_draw_composite_glyph_string_foreground (s
);
3934 if (!s
->for_overlaps
)
3936 /* Draw underline. */
3937 if (s
->face
->underline_p
)
3939 unsigned long tem
, h
;
3943 /* Get the underline thickness. Default is 1 pixel. */
3944 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3948 y
= s
->y
+ s
->height
- h
;
3949 if (!x_underline_at_descent_line
)
3951 /* Get the underline position. This is the recommended
3952 vertical offset in pixels from the baseline to the top of
3953 the underline. This is a signed value according to the
3954 specs, and its default is
3956 ROUND ((maximum descent) / 2), with
3957 ROUND(x) = floor (x + 0.5) */
3960 if (x_use_underline_position_properties
3961 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3962 y
= s
->ybase
+ (long) tem
;
3966 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3969 if (s
->face
->underline_defaulted_p
)
3970 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3971 s
->background_width
, h
);
3975 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3976 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3977 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3978 s
->background_width
, h
);
3979 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3983 /* Draw overline. */
3984 if (s
->face
->overline_p
)
3986 unsigned long dy
= 0, h
= 1;
3988 if (s
->face
->overline_color_defaulted_p
)
3989 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3990 s
->background_width
, h
);
3994 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3995 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3996 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3997 s
->background_width
, h
);
3998 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4002 /* Draw strike-through. */
4003 if (s
->face
->strike_through_p
)
4005 unsigned long h
= 1;
4006 unsigned long dy
= (s
->height
- h
) / 2;
4008 if (s
->face
->strike_through_color_defaulted_p
)
4009 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4014 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4015 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4016 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4018 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4022 /* Draw relief if not yet drawn. */
4023 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4024 x_draw_glyph_string_box (s
);
4027 /* Reset clipping. */
4028 mac_reset_clip_rectangles (s
->display
, s
->gc
);
4031 /* Shift display to make room for inserted glyphs. */
4034 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4036 int x
, y
, width
, height
, shift_by
;
4038 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4039 x
, y
, width
, height
,
4043 /* Delete N glyphs at the nominal cursor position. Not implemented
4054 /* Clear entire frame. If updating_frame is non-null, clear that
4055 frame. Otherwise clear the selected frame. */
4065 f
= SELECTED_FRAME ();
4067 /* Clearing the frame will erase any cursor, so mark them all as no
4069 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4070 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4071 output_cursor
.x
= -1;
4073 /* We don't set the output cursor here because there will always
4074 follow an explicit cursor_to. */
4076 mac_clear_window (f
);
4078 /* We have to clear the scroll bars, too. If we have changed
4079 colors or something like that, then they should be notified. */
4080 x_scroll_bar_clear (f
);
4082 XFlush (FRAME_MAC_DISPLAY (f
));
4088 /* Invert the middle quarter of the frame for .15 sec. */
4090 /* We use the select system call to do the waiting, so we have to make
4091 sure it's available. If it isn't, we just won't do visual bells. */
4093 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4096 /* Subtract the `struct timeval' values X and Y, storing the result in
4097 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4100 timeval_subtract (result
, x
, y
)
4101 struct timeval
*result
, x
, y
;
4103 /* Perform the carry for the later subtraction by updating y. This
4104 is safer because on some systems the tv_sec member is unsigned. */
4105 if (x
.tv_usec
< y
.tv_usec
)
4107 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4108 y
.tv_usec
-= 1000000 * nsec
;
4112 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4114 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4115 y
.tv_usec
+= 1000000 * nsec
;
4119 /* Compute the time remaining to wait. tv_usec is certainly
4121 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4122 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4124 /* Return indication of whether the result should be considered
4126 return x
.tv_sec
< y
.tv_sec
;
4133 /* Get the height not including a menu bar widget. */
4134 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4135 /* Height of each line to flash. */
4136 int flash_height
= FRAME_LINE_HEIGHT (f
);
4137 /* These will be the left and right margins of the rectangles. */
4138 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4139 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4143 /* Don't flash the area between a scroll bar and the frame
4144 edge it is next to. */
4145 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4147 case vertical_scroll_bar_left
:
4148 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4151 case vertical_scroll_bar_right
:
4152 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4159 width
= flash_right
- flash_left
;
4163 /* If window is tall, flash top and bottom line. */
4164 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4166 mac_invert_rectangle (f
, flash_left
,
4167 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4168 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4169 width
, flash_height
);
4170 mac_invert_rectangle (f
, flash_left
,
4171 (height
- flash_height
4172 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4173 width
, flash_height
);
4176 /* If it is short, flash it all. */
4177 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4178 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4183 struct timeval wakeup
;
4185 EMACS_GET_TIME (wakeup
);
4187 /* Compute time to wait until, propagating carry from usecs. */
4188 wakeup
.tv_usec
+= 150000;
4189 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4190 wakeup
.tv_usec
%= 1000000;
4192 /* Keep waiting until past the time wakeup or any input gets
4194 while (! detect_input_pending ())
4196 struct timeval current
;
4197 struct timeval timeout
;
4199 EMACS_GET_TIME (current
);
4201 /* Break if result would be negative. */
4202 if (timeval_subtract (¤t
, wakeup
, current
))
4205 /* How long `select' should wait. */
4207 timeout
.tv_usec
= 10000;
4209 /* Try to wait that long--but we might wake up sooner. */
4210 select (0, NULL
, NULL
, NULL
, &timeout
);
4214 /* If window is tall, flash top and bottom line. */
4215 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4217 mac_invert_rectangle (f
, flash_left
,
4218 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4219 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4220 width
, flash_height
);
4221 mac_invert_rectangle (f
, flash_left
,
4222 (height
- flash_height
4223 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4224 width
, flash_height
);
4227 /* If it is short, flash it all. */
4228 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4229 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4236 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4239 /* Make audible bell. */
4244 struct frame
*f
= SELECTED_FRAME ();
4246 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4254 XFlush (FRAME_MAC_DISPLAY (f
));
4260 /* Specify how many text lines, from the top of the window,
4261 should be affected by insert-lines and delete-lines operations.
4262 This, and those operations, are used only within an update
4263 that is bounded by calls to x_update_begin and x_update_end. */
4266 XTset_terminal_window (n
)
4269 /* This function intentionally left blank. */
4274 /***********************************************************************
4276 ***********************************************************************/
4278 /* Perform an insert-lines or delete-lines operation, inserting N
4279 lines or deleting -N lines at vertical position VPOS. */
4282 x_ins_del_lines (vpos
, n
)
4289 /* Scroll part of the display as described by RUN. */
4292 x_scroll_run (w
, run
)
4296 struct frame
*f
= XFRAME (w
->frame
);
4297 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4299 /* Get frame-relative bounding box of the text display area of W,
4300 without mode lines. Include in this box the left and right
4302 window_box (w
, -1, &x
, &y
, &width
, &height
);
4304 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4305 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4306 bottom_y
= y
+ height
;
4310 /* Scrolling up. Make sure we don't copy part of the mode
4311 line at the bottom. */
4312 if (from_y
+ run
->height
> bottom_y
)
4313 height
= bottom_y
- from_y
;
4315 height
= run
->height
;
4319 /* Scolling down. Make sure we don't copy over the mode line.
4321 if (to_y
+ run
->height
> bottom_y
)
4322 height
= bottom_y
- to_y
;
4324 height
= run
->height
;
4329 /* Cursor off. Will be switched on again in x_update_window_end. */
4333 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4343 /***********************************************************************
4345 ***********************************************************************/
4352 x_update_cursor (f
, 1);
4356 frame_unhighlight (f
)
4359 x_update_cursor (f
, 1);
4362 /* The focus has changed. Update the frames as necessary to reflect
4363 the new situation. Note that we can't change the selected frame
4364 here, because the Lisp code we are interrupting might become confused.
4365 Each event gets marked with the frame in which it occurred, so the
4366 Lisp code can tell when the switch took place by examining the events. */
4369 x_new_focus_frame (dpyinfo
, frame
)
4370 struct x_display_info
*dpyinfo
;
4371 struct frame
*frame
;
4373 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4375 if (frame
!= dpyinfo
->x_focus_frame
)
4377 /* Set this before calling other routines, so that they see
4378 the correct value of x_focus_frame. */
4379 dpyinfo
->x_focus_frame
= frame
;
4381 if (old_focus
&& old_focus
->auto_lower
)
4382 x_lower_frame (old_focus
);
4385 selected_frame
= frame
;
4386 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4388 Fselect_window (selected_frame
->selected_window
, Qnil
);
4389 choose_minibuf_frame ();
4392 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4393 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4395 pending_autoraise_frame
= 0;
4397 #if USE_MAC_FONT_PANEL
4399 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4403 x_frame_rehighlight (dpyinfo
);
4406 /* Handle FocusIn and FocusOut state changes for FRAME.
4407 If FRAME has focus and there exists more than one frame, puts
4408 a FOCUS_IN_EVENT into *BUFP. */
4411 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4413 struct mac_display_info
*dpyinfo
;
4414 struct frame
*frame
;
4415 struct input_event
*bufp
;
4417 if (type
== activeFlag
)
4419 if (dpyinfo
->x_focus_event_frame
!= frame
)
4421 x_new_focus_frame (dpyinfo
, frame
);
4422 dpyinfo
->x_focus_event_frame
= frame
;
4424 /* Don't stop displaying the initial startup message
4425 for a switch-frame event we don't need. */
4426 if (GC_NILP (Vterminal_frame
)
4427 && GC_CONSP (Vframe_list
)
4428 && !GC_NILP (XCDR (Vframe_list
)))
4430 bufp
->kind
= FOCUS_IN_EVENT
;
4431 XSETFRAME (bufp
->frame_or_window
, frame
);
4437 if (dpyinfo
->x_focus_event_frame
== frame
)
4439 dpyinfo
->x_focus_event_frame
= 0;
4440 x_new_focus_frame (dpyinfo
, 0);
4445 /* The focus may have changed. Figure out if it is a real focus change,
4446 by checking both FocusIn/Out and Enter/LeaveNotify events.
4448 Returns FOCUS_IN_EVENT event in *BUFP. */
4451 x_detect_focus_change (dpyinfo
, event
, bufp
)
4452 struct mac_display_info
*dpyinfo
;
4453 const EventRecord
*event
;
4454 struct input_event
*bufp
;
4456 struct frame
*frame
;
4458 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4462 /* On Mac, this is only called from focus events, so no switch needed. */
4463 mac_focus_changed ((event
->modifiers
& activeFlag
),
4464 dpyinfo
, frame
, bufp
);
4468 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4471 x_mouse_leave (dpyinfo
)
4472 struct x_display_info
*dpyinfo
;
4474 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4477 /* The focus has changed, or we have redirected a frame's focus to
4478 another frame (this happens when a frame uses a surrogate
4479 mini-buffer frame). Shift the highlight as appropriate.
4481 The FRAME argument doesn't necessarily have anything to do with which
4482 frame is being highlighted or un-highlighted; we only use it to find
4483 the appropriate X display info. */
4486 XTframe_rehighlight (frame
)
4487 struct frame
*frame
;
4489 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4493 x_frame_rehighlight (dpyinfo
)
4494 struct x_display_info
*dpyinfo
;
4496 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4498 if (dpyinfo
->x_focus_frame
)
4500 dpyinfo
->x_highlight_frame
4501 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4502 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4503 : dpyinfo
->x_focus_frame
);
4504 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4506 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4507 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4511 dpyinfo
->x_highlight_frame
= 0;
4513 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4516 frame_unhighlight (old_highlight
);
4517 if (dpyinfo
->x_highlight_frame
)
4518 frame_highlight (dpyinfo
->x_highlight_frame
);
4524 /* Convert a keysym to its name. */
4527 x_get_keysym_name (keysym
)
4534 value
= XKeysymToString (keysym
);
4545 /* Function to report a mouse movement to the mainstream Emacs code.
4546 The input handler calls this.
4548 We have received a mouse movement event, which is given in *event.
4549 If the mouse is over a different glyph than it was last time, tell
4550 the mainstream emacs code by setting mouse_moved. If not, ask for
4551 another motion event, so we can check again the next time it moves. */
4553 static Point last_mouse_motion_position
;
4554 static Lisp_Object last_mouse_motion_frame
;
4557 note_mouse_movement (frame
, pos
)
4561 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4562 #if TARGET_API_MAC_CARBON
4566 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4567 last_mouse_motion_position
= *pos
;
4568 XSETFRAME (last_mouse_motion_frame
, frame
);
4570 if (frame
== dpyinfo
->mouse_face_mouse_frame
4571 #if TARGET_API_MAC_CARBON
4572 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4574 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4578 /* This case corresponds to LeaveNotify in X11. If we move
4579 outside the frame, then we're certainly no longer on any text
4581 clear_mouse_face (dpyinfo
);
4582 dpyinfo
->mouse_face_mouse_frame
= 0;
4583 if (!dpyinfo
->grabbed
)
4584 rif
->define_frame_cursor (frame
,
4585 frame
->output_data
.mac
->nontext_cursor
);
4588 /* Has the mouse moved off the glyph it was on at the last sighting? */
4589 if (frame
!= last_mouse_glyph_frame
4590 || !PtInRect (*pos
, &last_mouse_glyph
))
4592 frame
->mouse_moved
= 1;
4593 last_mouse_scroll_bar
= Qnil
;
4594 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4595 /* Remember which glyph we're now on. */
4596 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4597 last_mouse_glyph_frame
= frame
;
4605 /************************************************************************
4607 ************************************************************************/
4609 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4612 redo_mouse_highlight ()
4614 if (!NILP (last_mouse_motion_frame
)
4615 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4616 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4617 last_mouse_motion_position
.h
,
4618 last_mouse_motion_position
.v
);
4622 static struct frame
*
4623 mac_focus_frame (dpyinfo
)
4624 struct mac_display_info
*dpyinfo
;
4626 if (dpyinfo
->x_focus_frame
)
4627 return dpyinfo
->x_focus_frame
;
4629 /* Mac version may get events, such as a menu bar click, even when
4630 all the frames are invisible. In this case, we regard the
4631 event came to the selected frame. */
4632 return SELECTED_FRAME ();
4636 /* Return the current position of the mouse.
4637 *FP should be a frame which indicates which display to ask about.
4639 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4640 and *PART to the frame, window, and scroll bar part that the mouse
4641 is over. Set *X and *Y to the portion and whole of the mouse's
4642 position on the scroll bar.
4644 If the mouse movement started elsewhere, set *FP to the frame the
4645 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4648 Set *TIME to the server time-stamp for the time at which the mouse
4649 was at this position.
4651 Don't store anything if we don't have a valid set of values to report.
4653 This clears the mouse_moved flag, so we can wait for the next mouse
4657 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4660 Lisp_Object
*bar_window
;
4661 enum scroll_bar_part
*part
;
4663 unsigned long *time
;
4669 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4670 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4673 Lisp_Object frame
, tail
;
4675 /* Clear the mouse-moved flag for every frame on this display. */
4676 FOR_EACH_FRAME (tail
, frame
)
4677 XFRAME (frame
)->mouse_moved
= 0;
4679 last_mouse_scroll_bar
= Qnil
;
4681 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4682 && FRAME_LIVE_P (last_mouse_frame
))
4683 f1
= last_mouse_frame
;
4685 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4689 /* Ok, we found a frame. Store all the values.
4690 last_mouse_glyph is a rectangle used to reduce the
4691 generation of mouse events. To not miss any motion
4692 events, we must divide the frame into rectangles of the
4693 size of the smallest character that could be displayed
4694 on it, i.e. into the same rectangles that matrices on
4695 the frame are divided into. */
4698 #if TARGET_API_MAC_CARBON
4699 GetGlobalMouse (&mouse_pos
);
4700 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4701 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4703 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4704 GetMouse (&mouse_pos
);
4706 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4708 last_mouse_glyph_frame
= f1
;
4713 XSETINT (*x
, mouse_pos
.h
);
4714 XSETINT (*y
, mouse_pos
.v
);
4715 *time
= last_mouse_movement_time
;
4723 /************************************************************************
4725 ************************************************************************/
4727 #ifdef USE_TOOLKIT_SCROLL_BARS
4729 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4730 static OSStatus install_scroll_bar_timer
P_ ((void));
4731 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4732 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4733 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4734 struct input_event
*));
4735 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4737 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4738 ControlPartCode
, Point
,
4739 struct input_event
*));
4740 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4741 struct input_event
*));
4742 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4743 Point
, struct input_event
*));
4744 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4747 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4749 static int last_scroll_bar_part
;
4751 static EventLoopTimerRef scroll_bar_timer
;
4753 static int scroll_bar_timer_event_posted_p
;
4755 #define SCROLL_BAR_FIRST_DELAY 0.5
4756 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4759 scroll_bar_timer_callback (timer
, data
)
4760 EventLoopTimerRef timer
;
4765 err
= mac_post_mouse_moved_event ();
4767 scroll_bar_timer_event_posted_p
= 1;
4771 install_scroll_bar_timer ()
4773 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4775 if (scroll_bar_timer_callbackUPP
== NULL
)
4776 scroll_bar_timer_callbackUPP
=
4777 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4779 if (scroll_bar_timer
== NULL
)
4780 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4781 kEventDurationForever as delays. */
4783 InstallEventLoopTimer (GetCurrentEventLoop (),
4784 kEventDurationForever
, kEventDurationForever
,
4785 scroll_bar_timer_callbackUPP
, NULL
,
4790 set_scroll_bar_timer (delay
)
4791 EventTimerInterval delay
;
4793 if (scroll_bar_timer
== NULL
)
4794 install_scroll_bar_timer ();
4796 scroll_bar_timer_event_posted_p
= 0;
4798 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4802 control_part_code_to_scroll_bar_part (part_code
)
4803 ControlPartCode part_code
;
4807 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4808 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4809 case kControlPageUpPart
: return scroll_bar_above_handle
;
4810 case kControlPageDownPart
: return scroll_bar_below_handle
;
4811 case kControlIndicatorPart
: return scroll_bar_handle
;
4818 construct_scroll_bar_click (bar
, part
, bufp
)
4819 struct scroll_bar
*bar
;
4821 struct input_event
*bufp
;
4823 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4824 bufp
->frame_or_window
= bar
->window
;
4828 XSETINT (bufp
->x
, 0);
4829 XSETINT (bufp
->y
, 0);
4830 bufp
->modifiers
= 0;
4834 get_control_part_bounds (ch
, part_code
, rect
)
4836 ControlPartCode part_code
;
4839 RgnHandle region
= NewRgn ();
4842 err
= GetControlRegion (ch
, part_code
, region
);
4844 GetRegionBounds (region
, rect
);
4845 DisposeRgn (region
);
4851 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4852 struct scroll_bar
*bar
;
4853 ControlPartCode part_code
;
4855 struct input_event
*bufp
;
4857 int part
= control_part_code_to_scroll_bar_part (part_code
);
4862 if (part
!= scroll_bar_handle
)
4864 construct_scroll_bar_click (bar
, part
, bufp
);
4865 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4866 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4867 bar
->dragging
= Qnil
;
4873 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4874 kControlIndicatorPart
, &r
);
4875 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4878 last_scroll_bar_part
= part
;
4879 tracked_scroll_bar
= bar
;
4883 x_scroll_bar_handle_release (bar
, bufp
)
4884 struct scroll_bar
*bar
;
4885 struct input_event
*bufp
;
4887 if (last_scroll_bar_part
!= scroll_bar_handle
4888 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4889 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4891 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4892 set_scroll_bar_timer (kEventDurationForever
);
4894 last_scroll_bar_part
= -1;
4895 bar
->dragging
= Qnil
;
4896 tracked_scroll_bar
= NULL
;
4900 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4902 struct scroll_bar
*bar
;
4904 struct input_event
*bufp
;
4906 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4908 if (last_scroll_bar_part
== scroll_bar_handle
)
4913 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4914 kControlIndicatorPart
, &r
);
4916 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4917 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4919 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4920 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4924 if (top
> top_range
)
4927 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4928 XSETINT (bufp
->x
, top
);
4929 XSETINT (bufp
->y
, top_range
);
4933 ControlPartCode part_code
;
4934 int unhilite_p
= 0, part
;
4936 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4940 part
= control_part_code_to_scroll_bar_part (part_code
);
4942 switch (last_scroll_bar_part
)
4944 case scroll_bar_above_handle
:
4945 case scroll_bar_below_handle
:
4946 if (part
!= scroll_bar_above_handle
4947 && part
!= scroll_bar_below_handle
)
4951 case scroll_bar_up_arrow
:
4952 case scroll_bar_down_arrow
:
4953 if (part
!= scroll_bar_up_arrow
4954 && part
!= scroll_bar_down_arrow
)
4961 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4962 else if (part
!= last_scroll_bar_part
4963 || scroll_bar_timer_event_posted_p
)
4965 construct_scroll_bar_click (bar
, part
, bufp
);
4966 last_scroll_bar_part
= part
;
4967 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4968 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4973 /* Set the thumb size and position of scroll bar BAR. We are currently
4974 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4977 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4978 struct scroll_bar
*bar
;
4979 int portion
, position
, whole
;
4981 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4982 int value
, viewsize
, maximum
;
4984 if (XINT (bar
->track_height
) == 0)
4987 if (whole
<= portion
)
4988 value
= 0, viewsize
= 1, maximum
= 0;
4993 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4994 scale
= (float) maximum
/ (whole
- portion
);
4995 value
= position
* scale
+ 0.5f
;
4996 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
5001 if (GetControlViewSize (ch
) != viewsize
5002 || GetControl32BitValue (ch
) != value
5003 || GetControl32BitMaximum (ch
) != maximum
)
5005 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5006 SetControlVisibility (ch
, false, false);
5008 SetControl32BitMaximum (ch
, maximum
);
5009 SetControl32BitValue (ch
, value
);
5010 SetControlViewSize (ch
, viewsize
);
5012 SetControlVisibility (ch
, true, true);
5018 #endif /* USE_TOOLKIT_SCROLL_BARS */
5022 /************************************************************************
5023 Scroll bars, general
5024 ************************************************************************/
5026 /* Create a scroll bar and return the scroll bar vector for it. W is
5027 the Emacs window on which to create the scroll bar. TOP, LEFT,
5028 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5031 static struct scroll_bar
*
5032 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5034 int top
, left
, width
, height
, disp_top
, disp_height
;
5036 struct frame
*f
= XFRAME (w
->frame
);
5037 struct scroll_bar
*bar
5038 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5046 r
.right
= left
+ width
;
5047 r
.bottom
= disp_top
+ disp_height
;
5050 mac_prepare_for_quickdraw (f
);
5052 #if TARGET_API_MAC_CARBON
5053 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5054 #ifdef USE_TOOLKIT_SCROLL_BARS
5057 width
< disp_height
,
5059 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5061 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5062 0, 0, 0, scrollBarProc
, (long) bar
);
5064 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5066 XSETWINDOW (bar
->window
, w
);
5067 XSETINT (bar
->top
, top
);
5068 XSETINT (bar
->left
, left
);
5069 XSETINT (bar
->width
, width
);
5070 XSETINT (bar
->height
, height
);
5071 XSETINT (bar
->start
, 0);
5072 XSETINT (bar
->end
, 0);
5073 bar
->dragging
= Qnil
;
5075 bar
->fringe_extended_p
= Qnil
;
5077 bar
->redraw_needed_p
= Qnil
;
5078 #ifdef USE_TOOLKIT_SCROLL_BARS
5079 bar
->track_top
= Qnil
;
5080 bar
->track_height
= Qnil
;
5081 bar
->min_handle
= Qnil
;
5084 /* Add bar to its frame's list of scroll bars. */
5085 bar
->next
= FRAME_SCROLL_BARS (f
);
5087 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5088 if (!NILP (bar
->next
))
5089 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5096 /* Draw BAR's handle in the proper position.
5098 If the handle is already drawn from START to END, don't bother
5099 redrawing it, unless REBUILD is non-zero; in that case, always
5100 redraw it. (REBUILD is handy for drawing the handle after expose
5103 Normally, we want to constrain the start and end of the handle to
5104 fit inside its rectangle, but if the user is dragging the scroll
5105 bar handle, we want to let them drag it down all the way, so that
5106 the bar's top is as far down as it goes; otherwise, there's no way
5107 to move to the very end of the buffer. */
5109 #ifndef USE_TOOLKIT_SCROLL_BARS
5112 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5113 struct scroll_bar
*bar
;
5117 int dragging
= ! NILP (bar
->dragging
);
5118 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5119 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5120 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5121 int length
= end
- start
;
5123 /* If the display is already accurate, do nothing. */
5125 && start
== XINT (bar
->start
)
5126 && end
== XINT (bar
->end
))
5131 /* Make sure the values are reasonable, and try to preserve the
5132 distance between start and end. */
5135 else if (start
> top_range
)
5137 end
= start
+ length
;
5141 else if (end
> top_range
&& ! dragging
)
5144 /* Store the adjusted setting in the scroll bar. */
5145 XSETINT (bar
->start
, start
);
5146 XSETINT (bar
->end
, end
);
5148 /* Clip the end position, just for display. */
5149 if (end
> top_range
)
5152 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5153 top positions, to make sure the handle is always at least that
5154 many pixels tall. */
5155 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5157 SetControlMinimum (ch
, 0);
5158 /* Don't inadvertently activate deactivated scroll bars */
5159 if (GetControlMaximum (ch
) != -1)
5160 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5162 SetControlValue (ch
, start
);
5163 #if TARGET_API_MAC_CARBON
5164 SetControlViewSize (ch
, end
- start
);
5170 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5172 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5176 x_scroll_bar_remove (bar
)
5177 struct scroll_bar
*bar
;
5179 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5184 mac_prepare_for_quickdraw (f
);
5186 /* Destroy the Mac scroll bar control */
5187 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5189 /* Disassociate this scroll bar from its window. */
5190 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5196 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5197 that we are displaying PORTION characters out of a total of WHOLE
5198 characters, starting at POSITION. If WINDOW has no scroll bar,
5202 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5204 int portion
, whole
, position
;
5206 struct frame
*f
= XFRAME (w
->frame
);
5207 struct scroll_bar
*bar
;
5208 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5209 int window_y
, window_height
;
5211 int fringe_extended_p
;
5214 /* Get window dimensions. */
5215 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5217 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5218 height
= window_height
;
5220 /* Compute the left edge of the scroll bar area. */
5221 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5223 /* Compute the width of the scroll bar which might be less than
5224 the width of the area reserved for the scroll bar. */
5225 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5226 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5230 /* Compute the left edge of the scroll bar. */
5231 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5232 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5234 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5236 /* Adjustments according to Inside Macintosh to make it look nice */
5238 disp_height
= height
;
5245 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5251 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5256 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5257 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5258 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5259 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5260 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5262 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5263 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5264 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5265 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5268 /* Does the scroll bar exist yet? */
5269 if (NILP (w
->vertical_scroll_bar
))
5273 if (fringe_extended_p
)
5274 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5277 mac_clear_area (f
, left
, top
, width
, height
);
5279 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5281 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5285 /* It may just need to be moved and resized. */
5288 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5289 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5293 /* If already correctly positioned, do nothing. */
5294 if (XINT (bar
->left
) == sb_left
5295 && XINT (bar
->top
) == top
5296 && XINT (bar
->width
) == sb_width
5297 && XINT (bar
->height
) == height
5299 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5303 if (!NILP (bar
->redraw_needed_p
))
5306 mac_prepare_for_quickdraw (f
);
5308 Draw1Control (SCROLL_BAR_CONTROL_REF (bar
));
5313 /* Since toolkit scroll bars are smaller than the space reserved
5314 for them on the frame, we have to clear "under" them. */
5316 if (fringe_extended_p
)
5317 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5320 mac_clear_area (f
, left
, top
, width
, height
);
5323 mac_prepare_for_quickdraw (f
);
5326 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5327 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5329 #ifndef USE_TOOLKIT_SCROLL_BARS
5330 if (sb_width
< disp_height
)
5334 /* Remember new settings. */
5335 XSETINT (bar
->left
, sb_left
);
5336 XSETINT (bar
->top
, top
);
5337 XSETINT (bar
->width
, sb_width
);
5338 XSETINT (bar
->height
, height
);
5339 #ifdef USE_TOOLKIT_SCROLL_BARS
5340 bar
->track_top
= Qnil
;
5341 bar
->track_height
= Qnil
;
5342 bar
->min_handle
= Qnil
;
5350 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5352 bar
->redraw_needed_p
= Qnil
;
5354 #ifdef USE_TOOLKIT_SCROLL_BARS
5355 if (NILP (bar
->track_top
))
5357 if (sb_width
>= disp_height
5359 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5363 XSETINT (bar
->track_top
, 0);
5364 XSETINT (bar
->track_height
, 0);
5365 XSETINT (bar
->min_handle
, 0);
5369 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5374 SetControl32BitMinimum (ch
, 0);
5375 SetControl32BitMaximum (ch
, 1 << 30);
5376 SetControlViewSize (ch
, 1);
5378 /* Move the scroll bar thumb to the top. */
5379 SetControl32BitValue (ch
, 0);
5380 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5382 /* Move the scroll bar thumb to the bottom. */
5383 SetControl32BitValue (ch
, 1 << 30);
5384 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5386 UnionRect (&r0
, &r1
, &r0
);
5387 XSETINT (bar
->track_top
, r0
.top
);
5388 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5389 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5391 /* Don't show the scroll bar if its height is not enough to
5392 display the scroll bar thumb. */
5393 if (r0
.bottom
- r0
.top
> 0)
5400 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5401 #else /* not USE_TOOLKIT_SCROLL_BARS */
5402 /* Set the scroll bar's current state, unless we're currently being
5404 if (NILP (bar
->dragging
))
5406 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5409 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5412 int start
= ((double) position
* top_range
) / whole
;
5413 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5414 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5417 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5421 /* The following three hooks are used when we're doing a thorough
5422 redisplay of the frame. We don't explicitly know which scroll bars
5423 are going to be deleted, because keeping track of when windows go
5424 away is a real pain - "Can you say set-window-configuration, boys
5425 and girls?" Instead, we just assert at the beginning of redisplay
5426 that *all* scroll bars are to be removed, and then save a scroll bar
5427 from the fiery pit when we actually redisplay its window. */
5429 /* Arrange for all scroll bars on FRAME to be removed at the next call
5430 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5431 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5434 XTcondemn_scroll_bars (frame
)
5437 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5438 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5441 bar
= FRAME_SCROLL_BARS (frame
);
5442 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5443 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5444 XSCROLL_BAR (bar
)->prev
= Qnil
;
5445 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5446 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5447 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5452 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5453 Note that WINDOW isn't necessarily condemned at all. */
5456 XTredeem_scroll_bar (window
)
5457 struct window
*window
;
5459 struct scroll_bar
*bar
;
5462 /* We can't redeem this window's scroll bar if it doesn't have one. */
5463 if (NILP (window
->vertical_scroll_bar
))
5466 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5468 /* Unlink it from the condemned list. */
5469 f
= XFRAME (WINDOW_FRAME (window
));
5470 if (NILP (bar
->prev
))
5472 /* If the prev pointer is nil, it must be the first in one of
5474 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5475 /* It's not condemned. Everything's fine. */
5477 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5478 window
->vertical_scroll_bar
))
5479 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5481 /* If its prev pointer is nil, it must be at the front of
5482 one or the other! */
5486 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5488 if (! NILP (bar
->next
))
5489 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5491 bar
->next
= FRAME_SCROLL_BARS (f
);
5493 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5494 if (! NILP (bar
->next
))
5495 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5498 /* Remove all scroll bars on FRAME that haven't been saved since the
5499 last call to `*condemn_scroll_bars_hook'. */
5502 XTjudge_scroll_bars (f
)
5505 Lisp_Object bar
, next
;
5507 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5509 /* Clear out the condemned list now so we won't try to process any
5510 more events on the hapless scroll bars. */
5511 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5513 for (; ! NILP (bar
); bar
= next
)
5515 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5517 x_scroll_bar_remove (b
);
5520 b
->next
= b
->prev
= Qnil
;
5523 /* Now there should be no references to the condemned scroll bars,
5524 and they should get garbage-collected. */
5528 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5529 is set to something other than NO_EVENT, it is enqueued.
5531 This may be called from a signal handler, so we have to ignore GC
5535 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5536 struct scroll_bar
*bar
;
5537 ControlPartCode part_code
;
5538 const EventRecord
*er
;
5539 struct input_event
*bufp
;
5541 int win_y
, top_range
;
5543 if (! GC_WINDOWP (bar
->window
))
5546 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5547 bufp
->frame_or_window
= bar
->window
;
5550 bar
->dragging
= Qnil
;
5554 case kControlUpButtonPart
:
5555 bufp
->part
= scroll_bar_up_arrow
;
5557 case kControlDownButtonPart
:
5558 bufp
->part
= scroll_bar_down_arrow
;
5560 case kControlPageUpPart
:
5561 bufp
->part
= scroll_bar_above_handle
;
5563 case kControlPageDownPart
:
5564 bufp
->part
= scroll_bar_below_handle
;
5566 #if TARGET_API_MAC_CARBON
5569 case kControlIndicatorPart
:
5571 if (er
->what
== mouseDown
)
5572 bar
->dragging
= make_number (0);
5573 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5574 bufp
->part
= scroll_bar_handle
;
5578 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5579 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5581 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5585 if (! NILP (bar
->dragging
))
5586 win_y
-= XINT (bar
->dragging
);
5590 if (win_y
> top_range
)
5593 XSETINT (bufp
->x
, win_y
);
5594 XSETINT (bufp
->y
, top_range
);
5597 #ifndef USE_TOOLKIT_SCROLL_BARS
5599 /* Handle some mouse motion while someone is dragging the scroll bar.
5601 This may be called from a signal handler, so we have to ignore GC
5605 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5606 struct scroll_bar
*bar
;
5610 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5612 last_mouse_movement_time
= t
;
5615 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5617 /* If we're dragging the bar, display it. */
5618 if (! GC_NILP (bar
->dragging
))
5620 /* Where should the handle be now? */
5621 int new_start
= y_pos
- 24;
5623 if (new_start
!= XINT (bar
->start
))
5625 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5627 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5632 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5634 /* Return information to the user about the current position of the mouse
5635 on the scroll bar. */
5638 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5640 Lisp_Object
*bar_window
;
5641 enum scroll_bar_part
*part
;
5643 unsigned long *time
;
5645 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5646 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5647 #if TARGET_API_MAC_CARBON
5648 WindowRef wp
= GetControlOwner (ch
);
5650 WindowRef wp
= (*ch
)->contrlOwner
;
5653 struct frame
*f
= mac_window_to_frame (wp
);
5654 int win_y
, top_range
;
5656 #if TARGET_API_MAC_CARBON
5657 GetGlobalMouse (&mouse_pos
);
5658 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5659 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5661 SetPortWindowPort (wp
);
5662 GetMouse (&mouse_pos
);
5665 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5666 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5668 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5672 if (! NILP (bar
->dragging
))
5673 win_y
-= XINT (bar
->dragging
);
5677 if (win_y
> top_range
)
5681 *bar_window
= bar
->window
;
5683 if (! NILP (bar
->dragging
))
5684 *part
= scroll_bar_handle
;
5685 else if (win_y
< XINT (bar
->start
))
5686 *part
= scroll_bar_above_handle
;
5687 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5688 *part
= scroll_bar_handle
;
5690 *part
= scroll_bar_below_handle
;
5692 XSETINT (*x
, win_y
);
5693 XSETINT (*y
, top_range
);
5696 last_mouse_scroll_bar
= Qnil
;
5698 *time
= last_mouse_movement_time
;
5702 /* The screen has been cleared so we may have changed foreground or
5703 background colors, and the scroll bars may need to be redrawn.
5704 Clear out the scroll bars, and ask for expose events, so we can
5708 x_scroll_bar_clear (f
)
5713 /* We can have scroll bars even if this is 0,
5714 if we just turned off scroll bar mode.
5715 But in that case we should not clear them. */
5716 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5717 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5718 bar
= XSCROLL_BAR (bar
)->next
)
5719 XSCROLL_BAR (bar
)->redraw_needed_p
= Qt
;
5723 /***********************************************************************
5725 ***********************************************************************/
5728 /* In identifiers such as function/variable names, Emacs tool bar is
5729 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5731 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5732 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5734 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5735 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5736 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5737 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5738 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5739 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5740 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5742 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5743 static void mac_handle_origin_change
P_ ((struct frame
*));
5744 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5748 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5755 mac_get_window_bounds (f
, &inner
, &outer
);
5757 switch (win_gravity
)
5759 case NorthWestGravity
:
5761 case SouthWestGravity
:
5762 left
+= inner
.left
- outer
.left
;
5768 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5771 case NorthEastGravity
:
5773 case SouthEastGravity
:
5774 left
+= inner
.right
- outer
.right
;
5778 switch (win_gravity
)
5780 case NorthWestGravity
:
5782 case NorthEastGravity
:
5783 top
+= inner
.top
- outer
.top
;
5789 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5792 case SouthWestGravity
:
5794 case SouthEastGravity
:
5795 top
+= inner
.bottom
- outer
.bottom
;
5799 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5803 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5810 mac_get_window_bounds (f
, &inner
, &outer
);
5812 switch (win_gravity
)
5814 case NorthWestGravity
:
5816 case SouthWestGravity
:
5823 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5824 - (inner
.right
- inner
.left
)) / 2;
5827 case NorthEastGravity
:
5829 case SouthEastGravity
:
5830 *left
= outer
.right
- (inner
.right
- inner
.left
);
5834 switch (win_gravity
)
5836 case NorthWestGravity
:
5838 case NorthEastGravity
:
5845 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5846 - (inner
.bottom
- inner
.top
)) / 2;
5849 case SouthWestGravity
:
5851 case SouthEastGravity
:
5852 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5858 mac_handle_toolbar_event (next_handler
, event
, data
)
5859 EventHandlerCallRef next_handler
;
5863 OSStatus err
, result
= eventNotHandledErr
;
5865 switch (GetEventKind (event
))
5867 case kEventToolbarGetDefaultIdentifiers
:
5871 case kEventToolbarGetAllowedIdentifiers
:
5873 CFMutableArrayRef array
;
5875 GetEventParameter (event
, kEventParamMutableArray
,
5876 typeCFMutableArrayRef
, NULL
,
5877 sizeof (CFMutableArrayRef
), NULL
, &array
);
5878 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5883 case kEventToolbarCreateItemWithIdentifier
:
5885 CFStringRef identifier
;
5886 HIToolbarItemRef item
= NULL
;
5888 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
5889 typeCFStringRef
, NULL
,
5890 sizeof (CFStringRef
), NULL
, &identifier
);
5892 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
5893 == kCFCompareEqualTo
)
5894 HIToolbarItemCreate (identifier
,
5895 kHIToolbarItemAllowDuplicates
5896 | kHIToolbarItemCantBeRemoved
, &item
);
5900 SetEventParameter (event
, kEventParamToolbarItem
,
5901 typeHIToolbarItemRef
,
5902 sizeof (HIToolbarItemRef
), &item
);
5916 mac_image_spec_to_cg_image (f
, image
)
5920 if (!valid_image_p (image
))
5924 int img_id
= lookup_image (f
, image
);
5925 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
5927 prepare_image_for_display (f
, img
);
5929 return img
->data
.ptr_val
;
5933 /* Create a tool bar for frame F. */
5936 mac_create_frame_tool_bar (f
)
5940 HIToolbarRef toolbar
;
5942 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
5946 static const EventTypeSpec specs
[] =
5947 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
5948 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
5949 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
5951 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
5952 mac_handle_toolbar_event
,
5953 GetEventTypeCount (specs
), specs
,
5958 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
5961 static const EventTypeSpec specs
[] =
5962 {{kEventClassCommand
, kEventCommandProcess
}};
5964 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
5965 mac_handle_toolbar_command_event
,
5966 GetEventTypeCount (specs
),
5970 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
5973 CFRelease (toolbar
);
5978 /* Update the tool bar for frame F. Add new buttons and remove old. */
5981 update_frame_tool_bar (f
)
5984 HIToolbarRef toolbar
= NULL
;
5986 CFArrayRef old_items
= NULL
;
5988 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
5989 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5993 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5994 if (toolbar
== NULL
)
5996 mac_create_frame_tool_bar (f
);
5997 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5998 if (toolbar
== NULL
)
6000 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6001 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
6004 HIToolbarCopyItems (toolbar
, &old_items
);
6005 if (old_items
== NULL
)
6008 old_count
= CFArrayGetCount (old_items
);
6010 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
6012 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
6014 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
6015 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
6018 CGImageRef cg_image
;
6020 HIToolbarItemRef item
;
6022 /* If image is a vector, choose the image according to the
6024 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6025 if (VECTORP (image
))
6029 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6030 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6033 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6034 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6036 xassert (ASIZE (image
) >= idx
);
6037 image
= AREF (image
, idx
);
6042 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6043 /* Ignore invalid image specifications. */
6044 if (cg_image
== NULL
)
6047 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6051 if (pos
< old_count
)
6053 CGImageRef old_cg_image
= NULL
;
6054 CFStringRef old_label
= NULL
;
6055 Boolean old_enabled_p
;
6057 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6059 HIToolbarItemCopyImage (item
, &old_cg_image
);
6060 if (cg_image
!= old_cg_image
)
6061 HIToolbarItemSetImage (item
, cg_image
);
6062 CGImageRelease (old_cg_image
);
6064 HIToolbarItemCopyLabel (item
, &old_label
);
6065 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6066 HIToolbarItemSetLabel (item
, label
);
6067 CFRelease (old_label
);
6069 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6070 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6071 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6076 HIToolbarCreateItemWithIdentifier (toolbar
,
6077 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6081 HIToolbarItemSetImage (item
, cg_image
);
6082 HIToolbarItemSetLabel (item
, label
);
6083 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6084 HIToolbarAppendItem (toolbar
, item
);
6092 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6097 CFRelease (old_items
);
6099 while (pos
< old_count
)
6100 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6102 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6103 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6104 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6105 toolbar visibility change. */
6106 mac_handle_origin_change (f
);
6107 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6109 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6110 /* If the title bar is completely outside the screen, adjust the
6112 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6113 kWindowConstrainMoveRegardlessOfFit
6114 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6115 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6122 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6123 doesn't deallocate the resources. */
6126 free_frame_tool_bar (f
)
6129 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6131 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6134 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6135 (NILP (find_symbol_value
6136 (intern ("frame-notice-user-settings")))
6137 && f
== mac_focus_frame (dpyinfo
)));
6138 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6139 on toolbar visibility change. */
6140 mac_handle_origin_change (f
);
6146 mac_tool_bar_note_mouse_movement (f
, event
)
6151 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6154 WindowPartCode part_code
;
6155 HIViewRef item_view
;
6158 mouse_down_p
= (dpyinfo
->grabbed
6159 && f
== last_mouse_frame
6160 && FRAME_LIVE_P (f
));
6164 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
, NULL
,
6165 sizeof (WindowRef
), NULL
, &window
);
6166 if (err
!= noErr
|| window
!= FRAME_MAC_WINDOW (f
))
6169 err
= GetEventParameter (event
, kEventParamWindowPartCode
,
6170 typeWindowPartCode
, NULL
,
6171 sizeof (WindowPartCode
), NULL
, &part_code
);
6172 if (err
!= noErr
|| part_code
!= inStructure
)
6175 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window
), event
, &item_view
);
6176 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6177 toolbar item view seems to have the same command ID with that of
6178 the toolbar item. */
6180 err
= GetControlCommandID (item_view
, &command_id
);
6181 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6183 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6185 if (i
< f
->n_tool_bar_items
)
6188 HIViewRef content_view
;
6190 err
= HIViewGetBounds (item_view
, &bounds
);
6192 err
= HIViewFindByID (HIViewGetRoot (window
),
6193 kHIViewWindowContentID
, &content_view
);
6195 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6197 SetRect (&last_mouse_glyph
,
6198 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6199 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6201 help_echo_object
= help_echo_window
= Qnil
;
6203 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6204 if (NILP (help_echo_string
))
6205 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6211 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6212 EventHandlerCallRef next_handler
;
6216 OSStatus err
, result
= eventNotHandledErr
;
6217 struct frame
*f
= (struct frame
*) data
;
6220 err
= GetEventParameter (event
, kEventParamDirectObject
,
6221 typeHICommand
, NULL
,
6222 sizeof (HICommand
), NULL
, &command
);
6226 switch (GetEventKind (event
))
6228 case kEventCommandProcess
:
6229 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6230 result
= CallNextEventHandler (next_handler
, event
);
6233 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6235 if (i
< f
->n_tool_bar_items
6236 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6239 struct input_event buf
;
6243 XSETFRAME (frame
, f
);
6244 buf
.kind
= TOOL_BAR_EVENT
;
6245 buf
.frame_or_window
= frame
;
6247 kbd_buffer_store_event (&buf
);
6249 buf
.kind
= TOOL_BAR_EVENT
;
6250 buf
.frame_or_window
= frame
;
6251 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6252 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6253 kbd_buffer_store_event (&buf
);
6267 #endif /* USE_MAC_TOOLBAR */
6270 /***********************************************************************
6272 ***********************************************************************/
6274 /* Set clipping for output in glyph row ROW. W is the window in which
6275 we operate. GC is the graphics context to set clipping in.
6277 ROW may be a text row or, e.g., a mode line. Text rows must be
6278 clipped to the interior of the window dedicated to text display,
6279 mode lines must be clipped to the whole window. */
6282 x_clip_to_row (w
, row
, area
, gc
)
6284 struct glyph_row
*row
;
6288 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6290 int window_x
, window_y
, window_width
;
6292 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6294 clip_rect
.left
= window_x
;
6295 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6296 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6297 clip_rect
.right
= clip_rect
.left
+ window_width
;
6298 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6300 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6304 /* Draw a hollow box cursor on window W in glyph row ROW. */
6307 x_draw_hollow_cursor (w
, row
)
6309 struct glyph_row
*row
;
6311 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6312 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6313 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6316 struct glyph
*cursor_glyph
;
6319 /* Get the glyph the cursor is on. If we can't tell because
6320 the current matrix is invalid or such, give up. */
6321 cursor_glyph
= get_phys_cursor_glyph (w
);
6322 if (cursor_glyph
== NULL
)
6325 /* Compute frame-relative coordinates for phys cursor. */
6326 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6327 wd
= w
->phys_cursor_width
;
6329 /* The foreground of cursor_gc is typically the same as the normal
6330 background color, which can cause the cursor box to be invisible. */
6331 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6332 if (dpyinfo
->scratch_cursor_gc
)
6333 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6335 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6336 GCForeground
, &xgcv
);
6337 gc
= dpyinfo
->scratch_cursor_gc
;
6339 /* Set clipping, draw the rectangle, and reset clipping again. */
6340 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6341 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6342 mac_reset_clip_rectangles (dpy
, gc
);
6346 /* Draw a bar cursor on window W in glyph row ROW.
6348 Implementation note: One would like to draw a bar cursor with an
6349 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6350 Unfortunately, I didn't find a font yet that has this property set.
6354 x_draw_bar_cursor (w
, row
, width
, kind
)
6356 struct glyph_row
*row
;
6358 enum text_cursor_kinds kind
;
6360 struct frame
*f
= XFRAME (w
->frame
);
6361 struct glyph
*cursor_glyph
;
6363 /* If cursor is out of bounds, don't draw garbage. This can happen
6364 in mini-buffer windows when switching between echo area glyphs
6366 cursor_glyph
= get_phys_cursor_glyph (w
);
6367 if (cursor_glyph
== NULL
)
6370 /* If on an image, draw like a normal cursor. That's usually better
6371 visible than drawing a bar, esp. if the image is large so that
6372 the bar might not be in the window. */
6373 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6375 struct glyph_row
*row
;
6376 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6377 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6381 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6382 Window window
= FRAME_MAC_WINDOW (f
);
6383 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6384 unsigned long mask
= GCForeground
| GCBackground
;
6385 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6388 /* If the glyph's background equals the color we normally draw
6389 the bar cursor in, the bar cursor in its normal color is
6390 invisible. Use the glyph's foreground color instead in this
6391 case, on the assumption that the glyph's colors are chosen so
6392 that the glyph is legible. */
6393 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6394 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6396 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6399 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6402 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6403 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6407 width
= FRAME_CURSOR_WIDTH (f
);
6408 width
= min (cursor_glyph
->pixel_width
, width
);
6410 w
->phys_cursor_width
= width
;
6411 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6413 if (kind
== BAR_CURSOR
)
6414 mac_fill_rectangle (f
, gc
,
6415 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6416 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6417 width
, row
->height
);
6419 mac_fill_rectangle (f
, gc
,
6420 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6421 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6422 row
->height
- width
),
6423 cursor_glyph
->pixel_width
,
6426 mac_reset_clip_rectangles (dpy
, gc
);
6431 /* RIF: Define cursor CURSOR on frame F. */
6434 mac_define_frame_cursor (f
, cursor
)
6438 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6440 if (dpyinfo
->x_focus_frame
== f
)
6441 SetThemeCursor (cursor
);
6445 /* RIF: Clear area on frame F. */
6448 mac_clear_frame_area (f
, x
, y
, width
, height
)
6450 int x
, y
, width
, height
;
6452 mac_clear_area (f
, x
, y
, width
, height
);
6456 /* RIF: Draw cursor on window W. */
6459 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6461 struct glyph_row
*glyph_row
;
6463 int cursor_type
, cursor_width
;
6468 w
->phys_cursor_type
= cursor_type
;
6469 w
->phys_cursor_on_p
= 1;
6471 if (glyph_row
->exact_window_width_line_p
6472 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6474 glyph_row
->cursor_in_fringe_p
= 1;
6475 draw_fringe_bitmap (w
, glyph_row
, 0);
6478 switch (cursor_type
)
6480 case HOLLOW_BOX_CURSOR
:
6481 x_draw_hollow_cursor (w
, glyph_row
);
6484 case FILLED_BOX_CURSOR
:
6485 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6489 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6493 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6497 w
->phys_cursor_width
= 0;
6509 #if 0 /* MAC_TODO: no icon support yet. */
6511 x_bitmap_icon (f
, icon
)
6517 if (FRAME_W32_WINDOW (f
) == 0)
6521 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6522 else if (STRINGP (icon
))
6523 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6524 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6525 else if (SYMBOLP (icon
))
6529 if (EQ (icon
, intern ("application")))
6530 name
= (LPCTSTR
) IDI_APPLICATION
;
6531 else if (EQ (icon
, intern ("hand")))
6532 name
= (LPCTSTR
) IDI_HAND
;
6533 else if (EQ (icon
, intern ("question")))
6534 name
= (LPCTSTR
) IDI_QUESTION
;
6535 else if (EQ (icon
, intern ("exclamation")))
6536 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6537 else if (EQ (icon
, intern ("asterisk")))
6538 name
= (LPCTSTR
) IDI_ASTERISK
;
6539 else if (EQ (icon
, intern ("winlogo")))
6540 name
= (LPCTSTR
) IDI_WINLOGO
;
6544 hicon
= LoadIcon (NULL
, name
);
6552 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6557 #endif /* MAC_TODO */
6559 /************************************************************************
6561 ************************************************************************/
6563 /* Display Error Handling functions not used on W32. Listing them here
6564 helps diff stay in step when comparing w32term.c with xterm.c.
6566 x_error_catcher (display, error)
6567 x_catch_errors (dpy)
6568 x_catch_errors_unwind (old_val)
6569 x_check_errors (dpy, format)
6570 x_had_errors_p (dpy)
6571 x_clear_errors (dpy)
6572 x_uncatch_errors (dpy, count)
6574 x_connection_signal (signalnum)
6575 x_connection_closed (dpy, error_message)
6576 x_error_quitter (display, error)
6577 x_error_handler (display, error)
6578 x_io_error_quitter (display)
6583 /* Changing the font of the frame. */
6585 /* Give frame F the font named FONTNAME as its default font, and
6586 return the full name of that font. FONTNAME may be a wildcard
6587 pattern; in that case, we choose some font that fits the pattern.
6588 The return value shows which font we chose. */
6591 x_new_font (f
, fontname
)
6593 register char *fontname
;
6595 struct font_info
*fontp
6596 = FS_LOAD_FONT (f
, 0, fontname
, -1);
6601 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6602 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6603 FRAME_FONTSET (f
) = -1;
6605 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6606 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6607 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6609 compute_fringe_widths (f
, 1);
6611 /* Compute the scroll bar width in character columns. */
6612 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6614 int wid
= FRAME_COLUMN_WIDTH (f
);
6615 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6616 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6620 int wid
= FRAME_COLUMN_WIDTH (f
);
6621 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6624 /* Now make the frame display the given font. */
6625 if (FRAME_MAC_WINDOW (f
) != 0)
6627 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6629 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6631 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6634 /* Don't change the size of a tip frame; there's no point in
6635 doing it because it's done in Fx_show_tip, and it leads to
6636 problems because the tip frame has no widget. */
6637 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6638 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6641 return build_string (fontp
->full_name
);
6644 /* Give frame F the fontset named FONTSETNAME as its default font, and
6645 return the full name of that fontset. FONTSETNAME may be a wildcard
6646 pattern; in that case, we choose some fontset that fits the pattern.
6647 The return value shows which fontset we chose. */
6650 x_new_fontset (f
, fontsetname
)
6654 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
6660 if (FRAME_FONTSET (f
) == fontset
)
6661 /* This fontset is already set in frame F. There's nothing more
6663 return fontset_name (fontset
);
6665 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6667 if (!STRINGP (result
))
6668 /* Can't load ASCII font. */
6671 /* Since x_new_font doesn't update any fontset information, do it now. */
6672 FRAME_FONTSET (f
) = fontset
;
6674 return build_string (fontsetname
);
6678 /***********************************************************************
6679 TODO: W32 Input Methods
6680 ***********************************************************************/
6681 /* Listing missing functions from xterm.c helps diff stay in step.
6683 xim_destroy_callback (xim, client_data, call_data)
6684 xim_open_dpy (dpyinfo, resource_name)
6686 xim_instantiate_callback (display, client_data, call_data)
6687 xim_initialize (dpyinfo, resource_name)
6688 xim_close_dpy (dpyinfo)
6694 mac_get_window_bounds (f
, inner
, outer
)
6696 Rect
*inner
, *outer
;
6698 #if TARGET_API_MAC_CARBON
6699 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6700 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6701 #else /* not TARGET_API_MAC_CARBON */
6702 RgnHandle region
= NewRgn ();
6704 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6705 *inner
= (*region
)->rgnBBox
;
6706 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6707 *outer
= (*region
)->rgnBBox
;
6708 DisposeRgn (region
);
6709 #endif /* not TARGET_API_MAC_CARBON */
6713 mac_handle_origin_change (f
)
6716 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6720 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6722 int pixelwidth
, pixelheight
;
6726 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6727 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6729 if (cols
!= FRAME_COLS (f
)
6730 || rows
!= FRAME_LINES (f
)
6731 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6732 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6734 /* We pass 1 for DELAY since we can't run Lisp code inside of
6736 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6737 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6738 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6739 SET_FRAME_GARBAGED (f
);
6741 /* If cursor was outside the new size, mark it as off. */
6742 mark_window_cursors_off (XWINDOW (f
->root_window
));
6744 /* Clear out any recollection of where the mouse highlighting
6745 was, since it might be in a place that's outside the new
6746 frame size. Actually checking whether it is outside is a
6747 pain in the neck, so don't try--just let the highlighting be
6748 done afresh with new size. */
6749 cancel_mouse_face (f
);
6751 #if TARGET_API_MAC_CARBON
6752 if (f
->output_data
.mac
->hourglass_control
)
6755 mac_prepare_for_quickdraw (f
);
6757 MoveControl (f
->output_data
.mac
->hourglass_control
,
6758 pixelwidth
- HOURGLASS_WIDTH
, 0);
6765 /* Calculate the absolute position in frame F
6766 from its current recorded position values and gravity. */
6769 x_calc_absolute_position (f
)
6772 int width_diff
= 0, height_diff
= 0;
6773 int flags
= f
->size_hint_flags
;
6776 /* We have nothing to do if the current position
6777 is already for the top-left corner. */
6778 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6781 /* Find the offsets of the outside upper-left corner of
6782 the inner window, with respect to the outer window. */
6784 mac_get_window_bounds (f
, &inner
, &outer
);
6787 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6788 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6790 /* Treat negative positions as relative to the leftmost bottommost
6791 position that fits on the screen. */
6792 if (flags
& XNegative
)
6793 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6795 - FRAME_PIXEL_WIDTH (f
)
6798 if (flags
& YNegative
)
6799 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6801 - FRAME_PIXEL_HEIGHT (f
)
6804 /* The left_pos and top_pos
6805 are now relative to the top and left screen edges,
6806 so the flags should correspond. */
6807 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6810 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6811 to really change the position, and 0 when calling from
6812 x_make_frame_visible (in that case, XOFF and YOFF are the current
6813 position values). It is -1 when calling from x_set_frame_parameters,
6814 which means, do adjust for borders but don't change the gravity. */
6817 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6819 register int xoff
, yoff
;
6822 if (change_gravity
> 0)
6826 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6828 f
->size_hint_flags
|= XNegative
;
6830 f
->size_hint_flags
|= YNegative
;
6831 f
->win_gravity
= NorthWestGravity
;
6833 x_calc_absolute_position (f
);
6836 x_wm_set_size_hint (f
, (long) 0, 0);
6838 #if TARGET_API_MAC_CARBON
6839 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6840 /* If the title bar is completely outside the screen, adjust the
6842 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6843 kWindowConstrainMoveRegardlessOfFit
6844 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6845 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6846 mac_handle_origin_change (f
);
6849 Rect inner
, outer
, screen_rect
, dummy
;
6850 RgnHandle region
= NewRgn ();
6852 mac_get_window_bounds (f
, &inner
, &outer
);
6853 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6854 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6855 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6856 f
->top_pos
+ f
->y_pixels_diff
, false);
6858 /* If the title bar is completely outside the screen, adjust the
6859 position. The variable `outer' holds the title bar rectangle.
6860 The variable `inner' holds slightly smaller one than `outer',
6861 so that the calculation of overlapping may not become too
6863 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6864 outer
= (*region
)->rgnBBox
;
6865 DisposeRgn (region
);
6867 InsetRect (&inner
, 8, 8);
6868 screen_rect
= qd
.screenBits
.bounds
;
6869 screen_rect
.top
+= GetMBarHeight ();
6871 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6873 if (inner
.right
<= screen_rect
.left
)
6874 f
->left_pos
= screen_rect
.left
;
6875 else if (inner
.left
>= screen_rect
.right
)
6876 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6878 if (inner
.bottom
<= screen_rect
.top
)
6879 f
->top_pos
= screen_rect
.top
;
6880 else if (inner
.top
>= screen_rect
.bottom
)
6881 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6883 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6884 f
->top_pos
+ f
->y_pixels_diff
, false);
6892 /* Call this to change the size of frame F's x-window.
6893 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6894 for this size change and subsequent size changes.
6895 Otherwise we leave the window gravity unchanged. */
6898 x_set_window_size (f
, change_gravity
, cols
, rows
)
6903 int pixelwidth
, pixelheight
;
6907 check_frame_size (f
, &rows
, &cols
);
6908 f
->scroll_bar_actual_width
6909 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6911 compute_fringe_widths (f
, 0);
6913 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6914 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6916 f
->win_gravity
= NorthWestGravity
;
6917 x_wm_set_size_hint (f
, (long) 0, 0);
6919 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6921 #if TARGET_API_MAC_CARBON
6922 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6924 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6926 if (f
->output_data
.mac
->internal_border_width
6927 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6929 mac_clear_window (f
);
6930 f
->output_data
.mac
->internal_border_width
6931 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6934 SET_FRAME_GARBAGED (f
);
6939 /* Mouse warping. */
6941 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6944 x_set_mouse_position (f
, x
, y
)
6950 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6951 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6953 if (pix_x
< 0) pix_x
= 0;
6954 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6956 if (pix_y
< 0) pix_y
= 0;
6957 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6959 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6963 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6968 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
6969 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
6972 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
6975 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6978 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6979 0, 0, 0, 0, pix_x
, pix_y
);
6985 /* focus shifting, raising and lowering. */
6988 x_focus_on_frame (f
)
6991 #if 0 /* This proves to be unpleasant. */
6995 /* I don't think that the ICCCM allows programs to do things like this
6996 without the interaction of the window manager. Whatever you end up
6997 doing with this code, do it to x_unfocus_frame too. */
6998 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6999 RevertToPointerRoot
, CurrentTime
);
7009 /* Raise frame F. */
7015 if (f
->async_visible
)
7018 BringToFront (FRAME_MAC_WINDOW (f
));
7023 /* Lower frame F. */
7029 if (f
->async_visible
)
7032 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7038 XTframe_raise_lower (f
, raise_flag
)
7048 /* Change of visibility. */
7051 mac_handle_visibility_change (f
)
7054 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7055 int visible
= 0, iconified
= 0;
7056 struct input_event buf
;
7058 if (IsWindowVisible (wp
))
7060 if (IsWindowCollapsed (wp
))
7066 if (!f
->async_visible
&& visible
)
7070 /* wait_reading_process_output will notice this and update
7071 the frame's display structures. If we were made
7072 invisible, we should not set garbaged, because that stops
7073 redrawing on Update events. */
7074 SET_FRAME_GARBAGED (f
);
7077 buf
.kind
= DEICONIFY_EVENT
;
7078 XSETFRAME (buf
.frame_or_window
, f
);
7080 kbd_buffer_store_event (&buf
);
7082 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7083 /* Force a redisplay sooner or later to update the
7084 frame titles in case this is the second frame. */
7085 record_asynch_buffer_change ();
7087 else if (f
->async_visible
&& !visible
)
7091 buf
.kind
= ICONIFY_EVENT
;
7092 XSETFRAME (buf
.frame_or_window
, f
);
7094 kbd_buffer_store_event (&buf
);
7097 f
->async_visible
= visible
;
7098 f
->async_iconified
= iconified
;
7101 /* This tries to wait until the frame is really visible.
7102 However, if the window manager asks the user where to position
7103 the frame, this will return before the user finishes doing that.
7104 The frame will not actually be visible at that time,
7105 but it will become visible later when the window manager
7106 finishes with it. */
7109 x_make_frame_visible (f
)
7114 if (! FRAME_VISIBLE_P (f
))
7116 /* We test FRAME_GARBAGED_P here to make sure we don't
7117 call x_set_offset a second time
7118 if we get to x_make_frame_visible a second time
7119 before the window gets really visible. */
7120 if (! FRAME_ICONIFIED_P (f
)
7121 && ! f
->output_data
.mac
->asked_for_visible
)
7122 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7124 f
->output_data
.mac
->asked_for_visible
= 1;
7126 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7127 ShowWindow (FRAME_MAC_WINDOW (f
));
7130 XFlush (FRAME_MAC_DISPLAY (f
));
7132 /* Synchronize to ensure Emacs knows the frame is visible
7133 before we do anything else. We do this loop with input not blocked
7134 so that incoming events are handled. */
7139 /* This must come after we set COUNT. */
7142 XSETFRAME (frame
, f
);
7144 /* Wait until the frame is visible. Process X events until a
7145 MapNotify event has been seen, or until we think we won't get a
7146 MapNotify at all.. */
7147 for (count
= input_signal_count
+ 10;
7148 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7150 /* Force processing of queued events. */
7153 /* Machines that do polling rather than SIGIO have been
7154 observed to go into a busy-wait here. So we'll fake an
7155 alarm signal to let the handler know that there's something
7156 to be read. We used to raise a real alarm, but it seems
7157 that the handler isn't always enabled here. This is
7159 if (input_polling_used ())
7161 /* It could be confusing if a real alarm arrives while
7162 processing the fake one. Turn it off and let the
7163 handler reset it. */
7164 extern void poll_for_input_1
P_ ((void));
7165 int old_poll_suppress_count
= poll_suppress_count
;
7166 poll_suppress_count
= 1;
7167 poll_for_input_1 ();
7168 poll_suppress_count
= old_poll_suppress_count
;
7171 /* See if a MapNotify event has been processed. */
7172 FRAME_SAMPLE_VISIBILITY (f
);
7177 /* Change from mapped state to withdrawn state. */
7179 /* Make the frame visible (mapped and not iconified). */
7182 x_make_frame_invisible (f
)
7185 /* A deactivate event does not occur when the last visible frame is
7186 made invisible. So if we clear the highlight here, it will not
7187 be rehighlighted when it is made visible. */
7189 /* Don't keep the highlight on an invisible frame. */
7190 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7191 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7196 #if !TARGET_API_MAC_CARBON
7197 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7198 that the current position of the window is user-specified, rather than
7199 program-specified, so that when the window is mapped again, it will be
7200 placed at the same location, without forcing the user to position it
7201 by hand again (they have already done that once for this window.) */
7202 x_wm_set_size_hint (f
, (long) 0, 1);
7205 HideWindow (FRAME_MAC_WINDOW (f
));
7209 #if !TARGET_API_MAC_CARBON
7210 mac_handle_visibility_change (f
);
7214 /* Change window state from mapped to iconified. */
7222 /* A deactivate event does not occur when the last visible frame is
7223 iconified. So if we clear the highlight here, it will not be
7224 rehighlighted when it is deiconified. */
7226 /* Don't keep the highlight on an invisible frame. */
7227 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7228 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7231 if (f
->async_iconified
)
7236 FRAME_SAMPLE_VISIBILITY (f
);
7238 if (! FRAME_VISIBLE_P (f
))
7239 ShowWindow (FRAME_MAC_WINDOW (f
));
7241 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7246 error ("Can't notify window manager of iconification");
7248 #if !TARGET_API_MAC_CARBON
7249 mac_handle_visibility_change (f
);
7254 /* Free X resources of frame F. */
7257 x_free_frame_resources (f
)
7260 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7261 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7265 if (wp
!= tip_window
)
7266 remove_window_handler (wp
);
7269 mac_prepare_for_quickdraw (f
);
7272 if (wp
== tip_window
)
7273 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7274 closed' event. So we reset tip_window here. */
7277 free_frame_menubar (f
);
7279 if (FRAME_FACE_CACHE (f
))
7280 free_frame_faces (f
);
7284 if (FRAME_SIZE_HINTS (f
))
7285 xfree (FRAME_SIZE_HINTS (f
));
7287 xfree (f
->output_data
.mac
);
7288 f
->output_data
.mac
= NULL
;
7290 if (f
== dpyinfo
->x_focus_frame
)
7292 dpyinfo
->x_focus_frame
= 0;
7293 #if USE_MAC_FONT_PANEL
7294 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7297 if (f
== dpyinfo
->x_focus_event_frame
)
7298 dpyinfo
->x_focus_event_frame
= 0;
7299 if (f
== dpyinfo
->x_highlight_frame
)
7300 dpyinfo
->x_highlight_frame
= 0;
7302 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7304 dpyinfo
->mouse_face_beg_row
7305 = dpyinfo
->mouse_face_beg_col
= -1;
7306 dpyinfo
->mouse_face_end_row
7307 = dpyinfo
->mouse_face_end_col
= -1;
7308 dpyinfo
->mouse_face_window
= Qnil
;
7309 dpyinfo
->mouse_face_deferred_gc
= 0;
7310 dpyinfo
->mouse_face_mouse_frame
= 0;
7317 /* Destroy the X window of frame F. */
7320 x_destroy_window (f
)
7323 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7325 x_free_frame_resources (f
);
7327 dpyinfo
->reference_count
--;
7331 /* Setting window manager hints. */
7333 /* Set the normal size hints for the window manager, for frame F.
7334 FLAGS is the flags word to use--or 0 meaning preserve the flags
7335 that the window now has.
7336 If USER_POSITION is nonzero, we set the USPosition
7337 flag (this is useful when FLAGS is 0). */
7339 x_wm_set_size_hint (f
, flags
, user_position
)
7344 int base_width
, base_height
, width_inc
, height_inc
;
7345 int min_rows
= 0, min_cols
= 0;
7346 XSizeHints
*size_hints
;
7348 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7349 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7350 width_inc
= FRAME_COLUMN_WIDTH (f
);
7351 height_inc
= FRAME_LINE_HEIGHT (f
);
7353 check_frame_size (f
, &min_rows
, &min_cols
);
7355 size_hints
= FRAME_SIZE_HINTS (f
);
7356 if (size_hints
== NULL
)
7358 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7359 bzero (size_hints
, sizeof (XSizeHints
));
7362 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7363 size_hints
->width_inc
= width_inc
;
7364 size_hints
->height_inc
= height_inc
;
7365 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7366 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7367 size_hints
->base_width
= base_width
;
7368 size_hints
->base_height
= base_height
;
7371 size_hints
->flags
= flags
;
7372 else if (user_position
)
7374 size_hints
->flags
&= ~ PPosition
;
7375 size_hints
->flags
|= USPosition
;
7379 #if 0 /* MAC_TODO: hide application instead of iconify? */
7380 /* Used for IconicState or NormalState */
7383 x_wm_set_window_state (f
, state
)
7387 #ifdef USE_X_TOOLKIT
7390 XtSetArg (al
[0], XtNinitialState
, state
);
7391 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7392 #else /* not USE_X_TOOLKIT */
7393 Window window
= FRAME_X_WINDOW (f
);
7395 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7396 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7398 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7399 #endif /* not USE_X_TOOLKIT */
7403 x_wm_set_icon_pixmap (f
, pixmap_id
)
7409 #ifndef USE_X_TOOLKIT
7410 Window window
= FRAME_X_WINDOW (f
);
7415 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7416 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7420 /* It seems there is no way to turn off use of an icon pixmap.
7421 The following line does it, only if no icon has yet been created,
7422 for some window managers. But with mwm it crashes.
7423 Some people say it should clear the IconPixmapHint bit in this case,
7424 but that doesn't work, and the X consortium said it isn't the
7425 right thing at all. Since there is no way to win,
7426 best to explicitly give up. */
7428 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7434 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7438 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7439 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7442 #else /* not USE_X_TOOLKIT */
7444 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7445 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7447 #endif /* not USE_X_TOOLKIT */
7450 #endif /* MAC_TODO */
7453 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7457 #if 0 /* MAC_TODO: no icons on Mac */
7458 #ifdef USE_X_TOOLKIT
7459 Window window
= XtWindow (f
->output_data
.x
->widget
);
7461 Window window
= FRAME_X_WINDOW (f
);
7464 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7465 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7466 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7468 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7469 #endif /* MAC_TODO */
7473 /***********************************************************************
7475 ***********************************************************************/
7477 /* An XLFD pattern is divided into blocks delimited by '*'. This
7478 structure holds information for each block. */
7479 struct xlfdpat_block
7481 /* Length of the pattern string in this block. Non-zero except for
7482 the first and the last blocks. */
7485 /* Pattern string except the last character in this block. The last
7486 character is replaced with NUL in order to use it as a
7488 unsigned char *pattern
;
7490 /* Last character of the pattern string. Must not be '?'. */
7491 unsigned char last_char
;
7493 /* One of the tables for the Boyer-Moore string search. It
7494 specifies the number of positions to proceed for each character
7495 with which the match fails. */
7498 /* The skip value for the last character in the above `skip' is
7499 assigned to `infinity' in order to simplify a loop condition.
7500 The original value is saved here. */
7506 /* Normalized pattern string. "Normalized" means that capital
7507 letters are lowered, blocks are not empty except the first and
7508 the last ones, and trailing '?'s in a block that is not the last
7509 one are moved to the next one. The last character in each block
7510 is replaced with NUL. */
7513 /* Number of characters except '*'s and trailing '?'s in the
7514 normalized pattern string. */
7517 /* Number of trailing '?'s in the normalized pattern string. */
7518 int trailing_anychars
;
7520 /* Number of blocks and information for each block. The latter is
7521 NULL if the pattern is exact (no '*' or '?' in it). */
7523 struct xlfdpat_block
*blocks
;
7527 xlfdpat_destroy (pat
)
7528 struct xlfdpat
*pat
;
7535 xfree (pat
->blocks
);
7542 static struct xlfdpat
*
7543 xlfdpat_create (pattern
)
7544 const char *pattern
;
7546 struct xlfdpat
*pat
;
7547 int nblocks
, i
, skip
;
7548 unsigned char last_char
, *p
, *q
, *anychar_head
;
7549 const unsigned char *ptr
;
7550 struct xlfdpat_block
*blk
;
7552 pat
= xmalloc (sizeof (struct xlfdpat
));
7553 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7555 /* Normalize the pattern string and store it to `pat->buf'. */
7557 anychar_head
= NULL
;
7560 for (ptr
= pattern
; *ptr
; ptr
++)
7562 unsigned char c
= *ptr
;
7565 if (last_char
== '*')
7566 /* ...a** -> ...a* */
7570 if (last_char
== '?')
7572 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7573 /* ...*??* -> ...*?? */
7576 /* ...a??* -> ...a*?? */
7578 *anychar_head
++ = '*';
7586 if (last_char
!= '?')
7590 /* On Mac OS X 10.3, tolower also converts non-ASCII
7591 characters for some locales. */
7595 *q
++ = last_char
= c
;
7599 pat
->nblocks
= nblocks
;
7600 if (last_char
!= '?')
7601 pat
->trailing_anychars
= 0;
7604 pat
->trailing_anychars
= q
- anychar_head
;
7607 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7609 if (anychar_head
== NULL
&& nblocks
== 1)
7611 /* The pattern is exact. */
7616 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7618 /* Divide the normalized pattern into blocks. */
7620 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7625 blk
->len
= p
- blk
->pattern
;
7629 blk
->len
= q
- blk
->pattern
;
7631 /* Setup a table for the Boyer-Moore string search. */
7632 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7635 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7636 blk
->pattern
[blk
->len
- 1] = '\0';
7638 for (skip
= 1; skip
< blk
->len
; skip
++)
7639 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7642 for (i
= 0; i
< 256; i
++)
7643 blk
->skip
[i
] = skip
;
7645 p
= blk
->pattern
+ (blk
->len
- skip
);
7647 blk
->skip
[*p
++] = skip
;
7649 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7656 xlfdpat_exact_p (pat
)
7657 struct xlfdpat
*pat
;
7659 return pat
->blocks
== NULL
;
7662 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7663 that the pattern in *BLK matches with its prefix. Return NULL
7664 there is no such strings. STRING must be lowered in advance. */
7667 xlfdpat_block_match_1 (blk
, string
, start_max
)
7668 struct xlfdpat_block
*blk
;
7669 const unsigned char *string
;
7672 int start
, infinity
;
7674 const unsigned char *s
;
7676 xassert (blk
->len
> 0);
7677 xassert (start_max
+ blk
->len
<= strlen (string
));
7678 xassert (blk
->last_char
!= '?');
7680 /* See the comments in the function `boyer_moore' (search.c) for the
7681 use of `infinity'. */
7682 infinity
= start_max
+ blk
->len
+ 1;
7683 blk
->skip
[blk
->last_char
] = infinity
;
7688 /* Check the last character of the pattern. */
7689 s
= string
+ blk
->len
- 1;
7692 start
+= blk
->skip
[*(s
+ start
)];
7694 while (start
<= start_max
);
7696 if (start
< infinity
)
7697 /* Couldn't find the last character. */
7700 /* No less than `infinity' means we could find the last
7701 character at `s[start - infinity]'. */
7704 /* Check the remaining characters. We prefer making no-'?'
7705 cases faster because the use of '?' is really rare. */
7710 while (*p
++ == *s
++)
7713 while (*(p
- 1) == '?');
7715 if (*(p
- 1) == '\0')
7717 return string
+ start
;
7720 start
+= blk
->last_char_skip
;
7722 while (start
<= start_max
);
7727 #define xlfdpat_block_match(b, s, m) \
7728 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7729 : xlfdpat_block_match_1 (b, s, m))
7731 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7732 matches with STRING. STRING must be lowered in advance. */
7735 xlfdpat_match (pat
, string
)
7736 struct xlfdpat
*pat
;
7737 const unsigned char *string
;
7739 int str_len
, nblocks
, i
, start_max
;
7740 struct xlfdpat_block
*blk
;
7741 const unsigned char *s
;
7743 xassert (pat
->nblocks
> 0);
7745 if (xlfdpat_exact_p (pat
))
7746 return strcmp (pat
->buf
, string
) == 0;
7748 /* The number of the characters in the string must not be smaller
7749 than that in the pattern. */
7750 str_len
= strlen (string
);
7751 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7754 /* Chop off the trailing '?'s. */
7755 str_len
-= pat
->trailing_anychars
;
7757 /* The last block. When it is non-empty, it must match at the end
7759 nblocks
= pat
->nblocks
;
7760 blk
= pat
->blocks
+ (nblocks
- 1);
7762 /* The last block is also the first one. */
7763 return (str_len
== blk
->len
7764 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7765 else if (blk
->len
!= 0)
7766 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7769 /* The first block. When it is non-empty, it must match at the
7770 beginning of the string. */
7774 s
= xlfdpat_block_match (blk
, string
, 0);
7777 string
= s
+ blk
->len
;
7780 /* The rest of the blocks. */
7781 start_max
= str_len
- pat
->nchars
;
7782 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7784 s
= xlfdpat_block_match (blk
, string
, start_max
);
7787 start_max
-= s
- string
;
7788 string
= s
+ blk
->len
;
7795 /***********************************************************************
7797 ***********************************************************************/
7799 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7802 x_get_font_info (f
, font_idx
)
7806 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7809 /* the global font name table */
7810 static char **font_name_table
= NULL
;
7811 static int font_name_table_size
= 0;
7812 static int font_name_count
= 0;
7814 /* Alist linking font family names to Font Manager font family
7815 references (which can also be used as QuickDraw font IDs). We use
7816 an alist because hash tables are not ready when the terminal frame
7817 for Mac OS Classic is created. */
7818 static Lisp_Object fm_font_family_alist
;
7820 /* Hash table linking font family names to ATSU font IDs. */
7821 static Lisp_Object atsu_font_id_hash
;
7822 /* Alist linking Font Manager style to face attributes. */
7823 static Lisp_Object fm_style_face_attributes_alist
;
7824 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7827 /* Alist linking character set strings to Mac text encoding and Emacs
7829 static Lisp_Object Vmac_charset_info_alist
;
7832 create_text_encoding_info_alist ()
7834 Lisp_Object result
= Qnil
, rest
;
7836 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7838 Lisp_Object charset_info
= XCAR (rest
);
7839 Lisp_Object charset
, coding_system
, text_encoding
;
7840 Lisp_Object existing_info
;
7842 if (!(CONSP (charset_info
)
7843 && (charset
= XCAR (charset_info
),
7845 && CONSP (XCDR (charset_info
))
7846 && (text_encoding
= XCAR (XCDR (charset_info
)),
7847 INTEGERP (text_encoding
))
7848 && CONSP (XCDR (XCDR (charset_info
)))
7849 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7850 SYMBOLP (coding_system
))))
7853 existing_info
= assq_no_quit (text_encoding
, result
);
7854 if (NILP (existing_info
))
7855 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7858 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7859 XSETCDR (XCDR (existing_info
),
7860 Fcons (charset
, XCDR (XCDR (existing_info
))));
7868 decode_mac_font_name (name
, size
, coding_system
)
7871 Lisp_Object coding_system
;
7873 struct coding_system coding
;
7876 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7878 for (p
= name
; *p
; p
++)
7879 if (!isascii (*p
) || iscntrl (*p
))
7884 setup_coding_system (coding_system
, &coding
);
7885 coding
.src_multibyte
= 0;
7886 coding
.dst_multibyte
= 1;
7887 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7888 coding
.composing
= COMPOSITION_DISABLED
;
7889 buf
= (char *) alloca (size
);
7891 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7892 bcopy (buf
, name
, coding
.produced
);
7893 name
[coding
.produced
] = '\0';
7897 /* If there's just one occurrence of '-' in the family name, it is
7898 replaced with '_'. (More than one occurrence of '-' means a
7899 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7900 p
= strchr (name
, '-');
7901 if (p
&& strchr (p
+ 1, '-') == NULL
)
7904 for (p
= name
; *p
; p
++)
7905 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7906 for some locales. */
7913 mac_to_x_fontname (name
, size
, style
, charset
)
7921 char xf
[256], *result
;
7924 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7928 strcpy(foundry
, "Apple");
7929 strcpy(family
, name
);
7932 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7933 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7934 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7936 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7937 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7938 for (p
= result
; *p
; p
++)
7939 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7940 for some locales. */
7947 /* Parse fully-specified and instantiated X11 font spec XF, and store
7948 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7949 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7950 caller must allocate at least 256 and 32 bytes respectively. For
7951 ordinary Mac fonts, the value stored to FAMILY should just be their
7952 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7953 intlfonts collection contain their charset designation in their
7954 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7955 types of font names are handled accordingly. */
7957 const int kDefaultFontSize
= 12;
7960 parse_x_font_name (xf
, family
, size
, style
, charset
)
7967 Str31 foundry
, weight
;
7968 int point_size
, avgwidth
;
7971 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7972 foundry
, family
, weight
, slant
, size
,
7973 &point_size
, &avgwidth
, charset
) != 8
7974 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7975 foundry
, family
, weight
, slant
, size
,
7976 &point_size
, &avgwidth
, charset
) != 8)
7982 *size
= point_size
/ 10;
7983 else if (avgwidth
> 0)
7984 *size
= avgwidth
/ 10;
7987 *size
= kDefaultFontSize
;
7990 if (strcmp (weight
, "bold") == 0)
7995 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7997 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7999 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
8001 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
8002 but take overlap into account. */
8003 memmove (family
+ foundry_len
+ 1, family
, family_len
);
8004 memcpy (family
, foundry
, foundry_len
);
8005 family
[foundry_len
] = '-';
8006 family
[foundry_len
+ 1 + family_len
] = '-';
8007 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
8013 for (p
= family
; *p
; p
++)
8014 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8015 for some locales. */
8024 add_font_name_table_entry (char *font_name
)
8026 if (font_name_table_size
== 0)
8028 font_name_table_size
= 256;
8029 font_name_table
= (char **)
8030 xmalloc (font_name_table_size
* sizeof (char *));
8032 else if (font_name_count
+ 1 >= font_name_table_size
)
8034 font_name_table_size
*= 2;
8035 font_name_table
= (char **)
8036 xrealloc (font_name_table
,
8037 font_name_table_size
* sizeof (char *));
8040 font_name_table
[font_name_count
++] = font_name
;
8044 add_mac_font_name (name
, size
, style
, charset
)
8048 const char *charset
;
8051 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8054 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8055 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8056 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8057 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8064 fm_get_style_from_font (font
)
8068 FMFontStyle style
= normal
;
8071 FMFontFamily font_family
;
8072 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8074 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8075 some font (e.g., Optima) even if it is `bold'. */
8076 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8077 sizeof (mac_style
), &mac_style
, &len
);
8079 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8080 style
= EndianU16_BtoN (mac_style
);
8082 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8088 atsu_find_font_from_family_name (family
)
8091 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8094 Lisp_Object rest
, best
;
8095 FMFontStyle min_style
, style
;
8097 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8100 return kATSUInvalidFontID
;
8102 rest
= HASH_VALUE (h
, i
);
8103 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8104 return cons_to_long (rest
);
8106 rest
= Fnreverse (rest
);
8110 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8113 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8114 if (style
< min_style
)
8117 if (style
== normal
)
8124 while (!NILP (rest
));
8126 HASH_VALUE (h
, i
) = best
;
8127 return cons_to_long (best
);
8131 fm_style_to_face_attributes (fm_style
)
8132 FMFontStyle fm_style
;
8136 fm_style
&= (bold
| italic
);
8137 tem
= assq_no_quit (make_number (fm_style
),
8138 fm_style_face_attributes_alist
);
8142 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8143 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8144 fm_style_face_attributes_alist
=
8145 Fcons (Fcons (make_number (fm_style
), tem
),
8146 fm_style_face_attributes_alist
);
8152 atsu_find_font_family_name (font_id
)
8157 Lisp_Object family
= Qnil
;
8159 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8160 kFontMacintoshPlatform
, kFontNoScript
,
8161 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8164 family
= make_uninit_string (len
);
8165 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8166 kFontMacintoshPlatform
, kFontNoScript
,
8167 kFontNoLanguage
, len
, SDATA (family
),
8171 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8177 mac_atsu_font_face_attributes (font_id
)
8180 Lisp_Object family
, style_attrs
;
8182 family
= atsu_find_font_family_name (font_id
);
8185 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8186 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8190 /* Sets up the table font_name_table to contain the list of all fonts
8191 in the system the first time the table is used so that the Resource
8192 Manager need not be accessed every time this information is
8196 init_font_name_table ()
8198 #if TARGET_API_MAC_CARBON
8199 FMFontFamilyIterator ffi
;
8200 FMFontFamilyInstanceIterator ffii
;
8202 Lisp_Object text_encoding_info_alist
;
8203 struct gcpro gcpro1
;
8205 text_encoding_info_alist
= create_text_encoding_info_alist ();
8208 #if USE_CG_TEXT_DRAWING
8209 init_cg_text_anti_aliasing_threshold ();
8211 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8212 text_encoding_info_alist
)))
8215 struct Lisp_Hash_Table
*h
;
8217 ItemCount nfonts
, i
;
8218 ATSUFontID
*font_ids
= NULL
;
8219 Lisp_Object prev_family
= Qnil
;
8223 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8224 make_float (DEFAULT_REHASH_SIZE
),
8225 make_float (DEFAULT_REHASH_THRESHOLD
),
8227 h
= XHASH_TABLE (atsu_font_id_hash
);
8229 err
= ATSUFontCount (&nfonts
);
8232 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8233 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8236 for (i
= 0; i
< nfonts
; i
++)
8240 family
= atsu_find_font_family_name (font_ids
[i
]);
8241 if (NILP (family
) || SREF (family
, 0) == '.')
8243 if (!NILP (Fequal (prev_family
, family
)))
8244 family
= prev_family
;
8246 j
= hash_lookup (h
, family
, &hash_code
);
8249 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8250 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8253 else if (EQ (prev_family
, family
))
8254 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8256 prev_family
= family
;
8263 /* Create a dummy instance iterator here to avoid creating and
8264 destroying it in the loop. */
8265 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8267 /* Create an iterator to enumerate the font families. */
8268 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8271 FMDisposeFontFamilyInstanceIterator (&ffii
);
8275 GCPRO1 (text_encoding_info_alist
);
8277 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8283 TextEncoding encoding
;
8284 TextEncodingBase sc
;
8285 Lisp_Object text_encoding_info
, family
;
8287 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8293 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8295 sc
= GetTextEncodingBase (encoding
);
8296 text_encoding_info
= assq_no_quit (make_number (sc
),
8297 text_encoding_info_alist
);
8298 if (NILP (text_encoding_info
))
8299 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8300 text_encoding_info_alist
);
8301 decode_mac_font_name (name
, sizeof (name
),
8302 XCAR (XCDR (text_encoding_info
)));
8303 family
= build_string (name
);
8304 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8306 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8307 fm_font_family_alist
);
8309 /* Point the instance iterator at the current font family. */
8310 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8313 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8316 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8318 if (size
> 0 || style
== normal
)
8319 for (; !NILP (rest
); rest
= XCDR (rest
))
8320 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8326 /* Dispose of the iterators. */
8327 FMDisposeFontFamilyIterator (&ffi
);
8328 FMDisposeFontFamilyInstanceIterator (&ffii
);
8329 #else /* !TARGET_API_MAC_CARBON */
8331 SInt16 fontnum
, old_fontnum
;
8332 int num_mac_fonts
= CountResources('FOND');
8334 Handle font_handle
, font_handle_2
;
8335 short id
, scriptcode
;
8338 struct FontAssoc
*fat
;
8339 struct AsscEntry
*assc_entry
;
8340 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8341 struct gcpro gcpro1
;
8343 GetPort (&port
); /* save the current font number used */
8344 old_fontnum
= port
->txFont
;
8346 text_encoding_info_alist
= create_text_encoding_info_alist ();
8348 GCPRO1 (text_encoding_info_alist
);
8350 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8352 font_handle
= GetIndResource ('FOND', i
);
8356 GetResInfo (font_handle
, &id
, &type
, name
);
8357 GetFNum (name
, &fontnum
);
8359 if (fontnum
== 0 || *name
== '.')
8363 scriptcode
= FontToScript (fontnum
);
8364 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8365 text_encoding_info_alist
);
8366 if (NILP (text_encoding_info
))
8367 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8368 text_encoding_info_alist
);
8369 decode_mac_font_name (name
, sizeof (name
),
8370 XCAR (XCDR (text_encoding_info
)));
8371 family
= build_string (name
);
8372 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8374 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8375 fm_font_family_alist
);
8378 HLock (font_handle
);
8380 if (GetResourceSizeOnDisk (font_handle
)
8381 >= sizeof (struct FamRec
))
8383 fat
= (struct FontAssoc
*) (*font_handle
8384 + sizeof (struct FamRec
));
8386 = (struct AsscEntry
*) (*font_handle
8387 + sizeof (struct FamRec
)
8388 + sizeof (struct FontAssoc
));
8390 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8392 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8394 for (; !NILP (rest
); rest
= XCDR (rest
))
8395 add_mac_font_name (name
, assc_entry
->fontSize
,
8396 assc_entry
->fontStyle
,
8397 SDATA (XCAR (rest
)));
8401 HUnlock (font_handle
);
8402 font_handle_2
= GetNextFOND (font_handle
);
8403 ReleaseResource (font_handle
);
8404 font_handle
= font_handle_2
;
8406 while (ResError () == noErr
&& font_handle
);
8411 TextFont (old_fontnum
);
8412 #endif /* !TARGET_API_MAC_CARBON */
8417 mac_clear_font_name_table ()
8421 for (i
= 0; i
< font_name_count
; i
++)
8422 xfree (font_name_table
[i
]);
8423 xfree (font_name_table
);
8424 font_name_table
= NULL
;
8425 font_name_table_size
= font_name_count
= 0;
8426 fm_font_family_alist
= Qnil
;
8430 enum xlfd_scalable_field_index
8432 XLFD_SCL_PIXEL_SIZE
,
8433 XLFD_SCL_POINT_SIZE
,
8438 static const int xlfd_scalable_fields
[] =
8447 mac_do_list_fonts (pattern
, maxnames
)
8448 const char *pattern
;
8452 Lisp_Object font_list
= Qnil
;
8453 struct xlfdpat
*pat
;
8456 int scl_val
[XLFD_SCL_LAST
], *val
;
8460 if (font_name_table
== NULL
) /* Initialize when first used. */
8461 init_font_name_table ();
8463 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8466 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8467 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8468 fonts are scaled according to the specified size. */
8471 field
= xlfd_scalable_fields
;
8479 if ('0' <= *ptr
&& *ptr
<= '9')
8481 *val
= *ptr
++ - '0';
8482 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8483 *val
= *val
* 10 + *ptr
++ - '0';
8490 ptr
= strchr (ptr
, '-');
8493 while (ptr
&& i
< 14);
8495 if (i
== 14 && ptr
== NULL
)
8497 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8498 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8499 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8500 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8502 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8503 scl_val
[XLFD_SCL_POINT_SIZE
] =
8504 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8505 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8507 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8508 scl_val
[XLFD_SCL_AVGWIDTH
] =
8509 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8510 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8514 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8516 pat
= xlfdpat_create (pattern
);
8520 exact
= xlfdpat_exact_p (pat
);
8522 for (i
= 0; i
< font_name_count
; i
++)
8524 if (xlfdpat_match (pat
, font_name_table
[i
]))
8526 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8527 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8530 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8531 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8533 int former_len
= ptr
- font_name_table
[i
];
8535 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8536 memcpy (scaled
, font_name_table
[i
], former_len
);
8537 sprintf (scaled
+ former_len
,
8538 "-%d-%d-72-72-m-%d-%s",
8539 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8540 scl_val
[XLFD_SCL_POINT_SIZE
],
8541 scl_val
[XLFD_SCL_AVGWIDTH
],
8542 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8544 if (xlfdpat_match (pat
, scaled
))
8546 font_list
= Fcons (build_string (scaled
), font_list
);
8548 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8556 xlfdpat_destroy (pat
);
8561 /* Return a list of names of available fonts matching PATTERN on frame F.
8563 Frame F null means we have not yet created any frame on Mac, and
8564 consult the first display in x_display_list. MAXNAMES sets a limit
8565 on how many fonts to match. */
8568 x_list_fonts (f
, pattern
, size
, maxnames
)
8570 Lisp_Object pattern
;
8573 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8574 struct mac_display_info
*dpyinfo
8575 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8577 xassert (size
<= 0);
8579 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8580 if (NILP (patterns
))
8581 patterns
= Fcons (pattern
, Qnil
);
8583 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8585 pattern
= XCAR (patterns
);
8587 if (!STRINGP (pattern
))
8590 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8591 key
= Fcons (pattern
, make_number (maxnames
));
8593 list
= Fassoc (key
, tem
);
8596 list
= Fcdr_safe (list
);
8597 /* We have a cashed list. Don't have to get the list again. */
8602 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8605 /* MAC_TODO: add code for matching outline fonts here */
8607 /* Now store the result in the cache. */
8608 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8609 Fcons (Fcons (key
, list
),
8610 XCAR (XCDR (dpyinfo
->name_list_element
))));
8613 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8622 /* Check that FONT is valid on frame F. It is if it can be found in F's
8626 x_check_font (f
, font
)
8631 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8633 xassert (font
!= NULL
);
8635 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8636 if (dpyinfo
->font_table
[i
].name
8637 && font
== dpyinfo
->font_table
[i
].font
)
8640 xassert (i
< dpyinfo
->n_fonts
);
8643 #endif /* GLYPH_DEBUG != 0 */
8645 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8646 Note: There are (broken) X fonts out there with invalid XFontStruct
8647 min_bounds contents. For example, handa@etl.go.jp reports that
8648 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8649 have font->min_bounds.width == 0. */
8652 x_font_min_bounds (font
, w
, h
)
8653 MacFontStruct
*font
;
8656 *h
= FONT_HEIGHT (font
);
8657 *w
= font
->min_bounds
.width
;
8661 /* Compute the smallest character width and smallest font height over
8662 all fonts available on frame F. Set the members smallest_char_width
8663 and smallest_font_height in F's x_display_info structure to
8664 the values computed. Value is non-zero if smallest_font_height or
8665 smallest_char_width become smaller than they were before. */
8668 x_compute_min_glyph_bounds (f
)
8672 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8673 MacFontStruct
*font
;
8674 int old_width
= dpyinfo
->smallest_char_width
;
8675 int old_height
= dpyinfo
->smallest_font_height
;
8677 dpyinfo
->smallest_font_height
= 100000;
8678 dpyinfo
->smallest_char_width
= 100000;
8680 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8681 if (dpyinfo
->font_table
[i
].name
)
8683 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8686 font
= (MacFontStruct
*) fontp
->font
;
8687 xassert (font
!= (MacFontStruct
*) ~0);
8688 x_font_min_bounds (font
, &w
, &h
);
8690 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8691 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8694 xassert (dpyinfo
->smallest_char_width
> 0
8695 && dpyinfo
->smallest_font_height
> 0);
8697 return (dpyinfo
->n_fonts
== 1
8698 || dpyinfo
->smallest_char_width
< old_width
8699 || dpyinfo
->smallest_font_height
< old_height
);
8703 /* Determine whether given string is a fully-specified XLFD: all 14
8704 fields are present, none is '*'. */
8707 is_fully_specified_xlfd (p
)
8716 for (i
= 0; i
< 13; i
++)
8718 q
= strchr (p
+ 1, '-');
8721 if (q
- p
== 2 && *(p
+ 1) == '*')
8726 if (strchr (p
+ 1, '-') != NULL
)
8729 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8736 /* mac_load_query_font creates and returns an internal representation
8737 for a font in a MacFontStruct struct. There is really no concept
8738 corresponding to "loading" a font on the Mac. But we check its
8739 existence and find the font number and all other information for it
8740 and store them in the returned MacFontStruct. */
8742 static MacFontStruct
*
8743 mac_load_query_font (f
, fontname
)
8753 static ATSUFontID font_id
;
8754 ATSUStyle mac_style
= NULL
;
8757 #if TARGET_API_MAC_CARBON
8758 TextEncoding encoding
;
8763 MacFontStruct
*font
;
8764 XCharStruct
*space_bounds
= NULL
, *pcm
;
8766 if (is_fully_specified_xlfd (fontname
))
8770 Lisp_Object matched_fonts
;
8772 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8773 if (NILP (matched_fonts
))
8775 name
= SDATA (XCAR (matched_fonts
));
8778 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8782 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8785 static const ATSUAttributeTag tags
[] =
8786 {kATSUFontTag
, kATSUSizeTag
,
8787 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8788 static const ByteCount sizes
[] =
8789 {sizeof (ATSUFontID
), sizeof (Fixed
),
8790 sizeof (Boolean
), sizeof (Boolean
)};
8791 static Fixed size_fixed
;
8792 static Boolean bold_p
, italic_p
;
8793 static const ATSUAttributeValuePtr values
[] =
8794 {&font_id
, &size_fixed
,
8795 &bold_p
, &italic_p
};
8796 static const ATSUFontFeatureType types
[] =
8797 {kAllTypographicFeaturesType
, kDiacriticsType
};
8798 static const ATSUFontFeatureSelector selectors
[] =
8799 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8802 font_id
= atsu_find_font_from_family_name (family
);
8803 if (font_id
== kATSUInvalidFontID
)
8805 size_fixed
= Long2Fix (size
);
8806 bold_p
= (fontface
& bold
) != 0;
8807 italic_p
= (fontface
& italic
) != 0;
8808 err
= ATSUCreateStyle (&mac_style
);
8811 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8815 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8816 tags
, sizes
, values
);
8819 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8822 scriptcode
= kTextEncodingMacUnicode
;
8827 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8831 fontnum
= XINT (XCDR (tmp
));
8832 #if TARGET_API_MAC_CARBON
8833 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8835 scriptcode
= GetTextEncodingBase (encoding
);
8837 scriptcode
= FontToScript (fontnum
);
8841 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8843 font
->mac_fontnum
= fontnum
;
8844 font
->mac_fontsize
= size
;
8845 font
->mac_fontface
= fontface
;
8846 font
->mac_scriptcode
= scriptcode
;
8848 font
->mac_style
= mac_style
;
8849 #if USE_CG_TEXT_DRAWING
8850 font
->cg_font
= NULL
;
8851 font
->cg_glyphs
= NULL
;
8855 /* Apple Japanese (SJIS) font is listed as both
8856 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8857 (Roman script) in init_font_name_table (). The latter should be
8858 treated as a one-byte font. */
8859 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8860 font
->mac_scriptcode
= smRoman
;
8862 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8865 if (font
->mac_style
)
8870 font
->min_byte1
= 0;
8871 font
->max_byte1
= 0xff;
8872 font
->min_char_or_byte2
= 0;
8873 font
->max_char_or_byte2
= 0xff;
8875 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8876 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8877 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8878 pcm_init (font
->bounds
.rows
[0], 0x100);
8880 #if USE_CG_TEXT_DRAWING
8884 ATSFontRef ats_font
;
8886 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8888 /* Use CG text drawing if italic/bold is not synthesized. */
8889 if (err
== noErr
&& style
== fontface
)
8891 ats_font
= FMGetATSFontRefFromFont (font_id
);
8892 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8898 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8899 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8902 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8903 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8904 &font
->ascent
, &font
->descent
,
8906 #if USE_CG_TEXT_DRAWING
8907 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8914 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8916 mac_unload_font (&one_mac_display_info
, font
);
8920 pcm
= font
->bounds
.rows
[0];
8921 for (c
= 0x21; c
<= 0xff; c
++)
8924 /* Soft hyphen is not supported in ATSUI. */
8928 #if USE_CG_TEXT_DRAWING
8929 if (font
->cg_glyphs
)
8939 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8940 pcm
? pcm
+ c
: NULL
,
8941 #if USE_CG_TEXT_DRAWING
8942 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8949 #if USE_CG_TEXT_DRAWING
8950 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8952 /* Don't use CG text drawing if font substitution occurs in
8953 ASCII or Latin-1 characters. */
8954 CGFontRelease (font
->cg_font
);
8955 font
->cg_font
= NULL
;
8956 xfree (font
->cg_glyphs
);
8957 font
->cg_glyphs
= NULL
;
8968 FontInfo the_fontinfo
;
8969 int is_two_byte_font
;
8972 mac_prepare_for_quickdraw (f
);
8974 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8978 TextFace (fontface
);
8980 GetFontInfo (&the_fontinfo
);
8982 font
->ascent
= the_fontinfo
.ascent
;
8983 font
->descent
= the_fontinfo
.descent
;
8985 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8986 || font
->mac_scriptcode
== smTradChinese
8987 || font
->mac_scriptcode
== smSimpChinese
8988 || font
->mac_scriptcode
== smKorean
);
8990 if (is_two_byte_font
)
8994 font
->min_byte1
= 0xa1;
8995 font
->max_byte1
= 0xfe;
8996 font
->min_char_or_byte2
= 0xa1;
8997 font
->max_char_or_byte2
= 0xfe;
8999 /* Use the width of an "ideographic space" of that font
9000 because the_fontinfo.widMax returns the wrong width for
9002 switch (font
->mac_scriptcode
)
9005 font
->min_byte1
= 0x81;
9006 font
->max_byte1
= 0xfc;
9007 font
->min_char_or_byte2
= 0x40;
9008 font
->max_char_or_byte2
= 0xfc;
9009 char_width
= StringWidth("\p\x81\x40");
9012 font
->min_char_or_byte2
= 0x40;
9013 char_width
= StringWidth("\p\xa1\x40");
9016 char_width
= StringWidth("\p\xa1\xa1");
9019 char_width
= StringWidth("\p\xa1\xa1");
9023 font
->bounds
.per_char
= NULL
;
9025 if (fontface
& italic
)
9026 font
->max_bounds
.rbearing
= char_width
+ 1;
9028 font
->max_bounds
.rbearing
= char_width
;
9029 font
->max_bounds
.lbearing
= 0;
9030 font
->max_bounds
.width
= char_width
;
9031 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
9032 font
->max_bounds
.descent
= the_fontinfo
.descent
;
9034 font
->min_bounds
= font
->max_bounds
;
9040 font
->min_byte1
= font
->max_byte1
= 0;
9041 font
->min_char_or_byte2
= 0x20;
9042 font
->max_char_or_byte2
= 0xff;
9044 font
->bounds
.per_char
=
9045 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9046 bzero (font
->bounds
.per_char
,
9047 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9049 space_bounds
= font
->bounds
.per_char
;
9050 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9051 &font
->descent
, space_bounds
, NULL
);
9052 if (err
!= noErr
|| space_bounds
->width
<= 0)
9054 mac_unload_font (&one_mac_display_info
, font
);
9058 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9059 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9067 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9068 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9071 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9073 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9075 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9077 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9079 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9082 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9084 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9086 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9088 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9090 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9095 font
->mac_style
== NULL
&&
9097 font
->max_bounds
.width
== font
->min_bounds
.width
9098 && font
->min_bounds
.lbearing
>= 0
9099 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9101 /* Fixed width and no overhangs. */
9102 xfree (font
->bounds
.per_char
);
9103 font
->bounds
.per_char
= NULL
;
9107 #if !defined (MAC_OS8) || USE_ATSUI
9108 /* AppKit and WebKit do some adjustment to the heights of Courier,
9109 Helvetica, and Times. This only works on the environments where
9110 srcCopy text transfer mode is never used. */
9112 #ifdef MAC_OS8 /* implies USE_ATSUI */
9115 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9116 || strcmp (family
, "times") == 0))
9117 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9125 mac_unload_font (dpyinfo
, font
)
9126 struct mac_display_info
*dpyinfo
;
9129 xfree (font
->full_name
);
9131 if (font
->mac_style
)
9135 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9136 if (font
->bounds
.rows
[i
])
9137 xfree (font
->bounds
.rows
[i
]);
9138 xfree (font
->bounds
.rows
);
9139 ATSUDisposeStyle (font
->mac_style
);
9143 if (font
->bounds
.per_char
)
9144 xfree (font
->bounds
.per_char
);
9145 #if USE_CG_TEXT_DRAWING
9147 CGFontRelease (font
->cg_font
);
9148 if (font
->cg_glyphs
)
9149 xfree (font
->cg_glyphs
);
9155 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9156 pointer to the structure font_info while allocating it dynamically.
9157 If SIZE is 0, load any size of font.
9158 If loading is failed, return NULL. */
9161 x_load_font (f
, fontname
, size
)
9163 register char *fontname
;
9166 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9167 Lisp_Object font_names
;
9169 /* Get a list of all the fonts that match this name. Once we
9170 have a list of matching fonts, we compare them against the fonts
9171 we already have by comparing names. */
9172 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9174 if (!NILP (font_names
))
9179 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9180 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9181 if (dpyinfo
->font_table
[i
].name
9182 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9183 SDATA (XCAR (tail
)))
9184 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9185 SDATA (XCAR (tail
)))))
9186 return (dpyinfo
->font_table
+ i
);
9191 /* Load the font and add it to the table. */
9193 struct MacFontStruct
*font
;
9194 struct font_info
*fontp
;
9197 fontname
= (char *) SDATA (XCAR (font_names
));
9200 font
= mac_load_query_font (f
, fontname
);
9205 /* Find a free slot in the font table. */
9206 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9207 if (dpyinfo
->font_table
[i
].name
== NULL
)
9210 /* If no free slot found, maybe enlarge the font table. */
9211 if (i
== dpyinfo
->n_fonts
9212 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9215 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9216 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9218 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9221 fontp
= dpyinfo
->font_table
+ i
;
9222 if (i
== dpyinfo
->n_fonts
)
9225 /* Now fill in the slots of *FONTP. */
9227 bzero (fontp
, sizeof (*fontp
));
9229 fontp
->font_idx
= i
;
9230 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9231 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9233 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9235 /* Fixed width font. */
9236 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9243 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9244 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9246 fontp
->space_width
= pcm
->width
;
9248 fontp
->space_width
= FONT_WIDTH (font
);
9252 int width
= pcm
->width
;
9253 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9254 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9255 width
+= pcm
->width
;
9256 fontp
->average_width
= width
/ 95;
9259 fontp
->average_width
= FONT_WIDTH (font
);
9262 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9263 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9265 fontp
->size
= font
->max_bounds
.width
;
9266 fontp
->height
= FONT_HEIGHT (font
);
9268 /* For some font, ascent and descent in max_bounds field is
9269 larger than the above value. */
9270 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9271 if (max_height
> fontp
->height
)
9272 fontp
->height
= max_height
;
9275 /* The slot `encoding' specifies how to map a character
9276 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9277 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9278 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9279 2:0xA020..0xFF7F). For the moment, we don't know which charset
9280 uses this font. So, we set information in fontp->encoding[1]
9281 which is never used by any charset. If mapping can't be
9282 decided, set FONT_ENCODING_NOT_DECIDED. */
9283 if (font
->mac_scriptcode
== smJapanese
)
9284 fontp
->encoding
[1] = 4;
9288 = (font
->max_byte1
== 0
9290 ? (font
->min_char_or_byte2
< 0x80
9291 ? (font
->max_char_or_byte2
< 0x80
9292 ? 0 /* 0x20..0x7F */
9293 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9294 : 1) /* 0xA0..0xFF */
9296 : (font
->min_byte1
< 0x80
9297 ? (font
->max_byte1
< 0x80
9298 ? (font
->min_char_or_byte2
< 0x80
9299 ? (font
->max_char_or_byte2
< 0x80
9300 ? 0 /* 0x2020..0x7F7F */
9301 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9302 : 3) /* 0x20A0..0x7FFF */
9303 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9304 : (font
->min_char_or_byte2
< 0x80
9305 ? (font
->max_char_or_byte2
< 0x80
9306 ? 2 /* 0xA020..0xFF7F */
9307 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9308 : 1))); /* 0xA0A0..0xFFFF */
9311 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9312 fontp
->baseline_offset
9313 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9314 ? (long) value
: 0);
9315 fontp
->relative_compose
9316 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9317 ? (long) value
: 0);
9318 fontp
->default_ascent
9319 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9320 ? (long) value
: 0);
9322 fontp
->baseline_offset
= 0;
9323 fontp
->relative_compose
= 0;
9324 fontp
->default_ascent
= 0;
9327 /* Set global flag fonts_changed_p to non-zero if the font loaded
9328 has a character with a smaller width than any other character
9329 before, or if the font loaded has a smaller height than any
9330 other font loaded before. If this happens, it will make a
9331 glyph matrix reallocation necessary. */
9332 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9339 /* Return a pointer to struct font_info of a font named FONTNAME for
9340 frame F. If no such font is loaded, return NULL. */
9343 x_query_font (f
, fontname
)
9345 register char *fontname
;
9347 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9350 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9351 if (dpyinfo
->font_table
[i
].name
9352 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9353 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9354 return (dpyinfo
->font_table
+ i
);
9359 /* Find a CCL program for a font specified by FONTP, and set the member
9360 `encoder' of the structure. */
9363 x_find_ccl_program (fontp
)
9364 struct font_info
*fontp
;
9366 Lisp_Object list
, elt
;
9368 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9372 && STRINGP (XCAR (elt
))
9373 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9379 struct ccl_program
*ccl
9380 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9382 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9385 fontp
->font_encoder
= ccl
;
9389 #if USE_MAC_FONT_PANEL
9390 /* Whether Font Panel has been shown before. The first call to font
9391 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9392 slow. This variable is used for deferring such a call as much as
9394 static int font_panel_shown_p
= 0;
9396 extern Lisp_Object Qfont
;
9397 static Lisp_Object Qpanel_closed
, Qselection
;
9399 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9403 const EventParamName
*,
9404 const EventParamType
*));
9407 mac_font_panel_visible_p ()
9409 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9412 static pascal OSStatus
9413 mac_handle_font_event (next_handler
, event
, data
)
9414 EventHandlerCallRef next_handler
;
9418 OSStatus result
, err
;
9421 const EventParamName
*names
;
9422 const EventParamType
*types
;
9423 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9424 kEventParamATSUFontSize
,
9425 kEventParamFMFontFamily
,
9426 kEventParamFMFontStyle
,
9427 kEventParamFMFontSize
,
9428 kEventParamFontColor
};
9429 static const EventParamType types_sel
[] = {typeATSUFontID
,
9436 result
= CallNextEventHandler (next_handler
, event
);
9437 if (result
!= eventNotHandledErr
)
9440 switch (GetEventKind (event
))
9442 case kEventFontPanelClosed
:
9443 id_key
= Qpanel_closed
;
9449 case kEventFontSelection
:
9450 id_key
= Qselection
;
9451 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9457 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9467 mac_show_hide_font_panel ()
9469 if (!font_panel_shown_p
)
9473 static const EventTypeSpec specs
[] =
9474 {{kEventClassFont
, kEventFontPanelClosed
},
9475 {kEventClassFont
, kEventFontSelection
}};
9477 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9478 GetEventTypeCount (specs
),
9483 font_panel_shown_p
= 1;
9486 return FPShowHideFontPanel ();
9490 mac_set_font_info_for_selection (f
, face_id
, c
)
9495 EventTargetRef target
= NULL
;
9496 XFontStruct
*font
= NULL
;
9498 if (!mac_font_panel_visible_p ())
9503 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9505 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9509 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9510 face
= FACE_FROM_ID (f
, face_id
);
9516 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9519 if (font
->mac_fontnum
!= -1)
9521 FontSelectionQDStyle qd_style
;
9523 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9524 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9525 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9526 qd_style
.size
= font
->mac_fontsize
;
9527 qd_style
.hasColor
= false;
9529 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9530 1, &qd_style
, target
);
9533 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9534 1, &font
->mac_style
, target
);
9542 /* The Mac Event loop code */
9544 #if !TARGET_API_MAC_CARBON
9546 #include <Quickdraw.h>
9547 #include <Balloons.h>
9548 #include <Devices.h>
9550 #include <Gestalt.h>
9552 #include <Processes.h>
9554 #include <ToolUtils.h>
9555 #include <TextUtils.h>
9556 #include <Dialogs.h>
9559 #include <Resources.h>
9564 #endif /* ! TARGET_API_MAC_CARBON */
9569 #define DEFAULT_NUM_COLS 80
9571 #define MIN_DOC_SIZE 64
9572 #define MAX_DOC_SIZE 32767
9574 #define EXTRA_STACK_ALLOC (256 * 1024)
9576 #define ARGV_STRING_LIST_ID 129
9577 #define ABOUT_ALERT_ID 128
9578 #define RAM_TOO_LARGE_ALERT_ID 129
9580 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9581 Lisp_Object Qreverse
;
9584 /* Modifier associated with the control key, or nil to ignore. */
9585 Lisp_Object Vmac_control_modifier
;
9587 /* Modifier associated with the option key, or nil to ignore. */
9588 Lisp_Object Vmac_option_modifier
;
9590 /* Modifier associated with the command key, or nil to ignore. */
9591 Lisp_Object Vmac_command_modifier
;
9593 /* Modifier associated with the function key, or nil to ignore. */
9594 Lisp_Object Vmac_function_modifier
;
9596 /* True if the option and command modifiers should be used to emulate
9597 a three button mouse */
9598 Lisp_Object Vmac_emulate_three_button_mouse
;
9600 #if TARGET_API_MAC_CARBON
9601 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9602 mouse-2, instead of mouse-3. */
9603 int mac_wheel_button_is_mouse_2
;
9605 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9606 for processing before Emacs sees it. */
9607 int mac_pass_command_to_system
;
9609 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9610 for processing before Emacs sees it. */
9611 int mac_pass_control_to_system
;
9614 /* Points to the variable `inev' in the function XTread_socket. It is
9615 used for passing an input event to the function back from
9616 Carbon/Apple event handlers. */
9617 static struct input_event
*read_socket_inev
= NULL
;
9619 /* Whether or not the screen configuration has changed. */
9620 static int mac_screen_config_changed
= 0;
9622 Point saved_menu_event_location
;
9625 #if TARGET_API_MAC_CARBON
9626 static Lisp_Object Qhi_command
;
9628 extern Lisp_Object Qwindow
;
9629 static Lisp_Object Qtoolbar_switch_mode
;
9632 static TSMDocumentID tsm_document_id
;
9633 static Lisp_Object Qtext_input
;
9634 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9635 static Lisp_Object Vmac_ts_active_input_overlay
;
9636 extern Lisp_Object Qbefore_string
;
9637 static Lisp_Object Vmac_ts_script_language_on_focus
;
9638 static Lisp_Object saved_ts_script_language_on_focus
;
9639 static ScriptLanguageRecord saved_ts_language
;
9640 static Component saved_ts_component
;
9642 #endif /* TARGET_API_MAC_CARBON */
9643 extern int mac_ready_for_apple_events
;
9644 extern Lisp_Object Qundefined
;
9645 extern void init_apple_event_handler
P_ ((void));
9646 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9647 Lisp_Object
*, Lisp_Object
*,
9649 extern OSErr init_coercion_handler
P_ ((void));
9652 extern OSErr install_drag_handler
P_ ((WindowRef
));
9653 extern void remove_drag_handler
P_ ((WindowRef
));
9655 #if TARGET_API_MAC_CARBON
9656 /* Showing help echo string during menu tracking */
9657 extern OSStatus install_menu_target_item_handler
P_ ((void));
9660 extern OSStatus
install_service_handler ();
9661 static Lisp_Object Qservice
, Qpaste
, Qperform
;
9665 extern void init_emacs_passwd_dir ();
9666 extern int emacs_main (int, char **, char **);
9668 extern void initialize_applescript();
9669 extern void terminate_applescript();
9671 /* Table for translating Mac keycode to X keysym values. Contributed
9673 Mapping for special keys is now identical to that in Apple X11
9674 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9675 on the right of the Cmd key on laptops, and fn + `enter' (->
9677 static const unsigned char keycode_to_xkeysym_table
[] = {
9678 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9679 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9680 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9682 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9683 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9684 /*0x38*/ 0, 0, 0, 0,
9685 /*0x3C*/ 0, 0, 0, 0,
9687 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9688 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9689 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9690 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9692 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9693 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9694 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9695 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9697 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9698 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9699 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9700 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9702 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9703 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9704 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9705 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9709 /* Table for translating Mac keycode with the laptop `fn' key to that
9710 without it. Destination symbols in comments are keys on US
9711 keyboard, and they may not be the same on other types of keyboards.
9712 If the destination is identical to the source, it doesn't map `fn'
9713 key to a modifier. */
9714 static const unsigned char fn_keycode_to_keycode_table
[] = {
9715 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9716 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9717 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9719 /*0x30*/ 0, 0, 0, 0,
9720 /*0x34*/ 0, 0, 0, 0,
9721 /*0x38*/ 0, 0, 0, 0,
9722 /*0x3C*/ 0, 0, 0, 0,
9724 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9725 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9726 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9727 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9729 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9730 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9731 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9732 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9734 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9735 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9736 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
9737 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9739 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
9740 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9741 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
9742 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
9744 #endif /* MAC_OSX */
9747 #if TARGET_API_MAC_CARBON
9748 mac_to_emacs_modifiers (UInt32 mods
, UInt32 unmapped_mods
)
9750 mac_to_emacs_modifiers (EventModifiers mods
, EventModifiers unmapped_mods
)
9753 unsigned int result
= 0;
9754 if ((mods
| unmapped_mods
) & shiftKey
)
9755 result
|= shift_modifier
;
9757 /* Deactivated to simplify configuration:
9758 if Vmac_option_modifier is non-NIL, we fully process the Option
9759 key. Otherwise, we only process it if an additional Ctrl or Command
9760 is pressed. That way the system may convert the character to a
9762 if ((mods & optionKey) &&
9763 (( !NILP(Vmac_option_modifier) ||
9764 ((mods & cmdKey) || (mods & controlKey))))) */
9766 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9767 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9769 result
|= XUINT(val
);
9771 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9772 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9774 result
|= XUINT(val
);
9776 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9777 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9779 result
|= XUINT(val
);
9783 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9784 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9786 result
|= XUINT(val
);
9794 mac_mapped_modifiers (modifiers
, key_code
)
9795 UInt32 modifiers
, key_code
;
9797 UInt32 mapped_modifiers_all
=
9798 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9799 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9800 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9803 mapped_modifiers_all
|=
9804 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9806 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
9807 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
9808 no longer means laptop's `fn' key is down for the following keys:
9809 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
9810 Down, the arrow keys, and Clear. We ignore the corresponding bit
9811 if that key can be entered without the `fn' key on laptops. */
9812 if (modifiers
& kEventKeyModifierFnMask
9814 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
9815 modifiers
&= ~kEventKeyModifierFnMask
;
9818 return mapped_modifiers_all
& modifiers
;
9822 mac_get_emulated_btn ( UInt32 modifiers
)
9825 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9826 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9827 if (modifiers
& cmdKey
)
9828 result
= cmdIs3
? 2 : 1;
9829 else if (modifiers
& optionKey
)
9830 result
= cmdIs3
? 1 : 2;
9835 #if TARGET_API_MAC_CARBON
9836 /***** Code to handle C-g testing *****/
9837 extern int quit_char
;
9838 extern int make_ctrl_char
P_ ((int));
9841 mac_quit_char_key_p (modifiers
, key_code
)
9842 UInt32 modifiers
, key_code
;
9844 UInt32 char_code
, mapped_modifiers
;
9845 unsigned long some_state
= 0;
9846 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9847 int c
, emacs_modifiers
;
9849 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9850 mapped_modifiers
= mac_mapped_modifiers (modifiers
, key_code
);
9851 key_code
|= (modifiers
& ~mapped_modifiers
);
9852 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9853 if (char_code
& ~0xff)
9856 emacs_modifiers
= mac_to_emacs_modifiers (mapped_modifiers
, modifiers
);
9857 if (emacs_modifiers
& ctrl_modifier
)
9858 c
= make_ctrl_char (char_code
);
9860 c
|= (emacs_modifiers
9861 & (meta_modifier
| alt_modifier
9862 | hyper_modifier
| super_modifier
));
9864 return c
== quit_char
;
9868 #if TARGET_API_MAC_CARBON
9869 /* Obtains the event modifiers from the event ref and then calls
9870 mac_to_emacs_modifiers. */
9872 mac_event_to_emacs_modifiers (EventRef eventRef
)
9874 UInt32 mods
= 0, class;
9876 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9877 sizeof (UInt32
), NULL
, &mods
);
9878 class = GetEventClass (eventRef
);
9879 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9880 (class == kEventClassMouse
|| class == kEventClassCommand
))
9882 mods
&= ~(optionKey
| cmdKey
);
9884 return mac_to_emacs_modifiers (mods
, 0);
9887 /* Given an event ref, return the code to use for the mouse button
9888 code in the emacs input_event. */
9890 mac_get_mouse_btn (EventRef ref
)
9892 EventMouseButton result
= kEventMouseButtonPrimary
;
9893 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9894 sizeof (EventMouseButton
), NULL
, &result
);
9897 case kEventMouseButtonPrimary
:
9898 if (NILP (Vmac_emulate_three_button_mouse
))
9902 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9903 sizeof (UInt32
), NULL
, &mods
);
9904 return mac_get_emulated_btn(mods
);
9906 case kEventMouseButtonSecondary
:
9907 return mac_wheel_button_is_mouse_2
? 2 : 1;
9908 case kEventMouseButtonTertiary
:
9909 case 4: /* 4 is the number for the mouse wheel button */
9910 return mac_wheel_button_is_mouse_2
? 1 : 2;
9916 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9917 events. However the click of the mouse wheel is not converted to a
9918 mouseDown or mouseUp event. Likewise for dead key events. This
9919 calls ConvertEventRefToEventRecord, but then checks to see if it is
9920 a mouse up/down, or a dead key Carbon event that has not been
9921 converted, and if so, converts it by hand (to be picked up in the
9922 XTread_socket loop). */
9923 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9926 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9932 switch (GetEventClass (eventRef
))
9934 case kEventClassMouse
:
9935 switch (GetEventKind (eventRef
))
9937 case kEventMouseDown
:
9938 eventRec
->what
= mouseDown
;
9943 eventRec
->what
= mouseUp
;
9952 case kEventClassKeyboard
:
9953 switch (GetEventKind (eventRef
))
9955 case kEventRawKeyDown
:
9957 goto keystroke_common
;
9958 case kEventRawKeyRepeat
:
9960 goto keystroke_common
;
9961 case kEventRawKeyUp
:
9965 unsigned char char_codes
;
9968 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9969 typeChar
, NULL
, sizeof (char),
9972 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9973 typeUInt32
, NULL
, sizeof (UInt32
),
9977 eventRec
->what
= action
;
9978 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9995 /* Need where and when. */
9998 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9999 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
10000 /* Use two step process because new event modifiers are 32-bit
10001 and old are 16-bit. Currently, only loss is NumLock & Fn. */
10002 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
10003 NULL
, sizeof (UInt32
), NULL
, &mods
);
10004 eventRec
->modifiers
= mods
;
10006 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
10016 do_get_menus (void)
10018 Handle menubar_handle
;
10021 menubar_handle
= GetNewMBar (128);
10022 if(menubar_handle
== NULL
)
10024 SetMenuBar (menubar_handle
);
10027 #if !TARGET_API_MAC_CARBON
10028 menu
= GetMenuRef (M_APPLE
);
10030 AppendResMenu (menu
, 'DRVR');
10038 do_init_managers (void)
10040 #if !TARGET_API_MAC_CARBON
10041 InitGraf (&qd
.thePort
);
10043 FlushEvents (everyEvent
, 0);
10047 InitDialogs (NULL
);
10048 #endif /* !TARGET_API_MAC_CARBON */
10051 #if !TARGET_API_MAC_CARBON
10052 /* set up some extra stack space for use by emacs */
10053 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10055 /* MaxApplZone must be called for AppleScript to execute more
10056 complicated scripts */
10059 #endif /* !TARGET_API_MAC_CARBON */
10063 do_check_ram_size (void)
10065 SInt32 physical_ram_size
, logical_ram_size
;
10067 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10068 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10069 || physical_ram_size
> (1 << VALBITS
)
10070 || logical_ram_size
> (1 << VALBITS
))
10072 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10076 #endif /* MAC_OS8 */
10079 do_window_update (WindowRef win
)
10081 struct frame
*f
= mac_window_to_frame (win
);
10085 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10087 if (win
!= tip_window
)
10089 if (f
->async_visible
== 0)
10091 /* Update events may occur when a frame gets iconified. */
10093 f
->async_visible
= 1;
10094 f
->async_iconified
= 0;
10095 SET_FRAME_GARBAGED (f
);
10101 #if TARGET_API_MAC_CARBON
10102 RgnHandle region
= NewRgn ();
10104 GetPortVisibleRegion (GetWindowPort (win
), region
);
10105 GetRegionBounds (region
, &r
);
10106 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10108 mac_prepare_for_quickdraw (f
);
10110 UpdateControls (win
, region
);
10111 DisposeRgn (region
);
10113 r
= (*win
->visRgn
)->rgnBBox
;
10114 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10115 UpdateControls (win
, win
->visRgn
);
10124 is_emacs_window (WindowRef win
)
10126 Lisp_Object tail
, frame
;
10131 FOR_EACH_FRAME (tail
, frame
)
10132 if (FRAME_MAC_P (XFRAME (frame
)))
10133 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10144 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10146 err
= ActivateTSMDocument (tsm_document_id
);
10150 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10151 && EQ (saved_ts_script_language_on_focus
, Qt
))
10152 slptr
= &saved_ts_language
;
10153 else if (CONSP (Vmac_ts_script_language_on_focus
)
10154 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10155 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10156 && CONSP (saved_ts_script_language_on_focus
)
10157 && EQ (XCAR (saved_ts_script_language_on_focus
),
10158 XCAR (Vmac_ts_script_language_on_focus
))
10159 && EQ (XCDR (saved_ts_script_language_on_focus
),
10160 XCDR (Vmac_ts_script_language_on_focus
)))
10162 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10163 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10170 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10171 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10172 kKeyboardInputMethodClass
);
10174 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10177 err
= SetTextServiceLanguage (slptr
);
10179 /* Seems to be needed on Mac OS X 10.2. */
10181 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10191 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10193 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10195 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10197 err
= GetTextServiceLanguage (&saved_ts_language
);
10199 slptr
= &saved_ts_language
;
10201 else if (CONSP (Vmac_ts_script_language_on_focus
)
10202 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10203 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10205 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10206 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10212 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10213 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10214 kKeyboardInputMethodClass
);
10216 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10220 err
= DeactivateTSMDocument (tsm_document_id
);
10226 #if !TARGET_API_MAC_CARBON
10228 do_apple_menu (SInt16 menu_item
)
10231 SInt16 da_driver_refnum
;
10233 if (menu_item
== I_ABOUT
)
10234 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10237 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10238 da_driver_refnum
= OpenDeskAcc (item_name
);
10241 #endif /* !TARGET_API_MAC_CARBON */
10243 /* Handle drags in size box. Based on code contributed by Ben
10244 Mesander and IM - Window Manager A. */
10247 do_grow_window (w
, e
)
10249 const EventRecord
*e
;
10252 int rows
, columns
, width
, height
;
10253 struct frame
*f
= mac_window_to_frame (w
);
10254 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10255 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10256 #if TARGET_API_MAC_CARBON
10262 if (size_hints
->flags
& PMinSize
)
10264 min_width
= size_hints
->min_width
;
10265 min_height
= size_hints
->min_height
;
10267 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10269 #if TARGET_API_MAC_CARBON
10270 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10272 height
= new_rect
.bottom
- new_rect
.top
;
10273 width
= new_rect
.right
- new_rect
.left
;
10275 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10276 /* see if it really changed size */
10277 if (grow_size
== 0)
10279 height
= HiWord (grow_size
);
10280 width
= LoWord (grow_size
);
10283 if (width
!= FRAME_PIXEL_WIDTH (f
)
10284 || height
!= FRAME_PIXEL_HEIGHT (f
))
10286 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10287 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10289 x_set_window_size (f
, 0, columns
, rows
);
10294 #if TARGET_API_MAC_CARBON
10296 mac_get_ideal_size (f
)
10299 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10300 WindowRef w
= FRAME_MAC_WINDOW (f
);
10302 Rect standard_rect
;
10303 int height
, width
, columns
, rows
;
10305 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10306 ideal_size
.v
= dpyinfo
->height
;
10307 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10308 /* Adjust the standard size according to character boundaries. */
10309 width
= standard_rect
.right
- standard_rect
.left
;
10310 height
= standard_rect
.bottom
- standard_rect
.top
;
10311 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10312 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10313 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10314 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10320 /* Handle clicks in zoom box. Calculation of "standard state" based
10321 on code in IM - Window Manager A and code contributed by Ben
10322 Mesander. The standard state of an Emacs window is 80-characters
10323 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10326 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10328 Rect zoom_rect
, port_rect
;
10330 struct frame
*f
= mac_window_to_frame (w
);
10331 #if TARGET_API_MAC_CARBON
10332 Point ideal_size
= mac_get_ideal_size (f
);
10334 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10335 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10336 && port_rect
.left
== zoom_rect
.left
10337 && port_rect
.top
== zoom_rect
.top
)
10338 zoom_in_or_out
= inZoomIn
;
10340 zoom_in_or_out
= inZoomOut
;
10343 mac_clear_window (f
);
10345 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10346 #else /* not TARGET_API_MAC_CARBON */
10349 int w_title_height
, rows
;
10350 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10352 GetPort (&save_port
);
10354 SetPortWindowPort (w
);
10356 /* Clear window to avoid flicker. */
10357 EraseRect (&(w
->portRect
));
10358 if (zoom_in_or_out
== inZoomOut
)
10360 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10361 LocalToGlobal (&top_left
);
10363 /* calculate height of window's title bar */
10364 w_title_height
= top_left
.v
- 1
10365 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10367 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10368 zoom_rect
= qd
.screenBits
.bounds
;
10369 zoom_rect
.top
+= w_title_height
;
10370 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10372 zoom_rect
.right
= zoom_rect
.left
10373 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10375 /* Adjust the standard size according to character boundaries. */
10376 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10378 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10380 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10384 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10386 SetPort (save_port
);
10387 #endif /* not TARGET_API_MAC_CARBON */
10389 #if !TARGET_API_MAC_CARBON
10390 /* retrieve window size and update application values */
10391 port_rect
= w
->portRect
;
10392 height
= port_rect
.bottom
- port_rect
.top
;
10393 width
= port_rect
.right
- port_rect
.left
;
10395 mac_handle_size_change (f
, width
, height
);
10396 mac_handle_origin_change (f
);
10401 mac_set_unicode_keystroke_event (code
, buf
)
10403 struct input_event
*buf
;
10405 int charset_id
, c1
, c2
;
10409 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10412 else if (code
< 0x100)
10415 charset_id
= CHARSET_8_BIT_CONTROL
;
10417 charset_id
= charset_latin_iso8859_1
;
10418 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10419 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10424 charset_id
= charset_mule_unicode_0100_24ff
,
10426 else if (code
< 0x33FF)
10427 charset_id
= charset_mule_unicode_2500_33ff
,
10429 else if (code
>= 0xE000)
10430 charset_id
= charset_mule_unicode_e000_ffff
,
10432 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10433 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10434 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10439 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10441 unsigned char char_code
;
10442 UInt32 key_code
, modifiers
;
10443 unsigned long timestamp
;
10444 struct input_event
*buf
;
10446 static SInt16 last_key_script
= -1;
10447 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10448 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
, key_code
);
10451 if (mapped_modifiers
& kEventKeyModifierFnMask
10452 && key_code
<= 0x7f
10453 && fn_keycode_to_keycode_table
[key_code
])
10454 key_code
= fn_keycode_to_keycode_table
[key_code
];
10457 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10459 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10460 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10462 else if (mapped_modifiers
)
10464 /* translate the keycode back to determine the original key */
10466 UCKeyboardLayout
*uchr_ptr
= NULL
;
10467 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10469 KeyboardLayoutRef layout
;
10471 err
= KLGetCurrentKeyboardLayout (&layout
);
10473 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10474 (const void **) &uchr_ptr
);
10476 static SInt16 last_key_layout_id
= 0;
10477 static Handle uchr_handle
= (Handle
)-1;
10478 SInt16 current_key_layout_id
=
10479 GetScriptVariable (current_key_script
, smScriptKeys
);
10481 if (uchr_handle
== (Handle
)-1
10482 || last_key_layout_id
!= current_key_layout_id
)
10484 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10485 last_key_layout_id
= current_key_layout_id
;
10488 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10494 UInt16 key_action
= action
- keyDown
;
10495 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10496 UInt32 keyboard_type
= LMGetKbdType ();
10497 SInt32 dead_key_state
= 0;
10499 UniCharCount actual_length
;
10501 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10502 modifier_key_state
, keyboard_type
,
10503 kUCKeyTranslateNoDeadKeysMask
,
10505 1, &actual_length
, &code
);
10506 if (status
== noErr
&& actual_length
== 1)
10507 mac_set_unicode_keystroke_event (code
, buf
);
10509 #endif /* MAC_OSX */
10511 if (buf
->kind
== NO_EVENT
)
10513 /* This code comes from Keyboard Resource, Appendix C of IM
10514 - Text. This is necessary since shift is ignored in KCHR
10515 table translation when option or command is pressed. It
10516 also does not translate correctly control-shift chars
10517 like C-% so mask off shift here also. */
10518 /* Mask off modifier keys that are mapped to some Emacs
10520 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10521 /* set high byte of keycode to modifier high byte*/
10522 int new_key_code
= key_code
| new_modifiers
;
10523 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10524 unsigned long some_state
= 0;
10525 UInt32 new_char_code
;
10527 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10528 if (new_char_code
== 0)
10529 /* Seems like a dead key. Append up-stroke. */
10530 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10534 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10535 buf
->code
= new_char_code
& 0xff;
10540 if (buf
->kind
== NO_EVENT
)
10542 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10543 buf
->code
= char_code
;
10546 buf
->modifiers
= mac_to_emacs_modifiers (mapped_modifiers
, modifiers
);
10547 buf
->modifiers
|= (extra_keyboard_modifiers
10548 & (meta_modifier
| alt_modifier
10549 | hyper_modifier
| super_modifier
));
10551 #if TARGET_API_MAC_CARBON
10552 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10553 && buf
->code
>= 0x80 && buf
->modifiers
)
10556 TextEncoding encoding
= kTextEncodingMacRoman
;
10557 TextToUnicodeInfo ttu_info
;
10559 UpgradeScriptInfoToTextEncoding (current_key_script
,
10560 kTextLanguageDontCare
,
10561 kTextRegionDontCare
,
10563 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10568 ByteCount unicode_len
;
10571 pstr
[1] = buf
->code
;
10572 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10574 &unicode_len
, &code
);
10575 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10576 mac_set_unicode_keystroke_event (code
, buf
);
10577 DisposeTextToUnicodeInfo (&ttu_info
);
10582 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10583 && buf
->code
>= 0x80
10584 && last_key_script
!= current_key_script
)
10586 struct input_event event
;
10588 EVENT_INIT (event
);
10589 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10591 event
.code
= current_key_script
;
10592 event
.timestamp
= timestamp
;
10593 kbd_buffer_store_event (&event
);
10594 last_key_script
= current_key_script
;
10599 mac_store_apple_event (class, id
, desc
)
10600 Lisp_Object
class, id
;
10601 const AEDesc
*desc
;
10603 struct input_event buf
;
10607 buf
.kind
= MAC_APPLE_EVENT
;
10610 XSETFRAME (buf
.frame_or_window
,
10611 mac_focus_frame (&one_mac_display_info
));
10612 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10613 is safe to use them during read_socket_hook. */
10614 buf
.arg
= mac_aedesc_to_lisp (desc
);
10615 kbd_buffer_store_event (&buf
);
10618 #if TARGET_API_MAC_CARBON
10620 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10621 event
, num_params
, names
, types
)
10622 AEEventClass
class;
10624 Lisp_Object class_key
, id_key
;
10627 const EventParamName
*names
;
10628 const EventParamType
*types
;
10630 OSStatus err
= eventNotHandledErr
;
10631 Lisp_Object binding
;
10633 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10634 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10636 if (INTEGERP (binding
))
10637 err
= XINT (binding
);
10640 AppleEvent apple_event
;
10641 err
= create_apple_event_from_event_ref (event
, num_params
,
10646 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10647 AEDisposeDesc (&apple_event
);
10648 mac_wakeup_from_rne ();
10657 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10661 const AEDesc
*desc
;
10663 struct input_event buf
;
10667 buf
.kind
= DRAG_N_DROP_EVENT
;
10668 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
, 0);
10669 buf
.timestamp
= TickCount () * (1000 / 60);
10670 XSETINT (buf
.x
, mouse_pos
.h
);
10671 XSETINT (buf
.y
, mouse_pos
.v
);
10672 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10673 buf
.arg
= mac_aedesc_to_lisp (desc
);
10674 kbd_buffer_store_event (&buf
);
10679 mac_store_service_event (event
)
10683 Lisp_Object id_key
;
10685 const EventParamName
*names
;
10686 const EventParamType
*types
;
10687 static const EventParamName names_pfm
[] =
10688 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10689 static const EventParamType types_pfm
[] =
10690 {typeCFStringRef
, typeCFStringRef
};
10692 switch (GetEventKind (event
))
10694 case kEventServicePaste
:
10701 case kEventServicePerform
:
10703 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10712 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10718 #endif /* MAC_OSX */
10720 static pascal OSStatus
10721 mac_handle_window_event (next_handler
, event
, data
)
10722 EventHandlerCallRef next_handler
;
10727 OSStatus err
, result
= eventNotHandledErr
;
10730 XSizeHints
*size_hints
;
10732 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
10733 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10735 return eventNotHandledErr
;
10737 f
= mac_window_to_frame (wp
);
10738 switch (GetEventKind (event
))
10740 /* -- window refresh events -- */
10742 case kEventWindowUpdate
:
10743 result
= CallNextEventHandler (next_handler
, event
);
10744 if (result
!= eventNotHandledErr
)
10747 do_window_update (wp
);
10751 /* -- window state change events -- */
10753 case kEventWindowShowing
:
10754 size_hints
= FRAME_SIZE_HINTS (f
);
10755 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
10757 struct frame
*sf
= SELECTED_FRAME ();
10759 if (!(FRAME_MAC_P (sf
) && sf
->async_visible
))
10760 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
10763 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
10764 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10765 kWindowCascadeStartAtParentWindowScreen
10767 kWindowCascadeOnParentWindowScreen
10770 #if USE_MAC_TOOLBAR
10771 /* This is a workaround. RepositionWindow fails to put
10772 a window at the cascading position when its parent
10773 window has a Carbon HIToolbar. */
10774 if ((f
->left_pos
== sf
->left_pos
10775 && f
->top_pos
== sf
->top_pos
)
10776 || (f
->left_pos
== sf
->left_pos
+ 10 * 2
10777 && f
->top_pos
== sf
->top_pos
+ 32 * 2))
10778 MoveWindowStructure (wp
, sf
->left_pos
+ 10, sf
->top_pos
+ 32);
10785 case kEventWindowHiding
:
10786 /* Before unmapping the window, update the WM_SIZE_HINTS
10787 property to claim that the current position of the window is
10788 user-specified, rather than program-specified, so that when
10789 the window is mapped again, it will be placed at the same
10790 location, without forcing the user to position it by hand
10791 again (they have already done that once for this window.) */
10792 x_wm_set_size_hint (f
, (long) 0, 1);
10796 case kEventWindowShown
:
10797 case kEventWindowHidden
:
10798 case kEventWindowCollapsed
:
10799 case kEventWindowExpanded
:
10800 mac_handle_visibility_change (f
);
10804 case kEventWindowBoundsChanging
:
10805 result
= CallNextEventHandler (next_handler
, event
);
10806 if (result
!= eventNotHandledErr
)
10809 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10810 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10814 size_hints
= FRAME_SIZE_HINTS (f
);
10815 if ((attributes
& kWindowBoundsChangeUserResize
)
10816 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
10817 == (PResizeInc
| PBaseSize
| PMinSize
)))
10822 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10823 typeQDRectangle
, NULL
, sizeof (Rect
),
10828 width
= bounds
.right
- bounds
.left
;
10829 height
= bounds
.bottom
- bounds
.top
;
10831 if (width
< size_hints
->min_width
)
10832 width
= size_hints
->min_width
;
10834 width
= size_hints
->base_width
10835 + (int) ((width
- size_hints
->base_width
)
10836 / (float) size_hints
->width_inc
+ .5)
10837 * size_hints
->width_inc
;
10839 if (height
< size_hints
->min_height
)
10840 height
= size_hints
->min_height
;
10842 height
= size_hints
->base_height
10843 + (int) ((height
- size_hints
->base_height
)
10844 / (float) size_hints
->height_inc
+ .5)
10845 * size_hints
->height_inc
;
10847 bounds
.right
= bounds
.left
+ width
;
10848 bounds
.bottom
= bounds
.top
+ height
;
10849 SetEventParameter (event
, kEventParamCurrentBounds
,
10850 typeQDRectangle
, sizeof (Rect
), &bounds
);
10855 case kEventWindowBoundsChanged
:
10856 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10857 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10861 if (attributes
& kWindowBoundsChangeSizeChanged
)
10865 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10866 typeQDRectangle
, NULL
, sizeof (Rect
),
10872 width
= bounds
.right
- bounds
.left
;
10873 height
= bounds
.bottom
- bounds
.top
;
10874 mac_handle_size_change (f
, width
, height
);
10875 mac_wakeup_from_rne ();
10879 if (attributes
& kWindowBoundsChangeOriginChanged
)
10880 mac_handle_origin_change (f
);
10885 /* -- window action events -- */
10887 case kEventWindowClose
:
10889 struct input_event buf
;
10892 buf
.kind
= DELETE_WINDOW_EVENT
;
10893 XSETFRAME (buf
.frame_or_window
, f
);
10895 kbd_buffer_store_event (&buf
);
10900 case kEventWindowGetIdealSize
:
10901 result
= CallNextEventHandler (next_handler
, event
);
10902 if (result
!= eventNotHandledErr
)
10906 Point ideal_size
= mac_get_ideal_size (f
);
10908 err
= SetEventParameter (event
, kEventParamDimensions
,
10909 typeQDPoint
, sizeof (Point
), &ideal_size
);
10916 case kEventWindowToolbarSwitchMode
:
10918 static const EventParamName names
[] = {kEventParamDirectObject
,
10919 kEventParamWindowMouseLocation
,
10920 kEventParamKeyModifiers
,
10921 kEventParamMouseButton
,
10922 kEventParamClickCount
,
10923 kEventParamMouseChord
};
10924 static const EventParamType types
[] = {typeWindowRef
,
10930 int num_params
= sizeof (names
) / sizeof (names
[0]);
10932 err
= mac_store_event_ref_as_apple_event (0, 0,
10934 Qtoolbar_switch_mode
,
10944 /* -- window focus events -- */
10946 case kEventWindowFocusAcquired
:
10947 err
= mac_tsm_resume ();
10952 case kEventWindowFocusRelinquish
:
10953 err
= mac_tsm_suspend ();
10966 static pascal OSStatus
10967 mac_handle_keyboard_event (next_handler
, event
, data
)
10968 EventHandlerCallRef next_handler
;
10972 OSStatus err
, result
= eventNotHandledErr
;
10973 UInt32 event_kind
, key_code
, modifiers
;
10974 unsigned char char_code
;
10976 event_kind
= GetEventKind (event
);
10977 switch (event_kind
)
10979 case kEventRawKeyDown
:
10980 case kEventRawKeyRepeat
:
10981 case kEventRawKeyUp
:
10982 /* When using Carbon Events, we need to pass raw keyboard events
10983 to the TSM ourselves. If TSM handles it, it will pass back
10984 noErr, otherwise it will pass back "eventNotHandledErr" and
10985 we can process it normally. */
10986 result
= CallNextEventHandler (next_handler
, event
);
10987 if (result
!= eventNotHandledErr
)
10990 if (read_socket_inev
== NULL
)
10994 if (read_socket_inev
->kind
!= NO_EVENT
)
11001 if (event_kind
== kEventRawKeyUp
)
11004 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11006 sizeof (char), NULL
, &char_code
);
11010 err
= GetEventParameter (event
, kEventParamKeyCode
,
11012 sizeof (UInt32
), NULL
, &key_code
);
11016 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
11018 sizeof (UInt32
), NULL
, &modifiers
);
11022 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11023 char_code
, key_code
, modifiers
,
11025 (GetEventTime (event
) / kEventDurationMillisecond
)),
11037 static pascal OSStatus
11038 mac_handle_command_event (next_handler
, event
, data
)
11039 EventHandlerCallRef next_handler
;
11043 OSStatus err
, result
= eventNotHandledErr
;
11045 static const EventParamName names
[] =
11046 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11047 static const EventParamType types
[] =
11048 {typeHICommand
, typeUInt32
};
11049 int num_params
= sizeof (names
) / sizeof (names
[0]);
11051 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11052 NULL
, sizeof (HICommand
), NULL
, &command
);
11054 return eventNotHandledErr
;
11056 switch (GetEventKind (event
))
11058 case kEventCommandProcess
:
11059 result
= CallNextEventHandler (next_handler
, event
);
11060 if (result
!= eventNotHandledErr
)
11063 err
= GetEventParameter (event
, kEventParamDirectObject
,
11064 typeHICommand
, NULL
,
11065 sizeof (HICommand
), NULL
, &command
);
11067 if (err
!= noErr
|| command
.commandID
== 0)
11070 /* A HI command event is mapped to an Apple event whose event
11071 class symbol is `hi-command' and event ID is its command
11073 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11088 static pascal OSStatus
11089 mac_handle_mouse_event (next_handler
, event
, data
)
11090 EventHandlerCallRef next_handler
;
11094 OSStatus err
, result
= eventNotHandledErr
;
11096 switch (GetEventKind (event
))
11098 case kEventMouseWheelMoved
:
11102 EventMouseWheelAxis axis
;
11106 result
= CallNextEventHandler (next_handler
, event
);
11107 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11110 f
= mac_focus_frame (&one_mac_display_info
);
11112 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11113 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11115 || wp
!= FRAME_MAC_WINDOW (f
))
11118 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11119 typeMouseWheelAxis
, NULL
,
11120 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11121 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11124 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11125 typeQDPoint
, NULL
, sizeof (Point
),
11130 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11131 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11132 if (point
.h
< 0 || point
.v
< 0
11133 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11134 f
->tool_bar_window
))
11137 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11138 typeSInt32
, NULL
, sizeof (SInt32
),
11143 read_socket_inev
->kind
= WHEEL_EVENT
;
11144 read_socket_inev
->code
= 0;
11145 read_socket_inev
->modifiers
=
11146 (mac_event_to_emacs_modifiers (event
)
11147 | ((delta
< 0) ? down_modifier
: up_modifier
));
11148 XSETINT (read_socket_inev
->x
, point
.h
);
11149 XSETINT (read_socket_inev
->y
, point
.v
);
11150 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11164 static pascal OSStatus
11165 mac_handle_text_input_event (next_handler
, event
, data
)
11166 EventHandlerCallRef next_handler
;
11170 OSStatus err
, result
;
11171 Lisp_Object id_key
= Qnil
;
11173 const EventParamName
*names
;
11174 const EventParamType
*types
;
11175 static UInt32 seqno_uaia
= 0;
11176 static const EventParamName names_uaia
[] =
11177 {kEventParamTextInputSendComponentInstance
,
11178 kEventParamTextInputSendRefCon
,
11179 kEventParamTextInputSendSLRec
,
11180 kEventParamTextInputSendFixLen
,
11181 kEventParamTextInputSendText
,
11182 kEventParamTextInputSendUpdateRng
,
11183 kEventParamTextInputSendHiliteRng
,
11184 kEventParamTextInputSendClauseRng
,
11185 kEventParamTextInputSendPinRng
,
11186 kEventParamTextInputSendTextServiceEncoding
,
11187 kEventParamTextInputSendTextServiceMacEncoding
,
11188 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11189 static const EventParamType types_uaia
[] =
11190 {typeComponentInstance
,
11192 typeIntlWritingCode
,
11199 typeTextRangeArray
,
11200 typeTextRangeArray
,
11206 static const EventParamName names_ufke
[] =
11207 {kEventParamTextInputSendComponentInstance
,
11208 kEventParamTextInputSendRefCon
,
11209 kEventParamTextInputSendSLRec
,
11210 kEventParamTextInputSendText
};
11211 static const EventParamType types_ufke
[] =
11212 {typeComponentInstance
,
11214 typeIntlWritingCode
,
11217 result
= CallNextEventHandler (next_handler
, event
);
11218 if (result
!= eventNotHandledErr
)
11221 switch (GetEventKind (event
))
11223 case kEventTextInputUpdateActiveInputArea
:
11224 id_key
= Qupdate_active_input_area
;
11225 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11226 names
= names_uaia
;
11227 types
= types_uaia
;
11228 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11229 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11234 case kEventTextInputUnicodeForKeyEvent
:
11236 EventRef kbd_event
;
11237 UInt32 actual_size
, modifiers
, key_code
;
11239 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11240 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11243 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11245 sizeof (UInt32
), NULL
, &modifiers
);
11247 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11248 typeUInt32
, NULL
, sizeof (UInt32
),
11250 if (err
== noErr
&& mac_mapped_modifiers (modifiers
, key_code
))
11251 /* There're mapped modifier keys. Process it in
11255 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11256 typeUnicodeText
, NULL
, 0, &actual_size
,
11258 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11262 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11263 typeUnicodeText
, NULL
,
11264 sizeof (UniChar
), NULL
, &code
);
11265 if (err
== noErr
&& code
< 0x80)
11267 /* ASCII character. Process it in do_keystroke. */
11268 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e
11269 && !(key_code
<= 0x7f
11270 && keycode_to_xkeysym_table
[key_code
]))
11272 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
11274 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11275 read_socket_inev
->code
= code
;
11276 read_socket_inev
->modifiers
=
11277 mac_to_emacs_modifiers (modifiers
, 0);
11278 read_socket_inev
->modifiers
|=
11279 (extra_keyboard_modifiers
11280 & (meta_modifier
| alt_modifier
11281 | hyper_modifier
| super_modifier
));
11282 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11289 /* Non-ASCII keystrokes without mapped modifiers are
11290 processed at the Lisp level. */
11291 id_key
= Qunicode_for_key_event
;
11292 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11293 names
= names_ufke
;
11294 types
= types_ufke
;
11300 case kEventTextInputOffsetToPos
:
11306 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11309 /* Strictly speaking, this is not always correct because
11310 previous events may change some states about display. */
11311 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11313 /* Active input area is displayed around the current point. */
11314 f
= SELECTED_FRAME ();
11315 w
= XWINDOW (f
->selected_window
);
11317 else if (WINDOWP (echo_area_window
))
11319 /* Active input area is displayed in the echo area. */
11320 w
= XWINDOW (echo_area_window
);
11321 f
= WINDOW_XFRAME (w
);
11326 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11327 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11328 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11329 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11330 + FONT_BASE (FRAME_FONT (f
))
11331 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11332 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11333 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11343 if (!NILP (id_key
))
11344 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11350 #endif /* TARGET_API_MAC_CARBON */
11354 install_window_handler (window
)
11357 OSStatus err
= noErr
;
11359 #if TARGET_API_MAC_CARBON
11362 static const EventTypeSpec specs
[] =
11364 /* -- window refresh events -- */
11365 {kEventClassWindow
, kEventWindowUpdate
},
11366 /* -- window state change events -- */
11367 {kEventClassWindow
, kEventWindowShowing
},
11368 {kEventClassWindow
, kEventWindowHiding
},
11369 {kEventClassWindow
, kEventWindowShown
},
11370 {kEventClassWindow
, kEventWindowHidden
},
11371 {kEventClassWindow
, kEventWindowCollapsed
},
11372 {kEventClassWindow
, kEventWindowExpanded
},
11373 {kEventClassWindow
, kEventWindowBoundsChanging
},
11374 {kEventClassWindow
, kEventWindowBoundsChanged
},
11375 /* -- window action events -- */
11376 {kEventClassWindow
, kEventWindowClose
},
11377 {kEventClassWindow
, kEventWindowGetIdealSize
},
11379 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11382 /* -- window focus events -- */
11383 {kEventClassWindow
, kEventWindowFocusAcquired
},
11384 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11387 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11389 if (handle_window_eventUPP
== NULL
)
11390 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11392 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11393 GetEventTypeCount (specs
),
11394 specs
, NULL
, NULL
);
11399 err
= install_drag_handler (window
);
11405 remove_window_handler (window
)
11408 remove_drag_handler (window
);
11411 #if TARGET_API_MAC_CARBON
11413 install_application_handler ()
11415 OSStatus err
= noErr
;
11419 static const EventTypeSpec specs
[] =
11420 {{kEventClassKeyboard
, kEventRawKeyDown
},
11421 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11422 {kEventClassKeyboard
, kEventRawKeyUp
}};
11424 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11425 (mac_handle_keyboard_event
),
11426 GetEventTypeCount (specs
),
11427 specs
, NULL
, NULL
);
11432 static const EventTypeSpec specs
[] =
11433 {{kEventClassCommand
, kEventCommandProcess
}};
11435 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11436 (mac_handle_command_event
),
11437 GetEventTypeCount (specs
),
11438 specs
, NULL
, NULL
);
11443 static const EventTypeSpec specs
[] =
11444 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11446 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11447 (mac_handle_mouse_event
),
11448 GetEventTypeCount (specs
),
11449 specs
, NULL
, NULL
);
11455 static const EventTypeSpec spec
[] =
11456 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11457 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11458 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11460 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11461 (mac_handle_text_input_event
),
11462 GetEventTypeCount (spec
),
11468 err
= install_menu_target_item_handler ();
11472 err
= install_service_handler ();
11480 mac_handle_dm_notification (event
)
11483 mac_screen_config_changed
= 1;
11486 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11488 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11489 CGDirectDisplayID display
;
11490 CGDisplayChangeSummaryFlags flags
;
11493 mac_screen_config_changed
= 1;
11498 init_dm_notification_handler ()
11502 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11503 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11504 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11507 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11510 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11511 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11513 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11514 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11516 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11517 ProcessSerialNumber psn
;
11519 if (handle_dm_notificationUPP
== NULL
)
11520 handle_dm_notificationUPP
=
11521 NewDMNotificationUPP (mac_handle_dm_notification
);
11523 err
= GetCurrentProcess (&psn
);
11525 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11533 mac_get_screen_info (dpyinfo
)
11534 struct mac_display_info
*dpyinfo
;
11537 /* HasDepth returns true if it is possible to have a 32 bit display,
11538 but this may not be what is actually used. Mac OSX can do better. */
11539 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11540 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11543 CGDisplayCount ndisps
;
11544 CGDirectDisplayID
*displays
;
11546 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11549 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11550 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11554 CGRect bounds
= CGRectZero
;
11556 while (ndisps
-- > 0)
11557 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11558 dpyinfo
->height
= CGRectGetHeight (bounds
);
11559 dpyinfo
->width
= CGRectGetWidth (bounds
);
11563 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11564 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11567 #else /* !MAC_OSX */
11569 GDHandle gdh
= GetMainDevice ();
11570 Rect rect
= (**gdh
).gdRect
;
11572 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11573 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11574 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11577 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11578 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11579 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11581 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11582 dpyinfo
->width
= rect
.right
- rect
.left
;
11584 #endif /* !MAC_OSX */
11590 profiler_exit_proc ()
11592 ProfilerDump ("\pEmacs.prof");
11597 /* These few functions implement Emacs as a normal Mac application
11598 (almost): set up the heap and the Toolbox, handle necessary system
11599 events plus a few simple menu events. They also set up Emacs's
11600 access to functions defined in the rest of this file. Emacs uses
11601 function hooks to perform all its terminal I/O. A complete list of
11602 these functions appear in termhooks.h. For what they do, read the
11603 comments there and see also w32term.c and xterm.c. What's
11604 noticeably missing here is the event loop, which is normally
11605 present in most Mac application. After performing the necessary
11606 Mac initializations, main passes off control to emacs_main
11607 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11608 (defined further below) to read input. This is where
11609 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11616 #if __profile__ /* is the profiler on? */
11617 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11622 /* set creator and type for files created by MSL */
11623 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11627 do_init_managers ();
11631 #ifndef USE_LSB_TAG
11632 do_check_ram_size ();
11635 init_emacs_passwd_dir ();
11639 init_coercion_handler ();
11641 initialize_applescript ();
11643 init_apple_event_handler ();
11645 init_dm_notification_handler ();
11651 /* set up argv array from STR# resource */
11652 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
11656 /* free up AppleScript resources on exit */
11657 atexit (terminate_applescript
);
11659 #if __profile__ /* is the profiler on? */
11660 atexit (profiler_exit_proc
);
11663 /* 3rd param "envp" never used in emacs_main */
11664 (void) emacs_main (argc
, argv
, 0);
11667 /* Never reached - real exit in Fkill_emacs */
11672 #if !TARGET_API_MAC_CARBON
11673 static RgnHandle mouse_region
= NULL
;
11676 mac_wait_next_event (er
, sleep_time
, dequeue
)
11681 static EventRecord er_buf
= {nullEvent
};
11682 UInt32 target_tick
, current_tick
;
11683 EventMask event_mask
;
11685 if (mouse_region
== NULL
)
11686 mouse_region
= NewRgn ();
11688 event_mask
= everyEvent
;
11689 if (!mac_ready_for_apple_events
)
11690 event_mask
-= highLevelEventMask
;
11692 current_tick
= TickCount ();
11693 target_tick
= current_tick
+ sleep_time
;
11695 if (er_buf
.what
== nullEvent
)
11696 while (!WaitNextEvent (event_mask
, &er_buf
,
11697 target_tick
- current_tick
, mouse_region
))
11699 current_tick
= TickCount ();
11700 if (target_tick
<= current_tick
)
11706 er_buf
.what
= nullEvent
;
11709 #endif /* not TARGET_API_MAC_CARBON */
11711 #if TARGET_API_MAC_CARBON
11713 mac_post_mouse_moved_event ()
11715 EventRef event
= NULL
;
11718 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
11719 kEventAttributeNone
, &event
);
11724 GetGlobalMouse (&mouse_pos
);
11725 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
11726 sizeof (Point
), &mouse_pos
);
11730 UInt32 modifiers
= GetCurrentKeyModifiers ();
11732 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
11733 sizeof (UInt32
), &modifiers
);
11736 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
11737 kEventPriorityStandard
);
11739 ReleaseEvent (event
);
11745 /* Emacs calls this whenever it wants to read an input event from the
11748 XTread_socket (sd
, expected
, hold_quit
)
11750 struct input_event
*hold_quit
;
11752 struct input_event inev
;
11754 #if TARGET_API_MAC_CARBON
11756 EventTargetRef toolbox_dispatcher
;
11759 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11761 if (interrupt_input_blocked
)
11763 interrupt_input_pending
= 1;
11767 interrupt_input_pending
= 0;
11770 /* So people can tell when we have read the available input. */
11771 input_signal_count
++;
11775 #if TARGET_API_MAC_CARBON
11776 toolbox_dispatcher
= GetEventDispatcherTarget ();
11780 mac_prepare_for_quickdraw (NULL
),
11782 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
11783 kEventRemoveFromQueue
, &eventRef
))
11784 #else /* !TARGET_API_MAC_CARBON */
11785 while (mac_wait_next_event (&er
, 0, true))
11786 #endif /* !TARGET_API_MAC_CARBON */
11790 unsigned long timestamp
;
11793 inev
.kind
= NO_EVENT
;
11796 #if TARGET_API_MAC_CARBON
11797 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
11799 if (!mac_convert_event_ref (eventRef
, &er
))
11801 #else /* !TARGET_API_MAC_CARBON */
11802 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
11803 #endif /* !TARGET_API_MAC_CARBON */
11810 WindowRef window_ptr
;
11811 ControlPartCode part_code
;
11812 int tool_bar_p
= 0;
11814 #if TARGET_API_MAC_CARBON
11817 /* This is needed to send mouse events like aqua window
11818 buttons to the correct handler. */
11819 read_socket_inev
= &inev
;
11820 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11821 read_socket_inev
= NULL
;
11822 if (err
!= eventNotHandledErr
)
11825 last_mouse_glyph_frame
= 0;
11827 if (dpyinfo
->grabbed
&& last_mouse_frame
11828 && FRAME_LIVE_P (last_mouse_frame
))
11830 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
11831 part_code
= inContent
;
11835 part_code
= FindWindow (er
.where
, &window_ptr
);
11836 if (tip_window
&& window_ptr
== tip_window
)
11838 HideWindow (tip_window
);
11839 part_code
= FindWindow (er
.where
, &window_ptr
);
11843 if (er
.what
!= mouseDown
&&
11844 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
11850 f
= mac_focus_frame (dpyinfo
);
11851 saved_menu_event_location
= er
.where
;
11852 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
11853 XSETFRAME (inev
.frame_or_window
, f
);
11858 #if TARGET_API_MAC_CARBON
11859 FrontNonFloatingWindow ()
11864 || (mac_window_to_frame (window_ptr
)
11865 != dpyinfo
->x_focus_frame
))
11866 SelectWindow (window_ptr
);
11869 ControlPartCode control_part_code
;
11873 ControlKind control_kind
;
11876 f
= mac_window_to_frame (window_ptr
);
11877 /* convert to local coordinates of new window */
11878 mouse_loc
.h
= (er
.where
.h
11880 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
11881 mouse_loc
.v
= (er
.where
.v
11883 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
11884 #if TARGET_API_MAC_CARBON
11885 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
11886 &control_part_code
);
11889 GetControlKind (ch
, &control_kind
);
11892 control_part_code
= FindControl (mouse_loc
, window_ptr
,
11896 #if TARGET_API_MAC_CARBON
11897 inev
.code
= mac_get_mouse_btn (eventRef
);
11898 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
11900 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
11901 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
, 0);
11903 XSETINT (inev
.x
, mouse_loc
.h
);
11904 XSETINT (inev
.y
, mouse_loc
.v
);
11906 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
11908 #ifndef USE_TOOLKIT_SCROLL_BARS
11909 /* control_part_code becomes kControlNoPart if
11910 a progress indicator is clicked. */
11911 && control_part_code
!= kControlNoPart
11912 #else /* USE_TOOLKIT_SCROLL_BARS */
11914 && control_kind
.kind
== kControlKindScrollBar
11915 #endif /* MAC_OSX */
11916 #endif /* USE_TOOLKIT_SCROLL_BARS */
11919 struct scroll_bar
*bar
;
11921 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11923 bar
= tracked_scroll_bar
;
11924 #ifndef USE_TOOLKIT_SCROLL_BARS
11925 control_part_code
= kControlIndicatorPart
;
11929 bar
= (struct scroll_bar
*) GetControlReference (ch
);
11930 #ifdef USE_TOOLKIT_SCROLL_BARS
11931 /* Make the "Ctrl-Mouse-2 splits window" work
11932 for toolkit scroll bars. */
11933 if (inev
.modifiers
& ctrl_modifier
)
11934 x_scroll_bar_handle_click (bar
, control_part_code
,
11936 else if (er
.what
== mouseDown
)
11937 x_scroll_bar_handle_press (bar
, control_part_code
,
11940 x_scroll_bar_handle_release (bar
, &inev
);
11941 #else /* not USE_TOOLKIT_SCROLL_BARS */
11942 x_scroll_bar_handle_click (bar
, control_part_code
,
11944 if (er
.what
== mouseDown
11945 && control_part_code
== kControlIndicatorPart
)
11946 tracked_scroll_bar
= bar
;
11948 tracked_scroll_bar
= NULL
;
11949 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11953 Lisp_Object window
;
11954 int x
= mouse_loc
.h
;
11955 int y
= mouse_loc
.v
;
11957 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
11958 if (EQ (window
, f
->tool_bar_window
))
11960 if (er
.what
== mouseDown
)
11961 handle_tool_bar_click (f
, x
, y
, 1, 0);
11963 handle_tool_bar_click (f
, x
, y
, 0,
11969 XSETFRAME (inev
.frame_or_window
, f
);
11970 inev
.kind
= MOUSE_CLICK_EVENT
;
11974 if (er
.what
== mouseDown
)
11976 dpyinfo
->grabbed
|= (1 << inev
.code
);
11977 last_mouse_frame
= f
;
11980 last_tool_bar_item
= -1;
11984 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
11985 /* If a button is released though it was not
11986 previously pressed, that would be because
11987 of multi-button emulation. */
11988 dpyinfo
->grabbed
= 0;
11990 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
11993 /* Ignore any mouse motion that happened before
11994 this event; any subsequent mouse-movement Emacs
11995 events should reflect only motion after the
11998 f
->mouse_moved
= 0;
12000 #ifdef USE_TOOLKIT_SCROLL_BARS
12001 if (inev
.kind
== MOUSE_CLICK_EVENT
12002 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12003 && (inev
.modifiers
& ctrl_modifier
)))
12008 inev
.modifiers
|= down_modifier
;
12011 inev
.modifiers
|= up_modifier
;
12018 #if TARGET_API_MAC_CARBON
12020 if (IsWindowPathSelectClick (window_ptr
, &er
))
12022 WindowPathSelect (window_ptr
, NULL
, NULL
);
12025 if (part_code
== inProxyIcon
12026 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12027 != errUserWantsToDragWindow
))
12029 DragWindow (window_ptr
, er
.where
, NULL
);
12030 #else /* not TARGET_API_MAC_CARBON */
12031 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12032 /* Update the frame parameters. */
12034 struct frame
*f
= mac_window_to_frame (window_ptr
);
12036 if (f
&& !f
->async_iconified
)
12037 mac_handle_origin_change (f
);
12039 #endif /* not TARGET_API_MAC_CARBON */
12043 if (TrackGoAway (window_ptr
, er
.where
))
12045 inev
.kind
= DELETE_WINDOW_EVENT
;
12046 XSETFRAME (inev
.frame_or_window
,
12047 mac_window_to_frame (window_ptr
));
12051 /* window resize handling added --ben */
12053 do_grow_window (window_ptr
, &er
);
12056 /* window zoom handling added --ben */
12059 if (TrackBox (window_ptr
, er
.where
, part_code
))
12060 do_zoom_window (window_ptr
, part_code
);
12063 #if USE_MAC_TOOLBAR
12069 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12071 /* This doesn't work on Mac OS X 10.2. */
12073 HIViewClick (ch
, eventRef
);
12076 #endif /* USE_MAC_TOOLBAR */
12084 #if !TARGET_API_MAC_CARBON
12086 do_window_update ((WindowRef
) er
.message
);
12091 #if TARGET_API_MAC_CARBON
12092 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
12093 != eventNotHandledErr
)
12096 switch ((er
.message
>> 24) & 0x000000FF)
12099 case suspendResumeMessage
:
12100 if (er
.message
& resumeFlag
)
12103 mac_tsm_suspend ();
12107 case mouseMovedMessage
:
12108 #if !TARGET_API_MAC_CARBON
12109 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12110 er
.where
.h
+ 1, er
.where
.v
+ 1);
12112 previous_help_echo_string
= help_echo_string
;
12113 help_echo_string
= Qnil
;
12115 if (dpyinfo
->grabbed
&& last_mouse_frame
12116 && FRAME_LIVE_P (last_mouse_frame
))
12117 f
= last_mouse_frame
;
12119 f
= dpyinfo
->x_focus_frame
;
12121 if (dpyinfo
->mouse_face_hidden
)
12123 dpyinfo
->mouse_face_hidden
= 0;
12124 clear_mouse_face (dpyinfo
);
12129 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12132 mouse_pos
.h
= (er
.where
.h
12134 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12135 mouse_pos
.v
= (er
.where
.v
12137 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12138 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12139 #ifdef USE_TOOLKIT_SCROLL_BARS
12140 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12142 #else /* not USE_TOOLKIT_SCROLL_BARS */
12143 x_scroll_bar_note_movement (tracked_scroll_bar
,
12145 - XINT (tracked_scroll_bar
->top
),
12146 er
.when
* (1000 / 60));
12147 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12150 /* Generate SELECT_WINDOW_EVENTs when needed. */
12151 if (!NILP (Vmouse_autoselect_window
))
12153 Lisp_Object window
;
12155 window
= window_from_coordinates (f
,
12160 /* Window will be selected only when it is
12161 not selected now and last mouse movement
12162 event was not in it. Minibuffer window
12163 will be selected only when it is active. */
12164 if (WINDOWP (window
)
12165 && !EQ (window
, last_window
)
12166 && !EQ (window
, selected_window
)
12167 /* For click-to-focus window managers
12168 create event iff we don't leave the
12170 && (focus_follows_mouse
12171 || (EQ (XWINDOW (window
)->frame
,
12172 XWINDOW (selected_window
)->frame
))))
12174 inev
.kind
= SELECT_WINDOW_EVENT
;
12175 inev
.frame_or_window
= window
;
12178 last_window
=window
;
12180 if (!note_mouse_movement (f
, &mouse_pos
))
12181 help_echo_string
= previous_help_echo_string
;
12182 #if USE_MAC_TOOLBAR
12184 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12189 /* If the contents of the global variable
12190 help_echo_string has changed, generate a
12192 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12200 WindowRef window_ptr
= (WindowRef
) er
.message
;
12202 ControlRef root_control
;
12204 if (window_ptr
== tip_window
)
12206 HideWindow (tip_window
);
12210 if (!is_emacs_window (window_ptr
))
12213 f
= mac_window_to_frame (window_ptr
);
12215 if ((er
.modifiers
& activeFlag
) != 0)
12217 /* A window has been activated */
12220 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12222 ActivateControl (root_control
);
12224 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12226 mouse_loc
.h
= (er
.where
.h
12228 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12229 mouse_loc
.v
= (er
.where
.v
12231 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12232 /* Window-activated event counts as mouse movement,
12233 so update things that depend on mouse position. */
12234 note_mouse_movement (f
, &mouse_loc
);
12238 /* A window has been deactivated */
12239 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12241 DeactivateControl (root_control
);
12243 #ifdef USE_TOOLKIT_SCROLL_BARS
12244 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12246 struct input_event event
;
12248 EVENT_INIT (event
);
12249 event
.kind
= NO_EVENT
;
12250 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12251 if (event
.kind
!= NO_EVENT
)
12253 event
.timestamp
= timestamp
;
12254 kbd_buffer_store_event_hold (&event
, hold_quit
);
12259 dpyinfo
->grabbed
= 0;
12261 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12263 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12265 /* If we move outside the frame, then we're
12266 certainly no longer on any text in the
12268 clear_mouse_face (dpyinfo
);
12269 dpyinfo
->mouse_face_mouse_frame
= 0;
12272 /* Generate a nil HELP_EVENT to cancel a help-echo.
12273 Do it only if there's something to cancel.
12274 Otherwise, the startup message is cleared when the
12275 mouse leaves the frame. */
12276 if (any_help_event_p
)
12287 f
= mac_focus_frame (dpyinfo
);
12288 XSETFRAME (inev
.frame_or_window
, f
);
12290 /* If mouse-highlight is an integer, input clears out mouse
12292 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12293 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12295 clear_mouse_face (dpyinfo
);
12296 dpyinfo
->mouse_face_hidden
= 1;
12300 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
12301 UInt32 key_code
= (er
.message
& keyCodeMask
) >> 8;
12304 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
12306 sizeof (UInt32
), NULL
, &modifiers
);
12308 mapped_modifiers
= mac_mapped_modifiers (modifiers
, key_code
);
12310 #if TARGET_API_MAC_CARBON
12311 if (!(mapped_modifiers
12312 & ~(mac_pass_command_to_system
? cmdKey
: 0)
12313 & ~(mac_pass_control_to_system
? controlKey
: 0)))
12317 if (er
.what
!= keyUp
)
12318 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12319 key_code
, modifiers
, timestamp
, &inev
);
12323 case kHighLevelEvent
:
12324 AEProcessAppleEvent (&er
);
12329 #if TARGET_API_MAC_CARBON
12333 read_socket_inev
= &inev
;
12334 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12335 read_socket_inev
= NULL
;
12340 #if TARGET_API_MAC_CARBON
12341 ReleaseEvent (eventRef
);
12344 if (inev
.kind
!= NO_EVENT
)
12346 inev
.timestamp
= timestamp
;
12347 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12352 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12357 XSETFRAME (frame
, f
);
12363 any_help_event_p
= 1;
12364 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12365 help_echo_object
, help_echo_pos
);
12369 help_echo_string
= Qnil
;
12370 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12376 /* If the focus was just given to an autoraising frame,
12378 /* ??? This ought to be able to handle more than one such frame. */
12379 if (pending_autoraise_frame
)
12381 x_raise_frame (pending_autoraise_frame
);
12382 pending_autoraise_frame
= 0;
12385 if (mac_screen_config_changed
)
12387 mac_get_screen_info (dpyinfo
);
12388 mac_screen_config_changed
= 0;
12391 #if !TARGET_API_MAC_CARBON
12392 /* Check which frames are still visible. We do this here because
12393 there doesn't seem to be any direct notification from the Window
12394 Manager that the visibility of a window has changed (at least,
12395 not in all cases). */
12397 Lisp_Object tail
, frame
;
12399 FOR_EACH_FRAME (tail
, frame
)
12401 struct frame
*f
= XFRAME (frame
);
12403 /* The tooltip has been drawn already. Avoid the
12404 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12405 if (EQ (frame
, tip_frame
))
12408 if (FRAME_MAC_P (f
))
12409 mac_handle_visibility_change (f
);
12420 /* Need to override CodeWarrior's input function so no conversion is
12421 done on newlines Otherwise compiled functions in .elc files will be
12422 read incorrectly. Defined in ...:MSL C:MSL
12423 Common:Source:buffer_io.c. */
12426 __convert_to_newlines (unsigned char * p
, size_t * n
)
12428 #pragma unused(p,n)
12432 __convert_from_newlines (unsigned char * p
, size_t * n
)
12434 #pragma unused(p,n)
12440 make_mac_terminal_frame (struct frame
*f
)
12445 XSETFRAME (frame
, f
);
12447 f
->output_method
= output_mac
;
12448 f
->output_data
.mac
= (struct mac_output
*)
12449 xmalloc (sizeof (struct mac_output
));
12450 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12452 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12454 FRAME_COLS (f
) = 96;
12455 FRAME_LINES (f
) = 4;
12457 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12458 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12460 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12462 f
->output_data
.mac
->cursor_pixel
= 0;
12463 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12464 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12465 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12467 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12468 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12469 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12470 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12471 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12472 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12474 FRAME_FONTSET (f
) = -1;
12475 f
->output_data
.mac
->explicit_parent
= 0;
12478 f
->border_width
= 0;
12480 f
->internal_border_width
= 0;
12485 f
->new_text_cols
= 0;
12486 f
->new_text_lines
= 0;
12488 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12489 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12490 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12494 if (!(FRAME_MAC_WINDOW (f
) =
12495 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12496 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12498 /* so that update events can find this mac_output struct */
12499 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12505 /* Need to be initialized for unshow_buffer in window.c. */
12506 selected_window
= f
->selected_window
;
12508 Fmodify_frame_parameters (frame
,
12509 Fcons (Fcons (Qfont
,
12510 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12511 Fmodify_frame_parameters (frame
,
12512 Fcons (Fcons (Qforeground_color
,
12513 build_string ("black")), Qnil
));
12514 Fmodify_frame_parameters (frame
,
12515 Fcons (Fcons (Qbackground_color
,
12516 build_string ("white")), Qnil
));
12521 /***********************************************************************
12523 ***********************************************************************/
12525 static int mac_initialized
= 0;
12528 mac_make_rdb (xrm_option
)
12529 const char *xrm_option
;
12531 XrmDatabase database
;
12533 database
= xrm_get_preference_database (NULL
);
12535 xrm_merge_string_database (database
, xrm_option
);
12540 struct mac_display_info
*
12541 mac_term_init (display_name
, xrm_option
, resource_name
)
12542 Lisp_Object display_name
;
12544 char *resource_name
;
12546 struct mac_display_info
*dpyinfo
;
12550 if (!mac_initialized
)
12553 mac_initialized
= 1;
12556 if (x_display_list
)
12557 error ("Sorry, this version can only handle one display");
12559 dpyinfo
= &one_mac_display_info
;
12560 bzero (dpyinfo
, sizeof (*dpyinfo
));
12563 dpyinfo
->mac_id_name
12564 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12565 + SCHARS (Vsystem_name
)
12567 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12568 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12570 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12571 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12574 dpyinfo
->reference_count
= 0;
12575 dpyinfo
->resx
= 72.0;
12576 dpyinfo
->resy
= 72.0;
12578 mac_get_screen_info (dpyinfo
);
12580 dpyinfo
->grabbed
= 0;
12581 dpyinfo
->root_window
= NULL
;
12582 dpyinfo
->image_cache
= make_image_cache ();
12584 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12585 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12586 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12587 dpyinfo
->mouse_face_window
= Qnil
;
12588 dpyinfo
->mouse_face_overlay
= Qnil
;
12589 dpyinfo
->mouse_face_hidden
= 0;
12591 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12593 /* Put this display on the chain. */
12594 dpyinfo
->next
= x_display_list
;
12595 x_display_list
= dpyinfo
;
12597 /* Put it on x_display_name_list. */
12598 x_display_name_list
= Fcons (Fcons (display_name
,
12599 Fcons (Qnil
, dpyinfo
->xrdb
)),
12600 x_display_name_list
);
12601 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12608 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12611 x_delete_display (dpyinfo
)
12612 struct mac_display_info
*dpyinfo
;
12616 /* Discard this display from x_display_name_list and x_display_list.
12617 We can't use Fdelq because that can quit. */
12618 if (! NILP (x_display_name_list
)
12619 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12620 x_display_name_list
= XCDR (x_display_name_list
);
12625 tail
= x_display_name_list
;
12626 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12628 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
12630 XSETCDR (tail
, XCDR (XCDR (tail
)));
12633 tail
= XCDR (tail
);
12637 if (x_display_list
== dpyinfo
)
12638 x_display_list
= dpyinfo
->next
;
12641 struct x_display_info
*tail
;
12643 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12644 if (tail
->next
== dpyinfo
)
12645 tail
->next
= tail
->next
->next
;
12648 /* Free the font names in the font table. */
12649 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12650 if (dpyinfo
->font_table
[i
].name
)
12652 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
12653 xfree (dpyinfo
->font_table
[i
].full_name
);
12654 xfree (dpyinfo
->font_table
[i
].name
);
12657 if (dpyinfo
->font_table
)
12659 if (dpyinfo
->font_table
->font_encoder
)
12660 xfree (dpyinfo
->font_table
->font_encoder
);
12661 xfree (dpyinfo
->font_table
);
12663 if (dpyinfo
->mac_id_name
)
12664 xfree (dpyinfo
->mac_id_name
);
12666 if (x_display_list
== 0)
12668 mac_clear_font_name_table ();
12669 bzero (dpyinfo
, sizeof (*dpyinfo
));
12680 MenuItemIndex menu_index
;
12682 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
12683 &menu
, &menu_index
);
12685 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12686 EnableMenuCommand (NULL
, kHICommandPreferences
);
12687 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
12688 &menu
, &menu_index
);
12691 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12692 InsertMenuItemTextWithCFString (menu
, NULL
,
12693 0, kMenuItemAttrSeparator
, 0);
12694 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
12695 0, 0, kHICommandAbout
);
12697 #else /* !MAC_OSX */
12698 #if TARGET_API_MAC_CARBON
12699 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
12709 static InterfaceTypeList types
= {kUnicodeDocument
};
12711 static InterfaceTypeList types
= {kTextService
};
12714 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
12715 &tsm_document_id
, 0);
12719 /* Set up use of X before we make the first connection. */
12721 extern frame_parm_handler mac_frame_parm_handlers
[];
12723 static struct redisplay_interface x_redisplay_interface
=
12725 mac_frame_parm_handlers
,
12729 x_clear_end_of_line
,
12731 x_after_update_window_line
,
12732 x_update_window_begin
,
12733 x_update_window_end
,
12737 mac_flush_display_optional
,
12739 0, /* flush_display_optional */
12741 x_clear_window_mouse_face
,
12742 x_get_glyph_overhangs
,
12743 x_fix_overlapping_area
,
12744 x_draw_fringe_bitmap
,
12746 mac_define_fringe_bitmap
,
12747 mac_destroy_fringe_bitmap
,
12749 0, /* define_fringe_bitmap */
12750 0, /* destroy_fringe_bitmap */
12752 mac_per_char_metric
,
12754 mac_compute_glyph_string_overhangs
,
12755 x_draw_glyph_string
,
12756 mac_define_frame_cursor
,
12757 mac_clear_frame_area
,
12758 mac_draw_window_cursor
,
12759 mac_draw_vertical_window_border
,
12760 mac_shift_glyphs_for_insert
12766 rif
= &x_redisplay_interface
;
12768 clear_frame_hook
= x_clear_frame
;
12769 ins_del_lines_hook
= x_ins_del_lines
;
12770 delete_glyphs_hook
= x_delete_glyphs
;
12771 ring_bell_hook
= XTring_bell
;
12772 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12773 set_terminal_modes_hook
= XTset_terminal_modes
;
12774 update_begin_hook
= x_update_begin
;
12775 update_end_hook
= x_update_end
;
12776 set_terminal_window_hook
= XTset_terminal_window
;
12777 read_socket_hook
= XTread_socket
;
12778 frame_up_to_date_hook
= XTframe_up_to_date
;
12779 mouse_position_hook
= XTmouse_position
;
12780 frame_rehighlight_hook
= XTframe_rehighlight
;
12781 frame_raise_lower_hook
= XTframe_raise_lower
;
12783 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12784 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12785 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12786 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12788 scroll_region_ok
= 1; /* we'll scroll partial frames */
12789 char_ins_del_ok
= 1;
12790 line_ins_del_ok
= 1; /* we'll just blt 'em */
12791 fast_clear_end_of_line
= 1; /* X does this well */
12792 memory_below_frame
= 0; /* we don't remember what scrolls
12796 last_tool_bar_item
= -1;
12797 any_help_event_p
= 0;
12799 /* Try to use interrupt input; if we can't, then start polling. */
12800 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
12804 #if TARGET_API_MAC_CARBON
12806 install_application_handler ();
12815 init_coercion_handler ();
12817 init_apple_event_handler ();
12819 init_dm_notification_handler ();
12821 if (!inhibit_window_system
)
12823 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
12825 SetFrontProcess (&psn
);
12833 mac_init_fringe ();
12844 staticpro (&x_error_message_string
);
12845 x_error_message_string
= Qnil
;
12848 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
12849 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
12850 Qalt
= intern ("alt"); staticpro (&Qalt
);
12851 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
12852 Qsuper
= intern ("super"); staticpro (&Qsuper
);
12853 Qmodifier_value
= intern ("modifier-value");
12854 staticpro (&Qmodifier_value
);
12856 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
12857 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12858 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12859 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12860 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12862 #if TARGET_API_MAC_CARBON
12863 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
12865 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
12866 staticpro (&Qtoolbar_switch_mode
);
12867 #if USE_MAC_FONT_PANEL
12868 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12869 Qselection
= intern ("selection"); staticpro (&Qselection
);
12872 Qservice
= intern ("service"); staticpro (&Qservice
);
12873 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12874 Qperform
= intern ("perform"); staticpro (&Qperform
);
12877 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12878 Qupdate_active_input_area
= intern ("update-active-input-area");
12879 staticpro (&Qupdate_active_input_area
);
12880 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12881 staticpro (&Qunicode_for_key_event
);
12886 Fprovide (intern ("mac-carbon"), Qnil
);
12889 staticpro (&Qreverse
);
12890 Qreverse
= intern ("reverse");
12892 staticpro (&x_display_name_list
);
12893 x_display_name_list
= Qnil
;
12895 staticpro (&last_mouse_scroll_bar
);
12896 last_mouse_scroll_bar
= Qnil
;
12898 staticpro (&fm_font_family_alist
);
12899 fm_font_family_alist
= Qnil
;
12902 staticpro (&atsu_font_id_hash
);
12903 atsu_font_id_hash
= Qnil
;
12905 staticpro (&fm_style_face_attributes_alist
);
12906 fm_style_face_attributes_alist
= Qnil
;
12910 staticpro (&saved_ts_script_language_on_focus
);
12911 saved_ts_script_language_on_focus
= Qnil
;
12914 /* We don't yet support this, but defining this here avoids whining
12915 from cus-start.el and other places, like "M-x set-variable". */
12916 DEFVAR_BOOL ("x-use-underline-position-properties",
12917 &x_use_underline_position_properties
,
12918 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12919 A value of nil means ignore them. If you encounter fonts with bogus
12920 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12921 to 4.1, set this to nil.
12923 NOTE: Not supported on Mac yet. */);
12924 x_use_underline_position_properties
= 0;
12926 DEFVAR_BOOL ("x-underline-at-descent-line",
12927 &x_underline_at_descent_line
,
12928 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12929 A value of nil means to draw the underline according to the value of the
12930 variable `x-use-underline-position-properties', which is usually at the
12931 baseline level. The default value is nil. */);
12932 x_underline_at_descent_line
= 0;
12934 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12935 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12936 #ifdef USE_TOOLKIT_SCROLL_BARS
12937 Vx_toolkit_scroll_bars
= Qt
;
12939 Vx_toolkit_scroll_bars
= Qnil
;
12942 staticpro (&last_mouse_motion_frame
);
12943 last_mouse_motion_frame
= Qnil
;
12945 /* Variables to configure modifier key assignment. */
12947 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12948 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12949 The value can be `control', `meta', `alt', `hyper', or `super' for the
12950 respective modifier. The default is `control'. */);
12951 Vmac_control_modifier
= Qcontrol
;
12953 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12954 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12955 The value can be `control', `meta', `alt', `hyper', or `super' for the
12956 respective modifier. If the value is nil then the key will act as the
12957 normal Mac control modifier, and the option key can be used to compose
12958 characters depending on the chosen Mac keyboard setting. */);
12959 Vmac_option_modifier
= Qnil
;
12961 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12962 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12963 The value can be `control', `meta', `alt', `hyper', or `super' for the
12964 respective modifier. The default is `meta'. */);
12965 Vmac_command_modifier
= Qmeta
;
12967 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12968 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12969 The value can be `control', `meta', `alt', `hyper', or `super' for the
12970 respective modifier. Note that remapping the function key may lead to
12971 unexpected results for some keys on non-US/GB keyboards. */);
12972 Vmac_function_modifier
= Qnil
;
12974 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12975 &Vmac_emulate_three_button_mouse
,
12976 doc
: /* *Specify a way of three button mouse emulation.
12977 The value can be nil, t, or the symbol `reverse'.
12978 A value of nil means that no emulation should be done and the modifiers
12979 should be placed on the mouse-1 event.
12980 t means that when the option-key is held down while pressing the mouse
12981 button, the click will register as mouse-2 and while the command-key
12982 is held down, the click will register as mouse-3.
12983 The symbol `reverse' means that the option-key will register for
12984 mouse-3 and the command-key will register for mouse-2. */);
12985 Vmac_emulate_three_button_mouse
= Qnil
;
12987 #if TARGET_API_MAC_CARBON
12988 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12989 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12990 Otherwise, the right click will be treated as mouse-2 and the wheel
12991 button will be mouse-3. */);
12992 mac_wheel_button_is_mouse_2
= 1;
12994 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12995 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12996 mac_pass_command_to_system
= 1;
12998 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12999 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13000 mac_pass_control_to_system
= 1;
13004 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
13005 doc
: /* *If non-nil, allow anti-aliasing.
13006 The text will be rendered using Core Graphics text rendering which
13007 may anti-alias the text. */);
13009 mac_use_core_graphics
= 1;
13011 mac_use_core_graphics
= 0;
13014 /* Register an entry for `mac-roman' so that it can be used when
13015 creating the terminal frame on Mac OS 9 before loading
13016 term/mac-win.elc. */
13017 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
13018 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
13019 Each entry should be of the form:
13021 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13023 where CHARSET-NAME is a string used in font names to identify the
13024 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13025 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13026 Vmac_charset_info_alist
=
13027 Fcons (list3 (build_string ("mac-roman"),
13028 make_number (smRoman
), Qnil
), Qnil
);
13031 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13032 doc
: /* Overlay used to display Mac TSM active input area. */);
13033 Vmac_ts_active_input_overlay
= Qnil
;
13035 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13036 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13037 If the value is t, the input script and language are restored to those
13038 used in the last focus frame. If the value is a pair of integers, the
13039 input script and language codes, which are defined in the Script
13040 Manager, are set to its car and cdr parts, respectively. Otherwise,
13041 Emacs doesn't set them and thus follows the system default behavior. */);
13042 Vmac_ts_script_language_on_focus
= Qnil
;
13046 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13047 (do not change this comment) */