1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
86 /* Non-nil means Emacs uses toolkit scroll bars. */
88 Lisp_Object Vx_toolkit_scroll_bars
;
90 /* If non-zero, the text will be rendered using Core Graphics text
91 rendering which may anti-alias the text. */
92 int mac_use_core_graphics
;
95 /* Non-zero means that a HELP_EVENT has been generated since Emacs
98 static int any_help_event_p
;
100 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
101 static Lisp_Object last_window
;
103 /* Non-zero means make use of UNDERLINE_POSITION font properties.
104 (Not yet supported.) */
105 int x_use_underline_position_properties
;
107 /* Non-zero means to draw the underline at the same place as the descent line. */
109 int x_underline_at_descent_line
;
111 /* This is a chain of structures for all the X displays currently in
114 struct x_display_info
*x_display_list
;
116 /* This is a list of cons cells, each of the form (NAME
117 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
118 x_display_list and in the same order. NAME is the name of the
119 frame. FONT-LIST-CACHE records previous values returned by
120 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
121 equivalent, which is implemented with a Lisp object, for the
124 Lisp_Object x_display_name_list
;
126 /* This is display since Mac does not support multiple ones. */
127 struct mac_display_info one_mac_display_info
;
129 /* Frame being updated by update_frame. This is declared in term.c.
130 This is set by update_begin and looked at by all the XT functions.
131 It is zero while not inside an update. In that case, the XT
132 functions assume that `selected_frame' is the frame to apply to. */
134 extern struct frame
*updating_frame
;
136 /* This is a frame waiting to be auto-raised, within XTread_socket. */
138 struct frame
*pending_autoraise_frame
;
142 Formerly, we used PointerMotionHintMask (in standard_event_mask)
143 so that we would have to call XQueryPointer after each MotionNotify
144 event to ask for another such event. However, this made mouse tracking
145 slow, and there was a bug that made it eventually stop.
147 Simply asking for MotionNotify all the time seems to work better.
149 In order to avoid asking for motion events and then throwing most
150 of them away or busy-polling the server for mouse positions, we ask
151 the server for pointer motion hints. This means that we get only
152 one event per group of mouse movements. "Groups" are delimited by
153 other kinds of events (focus changes and button clicks, for
154 example), or by XQueryPointer calls; when one of these happens, we
155 get another MotionNotify event the next time the mouse moves. This
156 is at least as efficient as getting motion events when mouse
157 tracking is on, and I suspect only negligibly worse when tracking
160 /* Where the mouse was last time we reported a mouse event. */
162 static Rect last_mouse_glyph
;
163 static FRAME_PTR last_mouse_glyph_frame
;
165 /* The scroll bar in which the last X motion event occurred.
167 If the last X motion event occurred in a scroll bar, we set this so
168 XTmouse_position can know whether to report a scroll bar motion or
171 If the last X motion event didn't occur in a scroll bar, we set
172 this to Qnil, to tell XTmouse_position to return an ordinary motion
175 static Lisp_Object last_mouse_scroll_bar
;
177 /* This is a hack. We would really prefer that XTmouse_position would
178 return the time associated with the position it returns, but there
179 doesn't seem to be any way to wrest the time-stamp from the server
180 along with the position query. So, we just keep track of the time
181 of the last movement we received, and return that in hopes that
182 it's somewhat accurate. */
184 static Time last_mouse_movement_time
;
186 struct scroll_bar
*tracked_scroll_bar
= NULL
;
188 /* Incremented by XTread_socket whenever it really tries to read
192 static int volatile input_signal_count
;
194 static int input_signal_count
;
197 extern Lisp_Object Vsystem_name
;
199 extern Lisp_Object Qeql
;
201 /* A mask of extra modifier bits to put into every keyboard char. */
203 extern EMACS_INT extra_keyboard_modifiers
;
205 /* The keysyms to use for the various modifiers. */
207 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
209 extern int inhibit_window_system
;
211 #if __MRC__ && !TARGET_API_MAC_CARBON
212 QDGlobals qd
; /* QuickDraw global information structure. */
215 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
217 struct mac_display_info
*mac_display_info_for_display (Display
*);
218 static void x_update_window_end
P_ ((struct window
*, int, int));
219 int x_catch_errors
P_ ((Display
*));
220 void x_uncatch_errors
P_ ((Display
*, int));
221 void x_lower_frame
P_ ((struct frame
*));
222 void x_scroll_bar_clear
P_ ((struct frame
*));
223 int x_had_errors_p
P_ ((Display
*));
224 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
225 void x_raise_frame
P_ ((struct frame
*));
226 void x_set_window_size
P_ ((struct frame
*, int, int, int));
227 void x_wm_set_window_state
P_ ((struct frame
*, int));
228 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
229 static void mac_initialize
P_ ((void));
230 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
231 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
232 static void x_update_end
P_ ((struct frame
*));
233 static void XTframe_up_to_date
P_ ((struct frame
*));
234 static void XTset_terminal_modes
P_ ((struct terminal
*));
235 static void XTreset_terminal_modes
P_ ((struct terminal
*));
236 static void x_clear_frame
P_ ((struct frame
*));
237 static void frame_highlight
P_ ((struct frame
*));
238 static void frame_unhighlight
P_ ((struct frame
*));
239 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
240 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
241 struct frame
*, struct input_event
*));
242 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
244 struct input_event
*));
245 static void XTframe_rehighlight
P_ ((struct frame
*));
246 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
247 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
248 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
249 enum text_cursor_kinds
));
251 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
252 static void x_flush
P_ ((struct frame
*f
));
253 static void x_update_begin
P_ ((struct frame
*));
254 static void x_update_window_begin
P_ ((struct window
*));
255 static void x_after_update_window_line
P_ ((struct glyph_row
*));
256 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
257 enum scroll_bar_part
*,
258 Lisp_Object
*, Lisp_Object
*,
261 static int is_emacs_window
P_ ((WindowRef
));
262 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
263 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
264 static struct terminal
*mac_create_terminal
P_ ((struct mac_display_info
*dpyinfo
));
267 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
268 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
269 #define GC_FONT(gc) ((gc)->xgcv.font)
270 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
272 #define CG_SET_FILL_COLOR(context, color) \
273 CGContextSetRGBFillColor (context, \
274 RED_FROM_ULONG (color) / 255.0f, \
275 GREEN_FROM_ULONG (color) / 255.0f, \
276 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
277 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
278 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
279 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
281 if (CGColorGetTypeID != NULL) \
282 CGContextSetFillColorWithColor (context, cg_color); \
284 CG_SET_FILL_COLOR (context, color); \
287 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
288 CGContextSetFillColorWithColor (context, cg_color)
291 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
292 CG_SET_FILL_COLOR (context, color)
294 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
295 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
297 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
298 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
302 #define CG_SET_STROKE_COLOR(context, color) \
303 CGContextSetRGBStrokeColor (context, \
304 RED_FROM_ULONG (color) / 255.0f, \
305 GREEN_FROM_ULONG (color) / 255.0f, \
306 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
307 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
308 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
309 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
311 if (CGColorGetTypeID != NULL) \
312 CGContextSetStrokeColorWithColor (context, cg_color); \
314 CG_SET_STROKE_COLOR (context, color); \
317 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
318 CGContextSetStrokeColorWithColor (context, cg_color)
321 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
322 CG_SET_STROKE_COLOR (context, color)
324 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
325 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
329 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
331 /* Fringe bitmaps. */
333 static int max_fringe_bmp
= 0;
334 static CGImageRef
*fringe_bmp
= 0;
336 static CGColorSpaceRef mac_cg_color_space_rgb
;
337 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
338 static CGColorRef mac_cg_color_black
;
344 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
345 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
346 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
347 /* Don't check the availability of CGColorCreate; this symbol is
348 defined even in Mac OS X 10.1. */
349 if (CGColorGetTypeID
!= NULL
)
352 float rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
354 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
360 mac_begin_cg_clip (f
, gc
)
364 CGContextRef context
= FRAME_CG_CONTEXT (f
);
368 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
369 FRAME_CG_CONTEXT (f
) = context
;
372 CGContextSaveGState (context
);
373 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
374 CGContextScaleCTM (context
, 1, -1);
375 if (gc
&& gc
->n_clip_rects
)
376 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
385 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
389 mac_prepare_for_quickdraw (f
)
394 Lisp_Object rest
, frame
;
395 FOR_EACH_FRAME (rest
, frame
)
396 if (FRAME_MAC_P (XFRAME (frame
)))
397 mac_prepare_for_quickdraw (XFRAME (frame
));
401 CGContextRef context
= FRAME_CG_CONTEXT (f
);
405 CGContextSynchronize (context
);
406 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
407 &FRAME_CG_CONTEXT (f
));
413 static RgnHandle saved_port_clip_region
= NULL
;
416 mac_begin_clip (f
, gc
)
420 static RgnHandle new_region
= NULL
;
422 if (saved_port_clip_region
== NULL
)
423 saved_port_clip_region
= NewRgn ();
424 if (new_region
== NULL
)
425 new_region
= NewRgn ();
428 mac_prepare_for_quickdraw (f
);
430 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
432 if (gc
->n_clip_rects
)
434 GetClip (saved_port_clip_region
);
435 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
436 SetClip (new_region
);
444 if (gc
->n_clip_rects
)
445 SetClip (saved_port_clip_region
);
449 /* X display function emulation */
451 /* Mac version of XDrawLine. */
454 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
460 CGContextRef context
;
461 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
464 gx1
+= 0.5f
, gx2
+= 0.5f
;
466 gy1
+= 0.5f
, gy2
+= 0.5f
;
468 context
= mac_begin_cg_clip (f
, gc
);
469 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
470 CGContextBeginPath (context
);
471 CGContextMoveToPoint (context
, gx1
, gy1
);
472 CGContextAddLineToPoint (context
, gx2
, gy2
);
473 CGContextClosePath (context
);
474 CGContextStrokePath (context
);
492 mac_begin_clip (f
, gc
);
493 RGBForeColor (GC_FORE_COLOR (gc
));
500 /* Mac version of XDrawLine (to Pixmap). */
503 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
527 GetGWorld (&old_port
, &old_gdh
);
530 RGBForeColor (GC_FORE_COLOR (gc
));
532 LockPixels (GetGWorldPixMap (p
));
535 UnlockPixels (GetGWorldPixMap (p
));
537 SetGWorld (old_port
, old_gdh
);
542 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
546 unsigned int width
, height
;
550 CGContextRef context
;
552 context
= mac_begin_cg_clip (f
, gc
);
553 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
554 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
561 mac_begin_clip (f
, gc
);
562 RGBBackColor (GC_BACK_COLOR (gc
));
563 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
565 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
572 /* Mac version of XClearArea. */
575 mac_clear_area (f
, x
, y
, width
, height
)
578 unsigned int width
, height
;
580 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
583 /* Mac version of XClearWindow. */
591 CGContextRef context
;
592 GC gc
= FRAME_NORMAL_GC (f
);
594 context
= mac_begin_cg_clip (f
, NULL
);
595 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
596 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
597 FRAME_PIXEL_HEIGHT (f
)));
600 #else /* !USE_CG_DRAWING */
601 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
603 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
605 #if TARGET_API_MAC_CARBON
609 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
612 #else /* not TARGET_API_MAC_CARBON */
613 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
614 #endif /* not TARGET_API_MAC_CARBON */
619 /* Mac replacement for XCopyArea. */
623 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
624 dest_x
, dest_y
, overlay_p
)
629 unsigned int width
, height
;
630 int dest_x
, dest_y
, overlay_p
;
632 CGContextRef context
;
633 float port_height
= FRAME_PIXEL_HEIGHT (f
);
634 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
636 context
= mac_begin_cg_clip (f
, gc
);
639 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
640 CGContextFillRect (context
, dest_rect
);
642 CGContextClipToRect (context
, dest_rect
);
643 CGContextScaleCTM (context
, 1, -1);
644 CGContextTranslateCTM (context
, 0, -port_height
);
645 if (CGImageIsMask (image
))
646 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
647 CGContextDrawImage (context
,
648 CGRectMake (dest_x
- src_x
,
649 port_height
- (dest_y
- src_y
650 + CGImageGetHeight (image
)),
651 CGImageGetWidth (image
),
652 CGImageGetHeight (image
)),
657 #else /* !USE_CG_DRAWING */
660 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
663 int x
, y
, width
, height
;
664 unsigned short *bits
;
670 bitmap
.rowBytes
= sizeof(unsigned short);
671 bitmap
.baseAddr
= (char *)bits
;
672 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
674 mac_begin_clip (f
, gc
);
675 RGBForeColor (GC_FORE_COLOR (gc
));
676 RGBBackColor (GC_BACK_COLOR (gc
));
677 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
678 #if TARGET_API_MAC_CARBON
684 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
685 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
686 UnlockPortBits (port
);
688 #else /* not TARGET_API_MAC_CARBON */
689 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
690 overlay_p
? srcOr
: srcCopy
, 0);
691 #endif /* not TARGET_API_MAC_CARBON */
692 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
695 #endif /* !USE_CG_DRAWING */
698 /* Mac replacement for XCreateBitmapFromBitmapData. */
701 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
706 static const unsigned char swap_nibble
[16]
707 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
708 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
709 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
710 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
714 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
715 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
716 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
717 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
718 for (i
= 0; i
< h
; i
++)
720 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
721 for (j
= 0; j
< w1
; j
++)
723 /* Bitswap XBM bytes to match how Mac does things. */
724 unsigned char c
= *bits
++;
725 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
726 | (swap_nibble
[(c
>>4) & 0xf]));
730 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
735 mac_free_bitmap (bitmap
)
738 xfree (bitmap
->baseAddr
);
743 XCreatePixmap (display
, w
, width
, height
, depth
)
746 unsigned int width
, height
;
753 SetPortWindowPort (w
);
755 SetRect (&r
, 0, 0, width
, height
);
756 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
759 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
760 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
762 /* CreateCGImageFromPixMaps requires ARGB format. */
763 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
772 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
776 unsigned int width
, height
;
777 unsigned long fg
, bg
;
787 gc
= XCreateGC (display
, w
, 0, NULL
);
789 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
793 GetGWorld (&old_port
, &old_gdh
);
794 SetGWorld (pixmap
, NULL
);
795 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
796 XSetForeground (display
, gc
, fg
);
797 XSetBackground (display
, gc
, bg
);
798 RGBForeColor (GC_FORE_COLOR (gc
));
799 RGBBackColor (GC_BACK_COLOR (gc
));
800 LockPixels (GetGWorldPixMap (pixmap
));
801 #if TARGET_API_MAC_CARBON
802 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
803 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
804 #else /* not TARGET_API_MAC_CARBON */
805 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
806 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
807 #endif /* not TARGET_API_MAC_CARBON */
808 UnlockPixels (GetGWorldPixMap (pixmap
));
809 SetGWorld (old_port
, old_gdh
);
810 mac_free_bitmap (&bitmap
);
817 XFreePixmap (display
, pixmap
)
821 DisposeGWorld (pixmap
);
825 /* Mac replacement for XFillRectangle. */
828 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
832 unsigned int width
, height
;
835 CGContextRef context
;
837 context
= mac_begin_cg_clip (f
, gc
);
838 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
839 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
844 mac_begin_clip (f
, gc
);
845 RGBForeColor (GC_FORE_COLOR (gc
));
846 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
847 PaintRect (&r
); /* using foreground color of gc */
853 /* Mac replacement for XDrawRectangle: dest is a window. */
856 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
860 unsigned int width
, height
;
863 CGContextRef context
;
865 context
= mac_begin_cg_clip (f
, gc
);
866 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
867 CGContextStrokeRect (context
,
868 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
873 mac_begin_clip (f
, gc
);
874 RGBForeColor (GC_FORE_COLOR (gc
));
875 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
876 FrameRect (&r
); /* using foreground color of gc */
883 mac_invert_rectangle (f
, x
, y
, width
, height
)
886 unsigned int width
, height
;
891 mac_prepare_for_quickdraw (f
);
893 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
895 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
903 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
904 ConstUniCharArrayPtr text
;
905 UniCharCount text_length
;
907 ATSUTextLayout
*text_layout
;
910 static ATSUTextLayout saved_text_layout
= NULL
;
912 if (saved_text_layout
== NULL
)
914 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
915 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
916 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
917 static ATSLineLayoutOptions line_layout
=
918 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
919 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
920 | kATSLineUseQDRendering
922 kATSLineIsDisplayOnly
| kATSLineFractDisable
925 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
927 err
= ATSUCreateTextLayoutWithTextPtr (text
,
928 kATSUFromTextBeginning
,
934 err
= ATSUSetLayoutControls (saved_text_layout
,
935 sizeof (tags
) / sizeof (tags
[0]),
936 tags
, sizes
, values
);
938 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
942 err
= ATSUSetRunStyle (saved_text_layout
, style
,
943 kATSUFromTextBeginning
, kATSUToTextEnd
);
945 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
946 kATSUFromTextBeginning
,
952 *text_layout
= saved_text_layout
;
958 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
959 overstrike_p
, bytes_per_char
)
964 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
967 ATSUTextLayout text_layout
;
969 xassert (bytes_per_char
== 2);
971 #ifndef WORDS_BIG_ENDIAN
974 UniChar
*text
= (UniChar
*)buf
;
976 for (i
= 0; i
< nchars
; i
++)
977 text
[i
] = EndianU16_BtoN (text
[i
]);
980 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
982 GC_FONT (gc
)->mac_style
,
987 if (!mac_use_core_graphics
)
990 mac_begin_clip (f
, gc
);
991 RGBForeColor (GC_FORE_COLOR (gc
));
996 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
997 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
998 RGBBackColor (GC_BACK_COLOR (gc
));
1000 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1003 ATSUDrawText (text_layout
,
1004 kATSUFromTextBeginning
, kATSUToTextEnd
,
1005 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1009 ATSUDrawText (text_layout
,
1010 kATSUFromTextBeginning
, kATSUToTextEnd
,
1011 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1018 static CGContextRef context
;
1019 float port_height
= FRAME_PIXEL_HEIGHT (f
);
1020 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1021 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1022 static const ATSUAttributeValuePtr values
[] = {&context
};
1025 context
= mac_begin_cg_clip (f
, gc
);
1030 QDBeginCGContext (port
, &context
);
1031 if (gc
->n_clip_rects
|| bg_width
)
1033 CGContextTranslateCTM (context
, 0, port_height
);
1034 CGContextScaleCTM (context
, 1, -1);
1035 if (gc
->n_clip_rects
)
1036 CGContextClipToRects (context
, gc
->clip_rects
,
1041 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1042 CGContextFillRect (context
,
1043 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
1045 FONT_HEIGHT (GC_FONT (gc
))));
1047 CGContextScaleCTM (context
, 1, -1);
1048 CGContextTranslateCTM (context
, 0, -port_height
);
1052 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1053 err
= ATSUSetLayoutControls (text_layout
,
1054 sizeof (tags
) / sizeof (tags
[0]),
1055 tags
, sizes
, values
);
1058 ATSUDrawText (text_layout
,
1059 kATSUFromTextBeginning
, kATSUToTextEnd
,
1060 Long2Fix (x
), Long2Fix (port_height
- y
));
1062 ATSUDrawText (text_layout
,
1063 kATSUFromTextBeginning
, kATSUToTextEnd
,
1064 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1067 mac_end_cg_clip (f
);
1070 CGContextSynchronize (context
);
1071 QDEndCGContext (port
, &context
);
1074 /* This doesn't work on Mac OS X 10.1. */
1075 ATSUClearLayoutControls (text_layout
,
1076 sizeof (tags
) / sizeof (tags
[0]), tags
);
1078 ATSUSetLayoutControls (text_layout
,
1079 sizeof (tags
) / sizeof (tags
[0]),
1080 tags
, sizes
, values
);
1083 #endif /* MAC_OSX */
1085 #endif /* USE_ATSUI */
1089 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1090 overstrike_p
, bytes_per_char
)
1095 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1097 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1101 mac_begin_clip (f
, gc
);
1102 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1103 if (mac_use_core_graphics
)
1104 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1106 RGBForeColor (GC_FORE_COLOR (gc
));
1110 RGBBackColor (GC_BACK_COLOR (gc
));
1116 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1118 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1119 into an offscreen graphics world first. So performance gain
1120 cannot be expected.)
1121 - It lowers rendering quality.
1122 - Some fonts leave garbage on cursor movement. */
1127 RGBBackColor (GC_BACK_COLOR (gc
));
1128 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1129 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1134 TextFont (GC_FONT (gc
)->mac_fontnum
);
1135 TextSize (GC_FONT (gc
)->mac_fontsize
);
1136 TextFace (GC_FONT (gc
)->mac_fontface
);
1138 DrawText (buf
, 0, nchars
* bytes_per_char
);
1143 DrawText (buf
, 0, nchars
* bytes_per_char
);
1146 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1149 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1150 if (mac_use_core_graphics
)
1151 SwapQDTextFlags(savedFlags
);
1157 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1158 overstrike_p
, bytes_per_char
)
1163 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1166 if (GC_FONT (gc
)->mac_style
)
1167 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1168 overstrike_p
, bytes_per_char
);
1170 #endif /* USE_ATSUI */
1171 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1172 overstrike_p
, bytes_per_char
);
1176 /* Mac replacement for XDrawImageString. */
1179 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1184 int nchars
, bg_width
, overstrike_p
;
1186 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1191 /* Mac replacement for XDrawImageString16. */
1194 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1199 int nchars
, bg_width
, overstrike_p
;
1201 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1206 /* Mac replacement for XQueryTextExtents, but takes a character. If
1207 STYLE is NULL, measurement is done by QuickDraw Text routines for
1208 the font of the current graphics port. If CG_GLYPH is not NULL,
1209 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1212 mac_query_char_extents (style
, c
,
1213 font_ascent_return
, font_descent_return
,
1214 overall_return
, cg_glyph
)
1221 int *font_ascent_return
, *font_descent_return
;
1222 XCharStruct
*overall_return
;
1223 #if USE_CG_TEXT_DRAWING
1229 OSStatus err
= noErr
;
1236 ATSUTextLayout text_layout
;
1239 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1241 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1243 ATSTrapezoid glyph_bounds
;
1245 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1246 kATSUFromTextBeginning
, kATSUToTextEnd
,
1247 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1248 kATSUseFractionalOrigins
,
1250 kATSUseDeviceOrigins
,
1252 1, &glyph_bounds
, NULL
);
1255 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1256 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1258 width
= Fix2Long (glyph_bounds
.upperRight
.x
1259 - glyph_bounds
.upperLeft
.x
);
1260 if (font_ascent_return
)
1261 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1262 if (font_descent_return
)
1263 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1266 if (err
== noErr
&& overall_return
)
1268 err
= ATSUMeasureTextImage (text_layout
,
1269 kATSUFromTextBeginning
, kATSUToTextEnd
,
1270 0, 0, &char_bounds
);
1272 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1273 #if USE_CG_TEXT_DRAWING
1274 if (err
== noErr
&& cg_glyph
)
1277 ATSUGlyphInfoArray glyph_info_array
;
1278 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1280 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1281 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1283 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1284 kATSUToTextEnd
, &count
,
1287 /* Make sure that we don't have to make layout
1289 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1290 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1291 && glyph_info_array
.glyphs
[0].screenX
== 0)
1293 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1294 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1305 if (font_ascent_return
|| font_descent_return
)
1309 GetFontInfo (&font_info
);
1310 if (font_ascent_return
)
1311 *font_ascent_return
= font_info
.ascent
;
1312 if (font_descent_return
)
1313 *font_descent_return
= font_info
.descent
;
1319 width
= CharWidth (ch
);
1320 QDTextBounds (1, &ch
, &char_bounds
);
1321 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1329 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1332 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1333 XFontStruct
*font_struct
;
1336 XCharStruct
*overall_return
;
1339 short width
= 0, lbearing
= 0, rbearing
= 0;
1342 for (i
= 0; i
< nchars
; i
++)
1344 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1346 width
+= FONT_WIDTH (font_struct
);
1349 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1350 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1351 width
+= pcm
->width
;
1356 overall_return
->lbearing
= lbearing
;
1357 overall_return
->rbearing
= rbearing
;
1358 overall_return
->width
= width
;
1360 /* What's the meaning of the return value of XTextExtents16? */
1364 #if USE_CG_TEXT_DRAWING
1365 static int cg_text_anti_aliasing_threshold
= 8;
1368 init_cg_text_anti_aliasing_threshold ()
1374 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1375 kCFPreferencesCurrentApplication
,
1378 cg_text_anti_aliasing_threshold
= threshold
;
1382 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1387 int nchars
, bg_width
, overstrike_p
;
1389 float port_height
, gx
, gy
;
1391 CGContextRef context
;
1395 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1398 port_height
= FRAME_PIXEL_HEIGHT (f
);
1400 gy
= port_height
- y
;
1401 glyphs
= (CGGlyph
*)buf
;
1402 advances
= alloca (sizeof (CGSize
) * nchars
);
1403 if (advances
== NULL
)
1405 for (i
= 0; i
< nchars
; i
++)
1407 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1409 advances
[i
].width
= pcm
->width
;
1410 advances
[i
].height
= 0;
1411 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1416 context
= mac_begin_cg_clip (f
, gc
);
1418 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1419 if (gc
->n_clip_rects
|| bg_width
)
1421 CGContextTranslateCTM (context
, 0, port_height
);
1422 CGContextScaleCTM (context
, 1, -1);
1423 if (gc
->n_clip_rects
)
1424 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1428 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1431 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1432 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1434 CGContextScaleCTM (context
, 1, -1);
1435 CGContextTranslateCTM (context
, 0, -port_height
);
1439 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1440 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1441 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1442 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1443 CGContextSetShouldAntialias (context
, false);
1444 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1445 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1446 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1449 CGContextSetTextPosition (context
, gx
, gy
);
1450 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1453 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1454 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1457 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1458 else /* CGContextShowGlyphsWithAdvances == NULL */
1460 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1461 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1463 for (i
= 0; i
< nchars
; i
++)
1465 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1467 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1468 gx
+= advances
[i
].width
;
1473 mac_end_cg_clip (f
);
1475 CGContextSynchronize (context
);
1476 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1485 /* Mac replacement for XCopyArea: dest must be window. */
1488 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1493 unsigned int width
, height
;
1498 mac_begin_clip (f
, gc
);
1500 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1501 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1503 ForeColor (blackColor
);
1504 BackColor (whiteColor
);
1506 LockPixels (GetGWorldPixMap (src
));
1507 #if TARGET_API_MAC_CARBON
1512 LockPortBits (port
);
1513 CopyBits (GetPortBitMapForCopyBits (src
),
1514 GetPortBitMapForCopyBits (port
),
1515 &src_r
, &dest_r
, srcCopy
, 0);
1516 UnlockPortBits (port
);
1518 #else /* not TARGET_API_MAC_CARBON */
1519 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1520 &src_r
, &dest_r
, srcCopy
, 0);
1521 #endif /* not TARGET_API_MAC_CARBON */
1522 UnlockPixels (GetGWorldPixMap (src
));
1524 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1531 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1532 width
, height
, dest_x
, dest_y
)
1537 unsigned int width
, height
;
1542 mac_begin_clip (f
, gc
);
1544 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1545 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1547 ForeColor (blackColor
);
1548 BackColor (whiteColor
);
1550 LockPixels (GetGWorldPixMap (src
));
1551 LockPixels (GetGWorldPixMap (mask
));
1552 #if TARGET_API_MAC_CARBON
1557 LockPortBits (port
);
1558 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1559 GetPortBitMapForCopyBits (port
),
1560 &src_r
, &src_r
, &dest_r
);
1561 UnlockPortBits (port
);
1563 #else /* not TARGET_API_MAC_CARBON */
1564 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1565 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1566 #endif /* not TARGET_API_MAC_CARBON */
1567 UnlockPixels (GetGWorldPixMap (mask
));
1568 UnlockPixels (GetGWorldPixMap (src
));
1570 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1574 #endif /* !USE_CG_DRAWING */
1577 /* Mac replacement for XCopyArea: used only for scrolling. */
1580 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1584 unsigned int width
, height
;
1587 #if TARGET_API_MAC_CARBON
1589 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1591 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1593 mac_prepare_for_quickdraw (f
);
1595 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1596 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1597 kScrollWindowNoOptions
, dummy
);
1599 #else /* not TARGET_API_MAC_CARBON */
1601 WindowRef w
= FRAME_MAC_WINDOW (f
);
1603 mac_begin_clip (f
, gc
);
1605 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1606 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1608 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1609 color mapping in CopyBits. Otherwise, it will be slow. */
1610 ForeColor (blackColor
);
1611 BackColor (whiteColor
);
1612 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1614 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1617 #endif /* not TARGET_API_MAC_CARBON */
1621 /* Mac replacement for XChangeGC. */
1624 XChangeGC (display
, gc
, mask
, xgcv
)
1630 if (mask
& GCForeground
)
1631 XSetForeground (display
, gc
, xgcv
->foreground
);
1632 if (mask
& GCBackground
)
1633 XSetBackground (display
, gc
, xgcv
->background
);
1635 XSetFont (display
, gc
, xgcv
->font
);
1639 /* Mac replacement for XCreateGC. */
1642 XCreateGC (display
, d
, mask
, xgcv
)
1648 GC gc
= xmalloc (sizeof (*gc
));
1650 bzero (gc
, sizeof (*gc
));
1651 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1652 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1653 if (CGColorGetTypeID
!= NULL
)
1656 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1657 CGColorRetain (gc
->cg_fore_color
);
1658 CGColorRetain (gc
->cg_back_color
);
1661 XChangeGC (display
, gc
, mask
, xgcv
);
1667 /* Used in xfaces.c. */
1670 XFreeGC (display
, gc
)
1674 if (gc
->clip_region
)
1675 DisposeRgn (gc
->clip_region
);
1676 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1677 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1678 if (CGColorGetTypeID
!= NULL
)
1681 CGColorRelease (gc
->cg_fore_color
);
1682 CGColorRelease (gc
->cg_back_color
);
1689 /* Mac replacement for XGetGCValues. */
1692 XGetGCValues (display
, gc
, mask
, xgcv
)
1698 if (mask
& GCForeground
)
1699 xgcv
->foreground
= gc
->xgcv
.foreground
;
1700 if (mask
& GCBackground
)
1701 xgcv
->background
= gc
->xgcv
.background
;
1703 xgcv
->font
= gc
->xgcv
.font
;
1707 /* Mac replacement for XSetForeground. */
1710 XSetForeground (display
, gc
, color
)
1713 unsigned long color
;
1715 if (gc
->xgcv
.foreground
!= color
)
1717 gc
->xgcv
.foreground
= color
;
1718 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1719 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1720 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1721 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1722 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1723 if (CGColorGetTypeID
!= NULL
)
1726 CGColorRelease (gc
->cg_fore_color
);
1729 gc
->cg_fore_color
= mac_cg_color_black
;
1730 CGColorRetain (gc
->cg_fore_color
);
1736 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1737 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1738 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1740 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1748 /* Mac replacement for XSetBackground. */
1751 XSetBackground (display
, gc
, color
)
1754 unsigned long color
;
1756 if (gc
->xgcv
.background
!= color
)
1758 gc
->xgcv
.background
= color
;
1759 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1760 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1761 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1762 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1763 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1764 if (CGColorGetTypeID
!= NULL
)
1767 CGColorRelease (gc
->cg_back_color
);
1770 gc
->cg_back_color
= mac_cg_color_black
;
1771 CGColorRetain (gc
->cg_back_color
);
1777 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1778 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1779 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1781 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1789 /* Mac replacement for XSetFont. */
1792 XSetFont (display
, gc
, font
)
1797 gc
->xgcv
.font
= font
;
1801 /* Mac replacement for XSetClipRectangles. */
1804 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1812 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1814 gc
->n_clip_rects
= n
;
1817 if (gc
->clip_region
== NULL
)
1818 gc
->clip_region
= NewRgn ();
1819 RectRgn (gc
->clip_region
, rectangles
);
1822 RgnHandle region
= NewRgn ();
1824 for (i
= 1; i
< n
; i
++)
1826 RectRgn (region
, rectangles
+ i
);
1827 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1829 DisposeRgn (region
);
1832 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1833 for (i
= 0; i
< n
; i
++)
1835 Rect
*rect
= rectangles
+ i
;
1837 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1838 rect
->right
- rect
->left
,
1839 rect
->bottom
- rect
->top
);
1845 /* Mac replacement for XSetClipMask. */
1848 mac_reset_clip_rectangles (display
, gc
)
1852 gc
->n_clip_rects
= 0;
1856 /* Mac replacement for XSetWindowBackground. */
1859 XSetWindowBackground (display
, w
, color
)
1862 unsigned long color
;
1864 #if !TARGET_API_MAC_CARBON
1865 AuxWinHandle aw_handle
;
1866 CTabHandle ctab_handle
;
1867 ColorSpecPtr ct_table
;
1872 bg_color
.red
= RED16_FROM_ULONG (color
);
1873 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1874 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1876 #if TARGET_API_MAC_CARBON
1877 SetWindowContentColor (w
, &bg_color
);
1879 if (GetAuxWin (w
, &aw_handle
))
1881 ctab_handle
= (*aw_handle
)->awCTable
;
1882 HandToHand ((Handle
*) &ctab_handle
);
1883 ct_table
= (*ctab_handle
)->ctTable
;
1884 ct_size
= (*ctab_handle
)->ctSize
;
1885 while (ct_size
> -1)
1887 if (ct_table
->value
== 0)
1889 ct_table
->rgb
= bg_color
;
1890 CTabChanged (ctab_handle
);
1891 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1899 /* Flush display of frame F, or of all frames if F is null. */
1905 #if TARGET_API_MAC_CARBON
1908 mac_prepare_for_quickdraw (f
);
1911 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1913 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1919 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1920 Calls to XFlush should be unnecessary because the X output buffer
1921 is flushed automatically as needed by calls to XPending,
1922 XNextEvent, or XWindowEvent according to the XFlush man page.
1923 XTread_socket calls XPending. Removing XFlush improves
1926 #define XFlush(DISPLAY) (void) 0
1930 mac_flush_display_optional (f
)
1934 mac_prepare_for_quickdraw (f
);
1939 /***********************************************************************
1940 Starting and ending an update
1941 ***********************************************************************/
1943 /* Start an update of frame F. This function is installed as a hook
1944 for update_begin, i.e. it is called when update_begin is called.
1945 This function is called prior to calls to x_update_window_begin for
1946 each window being updated. */
1952 #if TARGET_API_MAC_CARBON
1953 /* During update of a frame, availability of input events is
1954 periodically checked with ReceiveNextEvent if
1955 redisplay-dont-pause is nil. That normally flushes window buffer
1956 changes for every check, and thus screen update looks waving even
1957 if no input is available. So we disable screen updates during
1958 update of a frame. */
1960 DisableScreenUpdates ();
1966 /* Start update of window W. Set the global variable updated_window
1967 to the window being updated and set output_cursor to the cursor
1971 x_update_window_begin (w
)
1974 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1975 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1978 set_output_cursor (&w
->cursor
);
1982 if (f
== display_info
->mouse_face_mouse_frame
)
1984 /* Don't do highlighting for mouse motion during the update. */
1985 display_info
->mouse_face_defer
= 1;
1987 /* If F needs to be redrawn, simply forget about any prior mouse
1989 if (FRAME_GARBAGED_P (f
))
1990 display_info
->mouse_face_window
= Qnil
;
1992 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1993 their mouse_face_p flag set, which means that they are always
1994 unequal to rows in a desired matrix which never have that
1995 flag set. So, rows containing mouse-face glyphs are never
1996 scrolled, and we don't have to switch the mouse highlight off
1997 here to prevent it from being scrolled. */
1999 /* Can we tell that this update does not affect the window
2000 where the mouse highlight is? If so, no need to turn off.
2001 Likewise, don't do anything if the frame is garbaged;
2002 in that case, the frame's current matrix that we would use
2003 is all wrong, and we will redisplay that line anyway. */
2004 if (!NILP (display_info
->mouse_face_window
)
2005 && w
== XWINDOW (display_info
->mouse_face_window
))
2009 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2010 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2013 if (i
< w
->desired_matrix
->nrows
)
2014 clear_mouse_face (display_info
);
2023 /* Draw a vertical window border from (x,y0) to (x,y1) */
2026 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2030 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2033 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2035 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2038 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2041 /* End update of window W (which is equal to updated_window).
2043 Draw vertical borders between horizontally adjacent windows, and
2044 display W's cursor if CURSOR_ON_P is non-zero.
2046 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2047 glyphs in mouse-face were overwritten. In that case we have to
2048 make sure that the mouse-highlight is properly redrawn.
2050 W may be a menu bar pseudo-window in case we don't have X toolkit
2051 support. Such windows don't have a cursor, so don't display it
2055 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2057 int cursor_on_p
, mouse_face_overwritten_p
;
2059 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2061 if (!w
->pseudo_window_p
)
2066 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2068 output_cursor
.x
, output_cursor
.y
);
2070 if (draw_window_fringes (w
, 1))
2071 x_draw_vertical_border (w
);
2076 /* If a row with mouse-face was overwritten, arrange for
2077 XTframe_up_to_date to redisplay the mouse highlight. */
2078 if (mouse_face_overwritten_p
)
2080 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2081 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2082 dpyinfo
->mouse_face_window
= Qnil
;
2085 updated_window
= NULL
;
2089 /* End update of frame F. This function is installed as a hook in
2096 /* Mouse highlight may be displayed again. */
2097 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2100 #if TARGET_API_MAC_CARBON
2101 EnableScreenUpdates ();
2103 XFlush (FRAME_MAC_DISPLAY (f
));
2108 /* This function is called from various places in xdisp.c whenever a
2109 complete update has been performed. The global variable
2110 updated_window is not available here. */
2113 XTframe_up_to_date (f
)
2116 if (FRAME_MAC_P (f
))
2118 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2120 if (dpyinfo
->mouse_face_deferred_gc
2121 || f
== dpyinfo
->mouse_face_mouse_frame
)
2124 if (dpyinfo
->mouse_face_mouse_frame
)
2125 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2126 dpyinfo
->mouse_face_mouse_x
,
2127 dpyinfo
->mouse_face_mouse_y
);
2128 dpyinfo
->mouse_face_deferred_gc
= 0;
2135 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2136 arrow bitmaps, or clear the fringes if no bitmaps are required
2137 before DESIRED_ROW is made current. The window being updated is
2138 found in updated_window. This function is called from
2139 update_window_line only if it is known that there are differences
2140 between bitmaps to be drawn between current row and DESIRED_ROW. */
2143 x_after_update_window_line (desired_row
)
2144 struct glyph_row
*desired_row
;
2146 struct window
*w
= updated_window
;
2152 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2153 desired_row
->redraw_fringe_bitmaps_p
= 1;
2155 /* When a window has disappeared, make sure that no rest of
2156 full-width rows stays visible in the internal border. Could
2157 check here if updated_window is the leftmost/rightmost window,
2158 but I guess it's not worth doing since vertically split windows
2159 are almost never used, internal border is rarely set, and the
2160 overhead is very small. */
2161 if (windows_or_buffers_changed
2162 && desired_row
->full_width_p
2163 && (f
= XFRAME (w
->frame
),
2164 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2166 && (height
= desired_row
->visible_height
,
2169 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2171 /* Internal border is drawn below the tool bar. */
2172 if (WINDOWP (f
->tool_bar_window
)
2173 && w
== XWINDOW (f
->tool_bar_window
))
2177 mac_clear_area (f
, 0, y
, width
, height
);
2178 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2184 /* Draw the bitmap WHICH in one of the left or right fringes of
2185 window W. ROW is the glyph row for which to display the bitmap; it
2186 determines the vertical position at which the bitmap has to be
2190 x_draw_fringe_bitmap (w
, row
, p
)
2192 struct glyph_row
*row
;
2193 struct draw_fringe_bitmap_params
*p
;
2195 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2196 Display
*display
= FRAME_MAC_DISPLAY (f
);
2197 struct face
*face
= p
->face
;
2199 int overlay_p
= p
->overlay_p
;
2204 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2206 #if 0 /* MAC_TODO: stipple */
2207 /* In case the same realized face is used for fringes and
2208 for something displayed in the text (e.g. face `region' on
2209 mono-displays, the fill style may have been changed to
2210 FillSolid in x_draw_glyph_string_background. */
2212 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2214 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2217 /* If the fringe is adjacent to the left (right) scroll bar of a
2218 leftmost (rightmost, respectively) window, then extend its
2219 background to the gap between the fringe and the bar. */
2220 if ((WINDOW_LEFTMOST_P (w
)
2221 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2222 || (WINDOW_RIGHTMOST_P (w
)
2223 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2225 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2229 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2230 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2231 * FRAME_COLUMN_WIDTH (f
));
2234 && (left
+ width
== p
->x
2235 || p
->x
+ p
->wd
== left
))
2237 /* Bitmap fills the fringe and we need background
2239 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
2243 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
2245 ny
= row
->visible_height
;
2250 if (left
+ width
== bx
)
2252 bx
= left
+ sb_width
;
2253 nx
+= width
- sb_width
;
2255 else if (bx
+ nx
== left
)
2256 nx
+= width
- sb_width
;
2263 mac_erase_rectangle (f
, face
->gc
, bx
, by
, nx
, ny
);
2264 /* The fringe background has already been filled. */
2268 #if 0 /* MAC_TODO: stipple */
2270 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2273 #endif /* MAC_OSX */
2275 /* Must clip because of partially visible lines. */
2276 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2279 /* Adjust position of "bottom aligned" bitmap on partially
2280 visible last row. */
2282 int oldVH
= row
->visible_height
;
2283 row
->visible_height
= p
->h
;
2284 row
->y
-= rowY
- p
->y
;
2285 x_clip_to_row (w
, row
, -1, face
->gc
);
2287 row
->visible_height
= oldVH
;
2290 x_clip_to_row (w
, row
, -1, face
->gc
);
2293 if (p
->bx
>= 0 && !p
->overlay_p
)
2295 #if 0 /* MAC_TODO: stipple */
2296 /* In case the same realized face is used for fringes and
2297 for something displayed in the text (e.g. face `region' on
2298 mono-displays, the fill style may have been changed to
2299 FillSolid in x_draw_glyph_string_background. */
2301 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2303 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2306 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2308 #if 0 /* MAC_TODO: stipple */
2310 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2313 #endif /* !MAC_OSX */
2317 && p
->which
< max_fringe_bmp
2323 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2324 XSetForeground (display
, face
->gc
,
2326 ? (p
->overlay_p
? face
->background
2327 : f
->output_data
.mac
->cursor_pixel
)
2328 : face
->foreground
));
2330 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2331 p
->wd
, p
->h
, p
->x
, p
->y
, overlay_p
);
2333 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2334 p
->wd
, p
->h
, p
->bits
+ p
->dh
, overlay_p
);
2336 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2339 mac_reset_clip_rectangles (display
, face
->gc
);
2344 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2346 unsigned short *bits
;
2350 CGDataProviderRef provider
;
2352 if (which
>= max_fringe_bmp
)
2355 max_fringe_bmp
= which
+ 20;
2356 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2357 while (i
< max_fringe_bmp
)
2358 fringe_bmp
[i
++] = 0;
2361 for (i
= 0; i
< h
; i
++)
2363 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2364 sizeof (unsigned short) * h
, NULL
);
2367 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2368 sizeof (unsigned short),
2370 CGDataProviderRelease (provider
);
2375 mac_destroy_fringe_bitmap (which
)
2378 if (which
>= max_fringe_bmp
)
2381 if (fringe_bmp
[which
])
2382 CGImageRelease (fringe_bmp
[which
]);
2383 fringe_bmp
[which
] = 0;
2388 /* This is called when starting Emacs and when restarting after
2389 suspend. When starting Emacs, no window is mapped. And nothing
2390 must be done to Emacs's own window if it is suspended (though that
2394 XTset_terminal_modes (struct terminal
*t
)
2398 /* This is called when exiting or suspending Emacs. Exiting will make
2399 the windows go away, and suspending requires no action. */
2402 XTreset_terminal_modes (struct terminal
*t
)
2408 /***********************************************************************
2410 ***********************************************************************/
2412 /* Function prototypes of this page. */
2414 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2415 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2419 pcm_init (pcm
, count
)
2423 bzero (pcm
, sizeof (XCharStruct
) * count
);
2424 while (--count
>= 0)
2426 pcm
->descent
= PCM_INVALID
;
2431 static enum pcm_status
2432 pcm_get_status (pcm
)
2433 const XCharStruct
*pcm
;
2435 int height
= pcm
->ascent
+ pcm
->descent
;
2437 /* Negative height means some special status. */
2438 return height
>= 0 ? PCM_VALID
: height
;
2441 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2442 is not contained in the font. */
2444 static INLINE XCharStruct
*
2445 x_per_char_metric (font
, char2b
)
2449 /* The result metric information. */
2450 XCharStruct
*pcm
= NULL
;
2452 xassert (font
&& char2b
);
2455 if (font
->mac_style
)
2457 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2461 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2462 pcm_init (*row
, 0x100);
2464 pcm
= *row
+ char2b
->byte2
;
2465 if (pcm_get_status (pcm
) != PCM_VALID
)
2468 mac_query_char_extents (font
->mac_style
,
2469 (char2b
->byte1
<< 8) + char2b
->byte2
,
2470 NULL
, NULL
, pcm
, NULL
);
2477 if (font
->bounds
.per_char
!= NULL
)
2479 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2481 /* min_char_or_byte2 specifies the linear character index
2482 corresponding to the first element of the per_char array,
2483 max_char_or_byte2 is the index of the last character. A
2484 character with non-zero CHAR2B->byte1 is not in the font.
2485 A character with byte2 less than min_char_or_byte2 or
2486 greater max_char_or_byte2 is not in the font. */
2487 if (char2b
->byte1
== 0
2488 && char2b
->byte2
>= font
->min_char_or_byte2
2489 && char2b
->byte2
<= font
->max_char_or_byte2
)
2490 pcm
= font
->bounds
.per_char
2491 + (char2b
->byte2
- font
->min_char_or_byte2
);
2495 /* If either min_byte1 or max_byte1 are nonzero, both
2496 min_char_or_byte2 and max_char_or_byte2 are less than
2497 256, and the 2-byte character index values corresponding
2498 to the per_char array element N (counting from 0) are:
2500 byte1 = N/D + min_byte1
2501 byte2 = N\D + min_char_or_byte2
2505 D = max_char_or_byte2 - min_char_or_byte2 + 1
2506 / = integer division
2507 \ = integer modulus */
2508 if (char2b
->byte1
>= font
->min_byte1
2509 && char2b
->byte1
<= font
->max_byte1
2510 && char2b
->byte2
>= font
->min_char_or_byte2
2511 && char2b
->byte2
<= font
->max_char_or_byte2
)
2513 pcm
= (font
->bounds
.per_char
2514 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2515 * (char2b
->byte1
- font
->min_byte1
))
2516 + (char2b
->byte2
- font
->min_char_or_byte2
));
2522 /* If the per_char pointer is null, all glyphs between the first
2523 and last character indexes inclusive have the same
2524 information, as given by both min_bounds and max_bounds. */
2525 if (char2b
->byte2
>= font
->min_char_or_byte2
2526 && char2b
->byte2
<= font
->max_char_or_byte2
)
2527 pcm
= &font
->max_bounds
;
2533 return ((pcm
== NULL
2535 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2536 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2545 static XCharStruct
*
2546 mac_per_char_metric (font
, char2b
, font_type
)
2551 return x_per_char_metric (font
, char2b
);
2555 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2556 the two-byte form of C. Encoding is returned in *CHAR2B. */
2559 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2562 struct font_info
*font_info
;
2565 int charset
= CHAR_CHARSET (c
);
2566 XFontStruct
*font
= font_info
->font
;
2568 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2569 This may be either a program in a special encoder language or a
2571 if (font_info
->font_encoder
)
2573 /* It's a program. */
2574 struct ccl_program
*ccl
= font_info
->font_encoder
;
2576 check_ccl_update (ccl
);
2577 if (CHARSET_DIMENSION (charset
) == 1)
2579 ccl
->reg
[0] = charset
;
2580 ccl
->reg
[1] = char2b
->byte2
;
2585 ccl
->reg
[0] = charset
;
2586 ccl
->reg
[1] = char2b
->byte1
;
2587 ccl
->reg
[2] = char2b
->byte2
;
2590 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2592 /* We assume that MSBs are appropriately set/reset by CCL
2594 if (font
->max_byte1
== 0) /* 1-byte font */
2595 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2597 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2599 else if (font_info
->encoding
[charset
])
2601 /* Fixed encoding scheme. See fontset.h for the meaning of the
2602 encoding numbers. */
2603 int enc
= font_info
->encoding
[charset
];
2605 if ((enc
== 1 || enc
== 2)
2606 && CHARSET_DIMENSION (charset
) == 2)
2607 char2b
->byte1
|= 0x80;
2609 if (enc
== 1 || enc
== 3)
2610 char2b
->byte2
|= 0x80;
2616 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2617 char2b
->byte1
= sjis1
;
2618 char2b
->byte2
= sjis2
;
2623 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2625 return FONT_TYPE_UNKNOWN
;
2630 /***********************************************************************
2632 ***********************************************************************/
2636 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2637 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2638 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2640 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2641 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2642 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2643 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2644 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2645 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2646 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2647 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2648 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2649 unsigned long *, double, int));*/
2650 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2651 double, int, unsigned long));
2652 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2653 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2654 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2655 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2656 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2658 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2659 int, int, int, int, int, int,
2661 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2662 int, int, int, Rect
*));
2665 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2669 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2674 struct glyph_string
*s
;
2676 if (s
->font
== FRAME_FONT (s
->f
)
2677 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2678 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2680 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2683 /* Cursor on non-default face: must merge. */
2687 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2688 xgcv
.foreground
= s
->face
->background
;
2690 /* If the glyph would be invisible, try a different foreground. */
2691 if (xgcv
.foreground
== xgcv
.background
)
2692 xgcv
.foreground
= s
->face
->foreground
;
2693 if (xgcv
.foreground
== xgcv
.background
)
2694 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2695 if (xgcv
.foreground
== xgcv
.background
)
2696 xgcv
.foreground
= s
->face
->foreground
;
2698 /* Make sure the cursor is distinct from text in this face. */
2699 if (xgcv
.background
== s
->face
->background
2700 && xgcv
.foreground
== s
->face
->foreground
)
2702 xgcv
.background
= s
->face
->foreground
;
2703 xgcv
.foreground
= s
->face
->background
;
2706 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2707 xgcv
.font
= s
->font
;
2708 mask
= GCForeground
| GCBackground
| GCFont
;
2710 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2711 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2714 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2715 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2717 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2722 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2725 x_set_mouse_face_gc (s
)
2726 struct glyph_string
*s
;
2731 /* What face has to be used last for the mouse face? */
2732 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2733 face
= FACE_FROM_ID (s
->f
, face_id
);
2735 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2737 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2738 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2740 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2741 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2742 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2744 /* If font in this face is same as S->font, use it. */
2745 if (s
->font
== s
->face
->font
)
2746 s
->gc
= s
->face
->gc
;
2749 /* Otherwise construct scratch_cursor_gc with values from FACE
2754 xgcv
.background
= s
->face
->background
;
2755 xgcv
.foreground
= s
->face
->foreground
;
2756 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2757 xgcv
.font
= s
->font
;
2758 mask
= GCForeground
| GCBackground
| GCFont
;
2760 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2761 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2764 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2765 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2767 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2770 xassert (s
->gc
!= 0);
2774 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2775 Faces to use in the mode line have already been computed when the
2776 matrix was built, so there isn't much to do, here. */
2779 x_set_mode_line_face_gc (s
)
2780 struct glyph_string
*s
;
2782 s
->gc
= s
->face
->gc
;
2786 /* Set S->gc of glyph string S for drawing that glyph string. Set
2787 S->stippled_p to a non-zero value if the face of S has a stipple
2791 x_set_glyph_string_gc (s
)
2792 struct glyph_string
*s
;
2794 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2796 if (s
->hl
== DRAW_NORMAL_TEXT
)
2798 s
->gc
= s
->face
->gc
;
2799 s
->stippled_p
= s
->face
->stipple
!= 0;
2801 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2803 x_set_mode_line_face_gc (s
);
2804 s
->stippled_p
= s
->face
->stipple
!= 0;
2806 else if (s
->hl
== DRAW_CURSOR
)
2808 x_set_cursor_gc (s
);
2811 else if (s
->hl
== DRAW_MOUSE_FACE
)
2813 x_set_mouse_face_gc (s
);
2814 s
->stippled_p
= s
->face
->stipple
!= 0;
2816 else if (s
->hl
== DRAW_IMAGE_RAISED
2817 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2819 s
->gc
= s
->face
->gc
;
2820 s
->stippled_p
= s
->face
->stipple
!= 0;
2824 s
->gc
= s
->face
->gc
;
2825 s
->stippled_p
= s
->face
->stipple
!= 0;
2828 /* GC must have been set. */
2829 xassert (s
->gc
!= 0);
2833 /* Set clipping for output of glyph string S. S may be part of a mode
2834 line or menu if we don't have X toolkit support. */
2837 x_set_glyph_string_clipping (s
)
2838 struct glyph_string
*s
;
2840 Rect rects
[MAX_CLIP_RECTS
];
2843 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2844 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2849 Compute left and right overhang of glyph string S. If S is a glyph
2850 string for a composition, assume overhangs don't exist. */
2853 mac_compute_glyph_string_overhangs (s
)
2854 struct glyph_string
*s
;
2856 if (!(s
->cmp
== NULL
2857 && s
->first_glyph
->type
== CHAR_GLYPH
))
2862 || s
->font
->mac_style
2868 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2869 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2870 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2875 MacFontStruct
*font
= s
->font
;
2878 mac_prepare_for_quickdraw (s
->f
);
2880 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2882 TextFont (font
->mac_fontnum
);
2883 TextSize (font
->mac_fontsize
);
2884 TextFace (font
->mac_fontface
);
2886 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2888 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2889 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2894 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2897 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2898 struct glyph_string
*s
;
2901 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2905 /* Draw the background of glyph_string S. If S->background_filled_p
2906 is non-zero don't draw it. FORCE_P non-zero means draw the
2907 background even if it wouldn't be drawn normally. This is used
2908 when a string preceding S draws into the background of S, or S
2909 contains the first component of a composition. */
2912 x_draw_glyph_string_background (s
, force_p
)
2913 struct glyph_string
*s
;
2916 /* Nothing to do if background has already been drawn or if it
2917 shouldn't be drawn in the first place. */
2918 if (!s
->background_filled_p
)
2920 int box_line_width
= max (s
->face
->box_line_width
, 0);
2922 #if 0 /* MAC_TODO: stipple */
2925 /* Fill background with a stipple pattern. */
2926 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2927 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2928 s
->y
+ box_line_width
,
2929 s
->background_width
,
2930 s
->height
- 2 * box_line_width
);
2931 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2932 s
->background_filled_p
= 1;
2936 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2937 || s
->font_not_found_p
2938 || s
->extends_to_end_of_line_p
2941 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2942 s
->background_width
,
2943 s
->height
- 2 * box_line_width
);
2944 s
->background_filled_p
= 1;
2950 /* Draw the foreground of glyph string S. */
2953 x_draw_glyph_string_foreground (s
)
2954 struct glyph_string
*s
;
2958 /* If first glyph of S has a left box line, start drawing the text
2959 of S to the right of that box line. */
2960 if (s
->face
->box
!= FACE_NO_BOX
2961 && s
->first_glyph
->left_box_line_p
)
2962 x
= s
->x
+ abs (s
->face
->box_line_width
);
2966 /* Draw characters of S as rectangles if S's font could not be
2968 if (s
->font_not_found_p
)
2970 for (i
= 0; i
< s
->nchars
; ++i
)
2972 struct glyph
*g
= s
->first_glyph
+ i
;
2973 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2974 g
->pixel_width
- 1, s
->height
- 1);
2975 x
+= g
->pixel_width
;
2980 char *char1b
= (char *) s
->char2b
;
2981 int boff
= s
->font_info
->baseline_offset
;
2983 if (s
->font_info
->vertical_centering
)
2984 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2986 /* If we can use 8-bit functions, condense S->char2b. */
2989 && GC_FONT (s
->gc
)->mac_style
== NULL
2992 for (i
= 0; i
< s
->nchars
; ++i
)
2993 char1b
[i
] = s
->char2b
[i
].byte2
;
2995 /* Draw text with XDrawString if background has already been
2996 filled. Otherwise, use XDrawImageString. (Note that
2997 XDrawImageString is usually faster than XDrawString.) Always
2998 use XDrawImageString when drawing the cursor so that there is
2999 no chance that characters under a box cursor are invisible. */
3001 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3002 bg_width
= 0; /* Corresponds to XDrawString. */
3004 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
3008 || GC_FONT (s
->gc
)->mac_style
3011 #if USE_CG_TEXT_DRAWING
3013 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3014 s
->char2b
, s
->nchars
, bg_width
,
3015 s
->face
->overstrike
))
3019 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3020 s
->char2b
, s
->nchars
, bg_width
,
3021 s
->face
->overstrike
);
3023 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3024 char1b
, s
->nchars
, bg_width
,
3025 s
->face
->overstrike
);
3029 /* Draw the foreground of composite glyph string S. */
3032 x_draw_composite_glyph_string_foreground (s
)
3033 struct glyph_string
*s
;
3037 /* If first glyph of S has a left box line, start drawing the text
3038 of S to the right of that box line. */
3039 if (s
->face
->box
!= FACE_NO_BOX
3040 && s
->first_glyph
->left_box_line_p
)
3041 x
= s
->x
+ abs (s
->face
->box_line_width
);
3045 /* S is a glyph string for a composition. S->gidx is the index of
3046 the first character drawn for glyphs of this composition.
3047 S->gidx == 0 means we are drawing the very first character of
3048 this composition. */
3050 /* Draw a rectangle for the composition if the font for the very
3051 first character of the composition could not be loaded. */
3052 if (s
->font_not_found_p
)
3055 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3056 s
->width
- 1, s
->height
- 1);
3060 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3061 mac_draw_image_string_16 (s
->f
, s
->gc
,
3062 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3063 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3064 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3069 #ifdef USE_X_TOOLKIT
3071 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3074 /* Return the frame on which widget WIDGET is used.. Abort if frame
3075 cannot be determined. */
3077 static struct frame
*
3078 x_frame_of_widget (widget
)
3081 struct x_display_info
*dpyinfo
;
3085 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3087 /* Find the top-level shell of the widget. Note that this function
3088 can be called when the widget is not yet realized, so XtWindow
3089 (widget) == 0. That's the reason we can't simply use
3090 x_any_window_to_frame. */
3091 while (!XtIsTopLevelShell (widget
))
3092 widget
= XtParent (widget
);
3094 /* Look for a frame with that top-level widget. Allocate the color
3095 on that frame to get the right gamma correction value. */
3096 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3097 if (GC_FRAMEP (XCAR (tail
))
3098 && (f
= XFRAME (XCAR (tail
)),
3099 (f
->output_data
.nothing
!= 1
3100 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3101 && f
->output_data
.x
->widget
== widget
)
3108 /* Allocate the color COLOR->pixel on the screen and display of
3109 widget WIDGET in colormap CMAP. If an exact match cannot be
3110 allocated, try the nearest color available. Value is non-zero
3111 if successful. This is called from lwlib. */
3114 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3119 struct frame
*f
= x_frame_of_widget (widget
);
3120 return x_alloc_nearest_color (f
, cmap
, color
);
3124 #endif /* USE_X_TOOLKIT */
3126 #if 0 /* MAC_TODO */
3128 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3129 CMAP. If an exact match can't be allocated, try the nearest color
3130 available. Value is non-zero if successful. Set *COLOR to the
3134 x_alloc_nearest_color (f
, cmap
, color
)
3139 Display
*display
= FRAME_X_DISPLAY (f
);
3140 Screen
*screen
= FRAME_X_SCREEN (f
);
3143 gamma_correct (f
, color
);
3144 rc
= XAllocColor (display
, cmap
, color
);
3147 /* If we got to this point, the colormap is full, so we're going
3148 to try to get the next closest color. The algorithm used is
3149 a least-squares matching, which is what X uses for closest
3150 color matching with StaticColor visuals. */
3152 unsigned long nearest_delta
= ~0;
3153 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3154 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3156 for (i
= 0; i
< ncells
; ++i
)
3158 XQueryColors (display
, cmap
, cells
, ncells
);
3160 for (nearest
= i
= 0; i
< ncells
; ++i
)
3162 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3163 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3164 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3165 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3167 if (delta
< nearest_delta
)
3170 nearest_delta
= delta
;
3174 color
->red
= cells
[nearest
].red
;
3175 color
->green
= cells
[nearest
].green
;
3176 color
->blue
= cells
[nearest
].blue
;
3177 rc
= XAllocColor (display
, cmap
, color
);
3180 #ifdef DEBUG_X_COLORS
3182 register_color (color
->pixel
);
3183 #endif /* DEBUG_X_COLORS */
3189 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3190 It's necessary to do this instead of just using PIXEL directly to
3191 get color reference counts right. */
3194 x_copy_color (f
, pixel
)
3196 unsigned long pixel
;
3200 color
.pixel
= pixel
;
3202 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3203 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3205 #ifdef DEBUG_X_COLORS
3206 register_color (pixel
);
3212 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3213 It's necessary to do this instead of just using PIXEL directly to
3214 get color reference counts right. */
3217 x_copy_dpy_color (dpy
, cmap
, pixel
)
3220 unsigned long pixel
;
3224 color
.pixel
= pixel
;
3226 XQueryColor (dpy
, cmap
, &color
);
3227 XAllocColor (dpy
, cmap
, &color
);
3229 #ifdef DEBUG_X_COLORS
3230 register_color (pixel
);
3235 #endif /* MAC_TODO */
3238 /* Brightness beyond which a color won't have its highlight brightness
3241 Nominally, highlight colors for `3d' faces are calculated by
3242 brightening an object's color by a constant scale factor, but this
3243 doesn't yield good results for dark colors, so for colors who's
3244 brightness is less than this value (on a scale of 0-255) have to
3245 use an additional additive factor.
3247 The value here is set so that the default menu-bar/mode-line color
3248 (grey75) will not have its highlights changed at all. */
3249 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3252 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3253 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3254 If this produces the same color as COLOR, try a color where all RGB
3255 values have DELTA added. Return the allocated color in *COLOR.
3256 DISPLAY is the X display, CMAP is the colormap to operate on.
3257 Value is non-zero if successful. */
3260 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3262 unsigned long *color
;
3269 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3272 /* Change RGB values by specified FACTOR. Avoid overflow! */
3273 xassert (factor
>= 0);
3274 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3275 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3276 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3278 /* Calculate brightness of COLOR. */
3279 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3280 + BLUE_FROM_ULONG (*color
)) / 6;
3282 /* We only boost colors that are darker than
3283 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3284 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3285 /* Make an additive adjustment to NEW, because it's dark enough so
3286 that scaling by FACTOR alone isn't enough. */
3288 /* How far below the limit this color is (0 - 1, 1 being darker). */
3289 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3290 /* The additive adjustment. */
3291 int min_delta
= delta
* dimness
* factor
/ 2;
3294 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3295 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3296 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3298 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3299 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3300 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3304 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3305 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3306 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3308 /* MAC_TODO: Map to palette and retry with delta if same? */
3309 /* MAC_TODO: Free colors (if using palette)? */
3320 /* Set up the foreground color for drawing relief lines of glyph
3321 string S. RELIEF is a pointer to a struct relief containing the GC
3322 with which lines will be drawn. Use a color that is FACTOR or
3323 DELTA lighter or darker than the relief's background which is found
3324 in S->f->output_data.x->relief_background. If such a color cannot
3325 be allocated, use DEFAULT_PIXEL, instead. */
3328 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3330 struct relief
*relief
;
3333 unsigned long default_pixel
;
3336 struct mac_output
*di
= f
->output_data
.mac
;
3337 unsigned long mask
= GCForeground
;
3338 unsigned long pixel
;
3339 unsigned long background
= di
->relief_background
;
3340 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3342 /* MAC_TODO: Free colors (if using palette)? */
3344 /* Allocate new color. */
3345 xgcv
.foreground
= default_pixel
;
3347 if (dpyinfo
->n_planes
!= 1
3348 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3350 relief
->allocated_p
= 1;
3351 xgcv
.foreground
= relief
->pixel
= pixel
;
3354 if (relief
->gc
== 0)
3356 #if 0 /* MAC_TODO: stipple */
3357 xgcv
.stipple
= dpyinfo
->gray
;
3360 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3363 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3367 /* Set up colors for the relief lines around glyph string S. */
3370 x_setup_relief_colors (s
)
3371 struct glyph_string
*s
;
3373 struct mac_output
*di
= s
->f
->output_data
.mac
;
3374 unsigned long color
;
3376 if (s
->face
->use_box_color_for_shadows_p
)
3377 color
= s
->face
->box_color
;
3378 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3380 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3381 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3386 /* Get the background color of the face. */
3387 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3388 color
= xgcv
.background
;
3391 if (di
->white_relief
.gc
== 0
3392 || color
!= di
->relief_background
)
3394 di
->relief_background
= color
;
3395 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3396 WHITE_PIX_DEFAULT (s
->f
));
3397 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3398 BLACK_PIX_DEFAULT (s
->f
));
3403 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3404 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3405 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3406 relief. LEFT_P non-zero means draw a relief on the left side of
3407 the rectangle. RIGHT_P non-zero means draw a relief on the right
3408 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3412 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3413 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3415 int left_x
, top_y
, right_x
, bottom_y
, width
;
3416 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3419 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3424 gc
= f
->output_data
.mac
->white_relief
.gc
;
3426 gc
= f
->output_data
.mac
->black_relief
.gc
;
3427 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3431 for (i
= 0; i
< width
; ++i
)
3432 mac_draw_line (f
, gc
,
3433 left_x
+ i
* left_p
, top_y
+ i
,
3434 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3438 for (i
= 0; i
< width
; ++i
)
3439 mac_draw_line (f
, gc
,
3440 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3442 mac_reset_clip_rectangles (dpy
, gc
);
3444 gc
= f
->output_data
.mac
->black_relief
.gc
;
3446 gc
= f
->output_data
.mac
->white_relief
.gc
;
3447 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3451 for (i
= 0; i
< width
; ++i
)
3452 mac_draw_line (f
, gc
,
3453 left_x
+ i
* left_p
, bottom_y
- i
,
3454 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3458 for (i
= 0; i
< width
; ++i
)
3459 mac_draw_line (f
, gc
,
3460 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3462 mac_reset_clip_rectangles (dpy
, gc
);
3466 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3467 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3468 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3469 left side of the rectangle. RIGHT_P non-zero means draw a line
3470 on the right side of the rectangle. CLIP_RECT is the clipping
3471 rectangle to use when drawing. */
3474 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3475 left_p
, right_p
, clip_rect
)
3476 struct glyph_string
*s
;
3477 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3482 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3483 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3484 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3487 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3488 right_x
- left_x
+ 1, width
);
3492 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3493 width
, bottom_y
- top_y
+ 1);
3496 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3497 right_x
- left_x
+ 1, width
);
3501 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3502 top_y
, width
, bottom_y
- top_y
+ 1);
3504 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3505 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3509 /* Draw a box around glyph string S. */
3512 x_draw_glyph_string_box (s
)
3513 struct glyph_string
*s
;
3515 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3516 int left_p
, right_p
;
3517 struct glyph
*last_glyph
;
3520 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3521 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3522 : window_box_right (s
->w
, s
->area
));
3524 /* The glyph that may have a right box line. */
3525 last_glyph
= (s
->cmp
|| s
->img
3527 : s
->first_glyph
+ s
->nchars
- 1);
3529 width
= abs (s
->face
->box_line_width
);
3530 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3532 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3534 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3536 bottom_y
= top_y
+ s
->height
- 1;
3538 left_p
= (s
->first_glyph
->left_box_line_p
3539 || (s
->hl
== DRAW_MOUSE_FACE
3541 || s
->prev
->hl
!= s
->hl
)));
3542 right_p
= (last_glyph
->right_box_line_p
3543 || (s
->hl
== DRAW_MOUSE_FACE
3545 || s
->next
->hl
!= s
->hl
)));
3547 get_glyph_string_clip_rect (s
, &clip_rect
);
3549 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3550 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3551 left_p
, right_p
, &clip_rect
);
3554 x_setup_relief_colors (s
);
3555 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3556 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3561 /* Draw foreground of image glyph string S. */
3564 x_draw_image_foreground (s
)
3565 struct glyph_string
*s
;
3568 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3570 /* If first glyph of S has a left box line, start drawing it to the
3571 right of that line. */
3572 if (s
->face
->box
!= FACE_NO_BOX
3573 && s
->first_glyph
->left_box_line_p
3575 x
+= abs (s
->face
->box_line_width
);
3577 /* If there is a margin around the image, adjust x- and y-position
3579 if (s
->slice
.x
== 0)
3580 x
+= s
->img
->hmargin
;
3581 if (s
->slice
.y
== 0)
3582 y
+= s
->img
->vmargin
;
3586 x_set_glyph_string_clipping (s
);
3589 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3590 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3591 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3595 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3596 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3597 s
->slice
.width
, s
->slice
.height
, x
, y
);
3604 mac_copy_area (s
->img
->pixmap
,
3605 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3606 s
->slice
.width
, s
->slice
.height
, x
, y
);
3609 /* When the image has a mask, we can expect that at
3610 least part of a mouse highlight or a block cursor will
3611 be visible. If the image doesn't have a mask, make
3612 a block cursor visible by drawing a rectangle around
3613 the image. I believe it's looking better if we do
3614 nothing here for mouse-face. */
3615 if (s
->hl
== DRAW_CURSOR
)
3617 int r
= s
->img
->relief
;
3619 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3620 s
->slice
.width
+ r
*2 - 1,
3621 s
->slice
.height
+ r
*2 - 1);
3626 /* Draw a rectangle if image could not be loaded. */
3627 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3628 s
->slice
.width
- 1, s
->slice
.height
- 1);
3632 /* Draw a relief around the image glyph string S. */
3635 x_draw_image_relief (s
)
3636 struct glyph_string
*s
;
3638 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3641 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3643 /* If first glyph of S has a left box line, start drawing it to the
3644 right of that line. */
3645 if (s
->face
->box
!= FACE_NO_BOX
3646 && s
->first_glyph
->left_box_line_p
3648 x
+= abs (s
->face
->box_line_width
);
3650 /* If there is a margin around the image, adjust x- and y-position
3652 if (s
->slice
.x
== 0)
3653 x
+= s
->img
->hmargin
;
3654 if (s
->slice
.y
== 0)
3655 y
+= s
->img
->vmargin
;
3657 if (s
->hl
== DRAW_IMAGE_SUNKEN
3658 || s
->hl
== DRAW_IMAGE_RAISED
)
3660 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3661 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3665 thick
= abs (s
->img
->relief
);
3666 raised_p
= s
->img
->relief
> 0;
3671 x1
= x
+ s
->slice
.width
+ thick
- 1;
3672 y1
= y
+ s
->slice
.height
+ thick
- 1;
3674 x_setup_relief_colors (s
);
3675 get_glyph_string_clip_rect (s
, &r
);
3676 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3678 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3680 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3685 /* Draw part of the background of glyph string S. X, Y, W, and H
3686 give the rectangle to draw. */
3689 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3690 struct glyph_string
*s
;
3693 #if 0 /* MAC_TODO: stipple */
3696 /* Fill background with a stipple pattern. */
3697 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3698 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3699 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3702 #endif /* MAC_TODO */
3703 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3707 /* Draw image glyph string S.
3710 s->x +-------------------------
3713 | +-------------------------
3716 | | +-------------------
3722 x_draw_image_glyph_string (s
)
3723 struct glyph_string
*s
;
3726 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3727 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3730 height
= s
->height
- 2 * box_line_vwidth
;
3733 /* Fill background with face under the image. Do it only if row is
3734 taller than image or if image has a clip mask to reduce
3736 s
->stippled_p
= s
->face
->stipple
!= 0;
3737 if (height
> s
->slice
.height
3741 || s
->img
->pixmap
== 0
3742 || s
->width
!= s
->background_width
)
3745 if (s
->first_glyph
->left_box_line_p
3747 x
+= box_line_hwidth
;
3750 if (s
->slice
.y
== 0)
3751 y
+= box_line_vwidth
;
3753 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3755 s
->background_filled_p
= 1;
3758 /* Draw the foreground. */
3759 x_draw_image_foreground (s
);
3761 /* If we must draw a relief around the image, do it. */
3763 || s
->hl
== DRAW_IMAGE_RAISED
3764 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3765 x_draw_image_relief (s
);
3769 /* Draw stretch glyph string S. */
3772 x_draw_stretch_glyph_string (s
)
3773 struct glyph_string
*s
;
3775 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3776 s
->stippled_p
= s
->face
->stipple
!= 0;
3778 if (s
->hl
== DRAW_CURSOR
3779 && !x_stretch_cursor_p
)
3781 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3782 as wide as the stretch glyph. */
3783 int width
, background_width
= s
->background_width
;
3784 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3788 background_width
-= left_x
- x
;
3791 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3794 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3796 /* Clear rest using the GC of the original non-cursor face. */
3797 if (width
< background_width
)
3800 int w
= background_width
- width
, h
= s
->height
;
3805 if (s
->row
->mouse_face_p
3806 && cursor_in_mouse_face_p (s
->w
))
3808 x_set_mouse_face_gc (s
);
3814 get_glyph_string_clip_rect (s
, &r
);
3815 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3817 #if 0 /* MAC_TODO: stipple */
3818 if (s
->face
->stipple
)
3820 /* Fill background with a stipple pattern. */
3821 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3822 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3823 XSetFillStyle (s
->display
, gc
, FillSolid
);
3826 #endif /* MAC_TODO */
3827 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3830 else if (!s
->background_filled_p
)
3832 int background_width
= s
->background_width
;
3833 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3835 /* Don't draw into left margin, fringe or scrollbar area
3836 except for header line and mode line. */
3837 if (x
< left_x
&& !s
->row
->mode_line_p
)
3839 background_width
-= left_x
- x
;
3842 if (background_width
> 0)
3843 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3846 s
->background_filled_p
= 1;
3850 /* Draw glyph string S. */
3853 x_draw_glyph_string (s
)
3854 struct glyph_string
*s
;
3856 int relief_drawn_p
= 0;
3858 /* If S draws into the background of its successor that does not
3859 draw a cursor, draw the background of the successor first so that
3860 S can draw into it. This makes S->next use XDrawString instead
3861 of XDrawImageString. */
3862 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3863 && s
->next
->hl
!= DRAW_CURSOR
)
3865 xassert (s
->next
->img
== NULL
);
3866 x_set_glyph_string_gc (s
->next
);
3867 x_set_glyph_string_clipping (s
->next
);
3868 x_draw_glyph_string_background (s
->next
, 1);
3871 /* Set up S->gc, set clipping and draw S. */
3872 x_set_glyph_string_gc (s
);
3874 /* Draw relief (if any) in advance for char/composition so that the
3875 glyph string can be drawn over it. */
3876 if (!s
->for_overlaps
3877 && s
->face
->box
!= FACE_NO_BOX
3878 && (s
->first_glyph
->type
== CHAR_GLYPH
3879 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3882 x_set_glyph_string_clipping (s
);
3883 x_draw_glyph_string_background (s
, 1);
3884 x_draw_glyph_string_box (s
);
3885 x_set_glyph_string_clipping (s
);
3889 x_set_glyph_string_clipping (s
);
3891 switch (s
->first_glyph
->type
)
3894 x_draw_image_glyph_string (s
);
3898 x_draw_stretch_glyph_string (s
);
3902 if (s
->for_overlaps
)
3903 s
->background_filled_p
= 1;
3905 x_draw_glyph_string_background (s
, 0);
3906 x_draw_glyph_string_foreground (s
);
3909 case COMPOSITE_GLYPH
:
3910 if (s
->for_overlaps
|| s
->gidx
> 0)
3911 s
->background_filled_p
= 1;
3913 x_draw_glyph_string_background (s
, 1);
3914 x_draw_composite_glyph_string_foreground (s
);
3921 if (!s
->for_overlaps
)
3923 /* Draw underline. */
3924 if (s
->face
->underline_p
)
3926 unsigned long tem
, h
;
3930 /* Get the underline thickness. Default is 1 pixel. */
3931 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3935 y
= s
->y
+ s
->height
- h
;
3936 if (!x_underline_at_descent_line
)
3938 /* Get the underline position. This is the recommended
3939 vertical offset in pixels from the baseline to the top of
3940 the underline. This is a signed value according to the
3941 specs, and its default is
3943 ROUND ((maximum descent) / 2), with
3944 ROUND(x) = floor (x + 0.5) */
3947 if (x_use_underline_position_properties
3948 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3949 y
= s
->ybase
+ (long) tem
;
3953 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3956 if (s
->face
->underline_defaulted_p
)
3957 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3958 s
->background_width
, h
);
3962 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3963 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3964 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3965 s
->background_width
, h
);
3966 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3970 /* Draw overline. */
3971 if (s
->face
->overline_p
)
3973 unsigned long dy
= 0, h
= 1;
3975 if (s
->face
->overline_color_defaulted_p
)
3976 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3977 s
->background_width
, h
);
3981 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3982 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3983 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3984 s
->background_width
, h
);
3985 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3989 /* Draw strike-through. */
3990 if (s
->face
->strike_through_p
)
3992 unsigned long h
= 1;
3993 unsigned long dy
= (s
->height
- h
) / 2;
3995 if (s
->face
->strike_through_color_defaulted_p
)
3996 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4001 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4002 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4003 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4005 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4009 /* Draw relief if not yet drawn. */
4010 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4011 x_draw_glyph_string_box (s
);
4014 /* Reset clipping. */
4015 mac_reset_clip_rectangles (s
->display
, s
->gc
);
4018 /* Shift display to make room for inserted glyphs. */
4021 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4023 int x
, y
, width
, height
, shift_by
;
4025 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4026 x
, y
, width
, height
,
4030 /* Delete N glyphs at the nominal cursor position. Not implemented
4041 /* Clear entire frame. If updating_frame is non-null, clear that
4042 frame. Otherwise clear the selected frame. */
4045 x_clear_frame (struct frame
*f
)
4047 /* Clearing the frame will erase any cursor, so mark them all as no
4049 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4050 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4051 output_cursor
.x
= -1;
4053 /* We don't set the output cursor here because there will always
4054 follow an explicit cursor_to. */
4056 mac_clear_window (f
);
4058 /* We have to clear the scroll bars, too. If we have changed
4059 colors or something like that, then they should be notified. */
4060 x_scroll_bar_clear (f
);
4062 XFlush (FRAME_MAC_DISPLAY (f
));
4068 /* Invert the middle quarter of the frame for .15 sec. */
4070 /* We use the select system call to do the waiting, so we have to make
4071 sure it's available. If it isn't, we just won't do visual bells. */
4073 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4076 /* Subtract the `struct timeval' values X and Y, storing the result in
4077 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4080 timeval_subtract (result
, x
, y
)
4081 struct timeval
*result
, x
, y
;
4083 /* Perform the carry for the later subtraction by updating y. This
4084 is safer because on some systems the tv_sec member is unsigned. */
4085 if (x
.tv_usec
< y
.tv_usec
)
4087 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4088 y
.tv_usec
-= 1000000 * nsec
;
4092 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4094 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4095 y
.tv_usec
+= 1000000 * nsec
;
4099 /* Compute the time remaining to wait. tv_usec is certainly
4101 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4102 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4104 /* Return indication of whether the result should be considered
4106 return x
.tv_sec
< y
.tv_sec
;
4113 /* Get the height not including a menu bar widget. */
4114 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4115 /* Height of each line to flash. */
4116 int flash_height
= FRAME_LINE_HEIGHT (f
);
4117 /* These will be the left and right margins of the rectangles. */
4118 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4119 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4123 /* Don't flash the area between a scroll bar and the frame
4124 edge it is next to. */
4125 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4127 case vertical_scroll_bar_left
:
4128 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4131 case vertical_scroll_bar_right
:
4132 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4139 width
= flash_right
- flash_left
;
4143 /* If window is tall, flash top and bottom line. */
4144 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4146 mac_invert_rectangle (f
, flash_left
,
4147 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4148 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4149 width
, flash_height
);
4150 mac_invert_rectangle (f
, flash_left
,
4151 (height
- flash_height
4152 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4153 width
, flash_height
);
4156 /* If it is short, flash it all. */
4157 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4158 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4163 struct timeval wakeup
;
4165 EMACS_GET_TIME (wakeup
);
4167 /* Compute time to wait until, propagating carry from usecs. */
4168 wakeup
.tv_usec
+= 150000;
4169 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4170 wakeup
.tv_usec
%= 1000000;
4172 /* Keep waiting until past the time wakeup or any input gets
4174 while (! detect_input_pending ())
4176 struct timeval current
;
4177 struct timeval timeout
;
4179 EMACS_GET_TIME (current
);
4181 /* Break if result would be negative. */
4182 if (timeval_subtract (¤t
, wakeup
, current
))
4185 /* How long `select' should wait. */
4187 timeout
.tv_usec
= 10000;
4189 /* Try to wait that long--but we might wake up sooner. */
4190 select (0, NULL
, NULL
, NULL
, &timeout
);
4194 /* If window is tall, flash top and bottom line. */
4195 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4197 mac_invert_rectangle (f
, flash_left
,
4198 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4199 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4200 width
, flash_height
);
4201 mac_invert_rectangle (f
, flash_left
,
4202 (height
- flash_height
4203 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4204 width
, flash_height
);
4207 /* If it is short, flash it all. */
4208 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4209 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4216 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4219 /* Make audible bell. */
4224 struct frame
*f
= SELECTED_FRAME ();
4226 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4234 XFlush (FRAME_MAC_DISPLAY (f
));
4240 /* Specify how many text lines, from the top of the window,
4241 should be affected by insert-lines and delete-lines operations.
4242 This, and those operations, are used only within an update
4243 that is bounded by calls to x_update_begin and x_update_end. */
4246 XTset_terminal_window (n
)
4249 /* This function intentionally left blank. */
4254 /***********************************************************************
4256 ***********************************************************************/
4258 /* Perform an insert-lines or delete-lines operation, inserting N
4259 lines or deleting -N lines at vertical position VPOS. */
4262 x_ins_del_lines (vpos
, n
)
4269 /* Scroll part of the display as described by RUN. */
4272 x_scroll_run (w
, run
)
4276 struct frame
*f
= XFRAME (w
->frame
);
4277 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4279 /* Get frame-relative bounding box of the text display area of W,
4280 without mode lines. Include in this box the left and right
4282 window_box (w
, -1, &x
, &y
, &width
, &height
);
4284 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4285 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4286 bottom_y
= y
+ height
;
4290 /* Scrolling up. Make sure we don't copy part of the mode
4291 line at the bottom. */
4292 if (from_y
+ run
->height
> bottom_y
)
4293 height
= bottom_y
- from_y
;
4295 height
= run
->height
;
4299 /* Scolling down. Make sure we don't copy over the mode line.
4301 if (to_y
+ run
->height
> bottom_y
)
4302 height
= bottom_y
- to_y
;
4304 height
= run
->height
;
4309 /* Cursor off. Will be switched on again in x_update_window_end. */
4313 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4323 /***********************************************************************
4325 ***********************************************************************/
4333 ControlRef root_control
;
4336 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4338 ActivateControl (root_control
);
4340 x_update_cursor (f
, 1);
4344 frame_unhighlight (f
)
4348 ControlRef root_control
;
4351 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4353 DeactivateControl (root_control
);
4355 x_update_cursor (f
, 1);
4358 /* The focus has changed. Update the frames as necessary to reflect
4359 the new situation. Note that we can't change the selected frame
4360 here, because the Lisp code we are interrupting might become confused.
4361 Each event gets marked with the frame in which it occurred, so the
4362 Lisp code can tell when the switch took place by examining the events. */
4365 x_new_focus_frame (dpyinfo
, frame
)
4366 struct x_display_info
*dpyinfo
;
4367 struct frame
*frame
;
4369 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4371 if (frame
!= dpyinfo
->x_focus_frame
)
4373 /* Set this before calling other routines, so that they see
4374 the correct value of x_focus_frame. */
4375 dpyinfo
->x_focus_frame
= frame
;
4377 if (old_focus
&& old_focus
->auto_lower
)
4378 x_lower_frame (old_focus
);
4381 selected_frame
= frame
;
4382 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4384 Fselect_window (selected_frame
->selected_window
, Qnil
);
4385 choose_minibuf_frame ();
4388 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4389 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4391 pending_autoraise_frame
= 0;
4393 #if USE_MAC_FONT_PANEL
4395 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4399 x_frame_rehighlight (dpyinfo
);
4402 /* Handle FocusIn and FocusOut state changes for FRAME.
4403 If FRAME has focus and there exists more than one frame, puts
4404 a FOCUS_IN_EVENT into *BUFP. */
4407 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4409 struct mac_display_info
*dpyinfo
;
4410 struct frame
*frame
;
4411 struct input_event
*bufp
;
4413 if (type
== activeFlag
)
4415 if (dpyinfo
->x_focus_event_frame
!= frame
)
4417 x_new_focus_frame (dpyinfo
, frame
);
4418 dpyinfo
->x_focus_event_frame
= frame
;
4420 /* Don't stop displaying the initial startup message
4421 for a switch-frame event we don't need. */
4422 if (GC_NILP (Vterminal_frame
)
4423 && GC_CONSP (Vframe_list
)
4424 && !GC_NILP (XCDR (Vframe_list
)))
4426 bufp
->kind
= FOCUS_IN_EVENT
;
4427 XSETFRAME (bufp
->frame_or_window
, frame
);
4433 if (dpyinfo
->x_focus_event_frame
== frame
)
4435 dpyinfo
->x_focus_event_frame
= 0;
4436 x_new_focus_frame (dpyinfo
, 0);
4441 /* The focus may have changed. Figure out if it is a real focus change,
4442 by checking both FocusIn/Out and Enter/LeaveNotify events.
4444 Returns FOCUS_IN_EVENT event in *BUFP. */
4447 x_detect_focus_change (dpyinfo
, event
, bufp
)
4448 struct mac_display_info
*dpyinfo
;
4449 const EventRecord
*event
;
4450 struct input_event
*bufp
;
4452 struct frame
*frame
;
4454 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4458 /* On Mac, this is only called from focus events, so no switch needed. */
4459 mac_focus_changed ((event
->modifiers
& activeFlag
),
4460 dpyinfo
, frame
, bufp
);
4464 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4467 x_mouse_leave (dpyinfo
)
4468 struct x_display_info
*dpyinfo
;
4470 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4473 /* The focus has changed, or we have redirected a frame's focus to
4474 another frame (this happens when a frame uses a surrogate
4475 mini-buffer frame). Shift the highlight as appropriate.
4477 The FRAME argument doesn't necessarily have anything to do with which
4478 frame is being highlighted or un-highlighted; we only use it to find
4479 the appropriate X display info. */
4482 XTframe_rehighlight (frame
)
4483 struct frame
*frame
;
4485 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4489 x_frame_rehighlight (dpyinfo
)
4490 struct x_display_info
*dpyinfo
;
4492 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4494 if (dpyinfo
->x_focus_frame
)
4496 dpyinfo
->x_highlight_frame
4497 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4498 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4499 : dpyinfo
->x_focus_frame
);
4500 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4502 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4503 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4507 dpyinfo
->x_highlight_frame
= 0;
4509 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4512 frame_unhighlight (old_highlight
);
4513 if (dpyinfo
->x_highlight_frame
)
4514 frame_highlight (dpyinfo
->x_highlight_frame
);
4520 /* Convert a keysym to its name. */
4523 x_get_keysym_name (keysym
)
4530 value
= XKeysymToString (keysym
);
4541 /* Function to report a mouse movement to the mainstream Emacs code.
4542 The input handler calls this.
4544 We have received a mouse movement event, which is given in *event.
4545 If the mouse is over a different glyph than it was last time, tell
4546 the mainstream emacs code by setting mouse_moved. If not, ask for
4547 another motion event, so we can check again the next time it moves. */
4549 static Point last_mouse_motion_position
;
4550 static Lisp_Object last_mouse_motion_frame
;
4553 note_mouse_movement (frame
, pos
)
4557 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4558 #if TARGET_API_MAC_CARBON
4562 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4563 last_mouse_motion_position
= *pos
;
4564 XSETFRAME (last_mouse_motion_frame
, frame
);
4566 if (frame
== dpyinfo
->mouse_face_mouse_frame
4567 #if TARGET_API_MAC_CARBON
4568 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4570 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4574 /* This case corresponds to LeaveNotify in X11. If we move
4575 outside the frame, then we're certainly no longer on any text
4577 clear_mouse_face (dpyinfo
);
4578 dpyinfo
->mouse_face_mouse_frame
= 0;
4579 if (!dpyinfo
->grabbed
)
4580 FRAME_RIF (frame
)->define_frame_cursor (frame
,
4581 frame
->output_data
.mac
->nontext_cursor
);
4584 /* Has the mouse moved off the glyph it was on at the last sighting? */
4585 if (frame
!= last_mouse_glyph_frame
4586 || !PtInRect (*pos
, &last_mouse_glyph
))
4588 frame
->mouse_moved
= 1;
4589 last_mouse_scroll_bar
= Qnil
;
4590 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4591 /* Remember which glyph we're now on. */
4592 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4593 last_mouse_glyph_frame
= frame
;
4601 /************************************************************************
4603 ************************************************************************/
4605 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4608 redo_mouse_highlight ()
4610 if (!NILP (last_mouse_motion_frame
)
4611 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4612 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4613 last_mouse_motion_position
.h
,
4614 last_mouse_motion_position
.v
);
4618 static struct frame
*
4619 mac_focus_frame (dpyinfo
)
4620 struct mac_display_info
*dpyinfo
;
4622 if (dpyinfo
->x_focus_frame
)
4623 return dpyinfo
->x_focus_frame
;
4625 /* Mac version may get events, such as a menu bar click, even when
4626 all the frames are invisible. In this case, we regard the
4627 event came to the selected frame. */
4628 return SELECTED_FRAME ();
4632 /* Return the current position of the mouse.
4633 *FP should be a frame which indicates which display to ask about.
4635 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4636 and *PART to the frame, window, and scroll bar part that the mouse
4637 is over. Set *X and *Y to the portion and whole of the mouse's
4638 position on the scroll bar.
4640 If the mouse movement started elsewhere, set *FP to the frame the
4641 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4644 Set *TIME to the server time-stamp for the time at which the mouse
4645 was at this position.
4647 Don't store anything if we don't have a valid set of values to report.
4649 This clears the mouse_moved flag, so we can wait for the next mouse
4653 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4656 Lisp_Object
*bar_window
;
4657 enum scroll_bar_part
*part
;
4659 unsigned long *time
;
4665 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4666 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4669 Lisp_Object frame
, tail
;
4671 /* Clear the mouse-moved flag for every frame on this display. */
4672 FOR_EACH_FRAME (tail
, frame
)
4673 XFRAME (frame
)->mouse_moved
= 0;
4675 last_mouse_scroll_bar
= Qnil
;
4677 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4678 && FRAME_LIVE_P (last_mouse_frame
))
4679 f1
= last_mouse_frame
;
4681 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4685 /* Ok, we found a frame. Store all the values.
4686 last_mouse_glyph is a rectangle used to reduce the
4687 generation of mouse events. To not miss any motion
4688 events, we must divide the frame into rectangles of the
4689 size of the smallest character that could be displayed
4690 on it, i.e. into the same rectangles that matrices on
4691 the frame are divided into. */
4694 #if TARGET_API_MAC_CARBON
4695 GetGlobalMouse (&mouse_pos
);
4696 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4697 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4699 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4700 GetMouse (&mouse_pos
);
4702 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4704 last_mouse_glyph_frame
= f1
;
4709 XSETINT (*x
, mouse_pos
.h
);
4710 XSETINT (*y
, mouse_pos
.v
);
4711 *time
= last_mouse_movement_time
;
4719 /************************************************************************
4721 ************************************************************************/
4723 #ifdef USE_TOOLKIT_SCROLL_BARS
4725 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4726 static OSStatus install_scroll_bar_timer
P_ ((void));
4727 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4728 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4729 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4730 struct input_event
*));
4731 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4733 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4734 ControlPartCode
, Point
,
4735 struct input_event
*));
4736 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4737 struct input_event
*));
4738 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4739 Point
, struct input_event
*));
4740 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4743 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4745 static int last_scroll_bar_part
;
4747 static EventLoopTimerRef scroll_bar_timer
;
4749 static int scroll_bar_timer_event_posted_p
;
4751 #define SCROLL_BAR_FIRST_DELAY 0.5
4752 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4755 scroll_bar_timer_callback (timer
, data
)
4756 EventLoopTimerRef timer
;
4761 err
= mac_post_mouse_moved_event ();
4763 scroll_bar_timer_event_posted_p
= 1;
4767 install_scroll_bar_timer ()
4769 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4771 if (scroll_bar_timer_callbackUPP
== NULL
)
4772 scroll_bar_timer_callbackUPP
=
4773 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4775 if (scroll_bar_timer
== NULL
)
4776 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4777 kEventDurationForever as delays. */
4779 InstallEventLoopTimer (GetCurrentEventLoop (),
4780 kEventDurationForever
, kEventDurationForever
,
4781 scroll_bar_timer_callbackUPP
, NULL
,
4786 set_scroll_bar_timer (delay
)
4787 EventTimerInterval delay
;
4789 if (scroll_bar_timer
== NULL
)
4790 install_scroll_bar_timer ();
4792 scroll_bar_timer_event_posted_p
= 0;
4794 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4798 control_part_code_to_scroll_bar_part (part_code
)
4799 ControlPartCode part_code
;
4803 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4804 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4805 case kControlPageUpPart
: return scroll_bar_above_handle
;
4806 case kControlPageDownPart
: return scroll_bar_below_handle
;
4807 case kControlIndicatorPart
: return scroll_bar_handle
;
4814 construct_scroll_bar_click (bar
, part
, bufp
)
4815 struct scroll_bar
*bar
;
4817 struct input_event
*bufp
;
4819 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4820 bufp
->frame_or_window
= bar
->window
;
4824 XSETINT (bufp
->x
, 0);
4825 XSETINT (bufp
->y
, 0);
4826 bufp
->modifiers
= 0;
4830 get_control_part_bounds (ch
, part_code
, rect
)
4832 ControlPartCode part_code
;
4835 RgnHandle region
= NewRgn ();
4838 err
= GetControlRegion (ch
, part_code
, region
);
4840 GetRegionBounds (region
, rect
);
4841 DisposeRgn (region
);
4847 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4848 struct scroll_bar
*bar
;
4849 ControlPartCode part_code
;
4851 struct input_event
*bufp
;
4853 int part
= control_part_code_to_scroll_bar_part (part_code
);
4858 if (part
!= scroll_bar_handle
)
4860 construct_scroll_bar_click (bar
, part
, bufp
);
4861 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4862 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4863 bar
->dragging
= Qnil
;
4869 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4870 kControlIndicatorPart
, &r
);
4871 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4874 last_scroll_bar_part
= part
;
4875 tracked_scroll_bar
= bar
;
4879 x_scroll_bar_handle_release (bar
, bufp
)
4880 struct scroll_bar
*bar
;
4881 struct input_event
*bufp
;
4883 if (last_scroll_bar_part
!= scroll_bar_handle
4884 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4885 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4887 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4888 set_scroll_bar_timer (kEventDurationForever
);
4890 last_scroll_bar_part
= -1;
4891 bar
->dragging
= Qnil
;
4892 tracked_scroll_bar
= NULL
;
4896 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4898 struct scroll_bar
*bar
;
4900 struct input_event
*bufp
;
4902 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4904 if (last_scroll_bar_part
== scroll_bar_handle
)
4909 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4910 kControlIndicatorPart
, &r
);
4912 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4913 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4915 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4916 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4920 if (top
> top_range
)
4923 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4924 XSETINT (bufp
->x
, top
);
4925 XSETINT (bufp
->y
, top_range
);
4929 ControlPartCode part_code
;
4930 int unhilite_p
= 0, part
;
4932 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4936 part
= control_part_code_to_scroll_bar_part (part_code
);
4938 switch (last_scroll_bar_part
)
4940 case scroll_bar_above_handle
:
4941 case scroll_bar_below_handle
:
4942 if (part
!= scroll_bar_above_handle
4943 && part
!= scroll_bar_below_handle
)
4947 case scroll_bar_up_arrow
:
4948 case scroll_bar_down_arrow
:
4949 if (part
!= scroll_bar_up_arrow
4950 && part
!= scroll_bar_down_arrow
)
4957 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4958 else if (part
!= last_scroll_bar_part
4959 || scroll_bar_timer_event_posted_p
)
4961 construct_scroll_bar_click (bar
, part
, bufp
);
4962 last_scroll_bar_part
= part
;
4963 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4964 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4969 /* Set the thumb size and position of scroll bar BAR. We are currently
4970 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4973 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4974 struct scroll_bar
*bar
;
4975 int portion
, position
, whole
;
4977 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4978 int value
, viewsize
, maximum
;
4980 if (XINT (bar
->track_height
) == 0)
4983 if (whole
<= portion
)
4984 value
= 0, viewsize
= 1, maximum
= 0;
4989 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4990 scale
= (float) maximum
/ (whole
- portion
);
4991 value
= position
* scale
+ 0.5f
;
4992 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
4997 if (GetControlViewSize (ch
) != viewsize
4998 || GetControl32BitValue (ch
) != value
4999 || GetControl32BitMaximum (ch
) != maximum
)
5001 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5002 SetControlVisibility (ch
, false, false);
5004 SetControl32BitMaximum (ch
, maximum
);
5005 SetControl32BitValue (ch
, value
);
5006 SetControlViewSize (ch
, viewsize
);
5008 SetControlVisibility (ch
, true, true);
5014 #endif /* USE_TOOLKIT_SCROLL_BARS */
5018 /************************************************************************
5019 Scroll bars, general
5020 ************************************************************************/
5022 /* Create a scroll bar and return the scroll bar vector for it. W is
5023 the Emacs window on which to create the scroll bar. TOP, LEFT,
5024 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5027 static struct scroll_bar
*
5028 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5030 int top
, left
, width
, height
, disp_top
, disp_height
;
5032 struct frame
*f
= XFRAME (w
->frame
);
5033 struct scroll_bar
*bar
5034 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5042 r
.right
= left
+ width
;
5043 r
.bottom
= disp_top
+ disp_height
;
5046 mac_prepare_for_quickdraw (f
);
5048 #if TARGET_API_MAC_CARBON
5049 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5050 #ifdef USE_TOOLKIT_SCROLL_BARS
5053 width
< disp_height
,
5055 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5057 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5058 0, 0, 0, scrollBarProc
, (long) bar
);
5060 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5062 XSETWINDOW (bar
->window
, w
);
5063 XSETINT (bar
->top
, top
);
5064 XSETINT (bar
->left
, left
);
5065 XSETINT (bar
->width
, width
);
5066 XSETINT (bar
->height
, height
);
5067 XSETINT (bar
->start
, 0);
5068 XSETINT (bar
->end
, 0);
5069 bar
->dragging
= Qnil
;
5071 bar
->fringe_extended_p
= Qnil
;
5073 #ifdef USE_TOOLKIT_SCROLL_BARS
5074 bar
->track_top
= Qnil
;
5075 bar
->track_height
= Qnil
;
5076 bar
->min_handle
= Qnil
;
5079 /* Add bar to its frame's list of scroll bars. */
5080 bar
->next
= FRAME_SCROLL_BARS (f
);
5082 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5083 if (!NILP (bar
->next
))
5084 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5091 /* Draw BAR's handle in the proper position.
5093 If the handle is already drawn from START to END, don't bother
5094 redrawing it, unless REBUILD is non-zero; in that case, always
5095 redraw it. (REBUILD is handy for drawing the handle after expose
5098 Normally, we want to constrain the start and end of the handle to
5099 fit inside its rectangle, but if the user is dragging the scroll
5100 bar handle, we want to let them drag it down all the way, so that
5101 the bar's top is as far down as it goes; otherwise, there's no way
5102 to move to the very end of the buffer. */
5104 #ifndef USE_TOOLKIT_SCROLL_BARS
5107 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5108 struct scroll_bar
*bar
;
5112 int dragging
= ! NILP (bar
->dragging
);
5113 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5114 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5115 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5116 int length
= end
- start
;
5118 /* If the display is already accurate, do nothing. */
5120 && start
== XINT (bar
->start
)
5121 && end
== XINT (bar
->end
))
5126 /* Make sure the values are reasonable, and try to preserve the
5127 distance between start and end. */
5130 else if (start
> top_range
)
5132 end
= start
+ length
;
5136 else if (end
> top_range
&& ! dragging
)
5139 /* Store the adjusted setting in the scroll bar. */
5140 XSETINT (bar
->start
, start
);
5141 XSETINT (bar
->end
, end
);
5143 /* Clip the end position, just for display. */
5144 if (end
> top_range
)
5147 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5148 top positions, to make sure the handle is always at least that
5149 many pixels tall. */
5150 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5152 SetControlMinimum (ch
, 0);
5153 /* Don't inadvertently activate deactivated scroll bars */
5154 if (GetControlMaximum (ch
) != -1)
5155 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5157 SetControlValue (ch
, start
);
5158 #if TARGET_API_MAC_CARBON
5159 SetControlViewSize (ch
, end
- start
);
5165 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5167 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5171 x_scroll_bar_remove (bar
)
5172 struct scroll_bar
*bar
;
5174 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5179 mac_prepare_for_quickdraw (f
);
5181 /* Destroy the Mac scroll bar control */
5182 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5184 /* Disassociate this scroll bar from its window. */
5185 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5191 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5192 that we are displaying PORTION characters out of a total of WHOLE
5193 characters, starting at POSITION. If WINDOW has no scroll bar,
5197 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5199 int portion
, whole
, position
;
5201 struct frame
*f
= XFRAME (w
->frame
);
5202 struct scroll_bar
*bar
;
5203 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5204 int window_y
, window_height
;
5206 int fringe_extended_p
;
5209 /* Get window dimensions. */
5210 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5212 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5213 height
= window_height
;
5215 /* Compute the left edge of the scroll bar area. */
5216 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5218 /* Compute the width of the scroll bar which might be less than
5219 the width of the area reserved for the scroll bar. */
5220 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5221 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5225 /* Compute the left edge of the scroll bar. */
5226 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5227 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5229 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5231 /* Adjustments according to Inside Macintosh to make it look nice */
5233 disp_height
= height
;
5240 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5246 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5251 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5252 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5253 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5254 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5255 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5257 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5258 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5259 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5260 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5263 /* Does the scroll bar exist yet? */
5264 if (NILP (w
->vertical_scroll_bar
))
5268 if (fringe_extended_p
)
5269 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5272 mac_clear_area (f
, left
, top
, width
, height
);
5274 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5276 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5280 /* It may just need to be moved and resized. */
5283 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5284 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5288 /* If already correctly positioned, do nothing. */
5289 if (!(XINT (bar
->left
) == sb_left
5290 && XINT (bar
->top
) == top
5291 && XINT (bar
->width
) == sb_width
5292 && XINT (bar
->height
) == height
5294 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5298 /* Since toolkit scroll bars are smaller than the space reserved
5299 for them on the frame, we have to clear "under" them. */
5301 if (fringe_extended_p
)
5302 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5305 mac_clear_area (f
, left
, top
, width
, height
);
5308 mac_prepare_for_quickdraw (f
);
5311 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5312 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5314 #ifndef USE_TOOLKIT_SCROLL_BARS
5315 if (sb_width
< disp_height
)
5319 /* Remember new settings. */
5320 XSETINT (bar
->left
, sb_left
);
5321 XSETINT (bar
->top
, top
);
5322 XSETINT (bar
->width
, sb_width
);
5323 XSETINT (bar
->height
, height
);
5324 #ifdef USE_TOOLKIT_SCROLL_BARS
5325 bar
->track_top
= Qnil
;
5326 bar
->track_height
= Qnil
;
5327 bar
->min_handle
= Qnil
;
5335 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5338 #ifdef USE_TOOLKIT_SCROLL_BARS
5339 if (NILP (bar
->track_top
))
5341 if (sb_width
>= disp_height
5343 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5347 XSETINT (bar
->track_top
, 0);
5348 XSETINT (bar
->track_height
, 0);
5349 XSETINT (bar
->min_handle
, 0);
5353 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5358 SetControl32BitMinimum (ch
, 0);
5359 SetControl32BitMaximum (ch
, 1 << 30);
5360 SetControlViewSize (ch
, 1);
5362 /* Move the scroll bar thumb to the top. */
5363 SetControl32BitValue (ch
, 0);
5364 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5366 /* Move the scroll bar thumb to the bottom. */
5367 SetControl32BitValue (ch
, 1 << 30);
5368 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5370 UnionRect (&r0
, &r1
, &r0
);
5371 XSETINT (bar
->track_top
, r0
.top
);
5372 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5373 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5375 /* Don't show the scroll bar if its height is not enough to
5376 display the scroll bar thumb. */
5377 if (r0
.bottom
- r0
.top
> 0)
5384 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5385 #else /* not USE_TOOLKIT_SCROLL_BARS */
5386 /* Set the scroll bar's current state, unless we're currently being
5388 if (NILP (bar
->dragging
))
5390 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5393 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5396 int start
= ((double) position
* top_range
) / whole
;
5397 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5398 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5401 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5405 /* The following three hooks are used when we're doing a thorough
5406 redisplay of the frame. We don't explicitly know which scroll bars
5407 are going to be deleted, because keeping track of when windows go
5408 away is a real pain - "Can you say set-window-configuration, boys
5409 and girls?" Instead, we just assert at the beginning of redisplay
5410 that *all* scroll bars are to be removed, and then save a scroll bar
5411 from the fiery pit when we actually redisplay its window. */
5413 /* Arrange for all scroll bars on FRAME to be removed at the next call
5414 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5415 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5418 XTcondemn_scroll_bars (frame
)
5421 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5422 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5425 bar
= FRAME_SCROLL_BARS (frame
);
5426 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5427 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5428 XSCROLL_BAR (bar
)->prev
= Qnil
;
5429 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5430 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5431 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5436 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5437 Note that WINDOW isn't necessarily condemned at all. */
5440 XTredeem_scroll_bar (window
)
5441 struct window
*window
;
5443 struct scroll_bar
*bar
;
5446 /* We can't redeem this window's scroll bar if it doesn't have one. */
5447 if (NILP (window
->vertical_scroll_bar
))
5450 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5452 /* Unlink it from the condemned list. */
5453 f
= XFRAME (WINDOW_FRAME (window
));
5454 if (NILP (bar
->prev
))
5456 /* If the prev pointer is nil, it must be the first in one of
5458 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5459 /* It's not condemned. Everything's fine. */
5461 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5462 window
->vertical_scroll_bar
))
5463 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5465 /* If its prev pointer is nil, it must be at the front of
5466 one or the other! */
5470 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5472 if (! NILP (bar
->next
))
5473 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5475 bar
->next
= FRAME_SCROLL_BARS (f
);
5477 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5478 if (! NILP (bar
->next
))
5479 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5482 /* Remove all scroll bars on FRAME that haven't been saved since the
5483 last call to `*condemn_scroll_bars_hook'. */
5486 XTjudge_scroll_bars (f
)
5489 Lisp_Object bar
, next
;
5491 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5493 /* Clear out the condemned list now so we won't try to process any
5494 more events on the hapless scroll bars. */
5495 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5497 for (; ! NILP (bar
); bar
= next
)
5499 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5501 x_scroll_bar_remove (b
);
5504 b
->next
= b
->prev
= Qnil
;
5507 /* Now there should be no references to the condemned scroll bars,
5508 and they should get garbage-collected. */
5512 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5513 is set to something other than NO_EVENT, it is enqueued.
5515 This may be called from a signal handler, so we have to ignore GC
5519 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5520 struct scroll_bar
*bar
;
5521 ControlPartCode part_code
;
5522 const EventRecord
*er
;
5523 struct input_event
*bufp
;
5525 int win_y
, top_range
;
5527 if (! GC_WINDOWP (bar
->window
))
5530 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5531 bufp
->frame_or_window
= bar
->window
;
5534 bar
->dragging
= Qnil
;
5538 case kControlUpButtonPart
:
5539 bufp
->part
= scroll_bar_up_arrow
;
5541 case kControlDownButtonPart
:
5542 bufp
->part
= scroll_bar_down_arrow
;
5544 case kControlPageUpPart
:
5545 bufp
->part
= scroll_bar_above_handle
;
5547 case kControlPageDownPart
:
5548 bufp
->part
= scroll_bar_below_handle
;
5550 #if TARGET_API_MAC_CARBON
5553 case kControlIndicatorPart
:
5555 if (er
->what
== mouseDown
)
5556 bar
->dragging
= make_number (0);
5557 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5558 bufp
->part
= scroll_bar_handle
;
5562 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5563 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5565 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5569 if (! NILP (bar
->dragging
))
5570 win_y
-= XINT (bar
->dragging
);
5574 if (win_y
> top_range
)
5577 XSETINT (bufp
->x
, win_y
);
5578 XSETINT (bufp
->y
, top_range
);
5581 #ifndef USE_TOOLKIT_SCROLL_BARS
5583 /* Handle some mouse motion while someone is dragging the scroll bar.
5585 This may be called from a signal handler, so we have to ignore GC
5589 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5590 struct scroll_bar
*bar
;
5594 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5596 last_mouse_movement_time
= t
;
5599 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5601 /* If we're dragging the bar, display it. */
5602 if (! GC_NILP (bar
->dragging
))
5604 /* Where should the handle be now? */
5605 int new_start
= y_pos
- 24;
5607 if (new_start
!= XINT (bar
->start
))
5609 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5611 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5616 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5618 /* Return information to the user about the current position of the mouse
5619 on the scroll bar. */
5622 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5624 Lisp_Object
*bar_window
;
5625 enum scroll_bar_part
*part
;
5627 unsigned long *time
;
5629 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5630 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5631 #if TARGET_API_MAC_CARBON
5632 WindowRef wp
= GetControlOwner (ch
);
5634 WindowRef wp
= (*ch
)->contrlOwner
;
5637 struct frame
*f
= mac_window_to_frame (wp
);
5638 int win_y
, top_range
;
5640 #if TARGET_API_MAC_CARBON
5641 GetGlobalMouse (&mouse_pos
);
5642 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5643 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5645 SetPortWindowPort (wp
);
5646 GetMouse (&mouse_pos
);
5649 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5650 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5652 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5656 if (! NILP (bar
->dragging
))
5657 win_y
-= XINT (bar
->dragging
);
5661 if (win_y
> top_range
)
5665 *bar_window
= bar
->window
;
5667 if (! NILP (bar
->dragging
))
5668 *part
= scroll_bar_handle
;
5669 else if (win_y
< XINT (bar
->start
))
5670 *part
= scroll_bar_above_handle
;
5671 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5672 *part
= scroll_bar_handle
;
5674 *part
= scroll_bar_below_handle
;
5676 XSETINT (*x
, win_y
);
5677 XSETINT (*y
, top_range
);
5680 last_mouse_scroll_bar
= Qnil
;
5682 *time
= last_mouse_movement_time
;
5686 /* The screen has been cleared so we may have changed foreground or
5687 background colors, and the scroll bars may need to be redrawn.
5688 Clear out the scroll bars, and ask for expose events, so we can
5692 x_scroll_bar_clear (f
)
5695 XTcondemn_scroll_bars (f
);
5696 XTjudge_scroll_bars (f
);
5700 /***********************************************************************
5702 ***********************************************************************/
5705 /* In identifiers such as function/variable names, Emacs tool bar is
5706 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5708 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5709 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5711 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5712 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5713 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5714 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5715 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5716 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5717 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5719 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5720 static void mac_handle_origin_change
P_ ((struct frame
*));
5721 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5725 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5732 mac_get_window_bounds (f
, &inner
, &outer
);
5734 switch (win_gravity
)
5736 case NorthWestGravity
:
5738 case SouthWestGravity
:
5739 left
+= inner
.left
- outer
.left
;
5745 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5748 case NorthEastGravity
:
5750 case SouthEastGravity
:
5751 left
+= inner
.right
- outer
.right
;
5755 switch (win_gravity
)
5757 case NorthWestGravity
:
5759 case NorthEastGravity
:
5760 top
+= inner
.top
- outer
.top
;
5766 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5769 case SouthWestGravity
:
5771 case SouthEastGravity
:
5772 top
+= inner
.bottom
- outer
.bottom
;
5776 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5780 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5787 mac_get_window_bounds (f
, &inner
, &outer
);
5789 switch (win_gravity
)
5791 case NorthWestGravity
:
5793 case SouthWestGravity
:
5800 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5801 - (inner
.right
- inner
.left
)) / 2;
5804 case NorthEastGravity
:
5806 case SouthEastGravity
:
5807 *left
= outer
.right
- (inner
.right
- inner
.left
);
5811 switch (win_gravity
)
5813 case NorthWestGravity
:
5815 case NorthEastGravity
:
5822 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5823 - (inner
.bottom
- inner
.top
)) / 2;
5826 case SouthWestGravity
:
5828 case SouthEastGravity
:
5829 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5835 mac_handle_toolbar_event (next_handler
, event
, data
)
5836 EventHandlerCallRef next_handler
;
5840 OSStatus err
, result
= eventNotHandledErr
;
5842 switch (GetEventKind (event
))
5844 case kEventToolbarGetDefaultIdentifiers
:
5848 case kEventToolbarGetAllowedIdentifiers
:
5850 CFMutableArrayRef array
;
5852 GetEventParameter (event
, kEventParamMutableArray
,
5853 typeCFMutableArrayRef
, NULL
,
5854 sizeof (CFMutableArrayRef
), NULL
, &array
);
5855 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5860 case kEventToolbarCreateItemWithIdentifier
:
5862 CFStringRef identifier
;
5863 HIToolbarItemRef item
= NULL
;
5865 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
5866 typeCFStringRef
, NULL
,
5867 sizeof (CFStringRef
), NULL
, &identifier
);
5869 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
5870 == kCFCompareEqualTo
)
5871 HIToolbarItemCreate (identifier
,
5872 kHIToolbarItemAllowDuplicates
5873 | kHIToolbarItemCantBeRemoved
, &item
);
5877 SetEventParameter (event
, kEventParamToolbarItem
,
5878 typeHIToolbarItemRef
,
5879 sizeof (HIToolbarItemRef
), &item
);
5893 mac_image_spec_to_cg_image (f
, image
)
5897 if (!valid_image_p (image
))
5901 int img_id
= lookup_image (f
, image
);
5902 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
5904 prepare_image_for_display (f
, img
);
5906 return img
->data
.ptr_val
;
5910 /* Create a tool bar for frame F. */
5913 mac_create_frame_tool_bar (f
)
5917 HIToolbarRef toolbar
;
5919 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
5923 static const EventTypeSpec specs
[] =
5924 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
5925 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
5926 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
5928 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
5929 mac_handle_toolbar_event
,
5930 GetEventTypeCount (specs
), specs
,
5935 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
5938 static const EventTypeSpec specs
[] =
5939 {{kEventClassCommand
, kEventCommandProcess
}};
5941 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
5942 mac_handle_toolbar_command_event
,
5943 GetEventTypeCount (specs
),
5947 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
5950 CFRelease (toolbar
);
5955 /* Update the tool bar for frame F. Add new buttons and remove old. */
5958 update_frame_tool_bar (f
)
5961 HIToolbarRef toolbar
= NULL
;
5963 CFArrayRef old_items
= NULL
;
5965 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
5966 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5970 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5971 if (toolbar
== NULL
)
5973 mac_create_frame_tool_bar (f
);
5974 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5975 if (toolbar
== NULL
)
5977 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
5978 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
5981 HIToolbarCopyItems (toolbar
, &old_items
);
5982 if (old_items
== NULL
)
5985 old_count
= CFArrayGetCount (old_items
);
5987 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
5989 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5991 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
5992 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
5995 CGImageRef cg_image
;
5997 HIToolbarItemRef item
;
5999 /* If image is a vector, choose the image according to the
6001 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6002 if (VECTORP (image
))
6006 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6007 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6010 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6011 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6013 xassert (ASIZE (image
) >= idx
);
6014 image
= AREF (image
, idx
);
6019 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6020 /* Ignore invalid image specifications. */
6021 if (cg_image
== NULL
)
6024 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6028 if (pos
< old_count
)
6030 CGImageRef old_cg_image
= NULL
;
6031 CFStringRef old_label
= NULL
;
6032 Boolean old_enabled_p
;
6034 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6036 HIToolbarItemCopyImage (item
, &old_cg_image
);
6037 if (cg_image
!= old_cg_image
)
6038 HIToolbarItemSetImage (item
, cg_image
);
6039 CGImageRelease (old_cg_image
);
6041 HIToolbarItemCopyLabel (item
, &old_label
);
6042 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6043 HIToolbarItemSetLabel (item
, label
);
6044 CFRelease (old_label
);
6046 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6047 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6048 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6053 HIToolbarCreateItemWithIdentifier (toolbar
,
6054 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6058 HIToolbarItemSetImage (item
, cg_image
);
6059 HIToolbarItemSetLabel (item
, label
);
6060 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6061 HIToolbarAppendItem (toolbar
, item
);
6069 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6074 CFRelease (old_items
);
6076 while (pos
< old_count
)
6077 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6079 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6080 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6081 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6082 toolbar visibility change. */
6083 mac_handle_origin_change (f
);
6084 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6086 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6087 /* If the title bar is completely outside the screen, adjust the
6089 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6090 kWindowConstrainMoveRegardlessOfFit
6091 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6092 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6099 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6100 doesn't deallocate the resources. */
6103 free_frame_tool_bar (f
)
6106 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6108 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6111 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6112 f
== mac_focus_frame (dpyinfo
));
6113 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6114 on toolbar visibility change. */
6115 mac_handle_origin_change (f
);
6121 mac_tool_bar_note_mouse_movement (f
, event
)
6126 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6128 HIViewRef item_view
;
6131 mouse_down_p
= (dpyinfo
->grabbed
6132 && f
== last_mouse_frame
6133 && FRAME_LIVE_P (f
));
6137 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6139 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6140 toolbar item view seems to have the same command ID with that of
6141 the toolbar item. */
6143 err
= GetControlCommandID (item_view
, &command_id
);
6144 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6146 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6148 if (i
< f
->n_tool_bar_items
)
6151 HIViewRef content_view
;
6153 err
= HIViewGetBounds (item_view
, &bounds
);
6155 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6156 kHIViewWindowContentID
, &content_view
);
6158 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6160 SetRect (&last_mouse_glyph
,
6161 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6162 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6164 help_echo_object
= help_echo_window
= Qnil
;
6166 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6167 if (NILP (help_echo_string
))
6168 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6174 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6175 EventHandlerCallRef next_handler
;
6179 OSStatus err
, result
= eventNotHandledErr
;
6180 struct frame
*f
= (struct frame
*) data
;
6183 err
= GetEventParameter (event
, kEventParamDirectObject
,
6184 typeHICommand
, NULL
,
6185 sizeof (HICommand
), NULL
, &command
);
6189 switch (GetEventKind (event
))
6191 case kEventCommandProcess
:
6192 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6193 result
= CallNextEventHandler (next_handler
, event
);
6196 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6198 if (i
< f
->n_tool_bar_items
6199 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6202 struct input_event buf
;
6206 XSETFRAME (frame
, f
);
6207 buf
.kind
= TOOL_BAR_EVENT
;
6208 buf
.frame_or_window
= frame
;
6210 kbd_buffer_store_event (&buf
);
6212 buf
.kind
= TOOL_BAR_EVENT
;
6213 buf
.frame_or_window
= frame
;
6214 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6215 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6216 kbd_buffer_store_event (&buf
);
6230 #endif /* USE_MAC_TOOLBAR */
6233 /***********************************************************************
6235 ***********************************************************************/
6237 /* Set clipping for output in glyph row ROW. W is the window in which
6238 we operate. GC is the graphics context to set clipping in.
6240 ROW may be a text row or, e.g., a mode line. Text rows must be
6241 clipped to the interior of the window dedicated to text display,
6242 mode lines must be clipped to the whole window. */
6245 x_clip_to_row (w
, row
, area
, gc
)
6247 struct glyph_row
*row
;
6251 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6253 int window_x
, window_y
, window_width
;
6255 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6257 clip_rect
.left
= window_x
;
6258 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6259 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6260 clip_rect
.right
= clip_rect
.left
+ window_width
;
6261 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6263 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6267 /* Draw a hollow box cursor on window W in glyph row ROW. */
6270 x_draw_hollow_cursor (w
, row
)
6272 struct glyph_row
*row
;
6274 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6275 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6276 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6279 struct glyph
*cursor_glyph
;
6282 /* Get the glyph the cursor is on. If we can't tell because
6283 the current matrix is invalid or such, give up. */
6284 cursor_glyph
= get_phys_cursor_glyph (w
);
6285 if (cursor_glyph
== NULL
)
6288 /* Compute frame-relative coordinates for phys cursor. */
6289 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6290 wd
= w
->phys_cursor_width
;
6292 /* The foreground of cursor_gc is typically the same as the normal
6293 background color, which can cause the cursor box to be invisible. */
6294 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6295 if (dpyinfo
->scratch_cursor_gc
)
6296 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6298 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6299 GCForeground
, &xgcv
);
6300 gc
= dpyinfo
->scratch_cursor_gc
;
6302 /* Set clipping, draw the rectangle, and reset clipping again. */
6303 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6304 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6305 mac_reset_clip_rectangles (dpy
, gc
);
6309 /* Draw a bar cursor on window W in glyph row ROW.
6311 Implementation note: One would like to draw a bar cursor with an
6312 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6313 Unfortunately, I didn't find a font yet that has this property set.
6317 x_draw_bar_cursor (w
, row
, width
, kind
)
6319 struct glyph_row
*row
;
6321 enum text_cursor_kinds kind
;
6323 struct frame
*f
= XFRAME (w
->frame
);
6324 struct glyph
*cursor_glyph
;
6326 /* If cursor is out of bounds, don't draw garbage. This can happen
6327 in mini-buffer windows when switching between echo area glyphs
6329 cursor_glyph
= get_phys_cursor_glyph (w
);
6330 if (cursor_glyph
== NULL
)
6333 /* If on an image, draw like a normal cursor. That's usually better
6334 visible than drawing a bar, esp. if the image is large so that
6335 the bar might not be in the window. */
6336 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6338 struct glyph_row
*row
;
6339 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6340 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6344 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6345 Window window
= FRAME_MAC_WINDOW (f
);
6346 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6347 unsigned long mask
= GCForeground
| GCBackground
;
6348 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6351 /* If the glyph's background equals the color we normally draw
6352 the bar cursor in, the bar cursor in its normal color is
6353 invisible. Use the glyph's foreground color instead in this
6354 case, on the assumption that the glyph's colors are chosen so
6355 that the glyph is legible. */
6356 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6357 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6359 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6362 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6365 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6366 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6370 width
= FRAME_CURSOR_WIDTH (f
);
6371 width
= min (cursor_glyph
->pixel_width
, width
);
6373 w
->phys_cursor_width
= width
;
6374 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6376 if (kind
== BAR_CURSOR
)
6377 mac_fill_rectangle (f
, gc
,
6378 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6379 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6380 width
, row
->height
);
6382 mac_fill_rectangle (f
, gc
,
6383 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6384 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6385 row
->height
- width
),
6386 cursor_glyph
->pixel_width
,
6389 mac_reset_clip_rectangles (dpy
, gc
);
6394 /* RIF: Define cursor CURSOR on frame F. */
6397 mac_define_frame_cursor (f
, cursor
)
6401 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6403 if (dpyinfo
->x_focus_frame
== f
)
6404 SetThemeCursor (cursor
);
6408 /* RIF: Clear area on frame F. */
6411 mac_clear_frame_area (f
, x
, y
, width
, height
)
6413 int x
, y
, width
, height
;
6415 mac_clear_area (f
, x
, y
, width
, height
);
6419 /* RIF: Draw cursor on window W. */
6422 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6424 struct glyph_row
*glyph_row
;
6426 int cursor_type
, cursor_width
;
6431 w
->phys_cursor_type
= cursor_type
;
6432 w
->phys_cursor_on_p
= 1;
6434 if (glyph_row
->exact_window_width_line_p
6435 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6437 glyph_row
->cursor_in_fringe_p
= 1;
6438 draw_fringe_bitmap (w
, glyph_row
, 0);
6441 switch (cursor_type
)
6443 case HOLLOW_BOX_CURSOR
:
6444 x_draw_hollow_cursor (w
, glyph_row
);
6447 case FILLED_BOX_CURSOR
:
6448 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6452 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6456 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6460 w
->phys_cursor_width
= 0;
6472 #if 0 /* MAC_TODO: no icon support yet. */
6474 x_bitmap_icon (f
, icon
)
6480 if (FRAME_W32_WINDOW (f
) == 0)
6484 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6485 else if (STRINGP (icon
))
6486 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6487 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6488 else if (SYMBOLP (icon
))
6492 if (EQ (icon
, intern ("application")))
6493 name
= (LPCTSTR
) IDI_APPLICATION
;
6494 else if (EQ (icon
, intern ("hand")))
6495 name
= (LPCTSTR
) IDI_HAND
;
6496 else if (EQ (icon
, intern ("question")))
6497 name
= (LPCTSTR
) IDI_QUESTION
;
6498 else if (EQ (icon
, intern ("exclamation")))
6499 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6500 else if (EQ (icon
, intern ("asterisk")))
6501 name
= (LPCTSTR
) IDI_ASTERISK
;
6502 else if (EQ (icon
, intern ("winlogo")))
6503 name
= (LPCTSTR
) IDI_WINLOGO
;
6507 hicon
= LoadIcon (NULL
, name
);
6515 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6520 #endif /* MAC_TODO */
6522 /************************************************************************
6524 ************************************************************************/
6526 /* Display Error Handling functions not used on W32. Listing them here
6527 helps diff stay in step when comparing w32term.c with xterm.c.
6529 x_error_catcher (display, error)
6530 x_catch_errors (dpy)
6531 x_catch_errors_unwind (old_val)
6532 x_check_errors (dpy, format)
6533 x_had_errors_p (dpy)
6534 x_clear_errors (dpy)
6535 x_uncatch_errors (dpy, count)
6537 x_connection_signal (signalnum)
6538 x_connection_closed (dpy, error_message)
6539 x_error_quitter (display, error)
6540 x_error_handler (display, error)
6541 x_io_error_quitter (display)
6546 /* Changing the font of the frame. */
6548 /* Give frame F the font named FONTNAME as its default font, and
6549 return the full name of that font. FONTNAME may be a wildcard
6550 pattern; in that case, we choose some font that fits the pattern.
6551 The return value shows which font we chose. */
6554 x_new_font (f
, fontname
)
6556 register char *fontname
;
6558 struct font_info
*fontp
6559 = FS_LOAD_FONT (f
, 0, fontname
, -1);
6564 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6565 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6566 FRAME_FONTSET (f
) = -1;
6568 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6569 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6570 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6572 compute_fringe_widths (f
, 1);
6574 /* Compute the scroll bar width in character columns. */
6575 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6577 int wid
= FRAME_COLUMN_WIDTH (f
);
6578 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6579 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6583 int wid
= FRAME_COLUMN_WIDTH (f
);
6584 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6587 /* Now make the frame display the given font. */
6588 if (FRAME_MAC_WINDOW (f
) != 0)
6590 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6592 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6594 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6597 /* Don't change the size of a tip frame; there's no point in
6598 doing it because it's done in Fx_show_tip, and it leads to
6599 problems because the tip frame has no widget. */
6600 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6601 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6604 return build_string (fontp
->full_name
);
6607 /* Give frame F the fontset named FONTSETNAME as its default font, and
6608 return the full name of that fontset. FONTSETNAME may be a wildcard
6609 pattern; in that case, we choose some fontset that fits the pattern.
6610 The return value shows which fontset we chose. */
6613 x_new_fontset (f
, fontsetname
)
6617 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
6623 if (FRAME_FONTSET (f
) == fontset
)
6624 /* This fontset is already set in frame F. There's nothing more
6626 return fontset_name (fontset
);
6628 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6630 if (!STRINGP (result
))
6631 /* Can't load ASCII font. */
6634 /* Since x_new_font doesn't update any fontset information, do it now. */
6635 FRAME_FONTSET (f
) = fontset
;
6637 return build_string (fontsetname
);
6641 /***********************************************************************
6642 TODO: W32 Input Methods
6643 ***********************************************************************/
6644 /* Listing missing functions from xterm.c helps diff stay in step.
6646 xim_destroy_callback (xim, client_data, call_data)
6647 xim_open_dpy (dpyinfo, resource_name)
6649 xim_instantiate_callback (display, client_data, call_data)
6650 xim_initialize (dpyinfo, resource_name)
6651 xim_close_dpy (dpyinfo)
6657 mac_get_window_bounds (f
, inner
, outer
)
6659 Rect
*inner
, *outer
;
6661 #if TARGET_API_MAC_CARBON
6662 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6663 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6664 #else /* not TARGET_API_MAC_CARBON */
6665 RgnHandle region
= NewRgn ();
6667 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6668 *inner
= (*region
)->rgnBBox
;
6669 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6670 *outer
= (*region
)->rgnBBox
;
6671 DisposeRgn (region
);
6672 #endif /* not TARGET_API_MAC_CARBON */
6676 mac_handle_origin_change (f
)
6679 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6683 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6685 int pixelwidth
, pixelheight
;
6689 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6690 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6692 if (cols
!= FRAME_COLS (f
)
6693 || rows
!= FRAME_LINES (f
)
6694 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6695 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6697 /* We pass 1 for DELAY since we can't run Lisp code inside of
6699 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6700 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6701 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6702 SET_FRAME_GARBAGED (f
);
6704 /* If cursor was outside the new size, mark it as off. */
6705 mark_window_cursors_off (XWINDOW (f
->root_window
));
6707 /* Clear out any recollection of where the mouse highlighting
6708 was, since it might be in a place that's outside the new
6709 frame size. Actually checking whether it is outside is a
6710 pain in the neck, so don't try--just let the highlighting be
6711 done afresh with new size. */
6712 cancel_mouse_face (f
);
6714 #if TARGET_API_MAC_CARBON
6715 if (f
->output_data
.mac
->hourglass_control
)
6718 mac_prepare_for_quickdraw (f
);
6720 MoveControl (f
->output_data
.mac
->hourglass_control
,
6721 pixelwidth
- HOURGLASS_WIDTH
, 0);
6728 /* Calculate the absolute position in frame F
6729 from its current recorded position values and gravity. */
6732 x_calc_absolute_position (f
)
6735 int width_diff
= 0, height_diff
= 0;
6736 int flags
= f
->size_hint_flags
;
6739 /* We have nothing to do if the current position
6740 is already for the top-left corner. */
6741 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6744 /* Find the offsets of the outside upper-left corner of
6745 the inner window, with respect to the outer window. */
6747 mac_get_window_bounds (f
, &inner
, &outer
);
6750 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6751 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6753 /* Treat negative positions as relative to the leftmost bottommost
6754 position that fits on the screen. */
6755 if (flags
& XNegative
)
6756 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6758 - FRAME_PIXEL_WIDTH (f
)
6761 if (flags
& YNegative
)
6762 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6764 - FRAME_PIXEL_HEIGHT (f
)
6767 /* The left_pos and top_pos
6768 are now relative to the top and left screen edges,
6769 so the flags should correspond. */
6770 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6773 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6774 to really change the position, and 0 when calling from
6775 x_make_frame_visible (in that case, XOFF and YOFF are the current
6776 position values). It is -1 when calling from x_set_frame_parameters,
6777 which means, do adjust for borders but don't change the gravity. */
6780 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6782 register int xoff
, yoff
;
6785 if (change_gravity
> 0)
6789 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6791 f
->size_hint_flags
|= XNegative
;
6793 f
->size_hint_flags
|= YNegative
;
6794 f
->win_gravity
= NorthWestGravity
;
6796 x_calc_absolute_position (f
);
6799 x_wm_set_size_hint (f
, (long) 0, 0);
6801 #if TARGET_API_MAC_CARBON
6802 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6803 /* If the title bar is completely outside the screen, adjust the
6805 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6806 kWindowConstrainMoveRegardlessOfFit
6807 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6808 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6809 mac_handle_origin_change (f
);
6812 Rect inner
, outer
, screen_rect
, dummy
;
6813 RgnHandle region
= NewRgn ();
6815 mac_get_window_bounds (f
, &inner
, &outer
);
6816 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6817 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6818 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6819 f
->top_pos
+ f
->y_pixels_diff
, false);
6821 /* If the title bar is completely outside the screen, adjust the
6822 position. The variable `outer' holds the title bar rectangle.
6823 The variable `inner' holds slightly smaller one than `outer',
6824 so that the calculation of overlapping may not become too
6826 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6827 outer
= (*region
)->rgnBBox
;
6828 DisposeRgn (region
);
6830 InsetRect (&inner
, 8, 8);
6831 screen_rect
= qd
.screenBits
.bounds
;
6832 screen_rect
.top
+= GetMBarHeight ();
6834 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6836 if (inner
.right
<= screen_rect
.left
)
6837 f
->left_pos
= screen_rect
.left
;
6838 else if (inner
.left
>= screen_rect
.right
)
6839 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6841 if (inner
.bottom
<= screen_rect
.top
)
6842 f
->top_pos
= screen_rect
.top
;
6843 else if (inner
.top
>= screen_rect
.bottom
)
6844 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6846 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6847 f
->top_pos
+ f
->y_pixels_diff
, false);
6855 /* Call this to change the size of frame F's x-window.
6856 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6857 for this size change and subsequent size changes.
6858 Otherwise we leave the window gravity unchanged. */
6861 x_set_window_size (f
, change_gravity
, cols
, rows
)
6866 int pixelwidth
, pixelheight
;
6870 check_frame_size (f
, &rows
, &cols
);
6871 f
->scroll_bar_actual_width
6872 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6874 compute_fringe_widths (f
, 0);
6876 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6877 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6879 f
->win_gravity
= NorthWestGravity
;
6880 x_wm_set_size_hint (f
, (long) 0, 0);
6882 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6884 #if TARGET_API_MAC_CARBON
6885 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6887 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6889 if (f
->output_data
.mac
->internal_border_width
6890 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6892 mac_clear_window (f
);
6893 f
->output_data
.mac
->internal_border_width
6894 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6897 SET_FRAME_GARBAGED (f
);
6902 /* Mouse warping. */
6904 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6907 x_set_mouse_position (f
, x
, y
)
6913 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6914 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6916 if (pix_x
< 0) pix_x
= 0;
6917 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6919 if (pix_y
< 0) pix_y
= 0;
6920 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6922 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6926 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6931 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
6932 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
6935 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
6938 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6941 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6942 0, 0, 0, 0, pix_x
, pix_y
);
6948 /* focus shifting, raising and lowering. */
6951 x_focus_on_frame (f
)
6954 #if 0 /* This proves to be unpleasant. */
6958 /* I don't think that the ICCCM allows programs to do things like this
6959 without the interaction of the window manager. Whatever you end up
6960 doing with this code, do it to x_unfocus_frame too. */
6961 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6962 RevertToPointerRoot
, CurrentTime
);
6972 /* Raise frame F. */
6978 if (f
->async_visible
)
6981 BringToFront (FRAME_MAC_WINDOW (f
));
6986 /* Lower frame F. */
6992 if (f
->async_visible
)
6995 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7001 XTframe_raise_lower (f
, raise_flag
)
7011 /* Change of visibility. */
7014 mac_handle_visibility_change (f
)
7017 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7018 int visible
= 0, iconified
= 0;
7019 struct input_event buf
;
7021 if (IsWindowVisible (wp
))
7023 if (IsWindowCollapsed (wp
))
7029 if (!f
->async_visible
&& visible
)
7033 /* wait_reading_process_output will notice this and update
7034 the frame's display structures. If we were made
7035 invisible, we should not set garbaged, because that stops
7036 redrawing on Update events. */
7037 SET_FRAME_GARBAGED (f
);
7040 buf
.kind
= DEICONIFY_EVENT
;
7041 XSETFRAME (buf
.frame_or_window
, f
);
7043 kbd_buffer_store_event (&buf
);
7045 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7046 /* Force a redisplay sooner or later to update the
7047 frame titles in case this is the second frame. */
7048 record_asynch_buffer_change ();
7050 else if (f
->async_visible
&& !visible
)
7054 buf
.kind
= ICONIFY_EVENT
;
7055 XSETFRAME (buf
.frame_or_window
, f
);
7057 kbd_buffer_store_event (&buf
);
7060 f
->async_visible
= visible
;
7061 f
->async_iconified
= iconified
;
7064 /* This tries to wait until the frame is really visible.
7065 However, if the window manager asks the user where to position
7066 the frame, this will return before the user finishes doing that.
7067 The frame will not actually be visible at that time,
7068 but it will become visible later when the window manager
7069 finishes with it. */
7072 x_make_frame_visible (f
)
7077 if (! FRAME_VISIBLE_P (f
))
7079 /* We test FRAME_GARBAGED_P here to make sure we don't
7080 call x_set_offset a second time
7081 if we get to x_make_frame_visible a second time
7082 before the window gets really visible. */
7083 if (! FRAME_ICONIFIED_P (f
)
7084 && ! f
->output_data
.mac
->asked_for_visible
)
7085 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7087 f
->output_data
.mac
->asked_for_visible
= 1;
7089 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7090 ShowWindow (FRAME_MAC_WINDOW (f
));
7093 XFlush (FRAME_MAC_DISPLAY (f
));
7095 /* Synchronize to ensure Emacs knows the frame is visible
7096 before we do anything else. We do this loop with input not blocked
7097 so that incoming events are handled. */
7102 /* This must come after we set COUNT. */
7105 XSETFRAME (frame
, f
);
7107 /* Wait until the frame is visible. Process X events until a
7108 MapNotify event has been seen, or until we think we won't get a
7109 MapNotify at all.. */
7110 for (count
= input_signal_count
+ 10;
7111 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7113 /* Force processing of queued events. */
7116 /* Machines that do polling rather than SIGIO have been
7117 observed to go into a busy-wait here. So we'll fake an
7118 alarm signal to let the handler know that there's something
7119 to be read. We used to raise a real alarm, but it seems
7120 that the handler isn't always enabled here. This is
7122 if (input_polling_used ())
7124 /* It could be confusing if a real alarm arrives while
7125 processing the fake one. Turn it off and let the
7126 handler reset it. */
7127 extern void poll_for_input_1
P_ ((void));
7128 int old_poll_suppress_count
= poll_suppress_count
;
7129 poll_suppress_count
= 1;
7130 poll_for_input_1 ();
7131 poll_suppress_count
= old_poll_suppress_count
;
7134 /* See if a MapNotify event has been processed. */
7135 FRAME_SAMPLE_VISIBILITY (f
);
7140 /* Change from mapped state to withdrawn state. */
7142 /* Make the frame visible (mapped and not iconified). */
7145 x_make_frame_invisible (f
)
7148 /* A deactivate event does not occur when the last visible frame is
7149 made invisible. So if we clear the highlight here, it will not
7150 be rehighlighted when it is made visible. */
7152 /* Don't keep the highlight on an invisible frame. */
7153 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7154 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7159 #if !TARGET_API_MAC_CARBON
7160 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7161 that the current position of the window is user-specified, rather than
7162 program-specified, so that when the window is mapped again, it will be
7163 placed at the same location, without forcing the user to position it
7164 by hand again (they have already done that once for this window.) */
7165 x_wm_set_size_hint (f
, (long) 0, 1);
7168 HideWindow (FRAME_MAC_WINDOW (f
));
7172 #if !TARGET_API_MAC_CARBON
7173 mac_handle_visibility_change (f
);
7177 /* Change window state from mapped to iconified. */
7185 /* A deactivate event does not occur when the last visible frame is
7186 iconified. So if we clear the highlight here, it will not be
7187 rehighlighted when it is deiconified. */
7189 /* Don't keep the highlight on an invisible frame. */
7190 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7191 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7194 if (f
->async_iconified
)
7199 FRAME_SAMPLE_VISIBILITY (f
);
7201 if (! FRAME_VISIBLE_P (f
))
7202 ShowWindow (FRAME_MAC_WINDOW (f
));
7204 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7209 error ("Can't notify window manager of iconification");
7211 #if !TARGET_API_MAC_CARBON
7212 mac_handle_visibility_change (f
);
7217 /* Free X resources of frame F. */
7220 x_free_frame_resources (f
)
7223 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7224 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7228 if (wp
!= tip_window
)
7229 remove_window_handler (wp
);
7232 mac_prepare_for_quickdraw (f
);
7235 if (wp
== tip_window
)
7236 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7237 closed' event. So we reset tip_window here. */
7240 free_frame_menubar (f
);
7242 if (FRAME_FACE_CACHE (f
))
7243 free_frame_faces (f
);
7247 if (FRAME_SIZE_HINTS (f
))
7248 xfree (FRAME_SIZE_HINTS (f
));
7250 xfree (f
->output_data
.mac
);
7251 f
->output_data
.mac
= NULL
;
7253 if (f
== dpyinfo
->x_focus_frame
)
7255 dpyinfo
->x_focus_frame
= 0;
7256 #if USE_MAC_FONT_PANEL
7257 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7260 if (f
== dpyinfo
->x_focus_event_frame
)
7261 dpyinfo
->x_focus_event_frame
= 0;
7262 if (f
== dpyinfo
->x_highlight_frame
)
7263 dpyinfo
->x_highlight_frame
= 0;
7265 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7267 dpyinfo
->mouse_face_beg_row
7268 = dpyinfo
->mouse_face_beg_col
= -1;
7269 dpyinfo
->mouse_face_end_row
7270 = dpyinfo
->mouse_face_end_col
= -1;
7271 dpyinfo
->mouse_face_window
= Qnil
;
7272 dpyinfo
->mouse_face_deferred_gc
= 0;
7273 dpyinfo
->mouse_face_mouse_frame
= 0;
7280 /* Destroy the X window of frame F. */
7283 x_destroy_window (f
)
7286 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7288 x_free_frame_resources (f
);
7290 dpyinfo
->reference_count
--;
7294 /* Setting window manager hints. */
7296 /* Set the normal size hints for the window manager, for frame F.
7297 FLAGS is the flags word to use--or 0 meaning preserve the flags
7298 that the window now has.
7299 If USER_POSITION is nonzero, we set the USPosition
7300 flag (this is useful when FLAGS is 0). */
7302 x_wm_set_size_hint (f
, flags
, user_position
)
7307 int base_width
, base_height
, width_inc
, height_inc
;
7308 int min_rows
= 0, min_cols
= 0;
7309 XSizeHints
*size_hints
;
7311 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7312 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7313 width_inc
= FRAME_COLUMN_WIDTH (f
);
7314 height_inc
= FRAME_LINE_HEIGHT (f
);
7316 check_frame_size (f
, &min_rows
, &min_cols
);
7318 size_hints
= FRAME_SIZE_HINTS (f
);
7319 if (size_hints
== NULL
)
7321 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7322 bzero (size_hints
, sizeof (XSizeHints
));
7325 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7326 size_hints
->width_inc
= width_inc
;
7327 size_hints
->height_inc
= height_inc
;
7328 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7329 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7330 size_hints
->base_width
= base_width
;
7331 size_hints
->base_height
= base_height
;
7334 size_hints
->flags
= flags
;
7335 else if (user_position
)
7337 size_hints
->flags
&= ~ PPosition
;
7338 size_hints
->flags
|= USPosition
;
7342 #if 0 /* MAC_TODO: hide application instead of iconify? */
7343 /* Used for IconicState or NormalState */
7346 x_wm_set_window_state (f
, state
)
7350 #ifdef USE_X_TOOLKIT
7353 XtSetArg (al
[0], XtNinitialState
, state
);
7354 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7355 #else /* not USE_X_TOOLKIT */
7356 Window window
= FRAME_X_WINDOW (f
);
7358 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7359 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7361 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7362 #endif /* not USE_X_TOOLKIT */
7366 x_wm_set_icon_pixmap (f
, pixmap_id
)
7372 #ifndef USE_X_TOOLKIT
7373 Window window
= FRAME_X_WINDOW (f
);
7378 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7379 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7383 /* It seems there is no way to turn off use of an icon pixmap.
7384 The following line does it, only if no icon has yet been created,
7385 for some window managers. But with mwm it crashes.
7386 Some people say it should clear the IconPixmapHint bit in this case,
7387 but that doesn't work, and the X consortium said it isn't the
7388 right thing at all. Since there is no way to win,
7389 best to explicitly give up. */
7391 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7397 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7401 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7402 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7405 #else /* not USE_X_TOOLKIT */
7407 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7408 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7410 #endif /* not USE_X_TOOLKIT */
7413 #endif /* MAC_TODO */
7416 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7420 #if 0 /* MAC_TODO: no icons on Mac */
7421 #ifdef USE_X_TOOLKIT
7422 Window window
= XtWindow (f
->output_data
.x
->widget
);
7424 Window window
= FRAME_X_WINDOW (f
);
7427 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7428 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7429 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7431 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7432 #endif /* MAC_TODO */
7436 /***********************************************************************
7438 ***********************************************************************/
7440 /* An XLFD pattern is divided into blocks delimited by '*'. This
7441 structure holds information for each block. */
7442 struct xlfdpat_block
7444 /* Length of the pattern string in this block. Non-zero except for
7445 the first and the last blocks. */
7448 /* Pattern string except the last character in this block. The last
7449 character is replaced with NUL in order to use it as a
7451 unsigned char *pattern
;
7453 /* Last character of the pattern string. Must not be '?'. */
7454 unsigned char last_char
;
7456 /* One of the tables for the Boyer-Moore string search. It
7457 specifies the number of positions to proceed for each character
7458 with which the match fails. */
7461 /* The skip value for the last character in the above `skip' is
7462 assigned to `infinity' in order to simplify a loop condition.
7463 The original value is saved here. */
7469 /* Normalized pattern string. "Normalized" means that capital
7470 letters are lowered, blocks are not empty except the first and
7471 the last ones, and trailing '?'s in a block that is not the last
7472 one are moved to the next one. The last character in each block
7473 is replaced with NUL. */
7476 /* Number of characters except '*'s and trailing '?'s in the
7477 normalized pattern string. */
7480 /* Number of trailing '?'s in the normalized pattern string. */
7481 int trailing_anychars
;
7483 /* Number of blocks and information for each block. The latter is
7484 NULL if the pattern is exact (no '*' or '?' in it). */
7486 struct xlfdpat_block
*blocks
;
7490 xlfdpat_destroy (pat
)
7491 struct xlfdpat
*pat
;
7498 xfree (pat
->blocks
);
7505 static struct xlfdpat
*
7506 xlfdpat_create (pattern
)
7507 const char *pattern
;
7509 struct xlfdpat
*pat
;
7510 int nblocks
, i
, skip
;
7511 unsigned char last_char
, *p
, *q
, *anychar_head
;
7512 const unsigned char *ptr
;
7513 struct xlfdpat_block
*blk
;
7515 pat
= xmalloc (sizeof (struct xlfdpat
));
7516 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7518 /* Normalize the pattern string and store it to `pat->buf'. */
7520 anychar_head
= NULL
;
7523 for (ptr
= pattern
; *ptr
; ptr
++)
7525 unsigned char c
= *ptr
;
7528 if (last_char
== '*')
7529 /* ...a** -> ...a* */
7533 if (last_char
== '?')
7535 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7536 /* ...*??* -> ...*?? */
7539 /* ...a??* -> ...a*?? */
7541 *anychar_head
++ = '*';
7549 if (last_char
!= '?')
7553 /* On Mac OS X 10.3, tolower also converts non-ASCII
7554 characters for some locales. */
7558 *q
++ = last_char
= c
;
7562 pat
->nblocks
= nblocks
;
7563 if (last_char
!= '?')
7564 pat
->trailing_anychars
= 0;
7567 pat
->trailing_anychars
= q
- anychar_head
;
7570 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7572 if (anychar_head
== NULL
&& nblocks
== 1)
7574 /* The pattern is exact. */
7579 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7581 /* Divide the normalized pattern into blocks. */
7583 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7588 blk
->len
= p
- blk
->pattern
;
7592 blk
->len
= q
- blk
->pattern
;
7594 /* Setup a table for the Boyer-Moore string search. */
7595 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7598 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7599 blk
->pattern
[blk
->len
- 1] = '\0';
7601 for (skip
= 1; skip
< blk
->len
; skip
++)
7602 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7605 for (i
= 0; i
< 256; i
++)
7606 blk
->skip
[i
] = skip
;
7608 p
= blk
->pattern
+ (blk
->len
- skip
);
7610 blk
->skip
[*p
++] = skip
;
7612 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7619 xlfdpat_exact_p (pat
)
7620 struct xlfdpat
*pat
;
7622 return pat
->blocks
== NULL
;
7625 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7626 that the pattern in *BLK matches with its prefix. Return NULL
7627 there is no such strings. STRING must be lowered in advance. */
7630 xlfdpat_block_match_1 (blk
, string
, start_max
)
7631 struct xlfdpat_block
*blk
;
7632 const unsigned char *string
;
7635 int start
, infinity
;
7637 const unsigned char *s
;
7639 xassert (blk
->len
> 0);
7640 xassert (start_max
+ blk
->len
<= strlen (string
));
7641 xassert (blk
->last_char
!= '?');
7643 /* See the comments in the function `boyer_moore' (search.c) for the
7644 use of `infinity'. */
7645 infinity
= start_max
+ blk
->len
+ 1;
7646 blk
->skip
[blk
->last_char
] = infinity
;
7651 /* Check the last character of the pattern. */
7652 s
= string
+ blk
->len
- 1;
7655 start
+= blk
->skip
[*(s
+ start
)];
7657 while (start
<= start_max
);
7659 if (start
< infinity
)
7660 /* Couldn't find the last character. */
7663 /* No less than `infinity' means we could find the last
7664 character at `s[start - infinity]'. */
7667 /* Check the remaining characters. We prefer making no-'?'
7668 cases faster because the use of '?' is really rare. */
7673 while (*p
++ == *s
++)
7676 while (*(p
- 1) == '?');
7678 if (*(p
- 1) == '\0')
7680 return string
+ start
;
7683 start
+= blk
->last_char_skip
;
7685 while (start
<= start_max
);
7690 #define xlfdpat_block_match(b, s, m) \
7691 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7692 : xlfdpat_block_match_1 (b, s, m))
7694 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7695 matches with STRING. STRING must be lowered in advance. */
7698 xlfdpat_match (pat
, string
)
7699 struct xlfdpat
*pat
;
7700 const unsigned char *string
;
7702 int str_len
, nblocks
, i
, start_max
;
7703 struct xlfdpat_block
*blk
;
7704 const unsigned char *s
;
7706 xassert (pat
->nblocks
> 0);
7708 if (xlfdpat_exact_p (pat
))
7709 return strcmp (pat
->buf
, string
) == 0;
7711 /* The number of the characters in the string must not be smaller
7712 than that in the pattern. */
7713 str_len
= strlen (string
);
7714 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7717 /* Chop off the trailing '?'s. */
7718 str_len
-= pat
->trailing_anychars
;
7720 /* The last block. When it is non-empty, it must match at the end
7722 nblocks
= pat
->nblocks
;
7723 blk
= pat
->blocks
+ (nblocks
- 1);
7725 /* The last block is also the first one. */
7726 return (str_len
== blk
->len
7727 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7728 else if (blk
->len
!= 0)
7729 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7732 /* The first block. When it is non-empty, it must match at the
7733 beginning of the string. */
7737 s
= xlfdpat_block_match (blk
, string
, 0);
7740 string
= s
+ blk
->len
;
7743 /* The rest of the blocks. */
7744 start_max
= str_len
- pat
->nchars
;
7745 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7747 s
= xlfdpat_block_match (blk
, string
, start_max
);
7750 start_max
-= s
- string
;
7751 string
= s
+ blk
->len
;
7758 /***********************************************************************
7760 ***********************************************************************/
7762 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7765 x_get_font_info (f
, font_idx
)
7769 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7772 /* the global font name table */
7773 static char **font_name_table
= NULL
;
7774 static int font_name_table_size
= 0;
7775 static int font_name_count
= 0;
7777 /* Alist linking font family names to Font Manager font family
7778 references (which can also be used as QuickDraw font IDs). We use
7779 an alist because hash tables are not ready when the terminal frame
7780 for Mac OS Classic is created. */
7781 static Lisp_Object fm_font_family_alist
;
7783 /* Hash table linking font family names to ATSU font IDs. */
7784 static Lisp_Object atsu_font_id_hash
;
7785 /* Alist linking Font Manager style to face attributes. */
7786 static Lisp_Object fm_style_face_attributes_alist
;
7787 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7790 /* Alist linking character set strings to Mac text encoding and Emacs
7792 static Lisp_Object Vmac_charset_info_alist
;
7795 create_text_encoding_info_alist ()
7797 Lisp_Object result
= Qnil
, rest
;
7799 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7801 Lisp_Object charset_info
= XCAR (rest
);
7802 Lisp_Object charset
, coding_system
, text_encoding
;
7803 Lisp_Object existing_info
;
7805 if (!(CONSP (charset_info
)
7806 && (charset
= XCAR (charset_info
),
7808 && CONSP (XCDR (charset_info
))
7809 && (text_encoding
= XCAR (XCDR (charset_info
)),
7810 INTEGERP (text_encoding
))
7811 && CONSP (XCDR (XCDR (charset_info
)))
7812 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7813 SYMBOLP (coding_system
))))
7816 existing_info
= assq_no_quit (text_encoding
, result
);
7817 if (NILP (existing_info
))
7818 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7821 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7822 XSETCDR (XCDR (existing_info
),
7823 Fcons (charset
, XCDR (XCDR (existing_info
))));
7831 decode_mac_font_name (name
, size
, coding_system
)
7834 Lisp_Object coding_system
;
7836 struct coding_system coding
;
7839 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7841 for (p
= name
; *p
; p
++)
7842 if (!isascii (*p
) || iscntrl (*p
))
7847 setup_coding_system (coding_system
, &coding
);
7848 coding
.src_multibyte
= 0;
7849 coding
.dst_multibyte
= 1;
7850 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7851 coding
.composing
= COMPOSITION_DISABLED
;
7852 buf
= (char *) alloca (size
);
7854 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7855 bcopy (buf
, name
, coding
.produced
);
7856 name
[coding
.produced
] = '\0';
7860 /* If there's just one occurrence of '-' in the family name, it is
7861 replaced with '_'. (More than one occurrence of '-' means a
7862 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7863 p
= strchr (name
, '-');
7864 if (p
&& strchr (p
+ 1, '-') == NULL
)
7867 for (p
= name
; *p
; p
++)
7868 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7869 for some locales. */
7876 mac_to_x_fontname (name
, size
, style
, charset
)
7884 char xf
[256], *result
;
7887 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7891 strcpy(foundry
, "Apple");
7892 strcpy(family
, name
);
7895 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7896 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7897 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7899 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7900 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7901 for (p
= result
; *p
; p
++)
7902 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7903 for some locales. */
7910 /* Parse fully-specified and instantiated X11 font spec XF, and store
7911 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7912 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7913 caller must allocate at least 256 and 32 bytes respectively. For
7914 ordinary Mac fonts, the value stored to FAMILY should just be their
7915 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7916 intlfonts collection contain their charset designation in their
7917 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7918 types of font names are handled accordingly. */
7920 const int kDefaultFontSize
= 12;
7923 parse_x_font_name (xf
, family
, size
, style
, charset
)
7930 Str31 foundry
, weight
;
7931 int point_size
, avgwidth
;
7934 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7935 foundry
, family
, weight
, slant
, size
,
7936 &point_size
, &avgwidth
, charset
) != 8
7937 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7938 foundry
, family
, weight
, slant
, size
,
7939 &point_size
, &avgwidth
, charset
) != 8)
7945 *size
= point_size
/ 10;
7946 else if (avgwidth
> 0)
7947 *size
= avgwidth
/ 10;
7950 *size
= kDefaultFontSize
;
7953 if (strcmp (weight
, "bold") == 0)
7958 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7960 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7962 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7964 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7965 but take overlap into account. */
7966 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7967 memcpy (family
, foundry
, foundry_len
);
7968 family
[foundry_len
] = '-';
7969 family
[foundry_len
+ 1 + family_len
] = '-';
7970 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7976 for (p
= family
; *p
; p
++)
7977 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7978 for some locales. */
7987 add_font_name_table_entry (char *font_name
)
7989 if (font_name_table_size
== 0)
7991 font_name_table_size
= 256;
7992 font_name_table
= (char **)
7993 xmalloc (font_name_table_size
* sizeof (char *));
7995 else if (font_name_count
+ 1 >= font_name_table_size
)
7997 font_name_table_size
*= 2;
7998 font_name_table
= (char **)
7999 xrealloc (font_name_table
,
8000 font_name_table_size
* sizeof (char *));
8003 font_name_table
[font_name_count
++] = font_name
;
8007 add_mac_font_name (name
, size
, style
, charset
)
8011 const char *charset
;
8014 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8017 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8018 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8019 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8020 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8027 fm_get_style_from_font (font
)
8031 FMFontStyle style
= normal
;
8034 FMFontFamily font_family
;
8035 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8037 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8038 some font (e.g., Optima) even if it is `bold'. */
8039 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8040 sizeof (mac_style
), &mac_style
, &len
);
8042 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8043 style
= EndianU16_BtoN (mac_style
);
8045 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8051 atsu_find_font_from_family_name (family
)
8054 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8057 Lisp_Object rest
, best
;
8058 FMFontStyle min_style
, style
;
8060 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8063 return kATSUInvalidFontID
;
8065 rest
= HASH_VALUE (h
, i
);
8066 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8067 return cons_to_long (rest
);
8069 rest
= Fnreverse (rest
);
8073 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8076 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8077 if (style
< min_style
)
8080 if (style
== normal
)
8087 while (!NILP (rest
));
8089 HASH_VALUE (h
, i
) = best
;
8090 return cons_to_long (best
);
8094 fm_style_to_face_attributes (fm_style
)
8095 FMFontStyle fm_style
;
8099 fm_style
&= (bold
| italic
);
8100 tem
= assq_no_quit (make_number (fm_style
),
8101 fm_style_face_attributes_alist
);
8105 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8106 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8107 fm_style_face_attributes_alist
=
8108 Fcons (Fcons (make_number (fm_style
), tem
),
8109 fm_style_face_attributes_alist
);
8115 atsu_find_font_family_name (font_id
)
8120 Lisp_Object family
= Qnil
;
8122 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8123 kFontMacintoshPlatform
, kFontNoScript
,
8124 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8127 family
= make_uninit_string (len
);
8128 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8129 kFontMacintoshPlatform
, kFontNoScript
,
8130 kFontNoLanguage
, len
, SDATA (family
),
8134 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8140 mac_atsu_font_face_attributes (font_id
)
8143 Lisp_Object family
, style_attrs
;
8145 family
= atsu_find_font_family_name (font_id
);
8148 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8149 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8153 /* Sets up the table font_name_table to contain the list of all fonts
8154 in the system the first time the table is used so that the Resource
8155 Manager need not be accessed every time this information is
8159 init_font_name_table ()
8161 #if TARGET_API_MAC_CARBON
8162 FMFontFamilyIterator ffi
;
8163 FMFontFamilyInstanceIterator ffii
;
8165 Lisp_Object text_encoding_info_alist
;
8166 struct gcpro gcpro1
;
8168 text_encoding_info_alist
= create_text_encoding_info_alist ();
8171 #if USE_CG_TEXT_DRAWING
8172 init_cg_text_anti_aliasing_threshold ();
8174 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8175 text_encoding_info_alist
)))
8178 struct Lisp_Hash_Table
*h
;
8180 ItemCount nfonts
, i
;
8181 ATSUFontID
*font_ids
= NULL
;
8182 Lisp_Object prev_family
= Qnil
;
8186 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8187 make_float (DEFAULT_REHASH_SIZE
),
8188 make_float (DEFAULT_REHASH_THRESHOLD
),
8190 h
= XHASH_TABLE (atsu_font_id_hash
);
8192 err
= ATSUFontCount (&nfonts
);
8195 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8196 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8199 for (i
= 0; i
< nfonts
; i
++)
8203 family
= atsu_find_font_family_name (font_ids
[i
]);
8204 if (NILP (family
) || SREF (family
, 0) == '.')
8206 if (!NILP (Fequal (prev_family
, family
)))
8207 family
= prev_family
;
8209 j
= hash_lookup (h
, family
, &hash_code
);
8212 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8213 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8216 else if (EQ (prev_family
, family
))
8217 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8219 prev_family
= family
;
8226 /* Create a dummy instance iterator here to avoid creating and
8227 destroying it in the loop. */
8228 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8230 /* Create an iterator to enumerate the font families. */
8231 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8234 FMDisposeFontFamilyInstanceIterator (&ffii
);
8238 GCPRO1 (text_encoding_info_alist
);
8240 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8246 TextEncoding encoding
;
8247 TextEncodingBase sc
;
8248 Lisp_Object text_encoding_info
, family
;
8250 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8256 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8258 sc
= GetTextEncodingBase (encoding
);
8259 text_encoding_info
= assq_no_quit (make_number (sc
),
8260 text_encoding_info_alist
);
8261 if (NILP (text_encoding_info
))
8262 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8263 text_encoding_info_alist
);
8264 decode_mac_font_name (name
, sizeof (name
),
8265 XCAR (XCDR (text_encoding_info
)));
8266 family
= build_string (name
);
8267 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8269 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8270 fm_font_family_alist
);
8272 /* Point the instance iterator at the current font family. */
8273 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8276 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8279 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8281 if (size
> 0 || style
== normal
)
8282 for (; !NILP (rest
); rest
= XCDR (rest
))
8283 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8289 /* Dispose of the iterators. */
8290 FMDisposeFontFamilyIterator (&ffi
);
8291 FMDisposeFontFamilyInstanceIterator (&ffii
);
8292 #else /* !TARGET_API_MAC_CARBON */
8294 SInt16 fontnum
, old_fontnum
;
8295 int num_mac_fonts
= CountResources('FOND');
8297 Handle font_handle
, font_handle_2
;
8298 short id
, scriptcode
;
8301 struct FontAssoc
*fat
;
8302 struct AsscEntry
*assc_entry
;
8303 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8304 struct gcpro gcpro1
;
8306 GetPort (&port
); /* save the current font number used */
8307 old_fontnum
= port
->txFont
;
8309 text_encoding_info_alist
= create_text_encoding_info_alist ();
8311 GCPRO1 (text_encoding_info_alist
);
8313 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8315 font_handle
= GetIndResource ('FOND', i
);
8319 GetResInfo (font_handle
, &id
, &type
, name
);
8320 GetFNum (name
, &fontnum
);
8322 if (fontnum
== 0 || *name
== '.')
8326 scriptcode
= FontToScript (fontnum
);
8327 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8328 text_encoding_info_alist
);
8329 if (NILP (text_encoding_info
))
8330 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8331 text_encoding_info_alist
);
8332 decode_mac_font_name (name
, sizeof (name
),
8333 XCAR (XCDR (text_encoding_info
)));
8334 family
= build_string (name
);
8335 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8337 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8338 fm_font_family_alist
);
8341 HLock (font_handle
);
8343 if (GetResourceSizeOnDisk (font_handle
)
8344 >= sizeof (struct FamRec
))
8346 fat
= (struct FontAssoc
*) (*font_handle
8347 + sizeof (struct FamRec
));
8349 = (struct AsscEntry
*) (*font_handle
8350 + sizeof (struct FamRec
)
8351 + sizeof (struct FontAssoc
));
8353 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8355 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8357 for (; !NILP (rest
); rest
= XCDR (rest
))
8358 add_mac_font_name (name
, assc_entry
->fontSize
,
8359 assc_entry
->fontStyle
,
8360 SDATA (XCAR (rest
)));
8364 HUnlock (font_handle
);
8365 font_handle_2
= GetNextFOND (font_handle
);
8366 ReleaseResource (font_handle
);
8367 font_handle
= font_handle_2
;
8369 while (ResError () == noErr
&& font_handle
);
8374 TextFont (old_fontnum
);
8375 #endif /* !TARGET_API_MAC_CARBON */
8380 mac_clear_font_name_table ()
8384 for (i
= 0; i
< font_name_count
; i
++)
8385 xfree (font_name_table
[i
]);
8386 xfree (font_name_table
);
8387 font_name_table
= NULL
;
8388 font_name_table_size
= font_name_count
= 0;
8389 fm_font_family_alist
= Qnil
;
8393 enum xlfd_scalable_field_index
8395 XLFD_SCL_PIXEL_SIZE
,
8396 XLFD_SCL_POINT_SIZE
,
8401 static const int xlfd_scalable_fields
[] =
8410 mac_do_list_fonts (pattern
, maxnames
)
8411 const char *pattern
;
8415 Lisp_Object font_list
= Qnil
;
8416 struct xlfdpat
*pat
;
8419 int scl_val
[XLFD_SCL_LAST
], *val
;
8423 if (font_name_table
== NULL
) /* Initialize when first used. */
8424 init_font_name_table ();
8426 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8429 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8430 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8431 fonts are scaled according to the specified size. */
8434 field
= xlfd_scalable_fields
;
8442 if ('0' <= *ptr
&& *ptr
<= '9')
8444 *val
= *ptr
++ - '0';
8445 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8446 *val
= *val
* 10 + *ptr
++ - '0';
8453 ptr
= strchr (ptr
, '-');
8456 while (ptr
&& i
< 14);
8458 if (i
== 14 && ptr
== NULL
)
8460 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8461 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8462 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8463 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8465 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8466 scl_val
[XLFD_SCL_POINT_SIZE
] =
8467 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8468 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8470 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8471 scl_val
[XLFD_SCL_AVGWIDTH
] =
8472 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8473 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8477 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8479 pat
= xlfdpat_create (pattern
);
8483 exact
= xlfdpat_exact_p (pat
);
8485 for (i
= 0; i
< font_name_count
; i
++)
8487 if (xlfdpat_match (pat
, font_name_table
[i
]))
8489 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8490 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8493 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8494 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8496 int former_len
= ptr
- font_name_table
[i
];
8498 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8499 memcpy (scaled
, font_name_table
[i
], former_len
);
8500 sprintf (scaled
+ former_len
,
8501 "-%d-%d-72-72-m-%d-%s",
8502 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8503 scl_val
[XLFD_SCL_POINT_SIZE
],
8504 scl_val
[XLFD_SCL_AVGWIDTH
],
8505 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8507 if (xlfdpat_match (pat
, scaled
))
8509 font_list
= Fcons (build_string (scaled
), font_list
);
8511 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8519 xlfdpat_destroy (pat
);
8524 /* Return a list of names of available fonts matching PATTERN on frame F.
8526 Frame F null means we have not yet created any frame on Mac, and
8527 consult the first display in x_display_list. MAXNAMES sets a limit
8528 on how many fonts to match. */
8531 x_list_fonts (f
, pattern
, size
, maxnames
)
8533 Lisp_Object pattern
;
8536 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8537 struct mac_display_info
*dpyinfo
8538 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8540 xassert (size
<= 0);
8542 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8543 if (NILP (patterns
))
8544 patterns
= Fcons (pattern
, Qnil
);
8546 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8548 pattern
= XCAR (patterns
);
8550 if (!STRINGP (pattern
))
8553 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8554 key
= Fcons (pattern
, make_number (maxnames
));
8556 list
= Fassoc (key
, tem
);
8559 list
= Fcdr_safe (list
);
8560 /* We have a cashed list. Don't have to get the list again. */
8565 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8568 /* MAC_TODO: add code for matching outline fonts here */
8570 /* Now store the result in the cache. */
8571 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8572 Fcons (Fcons (key
, list
),
8573 XCAR (XCDR (dpyinfo
->name_list_element
))));
8576 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8585 /* Check that FONT is valid on frame F. It is if it can be found in F's
8589 x_check_font (f
, font
)
8594 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8596 xassert (font
!= NULL
);
8598 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8599 if (dpyinfo
->font_table
[i
].name
8600 && font
== dpyinfo
->font_table
[i
].font
)
8603 xassert (i
< dpyinfo
->n_fonts
);
8606 #endif /* GLYPH_DEBUG != 0 */
8608 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8609 Note: There are (broken) X fonts out there with invalid XFontStruct
8610 min_bounds contents. For example, handa@etl.go.jp reports that
8611 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8612 have font->min_bounds.width == 0. */
8615 x_font_min_bounds (font
, w
, h
)
8616 MacFontStruct
*font
;
8619 *h
= FONT_HEIGHT (font
);
8620 *w
= font
->min_bounds
.width
;
8624 /* Compute the smallest character width and smallest font height over
8625 all fonts available on frame F. Set the members smallest_char_width
8626 and smallest_font_height in F's x_display_info structure to
8627 the values computed. Value is non-zero if smallest_font_height or
8628 smallest_char_width become smaller than they were before. */
8631 x_compute_min_glyph_bounds (f
)
8635 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8636 MacFontStruct
*font
;
8637 int old_width
= dpyinfo
->smallest_char_width
;
8638 int old_height
= dpyinfo
->smallest_font_height
;
8640 dpyinfo
->smallest_font_height
= 100000;
8641 dpyinfo
->smallest_char_width
= 100000;
8643 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8644 if (dpyinfo
->font_table
[i
].name
)
8646 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8649 font
= (MacFontStruct
*) fontp
->font
;
8650 xassert (font
!= (MacFontStruct
*) ~0);
8651 x_font_min_bounds (font
, &w
, &h
);
8653 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8654 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8657 xassert (dpyinfo
->smallest_char_width
> 0
8658 && dpyinfo
->smallest_font_height
> 0);
8660 return (dpyinfo
->n_fonts
== 1
8661 || dpyinfo
->smallest_char_width
< old_width
8662 || dpyinfo
->smallest_font_height
< old_height
);
8666 /* Determine whether given string is a fully-specified XLFD: all 14
8667 fields are present, none is '*'. */
8670 is_fully_specified_xlfd (p
)
8679 for (i
= 0; i
< 13; i
++)
8681 q
= strchr (p
+ 1, '-');
8684 if (q
- p
== 2 && *(p
+ 1) == '*')
8689 if (strchr (p
+ 1, '-') != NULL
)
8692 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8699 /* mac_load_query_font creates and returns an internal representation
8700 for a font in a MacFontStruct struct. There is really no concept
8701 corresponding to "loading" a font on the Mac. But we check its
8702 existence and find the font number and all other information for it
8703 and store them in the returned MacFontStruct. */
8705 static MacFontStruct
*
8706 mac_load_query_font (f
, fontname
)
8716 static ATSUFontID font_id
;
8717 ATSUStyle mac_style
= NULL
;
8720 #if TARGET_API_MAC_CARBON
8721 TextEncoding encoding
;
8726 MacFontStruct
*font
;
8727 XCharStruct
*space_bounds
= NULL
, *pcm
;
8729 if (is_fully_specified_xlfd (fontname
))
8733 Lisp_Object matched_fonts
;
8735 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8736 if (NILP (matched_fonts
))
8738 name
= SDATA (XCAR (matched_fonts
));
8741 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8745 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8748 static const ATSUAttributeTag tags
[] =
8749 {kATSUFontTag
, kATSUSizeTag
,
8750 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8751 static const ByteCount sizes
[] =
8752 {sizeof (ATSUFontID
), sizeof (Fixed
),
8753 sizeof (Boolean
), sizeof (Boolean
)};
8754 static Fixed size_fixed
;
8755 static Boolean bold_p
, italic_p
;
8756 static const ATSUAttributeValuePtr values
[] =
8757 {&font_id
, &size_fixed
,
8758 &bold_p
, &italic_p
};
8759 static const ATSUFontFeatureType types
[] =
8760 {kAllTypographicFeaturesType
, kDiacriticsType
};
8761 static const ATSUFontFeatureSelector selectors
[] =
8762 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8765 font_id
= atsu_find_font_from_family_name (family
);
8766 if (font_id
== kATSUInvalidFontID
)
8768 size_fixed
= Long2Fix (size
);
8769 bold_p
= (fontface
& bold
) != 0;
8770 italic_p
= (fontface
& italic
) != 0;
8771 err
= ATSUCreateStyle (&mac_style
);
8774 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8778 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8779 tags
, sizes
, values
);
8782 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8785 scriptcode
= kTextEncodingMacUnicode
;
8790 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8794 fontnum
= XINT (XCDR (tmp
));
8795 #if TARGET_API_MAC_CARBON
8796 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8798 scriptcode
= GetTextEncodingBase (encoding
);
8800 scriptcode
= FontToScript (fontnum
);
8804 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8806 font
->mac_fontnum
= fontnum
;
8807 font
->mac_fontsize
= size
;
8808 font
->mac_fontface
= fontface
;
8809 font
->mac_scriptcode
= scriptcode
;
8811 font
->mac_style
= mac_style
;
8812 #if USE_CG_TEXT_DRAWING
8813 font
->cg_font
= NULL
;
8814 font
->cg_glyphs
= NULL
;
8818 /* Apple Japanese (SJIS) font is listed as both
8819 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8820 (Roman script) in init_font_name_table (). The latter should be
8821 treated as a one-byte font. */
8822 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8823 font
->mac_scriptcode
= smRoman
;
8825 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8828 if (font
->mac_style
)
8833 font
->min_byte1
= 0;
8834 font
->max_byte1
= 0xff;
8835 font
->min_char_or_byte2
= 0;
8836 font
->max_char_or_byte2
= 0xff;
8838 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8839 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8840 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8841 pcm_init (font
->bounds
.rows
[0], 0x100);
8843 #if USE_CG_TEXT_DRAWING
8847 ATSFontRef ats_font
;
8849 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8851 /* Use CG text drawing if italic/bold is not synthesized. */
8852 if (err
== noErr
&& style
== fontface
)
8854 ats_font
= FMGetATSFontRefFromFont (font_id
);
8855 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8861 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8862 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8865 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8866 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8867 &font
->ascent
, &font
->descent
,
8869 #if USE_CG_TEXT_DRAWING
8870 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8877 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8879 mac_unload_font (&one_mac_display_info
, font
);
8883 pcm
= font
->bounds
.rows
[0];
8884 for (c
= 0x21; c
<= 0xff; c
++)
8887 /* Soft hyphen is not supported in ATSUI. */
8891 #if USE_CG_TEXT_DRAWING
8892 if (font
->cg_glyphs
)
8902 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8903 pcm
? pcm
+ c
: NULL
,
8904 #if USE_CG_TEXT_DRAWING
8905 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8912 #if USE_CG_TEXT_DRAWING
8913 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8915 /* Don't use CG text drawing if font substitution occurs in
8916 ASCII or Latin-1 characters. */
8917 CGFontRelease (font
->cg_font
);
8918 font
->cg_font
= NULL
;
8919 xfree (font
->cg_glyphs
);
8920 font
->cg_glyphs
= NULL
;
8931 FontInfo the_fontinfo
;
8932 int is_two_byte_font
;
8935 mac_prepare_for_quickdraw (f
);
8937 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8941 TextFace (fontface
);
8943 GetFontInfo (&the_fontinfo
);
8945 font
->ascent
= the_fontinfo
.ascent
;
8946 font
->descent
= the_fontinfo
.descent
;
8948 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8949 || font
->mac_scriptcode
== smTradChinese
8950 || font
->mac_scriptcode
== smSimpChinese
8951 || font
->mac_scriptcode
== smKorean
);
8953 if (is_two_byte_font
)
8957 font
->min_byte1
= 0xa1;
8958 font
->max_byte1
= 0xfe;
8959 font
->min_char_or_byte2
= 0xa1;
8960 font
->max_char_or_byte2
= 0xfe;
8962 /* Use the width of an "ideographic space" of that font
8963 because the_fontinfo.widMax returns the wrong width for
8965 switch (font
->mac_scriptcode
)
8968 font
->min_byte1
= 0x81;
8969 font
->max_byte1
= 0xfc;
8970 font
->min_char_or_byte2
= 0x40;
8971 font
->max_char_or_byte2
= 0xfc;
8972 char_width
= StringWidth("\p\x81\x40");
8975 font
->min_char_or_byte2
= 0x40;
8976 char_width
= StringWidth("\p\xa1\x40");
8979 char_width
= StringWidth("\p\xa1\xa1");
8982 char_width
= StringWidth("\p\xa1\xa1");
8986 font
->bounds
.per_char
= NULL
;
8988 if (fontface
& italic
)
8989 font
->max_bounds
.rbearing
= char_width
+ 1;
8991 font
->max_bounds
.rbearing
= char_width
;
8992 font
->max_bounds
.lbearing
= 0;
8993 font
->max_bounds
.width
= char_width
;
8994 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8995 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8997 font
->min_bounds
= font
->max_bounds
;
9003 font
->min_byte1
= font
->max_byte1
= 0;
9004 font
->min_char_or_byte2
= 0x20;
9005 font
->max_char_or_byte2
= 0xff;
9007 font
->bounds
.per_char
=
9008 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9009 bzero (font
->bounds
.per_char
,
9010 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9012 space_bounds
= font
->bounds
.per_char
;
9013 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9014 &font
->descent
, space_bounds
, NULL
);
9015 if (err
!= noErr
|| space_bounds
->width
<= 0)
9017 mac_unload_font (&one_mac_display_info
, font
);
9021 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9022 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9030 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9031 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9034 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9036 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9038 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9040 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9042 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9045 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9047 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9049 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9051 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9053 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9058 font
->mac_style
== NULL
&&
9060 font
->max_bounds
.width
== font
->min_bounds
.width
9061 && font
->min_bounds
.lbearing
>= 0
9062 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9064 /* Fixed width and no overhangs. */
9065 xfree (font
->bounds
.per_char
);
9066 font
->bounds
.per_char
= NULL
;
9070 #if !defined (MAC_OS8) || USE_ATSUI
9071 /* AppKit and WebKit do some adjustment to the heights of Courier,
9072 Helvetica, and Times. This only works on the environments where
9073 srcCopy text transfer mode is never used. */
9075 #ifdef MAC_OS8 /* implies USE_ATSUI */
9078 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9079 || strcmp (family
, "times") == 0))
9080 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9088 mac_unload_font (dpyinfo
, font
)
9089 struct mac_display_info
*dpyinfo
;
9092 xfree (font
->full_name
);
9094 if (font
->mac_style
)
9098 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9099 if (font
->bounds
.rows
[i
])
9100 xfree (font
->bounds
.rows
[i
]);
9101 xfree (font
->bounds
.rows
);
9102 ATSUDisposeStyle (font
->mac_style
);
9106 if (font
->bounds
.per_char
)
9107 xfree (font
->bounds
.per_char
);
9108 #if USE_CG_TEXT_DRAWING
9110 CGFontRelease (font
->cg_font
);
9111 if (font
->cg_glyphs
)
9112 xfree (font
->cg_glyphs
);
9118 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9119 pointer to the structure font_info while allocating it dynamically.
9120 If SIZE is 0, load any size of font.
9121 If loading is failed, return NULL. */
9124 x_load_font (f
, fontname
, size
)
9126 register char *fontname
;
9129 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9130 Lisp_Object font_names
;
9132 /* Get a list of all the fonts that match this name. Once we
9133 have a list of matching fonts, we compare them against the fonts
9134 we already have by comparing names. */
9135 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9137 if (!NILP (font_names
))
9142 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9143 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9144 if (dpyinfo
->font_table
[i
].name
9145 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9146 SDATA (XCAR (tail
)))
9147 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9148 SDATA (XCAR (tail
)))))
9149 return (dpyinfo
->font_table
+ i
);
9154 /* Load the font and add it to the table. */
9156 struct MacFontStruct
*font
;
9157 struct font_info
*fontp
;
9160 fontname
= (char *) SDATA (XCAR (font_names
));
9163 font
= mac_load_query_font (f
, fontname
);
9168 /* Find a free slot in the font table. */
9169 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9170 if (dpyinfo
->font_table
[i
].name
== NULL
)
9173 /* If no free slot found, maybe enlarge the font table. */
9174 if (i
== dpyinfo
->n_fonts
9175 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9178 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9179 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9181 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9184 fontp
= dpyinfo
->font_table
+ i
;
9185 if (i
== dpyinfo
->n_fonts
)
9188 /* Now fill in the slots of *FONTP. */
9190 bzero (fontp
, sizeof (*fontp
));
9192 fontp
->font_idx
= i
;
9193 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9194 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9196 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9198 /* Fixed width font. */
9199 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9206 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9207 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9209 fontp
->space_width
= pcm
->width
;
9211 fontp
->space_width
= FONT_WIDTH (font
);
9215 int width
= pcm
->width
;
9216 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9217 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9218 width
+= pcm
->width
;
9219 fontp
->average_width
= width
/ 95;
9222 fontp
->average_width
= FONT_WIDTH (font
);
9225 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9226 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9228 fontp
->size
= font
->max_bounds
.width
;
9229 fontp
->height
= FONT_HEIGHT (font
);
9231 /* For some font, ascent and descent in max_bounds field is
9232 larger than the above value. */
9233 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9234 if (max_height
> fontp
->height
)
9235 fontp
->height
= max_height
;
9238 /* The slot `encoding' specifies how to map a character
9239 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9240 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9241 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9242 2:0xA020..0xFF7F). For the moment, we don't know which charset
9243 uses this font. So, we set information in fontp->encoding[1]
9244 which is never used by any charset. If mapping can't be
9245 decided, set FONT_ENCODING_NOT_DECIDED. */
9246 if (font
->mac_scriptcode
== smJapanese
)
9247 fontp
->encoding
[1] = 4;
9251 = (font
->max_byte1
== 0
9253 ? (font
->min_char_or_byte2
< 0x80
9254 ? (font
->max_char_or_byte2
< 0x80
9255 ? 0 /* 0x20..0x7F */
9256 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9257 : 1) /* 0xA0..0xFF */
9259 : (font
->min_byte1
< 0x80
9260 ? (font
->max_byte1
< 0x80
9261 ? (font
->min_char_or_byte2
< 0x80
9262 ? (font
->max_char_or_byte2
< 0x80
9263 ? 0 /* 0x2020..0x7F7F */
9264 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9265 : 3) /* 0x20A0..0x7FFF */
9266 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9267 : (font
->min_char_or_byte2
< 0x80
9268 ? (font
->max_char_or_byte2
< 0x80
9269 ? 2 /* 0xA020..0xFF7F */
9270 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9271 : 1))); /* 0xA0A0..0xFFFF */
9274 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9275 fontp
->baseline_offset
9276 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9277 ? (long) value
: 0);
9278 fontp
->relative_compose
9279 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9280 ? (long) value
: 0);
9281 fontp
->default_ascent
9282 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9283 ? (long) value
: 0);
9285 fontp
->baseline_offset
= 0;
9286 fontp
->relative_compose
= 0;
9287 fontp
->default_ascent
= 0;
9290 /* Set global flag fonts_changed_p to non-zero if the font loaded
9291 has a character with a smaller width than any other character
9292 before, or if the font loaded has a smaller height than any
9293 other font loaded before. If this happens, it will make a
9294 glyph matrix reallocation necessary. */
9295 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9302 /* Return a pointer to struct font_info of a font named FONTNAME for
9303 frame F. If no such font is loaded, return NULL. */
9306 x_query_font (f
, fontname
)
9308 register char *fontname
;
9310 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9313 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9314 if (dpyinfo
->font_table
[i
].name
9315 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9316 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9317 return (dpyinfo
->font_table
+ i
);
9322 /* Find a CCL program for a font specified by FONTP, and set the member
9323 `encoder' of the structure. */
9326 x_find_ccl_program (fontp
)
9327 struct font_info
*fontp
;
9329 Lisp_Object list
, elt
;
9331 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9335 && STRINGP (XCAR (elt
))
9336 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9342 struct ccl_program
*ccl
9343 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9345 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9348 fontp
->font_encoder
= ccl
;
9352 #if USE_MAC_FONT_PANEL
9353 /* Whether Font Panel has been shown before. The first call to font
9354 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9355 slow. This variable is used for deferring such a call as much as
9357 static int font_panel_shown_p
= 0;
9359 extern Lisp_Object Qfont
;
9360 static Lisp_Object Qpanel_closed
, Qselection
;
9362 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9366 const EventParamName
*,
9367 const EventParamType
*));
9370 mac_font_panel_visible_p ()
9372 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9375 static pascal OSStatus
9376 mac_handle_font_event (next_handler
, event
, data
)
9377 EventHandlerCallRef next_handler
;
9381 OSStatus result
, err
;
9384 const EventParamName
*names
;
9385 const EventParamType
*types
;
9386 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9387 kEventParamATSUFontSize
,
9388 kEventParamFMFontFamily
,
9389 kEventParamFMFontSize
,
9390 kEventParamFontColor
};
9391 static const EventParamType types_sel
[] = {typeATSUFontID
,
9397 result
= CallNextEventHandler (next_handler
, event
);
9398 if (result
!= eventNotHandledErr
)
9401 switch (GetEventKind (event
))
9403 case kEventFontPanelClosed
:
9404 id_key
= Qpanel_closed
;
9410 case kEventFontSelection
:
9411 id_key
= Qselection
;
9412 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9418 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9428 mac_show_hide_font_panel ()
9430 if (!font_panel_shown_p
)
9434 static const EventTypeSpec specs
[] =
9435 {{kEventClassFont
, kEventFontPanelClosed
},
9436 {kEventClassFont
, kEventFontSelection
}};
9438 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9439 GetEventTypeCount (specs
),
9444 font_panel_shown_p
= 1;
9447 return FPShowHideFontPanel ();
9451 mac_set_font_info_for_selection (f
, face_id
, c
)
9456 EventTargetRef target
= NULL
;
9457 XFontStruct
*font
= NULL
;
9459 if (!mac_font_panel_visible_p ())
9464 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9466 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9470 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9471 face
= FACE_FROM_ID (f
, face_id
);
9477 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9480 if (font
->mac_fontnum
!= -1)
9482 FontSelectionQDStyle qd_style
;
9484 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9485 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9486 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9487 qd_style
.size
= font
->mac_fontsize
;
9488 qd_style
.hasColor
= false;
9490 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9491 1, &qd_style
, target
);
9494 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9495 1, &font
->mac_style
, target
);
9503 /* The Mac Event loop code */
9505 #if !TARGET_API_MAC_CARBON
9507 #include <Quickdraw.h>
9508 #include <Balloons.h>
9509 #include <Devices.h>
9511 #include <Gestalt.h>
9513 #include <Processes.h>
9515 #include <ToolUtils.h>
9516 #include <TextUtils.h>
9517 #include <Dialogs.h>
9520 #include <Resources.h>
9525 #endif /* ! TARGET_API_MAC_CARBON */
9530 #define DEFAULT_NUM_COLS 80
9532 #define MIN_DOC_SIZE 64
9533 #define MAX_DOC_SIZE 32767
9535 #define EXTRA_STACK_ALLOC (256 * 1024)
9537 #define ARGV_STRING_LIST_ID 129
9538 #define ABOUT_ALERT_ID 128
9539 #define RAM_TOO_LARGE_ALERT_ID 129
9541 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9542 Lisp_Object Qreverse
;
9545 /* Modifier associated with the control key, or nil to ignore. */
9546 Lisp_Object Vmac_control_modifier
;
9548 /* Modifier associated with the option key, or nil to ignore. */
9549 Lisp_Object Vmac_option_modifier
;
9551 /* Modifier associated with the command key, or nil to ignore. */
9552 Lisp_Object Vmac_command_modifier
;
9554 /* Modifier associated with the function key, or nil to ignore. */
9555 Lisp_Object Vmac_function_modifier
;
9557 /* True if the option and command modifiers should be used to emulate
9558 a three button mouse */
9559 Lisp_Object Vmac_emulate_three_button_mouse
;
9561 #if TARGET_API_MAC_CARBON
9562 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9563 mouse-2, instead of mouse-3. */
9564 int mac_wheel_button_is_mouse_2
;
9566 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9567 for processing before Emacs sees it. */
9568 int mac_pass_command_to_system
;
9570 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9571 for processing before Emacs sees it. */
9572 int mac_pass_control_to_system
;
9575 /* Points to the variable `inev' in the function XTread_socket. It is
9576 used for passing an input event to the function back from
9577 Carbon/Apple event handlers. */
9578 static struct input_event
*read_socket_inev
= NULL
;
9580 /* Whether or not the screen configuration has changed. */
9581 static int mac_screen_config_changed
= 0;
9583 Point saved_menu_event_location
;
9586 #if TARGET_API_MAC_CARBON
9587 static Lisp_Object Qhi_command
;
9589 extern Lisp_Object Qwindow
;
9590 static Lisp_Object Qtoolbar_switch_mode
;
9593 static TSMDocumentID tsm_document_id
;
9594 static Lisp_Object Qtext_input
;
9595 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9596 static Lisp_Object Vmac_ts_active_input_overlay
;
9597 extern Lisp_Object Qbefore_string
;
9598 static Lisp_Object Vmac_ts_script_language_on_focus
;
9599 static Lisp_Object saved_ts_script_language_on_focus
;
9600 static ScriptLanguageRecord saved_ts_language
;
9601 static Component saved_ts_component
;
9603 #endif /* TARGET_API_MAC_CARBON */
9604 extern int mac_ready_for_apple_events
;
9605 extern Lisp_Object Qundefined
;
9606 extern void init_apple_event_handler
P_ ((void));
9607 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9608 Lisp_Object
*, Lisp_Object
*,
9610 extern OSErr init_coercion_handler
P_ ((void));
9613 extern OSErr install_drag_handler
P_ ((WindowRef
));
9614 extern void remove_drag_handler
P_ ((WindowRef
));
9616 #if TARGET_API_MAC_CARBON
9617 /* Showing help echo string during menu tracking */
9618 extern OSStatus install_menu_target_item_handler
P_ ((void));
9621 extern OSStatus
install_service_handler ();
9622 static Lisp_Object Qservice
, Qpaste
, Qperform
;
9626 extern void init_emacs_passwd_dir ();
9627 extern int emacs_main (int, char **, char **);
9629 extern void initialize_applescript();
9630 extern void terminate_applescript();
9632 /* Table for translating Mac keycode to X keysym values. Contributed
9634 Mapping for special keys is now identical to that in Apple X11
9635 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9636 on the right of the Cmd key on laptops, and fn + `enter' (->
9638 static const unsigned char keycode_to_xkeysym_table
[] = {
9639 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9640 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9641 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9643 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9644 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9645 /*0x38*/ 0, 0, 0, 0,
9646 /*0x3C*/ 0, 0, 0, 0,
9648 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9649 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9650 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9651 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9653 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9654 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9655 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9656 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9658 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9659 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9660 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9661 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9663 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9664 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9665 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9666 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9670 /* Table for translating Mac keycode with the laptop `fn' key to that
9671 without it. Destination symbols in comments are keys on US
9672 keyboard, and they may not be the same on other types of keyboards.
9673 If the destination is identical to the source (f1 ... f12), it
9674 doesn't map `fn' key to a modifier. */
9675 static const unsigned char fn_keycode_to_keycode_table
[] = {
9676 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9677 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9678 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9680 /*0x30*/ 0, 0, 0, 0,
9681 /*0x34*/ 0, 0, 0, 0,
9682 /*0x38*/ 0, 0, 0, 0,
9683 /*0x3C*/ 0, 0, 0, 0,
9685 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9686 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9687 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9688 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9690 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9691 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9692 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9693 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9695 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9696 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9697 /*0x68*/ 0, 0, 0, 0,
9698 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9700 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9701 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9702 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9705 #endif /* MAC_OSX */
9708 #if TARGET_API_MAC_CARBON
9709 mac_to_emacs_modifiers (UInt32 mods
)
9711 mac_to_emacs_modifiers (EventModifiers mods
)
9714 unsigned int result
= 0;
9715 if (mods
& shiftKey
)
9716 result
|= shift_modifier
;
9718 /* Deactivated to simplify configuration:
9719 if Vmac_option_modifier is non-NIL, we fully process the Option
9720 key. Otherwise, we only process it if an additional Ctrl or Command
9721 is pressed. That way the system may convert the character to a
9723 if ((mods & optionKey) &&
9724 (( !NILP(Vmac_option_modifier) ||
9725 ((mods & cmdKey) || (mods & controlKey))))) */
9727 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9728 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9730 result
|= XUINT(val
);
9732 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9733 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9735 result
|= XUINT(val
);
9737 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9738 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9740 result
|= XUINT(val
);
9744 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9745 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9747 result
|= XUINT(val
);
9755 mac_mapped_modifiers (modifiers
)
9758 UInt32 mapped_modifiers_all
=
9759 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9760 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9761 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9764 mapped_modifiers_all
|=
9765 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9768 return mapped_modifiers_all
& modifiers
;
9772 mac_get_emulated_btn ( UInt32 modifiers
)
9775 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9776 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9777 if (modifiers
& cmdKey
)
9778 result
= cmdIs3
? 2 : 1;
9779 else if (modifiers
& optionKey
)
9780 result
= cmdIs3
? 1 : 2;
9785 #if TARGET_API_MAC_CARBON
9786 /***** Code to handle C-g testing *****/
9787 extern int quit_char
;
9788 extern int make_ctrl_char
P_ ((int));
9791 mac_quit_char_key_p (modifiers
, key_code
)
9792 UInt32 modifiers
, key_code
;
9795 unsigned long some_state
= 0;
9796 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9797 int c
, emacs_modifiers
;
9799 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9800 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9801 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9802 if (char_code
& ~0xff)
9805 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9806 if (emacs_modifiers
& ctrl_modifier
)
9807 c
= make_ctrl_char (char_code
);
9809 c
|= (emacs_modifiers
9810 & (meta_modifier
| alt_modifier
9811 | hyper_modifier
| super_modifier
));
9813 return c
== quit_char
;
9817 #if TARGET_API_MAC_CARBON
9818 /* Obtains the event modifiers from the event ref and then calls
9819 mac_to_emacs_modifiers. */
9821 mac_event_to_emacs_modifiers (EventRef eventRef
)
9823 UInt32 mods
= 0, class;
9825 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9826 sizeof (UInt32
), NULL
, &mods
);
9827 class = GetEventClass (eventRef
);
9828 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9829 (class == kEventClassMouse
|| class == kEventClassCommand
))
9831 mods
&= ~(optionKey
| cmdKey
);
9833 return mac_to_emacs_modifiers (mods
);
9836 /* Given an event ref, return the code to use for the mouse button
9837 code in the emacs input_event. */
9839 mac_get_mouse_btn (EventRef ref
)
9841 EventMouseButton result
= kEventMouseButtonPrimary
;
9842 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9843 sizeof (EventMouseButton
), NULL
, &result
);
9846 case kEventMouseButtonPrimary
:
9847 if (NILP (Vmac_emulate_three_button_mouse
))
9851 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9852 sizeof (UInt32
), NULL
, &mods
);
9853 return mac_get_emulated_btn(mods
);
9855 case kEventMouseButtonSecondary
:
9856 return mac_wheel_button_is_mouse_2
? 2 : 1;
9857 case kEventMouseButtonTertiary
:
9858 case 4: /* 4 is the number for the mouse wheel button */
9859 return mac_wheel_button_is_mouse_2
? 1 : 2;
9865 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9866 events. However the click of the mouse wheel is not converted to a
9867 mouseDown or mouseUp event. Likewise for dead key events. This
9868 calls ConvertEventRefToEventRecord, but then checks to see if it is
9869 a mouse up/down, or a dead key Carbon event that has not been
9870 converted, and if so, converts it by hand (to be picked up in the
9871 XTread_socket loop). */
9872 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9875 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9881 switch (GetEventClass (eventRef
))
9883 case kEventClassMouse
:
9884 switch (GetEventKind (eventRef
))
9886 case kEventMouseDown
:
9887 eventRec
->what
= mouseDown
;
9892 eventRec
->what
= mouseUp
;
9901 case kEventClassKeyboard
:
9902 switch (GetEventKind (eventRef
))
9904 case kEventRawKeyDown
:
9906 goto keystroke_common
;
9907 case kEventRawKeyRepeat
:
9909 goto keystroke_common
;
9910 case kEventRawKeyUp
:
9914 unsigned char char_codes
;
9917 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9918 typeChar
, NULL
, sizeof (char),
9921 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9922 typeUInt32
, NULL
, sizeof (UInt32
),
9926 eventRec
->what
= action
;
9927 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9944 /* Need where and when. */
9947 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9948 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9949 /* Use two step process because new event modifiers are 32-bit
9950 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9951 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9952 NULL
, sizeof (UInt32
), NULL
, &mods
);
9953 eventRec
->modifiers
= mods
;
9955 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9967 Handle menubar_handle
;
9970 menubar_handle
= GetNewMBar (128);
9971 if(menubar_handle
== NULL
)
9973 SetMenuBar (menubar_handle
);
9976 #if !TARGET_API_MAC_CARBON
9977 menu
= GetMenuRef (M_APPLE
);
9979 AppendResMenu (menu
, 'DRVR');
9987 do_init_managers (void)
9989 #if !TARGET_API_MAC_CARBON
9990 InitGraf (&qd
.thePort
);
9992 FlushEvents (everyEvent
, 0);
9997 #endif /* !TARGET_API_MAC_CARBON */
10000 #if !TARGET_API_MAC_CARBON
10001 /* set up some extra stack space for use by emacs */
10002 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10004 /* MaxApplZone must be called for AppleScript to execute more
10005 complicated scripts */
10008 #endif /* !TARGET_API_MAC_CARBON */
10012 do_check_ram_size (void)
10014 SInt32 physical_ram_size
, logical_ram_size
;
10016 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10017 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10018 || physical_ram_size
> (1 << VALBITS
)
10019 || logical_ram_size
> (1 << VALBITS
))
10021 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10025 #endif /* MAC_OS8 */
10028 do_window_update (WindowRef win
)
10030 struct frame
*f
= mac_window_to_frame (win
);
10034 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10036 if (win
!= tip_window
)
10038 if (f
->async_visible
== 0)
10040 /* Update events may occur when a frame gets iconified. */
10042 f
->async_visible
= 1;
10043 f
->async_iconified
= 0;
10044 SET_FRAME_GARBAGED (f
);
10050 #if TARGET_API_MAC_CARBON
10051 RgnHandle region
= NewRgn ();
10053 GetPortVisibleRegion (GetWindowPort (win
), region
);
10054 GetRegionBounds (region
, &r
);
10055 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10057 mac_prepare_for_quickdraw (f
);
10059 UpdateControls (win
, region
);
10060 DisposeRgn (region
);
10062 r
= (*win
->visRgn
)->rgnBBox
;
10063 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10064 UpdateControls (win
, win
->visRgn
);
10073 is_emacs_window (WindowRef win
)
10075 Lisp_Object tail
, frame
;
10080 FOR_EACH_FRAME (tail
, frame
)
10081 if (FRAME_MAC_P (XFRAME (frame
)))
10082 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10093 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10095 err
= ActivateTSMDocument (tsm_document_id
);
10099 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10100 && EQ (saved_ts_script_language_on_focus
, Qt
))
10101 slptr
= &saved_ts_language
;
10102 else if (CONSP (Vmac_ts_script_language_on_focus
)
10103 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10104 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10105 && CONSP (saved_ts_script_language_on_focus
)
10106 && EQ (XCAR (saved_ts_script_language_on_focus
),
10107 XCAR (Vmac_ts_script_language_on_focus
))
10108 && EQ (XCDR (saved_ts_script_language_on_focus
),
10109 XCDR (Vmac_ts_script_language_on_focus
)))
10111 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10112 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10119 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10120 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10121 kKeyboardInputMethodClass
);
10123 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10126 err
= SetTextServiceLanguage (slptr
);
10128 /* Seems to be needed on Mac OS X 10.2. */
10130 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10140 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10142 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10144 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10146 err
= GetTextServiceLanguage (&saved_ts_language
);
10148 slptr
= &saved_ts_language
;
10150 else if (CONSP (Vmac_ts_script_language_on_focus
)
10151 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10152 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10154 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10155 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10161 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10162 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10163 kKeyboardInputMethodClass
);
10165 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10169 err
= DeactivateTSMDocument (tsm_document_id
);
10175 #if !TARGET_API_MAC_CARBON
10177 do_apple_menu (SInt16 menu_item
)
10180 SInt16 da_driver_refnum
;
10182 if (menu_item
== I_ABOUT
)
10183 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10186 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10187 da_driver_refnum
= OpenDeskAcc (item_name
);
10190 #endif /* !TARGET_API_MAC_CARBON */
10192 /* Handle drags in size box. Based on code contributed by Ben
10193 Mesander and IM - Window Manager A. */
10196 do_grow_window (w
, e
)
10198 const EventRecord
*e
;
10201 int rows
, columns
, width
, height
;
10202 struct frame
*f
= mac_window_to_frame (w
);
10203 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10204 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10205 #if TARGET_API_MAC_CARBON
10211 if (size_hints
->flags
& PMinSize
)
10213 min_width
= size_hints
->min_width
;
10214 min_height
= size_hints
->min_height
;
10216 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10218 #if TARGET_API_MAC_CARBON
10219 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10221 height
= new_rect
.bottom
- new_rect
.top
;
10222 width
= new_rect
.right
- new_rect
.left
;
10224 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10225 /* see if it really changed size */
10226 if (grow_size
== 0)
10228 height
= HiWord (grow_size
);
10229 width
= LoWord (grow_size
);
10232 if (width
!= FRAME_PIXEL_WIDTH (f
)
10233 || height
!= FRAME_PIXEL_HEIGHT (f
))
10235 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10236 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10238 x_set_window_size (f
, 0, columns
, rows
);
10243 #if TARGET_API_MAC_CARBON
10245 mac_get_ideal_size (f
)
10248 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10249 WindowRef w
= FRAME_MAC_WINDOW (f
);
10251 Rect standard_rect
;
10252 int height
, width
, columns
, rows
;
10254 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10255 ideal_size
.v
= dpyinfo
->height
;
10256 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10257 /* Adjust the standard size according to character boundaries. */
10258 width
= standard_rect
.right
- standard_rect
.left
;
10259 height
= standard_rect
.bottom
- standard_rect
.top
;
10260 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10261 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10262 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10263 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10269 /* Handle clicks in zoom box. Calculation of "standard state" based
10270 on code in IM - Window Manager A and code contributed by Ben
10271 Mesander. The standard state of an Emacs window is 80-characters
10272 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10275 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10277 Rect zoom_rect
, port_rect
;
10279 struct frame
*f
= mac_window_to_frame (w
);
10280 #if TARGET_API_MAC_CARBON
10281 Point ideal_size
= mac_get_ideal_size (f
);
10283 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10284 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10285 && port_rect
.left
== zoom_rect
.left
10286 && port_rect
.top
== zoom_rect
.top
)
10287 zoom_in_or_out
= inZoomIn
;
10289 zoom_in_or_out
= inZoomOut
;
10292 mac_clear_window (f
);
10294 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10295 #else /* not TARGET_API_MAC_CARBON */
10298 int w_title_height
, rows
;
10299 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10301 GetPort (&save_port
);
10303 SetPortWindowPort (w
);
10305 /* Clear window to avoid flicker. */
10306 EraseRect (&(w
->portRect
));
10307 if (zoom_in_or_out
== inZoomOut
)
10309 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10310 LocalToGlobal (&top_left
);
10312 /* calculate height of window's title bar */
10313 w_title_height
= top_left
.v
- 1
10314 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10316 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10317 zoom_rect
= qd
.screenBits
.bounds
;
10318 zoom_rect
.top
+= w_title_height
;
10319 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10321 zoom_rect
.right
= zoom_rect
.left
10322 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10324 /* Adjust the standard size according to character boundaries. */
10325 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10327 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10329 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10333 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10335 SetPort (save_port
);
10336 #endif /* not TARGET_API_MAC_CARBON */
10338 #if !TARGET_API_MAC_CARBON
10339 /* retrieve window size and update application values */
10340 port_rect
= w
->portRect
;
10341 height
= port_rect
.bottom
- port_rect
.top
;
10342 width
= port_rect
.right
- port_rect
.left
;
10344 mac_handle_size_change (f
, width
, height
);
10345 mac_handle_origin_change (f
);
10350 mac_set_unicode_keystroke_event (code
, buf
)
10352 struct input_event
*buf
;
10354 int charset_id
, c1
, c2
;
10358 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10361 else if (code
< 0x100)
10364 charset_id
= CHARSET_8_BIT_CONTROL
;
10366 charset_id
= charset_latin_iso8859_1
;
10367 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10368 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10373 charset_id
= charset_mule_unicode_0100_24ff
,
10375 else if (code
< 0x33FF)
10376 charset_id
= charset_mule_unicode_2500_33ff
,
10378 else if (code
>= 0xE000)
10379 charset_id
= charset_mule_unicode_e000_ffff
,
10381 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10382 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10383 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10388 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10390 unsigned char char_code
;
10391 UInt32 key_code
, modifiers
;
10392 unsigned long timestamp
;
10393 struct input_event
*buf
;
10395 static SInt16 last_key_script
= -1;
10396 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10397 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10400 if (mapped_modifiers
& kEventKeyModifierFnMask
10401 && key_code
<= 0x7f
10402 && fn_keycode_to_keycode_table
[key_code
])
10403 key_code
= fn_keycode_to_keycode_table
[key_code
];
10406 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10408 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10409 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10411 if (modifiers
& kEventKeyModifierFnMask
10412 && key_code
<= 0x7f
10413 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10414 modifiers
&= ~kEventKeyModifierFnMask
;
10417 else if (mapped_modifiers
)
10419 /* translate the keycode back to determine the original key */
10421 UCKeyboardLayout
*uchr_ptr
= NULL
;
10422 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10424 KeyboardLayoutRef layout
;
10426 err
= KLGetCurrentKeyboardLayout (&layout
);
10428 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10429 (const void **) &uchr_ptr
);
10431 static SInt16 last_key_layout_id
= 0;
10432 static Handle uchr_handle
= (Handle
)-1;
10433 SInt16 current_key_layout_id
=
10434 GetScriptVariable (current_key_script
, smScriptKeys
);
10436 if (uchr_handle
== (Handle
)-1
10437 || last_key_layout_id
!= current_key_layout_id
)
10439 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10440 last_key_layout_id
= current_key_layout_id
;
10443 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10449 UInt16 key_action
= action
- keyDown
;
10450 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10451 UInt32 keyboard_type
= LMGetKbdType ();
10452 SInt32 dead_key_state
= 0;
10454 UniCharCount actual_length
;
10456 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10457 modifier_key_state
, keyboard_type
,
10458 kUCKeyTranslateNoDeadKeysMask
,
10460 1, &actual_length
, &code
);
10461 if (status
== noErr
&& actual_length
== 1)
10462 mac_set_unicode_keystroke_event (code
, buf
);
10464 #endif /* MAC_OSX */
10466 if (buf
->kind
== NO_EVENT
)
10468 /* This code comes from Keyboard Resource, Appendix C of IM
10469 - Text. This is necessary since shift is ignored in KCHR
10470 table translation when option or command is pressed. It
10471 also does not translate correctly control-shift chars
10472 like C-% so mask off shift here also. */
10473 /* Mask off modifier keys that are mapped to some Emacs
10475 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10476 /* set high byte of keycode to modifier high byte*/
10477 int new_key_code
= key_code
| new_modifiers
;
10478 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10479 unsigned long some_state
= 0;
10480 UInt32 new_char_code
;
10482 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10483 if (new_char_code
== 0)
10484 /* Seems like a dead key. Append up-stroke. */
10485 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10489 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10490 buf
->code
= new_char_code
& 0xff;
10495 if (buf
->kind
== NO_EVENT
)
10497 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10498 buf
->code
= char_code
;
10501 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10502 buf
->modifiers
|= (extra_keyboard_modifiers
10503 & (meta_modifier
| alt_modifier
10504 | hyper_modifier
| super_modifier
));
10506 #if TARGET_API_MAC_CARBON
10507 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10508 && buf
->code
>= 0x80 && buf
->modifiers
)
10511 TextEncoding encoding
= kTextEncodingMacRoman
;
10512 TextToUnicodeInfo ttu_info
;
10514 UpgradeScriptInfoToTextEncoding (current_key_script
,
10515 kTextLanguageDontCare
,
10516 kTextRegionDontCare
,
10518 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10523 ByteCount unicode_len
;
10526 pstr
[1] = buf
->code
;
10527 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10529 &unicode_len
, &code
);
10530 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10531 mac_set_unicode_keystroke_event (code
, buf
);
10532 DisposeTextToUnicodeInfo (&ttu_info
);
10537 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10538 && buf
->code
>= 0x80
10539 && last_key_script
!= current_key_script
)
10541 struct input_event event
;
10543 EVENT_INIT (event
);
10544 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10546 event
.code
= current_key_script
;
10547 event
.timestamp
= timestamp
;
10548 kbd_buffer_store_event (&event
);
10549 last_key_script
= current_key_script
;
10554 mac_store_apple_event (class, id
, desc
)
10555 Lisp_Object
class, id
;
10556 const AEDesc
*desc
;
10558 struct input_event buf
;
10562 buf
.kind
= MAC_APPLE_EVENT
;
10565 XSETFRAME (buf
.frame_or_window
,
10566 mac_focus_frame (&one_mac_display_info
));
10567 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10568 is safe to use them during read_socket_hook. */
10569 buf
.arg
= mac_aedesc_to_lisp (desc
);
10570 kbd_buffer_store_event (&buf
);
10573 #if TARGET_API_MAC_CARBON
10575 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10576 event
, num_params
, names
, types
)
10577 AEEventClass
class;
10579 Lisp_Object class_key
, id_key
;
10582 const EventParamName
*names
;
10583 const EventParamType
*types
;
10585 OSStatus err
= eventNotHandledErr
;
10586 Lisp_Object binding
;
10588 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10589 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10591 if (INTEGERP (binding
))
10592 err
= XINT (binding
);
10595 AppleEvent apple_event
;
10596 err
= create_apple_event_from_event_ref (event
, num_params
,
10601 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10602 AEDisposeDesc (&apple_event
);
10603 mac_wakeup_from_rne ();
10612 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10616 const AEDesc
*desc
;
10618 struct input_event buf
;
10622 buf
.kind
= DRAG_N_DROP_EVENT
;
10623 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10624 buf
.timestamp
= TickCount () * (1000 / 60);
10625 XSETINT (buf
.x
, mouse_pos
.h
);
10626 XSETINT (buf
.y
, mouse_pos
.v
);
10627 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10628 buf
.arg
= mac_aedesc_to_lisp (desc
);
10629 kbd_buffer_store_event (&buf
);
10634 mac_store_service_event (event
)
10638 Lisp_Object id_key
;
10640 const EventParamName
*names
;
10641 const EventParamType
*types
;
10642 static const EventParamName names_pfm
[] =
10643 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10644 static const EventParamType types_pfm
[] =
10645 {typeCFStringRef
, typeCFStringRef
};
10647 switch (GetEventKind (event
))
10649 case kEventServicePaste
:
10656 case kEventServicePerform
:
10658 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10667 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10673 #endif /* MAC_OSX */
10675 static pascal OSStatus
10676 mac_handle_window_event (next_handler
, event
, data
)
10677 EventHandlerCallRef next_handler
;
10682 OSStatus err
, result
= eventNotHandledErr
;
10685 XSizeHints
*size_hints
;
10687 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
10688 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10690 return eventNotHandledErr
;
10692 f
= mac_window_to_frame (wp
);
10693 switch (GetEventKind (event
))
10695 /* -- window refresh events -- */
10697 case kEventWindowUpdate
:
10698 result
= CallNextEventHandler (next_handler
, event
);
10699 if (result
!= eventNotHandledErr
)
10702 do_window_update (wp
);
10706 /* -- window state change events -- */
10708 case kEventWindowShowing
:
10709 size_hints
= FRAME_SIZE_HINTS (f
);
10710 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
10712 struct frame
*sf
= SELECTED_FRAME ();
10714 if (!(FRAME_MAC_P (sf
)))
10715 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
10718 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
10719 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10720 kWindowCascadeStartAtParentWindowScreen
10722 kWindowCascadeOnParentWindowScreen
10725 #if USE_MAC_TOOLBAR
10726 /* This is a workaround. RepositionWindow fails to put
10727 a window at the cascading position when its parent
10728 window has a Carbon HIToolbar. */
10729 if (f
->top_pos
== sf
->top_pos
&& f
->left_pos
== sf
->left_pos
)
10730 MoveWindowStructure (wp
, f
->left_pos
+ 10, f
->top_pos
+ 32);
10737 case kEventWindowHiding
:
10738 /* Before unmapping the window, update the WM_SIZE_HINTS
10739 property to claim that the current position of the window is
10740 user-specified, rather than program-specified, so that when
10741 the window is mapped again, it will be placed at the same
10742 location, without forcing the user to position it by hand
10743 again (they have already done that once for this window.) */
10744 x_wm_set_size_hint (f
, (long) 0, 1);
10748 case kEventWindowShown
:
10749 case kEventWindowHidden
:
10750 case kEventWindowCollapsed
:
10751 case kEventWindowExpanded
:
10752 mac_handle_visibility_change (f
);
10756 case kEventWindowBoundsChanging
:
10757 result
= CallNextEventHandler (next_handler
, event
);
10758 if (result
!= eventNotHandledErr
)
10761 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10762 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10766 size_hints
= FRAME_SIZE_HINTS (f
);
10767 if ((attributes
& kWindowBoundsChangeUserResize
)
10768 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
10769 == (PResizeInc
| PBaseSize
| PMinSize
)))
10774 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10775 typeQDRectangle
, NULL
, sizeof (Rect
),
10780 width
= bounds
.right
- bounds
.left
;
10781 height
= bounds
.bottom
- bounds
.top
;
10783 if (width
< size_hints
->min_width
)
10784 width
= size_hints
->min_width
;
10786 width
= size_hints
->base_width
10787 + (int) ((width
- size_hints
->base_width
)
10788 / (float) size_hints
->width_inc
+ .5)
10789 * size_hints
->width_inc
;
10791 if (height
< size_hints
->min_height
)
10792 height
= size_hints
->min_height
;
10794 height
= size_hints
->base_height
10795 + (int) ((height
- size_hints
->base_height
)
10796 / (float) size_hints
->height_inc
+ .5)
10797 * size_hints
->height_inc
;
10799 bounds
.right
= bounds
.left
+ width
;
10800 bounds
.bottom
= bounds
.top
+ height
;
10801 SetEventParameter (event
, kEventParamCurrentBounds
,
10802 typeQDRectangle
, sizeof (Rect
), &bounds
);
10807 case kEventWindowBoundsChanged
:
10808 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10809 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10813 if (attributes
& kWindowBoundsChangeSizeChanged
)
10817 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10818 typeQDRectangle
, NULL
, sizeof (Rect
),
10824 width
= bounds
.right
- bounds
.left
;
10825 height
= bounds
.bottom
- bounds
.top
;
10826 mac_handle_size_change (f
, width
, height
);
10827 mac_wakeup_from_rne ();
10831 if (attributes
& kWindowBoundsChangeOriginChanged
)
10832 mac_handle_origin_change (f
);
10837 /* -- window action events -- */
10839 case kEventWindowClose
:
10841 struct input_event buf
;
10844 buf
.kind
= DELETE_WINDOW_EVENT
;
10845 XSETFRAME (buf
.frame_or_window
, f
);
10847 kbd_buffer_store_event (&buf
);
10852 case kEventWindowGetIdealSize
:
10853 result
= CallNextEventHandler (next_handler
, event
);
10854 if (result
!= eventNotHandledErr
)
10858 Point ideal_size
= mac_get_ideal_size (f
);
10860 err
= SetEventParameter (event
, kEventParamDimensions
,
10861 typeQDPoint
, sizeof (Point
), &ideal_size
);
10868 case kEventWindowToolbarSwitchMode
:
10870 static const EventParamName names
[] = {kEventParamDirectObject
,
10871 kEventParamWindowMouseLocation
,
10872 kEventParamKeyModifiers
,
10873 kEventParamMouseButton
,
10874 kEventParamClickCount
,
10875 kEventParamMouseChord
};
10876 static const EventParamType types
[] = {typeWindowRef
,
10882 int num_params
= sizeof (names
) / sizeof (names
[0]);
10884 err
= mac_store_event_ref_as_apple_event (0, 0,
10886 Qtoolbar_switch_mode
,
10896 /* -- window focus events -- */
10898 case kEventWindowFocusAcquired
:
10899 err
= mac_tsm_resume ();
10904 case kEventWindowFocusRelinquish
:
10905 err
= mac_tsm_suspend ();
10918 static pascal OSStatus
10919 mac_handle_application_event (next_handler
, event
, data
)
10920 EventHandlerCallRef next_handler
;
10924 OSStatus err
, result
= eventNotHandledErr
;
10926 switch (GetEventKind (event
))
10929 case kEventAppActivated
:
10930 err
= mac_tsm_resume ();
10933 case kEventAppDeactivated
:
10934 err
= mac_tsm_suspend ();
10948 static pascal OSStatus
10949 mac_handle_keyboard_event (next_handler
, event
, data
)
10950 EventHandlerCallRef next_handler
;
10954 OSStatus err
, result
= eventNotHandledErr
;
10955 UInt32 event_kind
, key_code
, modifiers
, mapped_modifiers
;
10956 unsigned char char_code
;
10958 event_kind
= GetEventKind (event
);
10959 switch (event_kind
)
10961 case kEventRawKeyDown
:
10962 case kEventRawKeyRepeat
:
10963 case kEventRawKeyUp
:
10964 if (read_socket_inev
== NULL
)
10966 result
= CallNextEventHandler (next_handler
, event
);
10970 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
10972 sizeof (UInt32
), NULL
, &modifiers
);
10976 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10978 /* When using Carbon Events, we need to pass raw keyboard events
10979 to the TSM ourselves. If TSM handles it, it will pass back
10980 noErr, otherwise it will pass back "eventNotHandledErr" and
10981 we can process it normally. */
10982 if (!(mapped_modifiers
10983 & ~(mac_pass_command_to_system
? cmdKey
: 0)
10984 & ~(mac_pass_control_to_system
? controlKey
: 0)))
10986 result
= CallNextEventHandler (next_handler
, event
);
10987 if (result
!= eventNotHandledErr
)
10992 if (read_socket_inev
->kind
!= NO_EVENT
)
10999 if (event_kind
== kEventRawKeyUp
)
11002 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11004 sizeof (char), NULL
, &char_code
);
11008 err
= GetEventParameter (event
, kEventParamKeyCode
,
11010 sizeof (UInt32
), NULL
, &key_code
);
11014 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11015 char_code
, key_code
, modifiers
,
11017 (GetEventTime (event
) / kEventDurationMillisecond
)),
11029 static pascal OSStatus
11030 mac_handle_command_event (next_handler
, event
, data
)
11031 EventHandlerCallRef next_handler
;
11035 OSStatus err
, result
= eventNotHandledErr
;
11037 static const EventParamName names
[] =
11038 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11039 static const EventParamType types
[] =
11040 {typeHICommand
, typeUInt32
};
11041 int num_params
= sizeof (names
) / sizeof (names
[0]);
11043 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11044 NULL
, sizeof (HICommand
), NULL
, &command
);
11046 return eventNotHandledErr
;
11048 switch (GetEventKind (event
))
11050 case kEventCommandProcess
:
11051 result
= CallNextEventHandler (next_handler
, event
);
11052 if (result
!= eventNotHandledErr
)
11055 err
= GetEventParameter (event
, kEventParamDirectObject
,
11056 typeHICommand
, NULL
,
11057 sizeof (HICommand
), NULL
, &command
);
11059 if (err
!= noErr
|| command
.commandID
== 0)
11062 /* A HI command event is mapped to an Apple event whose event
11063 class symbol is `hi-command' and event ID is its command
11065 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11080 static pascal OSStatus
11081 mac_handle_mouse_event (next_handler
, event
, data
)
11082 EventHandlerCallRef next_handler
;
11086 OSStatus err
, result
= eventNotHandledErr
;
11088 switch (GetEventKind (event
))
11090 case kEventMouseWheelMoved
:
11094 EventMouseWheelAxis axis
;
11098 result
= CallNextEventHandler (next_handler
, event
);
11099 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11102 f
= mac_focus_frame (&one_mac_display_info
);
11104 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11105 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11107 || wp
!= FRAME_MAC_WINDOW (f
))
11110 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11111 typeMouseWheelAxis
, NULL
,
11112 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11113 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11116 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11117 typeQDPoint
, NULL
, sizeof (Point
),
11122 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11123 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11124 if (point
.h
< 0 || point
.v
< 0
11125 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11126 f
->tool_bar_window
))
11129 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11130 typeSInt32
, NULL
, sizeof (SInt32
),
11135 read_socket_inev
->kind
= WHEEL_EVENT
;
11136 read_socket_inev
->code
= 0;
11137 read_socket_inev
->modifiers
=
11138 (mac_event_to_emacs_modifiers (event
)
11139 | ((delta
< 0) ? down_modifier
: up_modifier
));
11140 XSETINT (read_socket_inev
->x
, point
.h
);
11141 XSETINT (read_socket_inev
->y
, point
.v
);
11142 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11156 static pascal OSStatus
11157 mac_handle_text_input_event (next_handler
, event
, data
)
11158 EventHandlerCallRef next_handler
;
11162 OSStatus err
, result
;
11163 Lisp_Object id_key
= Qnil
;
11165 const EventParamName
*names
;
11166 const EventParamType
*types
;
11167 static UInt32 seqno_uaia
= 0;
11168 static const EventParamName names_uaia
[] =
11169 {kEventParamTextInputSendComponentInstance
,
11170 kEventParamTextInputSendRefCon
,
11171 kEventParamTextInputSendSLRec
,
11172 kEventParamTextInputSendFixLen
,
11173 kEventParamTextInputSendText
,
11174 kEventParamTextInputSendUpdateRng
,
11175 kEventParamTextInputSendHiliteRng
,
11176 kEventParamTextInputSendClauseRng
,
11177 kEventParamTextInputSendPinRng
,
11178 kEventParamTextInputSendTextServiceEncoding
,
11179 kEventParamTextInputSendTextServiceMacEncoding
,
11180 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11181 static const EventParamType types_uaia
[] =
11182 {typeComponentInstance
,
11184 typeIntlWritingCode
,
11191 typeTextRangeArray
,
11192 typeTextRangeArray
,
11198 static const EventParamName names_ufke
[] =
11199 {kEventParamTextInputSendComponentInstance
,
11200 kEventParamTextInputSendRefCon
,
11201 kEventParamTextInputSendSLRec
,
11202 kEventParamTextInputSendText
};
11203 static const EventParamType types_ufke
[] =
11204 {typeComponentInstance
,
11206 typeIntlWritingCode
,
11209 result
= CallNextEventHandler (next_handler
, event
);
11210 if (result
!= eventNotHandledErr
)
11213 switch (GetEventKind (event
))
11215 case kEventTextInputUpdateActiveInputArea
:
11216 id_key
= Qupdate_active_input_area
;
11217 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11218 names
= names_uaia
;
11219 types
= types_uaia
;
11220 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11221 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11226 case kEventTextInputUnicodeForKeyEvent
:
11228 EventRef kbd_event
;
11229 UInt32 actual_size
, modifiers
;
11231 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11232 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11235 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11237 sizeof (UInt32
), NULL
, &modifiers
);
11238 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11239 /* There're mapped modifier keys. Process it in
11243 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11244 typeUnicodeText
, NULL
, 0, &actual_size
,
11246 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11250 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11251 typeUnicodeText
, NULL
,
11252 sizeof (UniChar
), NULL
, &code
);
11253 if (err
== noErr
&& code
< 0x80)
11255 /* ASCII character. Process it in do_keystroke. */
11256 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11260 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11261 typeUInt32
, NULL
, sizeof (UInt32
),
11263 if (!(err
== noErr
&& key_code
<= 0x7f
11264 && keycode_to_xkeysym_table
[key_code
]))
11267 mac_focus_frame (&one_mac_display_info
);
11269 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11270 read_socket_inev
->code
= code
;
11271 read_socket_inev
->modifiers
=
11272 mac_to_emacs_modifiers (modifiers
);
11273 read_socket_inev
->modifiers
|=
11274 (extra_keyboard_modifiers
11275 & (meta_modifier
| alt_modifier
11276 | hyper_modifier
| super_modifier
));
11277 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11285 /* Non-ASCII keystrokes without mapped modifiers are
11286 processed at the Lisp level. */
11287 id_key
= Qunicode_for_key_event
;
11288 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11289 names
= names_ufke
;
11290 types
= types_ufke
;
11296 case kEventTextInputOffsetToPos
:
11302 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11305 /* Strictly speaking, this is not always correct because
11306 previous events may change some states about display. */
11307 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11309 /* Active input area is displayed around the current point. */
11310 f
= SELECTED_FRAME ();
11311 w
= XWINDOW (f
->selected_window
);
11313 else if (WINDOWP (echo_area_window
))
11315 /* Active input area is displayed in the echo area. */
11316 w
= XWINDOW (echo_area_window
);
11317 f
= WINDOW_XFRAME (w
);
11322 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11323 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11324 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11325 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11326 + FONT_BASE (FRAME_FONT (f
))
11327 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11328 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11329 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11339 if (!NILP (id_key
))
11340 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11346 #endif /* TARGET_API_MAC_CARBON */
11350 install_window_handler (window
)
11353 OSStatus err
= noErr
;
11355 #if TARGET_API_MAC_CARBON
11358 static const EventTypeSpec specs
[] =
11360 /* -- window refresh events -- */
11361 {kEventClassWindow
, kEventWindowUpdate
},
11362 /* -- window state change events -- */
11363 {kEventClassWindow
, kEventWindowShowing
},
11364 {kEventClassWindow
, kEventWindowHiding
},
11365 {kEventClassWindow
, kEventWindowShown
},
11366 {kEventClassWindow
, kEventWindowHidden
},
11367 {kEventClassWindow
, kEventWindowCollapsed
},
11368 {kEventClassWindow
, kEventWindowExpanded
},
11369 {kEventClassWindow
, kEventWindowBoundsChanging
},
11370 {kEventClassWindow
, kEventWindowBoundsChanged
},
11371 /* -- window action events -- */
11372 {kEventClassWindow
, kEventWindowClose
},
11373 {kEventClassWindow
, kEventWindowGetIdealSize
},
11375 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11378 /* -- window focus events -- */
11379 {kEventClassWindow
, kEventWindowFocusAcquired
},
11380 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11383 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11385 if (handle_window_eventUPP
== NULL
)
11386 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11388 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11389 GetEventTypeCount (specs
),
11390 specs
, NULL
, NULL
);
11395 err
= install_drag_handler (window
);
11401 remove_window_handler (window
)
11404 remove_drag_handler (window
);
11407 #if TARGET_API_MAC_CARBON
11409 install_application_handler ()
11411 OSStatus err
= noErr
;
11415 static const EventTypeSpec specs
[] = {
11417 {kEventClassApplication
, kEventAppActivated
},
11418 {kEventClassApplication
, kEventAppDeactivated
},
11422 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11423 (mac_handle_application_event
),
11424 GetEventTypeCount (specs
),
11425 specs
, NULL
, NULL
);
11430 static const EventTypeSpec specs
[] =
11431 {{kEventClassKeyboard
, kEventRawKeyDown
},
11432 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11433 {kEventClassKeyboard
, kEventRawKeyUp
}};
11435 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11436 (mac_handle_keyboard_event
),
11437 GetEventTypeCount (specs
),
11438 specs
, NULL
, NULL
);
11443 static const EventTypeSpec specs
[] =
11444 {{kEventClassCommand
, kEventCommandProcess
}};
11446 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11447 (mac_handle_command_event
),
11448 GetEventTypeCount (specs
),
11449 specs
, NULL
, NULL
);
11454 static const EventTypeSpec specs
[] =
11455 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11457 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11458 (mac_handle_mouse_event
),
11459 GetEventTypeCount (specs
),
11460 specs
, NULL
, NULL
);
11466 static const EventTypeSpec spec
[] =
11467 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11468 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11469 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11471 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11472 (mac_handle_text_input_event
),
11473 GetEventTypeCount (spec
),
11479 err
= install_menu_target_item_handler ();
11483 err
= install_service_handler ();
11491 mac_handle_dm_notification (event
)
11494 mac_screen_config_changed
= 1;
11497 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11499 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11500 CGDirectDisplayID display
;
11501 CGDisplayChangeSummaryFlags flags
;
11504 mac_screen_config_changed
= 1;
11509 init_dm_notification_handler ()
11513 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11514 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11515 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11518 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11521 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11522 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11524 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11525 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11527 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11528 ProcessSerialNumber psn
;
11530 if (handle_dm_notificationUPP
== NULL
)
11531 handle_dm_notificationUPP
=
11532 NewDMNotificationUPP (mac_handle_dm_notification
);
11534 err
= GetCurrentProcess (&psn
);
11536 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11544 mac_get_screen_info (dpyinfo
)
11545 struct mac_display_info
*dpyinfo
;
11548 /* HasDepth returns true if it is possible to have a 32 bit display,
11549 but this may not be what is actually used. Mac OSX can do better. */
11550 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11551 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11554 CGDisplayCount ndisps
;
11555 CGDirectDisplayID
*displays
;
11557 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11560 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11561 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11565 CGRect bounds
= CGRectZero
;
11567 while (ndisps
-- > 0)
11568 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11569 dpyinfo
->height
= CGRectGetHeight (bounds
);
11570 dpyinfo
->width
= CGRectGetWidth (bounds
);
11574 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11575 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11578 #else /* !MAC_OSX */
11580 GDHandle gdh
= GetMainDevice ();
11581 Rect rect
= (**gdh
).gdRect
;
11583 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11584 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11585 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11588 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11589 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11590 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11592 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11593 dpyinfo
->width
= rect
.right
- rect
.left
;
11595 #endif /* !MAC_OSX */
11601 profiler_exit_proc ()
11603 ProfilerDump ("\pEmacs.prof");
11608 /* These few functions implement Emacs as a normal Mac application
11609 (almost): set up the heap and the Toolbox, handle necessary system
11610 events plus a few simple menu events. They also set up Emacs's
11611 access to functions defined in the rest of this file. Emacs uses
11612 function hooks to perform all its terminal I/O. A complete list of
11613 these functions appear in termhooks.h. For what they do, read the
11614 comments there and see also w32term.c and xterm.c. What's
11615 noticeably missing here is the event loop, which is normally
11616 present in most Mac application. After performing the necessary
11617 Mac initializations, main passes off control to emacs_main
11618 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11619 (defined further below) to read input. This is where
11620 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11627 #if __profile__ /* is the profiler on? */
11628 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11633 /* set creator and type for files created by MSL */
11634 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11638 do_init_managers ();
11642 #ifndef USE_LSB_TAG
11643 do_check_ram_size ();
11646 init_emacs_passwd_dir ();
11650 init_coercion_handler ();
11652 initialize_applescript ();
11654 init_apple_event_handler ();
11656 init_dm_notification_handler ();
11662 /* set up argv array from STR# resource */
11663 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
11667 /* free up AppleScript resources on exit */
11668 atexit (terminate_applescript
);
11670 #if __profile__ /* is the profiler on? */
11671 atexit (profiler_exit_proc
);
11674 /* 3rd param "envp" never used in emacs_main */
11675 (void) emacs_main (argc
, argv
, 0);
11678 /* Never reached - real exit in Fkill_emacs */
11683 #if !TARGET_API_MAC_CARBON
11684 static RgnHandle mouse_region
= NULL
;
11687 mac_wait_next_event (er
, sleep_time
, dequeue
)
11692 static EventRecord er_buf
= {nullEvent
};
11693 UInt32 target_tick
, current_tick
;
11694 EventMask event_mask
;
11696 if (mouse_region
== NULL
)
11697 mouse_region
= NewRgn ();
11699 event_mask
= everyEvent
;
11700 if (!mac_ready_for_apple_events
)
11701 event_mask
-= highLevelEventMask
;
11703 current_tick
= TickCount ();
11704 target_tick
= current_tick
+ sleep_time
;
11706 if (er_buf
.what
== nullEvent
)
11707 while (!WaitNextEvent (event_mask
, &er_buf
,
11708 target_tick
- current_tick
, mouse_region
))
11710 current_tick
= TickCount ();
11711 if (target_tick
<= current_tick
)
11717 er_buf
.what
= nullEvent
;
11720 #endif /* not TARGET_API_MAC_CARBON */
11722 #if TARGET_API_MAC_CARBON
11724 mac_post_mouse_moved_event ()
11726 EventRef event
= NULL
;
11729 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
11730 kEventAttributeNone
, &event
);
11735 GetGlobalMouse (&mouse_pos
);
11736 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
11737 sizeof (Point
), &mouse_pos
);
11741 UInt32 modifiers
= GetCurrentKeyModifiers ();
11743 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
11744 sizeof (UInt32
), &modifiers
);
11747 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
11748 kEventPriorityStandard
);
11750 ReleaseEvent (event
);
11756 /* Emacs calls this whenever it wants to read an input event from the
11759 XTread_socket (sd
, expected
, hold_quit
)
11761 struct input_event
*hold_quit
;
11763 struct input_event inev
;
11765 #if TARGET_API_MAC_CARBON
11767 EventTargetRef toolbox_dispatcher
;
11770 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11772 if (interrupt_input_blocked
)
11774 interrupt_input_pending
= 1;
11778 interrupt_input_pending
= 0;
11781 /* So people can tell when we have read the available input. */
11782 input_signal_count
++;
11786 #if TARGET_API_MAC_CARBON
11787 toolbox_dispatcher
= GetEventDispatcherTarget ();
11791 mac_prepare_for_quickdraw (NULL
),
11793 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
11794 kEventRemoveFromQueue
, &eventRef
))
11795 #else /* !TARGET_API_MAC_CARBON */
11796 while (mac_wait_next_event (&er
, 0, true))
11797 #endif /* !TARGET_API_MAC_CARBON */
11801 unsigned long timestamp
;
11804 inev
.kind
= NO_EVENT
;
11807 #if TARGET_API_MAC_CARBON
11808 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
11810 if (!mac_convert_event_ref (eventRef
, &er
))
11812 #else /* !TARGET_API_MAC_CARBON */
11813 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
11814 #endif /* !TARGET_API_MAC_CARBON */
11821 WindowRef window_ptr
;
11822 ControlPartCode part_code
;
11823 int tool_bar_p
= 0;
11825 #if TARGET_API_MAC_CARBON
11828 /* This is needed to send mouse events like aqua window
11829 buttons to the correct handler. */
11830 read_socket_inev
= &inev
;
11831 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11832 read_socket_inev
= NULL
;
11833 if (err
!= eventNotHandledErr
)
11836 last_mouse_glyph_frame
= 0;
11838 if (dpyinfo
->grabbed
&& last_mouse_frame
11839 && FRAME_LIVE_P (last_mouse_frame
))
11841 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
11842 part_code
= inContent
;
11846 part_code
= FindWindow (er
.where
, &window_ptr
);
11847 if (tip_window
&& window_ptr
== tip_window
)
11849 HideWindow (tip_window
);
11850 part_code
= FindWindow (er
.where
, &window_ptr
);
11854 if (er
.what
!= mouseDown
&&
11855 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
11861 f
= mac_focus_frame (dpyinfo
);
11862 saved_menu_event_location
= er
.where
;
11863 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
11864 XSETFRAME (inev
.frame_or_window
, f
);
11869 #if TARGET_API_MAC_CARBON
11870 FrontNonFloatingWindow ()
11875 || (mac_window_to_frame (window_ptr
)
11876 != dpyinfo
->x_focus_frame
))
11877 SelectWindow (window_ptr
);
11880 ControlPartCode control_part_code
;
11884 ControlKind control_kind
;
11887 f
= mac_window_to_frame (window_ptr
);
11888 /* convert to local coordinates of new window */
11889 mouse_loc
.h
= (er
.where
.h
11891 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
11892 mouse_loc
.v
= (er
.where
.v
11894 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
11895 #if TARGET_API_MAC_CARBON
11896 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
11897 &control_part_code
);
11900 GetControlKind (ch
, &control_kind
);
11903 control_part_code
= FindControl (mouse_loc
, window_ptr
,
11907 #if TARGET_API_MAC_CARBON
11908 inev
.code
= mac_get_mouse_btn (eventRef
);
11909 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
11911 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
11912 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
11914 XSETINT (inev
.x
, mouse_loc
.h
);
11915 XSETINT (inev
.y
, mouse_loc
.v
);
11917 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
11919 #ifndef USE_TOOLKIT_SCROLL_BARS
11920 /* control_part_code becomes kControlNoPart if
11921 a progress indicator is clicked. */
11922 && control_part_code
!= kControlNoPart
11923 #else /* USE_TOOLKIT_SCROLL_BARS */
11925 && control_kind
.kind
== kControlKindScrollBar
11926 #endif /* MAC_OSX */
11927 #endif /* USE_TOOLKIT_SCROLL_BARS */
11930 struct scroll_bar
*bar
;
11932 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11934 bar
= tracked_scroll_bar
;
11935 #ifndef USE_TOOLKIT_SCROLL_BARS
11936 control_part_code
= kControlIndicatorPart
;
11940 bar
= (struct scroll_bar
*) GetControlReference (ch
);
11941 #ifdef USE_TOOLKIT_SCROLL_BARS
11942 /* Make the "Ctrl-Mouse-2 splits window" work
11943 for toolkit scroll bars. */
11944 if (inev
.modifiers
& ctrl_modifier
)
11945 x_scroll_bar_handle_click (bar
, control_part_code
,
11947 else if (er
.what
== mouseDown
)
11948 x_scroll_bar_handle_press (bar
, control_part_code
,
11951 x_scroll_bar_handle_release (bar
, &inev
);
11952 #else /* not USE_TOOLKIT_SCROLL_BARS */
11953 x_scroll_bar_handle_click (bar
, control_part_code
,
11955 if (er
.what
== mouseDown
11956 && control_part_code
== kControlIndicatorPart
)
11957 tracked_scroll_bar
= bar
;
11959 tracked_scroll_bar
= NULL
;
11960 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11964 Lisp_Object window
;
11965 int x
= mouse_loc
.h
;
11966 int y
= mouse_loc
.v
;
11968 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
11969 if (EQ (window
, f
->tool_bar_window
))
11971 if (er
.what
== mouseDown
)
11972 handle_tool_bar_click (f
, x
, y
, 1, 0);
11974 handle_tool_bar_click (f
, x
, y
, 0,
11980 XSETFRAME (inev
.frame_or_window
, f
);
11981 inev
.kind
= MOUSE_CLICK_EVENT
;
11985 if (er
.what
== mouseDown
)
11987 dpyinfo
->grabbed
|= (1 << inev
.code
);
11988 last_mouse_frame
= f
;
11991 last_tool_bar_item
= -1;
11995 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
11996 /* If a button is released though it was not
11997 previously pressed, that would be because
11998 of multi-button emulation. */
11999 dpyinfo
->grabbed
= 0;
12001 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
12004 /* Ignore any mouse motion that happened before
12005 this event; any subsequent mouse-movement Emacs
12006 events should reflect only motion after the
12009 f
->mouse_moved
= 0;
12011 #ifdef USE_TOOLKIT_SCROLL_BARS
12012 if (inev
.kind
== MOUSE_CLICK_EVENT
12013 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12014 && (inev
.modifiers
& ctrl_modifier
)))
12019 inev
.modifiers
|= down_modifier
;
12022 inev
.modifiers
|= up_modifier
;
12029 #if TARGET_API_MAC_CARBON
12031 if (IsWindowPathSelectClick (window_ptr
, &er
))
12033 WindowPathSelect (window_ptr
, NULL
, NULL
);
12036 if (part_code
== inProxyIcon
12037 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12038 != errUserWantsToDragWindow
))
12040 DragWindow (window_ptr
, er
.where
, NULL
);
12041 #else /* not TARGET_API_MAC_CARBON */
12042 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12043 /* Update the frame parameters. */
12045 struct frame
*f
= mac_window_to_frame (window_ptr
);
12047 if (f
&& !f
->async_iconified
)
12048 mac_handle_origin_change (f
);
12050 #endif /* not TARGET_API_MAC_CARBON */
12054 if (TrackGoAway (window_ptr
, er
.where
))
12056 inev
.kind
= DELETE_WINDOW_EVENT
;
12057 XSETFRAME (inev
.frame_or_window
,
12058 mac_window_to_frame (window_ptr
));
12062 /* window resize handling added --ben */
12064 do_grow_window (window_ptr
, &er
);
12067 /* window zoom handling added --ben */
12070 if (TrackBox (window_ptr
, er
.where
, part_code
))
12071 do_zoom_window (window_ptr
, part_code
);
12074 #if USE_MAC_TOOLBAR
12080 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12082 /* This doesn't work on Mac OS X 10.2. */
12084 HIViewClick (ch
, eventRef
);
12087 #endif /* USE_MAC_TOOLBAR */
12095 #if !TARGET_API_MAC_CARBON
12097 do_window_update ((WindowRef
) er
.message
);
12102 switch ((er
.message
>> 24) & 0x000000FF)
12104 case mouseMovedMessage
:
12105 #if !TARGET_API_MAC_CARBON
12106 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12107 er
.where
.h
+ 1, er
.where
.v
+ 1);
12109 previous_help_echo_string
= help_echo_string
;
12110 help_echo_string
= Qnil
;
12112 if (dpyinfo
->grabbed
&& last_mouse_frame
12113 && FRAME_LIVE_P (last_mouse_frame
))
12114 f
= last_mouse_frame
;
12116 f
= dpyinfo
->x_focus_frame
;
12118 if (dpyinfo
->mouse_face_hidden
)
12120 dpyinfo
->mouse_face_hidden
= 0;
12121 clear_mouse_face (dpyinfo
);
12126 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12129 mouse_pos
.h
= (er
.where
.h
12131 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12132 mouse_pos
.v
= (er
.where
.v
12134 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12135 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12136 #ifdef USE_TOOLKIT_SCROLL_BARS
12137 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12139 #else /* not USE_TOOLKIT_SCROLL_BARS */
12140 x_scroll_bar_note_movement (tracked_scroll_bar
,
12142 - XINT (tracked_scroll_bar
->top
),
12143 er
.when
* (1000 / 60));
12144 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12147 /* Generate SELECT_WINDOW_EVENTs when needed. */
12148 if (!NILP (Vmouse_autoselect_window
))
12150 Lisp_Object window
;
12152 window
= window_from_coordinates (f
,
12157 /* Window will be selected only when it is
12158 not selected now and last mouse movement
12159 event was not in it. Minibuffer window
12160 will be selected iff it is active. */
12161 if (WINDOWP (window
)
12162 && !EQ (window
, last_window
)
12163 && !EQ (window
, selected_window
))
12165 inev
.kind
= SELECT_WINDOW_EVENT
;
12166 inev
.frame_or_window
= window
;
12169 last_window
=window
;
12171 if (!note_mouse_movement (f
, &mouse_pos
))
12172 help_echo_string
= previous_help_echo_string
;
12173 #if USE_MAC_TOOLBAR
12175 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12180 /* If the contents of the global variable
12181 help_echo_string has changed, generate a
12183 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12194 WindowRef window_ptr
= (WindowRef
) er
.message
;
12196 if (window_ptr
== tip_window
)
12198 HideWindow (tip_window
);
12202 if (!is_emacs_window (window_ptr
))
12205 f
= mac_window_to_frame (window_ptr
);
12207 if ((er
.modifiers
& activeFlag
) != 0)
12209 /* A window has been activated */
12212 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12214 mouse_loc
.h
= (er
.where
.h
12216 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12217 mouse_loc
.v
= (er
.where
.v
12219 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12220 /* Window-activated event counts as mouse movement,
12221 so update things that depend on mouse position. */
12222 note_mouse_movement (f
, &mouse_loc
);
12226 /* A window has been deactivated */
12227 #ifdef USE_TOOLKIT_SCROLL_BARS
12228 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12230 struct input_event event
;
12232 EVENT_INIT (event
);
12233 event
.kind
= NO_EVENT
;
12234 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12235 if (event
.kind
!= NO_EVENT
)
12237 event
.timestamp
= timestamp
;
12238 kbd_buffer_store_event_hold (&event
, hold_quit
);
12243 dpyinfo
->grabbed
= 0;
12245 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12247 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12249 /* If we move outside the frame, then we're
12250 certainly no longer on any text in the
12252 clear_mouse_face (dpyinfo
);
12253 dpyinfo
->mouse_face_mouse_frame
= 0;
12256 /* Generate a nil HELP_EVENT to cancel a help-echo.
12257 Do it only if there's something to cancel.
12258 Otherwise, the startup message is cleared when the
12259 mouse leaves the frame. */
12260 if (any_help_event_p
)
12271 f
= mac_focus_frame (dpyinfo
);
12272 XSETFRAME (inev
.frame_or_window
, f
);
12274 /* If mouse-highlight is an integer, input clears out mouse
12276 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12277 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12279 clear_mouse_face (dpyinfo
);
12280 dpyinfo
->mouse_face_hidden
= 1;
12282 #if TARGET_API_MAC_CARBON
12285 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12286 (er
.message
& keyCodeMask
) >> 8,
12287 er
.modifiers
, timestamp
, &inev
);
12291 case kHighLevelEvent
:
12292 AEProcessAppleEvent (&er
);
12297 #if TARGET_API_MAC_CARBON
12301 read_socket_inev
= &inev
;
12302 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12303 read_socket_inev
= NULL
;
12308 #if TARGET_API_MAC_CARBON
12309 ReleaseEvent (eventRef
);
12312 if (inev
.kind
!= NO_EVENT
)
12314 inev
.timestamp
= timestamp
;
12315 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12320 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12325 XSETFRAME (frame
, f
);
12331 any_help_event_p
= 1;
12332 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12333 help_echo_object
, help_echo_pos
);
12337 help_echo_string
= Qnil
;
12338 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12345 /* If the focus was just given to an autoraising frame,
12347 /* ??? This ought to be able to handle more than one such frame. */
12348 if (pending_autoraise_frame
)
12350 x_raise_frame (pending_autoraise_frame
);
12351 pending_autoraise_frame
= 0;
12354 if (mac_screen_config_changed
)
12356 mac_get_screen_info (dpyinfo
);
12357 mac_screen_config_changed
= 0;
12360 #if !TARGET_API_MAC_CARBON
12361 /* Check which frames are still visible. We do this here because
12362 there doesn't seem to be any direct notification from the Window
12363 Manager that the visibility of a window has changed (at least,
12364 not in all cases). */
12366 Lisp_Object tail
, frame
;
12368 FOR_EACH_FRAME (tail
, frame
)
12370 struct frame
*f
= XFRAME (frame
);
12372 /* The tooltip has been drawn already. Avoid the
12373 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12374 if (EQ (frame
, tip_frame
))
12377 if (FRAME_MAC_P (f
))
12378 mac_handle_visibility_change (f
);
12389 /* Need to override CodeWarrior's input function so no conversion is
12390 done on newlines Otherwise compiled functions in .elc files will be
12391 read incorrectly. Defined in ...:MSL C:MSL
12392 Common:Source:buffer_io.c. */
12395 __convert_to_newlines (unsigned char * p
, size_t * n
)
12397 #pragma unused(p,n)
12401 __convert_from_newlines (unsigned char * p
, size_t * n
)
12403 #pragma unused(p,n)
12409 make_mac_terminal_frame (struct frame
*f
)
12414 XSETFRAME (frame
, f
);
12416 f
->output_method
= output_mac
;
12417 f
->output_data
.mac
= (struct mac_output
*)
12418 xmalloc (sizeof (struct mac_output
));
12419 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12421 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12423 FRAME_COLS (f
) = 96;
12424 FRAME_LINES (f
) = 4;
12426 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12427 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12429 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12431 f
->output_data
.mac
->cursor_pixel
= 0;
12432 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12433 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12434 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12436 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12437 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12438 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12439 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12440 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12441 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12443 FRAME_FONTSET (f
) = -1;
12444 f
->output_data
.mac
->explicit_parent
= 0;
12447 f
->border_width
= 0;
12449 f
->internal_border_width
= 0;
12454 f
->new_text_cols
= 0;
12455 f
->new_text_lines
= 0;
12457 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12458 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12459 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12463 if (!(FRAME_MAC_WINDOW (f
) =
12464 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12465 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12467 /* so that update events can find this mac_output struct */
12468 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12474 /* Need to be initialized for unshow_buffer in window.c. */
12475 selected_window
= f
->selected_window
;
12477 Fmodify_frame_parameters (frame
,
12478 Fcons (Fcons (Qfont
,
12479 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12480 Fmodify_frame_parameters (frame
,
12481 Fcons (Fcons (Qforeground_color
,
12482 build_string ("black")), Qnil
));
12483 Fmodify_frame_parameters (frame
,
12484 Fcons (Fcons (Qbackground_color
,
12485 build_string ("white")), Qnil
));
12490 /***********************************************************************
12492 ***********************************************************************/
12494 static int mac_initialized
= 0;
12497 mac_make_rdb (xrm_option
)
12498 const char *xrm_option
;
12500 XrmDatabase database
;
12502 database
= xrm_get_preference_database (NULL
);
12504 xrm_merge_string_database (database
, xrm_option
);
12509 struct mac_display_info
*
12510 mac_term_init (display_name
, xrm_option
, resource_name
)
12511 Lisp_Object display_name
;
12513 char *resource_name
;
12515 struct mac_display_info
*dpyinfo
;
12516 struct terminal
*terminal
;
12520 if (!mac_initialized
)
12523 mac_initialized
= 1;
12526 if (x_display_list
)
12527 error ("Sorry, this version can only handle one display");
12529 dpyinfo
= &one_mac_display_info
;
12530 bzero (dpyinfo
, sizeof (*dpyinfo
));
12532 terminal
= mac_create_terminal (dpyinfo
);
12534 /* Set the name of the terminal. */
12535 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
12536 strncpy (terminal
->name
, SDATA (display_name
), SBYTES (display_name
));
12537 terminal
->name
[SBYTES (display_name
)] = 0;
12540 dpyinfo
->mac_id_name
12541 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12542 + SCHARS (Vsystem_name
)
12544 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12545 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12547 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12548 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12551 dpyinfo
->reference_count
= 0;
12552 dpyinfo
->resx
= 72.0;
12553 dpyinfo
->resy
= 72.0;
12555 mac_get_screen_info (dpyinfo
);
12557 dpyinfo
->grabbed
= 0;
12558 dpyinfo
->root_window
= NULL
;
12559 dpyinfo
->image_cache
= make_image_cache ();
12561 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12562 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12563 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12564 dpyinfo
->mouse_face_window
= Qnil
;
12565 dpyinfo
->mouse_face_overlay
= Qnil
;
12566 dpyinfo
->mouse_face_hidden
= 0;
12568 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12570 /* Put this display on the chain. */
12571 dpyinfo
->next
= x_display_list
;
12572 x_display_list
= dpyinfo
;
12574 /* Put it on x_display_name_list. */
12575 x_display_name_list
= Fcons (Fcons (display_name
,
12576 Fcons (Qnil
, dpyinfo
->xrdb
)),
12577 x_display_name_list
);
12578 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12585 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12588 x_delete_display (dpyinfo
)
12589 struct mac_display_info
*dpyinfo
;
12593 /* Discard this display from x_display_name_list and x_display_list.
12594 We can't use Fdelq because that can quit. */
12595 if (! NILP (x_display_name_list
)
12596 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12597 x_display_name_list
= XCDR (x_display_name_list
);
12602 tail
= x_display_name_list
;
12603 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12605 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
12607 XSETCDR (tail
, XCDR (XCDR (tail
)));
12610 tail
= XCDR (tail
);
12614 if (x_display_list
== dpyinfo
)
12615 x_display_list
= dpyinfo
->next
;
12618 struct x_display_info
*tail
;
12620 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12621 if (tail
->next
== dpyinfo
)
12622 tail
->next
= tail
->next
->next
;
12625 /* Free the font names in the font table. */
12626 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12627 if (dpyinfo
->font_table
[i
].name
)
12629 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
12630 xfree (dpyinfo
->font_table
[i
].full_name
);
12631 xfree (dpyinfo
->font_table
[i
].name
);
12634 if (dpyinfo
->font_table
)
12636 if (dpyinfo
->font_table
->font_encoder
)
12637 xfree (dpyinfo
->font_table
->font_encoder
);
12638 xfree (dpyinfo
->font_table
);
12640 if (dpyinfo
->mac_id_name
)
12641 xfree (dpyinfo
->mac_id_name
);
12643 if (x_display_list
== 0)
12645 mac_clear_font_name_table ();
12646 bzero (dpyinfo
, sizeof (*dpyinfo
));
12657 MenuItemIndex menu_index
;
12659 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
12660 &menu
, &menu_index
);
12662 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12663 EnableMenuCommand (NULL
, kHICommandPreferences
);
12664 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
12665 &menu
, &menu_index
);
12668 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12669 InsertMenuItemTextWithCFString (menu
, NULL
,
12670 0, kMenuItemAttrSeparator
, 0);
12671 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
12672 0, 0, kHICommandAbout
);
12674 #else /* !MAC_OSX */
12675 #if TARGET_API_MAC_CARBON
12676 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
12686 static InterfaceTypeList types
= {kUnicodeDocument
};
12688 static InterfaceTypeList types
= {kTextService
};
12691 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
12692 &tsm_document_id
, 0);
12696 /* Set up use of X before we make the first connection. */
12698 extern frame_parm_handler mac_frame_parm_handlers
[];
12700 static struct redisplay_interface x_redisplay_interface
=
12702 mac_frame_parm_handlers
,
12706 x_clear_end_of_line
,
12708 x_after_update_window_line
,
12709 x_update_window_begin
,
12710 x_update_window_end
,
12714 mac_flush_display_optional
,
12716 0, /* flush_display_optional */
12718 x_clear_window_mouse_face
,
12719 x_get_glyph_overhangs
,
12720 x_fix_overlapping_area
,
12721 x_draw_fringe_bitmap
,
12723 mac_define_fringe_bitmap
,
12724 mac_destroy_fringe_bitmap
,
12726 0, /* define_fringe_bitmap */
12727 0, /* destroy_fringe_bitmap */
12729 mac_per_char_metric
,
12731 mac_compute_glyph_string_overhangs
,
12732 x_draw_glyph_string
,
12733 mac_define_frame_cursor
,
12734 mac_clear_frame_area
,
12735 mac_draw_window_cursor
,
12736 mac_draw_vertical_window_border
,
12737 mac_shift_glyphs_for_insert
12740 static struct terminal
*
12741 mac_create_terminal (struct mac_display_info
*dpyinfo
)
12743 struct terminal
*terminal
;
12745 terminal
= create_terminal ();
12747 terminal
->type
= output_mac
;
12748 terminal
->display_info
.mac
= dpyinfo
;
12749 dpyinfo
->terminal
= terminal
;
12751 terminal
->clear_frame_hook
= x_clear_frame
;
12752 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
12753 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
12754 terminal
->ring_bell_hook
= XTring_bell
;
12755 terminal
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
12756 terminal
->set_terminal_modes_hook
= XTset_terminal_modes
;
12757 terminal
->update_begin_hook
= x_update_begin
;
12758 terminal
->update_end_hook
= x_update_end
;
12759 terminal
->set_terminal_window_hook
= XTset_terminal_window
;
12760 terminal
->read_socket_hook
= XTread_socket
;
12761 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
12762 terminal
->mouse_position_hook
= XTmouse_position
;
12763 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
12764 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
12765 /* terminal->fullscreen_hook = XTfullscreen_hook; */
12766 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12767 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12768 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12769 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12770 terminal
->delete_frame_hook
= x_destroy_window
;
12771 /* terminal->delete_terminal_hook = x_delete_terminal; */
12773 terminal
->rif
= &x_redisplay_interface
;
12775 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
12776 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
12777 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
12778 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
12779 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
12783 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
12784 terminal
->char_ins_del_ok
= 1;
12785 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
12786 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
12787 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
12800 last_tool_bar_item
= -1;
12801 any_help_event_p
= 0;
12803 /* Try to use interrupt input; if we can't, then start polling. */
12804 Fset_input_interrupt_mode (Qt
);
12808 #if TARGET_API_MAC_CARBON
12810 install_application_handler ();
12819 init_coercion_handler ();
12821 init_apple_event_handler ();
12823 init_dm_notification_handler ();
12825 if (!inhibit_window_system
)
12827 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
12829 SetFrontProcess (&psn
);
12837 mac_init_fringe ();
12849 staticpro (&x_error_message_string
);
12850 x_error_message_string
= Qnil
;
12853 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
12854 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
12855 Qalt
= intern ("alt"); staticpro (&Qalt
);
12856 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
12857 Qsuper
= intern ("super"); staticpro (&Qsuper
);
12858 Qmodifier_value
= intern ("modifier-value");
12859 staticpro (&Qmodifier_value
);
12861 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
12862 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12863 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12864 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12865 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12867 #if TARGET_API_MAC_CARBON
12868 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
12870 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
12871 staticpro (&Qtoolbar_switch_mode
);
12872 #if USE_MAC_FONT_PANEL
12873 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12874 Qselection
= intern ("selection"); staticpro (&Qselection
);
12877 Qservice
= intern ("service"); staticpro (&Qservice
);
12878 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12879 Qperform
= intern ("perform"); staticpro (&Qperform
);
12882 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12883 Qupdate_active_input_area
= intern ("update-active-input-area");
12884 staticpro (&Qupdate_active_input_area
);
12885 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12886 staticpro (&Qunicode_for_key_event
);
12891 Fprovide (intern ("mac-carbon"), Qnil
);
12894 staticpro (&Qreverse
);
12895 Qreverse
= intern ("reverse");
12897 staticpro (&x_display_name_list
);
12898 x_display_name_list
= Qnil
;
12900 staticpro (&last_mouse_scroll_bar
);
12901 last_mouse_scroll_bar
= Qnil
;
12903 staticpro (&fm_font_family_alist
);
12904 fm_font_family_alist
= Qnil
;
12907 staticpro (&atsu_font_id_hash
);
12908 atsu_font_id_hash
= Qnil
;
12910 staticpro (&fm_style_face_attributes_alist
);
12911 fm_style_face_attributes_alist
= Qnil
;
12915 staticpro (&saved_ts_script_language_on_focus
);
12916 saved_ts_script_language_on_focus
= Qnil
;
12919 /* We don't yet support this, but defining this here avoids whining
12920 from cus-start.el and other places, like "M-x set-variable". */
12921 DEFVAR_BOOL ("x-use-underline-position-properties",
12922 &x_use_underline_position_properties
,
12923 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12924 A value of nil means ignore them. If you encounter fonts with bogus
12925 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12926 to 4.1, set this to nil.
12928 NOTE: Not supported on Mac yet. */);
12929 x_use_underline_position_properties
= 0;
12931 DEFVAR_BOOL ("x-underline-at-descent-line",
12932 &x_underline_at_descent_line
,
12933 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12934 A value of nil means to draw the underline according to the value of the
12935 variable `x-use-underline-position-properties', which is usually at the
12936 baseline level. The default value is nil. */);
12937 x_underline_at_descent_line
= 0;
12939 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12940 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12941 #ifdef USE_TOOLKIT_SCROLL_BARS
12942 Vx_toolkit_scroll_bars
= Qt
;
12944 Vx_toolkit_scroll_bars
= Qnil
;
12947 staticpro (&last_mouse_motion_frame
);
12948 last_mouse_motion_frame
= Qnil
;
12950 /* Variables to configure modifier key assignment. */
12952 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12953 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12954 The value can be `control', `meta', `alt', `hyper', or `super' for the
12955 respective modifier. The default is `control'. */);
12956 Vmac_control_modifier
= Qcontrol
;
12958 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12959 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12960 The value can be `control', `meta', `alt', `hyper', or `super' for the
12961 respective modifier. If the value is nil then the key will act as the
12962 normal Mac control modifier, and the option key can be used to compose
12963 characters depending on the chosen Mac keyboard setting. */);
12964 Vmac_option_modifier
= Qnil
;
12966 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12967 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12968 The value can be `control', `meta', `alt', `hyper', or `super' for the
12969 respective modifier. The default is `meta'. */);
12970 Vmac_command_modifier
= Qmeta
;
12972 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12973 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12974 The value can be `control', `meta', `alt', `hyper', or `super' for the
12975 respective modifier. Note that remapping the function key may lead to
12976 unexpected results for some keys on non-US/GB keyboards. */);
12977 Vmac_function_modifier
= Qnil
;
12979 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12980 &Vmac_emulate_three_button_mouse
,
12981 doc
: /* *Specify a way of three button mouse emulation.
12982 The value can be nil, t, or the symbol `reverse'.
12983 A value of nil means that no emulation should be done and the modifiers
12984 should be placed on the mouse-1 event.
12985 t means that when the option-key is held down while pressing the mouse
12986 button, the click will register as mouse-2 and while the command-key
12987 is held down, the click will register as mouse-3.
12988 The symbol `reverse' means that the option-key will register for
12989 mouse-3 and the command-key will register for mouse-2. */);
12990 Vmac_emulate_three_button_mouse
= Qnil
;
12992 #if TARGET_API_MAC_CARBON
12993 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12994 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12995 Otherwise, the right click will be treated as mouse-2 and the wheel
12996 button will be mouse-3. */);
12997 mac_wheel_button_is_mouse_2
= 1;
12999 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
13000 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
13001 mac_pass_command_to_system
= 1;
13003 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
13004 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13005 mac_pass_control_to_system
= 1;
13009 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
13010 doc
: /* *If non-nil, allow anti-aliasing.
13011 The text will be rendered using Core Graphics text rendering which
13012 may anti-alias the text. */);
13014 mac_use_core_graphics
= 1;
13016 mac_use_core_graphics
= 0;
13019 /* Register an entry for `mac-roman' so that it can be used when
13020 creating the terminal frame on Mac OS 9 before loading
13021 term/mac-win.elc. */
13022 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
13023 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
13024 Each entry should be of the form:
13026 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13028 where CHARSET-NAME is a string used in font names to identify the
13029 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13030 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13031 Vmac_charset_info_alist
=
13032 Fcons (list3 (build_string ("mac-roman"),
13033 make_number (smRoman
), Qnil
), Qnil
);
13036 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13037 doc
: /* Overlay used to display Mac TSM active input area. */);
13038 Vmac_ts_active_input_overlay
= Qnil
;
13040 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13041 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13042 If the value is t, the input script and language are restored to those
13043 used in the last focus frame. If the value is a pair of integers, the
13044 input script and language codes, which are defined in the Script
13045 Manager, are set to its car and cdr parts, respectively. Otherwise,
13046 Emacs doesn't set them and thus follows the system default behavior. */);
13047 Vmac_ts_script_language_on_focus
= Qnil
;
13051 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13052 (do not change this comment) */