1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
83 #include "character.h"
88 /* Non-nil means Emacs uses toolkit scroll bars. */
90 Lisp_Object Vx_toolkit_scroll_bars
;
92 /* If non-zero, the text will be rendered using Core Graphics text
93 rendering which may anti-alias the text. */
94 int mac_use_core_graphics
;
97 /* Non-zero means that a HELP_EVENT has been generated since Emacs
100 static int any_help_event_p
;
102 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
103 static Lisp_Object last_window
;
105 /* Non-zero means make use of UNDERLINE_POSITION font properties.
106 (Not yet supported.) */
107 int x_use_underline_position_properties
;
109 /* Non-zero means to draw the underline at the same place as the descent line. */
111 int x_underline_at_descent_line
;
113 /* This is a chain of structures for all the X displays currently in
116 struct x_display_info
*x_display_list
;
118 /* This is a list of cons cells, each of the form (NAME
119 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
120 x_display_list and in the same order. NAME is the name of the
121 frame. FONT-LIST-CACHE records previous values returned by
122 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
123 equivalent, which is implemented with a Lisp object, for the
126 Lisp_Object x_display_name_list
;
128 /* This is display since Mac does not support multiple ones. */
129 struct mac_display_info one_mac_display_info
;
131 /* Frame being updated by update_frame. This is declared in term.c.
132 This is set by update_begin and looked at by all the XT functions.
133 It is zero while not inside an update. In that case, the XT
134 functions assume that `selected_frame' is the frame to apply to. */
136 extern struct frame
*updating_frame
;
138 /* This is a frame waiting to be auto-raised, within XTread_socket. */
140 struct frame
*pending_autoraise_frame
;
144 Formerly, we used PointerMotionHintMask (in standard_event_mask)
145 so that we would have to call XQueryPointer after each MotionNotify
146 event to ask for another such event. However, this made mouse tracking
147 slow, and there was a bug that made it eventually stop.
149 Simply asking for MotionNotify all the time seems to work better.
151 In order to avoid asking for motion events and then throwing most
152 of them away or busy-polling the server for mouse positions, we ask
153 the server for pointer motion hints. This means that we get only
154 one event per group of mouse movements. "Groups" are delimited by
155 other kinds of events (focus changes and button clicks, for
156 example), or by XQueryPointer calls; when one of these happens, we
157 get another MotionNotify event the next time the mouse moves. This
158 is at least as efficient as getting motion events when mouse
159 tracking is on, and I suspect only negligibly worse when tracking
162 /* Where the mouse was last time we reported a mouse event. */
164 static Rect last_mouse_glyph
;
165 static FRAME_PTR last_mouse_glyph_frame
;
167 /* The scroll bar in which the last X motion event occurred.
169 If the last X motion event occurred in a scroll bar, we set this so
170 XTmouse_position can know whether to report a scroll bar motion or
173 If the last X motion event didn't occur in a scroll bar, we set
174 this to Qnil, to tell XTmouse_position to return an ordinary motion
177 static Lisp_Object last_mouse_scroll_bar
;
179 /* This is a hack. We would really prefer that XTmouse_position would
180 return the time associated with the position it returns, but there
181 doesn't seem to be any way to wrest the time-stamp from the server
182 along with the position query. So, we just keep track of the time
183 of the last movement we received, and return that in hopes that
184 it's somewhat accurate. */
186 static Time last_mouse_movement_time
;
188 struct scroll_bar
*tracked_scroll_bar
= NULL
;
190 /* Incremented by XTread_socket whenever it really tries to read
194 static int volatile input_signal_count
;
196 static int input_signal_count
;
199 extern Lisp_Object Vsystem_name
;
201 extern Lisp_Object Qeql
;
203 /* A mask of extra modifier bits to put into every keyboard char. */
205 extern EMACS_INT extra_keyboard_modifiers
;
207 /* The keysyms to use for the various modifiers. */
209 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
211 extern int inhibit_window_system
;
213 #if __MRC__ && !TARGET_API_MAC_CARBON
214 QDGlobals qd
; /* QuickDraw global information structure. */
217 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
219 struct mac_display_info
*mac_display_info_for_display (Display
*);
220 static void x_update_window_end
P_ ((struct window
*, int, int));
221 int x_catch_errors
P_ ((Display
*));
222 void x_uncatch_errors
P_ ((Display
*, int));
223 void x_lower_frame
P_ ((struct frame
*));
224 void x_scroll_bar_clear
P_ ((struct frame
*));
225 int x_had_errors_p
P_ ((Display
*));
226 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
227 void x_raise_frame
P_ ((struct frame
*));
228 void x_set_window_size
P_ ((struct frame
*, int, int, int));
229 void x_wm_set_window_state
P_ ((struct frame
*, int));
230 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
231 static void mac_initialize
P_ ((void));
232 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
233 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
234 static void x_update_end
P_ ((struct frame
*));
235 static void XTframe_up_to_date
P_ ((struct frame
*));
236 static void XTset_terminal_modes
P_ ((struct terminal
*));
237 static void XTreset_terminal_modes
P_ ((struct terminal
*));
238 static void x_clear_frame
P_ ((struct frame
*));
239 static void frame_highlight
P_ ((struct frame
*));
240 static void frame_unhighlight
P_ ((struct frame
*));
241 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
242 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
243 struct frame
*, struct input_event
*));
244 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
246 struct input_event
*));
247 static void XTframe_rehighlight
P_ ((struct frame
*));
248 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
249 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
250 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
251 enum text_cursor_kinds
));
253 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
254 static void x_flush
P_ ((struct frame
*f
));
255 static void x_update_begin
P_ ((struct frame
*));
256 static void x_update_window_begin
P_ ((struct window
*));
257 static void x_after_update_window_line
P_ ((struct glyph_row
*));
258 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
259 enum scroll_bar_part
*,
260 Lisp_Object
*, Lisp_Object
*,
263 static int is_emacs_window
P_ ((WindowRef
));
264 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
265 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
266 static struct terminal
*mac_create_terminal
P_ ((struct mac_display_info
*dpyinfo
));
269 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
270 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
271 #define GC_FONT(gc) ((gc)->xgcv.font)
272 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
274 #define CG_SET_FILL_COLOR(context, color) \
275 CGContextSetRGBFillColor (context, \
276 RED_FROM_ULONG (color) / 255.0f, \
277 GREEN_FROM_ULONG (color) / 255.0f, \
278 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
279 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
280 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
281 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
283 if (CGColorGetTypeID != NULL) \
284 CGContextSetFillColorWithColor (context, cg_color); \
286 CG_SET_FILL_COLOR (context, color); \
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CGContextSetFillColorWithColor (context, cg_color)
293 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
294 CG_SET_FILL_COLOR (context, color)
296 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
297 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
299 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
300 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
304 #define CG_SET_STROKE_COLOR(context, color) \
305 CGContextSetRGBStrokeColor (context, \
306 RED_FROM_ULONG (color) / 255.0f, \
307 GREEN_FROM_ULONG (color) / 255.0f, \
308 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
309 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
310 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
311 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
313 if (CGColorGetTypeID != NULL) \
314 CGContextSetStrokeColorWithColor (context, cg_color); \
316 CG_SET_STROKE_COLOR (context, color); \
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CGContextSetStrokeColorWithColor (context, cg_color)
323 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
324 CG_SET_STROKE_COLOR (context, color)
326 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
327 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
331 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
333 /* Fringe bitmaps. */
335 static int max_fringe_bmp
= 0;
336 static CGImageRef
*fringe_bmp
= 0;
338 static CGColorSpaceRef mac_cg_color_space_rgb
;
339 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
340 static CGColorRef mac_cg_color_black
;
346 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
347 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
348 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
349 /* Don't check the availability of CGColorCreate; this symbol is
350 defined even in Mac OS X 10.1. */
351 if (CGColorGetTypeID
!= NULL
)
354 float rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
356 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
362 mac_begin_cg_clip (f
, gc
)
366 CGContextRef context
= FRAME_CG_CONTEXT (f
);
370 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
371 FRAME_CG_CONTEXT (f
) = context
;
374 CGContextSaveGState (context
);
375 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
376 CGContextScaleCTM (context
, 1, -1);
377 if (gc
&& gc
->n_clip_rects
)
378 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
387 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
391 mac_prepare_for_quickdraw (f
)
396 Lisp_Object rest
, frame
;
397 FOR_EACH_FRAME (rest
, frame
)
398 if (FRAME_MAC_P (XFRAME (frame
)))
399 mac_prepare_for_quickdraw (XFRAME (frame
));
403 CGContextRef context
= FRAME_CG_CONTEXT (f
);
407 CGContextSynchronize (context
);
408 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
409 &FRAME_CG_CONTEXT (f
));
415 static RgnHandle saved_port_clip_region
= NULL
;
418 mac_begin_clip (f
, gc
)
422 static RgnHandle new_region
= NULL
;
424 if (saved_port_clip_region
== NULL
)
425 saved_port_clip_region
= NewRgn ();
426 if (new_region
== NULL
)
427 new_region
= NewRgn ();
430 mac_prepare_for_quickdraw (f
);
432 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
434 if (gc
->n_clip_rects
)
436 GetClip (saved_port_clip_region
);
437 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
438 SetClip (new_region
);
446 if (gc
->n_clip_rects
)
447 SetClip (saved_port_clip_region
);
451 /* X display function emulation */
453 /* Mac version of XDrawLine. */
456 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
462 CGContextRef context
;
463 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
466 gx1
+= 0.5f
, gx2
+= 0.5f
;
468 gy1
+= 0.5f
, gy2
+= 0.5f
;
470 context
= mac_begin_cg_clip (f
, gc
);
471 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
472 CGContextBeginPath (context
);
473 CGContextMoveToPoint (context
, gx1
, gy1
);
474 CGContextAddLineToPoint (context
, gx2
, gy2
);
475 CGContextClosePath (context
);
476 CGContextStrokePath (context
);
494 mac_begin_clip (f
, gc
);
495 RGBForeColor (GC_FORE_COLOR (gc
));
502 /* Mac version of XDrawLine (to Pixmap). */
505 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
529 GetGWorld (&old_port
, &old_gdh
);
532 RGBForeColor (GC_FORE_COLOR (gc
));
534 LockPixels (GetGWorldPixMap (p
));
537 UnlockPixels (GetGWorldPixMap (p
));
539 SetGWorld (old_port
, old_gdh
);
544 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
548 unsigned int width
, height
;
552 CGContextRef context
;
554 context
= mac_begin_cg_clip (f
, gc
);
555 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
556 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
563 mac_begin_clip (f
, gc
);
564 RGBBackColor (GC_BACK_COLOR (gc
));
565 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
567 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
574 /* Mac version of XClearArea. */
577 mac_clear_area (f
, x
, y
, width
, height
)
580 unsigned int width
, height
;
582 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
585 /* Mac version of XClearWindow. */
593 CGContextRef context
;
594 GC gc
= FRAME_NORMAL_GC (f
);
596 context
= mac_begin_cg_clip (f
, NULL
);
597 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
598 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
599 FRAME_PIXEL_HEIGHT (f
)));
602 #else /* !USE_CG_DRAWING */
603 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
605 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
607 #if TARGET_API_MAC_CARBON
611 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
614 #else /* not TARGET_API_MAC_CARBON */
615 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
616 #endif /* not TARGET_API_MAC_CARBON */
621 /* Mac replacement for XCopyArea. */
625 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
626 dest_x
, dest_y
, overlay_p
)
631 unsigned int width
, height
;
632 int dest_x
, dest_y
, overlay_p
;
634 CGContextRef context
;
635 float port_height
= FRAME_PIXEL_HEIGHT (f
);
636 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
638 context
= mac_begin_cg_clip (f
, gc
);
641 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
642 CGContextFillRect (context
, dest_rect
);
644 CGContextClipToRect (context
, dest_rect
);
645 CGContextScaleCTM (context
, 1, -1);
646 CGContextTranslateCTM (context
, 0, -port_height
);
647 if (CGImageIsMask (image
))
648 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
649 CGContextDrawImage (context
,
650 CGRectMake (dest_x
- src_x
,
651 port_height
- (dest_y
- src_y
652 + CGImageGetHeight (image
)),
653 CGImageGetWidth (image
),
654 CGImageGetHeight (image
)),
659 #else /* !USE_CG_DRAWING */
662 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
665 int x
, y
, width
, height
;
666 unsigned short *bits
;
672 bitmap
.rowBytes
= sizeof(unsigned short);
673 bitmap
.baseAddr
= (char *)bits
;
674 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
676 mac_begin_clip (f
, gc
);
677 RGBForeColor (GC_FORE_COLOR (gc
));
678 RGBBackColor (GC_BACK_COLOR (gc
));
679 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
680 #if TARGET_API_MAC_CARBON
686 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
687 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
688 UnlockPortBits (port
);
690 #else /* not TARGET_API_MAC_CARBON */
691 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
692 overlay_p
? srcOr
: srcCopy
, 0);
693 #endif /* not TARGET_API_MAC_CARBON */
694 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
697 #endif /* !USE_CG_DRAWING */
700 /* Mac replacement for XCreateBitmapFromBitmapData. */
703 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
708 static const unsigned char swap_nibble
[16]
709 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
710 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
711 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
712 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
716 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
717 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
718 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
719 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
720 for (i
= 0; i
< h
; i
++)
722 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
723 for (j
= 0; j
< w1
; j
++)
725 /* Bitswap XBM bytes to match how Mac does things. */
726 unsigned char c
= *bits
++;
727 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
728 | (swap_nibble
[(c
>>4) & 0xf]));
732 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
737 mac_free_bitmap (bitmap
)
740 xfree (bitmap
->baseAddr
);
745 XCreatePixmap (display
, w
, width
, height
, depth
)
748 unsigned int width
, height
;
755 SetPortWindowPort (w
);
757 SetRect (&r
, 0, 0, width
, height
);
758 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
761 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
762 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
764 /* CreateCGImageFromPixMaps requires ARGB format. */
765 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
774 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
778 unsigned int width
, height
;
779 unsigned long fg
, bg
;
789 gc
= XCreateGC (display
, w
, 0, NULL
);
791 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
795 GetGWorld (&old_port
, &old_gdh
);
796 SetGWorld (pixmap
, NULL
);
797 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
798 XSetForeground (display
, gc
, fg
);
799 XSetBackground (display
, gc
, bg
);
800 RGBForeColor (GC_FORE_COLOR (gc
));
801 RGBBackColor (GC_BACK_COLOR (gc
));
802 LockPixels (GetGWorldPixMap (pixmap
));
803 #if TARGET_API_MAC_CARBON
804 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
805 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
806 #else /* not TARGET_API_MAC_CARBON */
807 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
808 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
809 #endif /* not TARGET_API_MAC_CARBON */
810 UnlockPixels (GetGWorldPixMap (pixmap
));
811 SetGWorld (old_port
, old_gdh
);
812 mac_free_bitmap (&bitmap
);
819 XFreePixmap (display
, pixmap
)
823 DisposeGWorld (pixmap
);
827 /* Mac replacement for XFillRectangle. */
830 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
834 unsigned int width
, height
;
837 CGContextRef context
;
839 context
= mac_begin_cg_clip (f
, gc
);
840 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
841 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
846 mac_begin_clip (f
, gc
);
847 RGBForeColor (GC_FORE_COLOR (gc
));
848 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
849 PaintRect (&r
); /* using foreground color of gc */
855 /* Mac replacement for XDrawRectangle: dest is a window. */
858 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
862 unsigned int width
, height
;
865 CGContextRef context
;
867 context
= mac_begin_cg_clip (f
, gc
);
868 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
869 CGContextStrokeRect (context
,
870 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
875 mac_begin_clip (f
, gc
);
876 RGBForeColor (GC_FORE_COLOR (gc
));
877 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
878 FrameRect (&r
); /* using foreground color of gc */
885 mac_invert_rectangle (f
, x
, y
, width
, height
)
888 unsigned int width
, height
;
893 mac_prepare_for_quickdraw (f
);
895 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
897 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
905 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
906 ConstUniCharArrayPtr text
;
907 UniCharCount text_length
;
909 ATSUTextLayout
*text_layout
;
912 static ATSUTextLayout saved_text_layout
= NULL
;
914 if (saved_text_layout
== NULL
)
916 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
917 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
918 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
919 static ATSLineLayoutOptions line_layout
=
920 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
921 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
922 | kATSLineUseQDRendering
924 kATSLineIsDisplayOnly
| kATSLineFractDisable
927 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
929 err
= ATSUCreateTextLayoutWithTextPtr (text
,
930 kATSUFromTextBeginning
,
936 err
= ATSUSetLayoutControls (saved_text_layout
,
937 sizeof (tags
) / sizeof (tags
[0]),
938 tags
, sizes
, values
);
940 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
944 err
= ATSUSetRunStyle (saved_text_layout
, style
,
945 kATSUFromTextBeginning
, kATSUToTextEnd
);
947 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
948 kATSUFromTextBeginning
,
954 *text_layout
= saved_text_layout
;
960 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
961 overstrike_p
, bytes_per_char
)
966 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
969 ATSUTextLayout text_layout
;
971 xassert (bytes_per_char
== 2);
973 #ifndef WORDS_BIG_ENDIAN
976 UniChar
*text
= (UniChar
*)buf
;
978 for (i
= 0; i
< nchars
; i
++)
979 text
[i
] = EndianU16_BtoN (text
[i
]);
982 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
984 GC_FONT (gc
)->mac_style
,
989 if (!mac_use_core_graphics
)
992 mac_begin_clip (f
, gc
);
993 RGBForeColor (GC_FORE_COLOR (gc
));
998 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
999 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1000 RGBBackColor (GC_BACK_COLOR (gc
));
1002 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1005 ATSUDrawText (text_layout
,
1006 kATSUFromTextBeginning
, kATSUToTextEnd
,
1007 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1011 ATSUDrawText (text_layout
,
1012 kATSUFromTextBeginning
, kATSUToTextEnd
,
1013 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1020 static CGContextRef context
;
1021 float port_height
= FRAME_PIXEL_HEIGHT (f
);
1022 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1023 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1024 static const ATSUAttributeValuePtr values
[] = {&context
};
1027 context
= mac_begin_cg_clip (f
, gc
);
1032 QDBeginCGContext (port
, &context
);
1033 if (gc
->n_clip_rects
|| bg_width
)
1035 CGContextTranslateCTM (context
, 0, port_height
);
1036 CGContextScaleCTM (context
, 1, -1);
1037 if (gc
->n_clip_rects
)
1038 CGContextClipToRects (context
, gc
->clip_rects
,
1043 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1044 CGContextFillRect (context
,
1045 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
1047 FONT_HEIGHT (GC_FONT (gc
))));
1049 CGContextScaleCTM (context
, 1, -1);
1050 CGContextTranslateCTM (context
, 0, -port_height
);
1054 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1055 err
= ATSUSetLayoutControls (text_layout
,
1056 sizeof (tags
) / sizeof (tags
[0]),
1057 tags
, sizes
, values
);
1060 ATSUDrawText (text_layout
,
1061 kATSUFromTextBeginning
, kATSUToTextEnd
,
1062 Long2Fix (x
), Long2Fix (port_height
- y
));
1064 ATSUDrawText (text_layout
,
1065 kATSUFromTextBeginning
, kATSUToTextEnd
,
1066 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1069 mac_end_cg_clip (f
);
1072 CGContextSynchronize (context
);
1073 QDEndCGContext (port
, &context
);
1076 /* This doesn't work on Mac OS X 10.1. */
1077 ATSUClearLayoutControls (text_layout
,
1078 sizeof (tags
) / sizeof (tags
[0]), tags
);
1080 ATSUSetLayoutControls (text_layout
,
1081 sizeof (tags
) / sizeof (tags
[0]),
1082 tags
, sizes
, values
);
1085 #endif /* MAC_OSX */
1087 #endif /* USE_ATSUI */
1091 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1092 overstrike_p
, bytes_per_char
)
1097 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1099 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1103 mac_begin_clip (f
, gc
);
1104 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1105 if (mac_use_core_graphics
)
1106 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1108 RGBForeColor (GC_FORE_COLOR (gc
));
1112 RGBBackColor (GC_BACK_COLOR (gc
));
1118 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1120 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1121 into an offscreen graphics world first. So performance gain
1122 cannot be expected.)
1123 - It lowers rendering quality.
1124 - Some fonts leave garbage on cursor movement. */
1129 RGBBackColor (GC_BACK_COLOR (gc
));
1130 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1131 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1136 TextFont (GC_FONT (gc
)->mac_fontnum
);
1137 TextSize (GC_FONT (gc
)->mac_fontsize
);
1138 TextFace (GC_FONT (gc
)->mac_fontface
);
1140 DrawText (buf
, 0, nchars
* bytes_per_char
);
1145 DrawText (buf
, 0, nchars
* bytes_per_char
);
1148 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1151 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1152 if (mac_use_core_graphics
)
1153 SwapQDTextFlags(savedFlags
);
1159 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1160 overstrike_p
, bytes_per_char
)
1165 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1168 if (GC_FONT (gc
)->mac_style
)
1169 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1170 overstrike_p
, bytes_per_char
);
1172 #endif /* USE_ATSUI */
1173 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1174 overstrike_p
, bytes_per_char
);
1178 /* Mac replacement for XDrawImageString. */
1181 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1186 int nchars
, bg_width
, overstrike_p
;
1188 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1193 /* Mac replacement for XDrawImageString16. */
1196 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1201 int nchars
, bg_width
, overstrike_p
;
1203 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1208 /* Mac replacement for XQueryTextExtents, but takes a character. If
1209 STYLE is NULL, measurement is done by QuickDraw Text routines for
1210 the font of the current graphics port. If CG_GLYPH is not NULL,
1211 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1214 mac_query_char_extents (style
, c
,
1215 font_ascent_return
, font_descent_return
,
1216 overall_return
, cg_glyph
)
1223 int *font_ascent_return
, *font_descent_return
;
1224 XCharStruct
*overall_return
;
1225 #if USE_CG_TEXT_DRAWING
1231 OSStatus err
= noErr
;
1238 ATSUTextLayout text_layout
;
1241 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1243 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1245 ATSTrapezoid glyph_bounds
;
1247 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1248 kATSUFromTextBeginning
, kATSUToTextEnd
,
1249 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1250 kATSUseFractionalOrigins
,
1252 kATSUseDeviceOrigins
,
1254 1, &glyph_bounds
, NULL
);
1257 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1258 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1260 width
= Fix2Long (glyph_bounds
.upperRight
.x
1261 - glyph_bounds
.upperLeft
.x
);
1262 if (font_ascent_return
)
1263 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1264 if (font_descent_return
)
1265 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1268 if (err
== noErr
&& overall_return
)
1270 err
= ATSUMeasureTextImage (text_layout
,
1271 kATSUFromTextBeginning
, kATSUToTextEnd
,
1272 0, 0, &char_bounds
);
1274 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1275 #if USE_CG_TEXT_DRAWING
1276 if (err
== noErr
&& cg_glyph
)
1279 ATSUGlyphInfoArray glyph_info_array
;
1280 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1282 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1283 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1285 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1286 kATSUToTextEnd
, &count
,
1289 /* Make sure that we don't have to make layout
1291 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1292 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1293 && glyph_info_array
.glyphs
[0].screenX
== 0)
1295 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1296 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1307 if (font_ascent_return
|| font_descent_return
)
1311 GetFontInfo (&font_info
);
1312 if (font_ascent_return
)
1313 *font_ascent_return
= font_info
.ascent
;
1314 if (font_descent_return
)
1315 *font_descent_return
= font_info
.descent
;
1321 width
= CharWidth (ch
);
1322 QDTextBounds (1, &ch
, &char_bounds
);
1323 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1331 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1334 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1335 XFontStruct
*font_struct
;
1338 XCharStruct
*overall_return
;
1341 short width
= 0, lbearing
= 0, rbearing
= 0;
1344 for (i
= 0; i
< nchars
; i
++)
1346 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1348 width
+= FONT_WIDTH (font_struct
);
1351 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1352 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1353 width
+= pcm
->width
;
1358 overall_return
->lbearing
= lbearing
;
1359 overall_return
->rbearing
= rbearing
;
1360 overall_return
->width
= width
;
1362 /* What's the meaning of the return value of XTextExtents16? */
1366 #if USE_CG_TEXT_DRAWING
1367 static int cg_text_anti_aliasing_threshold
= 8;
1370 init_cg_text_anti_aliasing_threshold ()
1376 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1377 kCFPreferencesCurrentApplication
,
1380 cg_text_anti_aliasing_threshold
= threshold
;
1384 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1389 int nchars
, bg_width
, overstrike_p
;
1391 float port_height
, gx
, gy
;
1393 CGContextRef context
;
1397 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1400 port_height
= FRAME_PIXEL_HEIGHT (f
);
1402 gy
= port_height
- y
;
1403 glyphs
= (CGGlyph
*)buf
;
1404 advances
= alloca (sizeof (CGSize
) * nchars
);
1405 if (advances
== NULL
)
1407 for (i
= 0; i
< nchars
; i
++)
1409 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1411 advances
[i
].width
= pcm
->width
;
1412 advances
[i
].height
= 0;
1413 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1418 context
= mac_begin_cg_clip (f
, gc
);
1420 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1421 if (gc
->n_clip_rects
|| bg_width
)
1423 CGContextTranslateCTM (context
, 0, port_height
);
1424 CGContextScaleCTM (context
, 1, -1);
1425 if (gc
->n_clip_rects
)
1426 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1430 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1433 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1434 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1436 CGContextScaleCTM (context
, 1, -1);
1437 CGContextTranslateCTM (context
, 0, -port_height
);
1441 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1442 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1443 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1444 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1445 CGContextSetShouldAntialias (context
, false);
1446 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1447 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1448 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1451 CGContextSetTextPosition (context
, gx
, gy
);
1452 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1455 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1456 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1459 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1460 else /* CGContextShowGlyphsWithAdvances == NULL */
1462 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1463 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1465 for (i
= 0; i
< nchars
; i
++)
1467 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1469 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1470 gx
+= advances
[i
].width
;
1475 mac_end_cg_clip (f
);
1477 CGContextSynchronize (context
);
1478 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1487 /* Mac replacement for XCopyArea: dest must be window. */
1490 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1495 unsigned int width
, height
;
1500 mac_begin_clip (f
, gc
);
1502 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1503 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1505 ForeColor (blackColor
);
1506 BackColor (whiteColor
);
1508 LockPixels (GetGWorldPixMap (src
));
1509 #if TARGET_API_MAC_CARBON
1514 LockPortBits (port
);
1515 CopyBits (GetPortBitMapForCopyBits (src
),
1516 GetPortBitMapForCopyBits (port
),
1517 &src_r
, &dest_r
, srcCopy
, 0);
1518 UnlockPortBits (port
);
1520 #else /* not TARGET_API_MAC_CARBON */
1521 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1522 &src_r
, &dest_r
, srcCopy
, 0);
1523 #endif /* not TARGET_API_MAC_CARBON */
1524 UnlockPixels (GetGWorldPixMap (src
));
1526 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1533 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1534 width
, height
, dest_x
, dest_y
)
1539 unsigned int width
, height
;
1544 mac_begin_clip (f
, gc
);
1546 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1547 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1549 ForeColor (blackColor
);
1550 BackColor (whiteColor
);
1552 LockPixels (GetGWorldPixMap (src
));
1553 LockPixels (GetGWorldPixMap (mask
));
1554 #if TARGET_API_MAC_CARBON
1559 LockPortBits (port
);
1560 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1561 GetPortBitMapForCopyBits (port
),
1562 &src_r
, &src_r
, &dest_r
);
1563 UnlockPortBits (port
);
1565 #else /* not TARGET_API_MAC_CARBON */
1566 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1567 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1568 #endif /* not TARGET_API_MAC_CARBON */
1569 UnlockPixels (GetGWorldPixMap (mask
));
1570 UnlockPixels (GetGWorldPixMap (src
));
1572 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1576 #endif /* !USE_CG_DRAWING */
1579 /* Mac replacement for XCopyArea: used only for scrolling. */
1582 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1586 unsigned int width
, height
;
1589 #if TARGET_API_MAC_CARBON
1591 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1593 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1595 mac_prepare_for_quickdraw (f
);
1597 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1598 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1599 kScrollWindowNoOptions
, dummy
);
1601 #else /* not TARGET_API_MAC_CARBON */
1603 WindowRef w
= FRAME_MAC_WINDOW (f
);
1605 mac_begin_clip (f
, gc
);
1607 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1608 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1610 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1611 color mapping in CopyBits. Otherwise, it will be slow. */
1612 ForeColor (blackColor
);
1613 BackColor (whiteColor
);
1614 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1616 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1619 #endif /* not TARGET_API_MAC_CARBON */
1623 /* Mac replacement for XChangeGC. */
1626 XChangeGC (display
, gc
, mask
, xgcv
)
1632 if (mask
& GCForeground
)
1633 XSetForeground (display
, gc
, xgcv
->foreground
);
1634 if (mask
& GCBackground
)
1635 XSetBackground (display
, gc
, xgcv
->background
);
1637 XSetFont (display
, gc
, xgcv
->font
);
1641 /* Mac replacement for XCreateGC. */
1644 XCreateGC (display
, d
, mask
, xgcv
)
1650 GC gc
= xmalloc (sizeof (*gc
));
1652 bzero (gc
, sizeof (*gc
));
1653 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1654 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1655 if (CGColorGetTypeID
!= NULL
)
1658 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1659 CGColorRetain (gc
->cg_fore_color
);
1660 CGColorRetain (gc
->cg_back_color
);
1663 XChangeGC (display
, gc
, mask
, xgcv
);
1669 /* Used in xfaces.c. */
1672 XFreeGC (display
, gc
)
1676 if (gc
->clip_region
)
1677 DisposeRgn (gc
->clip_region
);
1678 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1679 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1680 if (CGColorGetTypeID
!= NULL
)
1683 CGColorRelease (gc
->cg_fore_color
);
1684 CGColorRelease (gc
->cg_back_color
);
1691 /* Mac replacement for XGetGCValues. */
1694 XGetGCValues (display
, gc
, mask
, xgcv
)
1700 if (mask
& GCForeground
)
1701 xgcv
->foreground
= gc
->xgcv
.foreground
;
1702 if (mask
& GCBackground
)
1703 xgcv
->background
= gc
->xgcv
.background
;
1705 xgcv
->font
= gc
->xgcv
.font
;
1709 /* Mac replacement for XSetForeground. */
1712 XSetForeground (display
, gc
, color
)
1715 unsigned long color
;
1717 if (gc
->xgcv
.foreground
!= color
)
1719 gc
->xgcv
.foreground
= color
;
1720 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1721 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1722 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1723 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1724 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1725 if (CGColorGetTypeID
!= NULL
)
1728 CGColorRelease (gc
->cg_fore_color
);
1731 gc
->cg_fore_color
= mac_cg_color_black
;
1732 CGColorRetain (gc
->cg_fore_color
);
1738 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1739 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1740 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1742 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1750 /* Mac replacement for XSetBackground. */
1753 XSetBackground (display
, gc
, color
)
1756 unsigned long color
;
1758 if (gc
->xgcv
.background
!= color
)
1760 gc
->xgcv
.background
= color
;
1761 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1762 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1763 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1764 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1765 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1766 if (CGColorGetTypeID
!= NULL
)
1769 CGColorRelease (gc
->cg_back_color
);
1772 gc
->cg_back_color
= mac_cg_color_black
;
1773 CGColorRetain (gc
->cg_back_color
);
1779 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1780 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1781 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1783 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1791 /* Mac replacement for XSetFont. */
1794 XSetFont (display
, gc
, font
)
1799 gc
->xgcv
.font
= font
;
1803 /* Mac replacement for XSetClipRectangles. */
1806 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1814 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1816 gc
->n_clip_rects
= n
;
1819 if (gc
->clip_region
== NULL
)
1820 gc
->clip_region
= NewRgn ();
1821 RectRgn (gc
->clip_region
, rectangles
);
1824 RgnHandle region
= NewRgn ();
1826 for (i
= 1; i
< n
; i
++)
1828 RectRgn (region
, rectangles
+ i
);
1829 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1831 DisposeRgn (region
);
1834 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1835 for (i
= 0; i
< n
; i
++)
1837 Rect
*rect
= rectangles
+ i
;
1839 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1840 rect
->right
- rect
->left
,
1841 rect
->bottom
- rect
->top
);
1847 /* Mac replacement for XSetClipMask. */
1850 mac_reset_clip_rectangles (display
, gc
)
1854 gc
->n_clip_rects
= 0;
1858 /* Mac replacement for XSetWindowBackground. */
1861 XSetWindowBackground (display
, w
, color
)
1864 unsigned long color
;
1866 #if !TARGET_API_MAC_CARBON
1867 AuxWinHandle aw_handle
;
1868 CTabHandle ctab_handle
;
1869 ColorSpecPtr ct_table
;
1874 bg_color
.red
= RED16_FROM_ULONG (color
);
1875 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1876 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1878 #if TARGET_API_MAC_CARBON
1879 SetWindowContentColor (w
, &bg_color
);
1881 if (GetAuxWin (w
, &aw_handle
))
1883 ctab_handle
= (*aw_handle
)->awCTable
;
1884 HandToHand ((Handle
*) &ctab_handle
);
1885 ct_table
= (*ctab_handle
)->ctTable
;
1886 ct_size
= (*ctab_handle
)->ctSize
;
1887 while (ct_size
> -1)
1889 if (ct_table
->value
== 0)
1891 ct_table
->rgb
= bg_color
;
1892 CTabChanged (ctab_handle
);
1893 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1901 /* Flush display of frame F, or of all frames if F is null. */
1907 #if TARGET_API_MAC_CARBON
1910 mac_prepare_for_quickdraw (f
);
1913 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1915 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1921 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1922 Calls to XFlush should be unnecessary because the X output buffer
1923 is flushed automatically as needed by calls to XPending,
1924 XNextEvent, or XWindowEvent according to the XFlush man page.
1925 XTread_socket calls XPending. Removing XFlush improves
1928 #define XFlush(DISPLAY) (void) 0
1932 mac_flush_display_optional (f
)
1936 mac_prepare_for_quickdraw (f
);
1941 /***********************************************************************
1942 Starting and ending an update
1943 ***********************************************************************/
1945 /* Start an update of frame F. This function is installed as a hook
1946 for update_begin, i.e. it is called when update_begin is called.
1947 This function is called prior to calls to x_update_window_begin for
1948 each window being updated. */
1954 #if TARGET_API_MAC_CARBON
1955 /* During update of a frame, availability of input events is
1956 periodically checked with ReceiveNextEvent if
1957 redisplay-dont-pause is nil. That normally flushes window buffer
1958 changes for every check, and thus screen update looks waving even
1959 if no input is available. So we disable screen updates during
1960 update of a frame. */
1962 DisableScreenUpdates ();
1968 /* Start update of window W. Set the global variable updated_window
1969 to the window being updated and set output_cursor to the cursor
1973 x_update_window_begin (w
)
1976 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1977 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1980 set_output_cursor (&w
->cursor
);
1984 if (f
== display_info
->mouse_face_mouse_frame
)
1986 /* Don't do highlighting for mouse motion during the update. */
1987 display_info
->mouse_face_defer
= 1;
1989 /* If F needs to be redrawn, simply forget about any prior mouse
1991 if (FRAME_GARBAGED_P (f
))
1992 display_info
->mouse_face_window
= Qnil
;
1994 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1995 their mouse_face_p flag set, which means that they are always
1996 unequal to rows in a desired matrix which never have that
1997 flag set. So, rows containing mouse-face glyphs are never
1998 scrolled, and we don't have to switch the mouse highlight off
1999 here to prevent it from being scrolled. */
2001 /* Can we tell that this update does not affect the window
2002 where the mouse highlight is? If so, no need to turn off.
2003 Likewise, don't do anything if the frame is garbaged;
2004 in that case, the frame's current matrix that we would use
2005 is all wrong, and we will redisplay that line anyway. */
2006 if (!NILP (display_info
->mouse_face_window
)
2007 && w
== XWINDOW (display_info
->mouse_face_window
))
2011 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2012 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2015 if (i
< w
->desired_matrix
->nrows
)
2016 clear_mouse_face (display_info
);
2025 /* Draw a vertical window border from (x,y0) to (x,y1) */
2028 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2032 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2035 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2037 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2040 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2043 /* End update of window W (which is equal to updated_window).
2045 Draw vertical borders between horizontally adjacent windows, and
2046 display W's cursor if CURSOR_ON_P is non-zero.
2048 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2049 glyphs in mouse-face were overwritten. In that case we have to
2050 make sure that the mouse-highlight is properly redrawn.
2052 W may be a menu bar pseudo-window in case we don't have X toolkit
2053 support. Such windows don't have a cursor, so don't display it
2057 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2059 int cursor_on_p
, mouse_face_overwritten_p
;
2061 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2063 if (!w
->pseudo_window_p
)
2068 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2070 output_cursor
.x
, output_cursor
.y
);
2072 if (draw_window_fringes (w
, 1))
2073 x_draw_vertical_border (w
);
2078 /* If a row with mouse-face was overwritten, arrange for
2079 XTframe_up_to_date to redisplay the mouse highlight. */
2080 if (mouse_face_overwritten_p
)
2082 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2083 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2084 dpyinfo
->mouse_face_window
= Qnil
;
2087 updated_window
= NULL
;
2091 /* End update of frame F. This function is installed as a hook in
2098 /* Mouse highlight may be displayed again. */
2099 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2102 #if TARGET_API_MAC_CARBON
2103 EnableScreenUpdates ();
2105 XFlush (FRAME_MAC_DISPLAY (f
));
2110 /* This function is called from various places in xdisp.c whenever a
2111 complete update has been performed. The global variable
2112 updated_window is not available here. */
2115 XTframe_up_to_date (f
)
2118 if (FRAME_MAC_P (f
))
2120 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2122 if (dpyinfo
->mouse_face_deferred_gc
2123 || f
== dpyinfo
->mouse_face_mouse_frame
)
2126 if (dpyinfo
->mouse_face_mouse_frame
)
2127 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2128 dpyinfo
->mouse_face_mouse_x
,
2129 dpyinfo
->mouse_face_mouse_y
);
2130 dpyinfo
->mouse_face_deferred_gc
= 0;
2137 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2138 arrow bitmaps, or clear the fringes if no bitmaps are required
2139 before DESIRED_ROW is made current. The window being updated is
2140 found in updated_window. This function is called from
2141 update_window_line only if it is known that there are differences
2142 between bitmaps to be drawn between current row and DESIRED_ROW. */
2145 x_after_update_window_line (desired_row
)
2146 struct glyph_row
*desired_row
;
2148 struct window
*w
= updated_window
;
2154 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2155 desired_row
->redraw_fringe_bitmaps_p
= 1;
2157 /* When a window has disappeared, make sure that no rest of
2158 full-width rows stays visible in the internal border. Could
2159 check here if updated_window is the leftmost/rightmost window,
2160 but I guess it's not worth doing since vertically split windows
2161 are almost never used, internal border is rarely set, and the
2162 overhead is very small. */
2163 if (windows_or_buffers_changed
2164 && desired_row
->full_width_p
2165 && (f
= XFRAME (w
->frame
),
2166 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2168 && (height
= desired_row
->visible_height
,
2171 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2173 /* Internal border is drawn below the tool bar. */
2174 if (WINDOWP (f
->tool_bar_window
)
2175 && w
== XWINDOW (f
->tool_bar_window
))
2179 mac_clear_area (f
, 0, y
, width
, height
);
2180 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2186 /* Draw the bitmap WHICH in one of the left or right fringes of
2187 window W. ROW is the glyph row for which to display the bitmap; it
2188 determines the vertical position at which the bitmap has to be
2192 x_draw_fringe_bitmap (w
, row
, p
)
2194 struct glyph_row
*row
;
2195 struct draw_fringe_bitmap_params
*p
;
2197 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2198 Display
*display
= FRAME_MAC_DISPLAY (f
);
2199 struct face
*face
= p
->face
;
2201 int overlay_p
= p
->overlay_p
;
2206 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2208 #if 0 /* MAC_TODO: stipple */
2209 /* In case the same realized face is used for fringes and
2210 for something displayed in the text (e.g. face `region' on
2211 mono-displays, the fill style may have been changed to
2212 FillSolid in x_draw_glyph_string_background. */
2214 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2216 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2219 /* If the fringe is adjacent to the left (right) scroll bar of a
2220 leftmost (rightmost, respectively) window, then extend its
2221 background to the gap between the fringe and the bar. */
2222 if ((WINDOW_LEFTMOST_P (w
)
2223 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2224 || (WINDOW_RIGHTMOST_P (w
)
2225 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2227 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2231 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2232 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2233 * FRAME_COLUMN_WIDTH (f
));
2236 && (left
+ width
== p
->x
2237 || p
->x
+ p
->wd
== left
))
2239 /* Bitmap fills the fringe and we need background
2241 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
2245 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
2247 ny
= row
->visible_height
;
2252 if (left
+ width
== bx
)
2254 bx
= left
+ sb_width
;
2255 nx
+= width
- sb_width
;
2257 else if (bx
+ nx
== left
)
2258 nx
+= width
- sb_width
;
2265 mac_erase_rectangle (f
, face
->gc
, bx
, by
, nx
, ny
);
2266 /* The fringe background has already been filled. */
2270 #if 0 /* MAC_TODO: stipple */
2272 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2275 #endif /* MAC_OSX */
2277 /* Must clip because of partially visible lines. */
2278 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2281 /* Adjust position of "bottom aligned" bitmap on partially
2282 visible last row. */
2284 int oldVH
= row
->visible_height
;
2285 row
->visible_height
= p
->h
;
2286 row
->y
-= rowY
- p
->y
;
2287 x_clip_to_row (w
, row
, -1, face
->gc
);
2289 row
->visible_height
= oldVH
;
2292 x_clip_to_row (w
, row
, -1, face
->gc
);
2295 if (p
->bx
>= 0 && !p
->overlay_p
)
2297 #if 0 /* MAC_TODO: stipple */
2298 /* In case the same realized face is used for fringes and
2299 for something displayed in the text (e.g. face `region' on
2300 mono-displays, the fill style may have been changed to
2301 FillSolid in x_draw_glyph_string_background. */
2303 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2305 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2308 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2310 #if 0 /* MAC_TODO: stipple */
2312 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2315 #endif /* !MAC_OSX */
2319 && p
->which
< max_fringe_bmp
2325 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2326 XSetForeground (display
, face
->gc
,
2328 ? (p
->overlay_p
? face
->background
2329 : f
->output_data
.mac
->cursor_pixel
)
2330 : face
->foreground
));
2332 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2333 p
->wd
, p
->h
, p
->x
, p
->y
, overlay_p
);
2335 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2336 p
->wd
, p
->h
, p
->bits
+ p
->dh
, overlay_p
);
2338 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2341 mac_reset_clip_rectangles (display
, face
->gc
);
2346 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2348 unsigned short *bits
;
2352 CGDataProviderRef provider
;
2354 if (which
>= max_fringe_bmp
)
2357 max_fringe_bmp
= which
+ 20;
2358 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2359 while (i
< max_fringe_bmp
)
2360 fringe_bmp
[i
++] = 0;
2363 for (i
= 0; i
< h
; i
++)
2368 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2369 sizeof (unsigned short) * h
, NULL
);
2372 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2373 sizeof (unsigned short),
2375 CGDataProviderRelease (provider
);
2382 mac_destroy_fringe_bitmap (which
)
2385 if (which
>= max_fringe_bmp
)
2388 if (fringe_bmp
[which
])
2391 CGImageRelease (fringe_bmp
[which
]);
2394 fringe_bmp
[which
] = 0;
2399 /* This is called when starting Emacs and when restarting after
2400 suspend. When starting Emacs, no window is mapped. And nothing
2401 must be done to Emacs's own window if it is suspended (though that
2405 XTset_terminal_modes (struct terminal
*t
)
2409 /* This is called when exiting or suspending Emacs. Exiting will make
2410 the windows go away, and suspending requires no action. */
2413 XTreset_terminal_modes (struct terminal
*t
)
2419 /***********************************************************************
2421 ***********************************************************************/
2423 /* Function prototypes of this page. */
2425 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2426 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
2427 struct charset
*, int *));
2431 pcm_init (pcm
, count
)
2435 bzero (pcm
, sizeof (XCharStruct
) * count
);
2436 while (--count
>= 0)
2438 pcm
->descent
= PCM_INVALID
;
2443 static enum pcm_status
2444 pcm_get_status (pcm
)
2445 const XCharStruct
*pcm
;
2447 int height
= pcm
->ascent
+ pcm
->descent
;
2449 /* Negative height means some special status. */
2450 return height
>= 0 ? PCM_VALID
: height
;
2453 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2454 is not contained in the font. */
2456 static INLINE XCharStruct
*
2457 x_per_char_metric (font
, char2b
)
2461 /* The result metric information. */
2462 XCharStruct
*pcm
= NULL
;
2464 xassert (font
&& char2b
);
2467 if (font
->mac_style
)
2469 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2473 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2474 pcm_init (*row
, 0x100);
2476 pcm
= *row
+ char2b
->byte2
;
2477 if (pcm_get_status (pcm
) != PCM_VALID
)
2480 mac_query_char_extents (font
->mac_style
,
2481 (char2b
->byte1
<< 8) + char2b
->byte2
,
2482 NULL
, NULL
, pcm
, NULL
);
2489 if (font
->bounds
.per_char
!= NULL
)
2491 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2493 /* min_char_or_byte2 specifies the linear character index
2494 corresponding to the first element of the per_char array,
2495 max_char_or_byte2 is the index of the last character. A
2496 character with non-zero CHAR2B->byte1 is not in the font.
2497 A character with byte2 less than min_char_or_byte2 or
2498 greater max_char_or_byte2 is not in the font. */
2499 if (char2b
->byte1
== 0
2500 && char2b
->byte2
>= font
->min_char_or_byte2
2501 && char2b
->byte2
<= font
->max_char_or_byte2
)
2502 pcm
= font
->bounds
.per_char
2503 + (char2b
->byte2
- font
->min_char_or_byte2
);
2507 /* If either min_byte1 or max_byte1 are nonzero, both
2508 min_char_or_byte2 and max_char_or_byte2 are less than
2509 256, and the 2-byte character index values corresponding
2510 to the per_char array element N (counting from 0) are:
2512 byte1 = N/D + min_byte1
2513 byte2 = N\D + min_char_or_byte2
2517 D = max_char_or_byte2 - min_char_or_byte2 + 1
2518 / = integer division
2519 \ = integer modulus */
2520 if (char2b
->byte1
>= font
->min_byte1
2521 && char2b
->byte1
<= font
->max_byte1
2522 && char2b
->byte2
>= font
->min_char_or_byte2
2523 && char2b
->byte2
<= font
->max_char_or_byte2
)
2525 pcm
= (font
->bounds
.per_char
2526 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2527 * (char2b
->byte1
- font
->min_byte1
))
2528 + (char2b
->byte2
- font
->min_char_or_byte2
));
2534 /* If the per_char pointer is null, all glyphs between the first
2535 and last character indexes inclusive have the same
2536 information, as given by both min_bounds and max_bounds. */
2537 if (char2b
->byte2
>= font
->min_char_or_byte2
2538 && char2b
->byte2
<= font
->max_char_or_byte2
)
2539 pcm
= &font
->max_bounds
;
2545 return ((pcm
== NULL
2547 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2548 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2557 static XCharStruct
*
2558 mac_per_char_metric (font
, char2b
, font_type
)
2563 return x_per_char_metric (font
, char2b
);
2567 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2568 the two-byte form of C. Encoding is returned in *CHAR2B. */
2571 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
2574 struct font_info
*font_info
;
2575 struct charset
*charset
;
2578 XFontStruct
*font
= font_info
->font
;
2580 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2581 This may be either a program in a special encoder language or a
2583 if (font_info
->font_encoder
)
2585 /* It's a program. */
2586 struct ccl_program
*ccl
= font_info
->font_encoder
;
2588 check_ccl_update (ccl
);
2589 if (CHARSET_DIMENSION (charset
) == 1)
2591 ccl
->reg
[0] = CHARSET_ID (charset
);
2592 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
2597 ccl
->reg
[0] = CHARSET_ID (charset
);
2598 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
2599 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
2602 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
2604 /* We assume that MSBs are appropriately set/reset by CCL
2606 if (font
->max_byte1
== 0) /* 1-byte font */
2607 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
2609 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
2611 else if (font_info
->encoding_type
)
2613 /* Fixed encoding scheme. See fontset.h for the meaning of the
2614 encoding numbers. */
2615 unsigned char enc
= font_info
->encoding_type
;
2617 if ((enc
== 1 || enc
== 2)
2618 && CHARSET_DIMENSION (charset
) == 2)
2619 char2b
->byte1
|= 0x80;
2621 if (enc
== 1 || enc
== 3)
2622 char2b
->byte2
|= 0x80;
2626 int code
= (char2b
->byte1
<< 8) | char2b
->byte2
;
2629 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
2634 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2636 return FONT_TYPE_UNKNOWN
;
2641 /***********************************************************************
2643 ***********************************************************************/
2647 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2648 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2649 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2651 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2652 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2653 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2654 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2655 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2656 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2657 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2658 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2659 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2660 unsigned long *, double, int));*/
2661 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2662 double, int, unsigned long));
2663 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2664 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2665 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2666 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2667 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2669 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2670 int, int, int, int, int, int,
2672 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2673 int, int, int, Rect
*));
2676 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2680 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2685 struct glyph_string
*s
;
2687 if (s
->font
== FRAME_FONT (s
->f
)
2688 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2689 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2691 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2694 /* Cursor on non-default face: must merge. */
2698 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2699 xgcv
.foreground
= s
->face
->background
;
2701 /* If the glyph would be invisible, try a different foreground. */
2702 if (xgcv
.foreground
== xgcv
.background
)
2703 xgcv
.foreground
= s
->face
->foreground
;
2704 if (xgcv
.foreground
== xgcv
.background
)
2705 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2706 if (xgcv
.foreground
== xgcv
.background
)
2707 xgcv
.foreground
= s
->face
->foreground
;
2709 /* Make sure the cursor is distinct from text in this face. */
2710 if (xgcv
.background
== s
->face
->background
2711 && xgcv
.foreground
== s
->face
->foreground
)
2713 xgcv
.background
= s
->face
->foreground
;
2714 xgcv
.foreground
= s
->face
->background
;
2717 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2718 xgcv
.font
= s
->font
;
2719 mask
= GCForeground
| GCBackground
| GCFont
;
2721 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2722 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2725 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2726 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2728 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2733 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2736 x_set_mouse_face_gc (s
)
2737 struct glyph_string
*s
;
2742 /* What face has to be used last for the mouse face? */
2743 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2744 face
= FACE_FROM_ID (s
->f
, face_id
);
2746 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2748 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2749 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
2751 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
2752 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2753 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2755 /* If font in this face is same as S->font, use it. */
2756 if (s
->font
== s
->face
->font
)
2757 s
->gc
= s
->face
->gc
;
2760 /* Otherwise construct scratch_cursor_gc with values from FACE
2765 xgcv
.background
= s
->face
->background
;
2766 xgcv
.foreground
= s
->face
->foreground
;
2767 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2768 xgcv
.font
= s
->font
;
2769 mask
= GCForeground
| GCBackground
| GCFont
;
2771 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2772 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2775 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2776 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2778 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2781 xassert (s
->gc
!= 0);
2785 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2786 Faces to use in the mode line have already been computed when the
2787 matrix was built, so there isn't much to do, here. */
2790 x_set_mode_line_face_gc (s
)
2791 struct glyph_string
*s
;
2793 s
->gc
= s
->face
->gc
;
2797 /* Set S->gc of glyph string S for drawing that glyph string. Set
2798 S->stippled_p to a non-zero value if the face of S has a stipple
2802 x_set_glyph_string_gc (s
)
2803 struct glyph_string
*s
;
2805 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2807 if (s
->hl
== DRAW_NORMAL_TEXT
)
2809 s
->gc
= s
->face
->gc
;
2810 s
->stippled_p
= s
->face
->stipple
!= 0;
2812 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2814 x_set_mode_line_face_gc (s
);
2815 s
->stippled_p
= s
->face
->stipple
!= 0;
2817 else if (s
->hl
== DRAW_CURSOR
)
2819 x_set_cursor_gc (s
);
2822 else if (s
->hl
== DRAW_MOUSE_FACE
)
2824 x_set_mouse_face_gc (s
);
2825 s
->stippled_p
= s
->face
->stipple
!= 0;
2827 else if (s
->hl
== DRAW_IMAGE_RAISED
2828 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2830 s
->gc
= s
->face
->gc
;
2831 s
->stippled_p
= s
->face
->stipple
!= 0;
2835 s
->gc
= s
->face
->gc
;
2836 s
->stippled_p
= s
->face
->stipple
!= 0;
2839 /* GC must have been set. */
2840 xassert (s
->gc
!= 0);
2844 /* Set clipping for output of glyph string S. S may be part of a mode
2845 line or menu if we don't have X toolkit support. */
2848 x_set_glyph_string_clipping (s
)
2849 struct glyph_string
*s
;
2851 Rect rects
[MAX_CLIP_RECTS
];
2854 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2855 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2860 Compute left and right overhang of glyph string S. If S is a glyph
2861 string for a composition, assume overhangs don't exist. */
2864 mac_compute_glyph_string_overhangs (s
)
2865 struct glyph_string
*s
;
2867 if (!(s
->cmp
== NULL
2868 && s
->first_glyph
->type
== CHAR_GLYPH
))
2873 || s
->font
->mac_style
2879 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2880 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2881 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2886 MacFontStruct
*font
= s
->font
;
2889 mac_prepare_for_quickdraw (s
->f
);
2891 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2893 TextFont (font
->mac_fontnum
);
2894 TextSize (font
->mac_fontsize
);
2895 TextFace (font
->mac_fontface
);
2897 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2899 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2900 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2905 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2908 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2909 struct glyph_string
*s
;
2912 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2916 /* Draw the background of glyph_string S. If S->background_filled_p
2917 is non-zero don't draw it. FORCE_P non-zero means draw the
2918 background even if it wouldn't be drawn normally. This is used
2919 when a string preceding S draws into the background of S, or S
2920 contains the first component of a composition. */
2923 x_draw_glyph_string_background (s
, force_p
)
2924 struct glyph_string
*s
;
2927 /* Nothing to do if background has already been drawn or if it
2928 shouldn't be drawn in the first place. */
2929 if (!s
->background_filled_p
)
2931 int box_line_width
= max (s
->face
->box_line_width
, 0);
2933 #if 0 /* MAC_TODO: stipple */
2936 /* Fill background with a stipple pattern. */
2937 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2938 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2939 s
->y
+ box_line_width
,
2940 s
->background_width
,
2941 s
->height
- 2 * box_line_width
);
2942 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2943 s
->background_filled_p
= 1;
2947 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2948 || s
->font_not_found_p
2949 || s
->extends_to_end_of_line_p
2952 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2953 s
->background_width
,
2954 s
->height
- 2 * box_line_width
);
2955 s
->background_filled_p
= 1;
2961 /* Draw the foreground of glyph string S. */
2964 x_draw_glyph_string_foreground (s
)
2965 struct glyph_string
*s
;
2969 /* If first glyph of S has a left box line, start drawing the text
2970 of S to the right of that box line. */
2971 if (s
->face
->box
!= FACE_NO_BOX
2972 && s
->first_glyph
->left_box_line_p
)
2973 x
= s
->x
+ eabs (s
->face
->box_line_width
);
2977 /* Draw characters of S as rectangles if S's font could not be
2979 if (s
->font_not_found_p
)
2981 for (i
= 0; i
< s
->nchars
; ++i
)
2983 struct glyph
*g
= s
->first_glyph
+ i
;
2984 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2985 g
->pixel_width
- 1, s
->height
- 1);
2986 x
+= g
->pixel_width
;
2991 char *char1b
= (char *) s
->char2b
;
2992 int boff
= s
->font_info
->baseline_offset
;
2994 if (s
->font_info
->vertical_centering
)
2995 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2997 /* If we can use 8-bit functions, condense S->char2b. */
3000 && GC_FONT (s
->gc
)->mac_style
== NULL
3003 for (i
= 0; i
< s
->nchars
; ++i
)
3004 char1b
[i
] = s
->char2b
[i
].byte2
;
3006 /* Draw text with XDrawString if background has already been
3007 filled. Otherwise, use XDrawImageString. (Note that
3008 XDrawImageString is usually faster than XDrawString.) Always
3009 use XDrawImageString when drawing the cursor so that there is
3010 no chance that characters under a box cursor are invisible. */
3012 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3013 bg_width
= 0; /* Corresponds to XDrawString. */
3015 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
3019 || GC_FONT (s
->gc
)->mac_style
3022 #if USE_CG_TEXT_DRAWING
3024 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3025 s
->char2b
, s
->nchars
, bg_width
,
3026 s
->face
->overstrike
))
3030 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3031 s
->char2b
, s
->nchars
, bg_width
,
3032 s
->face
->overstrike
);
3034 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3035 char1b
, s
->nchars
, bg_width
,
3036 s
->face
->overstrike
);
3040 /* Draw the foreground of composite glyph string S. */
3043 x_draw_composite_glyph_string_foreground (s
)
3044 struct glyph_string
*s
;
3048 /* If first glyph of S has a left box line, start drawing the text
3049 of S to the right of that box line. */
3050 if (s
->face
->box
!= FACE_NO_BOX
3051 && s
->first_glyph
->left_box_line_p
)
3052 x
= s
->x
+ eabs (s
->face
->box_line_width
);
3056 /* S is a glyph string for a composition. S->gidx is the index of
3057 the first character drawn for glyphs of this composition.
3058 S->gidx == 0 means we are drawing the very first character of
3059 this composition. */
3061 /* Draw a rectangle for the composition if the font for the very
3062 first character of the composition could not be loaded. */
3063 if (s
->font_not_found_p
)
3066 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3067 s
->width
- 1, s
->height
- 1);
3071 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3072 if (mac_per_char_metric (GC_FONT (s
->gc
), s
->char2b
+ i
, 0) == NULL
)
3073 /* This is a nonexistent or zero-width glyph such as a
3074 combining diacritic. Draw a rectangle. */
3075 mac_draw_rectangle (s
->f
, s
->gc
,
3076 x
+ s
->cmp
->offsets
[s
->gidx
* 2], s
->y
,
3077 FONT_WIDTH (GC_FONT (s
->gc
)) - 1, s
->height
- 1);
3079 mac_draw_image_string_16 (s
->f
, s
->gc
,
3080 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3081 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3082 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3087 #ifdef USE_X_TOOLKIT
3089 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3092 /* Return the frame on which widget WIDGET is used.. Abort if frame
3093 cannot be determined. */
3095 static struct frame
*
3096 x_frame_of_widget (widget
)
3099 struct x_display_info
*dpyinfo
;
3103 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3105 /* Find the top-level shell of the widget. Note that this function
3106 can be called when the widget is not yet realized, so XtWindow
3107 (widget) == 0. That's the reason we can't simply use
3108 x_any_window_to_frame. */
3109 while (!XtIsTopLevelShell (widget
))
3110 widget
= XtParent (widget
);
3112 /* Look for a frame with that top-level widget. Allocate the color
3113 on that frame to get the right gamma correction value. */
3114 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
3115 if (FRAMEP (XCAR (tail
))
3116 && (f
= XFRAME (XCAR (tail
)),
3117 (f
->output_data
.nothing
!= 1
3118 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3119 && f
->output_data
.x
->widget
== widget
)
3126 /* Allocate the color COLOR->pixel on the screen and display of
3127 widget WIDGET in colormap CMAP. If an exact match cannot be
3128 allocated, try the nearest color available. Value is non-zero
3129 if successful. This is called from lwlib. */
3132 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3137 struct frame
*f
= x_frame_of_widget (widget
);
3138 return x_alloc_nearest_color (f
, cmap
, color
);
3142 #endif /* USE_X_TOOLKIT */
3144 #if 0 /* MAC_TODO */
3146 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3147 CMAP. If an exact match can't be allocated, try the nearest color
3148 available. Value is non-zero if successful. Set *COLOR to the
3152 x_alloc_nearest_color (f
, cmap
, color
)
3157 Display
*display
= FRAME_X_DISPLAY (f
);
3158 Screen
*screen
= FRAME_X_SCREEN (f
);
3161 gamma_correct (f
, color
);
3162 rc
= XAllocColor (display
, cmap
, color
);
3165 /* If we got to this point, the colormap is full, so we're going
3166 to try to get the next closest color. The algorithm used is
3167 a least-squares matching, which is what X uses for closest
3168 color matching with StaticColor visuals. */
3170 unsigned long nearest_delta
= ~0;
3171 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3172 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3174 for (i
= 0; i
< ncells
; ++i
)
3176 XQueryColors (display
, cmap
, cells
, ncells
);
3178 for (nearest
= i
= 0; i
< ncells
; ++i
)
3180 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3181 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3182 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3183 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3185 if (delta
< nearest_delta
)
3188 nearest_delta
= delta
;
3192 color
->red
= cells
[nearest
].red
;
3193 color
->green
= cells
[nearest
].green
;
3194 color
->blue
= cells
[nearest
].blue
;
3195 rc
= XAllocColor (display
, cmap
, color
);
3198 #ifdef DEBUG_X_COLORS
3200 register_color (color
->pixel
);
3201 #endif /* DEBUG_X_COLORS */
3207 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3208 It's necessary to do this instead of just using PIXEL directly to
3209 get color reference counts right. */
3212 x_copy_color (f
, pixel
)
3214 unsigned long pixel
;
3218 color
.pixel
= pixel
;
3220 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3221 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3223 #ifdef DEBUG_X_COLORS
3224 register_color (pixel
);
3230 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3231 It's necessary to do this instead of just using PIXEL directly to
3232 get color reference counts right. */
3235 x_copy_dpy_color (dpy
, cmap
, pixel
)
3238 unsigned long pixel
;
3242 color
.pixel
= pixel
;
3244 XQueryColor (dpy
, cmap
, &color
);
3245 XAllocColor (dpy
, cmap
, &color
);
3247 #ifdef DEBUG_X_COLORS
3248 register_color (pixel
);
3253 #endif /* MAC_TODO */
3256 /* Brightness beyond which a color won't have its highlight brightness
3259 Nominally, highlight colors for `3d' faces are calculated by
3260 brightening an object's color by a constant scale factor, but this
3261 doesn't yield good results for dark colors, so for colors who's
3262 brightness is less than this value (on a scale of 0-255) have to
3263 use an additional additive factor.
3265 The value here is set so that the default menu-bar/mode-line color
3266 (grey75) will not have its highlights changed at all. */
3267 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3270 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3271 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3272 If this produces the same color as COLOR, try a color where all RGB
3273 values have DELTA added. Return the allocated color in *COLOR.
3274 DISPLAY is the X display, CMAP is the colormap to operate on.
3275 Value is non-zero if successful. */
3278 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3280 unsigned long *color
;
3287 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3290 /* Change RGB values by specified FACTOR. Avoid overflow! */
3291 xassert (factor
>= 0);
3292 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3293 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3294 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3296 /* Calculate brightness of COLOR. */
3297 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3298 + BLUE_FROM_ULONG (*color
)) / 6;
3300 /* We only boost colors that are darker than
3301 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3302 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3303 /* Make an additive adjustment to NEW, because it's dark enough so
3304 that scaling by FACTOR alone isn't enough. */
3306 /* How far below the limit this color is (0 - 1, 1 being darker). */
3307 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3308 /* The additive adjustment. */
3309 int min_delta
= delta
* dimness
* factor
/ 2;
3312 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3313 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3314 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3316 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3317 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3318 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3322 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3323 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3324 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3326 /* MAC_TODO: Map to palette and retry with delta if same? */
3327 /* MAC_TODO: Free colors (if using palette)? */
3338 /* Set up the foreground color for drawing relief lines of glyph
3339 string S. RELIEF is a pointer to a struct relief containing the GC
3340 with which lines will be drawn. Use a color that is FACTOR or
3341 DELTA lighter or darker than the relief's background which is found
3342 in S->f->output_data.x->relief_background. If such a color cannot
3343 be allocated, use DEFAULT_PIXEL, instead. */
3346 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3348 struct relief
*relief
;
3351 unsigned long default_pixel
;
3354 struct mac_output
*di
= f
->output_data
.mac
;
3355 unsigned long mask
= GCForeground
;
3356 unsigned long pixel
;
3357 unsigned long background
= di
->relief_background
;
3358 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3360 /* MAC_TODO: Free colors (if using palette)? */
3362 /* Allocate new color. */
3363 xgcv
.foreground
= default_pixel
;
3365 if (dpyinfo
->n_planes
!= 1
3366 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3368 relief
->allocated_p
= 1;
3369 xgcv
.foreground
= relief
->pixel
= pixel
;
3372 if (relief
->gc
== 0)
3374 #if 0 /* MAC_TODO: stipple */
3375 xgcv
.stipple
= dpyinfo
->gray
;
3378 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3381 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3385 /* Set up colors for the relief lines around glyph string S. */
3388 x_setup_relief_colors (s
)
3389 struct glyph_string
*s
;
3391 struct mac_output
*di
= s
->f
->output_data
.mac
;
3392 unsigned long color
;
3394 if (s
->face
->use_box_color_for_shadows_p
)
3395 color
= s
->face
->box_color
;
3396 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3398 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3399 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3404 /* Get the background color of the face. */
3405 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3406 color
= xgcv
.background
;
3409 if (di
->white_relief
.gc
== 0
3410 || color
!= di
->relief_background
)
3412 di
->relief_background
= color
;
3413 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3414 WHITE_PIX_DEFAULT (s
->f
));
3415 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3416 BLACK_PIX_DEFAULT (s
->f
));
3421 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3422 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3423 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3424 relief. LEFT_P non-zero means draw a relief on the left side of
3425 the rectangle. RIGHT_P non-zero means draw a relief on the right
3426 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3430 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3431 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3433 int left_x
, top_y
, right_x
, bottom_y
, width
;
3434 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3437 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3442 gc
= f
->output_data
.mac
->white_relief
.gc
;
3444 gc
= f
->output_data
.mac
->black_relief
.gc
;
3445 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3449 for (i
= 0; i
< width
; ++i
)
3450 mac_draw_line (f
, gc
,
3451 left_x
+ i
* left_p
, top_y
+ i
,
3452 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3456 for (i
= 0; i
< width
; ++i
)
3457 mac_draw_line (f
, gc
,
3458 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3460 mac_reset_clip_rectangles (dpy
, gc
);
3462 gc
= f
->output_data
.mac
->black_relief
.gc
;
3464 gc
= f
->output_data
.mac
->white_relief
.gc
;
3465 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3469 for (i
= 0; i
< width
; ++i
)
3470 mac_draw_line (f
, gc
,
3471 left_x
+ i
* left_p
, bottom_y
- i
,
3472 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3476 for (i
= 0; i
< width
; ++i
)
3477 mac_draw_line (f
, gc
,
3478 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3480 mac_reset_clip_rectangles (dpy
, gc
);
3484 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3485 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3486 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3487 left side of the rectangle. RIGHT_P non-zero means draw a line
3488 on the right side of the rectangle. CLIP_RECT is the clipping
3489 rectangle to use when drawing. */
3492 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3493 left_p
, right_p
, clip_rect
)
3494 struct glyph_string
*s
;
3495 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3500 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3501 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3502 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3505 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3506 right_x
- left_x
+ 1, width
);
3510 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3511 width
, bottom_y
- top_y
+ 1);
3514 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3515 right_x
- left_x
+ 1, width
);
3519 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3520 top_y
, width
, bottom_y
- top_y
+ 1);
3522 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3523 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3527 /* Draw a box around glyph string S. */
3530 x_draw_glyph_string_box (s
)
3531 struct glyph_string
*s
;
3533 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3534 int left_p
, right_p
;
3535 struct glyph
*last_glyph
;
3538 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3539 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3540 : window_box_right (s
->w
, s
->area
));
3542 /* The glyph that may have a right box line. */
3543 last_glyph
= (s
->cmp
|| s
->img
3545 : s
->first_glyph
+ s
->nchars
- 1);
3547 width
= eabs (s
->face
->box_line_width
);
3548 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3550 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3552 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3554 bottom_y
= top_y
+ s
->height
- 1;
3556 left_p
= (s
->first_glyph
->left_box_line_p
3557 || (s
->hl
== DRAW_MOUSE_FACE
3559 || s
->prev
->hl
!= s
->hl
)));
3560 right_p
= (last_glyph
->right_box_line_p
3561 || (s
->hl
== DRAW_MOUSE_FACE
3563 || s
->next
->hl
!= s
->hl
)));
3565 get_glyph_string_clip_rect (s
, &clip_rect
);
3567 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3568 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3569 left_p
, right_p
, &clip_rect
);
3572 x_setup_relief_colors (s
);
3573 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3574 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3579 /* Draw foreground of image glyph string S. */
3582 x_draw_image_foreground (s
)
3583 struct glyph_string
*s
;
3586 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3588 /* If first glyph of S has a left box line, start drawing it to the
3589 right of that line. */
3590 if (s
->face
->box
!= FACE_NO_BOX
3591 && s
->first_glyph
->left_box_line_p
3593 x
+= eabs (s
->face
->box_line_width
);
3595 /* If there is a margin around the image, adjust x- and y-position
3597 if (s
->slice
.x
== 0)
3598 x
+= s
->img
->hmargin
;
3599 if (s
->slice
.y
== 0)
3600 y
+= s
->img
->vmargin
;
3604 x_set_glyph_string_clipping (s
);
3607 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3608 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3609 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3613 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3614 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3615 s
->slice
.width
, s
->slice
.height
, x
, y
);
3622 mac_copy_area (s
->img
->pixmap
,
3623 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3624 s
->slice
.width
, s
->slice
.height
, x
, y
);
3627 /* When the image has a mask, we can expect that at
3628 least part of a mouse highlight or a block cursor will
3629 be visible. If the image doesn't have a mask, make
3630 a block cursor visible by drawing a rectangle around
3631 the image. I believe it's looking better if we do
3632 nothing here for mouse-face. */
3633 if (s
->hl
== DRAW_CURSOR
)
3635 int r
= s
->img
->relief
;
3637 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3638 s
->slice
.width
+ r
*2 - 1,
3639 s
->slice
.height
+ r
*2 - 1);
3644 /* Draw a rectangle if image could not be loaded. */
3645 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3646 s
->slice
.width
- 1, s
->slice
.height
- 1);
3650 /* Draw a relief around the image glyph string S. */
3653 x_draw_image_relief (s
)
3654 struct glyph_string
*s
;
3656 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3659 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3661 /* If first glyph of S has a left box line, start drawing it to the
3662 right of that line. */
3663 if (s
->face
->box
!= FACE_NO_BOX
3664 && s
->first_glyph
->left_box_line_p
3666 x
+= eabs (s
->face
->box_line_width
);
3668 /* If there is a margin around the image, adjust x- and y-position
3670 if (s
->slice
.x
== 0)
3671 x
+= s
->img
->hmargin
;
3672 if (s
->slice
.y
== 0)
3673 y
+= s
->img
->vmargin
;
3675 if (s
->hl
== DRAW_IMAGE_SUNKEN
3676 || s
->hl
== DRAW_IMAGE_RAISED
)
3678 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3679 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3683 thick
= eabs (s
->img
->relief
);
3684 raised_p
= s
->img
->relief
> 0;
3689 x1
= x
+ s
->slice
.width
+ thick
- 1;
3690 y1
= y
+ s
->slice
.height
+ thick
- 1;
3692 x_setup_relief_colors (s
);
3693 get_glyph_string_clip_rect (s
, &r
);
3694 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3696 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3698 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3703 /* Draw part of the background of glyph string S. X, Y, W, and H
3704 give the rectangle to draw. */
3707 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3708 struct glyph_string
*s
;
3711 #if 0 /* MAC_TODO: stipple */
3714 /* Fill background with a stipple pattern. */
3715 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3716 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3717 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3720 #endif /* MAC_TODO */
3721 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3725 /* Draw image glyph string S.
3728 s->x +-------------------------
3731 | +-------------------------
3734 | | +-------------------
3740 x_draw_image_glyph_string (s
)
3741 struct glyph_string
*s
;
3744 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
3745 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3748 height
= s
->height
- 2 * box_line_vwidth
;
3751 /* Fill background with face under the image. Do it only if row is
3752 taller than image or if image has a clip mask to reduce
3754 s
->stippled_p
= s
->face
->stipple
!= 0;
3755 if (height
> s
->slice
.height
3759 || s
->img
->pixmap
== 0
3760 || s
->width
!= s
->background_width
)
3763 if (s
->first_glyph
->left_box_line_p
3765 x
+= box_line_hwidth
;
3768 if (s
->slice
.y
== 0)
3769 y
+= box_line_vwidth
;
3771 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3773 s
->background_filled_p
= 1;
3776 /* Draw the foreground. */
3777 x_draw_image_foreground (s
);
3779 /* If we must draw a relief around the image, do it. */
3781 || s
->hl
== DRAW_IMAGE_RAISED
3782 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3783 x_draw_image_relief (s
);
3787 /* Draw stretch glyph string S. */
3790 x_draw_stretch_glyph_string (s
)
3791 struct glyph_string
*s
;
3793 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3795 if (s
->hl
== DRAW_CURSOR
3796 && !x_stretch_cursor_p
)
3798 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3799 as wide as the stretch glyph. */
3800 int width
, background_width
= s
->background_width
;
3801 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3805 background_width
-= left_x
- x
;
3808 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3811 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3813 /* Clear rest using the GC of the original non-cursor face. */
3814 if (width
< background_width
)
3817 int w
= background_width
- width
, h
= s
->height
;
3822 if (s
->row
->mouse_face_p
3823 && cursor_in_mouse_face_p (s
->w
))
3825 x_set_mouse_face_gc (s
);
3831 get_glyph_string_clip_rect (s
, &r
);
3832 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3834 #if 0 /* MAC_TODO: stipple */
3835 if (s
->face
->stipple
)
3837 /* Fill background with a stipple pattern. */
3838 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3839 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3840 XSetFillStyle (s
->display
, gc
, FillSolid
);
3843 #endif /* MAC_TODO */
3844 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3847 else if (!s
->background_filled_p
)
3849 int background_width
= s
->background_width
;
3850 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3852 /* Don't draw into left margin, fringe or scrollbar area
3853 except for header line and mode line. */
3854 if (x
< left_x
&& !s
->row
->mode_line_p
)
3856 background_width
-= left_x
- x
;
3859 if (background_width
> 0)
3860 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3863 s
->background_filled_p
= 1;
3867 /* Draw glyph string S. */
3870 x_draw_glyph_string (s
)
3871 struct glyph_string
*s
;
3873 int relief_drawn_p
= 0;
3875 /* If S draws into the background of its successor that does not
3876 draw a cursor, draw the background of the successor first so that
3877 S can draw into it. This makes S->next use XDrawString instead
3878 of XDrawImageString. */
3879 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3880 && s
->next
->hl
!= DRAW_CURSOR
)
3882 xassert (s
->next
->img
== NULL
);
3883 x_set_glyph_string_gc (s
->next
);
3884 x_set_glyph_string_clipping (s
->next
);
3885 x_draw_glyph_string_background (s
->next
, 1);
3888 /* Set up S->gc, set clipping and draw S. */
3889 x_set_glyph_string_gc (s
);
3891 /* Draw relief (if any) in advance for char/composition so that the
3892 glyph string can be drawn over it. */
3893 if (!s
->for_overlaps
3894 && s
->face
->box
!= FACE_NO_BOX
3895 && (s
->first_glyph
->type
== CHAR_GLYPH
3896 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3899 x_set_glyph_string_clipping (s
);
3900 x_draw_glyph_string_background (s
, 1);
3901 x_draw_glyph_string_box (s
);
3902 x_set_glyph_string_clipping (s
);
3906 x_set_glyph_string_clipping (s
);
3908 switch (s
->first_glyph
->type
)
3911 x_draw_image_glyph_string (s
);
3915 x_draw_stretch_glyph_string (s
);
3919 if (s
->for_overlaps
)
3920 s
->background_filled_p
= 1;
3922 x_draw_glyph_string_background (s
, 0);
3923 x_draw_glyph_string_foreground (s
);
3926 case COMPOSITE_GLYPH
:
3927 if (s
->for_overlaps
|| s
->gidx
> 0)
3928 s
->background_filled_p
= 1;
3930 x_draw_glyph_string_background (s
, 1);
3931 x_draw_composite_glyph_string_foreground (s
);
3938 if (!s
->for_overlaps
)
3940 /* Draw underline. */
3941 if (s
->face
->underline_p
)
3943 unsigned long tem
, h
;
3947 /* Get the underline thickness. Default is 1 pixel. */
3948 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3952 y
= s
->y
+ s
->height
- h
;
3953 if (!x_underline_at_descent_line
)
3955 /* Get the underline position. This is the recommended
3956 vertical offset in pixels from the baseline to the top of
3957 the underline. This is a signed value according to the
3958 specs, and its default is
3960 ROUND ((maximum descent) / 2), with
3961 ROUND(x) = floor (x + 0.5) */
3964 if (x_use_underline_position_properties
3965 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3966 y
= s
->ybase
+ (long) tem
;
3970 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3973 if (s
->face
->underline_defaulted_p
)
3974 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3975 s
->background_width
, h
);
3979 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3980 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3981 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3982 s
->background_width
, h
);
3983 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3987 /* Draw overline. */
3988 if (s
->face
->overline_p
)
3990 unsigned long dy
= 0, h
= 1;
3992 if (s
->face
->overline_color_defaulted_p
)
3993 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3994 s
->background_width
, h
);
3998 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3999 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4000 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4001 s
->background_width
, h
);
4002 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4006 /* Draw strike-through. */
4007 if (s
->face
->strike_through_p
)
4009 unsigned long h
= 1;
4010 unsigned long dy
= (s
->height
- h
) / 2;
4012 if (s
->face
->strike_through_color_defaulted_p
)
4013 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4018 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4019 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4020 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4022 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4026 /* Draw relief if not yet drawn. */
4027 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4028 x_draw_glyph_string_box (s
);
4031 /* Reset clipping. */
4032 mac_reset_clip_rectangles (s
->display
, s
->gc
);
4035 /* Shift display to make room for inserted glyphs. */
4038 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4040 int x
, y
, width
, height
, shift_by
;
4042 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4043 x
, y
, width
, height
,
4047 /* Delete N glyphs at the nominal cursor position. Not implemented
4058 /* Clear entire frame. If updating_frame is non-null, clear that
4059 frame. Otherwise clear the selected frame. */
4062 x_clear_frame (struct frame
*f
)
4064 /* Clearing the frame will erase any cursor, so mark them all as no
4066 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4067 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4068 output_cursor
.x
= -1;
4070 /* We don't set the output cursor here because there will always
4071 follow an explicit cursor_to. */
4073 mac_clear_window (f
);
4075 /* We have to clear the scroll bars, too. If we have changed
4076 colors or something like that, then they should be notified. */
4077 x_scroll_bar_clear (f
);
4079 XFlush (FRAME_MAC_DISPLAY (f
));
4085 /* Invert the middle quarter of the frame for .15 sec. */
4087 /* We use the select system call to do the waiting, so we have to make
4088 sure it's available. If it isn't, we just won't do visual bells. */
4090 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4093 /* Subtract the `struct timeval' values X and Y, storing the result in
4094 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4097 timeval_subtract (result
, x
, y
)
4098 struct timeval
*result
, x
, y
;
4100 /* Perform the carry for the later subtraction by updating y. This
4101 is safer because on some systems the tv_sec member is unsigned. */
4102 if (x
.tv_usec
< y
.tv_usec
)
4104 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4105 y
.tv_usec
-= 1000000 * nsec
;
4109 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4111 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4112 y
.tv_usec
+= 1000000 * nsec
;
4116 /* Compute the time remaining to wait. tv_usec is certainly
4118 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4119 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4121 /* Return indication of whether the result should be considered
4123 return x
.tv_sec
< y
.tv_sec
;
4130 /* Get the height not including a menu bar widget. */
4131 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4132 /* Height of each line to flash. */
4133 int flash_height
= FRAME_LINE_HEIGHT (f
);
4134 /* These will be the left and right margins of the rectangles. */
4135 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4136 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4140 /* Don't flash the area between a scroll bar and the frame
4141 edge it is next to. */
4142 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4144 case vertical_scroll_bar_left
:
4145 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4148 case vertical_scroll_bar_right
:
4149 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4156 width
= flash_right
- flash_left
;
4160 /* If window is tall, flash top and bottom line. */
4161 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4163 mac_invert_rectangle (f
, flash_left
,
4164 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4165 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4166 width
, flash_height
);
4167 mac_invert_rectangle (f
, flash_left
,
4168 (height
- flash_height
4169 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4170 width
, flash_height
);
4173 /* If it is short, flash it all. */
4174 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4175 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4180 struct timeval wakeup
;
4182 EMACS_GET_TIME (wakeup
);
4184 /* Compute time to wait until, propagating carry from usecs. */
4185 wakeup
.tv_usec
+= 150000;
4186 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4187 wakeup
.tv_usec
%= 1000000;
4189 /* Keep waiting until past the time wakeup or any input gets
4191 while (! detect_input_pending ())
4193 struct timeval current
;
4194 struct timeval timeout
;
4196 EMACS_GET_TIME (current
);
4198 /* Break if result would be negative. */
4199 if (timeval_subtract (¤t
, wakeup
, current
))
4202 /* How long `select' should wait. */
4204 timeout
.tv_usec
= 10000;
4206 /* Try to wait that long--but we might wake up sooner. */
4207 select (0, NULL
, NULL
, NULL
, &timeout
);
4211 /* If window is tall, flash top and bottom line. */
4212 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4214 mac_invert_rectangle (f
, flash_left
,
4215 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4216 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4217 width
, flash_height
);
4218 mac_invert_rectangle (f
, flash_left
,
4219 (height
- flash_height
4220 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4221 width
, flash_height
);
4224 /* If it is short, flash it all. */
4225 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4226 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4233 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4236 /* Make audible bell. */
4241 struct frame
*f
= SELECTED_FRAME ();
4243 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4251 XFlush (FRAME_MAC_DISPLAY (f
));
4257 /* Specify how many text lines, from the top of the window,
4258 should be affected by insert-lines and delete-lines operations.
4259 This, and those operations, are used only within an update
4260 that is bounded by calls to x_update_begin and x_update_end. */
4263 XTset_terminal_window (n
)
4266 /* This function intentionally left blank. */
4271 /***********************************************************************
4273 ***********************************************************************/
4275 /* Perform an insert-lines or delete-lines operation, inserting N
4276 lines or deleting -N lines at vertical position VPOS. */
4279 x_ins_del_lines (vpos
, n
)
4286 /* Scroll part of the display as described by RUN. */
4289 x_scroll_run (w
, run
)
4293 struct frame
*f
= XFRAME (w
->frame
);
4294 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4296 /* Get frame-relative bounding box of the text display area of W,
4297 without mode lines. Include in this box the left and right
4299 window_box (w
, -1, &x
, &y
, &width
, &height
);
4301 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4302 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4303 bottom_y
= y
+ height
;
4307 /* Scrolling up. Make sure we don't copy part of the mode
4308 line at the bottom. */
4309 if (from_y
+ run
->height
> bottom_y
)
4310 height
= bottom_y
- from_y
;
4312 height
= run
->height
;
4316 /* Scolling down. Make sure we don't copy over the mode line.
4318 if (to_y
+ run
->height
> bottom_y
)
4319 height
= bottom_y
- to_y
;
4321 height
= run
->height
;
4326 /* Cursor off. Will be switched on again in x_update_window_end. */
4330 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4340 /***********************************************************************
4342 ***********************************************************************/
4349 x_update_cursor (f
, 1);
4353 frame_unhighlight (f
)
4356 x_update_cursor (f
, 1);
4359 /* The focus has changed. Update the frames as necessary to reflect
4360 the new situation. Note that we can't change the selected frame
4361 here, because the Lisp code we are interrupting might become confused.
4362 Each event gets marked with the frame in which it occurred, so the
4363 Lisp code can tell when the switch took place by examining the events. */
4366 x_new_focus_frame (dpyinfo
, frame
)
4367 struct x_display_info
*dpyinfo
;
4368 struct frame
*frame
;
4370 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4372 if (frame
!= dpyinfo
->x_focus_frame
)
4374 /* Set this before calling other routines, so that they see
4375 the correct value of x_focus_frame. */
4376 dpyinfo
->x_focus_frame
= frame
;
4378 if (old_focus
&& old_focus
->auto_lower
)
4379 x_lower_frame (old_focus
);
4382 selected_frame
= frame
;
4383 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4385 Fselect_window (selected_frame
->selected_window
, Qnil
);
4386 choose_minibuf_frame ();
4389 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4390 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4392 pending_autoraise_frame
= 0;
4394 #if USE_MAC_FONT_PANEL
4396 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4400 x_frame_rehighlight (dpyinfo
);
4403 /* Handle FocusIn and FocusOut state changes for FRAME.
4404 If FRAME has focus and there exists more than one frame, puts
4405 a FOCUS_IN_EVENT into *BUFP. */
4408 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4410 struct mac_display_info
*dpyinfo
;
4411 struct frame
*frame
;
4412 struct input_event
*bufp
;
4414 if (type
== activeFlag
)
4416 if (dpyinfo
->x_focus_event_frame
!= frame
)
4418 x_new_focus_frame (dpyinfo
, frame
);
4419 dpyinfo
->x_focus_event_frame
= frame
;
4421 /* Don't stop displaying the initial startup message
4422 for a switch-frame event we don't need. */
4423 if (NILP (Vterminal_frame
)
4424 && CONSP (Vframe_list
)
4425 && !NILP (XCDR (Vframe_list
)))
4427 bufp
->kind
= FOCUS_IN_EVENT
;
4428 XSETFRAME (bufp
->frame_or_window
, frame
);
4434 if (dpyinfo
->x_focus_event_frame
== frame
)
4436 dpyinfo
->x_focus_event_frame
= 0;
4437 x_new_focus_frame (dpyinfo
, 0);
4442 /* The focus may have changed. Figure out if it is a real focus change,
4443 by checking both FocusIn/Out and Enter/LeaveNotify events.
4445 Returns FOCUS_IN_EVENT event in *BUFP. */
4448 x_detect_focus_change (dpyinfo
, event
, bufp
)
4449 struct mac_display_info
*dpyinfo
;
4450 const EventRecord
*event
;
4451 struct input_event
*bufp
;
4453 struct frame
*frame
;
4455 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4459 /* On Mac, this is only called from focus events, so no switch needed. */
4460 mac_focus_changed ((event
->modifiers
& activeFlag
),
4461 dpyinfo
, frame
, bufp
);
4465 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4468 x_mouse_leave (dpyinfo
)
4469 struct x_display_info
*dpyinfo
;
4471 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4474 /* The focus has changed, or we have redirected a frame's focus to
4475 another frame (this happens when a frame uses a surrogate
4476 mini-buffer frame). Shift the highlight as appropriate.
4478 The FRAME argument doesn't necessarily have anything to do with which
4479 frame is being highlighted or un-highlighted; we only use it to find
4480 the appropriate X display info. */
4483 XTframe_rehighlight (frame
)
4484 struct frame
*frame
;
4486 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4490 x_frame_rehighlight (dpyinfo
)
4491 struct x_display_info
*dpyinfo
;
4493 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4495 if (dpyinfo
->x_focus_frame
)
4497 dpyinfo
->x_highlight_frame
4498 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4499 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4500 : dpyinfo
->x_focus_frame
);
4501 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4503 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4504 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4508 dpyinfo
->x_highlight_frame
= 0;
4510 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4513 frame_unhighlight (old_highlight
);
4514 if (dpyinfo
->x_highlight_frame
)
4515 frame_highlight (dpyinfo
->x_highlight_frame
);
4521 /* Convert a keysym to its name. */
4524 x_get_keysym_name (keysym
)
4531 value
= XKeysymToString (keysym
);
4542 /* Function to report a mouse movement to the mainstream Emacs code.
4543 The input handler calls this.
4545 We have received a mouse movement event, which is given in *event.
4546 If the mouse is over a different glyph than it was last time, tell
4547 the mainstream emacs code by setting mouse_moved. If not, ask for
4548 another motion event, so we can check again the next time it moves. */
4550 static Point last_mouse_motion_position
;
4551 static Lisp_Object last_mouse_motion_frame
;
4554 note_mouse_movement (frame
, pos
)
4558 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4559 #if TARGET_API_MAC_CARBON
4563 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4564 last_mouse_motion_position
= *pos
;
4565 XSETFRAME (last_mouse_motion_frame
, frame
);
4567 if (frame
== dpyinfo
->mouse_face_mouse_frame
4568 #if TARGET_API_MAC_CARBON
4569 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4571 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4575 /* This case corresponds to LeaveNotify in X11. If we move
4576 outside the frame, then we're certainly no longer on any text
4578 clear_mouse_face (dpyinfo
);
4579 dpyinfo
->mouse_face_mouse_frame
= 0;
4580 if (!dpyinfo
->grabbed
)
4581 FRAME_RIF (frame
)->define_frame_cursor (frame
,
4582 frame
->output_data
.mac
->nontext_cursor
);
4585 /* Has the mouse moved off the glyph it was on at the last sighting? */
4586 if (frame
!= last_mouse_glyph_frame
4587 || !PtInRect (*pos
, &last_mouse_glyph
))
4589 frame
->mouse_moved
= 1;
4590 last_mouse_scroll_bar
= Qnil
;
4591 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4592 /* Remember which glyph we're now on. */
4593 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4594 last_mouse_glyph_frame
= frame
;
4602 /************************************************************************
4604 ************************************************************************/
4606 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4609 redo_mouse_highlight ()
4611 if (!NILP (last_mouse_motion_frame
)
4612 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4613 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4614 last_mouse_motion_position
.h
,
4615 last_mouse_motion_position
.v
);
4619 static struct frame
*
4620 mac_focus_frame (dpyinfo
)
4621 struct mac_display_info
*dpyinfo
;
4623 if (dpyinfo
->x_focus_frame
)
4624 return dpyinfo
->x_focus_frame
;
4626 /* Mac version may get events, such as a menu bar click, even when
4627 all the frames are invisible. In this case, we regard the
4628 event came to the selected frame. */
4629 return SELECTED_FRAME ();
4633 /* Return the current position of the mouse.
4634 *FP should be a frame which indicates which display to ask about.
4636 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4637 and *PART to the frame, window, and scroll bar part that the mouse
4638 is over. Set *X and *Y to the portion and whole of the mouse's
4639 position on the scroll bar.
4641 If the mouse movement started elsewhere, set *FP to the frame the
4642 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4645 Set *TIME to the server time-stamp for the time at which the mouse
4646 was at this position.
4648 Don't store anything if we don't have a valid set of values to report.
4650 This clears the mouse_moved flag, so we can wait for the next mouse
4654 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4657 Lisp_Object
*bar_window
;
4658 enum scroll_bar_part
*part
;
4660 unsigned long *time
;
4666 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4667 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4670 Lisp_Object frame
, tail
;
4672 /* Clear the mouse-moved flag for every frame on this display. */
4673 FOR_EACH_FRAME (tail
, frame
)
4674 XFRAME (frame
)->mouse_moved
= 0;
4676 last_mouse_scroll_bar
= Qnil
;
4678 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4679 && FRAME_LIVE_P (last_mouse_frame
))
4680 f1
= last_mouse_frame
;
4682 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4686 /* Ok, we found a frame. Store all the values.
4687 last_mouse_glyph is a rectangle used to reduce the
4688 generation of mouse events. To not miss any motion
4689 events, we must divide the frame into rectangles of the
4690 size of the smallest character that could be displayed
4691 on it, i.e. into the same rectangles that matrices on
4692 the frame are divided into. */
4695 #if TARGET_API_MAC_CARBON
4696 GetGlobalMouse (&mouse_pos
);
4697 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4698 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4700 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4701 GetMouse (&mouse_pos
);
4703 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4705 last_mouse_glyph_frame
= f1
;
4710 XSETINT (*x
, mouse_pos
.h
);
4711 XSETINT (*y
, mouse_pos
.v
);
4712 *time
= last_mouse_movement_time
;
4720 /************************************************************************
4722 ************************************************************************/
4724 #ifdef USE_TOOLKIT_SCROLL_BARS
4726 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4727 static OSStatus install_scroll_bar_timer
P_ ((void));
4728 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4729 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4730 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4731 struct input_event
*));
4732 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4734 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4735 ControlPartCode
, Point
,
4736 struct input_event
*));
4737 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4738 struct input_event
*));
4739 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4740 Point
, struct input_event
*));
4741 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4744 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4746 static int last_scroll_bar_part
;
4748 static EventLoopTimerRef scroll_bar_timer
;
4750 static int scroll_bar_timer_event_posted_p
;
4752 #define SCROLL_BAR_FIRST_DELAY 0.5
4753 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4756 scroll_bar_timer_callback (timer
, data
)
4757 EventLoopTimerRef timer
;
4762 err
= mac_post_mouse_moved_event ();
4764 scroll_bar_timer_event_posted_p
= 1;
4768 install_scroll_bar_timer ()
4770 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4772 if (scroll_bar_timer_callbackUPP
== NULL
)
4773 scroll_bar_timer_callbackUPP
=
4774 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4776 if (scroll_bar_timer
== NULL
)
4777 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4778 kEventDurationForever as delays. */
4780 InstallEventLoopTimer (GetCurrentEventLoop (),
4781 kEventDurationForever
, kEventDurationForever
,
4782 scroll_bar_timer_callbackUPP
, NULL
,
4787 set_scroll_bar_timer (delay
)
4788 EventTimerInterval delay
;
4790 if (scroll_bar_timer
== NULL
)
4791 install_scroll_bar_timer ();
4793 scroll_bar_timer_event_posted_p
= 0;
4795 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4799 control_part_code_to_scroll_bar_part (part_code
)
4800 ControlPartCode part_code
;
4804 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4805 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4806 case kControlPageUpPart
: return scroll_bar_above_handle
;
4807 case kControlPageDownPart
: return scroll_bar_below_handle
;
4808 case kControlIndicatorPart
: return scroll_bar_handle
;
4815 construct_scroll_bar_click (bar
, part
, bufp
)
4816 struct scroll_bar
*bar
;
4818 struct input_event
*bufp
;
4820 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4821 bufp
->frame_or_window
= bar
->window
;
4825 XSETINT (bufp
->x
, 0);
4826 XSETINT (bufp
->y
, 0);
4827 bufp
->modifiers
= 0;
4831 get_control_part_bounds (ch
, part_code
, rect
)
4833 ControlPartCode part_code
;
4836 RgnHandle region
= NewRgn ();
4839 err
= GetControlRegion (ch
, part_code
, region
);
4841 GetRegionBounds (region
, rect
);
4842 DisposeRgn (region
);
4848 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4849 struct scroll_bar
*bar
;
4850 ControlPartCode part_code
;
4852 struct input_event
*bufp
;
4854 int part
= control_part_code_to_scroll_bar_part (part_code
);
4859 if (part
!= scroll_bar_handle
)
4861 construct_scroll_bar_click (bar
, part
, bufp
);
4862 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4863 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4864 bar
->dragging
= Qnil
;
4870 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4871 kControlIndicatorPart
, &r
);
4872 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4875 last_scroll_bar_part
= part
;
4876 tracked_scroll_bar
= bar
;
4880 x_scroll_bar_handle_release (bar
, bufp
)
4881 struct scroll_bar
*bar
;
4882 struct input_event
*bufp
;
4884 if (last_scroll_bar_part
!= scroll_bar_handle
4885 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4886 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4888 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4889 set_scroll_bar_timer (kEventDurationForever
);
4891 last_scroll_bar_part
= -1;
4892 bar
->dragging
= Qnil
;
4893 tracked_scroll_bar
= NULL
;
4897 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4899 struct scroll_bar
*bar
;
4901 struct input_event
*bufp
;
4903 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4905 if (last_scroll_bar_part
== scroll_bar_handle
)
4910 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4911 kControlIndicatorPart
, &r
);
4913 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4914 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4916 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4917 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4921 if (top
> top_range
)
4924 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4925 XSETINT (bufp
->x
, top
);
4926 XSETINT (bufp
->y
, top_range
);
4930 ControlPartCode part_code
;
4931 int unhilite_p
= 0, part
;
4933 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4937 part
= control_part_code_to_scroll_bar_part (part_code
);
4939 switch (last_scroll_bar_part
)
4941 case scroll_bar_above_handle
:
4942 case scroll_bar_below_handle
:
4943 if (part
!= scroll_bar_above_handle
4944 && part
!= scroll_bar_below_handle
)
4948 case scroll_bar_up_arrow
:
4949 case scroll_bar_down_arrow
:
4950 if (part
!= scroll_bar_up_arrow
4951 && part
!= scroll_bar_down_arrow
)
4958 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4959 else if (part
!= last_scroll_bar_part
4960 || scroll_bar_timer_event_posted_p
)
4962 construct_scroll_bar_click (bar
, part
, bufp
);
4963 last_scroll_bar_part
= part
;
4964 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4965 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4970 /* Set the thumb size and position of scroll bar BAR. We are currently
4971 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4974 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4975 struct scroll_bar
*bar
;
4976 int portion
, position
, whole
;
4978 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4979 int value
, viewsize
, maximum
;
4981 if (XINT (bar
->track_height
) == 0)
4984 if (whole
<= portion
)
4985 value
= 0, viewsize
= 1, maximum
= 0;
4990 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4991 scale
= (float) maximum
/ (whole
- portion
);
4992 value
= position
* scale
+ 0.5f
;
4993 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
4998 if (GetControlViewSize (ch
) != viewsize
4999 || GetControl32BitValue (ch
) != value
5000 || GetControl32BitMaximum (ch
) != maximum
)
5002 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5003 SetControlVisibility (ch
, false, false);
5005 SetControl32BitMaximum (ch
, maximum
);
5006 SetControl32BitValue (ch
, value
);
5007 SetControlViewSize (ch
, viewsize
);
5009 SetControlVisibility (ch
, true, true);
5015 #endif /* USE_TOOLKIT_SCROLL_BARS */
5019 /************************************************************************
5020 Scroll bars, general
5021 ************************************************************************/
5023 /* Create a scroll bar and return the scroll bar vector for it. W is
5024 the Emacs window on which to create the scroll bar. TOP, LEFT,
5025 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5028 static struct scroll_bar
*
5029 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5031 int top
, left
, width
, height
, disp_top
, disp_height
;
5033 struct frame
*f
= XFRAME (w
->frame
);
5034 struct scroll_bar
*bar
5035 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5043 r
.right
= left
+ width
;
5044 r
.bottom
= disp_top
+ disp_height
;
5047 mac_prepare_for_quickdraw (f
);
5049 #if TARGET_API_MAC_CARBON
5050 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5051 #ifdef USE_TOOLKIT_SCROLL_BARS
5054 width
< disp_height
,
5056 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5058 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5059 0, 0, 0, scrollBarProc
, (long) bar
);
5061 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5063 XSETWINDOW (bar
->window
, w
);
5064 XSETINT (bar
->top
, top
);
5065 XSETINT (bar
->left
, left
);
5066 XSETINT (bar
->width
, width
);
5067 XSETINT (bar
->height
, height
);
5068 XSETINT (bar
->start
, 0);
5069 XSETINT (bar
->end
, 0);
5070 bar
->dragging
= Qnil
;
5072 bar
->fringe_extended_p
= Qnil
;
5074 #ifdef USE_TOOLKIT_SCROLL_BARS
5075 bar
->track_top
= Qnil
;
5076 bar
->track_height
= Qnil
;
5077 bar
->min_handle
= Qnil
;
5080 /* Add bar to its frame's list of scroll bars. */
5081 bar
->next
= FRAME_SCROLL_BARS (f
);
5083 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5084 if (!NILP (bar
->next
))
5085 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5092 /* Draw BAR's handle in the proper position.
5094 If the handle is already drawn from START to END, don't bother
5095 redrawing it, unless REBUILD is non-zero; in that case, always
5096 redraw it. (REBUILD is handy for drawing the handle after expose
5099 Normally, we want to constrain the start and end of the handle to
5100 fit inside its rectangle, but if the user is dragging the scroll
5101 bar handle, we want to let them drag it down all the way, so that
5102 the bar's top is as far down as it goes; otherwise, there's no way
5103 to move to the very end of the buffer. */
5105 #ifndef USE_TOOLKIT_SCROLL_BARS
5108 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5109 struct scroll_bar
*bar
;
5113 int dragging
= ! NILP (bar
->dragging
);
5114 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5115 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5116 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5117 int length
= end
- start
;
5119 /* If the display is already accurate, do nothing. */
5121 && start
== XINT (bar
->start
)
5122 && end
== XINT (bar
->end
))
5127 /* Make sure the values are reasonable, and try to preserve the
5128 distance between start and end. */
5131 else if (start
> top_range
)
5133 end
= start
+ length
;
5137 else if (end
> top_range
&& ! dragging
)
5140 /* Store the adjusted setting in the scroll bar. */
5141 XSETINT (bar
->start
, start
);
5142 XSETINT (bar
->end
, end
);
5144 /* Clip the end position, just for display. */
5145 if (end
> top_range
)
5148 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5149 top positions, to make sure the handle is always at least that
5150 many pixels tall. */
5151 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5153 SetControlMinimum (ch
, 0);
5154 /* Don't inadvertently activate deactivated scroll bars */
5155 if (GetControlMaximum (ch
) != -1)
5156 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5158 SetControlValue (ch
, start
);
5159 #if TARGET_API_MAC_CARBON
5160 SetControlViewSize (ch
, end
- start
);
5166 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5168 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5172 x_scroll_bar_remove (bar
)
5173 struct scroll_bar
*bar
;
5175 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5180 mac_prepare_for_quickdraw (f
);
5182 /* Destroy the Mac scroll bar control */
5183 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5185 /* Disassociate this scroll bar from its window. */
5186 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5192 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5193 that we are displaying PORTION characters out of a total of WHOLE
5194 characters, starting at POSITION. If WINDOW has no scroll bar,
5198 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5200 int portion
, whole
, position
;
5202 struct frame
*f
= XFRAME (w
->frame
);
5203 struct scroll_bar
*bar
;
5204 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5205 int window_y
, window_height
;
5207 int fringe_extended_p
;
5210 /* Get window dimensions. */
5211 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5213 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5214 height
= window_height
;
5216 /* Compute the left edge of the scroll bar area. */
5217 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5219 /* Compute the width of the scroll bar which might be less than
5220 the width of the area reserved for the scroll bar. */
5221 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5222 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5226 /* Compute the left edge of the scroll bar. */
5227 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5228 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5230 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5232 /* Adjustments according to Inside Macintosh to make it look nice */
5234 disp_height
= height
;
5241 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5247 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5252 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5253 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5254 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5255 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5256 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5258 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5259 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5260 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5261 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5264 /* Does the scroll bar exist yet? */
5265 if (NILP (w
->vertical_scroll_bar
))
5269 if (fringe_extended_p
)
5270 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5273 mac_clear_area (f
, left
, top
, width
, height
);
5275 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5277 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5281 /* It may just need to be moved and resized. */
5284 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5285 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5289 /* If already correctly positioned, do nothing. */
5290 if (!(XINT (bar
->left
) == sb_left
5291 && XINT (bar
->top
) == top
5292 && XINT (bar
->width
) == sb_width
5293 && XINT (bar
->height
) == height
5295 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5299 /* Since toolkit scroll bars are smaller than the space reserved
5300 for them on the frame, we have to clear "under" them. */
5302 if (fringe_extended_p
)
5303 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5306 mac_clear_area (f
, left
, top
, width
, height
);
5309 mac_prepare_for_quickdraw (f
);
5312 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5313 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5315 #ifndef USE_TOOLKIT_SCROLL_BARS
5316 if (sb_width
< disp_height
)
5320 /* Remember new settings. */
5321 XSETINT (bar
->left
, sb_left
);
5322 XSETINT (bar
->top
, top
);
5323 XSETINT (bar
->width
, sb_width
);
5324 XSETINT (bar
->height
, height
);
5325 #ifdef USE_TOOLKIT_SCROLL_BARS
5326 bar
->track_top
= Qnil
;
5327 bar
->track_height
= Qnil
;
5328 bar
->min_handle
= Qnil
;
5336 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5339 #ifdef USE_TOOLKIT_SCROLL_BARS
5340 if (NILP (bar
->track_top
))
5342 if (sb_width
>= disp_height
5344 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5348 XSETINT (bar
->track_top
, 0);
5349 XSETINT (bar
->track_height
, 0);
5350 XSETINT (bar
->min_handle
, 0);
5354 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5359 SetControl32BitMinimum (ch
, 0);
5360 SetControl32BitMaximum (ch
, 1 << 30);
5361 SetControlViewSize (ch
, 1);
5363 /* Move the scroll bar thumb to the top. */
5364 SetControl32BitValue (ch
, 0);
5365 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5367 /* Move the scroll bar thumb to the bottom. */
5368 SetControl32BitValue (ch
, 1 << 30);
5369 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5371 UnionRect (&r0
, &r1
, &r0
);
5372 XSETINT (bar
->track_top
, r0
.top
);
5373 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5374 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5376 /* Don't show the scroll bar if its height is not enough to
5377 display the scroll bar thumb. */
5378 if (r0
.bottom
- r0
.top
> 0)
5385 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5386 #else /* not USE_TOOLKIT_SCROLL_BARS */
5387 /* Set the scroll bar's current state, unless we're currently being
5389 if (NILP (bar
->dragging
))
5391 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5394 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5397 int start
= ((double) position
* top_range
) / whole
;
5398 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5399 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5402 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5406 /* The following three hooks are used when we're doing a thorough
5407 redisplay of the frame. We don't explicitly know which scroll bars
5408 are going to be deleted, because keeping track of when windows go
5409 away is a real pain - "Can you say set-window-configuration, boys
5410 and girls?" Instead, we just assert at the beginning of redisplay
5411 that *all* scroll bars are to be removed, and then save a scroll bar
5412 from the fiery pit when we actually redisplay its window. */
5414 /* Arrange for all scroll bars on FRAME to be removed at the next call
5415 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5416 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5419 XTcondemn_scroll_bars (frame
)
5422 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5423 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5426 bar
= FRAME_SCROLL_BARS (frame
);
5427 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5428 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5429 XSCROLL_BAR (bar
)->prev
= Qnil
;
5430 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5431 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5432 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5437 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5438 Note that WINDOW isn't necessarily condemned at all. */
5441 XTredeem_scroll_bar (window
)
5442 struct window
*window
;
5444 struct scroll_bar
*bar
;
5447 /* We can't redeem this window's scroll bar if it doesn't have one. */
5448 if (NILP (window
->vertical_scroll_bar
))
5451 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5453 /* Unlink it from the condemned list. */
5454 f
= XFRAME (WINDOW_FRAME (window
));
5455 if (NILP (bar
->prev
))
5457 /* If the prev pointer is nil, it must be the first in one of
5459 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5460 /* It's not condemned. Everything's fine. */
5462 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5463 window
->vertical_scroll_bar
))
5464 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5466 /* If its prev pointer is nil, it must be at the front of
5467 one or the other! */
5471 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5473 if (! NILP (bar
->next
))
5474 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5476 bar
->next
= FRAME_SCROLL_BARS (f
);
5478 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5479 if (! NILP (bar
->next
))
5480 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5483 /* Remove all scroll bars on FRAME that haven't been saved since the
5484 last call to `*condemn_scroll_bars_hook'. */
5487 XTjudge_scroll_bars (f
)
5490 Lisp_Object bar
, next
;
5492 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5494 /* Clear out the condemned list now so we won't try to process any
5495 more events on the hapless scroll bars. */
5496 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5498 for (; ! NILP (bar
); bar
= next
)
5500 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5502 x_scroll_bar_remove (b
);
5505 b
->next
= b
->prev
= Qnil
;
5508 /* Now there should be no references to the condemned scroll bars,
5509 and they should get garbage-collected. */
5513 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5514 is set to something other than NO_EVENT, it is enqueued.
5516 This may be called from a signal handler, so we have to ignore GC
5520 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5521 struct scroll_bar
*bar
;
5522 ControlPartCode part_code
;
5523 const EventRecord
*er
;
5524 struct input_event
*bufp
;
5526 int win_y
, top_range
;
5528 if (! WINDOWP (bar
->window
))
5531 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5532 bufp
->frame_or_window
= bar
->window
;
5535 bar
->dragging
= Qnil
;
5539 case kControlUpButtonPart
:
5540 bufp
->part
= scroll_bar_up_arrow
;
5542 case kControlDownButtonPart
:
5543 bufp
->part
= scroll_bar_down_arrow
;
5545 case kControlPageUpPart
:
5546 bufp
->part
= scroll_bar_above_handle
;
5548 case kControlPageDownPart
:
5549 bufp
->part
= scroll_bar_below_handle
;
5551 #if TARGET_API_MAC_CARBON
5554 case kControlIndicatorPart
:
5556 if (er
->what
== mouseDown
)
5557 bar
->dragging
= make_number (0);
5558 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5559 bufp
->part
= scroll_bar_handle
;
5563 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5564 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5566 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5570 if (! NILP (bar
->dragging
))
5571 win_y
-= XINT (bar
->dragging
);
5575 if (win_y
> top_range
)
5578 XSETINT (bufp
->x
, win_y
);
5579 XSETINT (bufp
->y
, top_range
);
5582 #ifndef USE_TOOLKIT_SCROLL_BARS
5584 /* Handle some mouse motion while someone is dragging the scroll bar.
5586 This may be called from a signal handler, so we have to ignore GC
5590 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5591 struct scroll_bar
*bar
;
5595 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5597 last_mouse_movement_time
= t
;
5600 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5602 /* If we're dragging the bar, display it. */
5603 if (! NILP (bar
->dragging
))
5605 /* Where should the handle be now? */
5606 int new_start
= y_pos
- 24;
5608 if (new_start
!= XINT (bar
->start
))
5610 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5612 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5617 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5619 /* Return information to the user about the current position of the mouse
5620 on the scroll bar. */
5623 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5625 Lisp_Object
*bar_window
;
5626 enum scroll_bar_part
*part
;
5628 unsigned long *time
;
5630 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5631 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5632 #if TARGET_API_MAC_CARBON
5633 WindowRef wp
= GetControlOwner (ch
);
5635 WindowRef wp
= (*ch
)->contrlOwner
;
5638 struct frame
*f
= mac_window_to_frame (wp
);
5639 int win_y
, top_range
;
5641 #if TARGET_API_MAC_CARBON
5642 GetGlobalMouse (&mouse_pos
);
5643 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5644 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5646 SetPortWindowPort (wp
);
5647 GetMouse (&mouse_pos
);
5650 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5651 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5653 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5657 if (! NILP (bar
->dragging
))
5658 win_y
-= XINT (bar
->dragging
);
5662 if (win_y
> top_range
)
5666 *bar_window
= bar
->window
;
5668 if (! NILP (bar
->dragging
))
5669 *part
= scroll_bar_handle
;
5670 else if (win_y
< XINT (bar
->start
))
5671 *part
= scroll_bar_above_handle
;
5672 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5673 *part
= scroll_bar_handle
;
5675 *part
= scroll_bar_below_handle
;
5677 XSETINT (*x
, win_y
);
5678 XSETINT (*y
, top_range
);
5681 last_mouse_scroll_bar
= Qnil
;
5683 *time
= last_mouse_movement_time
;
5687 /* The screen has been cleared so we may have changed foreground or
5688 background colors, and the scroll bars may need to be redrawn.
5689 Clear out the scroll bars, and ask for expose events, so we can
5693 x_scroll_bar_clear (f
)
5696 XTcondemn_scroll_bars (f
);
5697 XTjudge_scroll_bars (f
);
5701 /***********************************************************************
5703 ***********************************************************************/
5706 /* In identifiers such as function/variable names, Emacs tool bar is
5707 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5709 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5710 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5712 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5713 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5714 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5715 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5716 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5717 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5718 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5720 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5721 static void mac_handle_origin_change
P_ ((struct frame
*));
5722 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5726 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5733 mac_get_window_bounds (f
, &inner
, &outer
);
5735 switch (win_gravity
)
5737 case NorthWestGravity
:
5739 case SouthWestGravity
:
5740 left
+= inner
.left
- outer
.left
;
5746 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5749 case NorthEastGravity
:
5751 case SouthEastGravity
:
5752 left
+= inner
.right
- outer
.right
;
5756 switch (win_gravity
)
5758 case NorthWestGravity
:
5760 case NorthEastGravity
:
5761 top
+= inner
.top
- outer
.top
;
5767 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5770 case SouthWestGravity
:
5772 case SouthEastGravity
:
5773 top
+= inner
.bottom
- outer
.bottom
;
5777 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5781 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5788 mac_get_window_bounds (f
, &inner
, &outer
);
5790 switch (win_gravity
)
5792 case NorthWestGravity
:
5794 case SouthWestGravity
:
5801 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5802 - (inner
.right
- inner
.left
)) / 2;
5805 case NorthEastGravity
:
5807 case SouthEastGravity
:
5808 *left
= outer
.right
- (inner
.right
- inner
.left
);
5812 switch (win_gravity
)
5814 case NorthWestGravity
:
5816 case NorthEastGravity
:
5823 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5824 - (inner
.bottom
- inner
.top
)) / 2;
5827 case SouthWestGravity
:
5829 case SouthEastGravity
:
5830 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5836 mac_handle_toolbar_event (next_handler
, event
, data
)
5837 EventHandlerCallRef next_handler
;
5841 OSStatus err
, result
= eventNotHandledErr
;
5843 switch (GetEventKind (event
))
5845 case kEventToolbarGetDefaultIdentifiers
:
5849 case kEventToolbarGetAllowedIdentifiers
:
5851 CFMutableArrayRef array
;
5853 GetEventParameter (event
, kEventParamMutableArray
,
5854 typeCFMutableArrayRef
, NULL
,
5855 sizeof (CFMutableArrayRef
), NULL
, &array
);
5856 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5861 case kEventToolbarCreateItemWithIdentifier
:
5863 CFStringRef identifier
;
5864 HIToolbarItemRef item
= NULL
;
5866 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
5867 typeCFStringRef
, NULL
,
5868 sizeof (CFStringRef
), NULL
, &identifier
);
5870 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
5871 == kCFCompareEqualTo
)
5872 HIToolbarItemCreate (identifier
,
5873 kHIToolbarItemAllowDuplicates
5874 | kHIToolbarItemCantBeRemoved
, &item
);
5878 SetEventParameter (event
, kEventParamToolbarItem
,
5879 typeHIToolbarItemRef
,
5880 sizeof (HIToolbarItemRef
), &item
);
5894 mac_image_spec_to_cg_image (f
, image
)
5898 if (!valid_image_p (image
))
5902 int img_id
= lookup_image (f
, image
);
5903 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
5905 prepare_image_for_display (f
, img
);
5907 return img
->data
.ptr_val
;
5911 /* Create a tool bar for frame F. */
5914 mac_create_frame_tool_bar (f
)
5918 HIToolbarRef toolbar
;
5920 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
5924 static const EventTypeSpec specs
[] =
5925 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
5926 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
5927 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
5929 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
5930 mac_handle_toolbar_event
,
5931 GetEventTypeCount (specs
), specs
,
5936 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
5939 static const EventTypeSpec specs
[] =
5940 {{kEventClassCommand
, kEventCommandProcess
}};
5942 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
5943 mac_handle_toolbar_command_event
,
5944 GetEventTypeCount (specs
),
5948 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
5951 CFRelease (toolbar
);
5956 /* Update the tool bar for frame F. Add new buttons and remove old. */
5959 update_frame_tool_bar (f
)
5962 HIToolbarRef toolbar
= NULL
;
5964 CFArrayRef old_items
= NULL
;
5966 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
5967 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5971 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5972 if (toolbar
== NULL
)
5974 mac_create_frame_tool_bar (f
);
5975 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5976 if (toolbar
== NULL
)
5978 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
5979 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
5982 HIToolbarCopyItems (toolbar
, &old_items
);
5983 if (old_items
== NULL
)
5986 old_count
= CFArrayGetCount (old_items
);
5988 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
5990 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5992 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
5993 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
5996 CGImageRef cg_image
;
5998 HIToolbarItemRef item
;
6000 /* If image is a vector, choose the image according to the
6002 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6003 if (VECTORP (image
))
6007 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6008 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6011 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6012 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6014 xassert (ASIZE (image
) >= idx
);
6015 image
= AREF (image
, idx
);
6020 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6021 /* Ignore invalid image specifications. */
6022 if (cg_image
== NULL
)
6025 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6029 if (pos
< old_count
)
6031 CGImageRef old_cg_image
= NULL
;
6032 CFStringRef old_label
= NULL
;
6033 Boolean old_enabled_p
;
6035 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6037 HIToolbarItemCopyImage (item
, &old_cg_image
);
6038 if (cg_image
!= old_cg_image
)
6039 HIToolbarItemSetImage (item
, cg_image
);
6040 CGImageRelease (old_cg_image
);
6042 HIToolbarItemCopyLabel (item
, &old_label
);
6043 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6044 HIToolbarItemSetLabel (item
, label
);
6045 CFRelease (old_label
);
6047 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6048 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6049 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6054 HIToolbarCreateItemWithIdentifier (toolbar
,
6055 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6059 HIToolbarItemSetImage (item
, cg_image
);
6060 HIToolbarItemSetLabel (item
, label
);
6061 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6062 HIToolbarAppendItem (toolbar
, item
);
6070 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6075 CFRelease (old_items
);
6077 while (pos
< old_count
)
6078 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6080 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6081 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6082 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6083 toolbar visibility change. */
6084 mac_handle_origin_change (f
);
6085 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6087 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6088 /* If the title bar is completely outside the screen, adjust the
6090 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6091 kWindowConstrainMoveRegardlessOfFit
6092 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6093 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6100 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6101 doesn't deallocate the resources. */
6104 free_frame_tool_bar (f
)
6107 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6109 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6112 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6113 (NILP (Fsymbol_value
6114 (intern ("frame-notice-user-settings")))
6115 && f
== mac_focus_frame (dpyinfo
)));
6116 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6117 on toolbar visibility change. */
6118 mac_handle_origin_change (f
);
6124 mac_tool_bar_note_mouse_movement (f
, event
)
6129 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6131 HIViewRef item_view
;
6134 mouse_down_p
= (dpyinfo
->grabbed
6135 && f
== last_mouse_frame
6136 && FRAME_LIVE_P (f
));
6140 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6142 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6143 toolbar item view seems to have the same command ID with that of
6144 the toolbar item. */
6146 err
= GetControlCommandID (item_view
, &command_id
);
6147 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6149 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6151 if (i
< f
->n_tool_bar_items
)
6154 HIViewRef content_view
;
6156 err
= HIViewGetBounds (item_view
, &bounds
);
6158 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6159 kHIViewWindowContentID
, &content_view
);
6161 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6163 SetRect (&last_mouse_glyph
,
6164 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6165 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6167 help_echo_object
= help_echo_window
= Qnil
;
6169 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6170 if (NILP (help_echo_string
))
6171 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6177 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6178 EventHandlerCallRef next_handler
;
6182 OSStatus err
, result
= eventNotHandledErr
;
6183 struct frame
*f
= (struct frame
*) data
;
6186 err
= GetEventParameter (event
, kEventParamDirectObject
,
6187 typeHICommand
, NULL
,
6188 sizeof (HICommand
), NULL
, &command
);
6192 switch (GetEventKind (event
))
6194 case kEventCommandProcess
:
6195 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6196 result
= CallNextEventHandler (next_handler
, event
);
6199 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6201 if (i
< f
->n_tool_bar_items
6202 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6205 struct input_event buf
;
6209 XSETFRAME (frame
, f
);
6210 buf
.kind
= TOOL_BAR_EVENT
;
6211 buf
.frame_or_window
= frame
;
6213 kbd_buffer_store_event (&buf
);
6215 buf
.kind
= TOOL_BAR_EVENT
;
6216 buf
.frame_or_window
= frame
;
6217 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6218 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6219 kbd_buffer_store_event (&buf
);
6233 #endif /* USE_MAC_TOOLBAR */
6236 /***********************************************************************
6238 ***********************************************************************/
6240 /* Set clipping for output in glyph row ROW. W is the window in which
6241 we operate. GC is the graphics context to set clipping in.
6243 ROW may be a text row or, e.g., a mode line. Text rows must be
6244 clipped to the interior of the window dedicated to text display,
6245 mode lines must be clipped to the whole window. */
6248 x_clip_to_row (w
, row
, area
, gc
)
6250 struct glyph_row
*row
;
6254 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6256 int window_x
, window_y
, window_width
;
6258 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6260 clip_rect
.left
= window_x
;
6261 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6262 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6263 clip_rect
.right
= clip_rect
.left
+ window_width
;
6264 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6266 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6270 /* Draw a hollow box cursor on window W in glyph row ROW. */
6273 x_draw_hollow_cursor (w
, row
)
6275 struct glyph_row
*row
;
6277 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6278 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6279 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6282 struct glyph
*cursor_glyph
;
6285 /* Get the glyph the cursor is on. If we can't tell because
6286 the current matrix is invalid or such, give up. */
6287 cursor_glyph
= get_phys_cursor_glyph (w
);
6288 if (cursor_glyph
== NULL
)
6291 /* Compute frame-relative coordinates for phys cursor. */
6292 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6293 wd
= w
->phys_cursor_width
;
6295 /* The foreground of cursor_gc is typically the same as the normal
6296 background color, which can cause the cursor box to be invisible. */
6297 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6298 if (dpyinfo
->scratch_cursor_gc
)
6299 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6301 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6302 GCForeground
, &xgcv
);
6303 gc
= dpyinfo
->scratch_cursor_gc
;
6305 /* Set clipping, draw the rectangle, and reset clipping again. */
6306 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6307 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6308 mac_reset_clip_rectangles (dpy
, gc
);
6312 /* Draw a bar cursor on window W in glyph row ROW.
6314 Implementation note: One would like to draw a bar cursor with an
6315 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6316 Unfortunately, I didn't find a font yet that has this property set.
6320 x_draw_bar_cursor (w
, row
, width
, kind
)
6322 struct glyph_row
*row
;
6324 enum text_cursor_kinds kind
;
6326 struct frame
*f
= XFRAME (w
->frame
);
6327 struct glyph
*cursor_glyph
;
6329 /* If cursor is out of bounds, don't draw garbage. This can happen
6330 in mini-buffer windows when switching between echo area glyphs
6332 cursor_glyph
= get_phys_cursor_glyph (w
);
6333 if (cursor_glyph
== NULL
)
6336 /* If on an image, draw like a normal cursor. That's usually better
6337 visible than drawing a bar, esp. if the image is large so that
6338 the bar might not be in the window. */
6339 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6341 struct glyph_row
*row
;
6342 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6343 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6347 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6348 Window window
= FRAME_MAC_WINDOW (f
);
6349 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6350 unsigned long mask
= GCForeground
| GCBackground
;
6351 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6354 /* If the glyph's background equals the color we normally draw
6355 the bar cursor in, the bar cursor in its normal color is
6356 invisible. Use the glyph's foreground color instead in this
6357 case, on the assumption that the glyph's colors are chosen so
6358 that the glyph is legible. */
6359 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6360 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6362 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6365 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6368 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6369 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6373 width
= FRAME_CURSOR_WIDTH (f
);
6374 width
= min (cursor_glyph
->pixel_width
, width
);
6376 w
->phys_cursor_width
= width
;
6377 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6379 if (kind
== BAR_CURSOR
)
6380 mac_fill_rectangle (f
, gc
,
6381 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6382 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6383 width
, row
->height
);
6385 mac_fill_rectangle (f
, gc
,
6386 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6387 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6388 row
->height
- width
),
6389 cursor_glyph
->pixel_width
,
6392 mac_reset_clip_rectangles (dpy
, gc
);
6397 /* RIF: Define cursor CURSOR on frame F. */
6400 mac_define_frame_cursor (f
, cursor
)
6404 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6406 if (dpyinfo
->x_focus_frame
== f
)
6407 SetThemeCursor (cursor
);
6411 /* RIF: Clear area on frame F. */
6414 mac_clear_frame_area (f
, x
, y
, width
, height
)
6416 int x
, y
, width
, height
;
6418 mac_clear_area (f
, x
, y
, width
, height
);
6422 /* RIF: Draw cursor on window W. */
6425 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6427 struct glyph_row
*glyph_row
;
6429 int cursor_type
, cursor_width
;
6434 w
->phys_cursor_type
= cursor_type
;
6435 w
->phys_cursor_on_p
= 1;
6437 if (glyph_row
->exact_window_width_line_p
6438 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6440 glyph_row
->cursor_in_fringe_p
= 1;
6441 draw_fringe_bitmap (w
, glyph_row
, 0);
6444 switch (cursor_type
)
6446 case HOLLOW_BOX_CURSOR
:
6447 x_draw_hollow_cursor (w
, glyph_row
);
6450 case FILLED_BOX_CURSOR
:
6451 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6455 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6459 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6463 w
->phys_cursor_width
= 0;
6475 #if 0 /* MAC_TODO: no icon support yet. */
6477 x_bitmap_icon (f
, icon
)
6483 if (FRAME_W32_WINDOW (f
) == 0)
6487 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6488 else if (STRINGP (icon
))
6489 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6490 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6491 else if (SYMBOLP (icon
))
6495 if (EQ (icon
, intern ("application")))
6496 name
= (LPCTSTR
) IDI_APPLICATION
;
6497 else if (EQ (icon
, intern ("hand")))
6498 name
= (LPCTSTR
) IDI_HAND
;
6499 else if (EQ (icon
, intern ("question")))
6500 name
= (LPCTSTR
) IDI_QUESTION
;
6501 else if (EQ (icon
, intern ("exclamation")))
6502 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6503 else if (EQ (icon
, intern ("asterisk")))
6504 name
= (LPCTSTR
) IDI_ASTERISK
;
6505 else if (EQ (icon
, intern ("winlogo")))
6506 name
= (LPCTSTR
) IDI_WINLOGO
;
6510 hicon
= LoadIcon (NULL
, name
);
6518 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6523 #endif /* MAC_TODO */
6525 /************************************************************************
6527 ************************************************************************/
6529 /* Display Error Handling functions not used on W32. Listing them here
6530 helps diff stay in step when comparing w32term.c with xterm.c.
6532 x_error_catcher (display, error)
6533 x_catch_errors (dpy)
6534 x_catch_errors_unwind (old_val)
6535 x_check_errors (dpy, format)
6536 x_had_errors_p (dpy)
6537 x_clear_errors (dpy)
6538 x_uncatch_errors (dpy, count)
6540 x_connection_signal (signalnum)
6541 x_connection_closed (dpy, error_message)
6542 x_error_quitter (display, error)
6543 x_error_handler (display, error)
6544 x_io_error_quitter (display)
6549 /* Changing the font of the frame. */
6551 /* Give frame F the font named FONTNAME as its default font, and
6552 return the full name of that font. FONTNAME may be a wildcard
6553 pattern; in that case, we choose some font that fits the pattern.
6554 The return value shows which font we chose. */
6557 x_new_font (f
, fontname
)
6559 register char *fontname
;
6561 struct font_info
*fontp
6562 = FS_LOAD_FONT (f
, fontname
);
6567 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
6568 /* This font is already set in frame F. There's nothing more to
6570 return build_string (fontp
->full_name
);
6572 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6573 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6574 FRAME_FONTSET (f
) = -1;
6576 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6577 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6578 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6580 compute_fringe_widths (f
, 1);
6582 /* Compute the scroll bar width in character columns. */
6583 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6585 int wid
= FRAME_COLUMN_WIDTH (f
);
6586 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6587 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6591 int wid
= FRAME_COLUMN_WIDTH (f
);
6592 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6595 /* Now make the frame display the given font. */
6596 if (FRAME_MAC_WINDOW (f
) != 0)
6598 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6600 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6602 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6605 /* Don't change the size of a tip frame; there's no point in
6606 doing it because it's done in Fx_show_tip, and it leads to
6607 problems because the tip frame has no widget. */
6608 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6609 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6612 return build_string (fontp
->full_name
);
6615 /* Give frame F the fontset named FONTSETNAME as its default fontset,
6616 and return the full name of that fontset. FONTSETNAME may be a
6617 wildcard pattern; in that case, we choose some fontset that fits
6618 the pattern. FONTSETNAME may be a font name for ASCII characters;
6619 in that case, we create a fontset from that font name.
6621 The return value shows which fontset we chose.
6622 If FONTSETNAME specifies the default fontset, return Qt.
6623 If an ASCII font in the specified fontset can't be loaded, return
6627 x_new_fontset (f
, fontsetname
)
6629 Lisp_Object fontsetname
;
6631 int fontset
= fs_query_fontset (fontsetname
, 0);
6634 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
6635 /* This fontset is already set in frame F. There's nothing more
6637 return fontset_name (fontset
);
6638 else if (fontset
== 0)
6639 /* The default fontset can't be the default font. */
6643 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6645 result
= x_new_font (f
, SDATA (fontsetname
));
6647 if (!STRINGP (result
))
6648 /* Can't load ASCII font. */
6652 fontset
= new_fontset_from_font_name (result
);
6654 /* Since x_new_font doesn't update any fontset information, do it now. */
6655 FRAME_FONTSET (f
) = fontset
;
6657 return fontset_name (fontset
);
6661 /***********************************************************************
6662 TODO: W32 Input Methods
6663 ***********************************************************************/
6664 /* Listing missing functions from xterm.c helps diff stay in step.
6666 xim_destroy_callback (xim, client_data, call_data)
6667 xim_open_dpy (dpyinfo, resource_name)
6669 xim_instantiate_callback (display, client_data, call_data)
6670 xim_initialize (dpyinfo, resource_name)
6671 xim_close_dpy (dpyinfo)
6677 mac_get_window_bounds (f
, inner
, outer
)
6679 Rect
*inner
, *outer
;
6681 #if TARGET_API_MAC_CARBON
6682 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6683 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6684 #else /* not TARGET_API_MAC_CARBON */
6685 RgnHandle region
= NewRgn ();
6687 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6688 *inner
= (*region
)->rgnBBox
;
6689 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6690 *outer
= (*region
)->rgnBBox
;
6691 DisposeRgn (region
);
6692 #endif /* not TARGET_API_MAC_CARBON */
6696 mac_handle_origin_change (f
)
6699 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6703 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6705 int pixelwidth
, pixelheight
;
6709 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6710 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6712 if (cols
!= FRAME_COLS (f
)
6713 || rows
!= FRAME_LINES (f
)
6714 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6715 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6717 /* We pass 1 for DELAY since we can't run Lisp code inside of
6719 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6720 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6721 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6722 SET_FRAME_GARBAGED (f
);
6724 /* If cursor was outside the new size, mark it as off. */
6725 mark_window_cursors_off (XWINDOW (f
->root_window
));
6727 /* Clear out any recollection of where the mouse highlighting
6728 was, since it might be in a place that's outside the new
6729 frame size. Actually checking whether it is outside is a
6730 pain in the neck, so don't try--just let the highlighting be
6731 done afresh with new size. */
6732 cancel_mouse_face (f
);
6734 #if TARGET_API_MAC_CARBON
6735 if (f
->output_data
.mac
->hourglass_control
)
6738 mac_prepare_for_quickdraw (f
);
6740 MoveControl (f
->output_data
.mac
->hourglass_control
,
6741 pixelwidth
- HOURGLASS_WIDTH
, 0);
6748 /* Calculate the absolute position in frame F
6749 from its current recorded position values and gravity. */
6752 x_calc_absolute_position (f
)
6755 int width_diff
= 0, height_diff
= 0;
6756 int flags
= f
->size_hint_flags
;
6759 /* We have nothing to do if the current position
6760 is already for the top-left corner. */
6761 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6764 /* Find the offsets of the outside upper-left corner of
6765 the inner window, with respect to the outer window. */
6767 mac_get_window_bounds (f
, &inner
, &outer
);
6770 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6771 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6773 /* Treat negative positions as relative to the leftmost bottommost
6774 position that fits on the screen. */
6775 if (flags
& XNegative
)
6776 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6778 - FRAME_PIXEL_WIDTH (f
)
6781 if (flags
& YNegative
)
6782 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6784 - FRAME_PIXEL_HEIGHT (f
)
6787 /* The left_pos and top_pos
6788 are now relative to the top and left screen edges,
6789 so the flags should correspond. */
6790 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6793 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6794 to really change the position, and 0 when calling from
6795 x_make_frame_visible (in that case, XOFF and YOFF are the current
6796 position values). It is -1 when calling from x_set_frame_parameters,
6797 which means, do adjust for borders but don't change the gravity. */
6800 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6802 register int xoff
, yoff
;
6805 if (change_gravity
> 0)
6809 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6811 f
->size_hint_flags
|= XNegative
;
6813 f
->size_hint_flags
|= YNegative
;
6814 f
->win_gravity
= NorthWestGravity
;
6816 x_calc_absolute_position (f
);
6819 x_wm_set_size_hint (f
, (long) 0, 0);
6821 #if TARGET_API_MAC_CARBON
6822 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6823 /* If the title bar is completely outside the screen, adjust the
6825 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6826 kWindowConstrainMoveRegardlessOfFit
6827 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6828 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6829 mac_handle_origin_change (f
);
6832 Rect inner
, outer
, screen_rect
, dummy
;
6833 RgnHandle region
= NewRgn ();
6835 mac_get_window_bounds (f
, &inner
, &outer
);
6836 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6837 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6838 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6839 f
->top_pos
+ f
->y_pixels_diff
, false);
6841 /* If the title bar is completely outside the screen, adjust the
6842 position. The variable `outer' holds the title bar rectangle.
6843 The variable `inner' holds slightly smaller one than `outer',
6844 so that the calculation of overlapping may not become too
6846 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6847 outer
= (*region
)->rgnBBox
;
6848 DisposeRgn (region
);
6850 InsetRect (&inner
, 8, 8);
6851 screen_rect
= qd
.screenBits
.bounds
;
6852 screen_rect
.top
+= GetMBarHeight ();
6854 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6856 if (inner
.right
<= screen_rect
.left
)
6857 f
->left_pos
= screen_rect
.left
;
6858 else if (inner
.left
>= screen_rect
.right
)
6859 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6861 if (inner
.bottom
<= screen_rect
.top
)
6862 f
->top_pos
= screen_rect
.top
;
6863 else if (inner
.top
>= screen_rect
.bottom
)
6864 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6866 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6867 f
->top_pos
+ f
->y_pixels_diff
, false);
6875 /* Call this to change the size of frame F's x-window.
6876 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6877 for this size change and subsequent size changes.
6878 Otherwise we leave the window gravity unchanged. */
6881 x_set_window_size (f
, change_gravity
, cols
, rows
)
6886 int pixelwidth
, pixelheight
;
6890 check_frame_size (f
, &rows
, &cols
);
6891 f
->scroll_bar_actual_width
6892 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6894 compute_fringe_widths (f
, 0);
6896 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6897 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6899 f
->win_gravity
= NorthWestGravity
;
6900 x_wm_set_size_hint (f
, (long) 0, 0);
6902 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6904 #if TARGET_API_MAC_CARBON
6905 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6907 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6909 if (f
->output_data
.mac
->internal_border_width
6910 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6912 mac_clear_window (f
);
6913 f
->output_data
.mac
->internal_border_width
6914 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6917 SET_FRAME_GARBAGED (f
);
6922 /* Mouse warping. */
6924 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6927 x_set_mouse_position (f
, x
, y
)
6933 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6934 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6936 if (pix_x
< 0) pix_x
= 0;
6937 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6939 if (pix_y
< 0) pix_y
= 0;
6940 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6942 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6946 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6951 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
6952 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
6955 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
6958 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6961 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6962 0, 0, 0, 0, pix_x
, pix_y
);
6968 /* focus shifting, raising and lowering. */
6971 x_focus_on_frame (f
)
6974 #if 0 /* This proves to be unpleasant. */
6978 /* I don't think that the ICCCM allows programs to do things like this
6979 without the interaction of the window manager. Whatever you end up
6980 doing with this code, do it to x_unfocus_frame too. */
6981 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6982 RevertToPointerRoot
, CurrentTime
);
6992 /* Raise frame F. */
6998 if (f
->async_visible
)
7001 BringToFront (FRAME_MAC_WINDOW (f
));
7006 /* Lower frame F. */
7012 if (f
->async_visible
)
7015 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7021 XTframe_raise_lower (f
, raise_flag
)
7031 /* Change of visibility. */
7034 mac_handle_visibility_change (f
)
7037 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7038 int visible
= 0, iconified
= 0;
7039 struct input_event buf
;
7041 if (IsWindowVisible (wp
))
7043 if (IsWindowCollapsed (wp
))
7049 if (!f
->async_visible
&& visible
)
7053 /* wait_reading_process_output will notice this and update
7054 the frame's display structures. If we were made
7055 invisible, we should not set garbaged, because that stops
7056 redrawing on Update events. */
7057 SET_FRAME_GARBAGED (f
);
7060 buf
.kind
= DEICONIFY_EVENT
;
7061 XSETFRAME (buf
.frame_or_window
, f
);
7063 kbd_buffer_store_event (&buf
);
7065 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7066 /* Force a redisplay sooner or later to update the
7067 frame titles in case this is the second frame. */
7068 record_asynch_buffer_change ();
7070 else if (f
->async_visible
&& !visible
)
7074 buf
.kind
= ICONIFY_EVENT
;
7075 XSETFRAME (buf
.frame_or_window
, f
);
7077 kbd_buffer_store_event (&buf
);
7080 f
->async_visible
= visible
;
7081 f
->async_iconified
= iconified
;
7084 /* This tries to wait until the frame is really visible.
7085 However, if the window manager asks the user where to position
7086 the frame, this will return before the user finishes doing that.
7087 The frame will not actually be visible at that time,
7088 but it will become visible later when the window manager
7089 finishes with it. */
7092 x_make_frame_visible (f
)
7097 if (! FRAME_VISIBLE_P (f
))
7099 /* We test FRAME_GARBAGED_P here to make sure we don't
7100 call x_set_offset a second time
7101 if we get to x_make_frame_visible a second time
7102 before the window gets really visible. */
7103 if (! FRAME_ICONIFIED_P (f
)
7104 && ! f
->output_data
.mac
->asked_for_visible
)
7105 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7107 f
->output_data
.mac
->asked_for_visible
= 1;
7109 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7110 ShowWindow (FRAME_MAC_WINDOW (f
));
7113 XFlush (FRAME_MAC_DISPLAY (f
));
7115 /* Synchronize to ensure Emacs knows the frame is visible
7116 before we do anything else. We do this loop with input not blocked
7117 so that incoming events are handled. */
7122 /* This must come after we set COUNT. */
7125 XSETFRAME (frame
, f
);
7127 /* Wait until the frame is visible. Process X events until a
7128 MapNotify event has been seen, or until we think we won't get a
7129 MapNotify at all.. */
7130 for (count
= input_signal_count
+ 10;
7131 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7133 /* Force processing of queued events. */
7136 /* Machines that do polling rather than SIGIO have been
7137 observed to go into a busy-wait here. So we'll fake an
7138 alarm signal to let the handler know that there's something
7139 to be read. We used to raise a real alarm, but it seems
7140 that the handler isn't always enabled here. This is
7142 if (input_polling_used ())
7144 /* It could be confusing if a real alarm arrives while
7145 processing the fake one. Turn it off and let the
7146 handler reset it. */
7147 extern void poll_for_input_1
P_ ((void));
7148 int old_poll_suppress_count
= poll_suppress_count
;
7149 poll_suppress_count
= 1;
7150 poll_for_input_1 ();
7151 poll_suppress_count
= old_poll_suppress_count
;
7154 /* See if a MapNotify event has been processed. */
7155 FRAME_SAMPLE_VISIBILITY (f
);
7160 /* Change from mapped state to withdrawn state. */
7162 /* Make the frame visible (mapped and not iconified). */
7165 x_make_frame_invisible (f
)
7168 /* A deactivate event does not occur when the last visible frame is
7169 made invisible. So if we clear the highlight here, it will not
7170 be rehighlighted when it is made visible. */
7172 /* Don't keep the highlight on an invisible frame. */
7173 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7174 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7179 #if !TARGET_API_MAC_CARBON
7180 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7181 that the current position of the window is user-specified, rather than
7182 program-specified, so that when the window is mapped again, it will be
7183 placed at the same location, without forcing the user to position it
7184 by hand again (they have already done that once for this window.) */
7185 x_wm_set_size_hint (f
, (long) 0, 1);
7188 HideWindow (FRAME_MAC_WINDOW (f
));
7192 #if !TARGET_API_MAC_CARBON
7193 mac_handle_visibility_change (f
);
7197 /* Change window state from mapped to iconified. */
7205 /* A deactivate event does not occur when the last visible frame is
7206 iconified. So if we clear the highlight here, it will not be
7207 rehighlighted when it is deiconified. */
7209 /* Don't keep the highlight on an invisible frame. */
7210 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7211 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7214 if (f
->async_iconified
)
7219 FRAME_SAMPLE_VISIBILITY (f
);
7221 if (! FRAME_VISIBLE_P (f
))
7222 ShowWindow (FRAME_MAC_WINDOW (f
));
7224 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7229 error ("Can't notify window manager of iconification");
7231 #if !TARGET_API_MAC_CARBON
7232 mac_handle_visibility_change (f
);
7237 /* Free X resources of frame F. */
7240 x_free_frame_resources (f
)
7243 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7244 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7248 if (wp
!= tip_window
)
7249 remove_window_handler (wp
);
7252 mac_prepare_for_quickdraw (f
);
7255 if (wp
== tip_window
)
7256 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7257 closed' event. So we reset tip_window here. */
7260 free_frame_menubar (f
);
7262 if (FRAME_FACE_CACHE (f
))
7263 free_frame_faces (f
);
7267 if (FRAME_SIZE_HINTS (f
))
7268 xfree (FRAME_SIZE_HINTS (f
));
7270 xfree (f
->output_data
.mac
);
7271 f
->output_data
.mac
= NULL
;
7273 if (f
== dpyinfo
->x_focus_frame
)
7275 dpyinfo
->x_focus_frame
= 0;
7276 #if USE_MAC_FONT_PANEL
7277 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7280 if (f
== dpyinfo
->x_focus_event_frame
)
7281 dpyinfo
->x_focus_event_frame
= 0;
7282 if (f
== dpyinfo
->x_highlight_frame
)
7283 dpyinfo
->x_highlight_frame
= 0;
7285 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7287 dpyinfo
->mouse_face_beg_row
7288 = dpyinfo
->mouse_face_beg_col
= -1;
7289 dpyinfo
->mouse_face_end_row
7290 = dpyinfo
->mouse_face_end_col
= -1;
7291 dpyinfo
->mouse_face_window
= Qnil
;
7292 dpyinfo
->mouse_face_deferred_gc
= 0;
7293 dpyinfo
->mouse_face_mouse_frame
= 0;
7300 /* Destroy the X window of frame F. */
7303 x_destroy_window (f
)
7306 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7308 x_free_frame_resources (f
);
7310 dpyinfo
->reference_count
--;
7314 /* Setting window manager hints. */
7316 /* Set the normal size hints for the window manager, for frame F.
7317 FLAGS is the flags word to use--or 0 meaning preserve the flags
7318 that the window now has.
7319 If USER_POSITION is nonzero, we set the USPosition
7320 flag (this is useful when FLAGS is 0). */
7322 x_wm_set_size_hint (f
, flags
, user_position
)
7327 int base_width
, base_height
, width_inc
, height_inc
;
7328 int min_rows
= 0, min_cols
= 0;
7329 XSizeHints
*size_hints
;
7331 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7332 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7333 width_inc
= FRAME_COLUMN_WIDTH (f
);
7334 height_inc
= FRAME_LINE_HEIGHT (f
);
7336 check_frame_size (f
, &min_rows
, &min_cols
);
7338 size_hints
= FRAME_SIZE_HINTS (f
);
7339 if (size_hints
== NULL
)
7341 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7342 bzero (size_hints
, sizeof (XSizeHints
));
7345 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7346 size_hints
->width_inc
= width_inc
;
7347 size_hints
->height_inc
= height_inc
;
7348 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7349 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7350 size_hints
->base_width
= base_width
;
7351 size_hints
->base_height
= base_height
;
7354 size_hints
->flags
= flags
;
7355 else if (user_position
)
7357 size_hints
->flags
&= ~ PPosition
;
7358 size_hints
->flags
|= USPosition
;
7362 #if 0 /* MAC_TODO: hide application instead of iconify? */
7363 /* Used for IconicState or NormalState */
7366 x_wm_set_window_state (f
, state
)
7370 #ifdef USE_X_TOOLKIT
7373 XtSetArg (al
[0], XtNinitialState
, state
);
7374 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7375 #else /* not USE_X_TOOLKIT */
7376 Window window
= FRAME_X_WINDOW (f
);
7378 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7379 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7381 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7382 #endif /* not USE_X_TOOLKIT */
7386 x_wm_set_icon_pixmap (f
, pixmap_id
)
7392 #ifndef USE_X_TOOLKIT
7393 Window window
= FRAME_X_WINDOW (f
);
7398 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7399 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7403 /* It seems there is no way to turn off use of an icon pixmap.
7404 The following line does it, only if no icon has yet been created,
7405 for some window managers. But with mwm it crashes.
7406 Some people say it should clear the IconPixmapHint bit in this case,
7407 but that doesn't work, and the X consortium said it isn't the
7408 right thing at all. Since there is no way to win,
7409 best to explicitly give up. */
7411 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7417 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7421 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7422 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7425 #else /* not USE_X_TOOLKIT */
7427 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7428 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7430 #endif /* not USE_X_TOOLKIT */
7433 #endif /* MAC_TODO */
7436 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7440 #if 0 /* MAC_TODO: no icons on Mac */
7441 #ifdef USE_X_TOOLKIT
7442 Window window
= XtWindow (f
->output_data
.x
->widget
);
7444 Window window
= FRAME_X_WINDOW (f
);
7447 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7448 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7449 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7451 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7452 #endif /* MAC_TODO */
7456 /***********************************************************************
7458 ***********************************************************************/
7460 /* An XLFD pattern is divided into blocks delimited by '*'. This
7461 structure holds information for each block. */
7462 struct xlfdpat_block
7464 /* Length of the pattern string in this block. Non-zero except for
7465 the first and the last blocks. */
7468 /* Pattern string except the last character in this block. The last
7469 character is replaced with NUL in order to use it as a
7471 unsigned char *pattern
;
7473 /* Last character of the pattern string. Must not be '?'. */
7474 unsigned char last_char
;
7476 /* One of the tables for the Boyer-Moore string search. It
7477 specifies the number of positions to proceed for each character
7478 with which the match fails. */
7481 /* The skip value for the last character in the above `skip' is
7482 assigned to `infinity' in order to simplify a loop condition.
7483 The original value is saved here. */
7489 /* Normalized pattern string. "Normalized" means that capital
7490 letters are lowered, blocks are not empty except the first and
7491 the last ones, and trailing '?'s in a block that is not the last
7492 one are moved to the next one. The last character in each block
7493 is replaced with NUL. */
7496 /* Number of characters except '*'s and trailing '?'s in the
7497 normalized pattern string. */
7500 /* Number of trailing '?'s in the normalized pattern string. */
7501 int trailing_anychars
;
7503 /* Number of blocks and information for each block. The latter is
7504 NULL if the pattern is exact (no '*' or '?' in it). */
7506 struct xlfdpat_block
*blocks
;
7510 xlfdpat_destroy (pat
)
7511 struct xlfdpat
*pat
;
7518 xfree (pat
->blocks
);
7525 static struct xlfdpat
*
7526 xlfdpat_create (pattern
)
7527 const char *pattern
;
7529 struct xlfdpat
*pat
;
7530 int nblocks
, i
, skip
;
7531 unsigned char last_char
, *p
, *q
, *anychar_head
;
7532 const unsigned char *ptr
;
7533 struct xlfdpat_block
*blk
;
7535 pat
= xmalloc (sizeof (struct xlfdpat
));
7536 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7538 /* Normalize the pattern string and store it to `pat->buf'. */
7540 anychar_head
= NULL
;
7543 for (ptr
= pattern
; *ptr
; ptr
++)
7545 unsigned char c
= *ptr
;
7548 if (last_char
== '*')
7549 /* ...a** -> ...a* */
7553 if (last_char
== '?')
7555 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7556 /* ...*??* -> ...*?? */
7559 /* ...a??* -> ...a*?? */
7561 *anychar_head
++ = '*';
7569 if (last_char
!= '?')
7573 /* On Mac OS X 10.3, tolower also converts non-ASCII
7574 characters for some locales. */
7578 *q
++ = last_char
= c
;
7582 pat
->nblocks
= nblocks
;
7583 if (last_char
!= '?')
7584 pat
->trailing_anychars
= 0;
7587 pat
->trailing_anychars
= q
- anychar_head
;
7590 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7592 if (anychar_head
== NULL
&& nblocks
== 1)
7594 /* The pattern is exact. */
7599 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7601 /* Divide the normalized pattern into blocks. */
7603 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7608 blk
->len
= p
- blk
->pattern
;
7612 blk
->len
= q
- blk
->pattern
;
7614 /* Setup a table for the Boyer-Moore string search. */
7615 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7618 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7619 blk
->pattern
[blk
->len
- 1] = '\0';
7621 for (skip
= 1; skip
< blk
->len
; skip
++)
7622 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7625 for (i
= 0; i
< 256; i
++)
7626 blk
->skip
[i
] = skip
;
7628 p
= blk
->pattern
+ (blk
->len
- skip
);
7630 blk
->skip
[*p
++] = skip
;
7632 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7639 xlfdpat_exact_p (pat
)
7640 struct xlfdpat
*pat
;
7642 return pat
->blocks
== NULL
;
7645 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7646 that the pattern in *BLK matches with its prefix. Return NULL
7647 there is no such strings. STRING must be lowered in advance. */
7650 xlfdpat_block_match_1 (blk
, string
, start_max
)
7651 struct xlfdpat_block
*blk
;
7652 const unsigned char *string
;
7655 int start
, infinity
;
7657 const unsigned char *s
;
7659 xassert (blk
->len
> 0);
7660 xassert (start_max
+ blk
->len
<= strlen (string
));
7661 xassert (blk
->last_char
!= '?');
7663 /* See the comments in the function `boyer_moore' (search.c) for the
7664 use of `infinity'. */
7665 infinity
= start_max
+ blk
->len
+ 1;
7666 blk
->skip
[blk
->last_char
] = infinity
;
7671 /* Check the last character of the pattern. */
7672 s
= string
+ blk
->len
- 1;
7675 start
+= blk
->skip
[*(s
+ start
)];
7677 while (start
<= start_max
);
7679 if (start
< infinity
)
7680 /* Couldn't find the last character. */
7683 /* No less than `infinity' means we could find the last
7684 character at `s[start - infinity]'. */
7687 /* Check the remaining characters. We prefer making no-'?'
7688 cases faster because the use of '?' is really rare. */
7693 while (*p
++ == *s
++)
7696 while (*(p
- 1) == '?');
7698 if (*(p
- 1) == '\0')
7700 return string
+ start
;
7703 start
+= blk
->last_char_skip
;
7705 while (start
<= start_max
);
7710 #define xlfdpat_block_match(b, s, m) \
7711 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7712 : xlfdpat_block_match_1 (b, s, m))
7714 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7715 matches with STRING. STRING must be lowered in advance. */
7718 xlfdpat_match (pat
, string
)
7719 struct xlfdpat
*pat
;
7720 const unsigned char *string
;
7722 int str_len
, nblocks
, i
, start_max
;
7723 struct xlfdpat_block
*blk
;
7724 const unsigned char *s
;
7726 xassert (pat
->nblocks
> 0);
7728 if (xlfdpat_exact_p (pat
))
7729 return strcmp (pat
->buf
, string
) == 0;
7731 /* The number of the characters in the string must not be smaller
7732 than that in the pattern. */
7733 str_len
= strlen (string
);
7734 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7737 /* Chop off the trailing '?'s. */
7738 str_len
-= pat
->trailing_anychars
;
7740 /* The last block. When it is non-empty, it must match at the end
7742 nblocks
= pat
->nblocks
;
7743 blk
= pat
->blocks
+ (nblocks
- 1);
7745 /* The last block is also the first one. */
7746 return (str_len
== blk
->len
7747 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7748 else if (blk
->len
!= 0)
7749 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7752 /* The first block. When it is non-empty, it must match at the
7753 beginning of the string. */
7757 s
= xlfdpat_block_match (blk
, string
, 0);
7760 string
= s
+ blk
->len
;
7763 /* The rest of the blocks. */
7764 start_max
= str_len
- pat
->nchars
;
7765 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7767 s
= xlfdpat_block_match (blk
, string
, start_max
);
7770 start_max
-= s
- string
;
7771 string
= s
+ blk
->len
;
7778 /***********************************************************************
7780 ***********************************************************************/
7782 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7785 x_get_font_info (f
, font_idx
)
7789 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7792 /* the global font name table */
7793 static char **font_name_table
= NULL
;
7794 static int font_name_table_size
= 0;
7795 static int font_name_count
= 0;
7797 /* Alist linking font family names to Font Manager font family
7798 references (which can also be used as QuickDraw font IDs). We use
7799 an alist because hash tables are not ready when the terminal frame
7800 for Mac OS Classic is created. */
7801 static Lisp_Object fm_font_family_alist
;
7803 /* Hash table linking font family names to ATSU font IDs. */
7804 static Lisp_Object atsu_font_id_hash
;
7805 /* Alist linking Font Manager style to face attributes. */
7806 static Lisp_Object fm_style_face_attributes_alist
;
7807 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7810 /* Alist linking character set strings to Mac text encoding and Emacs
7812 static Lisp_Object Vmac_charset_info_alist
;
7815 create_text_encoding_info_alist ()
7817 Lisp_Object result
= Qnil
, rest
;
7819 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7821 Lisp_Object charset_info
= XCAR (rest
);
7822 Lisp_Object charset
, coding_system
, text_encoding
;
7823 Lisp_Object existing_info
;
7825 if (!(CONSP (charset_info
)
7826 && (charset
= XCAR (charset_info
),
7828 && CONSP (XCDR (charset_info
))
7829 && (text_encoding
= XCAR (XCDR (charset_info
)),
7830 INTEGERP (text_encoding
))
7831 && CONSP (XCDR (XCDR (charset_info
)))
7832 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7833 SYMBOLP (coding_system
))))
7836 existing_info
= assq_no_quit (text_encoding
, result
);
7837 if (NILP (existing_info
))
7838 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7841 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7842 XSETCDR (XCDR (existing_info
),
7843 Fcons (charset
, XCDR (XCDR (existing_info
))));
7851 decode_mac_font_name (name
, size
, coding_system
)
7854 Lisp_Object coding_system
;
7856 struct coding_system coding
;
7859 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7861 for (p
= name
; *p
; p
++)
7862 if (!isascii (*p
) || iscntrl (*p
))
7867 setup_coding_system (coding_system
, &coding
);
7868 coding
.src_multibyte
= 0;
7869 coding
.dst_multibyte
= 1;
7870 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7871 coding
.dst_bytes
= size
;
7872 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
7874 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
7875 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
7876 name
[min (coding
.produced
, size
)] = '\0';
7880 /* If there's just one occurrence of '-' in the family name, it is
7881 replaced with '_'. (More than one occurrence of '-' means a
7882 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7883 p
= strchr (name
, '-');
7884 if (p
&& strchr (p
+ 1, '-') == NULL
)
7887 for (p
= name
; *p
; p
++)
7888 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7889 for some locales. */
7896 mac_to_x_fontname (name
, size
, style
, charset
)
7904 char xf
[256], *result
;
7907 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7911 strcpy(foundry
, "Apple");
7912 strcpy(family
, name
);
7915 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7916 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7917 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7919 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7920 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7921 for (p
= result
; *p
; p
++)
7922 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7923 for some locales. */
7930 /* Parse fully-specified and instantiated X11 font spec XF, and store
7931 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7932 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7933 caller must allocate at least 256 and 32 bytes respectively. For
7934 ordinary Mac fonts, the value stored to FAMILY should just be their
7935 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7936 intlfonts collection contain their charset designation in their
7937 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7938 types of font names are handled accordingly. */
7940 const int kDefaultFontSize
= 12;
7943 parse_x_font_name (xf
, family
, size
, style
, charset
)
7950 Str31 foundry
, weight
;
7951 int point_size
, avgwidth
;
7954 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7955 foundry
, family
, weight
, slant
, size
,
7956 &point_size
, &avgwidth
, charset
) != 8
7957 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7958 foundry
, family
, weight
, slant
, size
,
7959 &point_size
, &avgwidth
, charset
) != 8)
7965 *size
= point_size
/ 10;
7966 else if (avgwidth
> 0)
7967 *size
= avgwidth
/ 10;
7970 *size
= kDefaultFontSize
;
7973 if (strcmp (weight
, "bold") == 0)
7978 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7980 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7982 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7984 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7985 but take overlap into account. */
7986 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7987 memcpy (family
, foundry
, foundry_len
);
7988 family
[foundry_len
] = '-';
7989 family
[foundry_len
+ 1 + family_len
] = '-';
7990 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7996 for (p
= family
; *p
; p
++)
7997 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7998 for some locales. */
8007 add_font_name_table_entry (char *font_name
)
8009 if (font_name_table_size
== 0)
8011 font_name_table_size
= 256;
8012 font_name_table
= (char **)
8013 xmalloc (font_name_table_size
* sizeof (char *));
8015 else if (font_name_count
+ 1 >= font_name_table_size
)
8017 font_name_table_size
*= 2;
8018 font_name_table
= (char **)
8019 xrealloc (font_name_table
,
8020 font_name_table_size
* sizeof (char *));
8023 font_name_table
[font_name_count
++] = font_name
;
8027 add_mac_font_name (name
, size
, style
, charset
)
8031 const char *charset
;
8034 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8037 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8038 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8039 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8040 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8047 fm_get_style_from_font (font
)
8051 FMFontStyle style
= normal
;
8054 FMFontFamily font_family
;
8055 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8057 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8058 some font (e.g., Optima) even if it is `bold'. */
8059 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8060 sizeof (mac_style
), &mac_style
, &len
);
8062 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8063 style
= EndianU16_BtoN (mac_style
);
8065 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8071 atsu_find_font_from_family_name (family
)
8074 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8077 Lisp_Object rest
, best
;
8078 FMFontStyle min_style
, style
;
8080 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8083 return kATSUInvalidFontID
;
8085 rest
= HASH_VALUE (h
, i
);
8086 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8087 return cons_to_long (rest
);
8089 rest
= Fnreverse (rest
);
8093 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8096 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8097 if (style
< min_style
)
8100 if (style
== normal
)
8107 while (!NILP (rest
));
8109 HASH_VALUE (h
, i
) = best
;
8110 return cons_to_long (best
);
8114 fm_style_to_face_attributes (fm_style
)
8115 FMFontStyle fm_style
;
8119 fm_style
&= (bold
| italic
);
8120 tem
= assq_no_quit (make_number (fm_style
),
8121 fm_style_face_attributes_alist
);
8125 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8126 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8127 fm_style_face_attributes_alist
=
8128 Fcons (Fcons (make_number (fm_style
), tem
),
8129 fm_style_face_attributes_alist
);
8135 atsu_find_font_family_name (font_id
)
8140 Lisp_Object family
= Qnil
;
8142 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8143 kFontMacintoshPlatform
, kFontNoScript
,
8144 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8147 family
= make_uninit_string (len
);
8148 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8149 kFontMacintoshPlatform
, kFontNoScript
,
8150 kFontNoLanguage
, len
, SDATA (family
),
8154 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8160 mac_atsu_font_face_attributes (font_id
)
8163 Lisp_Object family
, style_attrs
;
8165 family
= atsu_find_font_family_name (font_id
);
8168 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8169 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8173 /* Sets up the table font_name_table to contain the list of all fonts
8174 in the system the first time the table is used so that the Resource
8175 Manager need not be accessed every time this information is
8179 init_font_name_table ()
8181 #if TARGET_API_MAC_CARBON
8182 FMFontFamilyIterator ffi
;
8183 FMFontFamilyInstanceIterator ffii
;
8185 Lisp_Object text_encoding_info_alist
;
8186 struct gcpro gcpro1
;
8188 text_encoding_info_alist
= create_text_encoding_info_alist ();
8191 #if USE_CG_TEXT_DRAWING
8192 init_cg_text_anti_aliasing_threshold ();
8194 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8195 text_encoding_info_alist
)))
8198 struct Lisp_Hash_Table
*h
;
8200 ItemCount nfonts
, i
;
8201 ATSUFontID
*font_ids
= NULL
;
8202 Lisp_Object prev_family
= Qnil
;
8206 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8207 make_float (DEFAULT_REHASH_SIZE
),
8208 make_float (DEFAULT_REHASH_THRESHOLD
),
8210 h
= XHASH_TABLE (atsu_font_id_hash
);
8212 err
= ATSUFontCount (&nfonts
);
8215 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8216 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8219 for (i
= 0; i
< nfonts
; i
++)
8223 family
= atsu_find_font_family_name (font_ids
[i
]);
8224 if (NILP (family
) || SREF (family
, 0) == '.')
8226 if (!NILP (Fequal (prev_family
, family
)))
8227 family
= prev_family
;
8229 j
= hash_lookup (h
, family
, &hash_code
);
8232 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8233 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8236 else if (EQ (prev_family
, family
))
8237 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8239 prev_family
= family
;
8246 /* Create a dummy instance iterator here to avoid creating and
8247 destroying it in the loop. */
8248 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8250 /* Create an iterator to enumerate the font families. */
8251 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8254 FMDisposeFontFamilyInstanceIterator (&ffii
);
8258 GCPRO1 (text_encoding_info_alist
);
8260 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8266 TextEncoding encoding
;
8267 TextEncodingBase sc
;
8268 Lisp_Object text_encoding_info
, family
;
8270 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8276 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8278 sc
= GetTextEncodingBase (encoding
);
8279 text_encoding_info
= assq_no_quit (make_number (sc
),
8280 text_encoding_info_alist
);
8281 if (NILP (text_encoding_info
))
8282 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8283 text_encoding_info_alist
);
8284 decode_mac_font_name (name
, sizeof (name
),
8285 XCAR (XCDR (text_encoding_info
)));
8286 family
= build_string (name
);
8287 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8289 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8290 fm_font_family_alist
);
8292 /* Point the instance iterator at the current font family. */
8293 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8296 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8299 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8301 if (size
> 0 || style
== normal
)
8302 for (; CONSP (rest
); rest
= XCDR (rest
))
8303 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8309 /* Dispose of the iterators. */
8310 FMDisposeFontFamilyIterator (&ffi
);
8311 FMDisposeFontFamilyInstanceIterator (&ffii
);
8312 #else /* !TARGET_API_MAC_CARBON */
8314 SInt16 fontnum
, old_fontnum
;
8315 int num_mac_fonts
= CountResources('FOND');
8317 Handle font_handle
, font_handle_2
;
8318 short id
, scriptcode
;
8321 struct FontAssoc
*fat
;
8322 struct AsscEntry
*assc_entry
;
8323 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8324 struct gcpro gcpro1
;
8326 GetPort (&port
); /* save the current font number used */
8327 old_fontnum
= port
->txFont
;
8329 text_encoding_info_alist
= create_text_encoding_info_alist ();
8331 GCPRO1 (text_encoding_info_alist
);
8333 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8335 font_handle
= GetIndResource ('FOND', i
);
8339 GetResInfo (font_handle
, &id
, &type
, name
);
8340 GetFNum (name
, &fontnum
);
8342 if (fontnum
== 0 || *name
== '.')
8346 scriptcode
= FontToScript (fontnum
);
8347 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8348 text_encoding_info_alist
);
8349 if (NILP (text_encoding_info
))
8350 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8351 text_encoding_info_alist
);
8352 decode_mac_font_name (name
, sizeof (name
),
8353 XCAR (XCDR (text_encoding_info
)));
8354 family
= build_string (name
);
8355 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8357 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8358 fm_font_family_alist
);
8361 HLock (font_handle
);
8363 if (GetResourceSizeOnDisk (font_handle
)
8364 >= sizeof (struct FamRec
))
8366 fat
= (struct FontAssoc
*) (*font_handle
8367 + sizeof (struct FamRec
));
8369 = (struct AsscEntry
*) (*font_handle
8370 + sizeof (struct FamRec
)
8371 + sizeof (struct FontAssoc
));
8373 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8375 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8377 for (; CONSP (rest
); rest
= XCDR (rest
))
8378 add_mac_font_name (name
, assc_entry
->fontSize
,
8379 assc_entry
->fontStyle
,
8380 SDATA (XCAR (rest
)));
8384 HUnlock (font_handle
);
8385 font_handle_2
= GetNextFOND (font_handle
);
8386 ReleaseResource (font_handle
);
8387 font_handle
= font_handle_2
;
8389 while (ResError () == noErr
&& font_handle
);
8394 TextFont (old_fontnum
);
8395 #endif /* !TARGET_API_MAC_CARBON */
8400 mac_clear_font_name_table ()
8404 for (i
= 0; i
< font_name_count
; i
++)
8405 xfree (font_name_table
[i
]);
8406 xfree (font_name_table
);
8407 font_name_table
= NULL
;
8408 font_name_table_size
= font_name_count
= 0;
8409 fm_font_family_alist
= Qnil
;
8413 enum xlfd_scalable_field_index
8415 XLFD_SCL_PIXEL_SIZE
,
8416 XLFD_SCL_POINT_SIZE
,
8421 static const int xlfd_scalable_fields
[] =
8430 mac_do_list_fonts (pattern
, maxnames
)
8431 const char *pattern
;
8435 Lisp_Object font_list
= Qnil
;
8436 struct xlfdpat
*pat
;
8439 int scl_val
[XLFD_SCL_LAST
], *val
;
8443 if (font_name_table
== NULL
) /* Initialize when first used. */
8444 init_font_name_table ();
8446 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8449 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8450 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8451 fonts are scaled according to the specified size. */
8454 field
= xlfd_scalable_fields
;
8462 if ('0' <= *ptr
&& *ptr
<= '9')
8464 *val
= *ptr
++ - '0';
8465 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8466 *val
= *val
* 10 + *ptr
++ - '0';
8473 ptr
= strchr (ptr
, '-');
8476 while (ptr
&& i
< 14);
8478 if (i
== 14 && ptr
== NULL
)
8480 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8481 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8482 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8483 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8485 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8486 scl_val
[XLFD_SCL_POINT_SIZE
] =
8487 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8488 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8490 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8491 scl_val
[XLFD_SCL_AVGWIDTH
] =
8492 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8493 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8497 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8499 pat
= xlfdpat_create (pattern
);
8503 exact
= xlfdpat_exact_p (pat
);
8505 for (i
= 0; i
< font_name_count
; i
++)
8507 if (xlfdpat_match (pat
, font_name_table
[i
]))
8509 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8510 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8513 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8514 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8516 int former_len
= ptr
- font_name_table
[i
];
8518 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8519 memcpy (scaled
, font_name_table
[i
], former_len
);
8520 sprintf (scaled
+ former_len
,
8521 "-%d-%d-72-72-m-%d-%s",
8522 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8523 scl_val
[XLFD_SCL_POINT_SIZE
],
8524 scl_val
[XLFD_SCL_AVGWIDTH
],
8525 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8527 if (xlfdpat_match (pat
, scaled
))
8529 font_list
= Fcons (build_string (scaled
), font_list
);
8531 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8539 xlfdpat_destroy (pat
);
8544 /* Return a list of names of available fonts matching PATTERN on frame F.
8546 Frame F null means we have not yet created any frame on Mac, and
8547 consult the first display in x_display_list. MAXNAMES sets a limit
8548 on how many fonts to match. */
8551 x_list_fonts (f
, pattern
, size
, maxnames
)
8553 Lisp_Object pattern
;
8556 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8557 struct mac_display_info
*dpyinfo
8558 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8560 xassert (size
<= 0);
8562 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8563 if (NILP (patterns
))
8564 patterns
= Fcons (pattern
, Qnil
);
8566 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8568 pattern
= XCAR (patterns
);
8570 if (!STRINGP (pattern
))
8573 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8574 key
= Fcons (pattern
, make_number (maxnames
));
8576 list
= Fassoc (key
, tem
);
8579 list
= Fcdr_safe (list
);
8580 /* We have a cashed list. Don't have to get the list again. */
8585 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8588 /* MAC_TODO: add code for matching outline fonts here */
8590 /* Now store the result in the cache. */
8591 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8592 Fcons (Fcons (key
, list
),
8593 XCAR (XCDR (dpyinfo
->name_list_element
))));
8596 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8605 /* Check that FONT is valid on frame F. It is if it can be found in F's
8609 x_check_font (f
, font
)
8614 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8616 xassert (font
!= NULL
);
8618 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8619 if (dpyinfo
->font_table
[i
].name
8620 && font
== dpyinfo
->font_table
[i
].font
)
8623 xassert (i
< dpyinfo
->n_fonts
);
8626 #endif /* GLYPH_DEBUG != 0 */
8628 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8629 Note: There are (broken) X fonts out there with invalid XFontStruct
8630 min_bounds contents. For example, handa@etl.go.jp reports that
8631 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8632 have font->min_bounds.width == 0. */
8635 x_font_min_bounds (font
, w
, h
)
8636 MacFontStruct
*font
;
8639 *h
= FONT_HEIGHT (font
);
8640 *w
= font
->min_bounds
.width
;
8644 /* Compute the smallest character width and smallest font height over
8645 all fonts available on frame F. Set the members smallest_char_width
8646 and smallest_font_height in F's x_display_info structure to
8647 the values computed. Value is non-zero if smallest_font_height or
8648 smallest_char_width become smaller than they were before. */
8651 x_compute_min_glyph_bounds (f
)
8655 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8656 MacFontStruct
*font
;
8657 int old_width
= dpyinfo
->smallest_char_width
;
8658 int old_height
= dpyinfo
->smallest_font_height
;
8660 dpyinfo
->smallest_font_height
= 100000;
8661 dpyinfo
->smallest_char_width
= 100000;
8663 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8664 if (dpyinfo
->font_table
[i
].name
)
8666 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8669 font
= (MacFontStruct
*) fontp
->font
;
8670 xassert (font
!= (MacFontStruct
*) ~0);
8671 x_font_min_bounds (font
, &w
, &h
);
8673 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8674 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8677 xassert (dpyinfo
->smallest_char_width
> 0
8678 && dpyinfo
->smallest_font_height
> 0);
8680 return (dpyinfo
->n_fonts
== 1
8681 || dpyinfo
->smallest_char_width
< old_width
8682 || dpyinfo
->smallest_font_height
< old_height
);
8686 /* Determine whether given string is a fully-specified XLFD: all 14
8687 fields are present, none is '*'. */
8690 is_fully_specified_xlfd (p
)
8699 for (i
= 0; i
< 13; i
++)
8701 q
= strchr (p
+ 1, '-');
8704 if (q
- p
== 2 && *(p
+ 1) == '*')
8709 if (strchr (p
+ 1, '-') != NULL
)
8712 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8719 /* mac_load_query_font creates and returns an internal representation
8720 for a font in a MacFontStruct struct. There is really no concept
8721 corresponding to "loading" a font on the Mac. But we check its
8722 existence and find the font number and all other information for it
8723 and store them in the returned MacFontStruct. */
8725 static MacFontStruct
*
8726 mac_load_query_font (f
, fontname
)
8736 static ATSUFontID font_id
;
8737 ATSUStyle mac_style
= NULL
;
8740 #if TARGET_API_MAC_CARBON
8741 TextEncoding encoding
;
8746 MacFontStruct
*font
;
8747 XCharStruct
*space_bounds
= NULL
, *pcm
;
8749 if (is_fully_specified_xlfd (fontname
))
8753 Lisp_Object matched_fonts
;
8755 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8756 if (NILP (matched_fonts
))
8758 name
= SDATA (XCAR (matched_fonts
));
8761 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8765 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8768 static const ATSUAttributeTag tags
[] =
8769 {kATSUFontTag
, kATSUSizeTag
,
8770 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8771 static const ByteCount sizes
[] =
8772 {sizeof (ATSUFontID
), sizeof (Fixed
),
8773 sizeof (Boolean
), sizeof (Boolean
)};
8774 static Fixed size_fixed
;
8775 static Boolean bold_p
, italic_p
;
8776 static const ATSUAttributeValuePtr values
[] =
8777 {&font_id
, &size_fixed
,
8778 &bold_p
, &italic_p
};
8779 static const ATSUFontFeatureType types
[] =
8780 {kAllTypographicFeaturesType
, kDiacriticsType
};
8781 static const ATSUFontFeatureSelector selectors
[] =
8782 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8785 font_id
= atsu_find_font_from_family_name (family
);
8786 if (font_id
== kATSUInvalidFontID
)
8788 size_fixed
= Long2Fix (size
);
8789 bold_p
= (fontface
& bold
) != 0;
8790 italic_p
= (fontface
& italic
) != 0;
8791 err
= ATSUCreateStyle (&mac_style
);
8794 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8798 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8799 tags
, sizes
, values
);
8802 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8805 scriptcode
= kTextEncodingMacUnicode
;
8810 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8814 fontnum
= XINT (XCDR (tmp
));
8815 #if TARGET_API_MAC_CARBON
8816 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8818 scriptcode
= GetTextEncodingBase (encoding
);
8820 scriptcode
= FontToScript (fontnum
);
8824 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8826 font
->mac_fontnum
= fontnum
;
8827 font
->mac_fontsize
= size
;
8828 font
->mac_fontface
= fontface
;
8829 font
->mac_scriptcode
= scriptcode
;
8831 font
->mac_style
= mac_style
;
8832 #if USE_CG_TEXT_DRAWING
8833 font
->cg_font
= NULL
;
8834 font
->cg_glyphs
= NULL
;
8838 /* Apple Japanese (SJIS) font is listed as both
8839 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8840 (Roman script) in init_font_name_table (). The latter should be
8841 treated as a one-byte font. */
8842 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8843 font
->mac_scriptcode
= smRoman
;
8845 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8848 if (font
->mac_style
)
8853 font
->min_byte1
= 0;
8854 font
->max_byte1
= 0xff;
8855 font
->min_char_or_byte2
= 0;
8856 font
->max_char_or_byte2
= 0xff;
8858 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8859 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8860 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8861 pcm_init (font
->bounds
.rows
[0], 0x100);
8863 #if USE_CG_TEXT_DRAWING
8867 ATSFontRef ats_font
;
8869 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8871 /* Use CG text drawing if italic/bold is not synthesized. */
8872 if (err
== noErr
&& style
== fontface
)
8874 ats_font
= FMGetATSFontRefFromFont (font_id
);
8875 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8881 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8882 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8885 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8886 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8887 &font
->ascent
, &font
->descent
,
8889 #if USE_CG_TEXT_DRAWING
8890 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8897 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8899 mac_unload_font (&one_mac_display_info
, font
);
8903 pcm
= font
->bounds
.rows
[0];
8904 for (c
= 0x21; c
<= 0xff; c
++)
8907 /* Soft hyphen is not supported in ATSUI. */
8911 #if USE_CG_TEXT_DRAWING
8912 if (font
->cg_glyphs
)
8922 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8923 pcm
? pcm
+ c
: NULL
,
8924 #if USE_CG_TEXT_DRAWING
8925 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8932 #if USE_CG_TEXT_DRAWING
8933 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8935 /* Don't use CG text drawing if font substitution occurs in
8936 ASCII or Latin-1 characters. */
8937 CGFontRelease (font
->cg_font
);
8938 font
->cg_font
= NULL
;
8939 xfree (font
->cg_glyphs
);
8940 font
->cg_glyphs
= NULL
;
8951 FontInfo the_fontinfo
;
8952 int is_two_byte_font
;
8955 mac_prepare_for_quickdraw (f
);
8957 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8961 TextFace (fontface
);
8963 GetFontInfo (&the_fontinfo
);
8965 font
->ascent
= the_fontinfo
.ascent
;
8966 font
->descent
= the_fontinfo
.descent
;
8968 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8969 || font
->mac_scriptcode
== smTradChinese
8970 || font
->mac_scriptcode
== smSimpChinese
8971 || font
->mac_scriptcode
== smKorean
);
8973 if (is_two_byte_font
)
8977 font
->min_byte1
= 0xa1;
8978 font
->max_byte1
= 0xfe;
8979 font
->min_char_or_byte2
= 0xa1;
8980 font
->max_char_or_byte2
= 0xfe;
8982 /* Use the width of an "ideographic space" of that font
8983 because the_fontinfo.widMax returns the wrong width for
8985 switch (font
->mac_scriptcode
)
8988 font
->min_byte1
= 0x81;
8989 font
->max_byte1
= 0xfc;
8990 font
->min_char_or_byte2
= 0x40;
8991 font
->max_char_or_byte2
= 0xfc;
8992 char_width
= StringWidth("\p\x81\x40");
8995 font
->min_char_or_byte2
= 0x40;
8996 char_width
= StringWidth("\p\xa1\x40");
8999 char_width
= StringWidth("\p\xa1\xa1");
9002 char_width
= StringWidth("\p\xa1\xa1");
9006 font
->bounds
.per_char
= NULL
;
9008 if (fontface
& italic
)
9009 font
->max_bounds
.rbearing
= char_width
+ 1;
9011 font
->max_bounds
.rbearing
= char_width
;
9012 font
->max_bounds
.lbearing
= 0;
9013 font
->max_bounds
.width
= char_width
;
9014 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
9015 font
->max_bounds
.descent
= the_fontinfo
.descent
;
9017 font
->min_bounds
= font
->max_bounds
;
9023 font
->min_byte1
= font
->max_byte1
= 0;
9024 font
->min_char_or_byte2
= 0x20;
9025 font
->max_char_or_byte2
= 0xff;
9027 font
->bounds
.per_char
=
9028 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9029 bzero (font
->bounds
.per_char
,
9030 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9032 space_bounds
= font
->bounds
.per_char
;
9033 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9034 &font
->descent
, space_bounds
, NULL
);
9035 if (err
!= noErr
|| space_bounds
->width
<= 0)
9037 mac_unload_font (&one_mac_display_info
, font
);
9041 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9042 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9050 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9051 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9054 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9056 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9058 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9060 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9062 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9065 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9067 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9069 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9071 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9073 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9078 font
->mac_style
== NULL
&&
9080 font
->max_bounds
.width
== font
->min_bounds
.width
9081 && font
->min_bounds
.lbearing
>= 0
9082 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9084 /* Fixed width and no overhangs. */
9085 xfree (font
->bounds
.per_char
);
9086 font
->bounds
.per_char
= NULL
;
9090 #if !defined (MAC_OS8) || USE_ATSUI
9091 /* AppKit and WebKit do some adjustment to the heights of Courier,
9092 Helvetica, and Times. This only works on the environments where
9093 srcCopy text transfer mode is never used. */
9095 #ifdef MAC_OS8 /* implies USE_ATSUI */
9098 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9099 || strcmp (family
, "times") == 0))
9100 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9108 mac_unload_font (dpyinfo
, font
)
9109 struct mac_display_info
*dpyinfo
;
9112 xfree (font
->full_name
);
9114 if (font
->mac_style
)
9118 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9119 if (font
->bounds
.rows
[i
])
9120 xfree (font
->bounds
.rows
[i
]);
9121 xfree (font
->bounds
.rows
);
9122 ATSUDisposeStyle (font
->mac_style
);
9126 if (font
->bounds
.per_char
)
9127 xfree (font
->bounds
.per_char
);
9128 #if USE_CG_TEXT_DRAWING
9130 CGFontRelease (font
->cg_font
);
9131 if (font
->cg_glyphs
)
9132 xfree (font
->cg_glyphs
);
9138 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9139 pointer to the structure font_info while allocating it dynamically.
9140 If SIZE is 0, load any size of font.
9141 If loading is failed, return NULL. */
9144 x_load_font (f
, fontname
, size
)
9146 register char *fontname
;
9149 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9150 Lisp_Object font_names
;
9152 /* Get a list of all the fonts that match this name. Once we
9153 have a list of matching fonts, we compare them against the fonts
9154 we already have by comparing names. */
9155 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9157 if (!NILP (font_names
))
9162 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9163 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9164 if (dpyinfo
->font_table
[i
].name
9165 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9166 SDATA (XCAR (tail
)))
9167 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9168 SDATA (XCAR (tail
)))))
9169 return (dpyinfo
->font_table
+ i
);
9174 /* Load the font and add it to the table. */
9176 struct MacFontStruct
*font
;
9177 struct font_info
*fontp
;
9180 fontname
= (char *) SDATA (XCAR (font_names
));
9183 font
= mac_load_query_font (f
, fontname
);
9188 /* Find a free slot in the font table. */
9189 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9190 if (dpyinfo
->font_table
[i
].name
== NULL
)
9193 /* If no free slot found, maybe enlarge the font table. */
9194 if (i
== dpyinfo
->n_fonts
9195 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9198 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9199 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9201 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9204 fontp
= dpyinfo
->font_table
+ i
;
9205 if (i
== dpyinfo
->n_fonts
)
9208 /* Now fill in the slots of *FONTP. */
9210 bzero (fontp
, sizeof (*fontp
));
9212 fontp
->font_idx
= i
;
9213 fontp
->charset
= -1; /* fs_load_font sets it. */
9214 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9215 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9217 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9219 /* Fixed width font. */
9220 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9227 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9228 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9230 fontp
->space_width
= pcm
->width
;
9232 fontp
->space_width
= FONT_WIDTH (font
);
9236 int width
= pcm
->width
;
9237 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9238 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9239 width
+= pcm
->width
;
9240 fontp
->average_width
= width
/ 95;
9243 fontp
->average_width
= FONT_WIDTH (font
);
9246 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9247 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9249 fontp
->size
= font
->max_bounds
.width
;
9250 fontp
->height
= FONT_HEIGHT (font
);
9252 /* For some font, ascent and descent in max_bounds field is
9253 larger than the above value. */
9254 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9255 if (max_height
> fontp
->height
)
9256 fontp
->height
= max_height
;
9259 /* MAC_TODO: The script encoding is irrelevant in unicode? */
9260 /* The slot `encoding' specifies how to map a character
9261 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9262 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9263 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9264 2:0xA020..0xFF7F). For the moment, we don't know which charset
9265 uses this font. So, we set information in fontp->encoding_type
9266 which is never used by any charset. If mapping can't be
9267 decided, set FONT_ENCODING_NOT_DECIDED. */
9268 if (font
->mac_scriptcode
== smJapanese
)
9269 fontp
->encoding_type
= 4;
9272 fontp
->encoding_type
9273 = (font
->max_byte1
== 0
9275 ? (font
->min_char_or_byte2
< 0x80
9276 ? (font
->max_char_or_byte2
< 0x80
9277 ? 0 /* 0x20..0x7F */
9278 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9279 : 1) /* 0xA0..0xFF */
9281 : (font
->min_byte1
< 0x80
9282 ? (font
->max_byte1
< 0x80
9283 ? (font
->min_char_or_byte2
< 0x80
9284 ? (font
->max_char_or_byte2
< 0x80
9285 ? 0 /* 0x2020..0x7F7F */
9286 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9287 : 3) /* 0x20A0..0x7FFF */
9288 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9289 : (font
->min_char_or_byte2
< 0x80
9290 ? (font
->max_char_or_byte2
< 0x80
9291 ? 2 /* 0xA020..0xFF7F */
9292 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9293 : 1))); /* 0xA0A0..0xFFFF */
9296 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9297 fontp
->baseline_offset
9298 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9299 ? (long) value
: 0);
9300 fontp
->relative_compose
9301 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9302 ? (long) value
: 0);
9303 fontp
->default_ascent
9304 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9305 ? (long) value
: 0);
9307 fontp
->baseline_offset
= 0;
9308 fontp
->relative_compose
= 0;
9309 fontp
->default_ascent
= 0;
9312 /* Set global flag fonts_changed_p to non-zero if the font loaded
9313 has a character with a smaller width than any other character
9314 before, or if the font loaded has a smaller height than any
9315 other font loaded before. If this happens, it will make a
9316 glyph matrix reallocation necessary. */
9317 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9324 /* Return a pointer to struct font_info of a font named FONTNAME for
9325 frame F. If no such font is loaded, return NULL. */
9328 x_query_font (f
, fontname
)
9330 register char *fontname
;
9332 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9335 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9336 if (dpyinfo
->font_table
[i
].name
9337 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9338 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9339 return (dpyinfo
->font_table
+ i
);
9344 /* Find a CCL program for a font specified by FONTP, and set the member
9345 `encoder' of the structure. */
9348 x_find_ccl_program (fontp
)
9349 struct font_info
*fontp
;
9351 Lisp_Object list
, elt
;
9353 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9357 && STRINGP (XCAR (elt
))
9358 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9364 struct ccl_program
*ccl
9365 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9367 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9370 fontp
->font_encoder
= ccl
;
9374 #if USE_MAC_FONT_PANEL
9375 /* Whether Font Panel has been shown before. The first call to font
9376 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9377 slow. This variable is used for deferring such a call as much as
9379 static int font_panel_shown_p
= 0;
9381 extern Lisp_Object Qfont
;
9382 static Lisp_Object Qpanel_closed
, Qselection
;
9384 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9388 const EventParamName
*,
9389 const EventParamType
*));
9392 mac_font_panel_visible_p ()
9394 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9397 static pascal OSStatus
9398 mac_handle_font_event (next_handler
, event
, data
)
9399 EventHandlerCallRef next_handler
;
9403 OSStatus result
, err
;
9406 const EventParamName
*names
;
9407 const EventParamType
*types
;
9408 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9409 kEventParamATSUFontSize
,
9410 kEventParamFMFontFamily
,
9411 kEventParamFMFontStyle
,
9412 kEventParamFMFontSize
,
9413 kEventParamFontColor
};
9414 static const EventParamType types_sel
[] = {typeATSUFontID
,
9421 result
= CallNextEventHandler (next_handler
, event
);
9422 if (result
!= eventNotHandledErr
)
9425 switch (GetEventKind (event
))
9427 case kEventFontPanelClosed
:
9428 id_key
= Qpanel_closed
;
9434 case kEventFontSelection
:
9435 id_key
= Qselection
;
9436 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9442 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9452 mac_show_hide_font_panel ()
9454 if (!font_panel_shown_p
)
9458 static const EventTypeSpec specs
[] =
9459 {{kEventClassFont
, kEventFontPanelClosed
},
9460 {kEventClassFont
, kEventFontSelection
}};
9462 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9463 GetEventTypeCount (specs
),
9468 font_panel_shown_p
= 1;
9471 return FPShowHideFontPanel ();
9475 mac_set_font_info_for_selection (f
, face_id
, c
)
9480 EventTargetRef target
= NULL
;
9481 XFontStruct
*font
= NULL
;
9483 if (!mac_font_panel_visible_p ())
9488 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9490 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9494 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9495 face
= FACE_FROM_ID (f
, face_id
);
9501 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9504 if (font
->mac_fontnum
!= -1)
9506 FontSelectionQDStyle qd_style
;
9508 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9509 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9510 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9511 qd_style
.size
= font
->mac_fontsize
;
9512 qd_style
.hasColor
= false;
9514 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9515 1, &qd_style
, target
);
9518 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9519 1, &font
->mac_style
, target
);
9527 /* The Mac Event loop code */
9529 #if !TARGET_API_MAC_CARBON
9531 #include <Quickdraw.h>
9532 #include <Balloons.h>
9533 #include <Devices.h>
9535 #include <Gestalt.h>
9537 #include <Processes.h>
9539 #include <ToolUtils.h>
9540 #include <TextUtils.h>
9541 #include <Dialogs.h>
9544 #include <Resources.h>
9549 #endif /* ! TARGET_API_MAC_CARBON */
9554 #define DEFAULT_NUM_COLS 80
9556 #define MIN_DOC_SIZE 64
9557 #define MAX_DOC_SIZE 32767
9559 #define EXTRA_STACK_ALLOC (256 * 1024)
9561 #define ARGV_STRING_LIST_ID 129
9562 #define ABOUT_ALERT_ID 128
9563 #define RAM_TOO_LARGE_ALERT_ID 129
9565 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9566 Lisp_Object Qreverse
;
9569 /* Modifier associated with the control key, or nil to ignore. */
9570 Lisp_Object Vmac_control_modifier
;
9572 /* Modifier associated with the option key, or nil to ignore. */
9573 Lisp_Object Vmac_option_modifier
;
9575 /* Modifier associated with the command key, or nil to ignore. */
9576 Lisp_Object Vmac_command_modifier
;
9578 /* Modifier associated with the function key, or nil to ignore. */
9579 Lisp_Object Vmac_function_modifier
;
9581 /* True if the option and command modifiers should be used to emulate
9582 a three button mouse */
9583 Lisp_Object Vmac_emulate_three_button_mouse
;
9585 #if TARGET_API_MAC_CARBON
9586 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9587 mouse-2, instead of mouse-3. */
9588 int mac_wheel_button_is_mouse_2
;
9590 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9591 for processing before Emacs sees it. */
9592 int mac_pass_command_to_system
;
9594 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9595 for processing before Emacs sees it. */
9596 int mac_pass_control_to_system
;
9599 /* Points to the variable `inev' in the function XTread_socket. It is
9600 used for passing an input event to the function back from
9601 Carbon/Apple event handlers. */
9602 static struct input_event
*read_socket_inev
= NULL
;
9604 /* Whether or not the screen configuration has changed. */
9605 static int mac_screen_config_changed
= 0;
9607 Point saved_menu_event_location
;
9610 #if TARGET_API_MAC_CARBON
9611 static Lisp_Object Qhi_command
;
9613 extern Lisp_Object Qwindow
;
9614 static Lisp_Object Qtoolbar_switch_mode
;
9617 static TSMDocumentID tsm_document_id
;
9618 static Lisp_Object Qtext_input
;
9619 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9620 static Lisp_Object Vmac_ts_active_input_overlay
;
9621 extern Lisp_Object Qbefore_string
;
9622 static Lisp_Object Vmac_ts_script_language_on_focus
;
9623 static Lisp_Object saved_ts_script_language_on_focus
;
9624 static ScriptLanguageRecord saved_ts_language
;
9625 static Component saved_ts_component
;
9627 #endif /* TARGET_API_MAC_CARBON */
9628 extern int mac_ready_for_apple_events
;
9629 extern Lisp_Object Qundefined
;
9630 extern void init_apple_event_handler
P_ ((void));
9631 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9632 Lisp_Object
*, Lisp_Object
*,
9634 extern OSErr init_coercion_handler
P_ ((void));
9637 extern OSErr install_drag_handler
P_ ((WindowRef
));
9638 extern void remove_drag_handler
P_ ((WindowRef
));
9640 #if TARGET_API_MAC_CARBON
9641 /* Showing help echo string during menu tracking */
9642 extern OSStatus install_menu_target_item_handler
P_ ((void));
9645 extern OSStatus
install_service_handler ();
9646 static Lisp_Object Qservice
, Qpaste
, Qperform
;
9650 extern void init_emacs_passwd_dir ();
9651 extern int emacs_main (int, char **, char **);
9653 extern void initialize_applescript();
9654 extern void terminate_applescript();
9656 /* Table for translating Mac keycode to X keysym values. Contributed
9658 Mapping for special keys is now identical to that in Apple X11
9659 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9660 on the right of the Cmd key on laptops, and fn + `enter' (->
9662 static const unsigned char keycode_to_xkeysym_table
[] = {
9663 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9664 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9665 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9667 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9668 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9669 /*0x38*/ 0, 0, 0, 0,
9670 /*0x3C*/ 0, 0, 0, 0,
9672 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9673 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9674 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9675 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9677 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9678 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9679 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9680 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9682 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9683 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9684 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9685 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9687 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9688 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9689 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9690 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9694 /* Table for translating Mac keycode with the laptop `fn' key to that
9695 without it. Destination symbols in comments are keys on US
9696 keyboard, and they may not be the same on other types of keyboards.
9697 If the destination is identical to the source (f1 ... f12), it
9698 doesn't map `fn' key to a modifier. */
9699 static const unsigned char fn_keycode_to_keycode_table
[] = {
9700 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9701 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9702 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9704 /*0x30*/ 0, 0, 0, 0,
9705 /*0x34*/ 0, 0, 0, 0,
9706 /*0x38*/ 0, 0, 0, 0,
9707 /*0x3C*/ 0, 0, 0, 0,
9709 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9710 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9711 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9712 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9714 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9715 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9716 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9717 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9719 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9720 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9721 /*0x68*/ 0, 0, 0, 0,
9722 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9724 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9725 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9726 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9729 #endif /* MAC_OSX */
9732 #if TARGET_API_MAC_CARBON
9733 mac_to_emacs_modifiers (UInt32 mods
)
9735 mac_to_emacs_modifiers (EventModifiers mods
)
9738 unsigned int result
= 0;
9739 if (mods
& shiftKey
)
9740 result
|= shift_modifier
;
9742 /* Deactivated to simplify configuration:
9743 if Vmac_option_modifier is non-NIL, we fully process the Option
9744 key. Otherwise, we only process it if an additional Ctrl or Command
9745 is pressed. That way the system may convert the character to a
9747 if ((mods & optionKey) &&
9748 (( !NILP(Vmac_option_modifier) ||
9749 ((mods & cmdKey) || (mods & controlKey))))) */
9751 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9752 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9754 result
|= XUINT(val
);
9756 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9757 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9759 result
|= XUINT(val
);
9761 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9762 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9764 result
|= XUINT(val
);
9768 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9769 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9771 result
|= XUINT(val
);
9779 mac_mapped_modifiers (modifiers
)
9782 UInt32 mapped_modifiers_all
=
9783 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9784 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9785 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9788 mapped_modifiers_all
|=
9789 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9792 return mapped_modifiers_all
& modifiers
;
9796 mac_get_emulated_btn ( UInt32 modifiers
)
9799 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9800 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9801 if (modifiers
& cmdKey
)
9802 result
= cmdIs3
? 2 : 1;
9803 else if (modifiers
& optionKey
)
9804 result
= cmdIs3
? 1 : 2;
9809 #if TARGET_API_MAC_CARBON
9810 /***** Code to handle C-g testing *****/
9811 extern int quit_char
;
9812 extern int make_ctrl_char
P_ ((int));
9815 mac_quit_char_key_p (modifiers
, key_code
)
9816 UInt32 modifiers
, key_code
;
9819 unsigned long some_state
= 0;
9820 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9821 int c
, emacs_modifiers
;
9823 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9824 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9825 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9826 if (char_code
& ~0xff)
9829 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9830 if (emacs_modifiers
& ctrl_modifier
)
9831 c
= make_ctrl_char (char_code
);
9833 c
|= (emacs_modifiers
9834 & (meta_modifier
| alt_modifier
9835 | hyper_modifier
| super_modifier
));
9837 return c
== quit_char
;
9841 #if TARGET_API_MAC_CARBON
9842 /* Obtains the event modifiers from the event ref and then calls
9843 mac_to_emacs_modifiers. */
9845 mac_event_to_emacs_modifiers (EventRef eventRef
)
9847 UInt32 mods
= 0, class;
9849 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9850 sizeof (UInt32
), NULL
, &mods
);
9851 class = GetEventClass (eventRef
);
9852 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9853 (class == kEventClassMouse
|| class == kEventClassCommand
))
9855 mods
&= ~(optionKey
| cmdKey
);
9857 return mac_to_emacs_modifiers (mods
);
9860 /* Given an event ref, return the code to use for the mouse button
9861 code in the emacs input_event. */
9863 mac_get_mouse_btn (EventRef ref
)
9865 EventMouseButton result
= kEventMouseButtonPrimary
;
9866 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9867 sizeof (EventMouseButton
), NULL
, &result
);
9870 case kEventMouseButtonPrimary
:
9871 if (NILP (Vmac_emulate_three_button_mouse
))
9875 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9876 sizeof (UInt32
), NULL
, &mods
);
9877 return mac_get_emulated_btn(mods
);
9879 case kEventMouseButtonSecondary
:
9880 return mac_wheel_button_is_mouse_2
? 2 : 1;
9881 case kEventMouseButtonTertiary
:
9882 case 4: /* 4 is the number for the mouse wheel button */
9883 return mac_wheel_button_is_mouse_2
? 1 : 2;
9889 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9890 events. However the click of the mouse wheel is not converted to a
9891 mouseDown or mouseUp event. Likewise for dead key events. This
9892 calls ConvertEventRefToEventRecord, but then checks to see if it is
9893 a mouse up/down, or a dead key Carbon event that has not been
9894 converted, and if so, converts it by hand (to be picked up in the
9895 XTread_socket loop). */
9896 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9899 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9905 switch (GetEventClass (eventRef
))
9907 case kEventClassMouse
:
9908 switch (GetEventKind (eventRef
))
9910 case kEventMouseDown
:
9911 eventRec
->what
= mouseDown
;
9916 eventRec
->what
= mouseUp
;
9925 case kEventClassKeyboard
:
9926 switch (GetEventKind (eventRef
))
9928 case kEventRawKeyDown
:
9930 goto keystroke_common
;
9931 case kEventRawKeyRepeat
:
9933 goto keystroke_common
;
9934 case kEventRawKeyUp
:
9938 unsigned char char_codes
;
9941 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9942 typeChar
, NULL
, sizeof (char),
9945 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9946 typeUInt32
, NULL
, sizeof (UInt32
),
9950 eventRec
->what
= action
;
9951 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9968 /* Need where and when. */
9971 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9972 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9973 /* Use two step process because new event modifiers are 32-bit
9974 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9975 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9976 NULL
, sizeof (UInt32
), NULL
, &mods
);
9977 eventRec
->modifiers
= mods
;
9979 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9991 Handle menubar_handle
;
9994 menubar_handle
= GetNewMBar (128);
9995 if(menubar_handle
== NULL
)
9997 SetMenuBar (menubar_handle
);
10000 #if !TARGET_API_MAC_CARBON
10001 menu
= GetMenuRef (M_APPLE
);
10003 AppendResMenu (menu
, 'DRVR');
10011 do_init_managers (void)
10013 #if !TARGET_API_MAC_CARBON
10014 InitGraf (&qd
.thePort
);
10016 FlushEvents (everyEvent
, 0);
10020 InitDialogs (NULL
);
10021 #endif /* !TARGET_API_MAC_CARBON */
10024 #if !TARGET_API_MAC_CARBON
10025 /* set up some extra stack space for use by emacs */
10026 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10028 /* MaxApplZone must be called for AppleScript to execute more
10029 complicated scripts */
10032 #endif /* !TARGET_API_MAC_CARBON */
10036 do_check_ram_size (void)
10038 SInt32 physical_ram_size
, logical_ram_size
;
10040 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10041 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10042 || physical_ram_size
> (1 << VALBITS
)
10043 || logical_ram_size
> (1 << VALBITS
))
10045 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10049 #endif /* MAC_OS8 */
10052 do_window_update (WindowRef win
)
10054 struct frame
*f
= mac_window_to_frame (win
);
10058 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10060 if (win
!= tip_window
)
10062 if (f
->async_visible
== 0)
10064 /* Update events may occur when a frame gets iconified. */
10066 f
->async_visible
= 1;
10067 f
->async_iconified
= 0;
10068 SET_FRAME_GARBAGED (f
);
10074 #if TARGET_API_MAC_CARBON
10075 RgnHandle region
= NewRgn ();
10077 GetPortVisibleRegion (GetWindowPort (win
), region
);
10078 GetRegionBounds (region
, &r
);
10079 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10081 mac_prepare_for_quickdraw (f
);
10083 UpdateControls (win
, region
);
10084 DisposeRgn (region
);
10086 r
= (*win
->visRgn
)->rgnBBox
;
10087 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10088 UpdateControls (win
, win
->visRgn
);
10097 is_emacs_window (WindowRef win
)
10099 Lisp_Object tail
, frame
;
10104 FOR_EACH_FRAME (tail
, frame
)
10105 if (FRAME_MAC_P (XFRAME (frame
)))
10106 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10117 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10119 err
= ActivateTSMDocument (tsm_document_id
);
10123 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10124 && EQ (saved_ts_script_language_on_focus
, Qt
))
10125 slptr
= &saved_ts_language
;
10126 else if (CONSP (Vmac_ts_script_language_on_focus
)
10127 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10128 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10129 && CONSP (saved_ts_script_language_on_focus
)
10130 && EQ (XCAR (saved_ts_script_language_on_focus
),
10131 XCAR (Vmac_ts_script_language_on_focus
))
10132 && EQ (XCDR (saved_ts_script_language_on_focus
),
10133 XCDR (Vmac_ts_script_language_on_focus
)))
10135 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10136 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10143 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10144 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10145 kKeyboardInputMethodClass
);
10147 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10150 err
= SetTextServiceLanguage (slptr
);
10152 /* Seems to be needed on Mac OS X 10.2. */
10154 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10164 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10166 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10168 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10170 err
= GetTextServiceLanguage (&saved_ts_language
);
10172 slptr
= &saved_ts_language
;
10174 else if (CONSP (Vmac_ts_script_language_on_focus
)
10175 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10176 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10178 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10179 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10185 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10186 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10187 kKeyboardInputMethodClass
);
10189 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10193 err
= DeactivateTSMDocument (tsm_document_id
);
10199 #if !TARGET_API_MAC_CARBON
10201 do_apple_menu (SInt16 menu_item
)
10204 SInt16 da_driver_refnum
;
10206 if (menu_item
== I_ABOUT
)
10207 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10210 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10211 da_driver_refnum
= OpenDeskAcc (item_name
);
10214 #endif /* !TARGET_API_MAC_CARBON */
10216 /* Handle drags in size box. Based on code contributed by Ben
10217 Mesander and IM - Window Manager A. */
10220 do_grow_window (w
, e
)
10222 const EventRecord
*e
;
10225 int rows
, columns
, width
, height
;
10226 struct frame
*f
= mac_window_to_frame (w
);
10227 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10228 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10229 #if TARGET_API_MAC_CARBON
10235 if (size_hints
->flags
& PMinSize
)
10237 min_width
= size_hints
->min_width
;
10238 min_height
= size_hints
->min_height
;
10240 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10242 #if TARGET_API_MAC_CARBON
10243 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10245 height
= new_rect
.bottom
- new_rect
.top
;
10246 width
= new_rect
.right
- new_rect
.left
;
10248 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10249 /* see if it really changed size */
10250 if (grow_size
== 0)
10252 height
= HiWord (grow_size
);
10253 width
= LoWord (grow_size
);
10256 if (width
!= FRAME_PIXEL_WIDTH (f
)
10257 || height
!= FRAME_PIXEL_HEIGHT (f
))
10259 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10260 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10262 x_set_window_size (f
, 0, columns
, rows
);
10267 #if TARGET_API_MAC_CARBON
10269 mac_get_ideal_size (f
)
10272 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10273 WindowRef w
= FRAME_MAC_WINDOW (f
);
10275 Rect standard_rect
;
10276 int height
, width
, columns
, rows
;
10278 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10279 ideal_size
.v
= dpyinfo
->height
;
10280 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10281 /* Adjust the standard size according to character boundaries. */
10282 width
= standard_rect
.right
- standard_rect
.left
;
10283 height
= standard_rect
.bottom
- standard_rect
.top
;
10284 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10285 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10286 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10287 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10293 /* Handle clicks in zoom box. Calculation of "standard state" based
10294 on code in IM - Window Manager A and code contributed by Ben
10295 Mesander. The standard state of an Emacs window is 80-characters
10296 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10299 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10301 Rect zoom_rect
, port_rect
;
10303 struct frame
*f
= mac_window_to_frame (w
);
10304 #if TARGET_API_MAC_CARBON
10305 Point ideal_size
= mac_get_ideal_size (f
);
10307 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10308 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10309 && port_rect
.left
== zoom_rect
.left
10310 && port_rect
.top
== zoom_rect
.top
)
10311 zoom_in_or_out
= inZoomIn
;
10313 zoom_in_or_out
= inZoomOut
;
10316 mac_clear_window (f
);
10318 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10319 #else /* not TARGET_API_MAC_CARBON */
10322 int w_title_height
, rows
;
10323 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10325 GetPort (&save_port
);
10327 SetPortWindowPort (w
);
10329 /* Clear window to avoid flicker. */
10330 EraseRect (&(w
->portRect
));
10331 if (zoom_in_or_out
== inZoomOut
)
10333 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10334 LocalToGlobal (&top_left
);
10336 /* calculate height of window's title bar */
10337 w_title_height
= top_left
.v
- 1
10338 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10340 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10341 zoom_rect
= qd
.screenBits
.bounds
;
10342 zoom_rect
.top
+= w_title_height
;
10343 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10345 zoom_rect
.right
= zoom_rect
.left
10346 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10348 /* Adjust the standard size according to character boundaries. */
10349 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10351 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10353 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10357 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10359 SetPort (save_port
);
10360 #endif /* not TARGET_API_MAC_CARBON */
10362 #if !TARGET_API_MAC_CARBON
10363 /* retrieve window size and update application values */
10364 port_rect
= w
->portRect
;
10365 height
= port_rect
.bottom
- port_rect
.top
;
10366 width
= port_rect
.right
- port_rect
.left
;
10368 mac_handle_size_change (f
, width
, height
);
10369 mac_handle_origin_change (f
);
10374 mac_set_unicode_keystroke_event (code
, buf
)
10376 struct input_event
*buf
;
10378 int charset_id
, c1
, c2
;
10382 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10385 else if (code
< 0x100)
10388 charset_id
= CHARSET_8_BIT_CONTROL
;
10390 charset_id
= charset_latin_iso8859_1
;
10391 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10392 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10397 charset_id
= charset_mule_unicode_0100_24ff
,
10399 else if (code
< 0x33FF)
10400 charset_id
= charset_mule_unicode_2500_33ff
,
10402 else if (code
>= 0xE000)
10403 charset_id
= charset_mule_unicode_e000_ffff
,
10405 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10406 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10407 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10412 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10414 unsigned char char_code
;
10415 UInt32 key_code
, modifiers
;
10416 unsigned long timestamp
;
10417 struct input_event
*buf
;
10419 static SInt16 last_key_script
= -1;
10420 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10421 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10424 if (mapped_modifiers
& kEventKeyModifierFnMask
10425 && key_code
<= 0x7f
10426 && fn_keycode_to_keycode_table
[key_code
])
10427 key_code
= fn_keycode_to_keycode_table
[key_code
];
10430 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10432 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10433 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10435 if (modifiers
& kEventKeyModifierFnMask
10436 && key_code
<= 0x7f
10437 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10438 modifiers
&= ~kEventKeyModifierFnMask
;
10441 else if (mapped_modifiers
)
10443 /* translate the keycode back to determine the original key */
10445 UCKeyboardLayout
*uchr_ptr
= NULL
;
10446 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10448 KeyboardLayoutRef layout
;
10450 err
= KLGetCurrentKeyboardLayout (&layout
);
10452 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10453 (const void **) &uchr_ptr
);
10455 static SInt16 last_key_layout_id
= 0;
10456 static Handle uchr_handle
= (Handle
)-1;
10457 SInt16 current_key_layout_id
=
10458 GetScriptVariable (current_key_script
, smScriptKeys
);
10460 if (uchr_handle
== (Handle
)-1
10461 || last_key_layout_id
!= current_key_layout_id
)
10463 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10464 last_key_layout_id
= current_key_layout_id
;
10467 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10473 UInt16 key_action
= action
- keyDown
;
10474 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10475 UInt32 keyboard_type
= LMGetKbdType ();
10476 SInt32 dead_key_state
= 0;
10478 UniCharCount actual_length
;
10480 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10481 modifier_key_state
, keyboard_type
,
10482 kUCKeyTranslateNoDeadKeysMask
,
10484 1, &actual_length
, &code
);
10485 if (status
== noErr
&& actual_length
== 1)
10486 mac_set_unicode_keystroke_event (code
, buf
);
10488 #endif /* MAC_OSX */
10490 if (buf
->kind
== NO_EVENT
)
10492 /* This code comes from Keyboard Resource, Appendix C of IM
10493 - Text. This is necessary since shift is ignored in KCHR
10494 table translation when option or command is pressed. It
10495 also does not translate correctly control-shift chars
10496 like C-% so mask off shift here also. */
10497 /* Mask off modifier keys that are mapped to some Emacs
10499 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10500 /* set high byte of keycode to modifier high byte*/
10501 int new_key_code
= key_code
| new_modifiers
;
10502 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10503 unsigned long some_state
= 0;
10504 UInt32 new_char_code
;
10506 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10507 if (new_char_code
== 0)
10508 /* Seems like a dead key. Append up-stroke. */
10509 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10513 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10514 buf
->code
= new_char_code
& 0xff;
10519 if (buf
->kind
== NO_EVENT
)
10521 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10522 buf
->code
= char_code
;
10525 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10526 buf
->modifiers
|= (extra_keyboard_modifiers
10527 & (meta_modifier
| alt_modifier
10528 | hyper_modifier
| super_modifier
));
10530 #if TARGET_API_MAC_CARBON
10531 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10532 && buf
->code
>= 0x80 && buf
->modifiers
)
10535 TextEncoding encoding
= kTextEncodingMacRoman
;
10536 TextToUnicodeInfo ttu_info
;
10538 UpgradeScriptInfoToTextEncoding (current_key_script
,
10539 kTextLanguageDontCare
,
10540 kTextRegionDontCare
,
10542 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10547 ByteCount unicode_len
;
10550 pstr
[1] = buf
->code
;
10551 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10553 &unicode_len
, &code
);
10554 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10555 mac_set_unicode_keystroke_event (code
, buf
);
10556 DisposeTextToUnicodeInfo (&ttu_info
);
10561 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10562 && buf
->code
>= 0x80
10563 && last_key_script
!= current_key_script
)
10565 struct input_event event
;
10567 EVENT_INIT (event
);
10568 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10570 event
.code
= current_key_script
;
10571 event
.timestamp
= timestamp
;
10572 kbd_buffer_store_event (&event
);
10573 last_key_script
= current_key_script
;
10578 mac_store_apple_event (class, id
, desc
)
10579 Lisp_Object
class, id
;
10580 const AEDesc
*desc
;
10582 struct input_event buf
;
10586 buf
.kind
= MAC_APPLE_EVENT
;
10589 XSETFRAME (buf
.frame_or_window
,
10590 mac_focus_frame (&one_mac_display_info
));
10591 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10592 is safe to use them during read_socket_hook. */
10593 buf
.arg
= mac_aedesc_to_lisp (desc
);
10594 kbd_buffer_store_event (&buf
);
10597 #if TARGET_API_MAC_CARBON
10599 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10600 event
, num_params
, names
, types
)
10601 AEEventClass
class;
10603 Lisp_Object class_key
, id_key
;
10606 const EventParamName
*names
;
10607 const EventParamType
*types
;
10609 OSStatus err
= eventNotHandledErr
;
10610 Lisp_Object binding
;
10612 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10613 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10615 if (INTEGERP (binding
))
10616 err
= XINT (binding
);
10619 AppleEvent apple_event
;
10620 err
= create_apple_event_from_event_ref (event
, num_params
,
10625 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10626 AEDisposeDesc (&apple_event
);
10627 mac_wakeup_from_rne ();
10636 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10640 const AEDesc
*desc
;
10642 struct input_event buf
;
10646 buf
.kind
= DRAG_N_DROP_EVENT
;
10647 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10648 buf
.timestamp
= TickCount () * (1000 / 60);
10649 XSETINT (buf
.x
, mouse_pos
.h
);
10650 XSETINT (buf
.y
, mouse_pos
.v
);
10651 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10652 buf
.arg
= mac_aedesc_to_lisp (desc
);
10653 kbd_buffer_store_event (&buf
);
10658 mac_store_service_event (event
)
10662 Lisp_Object id_key
;
10664 const EventParamName
*names
;
10665 const EventParamType
*types
;
10666 static const EventParamName names_pfm
[] =
10667 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10668 static const EventParamType types_pfm
[] =
10669 {typeCFStringRef
, typeCFStringRef
};
10671 switch (GetEventKind (event
))
10673 case kEventServicePaste
:
10680 case kEventServicePerform
:
10682 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10691 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10697 #endif /* MAC_OSX */
10699 static pascal OSStatus
10700 mac_handle_window_event (next_handler
, event
, data
)
10701 EventHandlerCallRef next_handler
;
10706 OSStatus err
, result
= eventNotHandledErr
;
10709 XSizeHints
*size_hints
;
10711 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
10712 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10714 return eventNotHandledErr
;
10716 f
= mac_window_to_frame (wp
);
10717 switch (GetEventKind (event
))
10719 /* -- window refresh events -- */
10721 case kEventWindowUpdate
:
10722 result
= CallNextEventHandler (next_handler
, event
);
10723 if (result
!= eventNotHandledErr
)
10726 do_window_update (wp
);
10730 /* -- window state change events -- */
10732 case kEventWindowShowing
:
10733 size_hints
= FRAME_SIZE_HINTS (f
);
10734 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
10736 struct frame
*sf
= SELECTED_FRAME ();
10738 if (!(FRAME_MAC_P (sf
) && sf
->async_visible
))
10739 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
10742 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
10743 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10744 kWindowCascadeStartAtParentWindowScreen
10746 kWindowCascadeOnParentWindowScreen
10749 #if USE_MAC_TOOLBAR
10750 /* This is a workaround. RepositionWindow fails to put
10751 a window at the cascading position when its parent
10752 window has a Carbon HIToolbar. */
10753 if ((f
->left_pos
== sf
->left_pos
10754 && f
->top_pos
== sf
->top_pos
)
10755 || (f
->left_pos
== sf
->left_pos
+ 10 * 2
10756 && f
->top_pos
== sf
->top_pos
+ 32 * 2))
10757 MoveWindowStructure (wp
, sf
->left_pos
+ 10, sf
->top_pos
+ 32);
10764 case kEventWindowHiding
:
10765 /* Before unmapping the window, update the WM_SIZE_HINTS
10766 property to claim that the current position of the window is
10767 user-specified, rather than program-specified, so that when
10768 the window is mapped again, it will be placed at the same
10769 location, without forcing the user to position it by hand
10770 again (they have already done that once for this window.) */
10771 x_wm_set_size_hint (f
, (long) 0, 1);
10775 case kEventWindowShown
:
10776 case kEventWindowHidden
:
10777 case kEventWindowCollapsed
:
10778 case kEventWindowExpanded
:
10779 mac_handle_visibility_change (f
);
10783 case kEventWindowBoundsChanging
:
10784 result
= CallNextEventHandler (next_handler
, event
);
10785 if (result
!= eventNotHandledErr
)
10788 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10789 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10793 size_hints
= FRAME_SIZE_HINTS (f
);
10794 if ((attributes
& kWindowBoundsChangeUserResize
)
10795 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
10796 == (PResizeInc
| PBaseSize
| PMinSize
)))
10801 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10802 typeQDRectangle
, NULL
, sizeof (Rect
),
10807 width
= bounds
.right
- bounds
.left
;
10808 height
= bounds
.bottom
- bounds
.top
;
10810 if (width
< size_hints
->min_width
)
10811 width
= size_hints
->min_width
;
10813 width
= size_hints
->base_width
10814 + (int) ((width
- size_hints
->base_width
)
10815 / (float) size_hints
->width_inc
+ .5)
10816 * size_hints
->width_inc
;
10818 if (height
< size_hints
->min_height
)
10819 height
= size_hints
->min_height
;
10821 height
= size_hints
->base_height
10822 + (int) ((height
- size_hints
->base_height
)
10823 / (float) size_hints
->height_inc
+ .5)
10824 * size_hints
->height_inc
;
10826 bounds
.right
= bounds
.left
+ width
;
10827 bounds
.bottom
= bounds
.top
+ height
;
10828 SetEventParameter (event
, kEventParamCurrentBounds
,
10829 typeQDRectangle
, sizeof (Rect
), &bounds
);
10834 case kEventWindowBoundsChanged
:
10835 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10836 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10840 if (attributes
& kWindowBoundsChangeSizeChanged
)
10844 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10845 typeQDRectangle
, NULL
, sizeof (Rect
),
10851 width
= bounds
.right
- bounds
.left
;
10852 height
= bounds
.bottom
- bounds
.top
;
10853 mac_handle_size_change (f
, width
, height
);
10854 mac_wakeup_from_rne ();
10858 if (attributes
& kWindowBoundsChangeOriginChanged
)
10859 mac_handle_origin_change (f
);
10864 /* -- window action events -- */
10866 case kEventWindowClose
:
10868 struct input_event buf
;
10871 buf
.kind
= DELETE_WINDOW_EVENT
;
10872 XSETFRAME (buf
.frame_or_window
, f
);
10874 kbd_buffer_store_event (&buf
);
10879 case kEventWindowGetIdealSize
:
10880 result
= CallNextEventHandler (next_handler
, event
);
10881 if (result
!= eventNotHandledErr
)
10885 Point ideal_size
= mac_get_ideal_size (f
);
10887 err
= SetEventParameter (event
, kEventParamDimensions
,
10888 typeQDPoint
, sizeof (Point
), &ideal_size
);
10895 case kEventWindowToolbarSwitchMode
:
10897 static const EventParamName names
[] = {kEventParamDirectObject
,
10898 kEventParamWindowMouseLocation
,
10899 kEventParamKeyModifiers
,
10900 kEventParamMouseButton
,
10901 kEventParamClickCount
,
10902 kEventParamMouseChord
};
10903 static const EventParamType types
[] = {typeWindowRef
,
10909 int num_params
= sizeof (names
) / sizeof (names
[0]);
10911 err
= mac_store_event_ref_as_apple_event (0, 0,
10913 Qtoolbar_switch_mode
,
10923 /* -- window focus events -- */
10925 case kEventWindowFocusAcquired
:
10926 err
= mac_tsm_resume ();
10931 case kEventWindowFocusRelinquish
:
10932 err
= mac_tsm_suspend ();
10945 static pascal OSStatus
10946 mac_handle_application_event (next_handler
, event
, data
)
10947 EventHandlerCallRef next_handler
;
10951 OSStatus err
, result
= eventNotHandledErr
;
10953 switch (GetEventKind (event
))
10956 case kEventAppActivated
:
10957 err
= mac_tsm_resume ();
10960 case kEventAppDeactivated
:
10961 err
= mac_tsm_suspend ();
10975 static pascal OSStatus
10976 mac_handle_keyboard_event (next_handler
, event
, data
)
10977 EventHandlerCallRef next_handler
;
10981 OSStatus err
, result
= eventNotHandledErr
;
10982 UInt32 event_kind
, key_code
, modifiers
;
10983 unsigned char char_code
;
10985 event_kind
= GetEventKind (event
);
10986 switch (event_kind
)
10988 case kEventRawKeyDown
:
10989 case kEventRawKeyRepeat
:
10990 case kEventRawKeyUp
:
10991 /* When using Carbon Events, we need to pass raw keyboard events
10992 to the TSM ourselves. If TSM handles it, it will pass back
10993 noErr, otherwise it will pass back "eventNotHandledErr" and
10994 we can process it normally. */
10995 result
= CallNextEventHandler (next_handler
, event
);
10996 if (result
!= eventNotHandledErr
)
10999 if (read_socket_inev
== NULL
)
11003 if (read_socket_inev
->kind
!= NO_EVENT
)
11010 if (event_kind
== kEventRawKeyUp
)
11013 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11015 sizeof (char), NULL
, &char_code
);
11019 err
= GetEventParameter (event
, kEventParamKeyCode
,
11021 sizeof (UInt32
), NULL
, &key_code
);
11025 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
11027 sizeof (UInt32
), NULL
, &modifiers
);
11031 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11032 char_code
, key_code
, modifiers
,
11034 (GetEventTime (event
) / kEventDurationMillisecond
)),
11046 static pascal OSStatus
11047 mac_handle_command_event (next_handler
, event
, data
)
11048 EventHandlerCallRef next_handler
;
11052 OSStatus err
, result
= eventNotHandledErr
;
11054 static const EventParamName names
[] =
11055 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11056 static const EventParamType types
[] =
11057 {typeHICommand
, typeUInt32
};
11058 int num_params
= sizeof (names
) / sizeof (names
[0]);
11060 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11061 NULL
, sizeof (HICommand
), NULL
, &command
);
11063 return eventNotHandledErr
;
11065 switch (GetEventKind (event
))
11067 case kEventCommandProcess
:
11068 result
= CallNextEventHandler (next_handler
, event
);
11069 if (result
!= eventNotHandledErr
)
11072 err
= GetEventParameter (event
, kEventParamDirectObject
,
11073 typeHICommand
, NULL
,
11074 sizeof (HICommand
), NULL
, &command
);
11076 if (err
!= noErr
|| command
.commandID
== 0)
11079 /* A HI command event is mapped to an Apple event whose event
11080 class symbol is `hi-command' and event ID is its command
11082 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11097 static pascal OSStatus
11098 mac_handle_mouse_event (next_handler
, event
, data
)
11099 EventHandlerCallRef next_handler
;
11103 OSStatus err
, result
= eventNotHandledErr
;
11105 switch (GetEventKind (event
))
11107 case kEventMouseWheelMoved
:
11111 EventMouseWheelAxis axis
;
11115 result
= CallNextEventHandler (next_handler
, event
);
11116 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11119 f
= mac_focus_frame (&one_mac_display_info
);
11121 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11122 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11124 || wp
!= FRAME_MAC_WINDOW (f
))
11127 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11128 typeMouseWheelAxis
, NULL
,
11129 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11130 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11133 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11134 typeQDPoint
, NULL
, sizeof (Point
),
11139 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11140 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11141 if (point
.h
< 0 || point
.v
< 0
11142 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11143 f
->tool_bar_window
))
11146 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11147 typeSInt32
, NULL
, sizeof (SInt32
),
11152 read_socket_inev
->kind
= WHEEL_EVENT
;
11153 read_socket_inev
->code
= 0;
11154 read_socket_inev
->modifiers
=
11155 (mac_event_to_emacs_modifiers (event
)
11156 | ((delta
< 0) ? down_modifier
: up_modifier
));
11157 XSETINT (read_socket_inev
->x
, point
.h
);
11158 XSETINT (read_socket_inev
->y
, point
.v
);
11159 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11173 static pascal OSStatus
11174 mac_handle_text_input_event (next_handler
, event
, data
)
11175 EventHandlerCallRef next_handler
;
11179 OSStatus err
, result
;
11180 Lisp_Object id_key
= Qnil
;
11182 const EventParamName
*names
;
11183 const EventParamType
*types
;
11184 static UInt32 seqno_uaia
= 0;
11185 static const EventParamName names_uaia
[] =
11186 {kEventParamTextInputSendComponentInstance
,
11187 kEventParamTextInputSendRefCon
,
11188 kEventParamTextInputSendSLRec
,
11189 kEventParamTextInputSendFixLen
,
11190 kEventParamTextInputSendText
,
11191 kEventParamTextInputSendUpdateRng
,
11192 kEventParamTextInputSendHiliteRng
,
11193 kEventParamTextInputSendClauseRng
,
11194 kEventParamTextInputSendPinRng
,
11195 kEventParamTextInputSendTextServiceEncoding
,
11196 kEventParamTextInputSendTextServiceMacEncoding
,
11197 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11198 static const EventParamType types_uaia
[] =
11199 {typeComponentInstance
,
11201 typeIntlWritingCode
,
11208 typeTextRangeArray
,
11209 typeTextRangeArray
,
11215 static const EventParamName names_ufke
[] =
11216 {kEventParamTextInputSendComponentInstance
,
11217 kEventParamTextInputSendRefCon
,
11218 kEventParamTextInputSendSLRec
,
11219 kEventParamTextInputSendText
};
11220 static const EventParamType types_ufke
[] =
11221 {typeComponentInstance
,
11223 typeIntlWritingCode
,
11226 result
= CallNextEventHandler (next_handler
, event
);
11227 if (result
!= eventNotHandledErr
)
11230 switch (GetEventKind (event
))
11232 case kEventTextInputUpdateActiveInputArea
:
11233 id_key
= Qupdate_active_input_area
;
11234 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11235 names
= names_uaia
;
11236 types
= types_uaia
;
11237 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11238 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11243 case kEventTextInputUnicodeForKeyEvent
:
11245 EventRef kbd_event
;
11246 UInt32 actual_size
, modifiers
;
11248 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11249 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11252 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11254 sizeof (UInt32
), NULL
, &modifiers
);
11255 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11256 /* There're mapped modifier keys. Process it in
11260 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11261 typeUnicodeText
, NULL
, 0, &actual_size
,
11263 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11267 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11268 typeUnicodeText
, NULL
,
11269 sizeof (UniChar
), NULL
, &code
);
11270 if (err
== noErr
&& code
< 0x80)
11272 /* ASCII character. Process it in do_keystroke. */
11273 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11277 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11278 typeUInt32
, NULL
, sizeof (UInt32
),
11280 if (!(err
== noErr
&& key_code
<= 0x7f
11281 && keycode_to_xkeysym_table
[key_code
]))
11284 mac_focus_frame (&one_mac_display_info
);
11286 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11287 read_socket_inev
->code
= code
;
11288 read_socket_inev
->modifiers
=
11289 mac_to_emacs_modifiers (modifiers
);
11290 read_socket_inev
->modifiers
|=
11291 (extra_keyboard_modifiers
11292 & (meta_modifier
| alt_modifier
11293 | hyper_modifier
| super_modifier
));
11294 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11302 /* Non-ASCII keystrokes without mapped modifiers are
11303 processed at the Lisp level. */
11304 id_key
= Qunicode_for_key_event
;
11305 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11306 names
= names_ufke
;
11307 types
= types_ufke
;
11313 case kEventTextInputOffsetToPos
:
11319 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11322 /* Strictly speaking, this is not always correct because
11323 previous events may change some states about display. */
11324 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11326 /* Active input area is displayed around the current point. */
11327 f
= SELECTED_FRAME ();
11328 w
= XWINDOW (f
->selected_window
);
11330 else if (WINDOWP (echo_area_window
))
11332 /* Active input area is displayed in the echo area. */
11333 w
= XWINDOW (echo_area_window
);
11334 f
= WINDOW_XFRAME (w
);
11339 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11340 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11341 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11342 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11343 + FONT_BASE (FRAME_FONT (f
))
11344 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11345 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11346 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11356 if (!NILP (id_key
))
11357 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11363 #endif /* TARGET_API_MAC_CARBON */
11367 install_window_handler (window
)
11370 OSStatus err
= noErr
;
11372 #if TARGET_API_MAC_CARBON
11375 static const EventTypeSpec specs
[] =
11377 /* -- window refresh events -- */
11378 {kEventClassWindow
, kEventWindowUpdate
},
11379 /* -- window state change events -- */
11380 {kEventClassWindow
, kEventWindowShowing
},
11381 {kEventClassWindow
, kEventWindowHiding
},
11382 {kEventClassWindow
, kEventWindowShown
},
11383 {kEventClassWindow
, kEventWindowHidden
},
11384 {kEventClassWindow
, kEventWindowCollapsed
},
11385 {kEventClassWindow
, kEventWindowExpanded
},
11386 {kEventClassWindow
, kEventWindowBoundsChanging
},
11387 {kEventClassWindow
, kEventWindowBoundsChanged
},
11388 /* -- window action events -- */
11389 {kEventClassWindow
, kEventWindowClose
},
11390 {kEventClassWindow
, kEventWindowGetIdealSize
},
11392 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11395 /* -- window focus events -- */
11396 {kEventClassWindow
, kEventWindowFocusAcquired
},
11397 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11400 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11402 if (handle_window_eventUPP
== NULL
)
11403 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11405 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11406 GetEventTypeCount (specs
),
11407 specs
, NULL
, NULL
);
11412 err
= install_drag_handler (window
);
11418 remove_window_handler (window
)
11421 remove_drag_handler (window
);
11424 #if TARGET_API_MAC_CARBON
11426 install_application_handler ()
11428 OSStatus err
= noErr
;
11432 static const EventTypeSpec specs
[] = {
11434 {kEventClassApplication
, kEventAppActivated
},
11435 {kEventClassApplication
, kEventAppDeactivated
},
11439 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11440 (mac_handle_application_event
),
11441 GetEventTypeCount (specs
),
11442 specs
, NULL
, NULL
);
11447 static const EventTypeSpec specs
[] =
11448 {{kEventClassKeyboard
, kEventRawKeyDown
},
11449 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11450 {kEventClassKeyboard
, kEventRawKeyUp
}};
11452 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11453 (mac_handle_keyboard_event
),
11454 GetEventTypeCount (specs
),
11455 specs
, NULL
, NULL
);
11460 static const EventTypeSpec specs
[] =
11461 {{kEventClassCommand
, kEventCommandProcess
}};
11463 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11464 (mac_handle_command_event
),
11465 GetEventTypeCount (specs
),
11466 specs
, NULL
, NULL
);
11471 static const EventTypeSpec specs
[] =
11472 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11474 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11475 (mac_handle_mouse_event
),
11476 GetEventTypeCount (specs
),
11477 specs
, NULL
, NULL
);
11483 static const EventTypeSpec spec
[] =
11484 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11485 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11486 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11488 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11489 (mac_handle_text_input_event
),
11490 GetEventTypeCount (spec
),
11496 err
= install_menu_target_item_handler ();
11500 err
= install_service_handler ();
11508 mac_handle_dm_notification (event
)
11511 mac_screen_config_changed
= 1;
11514 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11516 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11517 CGDirectDisplayID display
;
11518 CGDisplayChangeSummaryFlags flags
;
11521 mac_screen_config_changed
= 1;
11526 init_dm_notification_handler ()
11530 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11531 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11532 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11535 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11538 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11539 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11541 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11542 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11544 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11545 ProcessSerialNumber psn
;
11547 if (handle_dm_notificationUPP
== NULL
)
11548 handle_dm_notificationUPP
=
11549 NewDMNotificationUPP (mac_handle_dm_notification
);
11551 err
= GetCurrentProcess (&psn
);
11553 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11561 mac_get_screen_info (dpyinfo
)
11562 struct mac_display_info
*dpyinfo
;
11565 /* HasDepth returns true if it is possible to have a 32 bit display,
11566 but this may not be what is actually used. Mac OSX can do better. */
11567 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11568 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11571 CGDisplayCount ndisps
;
11572 CGDirectDisplayID
*displays
;
11574 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11577 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11578 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11582 CGRect bounds
= CGRectZero
;
11584 while (ndisps
-- > 0)
11585 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11586 dpyinfo
->height
= CGRectGetHeight (bounds
);
11587 dpyinfo
->width
= CGRectGetWidth (bounds
);
11591 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11592 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11595 #else /* !MAC_OSX */
11597 GDHandle gdh
= GetMainDevice ();
11598 Rect rect
= (**gdh
).gdRect
;
11600 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11601 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11602 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11605 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11606 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11607 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11609 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11610 dpyinfo
->width
= rect
.right
- rect
.left
;
11612 #endif /* !MAC_OSX */
11618 profiler_exit_proc ()
11620 ProfilerDump ("\pEmacs.prof");
11625 /* These few functions implement Emacs as a normal Mac application
11626 (almost): set up the heap and the Toolbox, handle necessary system
11627 events plus a few simple menu events. They also set up Emacs's
11628 access to functions defined in the rest of this file. Emacs uses
11629 function hooks to perform all its terminal I/O. A complete list of
11630 these functions appear in termhooks.h. For what they do, read the
11631 comments there and see also w32term.c and xterm.c. What's
11632 noticeably missing here is the event loop, which is normally
11633 present in most Mac application. After performing the necessary
11634 Mac initializations, main passes off control to emacs_main
11635 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11636 (defined further below) to read input. This is where
11637 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11644 #if __profile__ /* is the profiler on? */
11645 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11650 /* set creator and type for files created by MSL */
11651 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11655 do_init_managers ();
11659 #ifndef USE_LSB_TAG
11660 do_check_ram_size ();
11663 init_emacs_passwd_dir ();
11667 init_coercion_handler ();
11669 initialize_applescript ();
11671 init_apple_event_handler ();
11673 init_dm_notification_handler ();
11679 /* set up argv array from STR# resource */
11680 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
11684 /* free up AppleScript resources on exit */
11685 atexit (terminate_applescript
);
11687 #if __profile__ /* is the profiler on? */
11688 atexit (profiler_exit_proc
);
11691 /* 3rd param "envp" never used in emacs_main */
11692 (void) emacs_main (argc
, argv
, 0);
11695 /* Never reached - real exit in Fkill_emacs */
11700 #if !TARGET_API_MAC_CARBON
11701 static RgnHandle mouse_region
= NULL
;
11704 mac_wait_next_event (er
, sleep_time
, dequeue
)
11709 static EventRecord er_buf
= {nullEvent
};
11710 UInt32 target_tick
, current_tick
;
11711 EventMask event_mask
;
11713 if (mouse_region
== NULL
)
11714 mouse_region
= NewRgn ();
11716 event_mask
= everyEvent
;
11717 if (!mac_ready_for_apple_events
)
11718 event_mask
-= highLevelEventMask
;
11720 current_tick
= TickCount ();
11721 target_tick
= current_tick
+ sleep_time
;
11723 if (er_buf
.what
== nullEvent
)
11724 while (!WaitNextEvent (event_mask
, &er_buf
,
11725 target_tick
- current_tick
, mouse_region
))
11727 current_tick
= TickCount ();
11728 if (target_tick
<= current_tick
)
11734 er_buf
.what
= nullEvent
;
11737 #endif /* not TARGET_API_MAC_CARBON */
11739 #if TARGET_API_MAC_CARBON
11741 mac_post_mouse_moved_event ()
11743 EventRef event
= NULL
;
11746 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
11747 kEventAttributeNone
, &event
);
11752 GetGlobalMouse (&mouse_pos
);
11753 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
11754 sizeof (Point
), &mouse_pos
);
11758 UInt32 modifiers
= GetCurrentKeyModifiers ();
11760 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
11761 sizeof (UInt32
), &modifiers
);
11764 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
11765 kEventPriorityStandard
);
11767 ReleaseEvent (event
);
11773 /* Emacs calls this whenever it wants to read an input event from the
11776 XTread_socket (sd
, expected
, hold_quit
)
11778 struct input_event
*hold_quit
;
11780 struct input_event inev
;
11782 #if TARGET_API_MAC_CARBON
11784 EventTargetRef toolbox_dispatcher
;
11787 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11789 if (interrupt_input_blocked
)
11791 interrupt_input_pending
= 1;
11795 interrupt_input_pending
= 0;
11798 /* So people can tell when we have read the available input. */
11799 input_signal_count
++;
11803 #if TARGET_API_MAC_CARBON
11804 toolbox_dispatcher
= GetEventDispatcherTarget ();
11808 mac_prepare_for_quickdraw (NULL
),
11810 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
11811 kEventRemoveFromQueue
, &eventRef
))
11812 #else /* !TARGET_API_MAC_CARBON */
11813 while (mac_wait_next_event (&er
, 0, true))
11814 #endif /* !TARGET_API_MAC_CARBON */
11818 unsigned long timestamp
;
11821 inev
.kind
= NO_EVENT
;
11824 #if TARGET_API_MAC_CARBON
11825 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
11827 if (!mac_convert_event_ref (eventRef
, &er
))
11829 #else /* !TARGET_API_MAC_CARBON */
11830 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
11831 #endif /* !TARGET_API_MAC_CARBON */
11838 WindowRef window_ptr
;
11839 ControlPartCode part_code
;
11840 int tool_bar_p
= 0;
11842 #if TARGET_API_MAC_CARBON
11845 /* This is needed to send mouse events like aqua window
11846 buttons to the correct handler. */
11847 read_socket_inev
= &inev
;
11848 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11849 read_socket_inev
= NULL
;
11850 if (err
!= eventNotHandledErr
)
11853 last_mouse_glyph_frame
= 0;
11855 if (dpyinfo
->grabbed
&& last_mouse_frame
11856 && FRAME_LIVE_P (last_mouse_frame
))
11858 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
11859 part_code
= inContent
;
11863 part_code
= FindWindow (er
.where
, &window_ptr
);
11864 if (tip_window
&& window_ptr
== tip_window
)
11866 HideWindow (tip_window
);
11867 part_code
= FindWindow (er
.where
, &window_ptr
);
11871 if (er
.what
!= mouseDown
&&
11872 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
11878 f
= mac_focus_frame (dpyinfo
);
11879 saved_menu_event_location
= er
.where
;
11880 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
11881 XSETFRAME (inev
.frame_or_window
, f
);
11886 #if TARGET_API_MAC_CARBON
11887 FrontNonFloatingWindow ()
11892 || (mac_window_to_frame (window_ptr
)
11893 != dpyinfo
->x_focus_frame
))
11894 SelectWindow (window_ptr
);
11897 ControlPartCode control_part_code
;
11901 ControlKind control_kind
;
11904 f
= mac_window_to_frame (window_ptr
);
11905 /* convert to local coordinates of new window */
11906 mouse_loc
.h
= (er
.where
.h
11908 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
11909 mouse_loc
.v
= (er
.where
.v
11911 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
11912 #if TARGET_API_MAC_CARBON
11913 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
11914 &control_part_code
);
11917 GetControlKind (ch
, &control_kind
);
11920 control_part_code
= FindControl (mouse_loc
, window_ptr
,
11924 #if TARGET_API_MAC_CARBON
11925 inev
.code
= mac_get_mouse_btn (eventRef
);
11926 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
11928 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
11929 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
11931 XSETINT (inev
.x
, mouse_loc
.h
);
11932 XSETINT (inev
.y
, mouse_loc
.v
);
11934 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
11936 #ifndef USE_TOOLKIT_SCROLL_BARS
11937 /* control_part_code becomes kControlNoPart if
11938 a progress indicator is clicked. */
11939 && control_part_code
!= kControlNoPart
11940 #else /* USE_TOOLKIT_SCROLL_BARS */
11942 && control_kind
.kind
== kControlKindScrollBar
11943 #endif /* MAC_OSX */
11944 #endif /* USE_TOOLKIT_SCROLL_BARS */
11947 struct scroll_bar
*bar
;
11949 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11951 bar
= tracked_scroll_bar
;
11952 #ifndef USE_TOOLKIT_SCROLL_BARS
11953 control_part_code
= kControlIndicatorPart
;
11957 bar
= (struct scroll_bar
*) GetControlReference (ch
);
11958 #ifdef USE_TOOLKIT_SCROLL_BARS
11959 /* Make the "Ctrl-Mouse-2 splits window" work
11960 for toolkit scroll bars. */
11961 if (inev
.modifiers
& ctrl_modifier
)
11962 x_scroll_bar_handle_click (bar
, control_part_code
,
11964 else if (er
.what
== mouseDown
)
11965 x_scroll_bar_handle_press (bar
, control_part_code
,
11968 x_scroll_bar_handle_release (bar
, &inev
);
11969 #else /* not USE_TOOLKIT_SCROLL_BARS */
11970 x_scroll_bar_handle_click (bar
, control_part_code
,
11972 if (er
.what
== mouseDown
11973 && control_part_code
== kControlIndicatorPart
)
11974 tracked_scroll_bar
= bar
;
11976 tracked_scroll_bar
= NULL
;
11977 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11981 Lisp_Object window
;
11982 int x
= mouse_loc
.h
;
11983 int y
= mouse_loc
.v
;
11985 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
11986 if (EQ (window
, f
->tool_bar_window
))
11988 if (er
.what
== mouseDown
)
11989 handle_tool_bar_click (f
, x
, y
, 1, 0);
11991 handle_tool_bar_click (f
, x
, y
, 0,
11997 XSETFRAME (inev
.frame_or_window
, f
);
11998 inev
.kind
= MOUSE_CLICK_EVENT
;
12002 if (er
.what
== mouseDown
)
12004 dpyinfo
->grabbed
|= (1 << inev
.code
);
12005 last_mouse_frame
= f
;
12008 last_tool_bar_item
= -1;
12012 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
12013 /* If a button is released though it was not
12014 previously pressed, that would be because
12015 of multi-button emulation. */
12016 dpyinfo
->grabbed
= 0;
12018 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
12021 /* Ignore any mouse motion that happened before
12022 this event; any subsequent mouse-movement Emacs
12023 events should reflect only motion after the
12026 f
->mouse_moved
= 0;
12028 #ifdef USE_TOOLKIT_SCROLL_BARS
12029 if (inev
.kind
== MOUSE_CLICK_EVENT
12030 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12031 && (inev
.modifiers
& ctrl_modifier
)))
12036 inev
.modifiers
|= down_modifier
;
12039 inev
.modifiers
|= up_modifier
;
12046 #if TARGET_API_MAC_CARBON
12048 if (IsWindowPathSelectClick (window_ptr
, &er
))
12050 WindowPathSelect (window_ptr
, NULL
, NULL
);
12053 if (part_code
== inProxyIcon
12054 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12055 != errUserWantsToDragWindow
))
12057 DragWindow (window_ptr
, er
.where
, NULL
);
12058 #else /* not TARGET_API_MAC_CARBON */
12059 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12060 /* Update the frame parameters. */
12062 struct frame
*f
= mac_window_to_frame (window_ptr
);
12064 if (f
&& !f
->async_iconified
)
12065 mac_handle_origin_change (f
);
12067 #endif /* not TARGET_API_MAC_CARBON */
12071 if (TrackGoAway (window_ptr
, er
.where
))
12073 inev
.kind
= DELETE_WINDOW_EVENT
;
12074 XSETFRAME (inev
.frame_or_window
,
12075 mac_window_to_frame (window_ptr
));
12079 /* window resize handling added --ben */
12081 do_grow_window (window_ptr
, &er
);
12084 /* window zoom handling added --ben */
12087 if (TrackBox (window_ptr
, er
.where
, part_code
))
12088 do_zoom_window (window_ptr
, part_code
);
12091 #if USE_MAC_TOOLBAR
12097 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12099 /* This doesn't work on Mac OS X 10.2. */
12101 HIViewClick (ch
, eventRef
);
12104 #endif /* USE_MAC_TOOLBAR */
12112 #if !TARGET_API_MAC_CARBON
12114 do_window_update ((WindowRef
) er
.message
);
12119 switch ((er
.message
>> 24) & 0x000000FF)
12121 case mouseMovedMessage
:
12122 #if !TARGET_API_MAC_CARBON
12123 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12124 er
.where
.h
+ 1, er
.where
.v
+ 1);
12126 previous_help_echo_string
= help_echo_string
;
12127 help_echo_string
= Qnil
;
12129 if (dpyinfo
->grabbed
&& last_mouse_frame
12130 && FRAME_LIVE_P (last_mouse_frame
))
12131 f
= last_mouse_frame
;
12133 f
= dpyinfo
->x_focus_frame
;
12135 if (dpyinfo
->mouse_face_hidden
)
12137 dpyinfo
->mouse_face_hidden
= 0;
12138 clear_mouse_face (dpyinfo
);
12143 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12146 mouse_pos
.h
= (er
.where
.h
12148 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12149 mouse_pos
.v
= (er
.where
.v
12151 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12152 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12153 #ifdef USE_TOOLKIT_SCROLL_BARS
12154 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12156 #else /* not USE_TOOLKIT_SCROLL_BARS */
12157 x_scroll_bar_note_movement (tracked_scroll_bar
,
12159 - XINT (tracked_scroll_bar
->top
),
12160 er
.when
* (1000 / 60));
12161 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12164 /* Generate SELECT_WINDOW_EVENTs when needed. */
12165 if (!NILP (Vmouse_autoselect_window
))
12167 Lisp_Object window
;
12169 window
= window_from_coordinates (f
,
12174 /* Window will be selected only when it is
12175 not selected now and last mouse movement
12176 event was not in it. Minibuffer window
12177 will be selected only when it is active. */
12178 if (WINDOWP (window
)
12179 && !EQ (window
, last_window
)
12180 && !EQ (window
, selected_window
)
12181 /* For click-to-focus window managers
12182 create event iff we don't leave the
12184 && (focus_follows_mouse
12185 || (EQ (XWINDOW (window
)->frame
,
12186 XWINDOW (selected_window
)->frame
))))
12188 inev
.kind
= SELECT_WINDOW_EVENT
;
12189 inev
.frame_or_window
= window
;
12192 last_window
=window
;
12194 if (!note_mouse_movement (f
, &mouse_pos
))
12195 help_echo_string
= previous_help_echo_string
;
12196 #if USE_MAC_TOOLBAR
12198 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12203 /* If the contents of the global variable
12204 help_echo_string has changed, generate a
12206 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12217 WindowRef window_ptr
= (WindowRef
) er
.message
;
12219 ControlRef root_control
;
12221 if (window_ptr
== tip_window
)
12223 HideWindow (tip_window
);
12227 if (!is_emacs_window (window_ptr
))
12230 f
= mac_window_to_frame (window_ptr
);
12232 if ((er
.modifiers
& activeFlag
) != 0)
12234 /* A window has been activated */
12237 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12239 ActivateControl (root_control
);
12241 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12243 mouse_loc
.h
= (er
.where
.h
12245 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12246 mouse_loc
.v
= (er
.where
.v
12248 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12249 /* Window-activated event counts as mouse movement,
12250 so update things that depend on mouse position. */
12251 note_mouse_movement (f
, &mouse_loc
);
12255 /* A window has been deactivated */
12256 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
12258 DeactivateControl (root_control
);
12260 #ifdef USE_TOOLKIT_SCROLL_BARS
12261 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12263 struct input_event event
;
12265 EVENT_INIT (event
);
12266 event
.kind
= NO_EVENT
;
12267 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12268 if (event
.kind
!= NO_EVENT
)
12270 event
.timestamp
= timestamp
;
12271 kbd_buffer_store_event_hold (&event
, hold_quit
);
12276 dpyinfo
->grabbed
= 0;
12278 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12280 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12282 /* If we move outside the frame, then we're
12283 certainly no longer on any text in the
12285 clear_mouse_face (dpyinfo
);
12286 dpyinfo
->mouse_face_mouse_frame
= 0;
12289 /* Generate a nil HELP_EVENT to cancel a help-echo.
12290 Do it only if there's something to cancel.
12291 Otherwise, the startup message is cleared when the
12292 mouse leaves the frame. */
12293 if (any_help_event_p
)
12304 f
= mac_focus_frame (dpyinfo
);
12305 XSETFRAME (inev
.frame_or_window
, f
);
12307 /* If mouse-highlight is an integer, input clears out mouse
12309 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12310 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12312 clear_mouse_face (dpyinfo
);
12313 dpyinfo
->mouse_face_hidden
= 1;
12317 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
12320 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
12322 sizeof (UInt32
), NULL
, &modifiers
);
12324 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
12326 #if TARGET_API_MAC_CARBON
12327 if (!(mapped_modifiers
12328 & ~(mac_pass_command_to_system
? cmdKey
: 0)
12329 & ~(mac_pass_control_to_system
? controlKey
: 0)))
12333 if (er
.what
!= keyUp
)
12334 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12335 (er
.message
& keyCodeMask
) >> 8,
12336 modifiers
, timestamp
, &inev
);
12340 case kHighLevelEvent
:
12341 AEProcessAppleEvent (&er
);
12346 #if TARGET_API_MAC_CARBON
12350 read_socket_inev
= &inev
;
12351 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12352 read_socket_inev
= NULL
;
12357 #if TARGET_API_MAC_CARBON
12358 ReleaseEvent (eventRef
);
12361 if (inev
.kind
!= NO_EVENT
)
12363 inev
.timestamp
= timestamp
;
12364 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12369 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12374 XSETFRAME (frame
, f
);
12380 any_help_event_p
= 1;
12381 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12382 help_echo_object
, help_echo_pos
);
12386 help_echo_string
= Qnil
;
12387 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12393 /* If the focus was just given to an autoraising frame,
12395 /* ??? This ought to be able to handle more than one such frame. */
12396 if (pending_autoraise_frame
)
12398 x_raise_frame (pending_autoraise_frame
);
12399 pending_autoraise_frame
= 0;
12402 if (mac_screen_config_changed
)
12404 mac_get_screen_info (dpyinfo
);
12405 mac_screen_config_changed
= 0;
12408 #if !TARGET_API_MAC_CARBON
12409 /* Check which frames are still visible. We do this here because
12410 there doesn't seem to be any direct notification from the Window
12411 Manager that the visibility of a window has changed (at least,
12412 not in all cases). */
12414 Lisp_Object tail
, frame
;
12416 FOR_EACH_FRAME (tail
, frame
)
12418 struct frame
*f
= XFRAME (frame
);
12420 /* The tooltip has been drawn already. Avoid the
12421 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12422 if (EQ (frame
, tip_frame
))
12425 if (FRAME_MAC_P (f
))
12426 mac_handle_visibility_change (f
);
12437 /* Need to override CodeWarrior's input function so no conversion is
12438 done on newlines Otherwise compiled functions in .elc files will be
12439 read incorrectly. Defined in ...:MSL C:MSL
12440 Common:Source:buffer_io.c. */
12443 __convert_to_newlines (unsigned char * p
, size_t * n
)
12445 #pragma unused(p,n)
12449 __convert_from_newlines (unsigned char * p
, size_t * n
)
12451 #pragma unused(p,n)
12457 make_mac_terminal_frame (struct frame
*f
)
12462 XSETFRAME (frame
, f
);
12464 f
->output_method
= output_mac
;
12465 f
->output_data
.mac
= (struct mac_output
*)
12466 xmalloc (sizeof (struct mac_output
));
12467 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12469 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12471 FRAME_COLS (f
) = 96;
12472 FRAME_LINES (f
) = 4;
12474 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12475 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12477 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12479 f
->output_data
.mac
->cursor_pixel
= 0;
12480 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12481 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12482 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12484 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12485 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12486 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12487 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12488 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12489 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12491 FRAME_FONTSET (f
) = -1;
12492 f
->output_data
.mac
->explicit_parent
= 0;
12495 f
->border_width
= 0;
12497 f
->internal_border_width
= 0;
12502 f
->new_text_cols
= 0;
12503 f
->new_text_lines
= 0;
12505 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12506 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12507 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12511 if (!(FRAME_MAC_WINDOW (f
) =
12512 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12513 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12515 /* so that update events can find this mac_output struct */
12516 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12522 /* Need to be initialized for unshow_buffer in window.c. */
12523 selected_window
= f
->selected_window
;
12525 Fmodify_frame_parameters (frame
,
12526 Fcons (Fcons (Qfont
,
12527 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12528 Fmodify_frame_parameters (frame
,
12529 Fcons (Fcons (Qforeground_color
,
12530 build_string ("black")), Qnil
));
12531 Fmodify_frame_parameters (frame
,
12532 Fcons (Fcons (Qbackground_color
,
12533 build_string ("white")), Qnil
));
12538 /***********************************************************************
12540 ***********************************************************************/
12542 static int mac_initialized
= 0;
12545 mac_make_rdb (xrm_option
)
12546 const char *xrm_option
;
12548 XrmDatabase database
;
12550 database
= xrm_get_preference_database (NULL
);
12552 xrm_merge_string_database (database
, xrm_option
);
12557 struct mac_display_info
*
12558 mac_term_init (display_name
, xrm_option
, resource_name
)
12559 Lisp_Object display_name
;
12561 char *resource_name
;
12563 struct mac_display_info
*dpyinfo
;
12564 struct terminal
*terminal
;
12568 if (!mac_initialized
)
12571 mac_initialized
= 1;
12574 if (x_display_list
)
12575 error ("Sorry, this version can only handle one display");
12577 dpyinfo
= &one_mac_display_info
;
12578 bzero (dpyinfo
, sizeof (*dpyinfo
));
12580 terminal
= mac_create_terminal (dpyinfo
);
12582 /* Set the name of the terminal. */
12583 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
12584 strncpy (terminal
->name
, SDATA (display_name
), SBYTES (display_name
));
12585 terminal
->name
[SBYTES (display_name
)] = 0;
12588 dpyinfo
->mac_id_name
12589 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12590 + SCHARS (Vsystem_name
)
12592 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12593 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12595 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12596 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12599 dpyinfo
->reference_count
= 0;
12600 dpyinfo
->resx
= 72.0;
12601 dpyinfo
->resy
= 72.0;
12603 mac_get_screen_info (dpyinfo
);
12605 dpyinfo
->grabbed
= 0;
12606 dpyinfo
->root_window
= NULL
;
12607 dpyinfo
->image_cache
= make_image_cache ();
12609 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12610 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12611 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12612 dpyinfo
->mouse_face_window
= Qnil
;
12613 dpyinfo
->mouse_face_overlay
= Qnil
;
12614 dpyinfo
->mouse_face_hidden
= 0;
12616 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12618 /* Put this display on the chain. */
12619 dpyinfo
->next
= x_display_list
;
12620 x_display_list
= dpyinfo
;
12622 /* Put it on x_display_name_list. */
12623 x_display_name_list
= Fcons (Fcons (display_name
,
12624 Fcons (Qnil
, dpyinfo
->xrdb
)),
12625 x_display_name_list
);
12626 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12628 /* FIXME: Untested.
12629 Add the default keyboard. */
12630 add_keyboard_wait_descriptor (0);
12633 mac_init_fringe (terminal
->rif
);
12641 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12644 x_delete_display (dpyinfo
)
12645 struct mac_display_info
*dpyinfo
;
12649 /* Discard this display from x_display_name_list and x_display_list.
12650 We can't use Fdelq because that can quit. */
12651 if (! NILP (x_display_name_list
)
12652 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12653 x_display_name_list
= XCDR (x_display_name_list
);
12658 tail
= x_display_name_list
;
12659 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12661 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
12663 XSETCDR (tail
, XCDR (XCDR (tail
)));
12666 tail
= XCDR (tail
);
12670 if (x_display_list
== dpyinfo
)
12671 x_display_list
= dpyinfo
->next
;
12674 struct x_display_info
*tail
;
12676 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12677 if (tail
->next
== dpyinfo
)
12678 tail
->next
= tail
->next
->next
;
12681 /* Free the font names in the font table. */
12682 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12683 if (dpyinfo
->font_table
[i
].name
)
12685 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
12686 xfree (dpyinfo
->font_table
[i
].full_name
);
12687 xfree (dpyinfo
->font_table
[i
].name
);
12690 if (dpyinfo
->font_table
)
12692 if (dpyinfo
->font_table
->font_encoder
)
12693 xfree (dpyinfo
->font_table
->font_encoder
);
12694 xfree (dpyinfo
->font_table
);
12696 if (dpyinfo
->mac_id_name
)
12697 xfree (dpyinfo
->mac_id_name
);
12699 if (x_display_list
== 0)
12701 mac_clear_font_name_table ();
12702 bzero (dpyinfo
, sizeof (*dpyinfo
));
12713 MenuItemIndex menu_index
;
12715 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
12716 &menu
, &menu_index
);
12718 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12719 EnableMenuCommand (NULL
, kHICommandPreferences
);
12720 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
12721 &menu
, &menu_index
);
12724 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12725 InsertMenuItemTextWithCFString (menu
, NULL
,
12726 0, kMenuItemAttrSeparator
, 0);
12727 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
12728 0, 0, kHICommandAbout
);
12730 #else /* !MAC_OSX */
12731 #if TARGET_API_MAC_CARBON
12732 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
12742 static InterfaceTypeList types
= {kUnicodeDocument
};
12744 static InterfaceTypeList types
= {kTextService
};
12747 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
12748 &tsm_document_id
, 0);
12752 /* Set up use of X before we make the first connection. */
12754 extern frame_parm_handler mac_frame_parm_handlers
[];
12756 static struct redisplay_interface x_redisplay_interface
=
12758 mac_frame_parm_handlers
,
12762 x_clear_end_of_line
,
12764 x_after_update_window_line
,
12765 x_update_window_begin
,
12766 x_update_window_end
,
12770 mac_flush_display_optional
,
12772 0, /* flush_display_optional */
12774 x_clear_window_mouse_face
,
12775 x_get_glyph_overhangs
,
12776 x_fix_overlapping_area
,
12777 x_draw_fringe_bitmap
,
12779 mac_define_fringe_bitmap
,
12780 mac_destroy_fringe_bitmap
,
12782 0, /* define_fringe_bitmap */
12783 0, /* destroy_fringe_bitmap */
12785 mac_per_char_metric
,
12787 mac_compute_glyph_string_overhangs
,
12788 x_draw_glyph_string
,
12789 mac_define_frame_cursor
,
12790 mac_clear_frame_area
,
12791 mac_draw_window_cursor
,
12792 mac_draw_vertical_window_border
,
12793 mac_shift_glyphs_for_insert
12796 static struct terminal
*
12797 mac_create_terminal (struct mac_display_info
*dpyinfo
)
12799 struct terminal
*terminal
;
12801 terminal
= create_terminal ();
12803 terminal
->type
= output_mac
;
12804 terminal
->display_info
.mac
= dpyinfo
;
12805 dpyinfo
->terminal
= terminal
;
12807 terminal
->clear_frame_hook
= x_clear_frame
;
12808 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
12809 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
12810 terminal
->ring_bell_hook
= XTring_bell
;
12811 terminal
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
12812 terminal
->set_terminal_modes_hook
= XTset_terminal_modes
;
12813 terminal
->update_begin_hook
= x_update_begin
;
12814 terminal
->update_end_hook
= x_update_end
;
12815 terminal
->set_terminal_window_hook
= XTset_terminal_window
;
12816 terminal
->read_socket_hook
= XTread_socket
;
12817 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
12818 terminal
->mouse_position_hook
= XTmouse_position
;
12819 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
12820 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
12821 /* terminal->fullscreen_hook = XTfullscreen_hook; */
12822 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12823 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12824 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12825 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12826 terminal
->delete_frame_hook
= x_destroy_window
;
12827 /* terminal->delete_terminal_hook = x_delete_terminal; */
12829 terminal
->rif
= &x_redisplay_interface
;
12831 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
12832 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
12833 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
12834 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
12835 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
12839 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
12840 terminal
->char_ins_del_ok
= 1;
12841 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
12842 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
12843 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
12848 /* FIXME: This keyboard setup is 100% untested, just copied from
12849 w32_create_terminal in order to set window-system now that it's
12850 a keyboard object. */
12851 /* We don't yet support separate terminals on Mac, so don't try to share
12852 keyboards between virtual terminals that are on the same physical
12853 terminal like X does. */
12854 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
12855 init_kboard (terminal
->kboard
);
12856 terminal
->kboard
->Vwindow_system
= intern ("mac");
12857 terminal
->kboard
->next_kboard
= all_kboards
;
12858 all_kboards
= terminal
->kboard
;
12859 /* Don't let the initial kboard remain current longer than necessary.
12860 That would cause problems if a file loaded on startup tries to
12861 prompt in the mini-buffer. */
12862 if (current_kboard
== initial_kboard
)
12863 current_kboard
= terminal
->kboard
;
12864 terminal
->kboard
->reference_count
++;
12875 last_tool_bar_item
= -1;
12876 any_help_event_p
= 0;
12878 /* Try to use interrupt input; if we can't, then start polling. */
12879 Fset_input_interrupt_mode (Qt
);
12883 #if TARGET_API_MAC_CARBON
12885 install_application_handler ();
12894 init_coercion_handler ();
12896 init_apple_event_handler ();
12898 init_dm_notification_handler ();
12900 if (!inhibit_window_system
)
12902 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
12904 SetFrontProcess (&psn
);
12922 staticpro (&x_error_message_string
);
12923 x_error_message_string
= Qnil
;
12926 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
12927 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
12928 Qalt
= intern ("alt"); staticpro (&Qalt
);
12929 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
12930 Qsuper
= intern ("super"); staticpro (&Qsuper
);
12931 Qmodifier_value
= intern ("modifier-value");
12932 staticpro (&Qmodifier_value
);
12934 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
12935 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12936 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12937 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12938 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12940 #if TARGET_API_MAC_CARBON
12941 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
12943 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
12944 staticpro (&Qtoolbar_switch_mode
);
12945 #if USE_MAC_FONT_PANEL
12946 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12947 Qselection
= intern ("selection"); staticpro (&Qselection
);
12950 Qservice
= intern ("service"); staticpro (&Qservice
);
12951 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12952 Qperform
= intern ("perform"); staticpro (&Qperform
);
12955 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12956 Qupdate_active_input_area
= intern ("update-active-input-area");
12957 staticpro (&Qupdate_active_input_area
);
12958 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12959 staticpro (&Qunicode_for_key_event
);
12964 Fprovide (intern ("mac-carbon"), Qnil
);
12967 staticpro (&Qreverse
);
12968 Qreverse
= intern ("reverse");
12970 staticpro (&x_display_name_list
);
12971 x_display_name_list
= Qnil
;
12973 staticpro (&last_mouse_scroll_bar
);
12974 last_mouse_scroll_bar
= Qnil
;
12976 staticpro (&fm_font_family_alist
);
12977 fm_font_family_alist
= Qnil
;
12980 staticpro (&atsu_font_id_hash
);
12981 atsu_font_id_hash
= Qnil
;
12983 staticpro (&fm_style_face_attributes_alist
);
12984 fm_style_face_attributes_alist
= Qnil
;
12988 staticpro (&saved_ts_script_language_on_focus
);
12989 saved_ts_script_language_on_focus
= Qnil
;
12992 /* We don't yet support this, but defining this here avoids whining
12993 from cus-start.el and other places, like "M-x set-variable". */
12994 DEFVAR_BOOL ("x-use-underline-position-properties",
12995 &x_use_underline_position_properties
,
12996 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12997 A value of nil means ignore them. If you encounter fonts with bogus
12998 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12999 to 4.1, set this to nil.
13001 NOTE: Not supported on Mac yet. */);
13002 x_use_underline_position_properties
= 0;
13004 DEFVAR_BOOL ("x-underline-at-descent-line",
13005 &x_underline_at_descent_line
,
13006 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
13007 A value of nil means to draw the underline according to the value of the
13008 variable `x-use-underline-position-properties', which is usually at the
13009 baseline level. The default value is nil. */);
13010 x_underline_at_descent_line
= 0;
13012 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
13013 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
13014 #ifdef USE_TOOLKIT_SCROLL_BARS
13015 Vx_toolkit_scroll_bars
= Qt
;
13017 Vx_toolkit_scroll_bars
= Qnil
;
13020 staticpro (&last_mouse_motion_frame
);
13021 last_mouse_motion_frame
= Qnil
;
13023 /* Variables to configure modifier key assignment. */
13025 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
13026 doc
: /* *Modifier key assumed when the Mac control key is pressed.
13027 The value can be `control', `meta', `alt', `hyper', or `super' for the
13028 respective modifier. The default is `control'. */);
13029 Vmac_control_modifier
= Qcontrol
;
13031 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
13032 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
13033 The value can be `control', `meta', `alt', `hyper', or `super' for the
13034 respective modifier. If the value is nil then the key will act as the
13035 normal Mac control modifier, and the option key can be used to compose
13036 characters depending on the chosen Mac keyboard setting. */);
13037 Vmac_option_modifier
= Qnil
;
13039 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
13040 doc
: /* *Modifier key assumed when the Mac command key is pressed.
13041 The value can be `control', `meta', `alt', `hyper', or `super' for the
13042 respective modifier. The default is `meta'. */);
13043 Vmac_command_modifier
= Qmeta
;
13045 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
13046 doc
: /* *Modifier key assumed when the Mac function key is pressed.
13047 The value can be `control', `meta', `alt', `hyper', or `super' for the
13048 respective modifier. Note that remapping the function key may lead to
13049 unexpected results for some keys on non-US/GB keyboards. */);
13050 Vmac_function_modifier
= Qnil
;
13052 DEFVAR_LISP ("mac-emulate-three-button-mouse",
13053 &Vmac_emulate_three_button_mouse
,
13054 doc
: /* *Specify a way of three button mouse emulation.
13055 The value can be nil, t, or the symbol `reverse'.
13056 A value of nil means that no emulation should be done and the modifiers
13057 should be placed on the mouse-1 event.
13058 t means that when the option-key is held down while pressing the mouse
13059 button, the click will register as mouse-2 and while the command-key
13060 is held down, the click will register as mouse-3.
13061 The symbol `reverse' means that the option-key will register for
13062 mouse-3 and the command-key will register for mouse-2. */);
13063 Vmac_emulate_three_button_mouse
= Qnil
;
13065 #if TARGET_API_MAC_CARBON
13066 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
13067 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
13068 Otherwise, the right click will be treated as mouse-2 and the wheel
13069 button will be mouse-3. */);
13070 mac_wheel_button_is_mouse_2
= 1;
13072 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
13073 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
13074 mac_pass_command_to_system
= 1;
13076 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
13077 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13078 mac_pass_control_to_system
= 1;
13082 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
13083 doc
: /* *If non-nil, allow anti-aliasing.
13084 The text will be rendered using Core Graphics text rendering which
13085 may anti-alias the text. */);
13087 mac_use_core_graphics
= 1;
13089 mac_use_core_graphics
= 0;
13092 /* Register an entry for `mac-roman' so that it can be used when
13093 creating the terminal frame on Mac OS 9 before loading
13094 term/mac-win.elc. */
13095 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
13096 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
13097 Each entry should be of the form:
13099 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13101 where CHARSET-NAME is a string used in font names to identify the
13102 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13103 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13104 Vmac_charset_info_alist
=
13105 Fcons (list3 (build_string ("mac-roman"),
13106 make_number (smRoman
), Qnil
), Qnil
);
13109 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13110 doc
: /* Overlay used to display Mac TSM active input area. */);
13111 Vmac_ts_active_input_overlay
= Qnil
;
13113 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13114 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13115 If the value is t, the input script and language are restored to those
13116 used in the last focus frame. If the value is a pair of integers, the
13117 input script and language codes, which are defined in the Script
13118 Manager, are set to its car and cdr parts, respectively. Otherwise,
13119 Emacs doesn't set them and thus follows the system default behavior. */);
13120 Vmac_ts_script_language_on_focus
= Qnil
;
13124 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13125 (do not change this comment) */