1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
83 #include "character.h"
88 /* Non-nil means Emacs uses toolkit scroll bars. */
90 Lisp_Object Vx_toolkit_scroll_bars
;
92 /* If non-zero, the text will be rendered using Core Graphics text
93 rendering which may anti-alias the text. */
94 int mac_use_core_graphics
;
97 /* Non-zero means that a HELP_EVENT has been generated since Emacs
100 static int any_help_event_p
;
102 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
103 static Lisp_Object last_window
;
105 /* Non-zero means make use of UNDERLINE_POSITION font properties.
106 (Not yet supported.) */
107 int x_use_underline_position_properties
;
109 /* Non-zero means to draw the underline at the same place as the descent line. */
111 int x_underline_at_descent_line
;
113 /* This is a chain of structures for all the X displays currently in
116 struct x_display_info
*x_display_list
;
118 /* This is a list of cons cells, each of the form (NAME
119 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
120 x_display_list and in the same order. NAME is the name of the
121 frame. FONT-LIST-CACHE records previous values returned by
122 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
123 equivalent, which is implemented with a Lisp object, for the
126 Lisp_Object x_display_name_list
;
128 /* This is display since Mac does not support multiple ones. */
129 struct mac_display_info one_mac_display_info
;
131 /* Frame being updated by update_frame. This is declared in term.c.
132 This is set by update_begin and looked at by all the XT functions.
133 It is zero while not inside an update. In that case, the XT
134 functions assume that `selected_frame' is the frame to apply to. */
136 extern struct frame
*updating_frame
;
138 /* This is a frame waiting to be auto-raised, within XTread_socket. */
140 struct frame
*pending_autoraise_frame
;
144 Formerly, we used PointerMotionHintMask (in standard_event_mask)
145 so that we would have to call XQueryPointer after each MotionNotify
146 event to ask for another such event. However, this made mouse tracking
147 slow, and there was a bug that made it eventually stop.
149 Simply asking for MotionNotify all the time seems to work better.
151 In order to avoid asking for motion events and then throwing most
152 of them away or busy-polling the server for mouse positions, we ask
153 the server for pointer motion hints. This means that we get only
154 one event per group of mouse movements. "Groups" are delimited by
155 other kinds of events (focus changes and button clicks, for
156 example), or by XQueryPointer calls; when one of these happens, we
157 get another MotionNotify event the next time the mouse moves. This
158 is at least as efficient as getting motion events when mouse
159 tracking is on, and I suspect only negligibly worse when tracking
162 /* Where the mouse was last time we reported a mouse event. */
164 static Rect last_mouse_glyph
;
165 static FRAME_PTR last_mouse_glyph_frame
;
167 /* The scroll bar in which the last X motion event occurred.
169 If the last X motion event occurred in a scroll bar, we set this so
170 XTmouse_position can know whether to report a scroll bar motion or
173 If the last X motion event didn't occur in a scroll bar, we set
174 this to Qnil, to tell XTmouse_position to return an ordinary motion
177 static Lisp_Object last_mouse_scroll_bar
;
179 /* This is a hack. We would really prefer that XTmouse_position would
180 return the time associated with the position it returns, but there
181 doesn't seem to be any way to wrest the time-stamp from the server
182 along with the position query. So, we just keep track of the time
183 of the last movement we received, and return that in hopes that
184 it's somewhat accurate. */
186 static Time last_mouse_movement_time
;
188 struct scroll_bar
*tracked_scroll_bar
= NULL
;
190 /* Incremented by XTread_socket whenever it really tries to read
194 static int volatile input_signal_count
;
196 static int input_signal_count
;
199 extern Lisp_Object Vsystem_name
;
201 extern Lisp_Object Qeql
;
203 /* A mask of extra modifier bits to put into every keyboard char. */
205 extern EMACS_INT extra_keyboard_modifiers
;
207 /* The keysyms to use for the various modifiers. */
209 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
211 extern int inhibit_window_system
;
213 #if __MRC__ && !TARGET_API_MAC_CARBON
214 QDGlobals qd
; /* QuickDraw global information structure. */
217 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
219 struct mac_display_info
*mac_display_info_for_display (Display
*);
220 static void x_update_window_end
P_ ((struct window
*, int, int));
221 int x_catch_errors
P_ ((Display
*));
222 void x_uncatch_errors
P_ ((Display
*, int));
223 void x_lower_frame
P_ ((struct frame
*));
224 void x_scroll_bar_clear
P_ ((struct frame
*));
225 int x_had_errors_p
P_ ((Display
*));
226 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
227 void x_raise_frame
P_ ((struct frame
*));
228 void x_set_window_size
P_ ((struct frame
*, int, int, int));
229 void x_wm_set_window_state
P_ ((struct frame
*, int));
230 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
231 void mac_initialize
P_ ((void));
232 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
233 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
234 static void x_update_end
P_ ((struct frame
*));
235 static void XTframe_up_to_date
P_ ((struct frame
*));
236 static void XTset_terminal_modes
P_ ((void));
237 static void XTreset_terminal_modes
P_ ((void));
238 static void x_clear_frame
P_ ((void));
239 static void frame_highlight
P_ ((struct frame
*));
240 static void frame_unhighlight
P_ ((struct frame
*));
241 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
242 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
243 struct frame
*, struct input_event
*));
244 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
246 struct input_event
*));
247 static void XTframe_rehighlight
P_ ((struct frame
*));
248 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
249 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
250 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
251 enum text_cursor_kinds
));
253 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
254 static void x_flush
P_ ((struct frame
*f
));
255 static void x_update_begin
P_ ((struct frame
*));
256 static void x_update_window_begin
P_ ((struct window
*));
257 static void x_after_update_window_line
P_ ((struct glyph_row
*));
258 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
259 enum scroll_bar_part
*,
260 Lisp_Object
*, Lisp_Object
*,
263 static int is_emacs_window
P_ ((WindowRef
));
264 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
265 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
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 ()
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 ()
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
*,
2416 struct charset
*, int *));
2420 pcm_init (pcm
, count
)
2424 bzero (pcm
, sizeof (XCharStruct
) * count
);
2425 while (--count
>= 0)
2427 pcm
->descent
= PCM_INVALID
;
2432 static enum pcm_status
2433 pcm_get_status (pcm
)
2434 const XCharStruct
*pcm
;
2436 int height
= pcm
->ascent
+ pcm
->descent
;
2438 /* Negative height means some special status. */
2439 return height
>= 0 ? PCM_VALID
: height
;
2442 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2443 is not contained in the font. */
2445 static INLINE XCharStruct
*
2446 x_per_char_metric (font
, char2b
)
2450 /* The result metric information. */
2451 XCharStruct
*pcm
= NULL
;
2453 xassert (font
&& char2b
);
2456 if (font
->mac_style
)
2458 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2462 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2463 pcm_init (*row
, 0x100);
2465 pcm
= *row
+ char2b
->byte2
;
2466 if (pcm_get_status (pcm
) != PCM_VALID
)
2469 mac_query_char_extents (font
->mac_style
,
2470 (char2b
->byte1
<< 8) + char2b
->byte2
,
2471 NULL
, NULL
, pcm
, NULL
);
2478 if (font
->bounds
.per_char
!= NULL
)
2480 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2482 /* min_char_or_byte2 specifies the linear character index
2483 corresponding to the first element of the per_char array,
2484 max_char_or_byte2 is the index of the last character. A
2485 character with non-zero CHAR2B->byte1 is not in the font.
2486 A character with byte2 less than min_char_or_byte2 or
2487 greater max_char_or_byte2 is not in the font. */
2488 if (char2b
->byte1
== 0
2489 && char2b
->byte2
>= font
->min_char_or_byte2
2490 && char2b
->byte2
<= font
->max_char_or_byte2
)
2491 pcm
= font
->bounds
.per_char
2492 + (char2b
->byte2
- font
->min_char_or_byte2
);
2496 /* If either min_byte1 or max_byte1 are nonzero, both
2497 min_char_or_byte2 and max_char_or_byte2 are less than
2498 256, and the 2-byte character index values corresponding
2499 to the per_char array element N (counting from 0) are:
2501 byte1 = N/D + min_byte1
2502 byte2 = N\D + min_char_or_byte2
2506 D = max_char_or_byte2 - min_char_or_byte2 + 1
2507 / = integer division
2508 \ = integer modulus */
2509 if (char2b
->byte1
>= font
->min_byte1
2510 && char2b
->byte1
<= font
->max_byte1
2511 && char2b
->byte2
>= font
->min_char_or_byte2
2512 && char2b
->byte2
<= font
->max_char_or_byte2
)
2514 pcm
= (font
->bounds
.per_char
2515 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2516 * (char2b
->byte1
- font
->min_byte1
))
2517 + (char2b
->byte2
- font
->min_char_or_byte2
));
2523 /* If the per_char pointer is null, all glyphs between the first
2524 and last character indexes inclusive have the same
2525 information, as given by both min_bounds and max_bounds. */
2526 if (char2b
->byte2
>= font
->min_char_or_byte2
2527 && char2b
->byte2
<= font
->max_char_or_byte2
)
2528 pcm
= &font
->max_bounds
;
2534 return ((pcm
== NULL
2536 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2537 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2546 static XCharStruct
*
2547 mac_per_char_metric (font
, char2b
, font_type
)
2552 return x_per_char_metric (font
, char2b
);
2556 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2557 the two-byte form of C. Encoding is returned in *CHAR2B. */
2560 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
2563 struct font_info
*font_info
;
2564 struct charset
*charset
;
2567 XFontStruct
*font
= font_info
->font
;
2569 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2570 This may be either a program in a special encoder language or a
2572 if (font_info
->font_encoder
)
2574 /* It's a program. */
2575 struct ccl_program
*ccl
= font_info
->font_encoder
;
2577 check_ccl_update (ccl
);
2578 if (CHARSET_DIMENSION (charset
) == 1)
2580 ccl
->reg
[0] = CHARSET_ID (charset
);
2581 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
2586 ccl
->reg
[0] = CHARSET_ID (charset
);
2587 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
2588 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
2591 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
2593 /* We assume that MSBs are appropriately set/reset by CCL
2595 if (font
->max_byte1
== 0) /* 1-byte font */
2596 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
2598 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
2600 else if (font_info
->encoding_type
)
2602 /* Fixed encoding scheme. See fontset.h for the meaning of the
2603 encoding numbers. */
2604 unsigned char enc
= font_info
->encoding_type
;
2606 if ((enc
== 1 || enc
== 2)
2607 && CHARSET_DIMENSION (charset
) == 2)
2608 char2b
->byte1
|= 0x80;
2610 if (enc
== 1 || enc
== 3)
2611 char2b
->byte2
|= 0x80;
2615 int code
= (char2b
->byte1
<< 8) | char2b
->byte2
;
2618 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
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
, -1, Qnil
);
2740 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
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
; CONSP (tail
); tail
= XCDR (tail
))
3097 if (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. */
4052 f
= SELECTED_FRAME ();
4054 /* Clearing the frame will erase any cursor, so mark them all as no
4056 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4057 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4058 output_cursor
.x
= -1;
4060 /* We don't set the output cursor here because there will always
4061 follow an explicit cursor_to. */
4063 mac_clear_window (f
);
4065 /* We have to clear the scroll bars, too. If we have changed
4066 colors or something like that, then they should be notified. */
4067 x_scroll_bar_clear (f
);
4069 XFlush (FRAME_MAC_DISPLAY (f
));
4075 /* Invert the middle quarter of the frame for .15 sec. */
4077 /* We use the select system call to do the waiting, so we have to make
4078 sure it's available. If it isn't, we just won't do visual bells. */
4080 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4083 /* Subtract the `struct timeval' values X and Y, storing the result in
4084 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4087 timeval_subtract (result
, x
, y
)
4088 struct timeval
*result
, x
, y
;
4090 /* Perform the carry for the later subtraction by updating y. This
4091 is safer because on some systems the tv_sec member is unsigned. */
4092 if (x
.tv_usec
< y
.tv_usec
)
4094 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4095 y
.tv_usec
-= 1000000 * nsec
;
4099 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4101 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4102 y
.tv_usec
+= 1000000 * nsec
;
4106 /* Compute the time remaining to wait. tv_usec is certainly
4108 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4109 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4111 /* Return indication of whether the result should be considered
4113 return x
.tv_sec
< y
.tv_sec
;
4120 /* Get the height not including a menu bar widget. */
4121 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4122 /* Height of each line to flash. */
4123 int flash_height
= FRAME_LINE_HEIGHT (f
);
4124 /* These will be the left and right margins of the rectangles. */
4125 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4126 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4130 /* Don't flash the area between a scroll bar and the frame
4131 edge it is next to. */
4132 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4134 case vertical_scroll_bar_left
:
4135 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4138 case vertical_scroll_bar_right
:
4139 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4146 width
= flash_right
- flash_left
;
4150 /* If window is tall, flash top and bottom line. */
4151 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4153 mac_invert_rectangle (f
, flash_left
,
4154 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4155 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4156 width
, flash_height
);
4157 mac_invert_rectangle (f
, flash_left
,
4158 (height
- flash_height
4159 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4160 width
, flash_height
);
4163 /* If it is short, flash it all. */
4164 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4165 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4170 struct timeval wakeup
;
4172 EMACS_GET_TIME (wakeup
);
4174 /* Compute time to wait until, propagating carry from usecs. */
4175 wakeup
.tv_usec
+= 150000;
4176 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4177 wakeup
.tv_usec
%= 1000000;
4179 /* Keep waiting until past the time wakeup or any input gets
4181 while (! detect_input_pending ())
4183 struct timeval current
;
4184 struct timeval timeout
;
4186 EMACS_GET_TIME (current
);
4188 /* Break if result would be negative. */
4189 if (timeval_subtract (¤t
, wakeup
, current
))
4192 /* How long `select' should wait. */
4194 timeout
.tv_usec
= 10000;
4196 /* Try to wait that long--but we might wake up sooner. */
4197 select (0, NULL
, NULL
, NULL
, &timeout
);
4201 /* If window is tall, flash top and bottom line. */
4202 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4204 mac_invert_rectangle (f
, flash_left
,
4205 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4206 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4207 width
, flash_height
);
4208 mac_invert_rectangle (f
, flash_left
,
4209 (height
- flash_height
4210 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4211 width
, flash_height
);
4214 /* If it is short, flash it all. */
4215 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4216 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4223 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4226 /* Make audible bell. */
4231 struct frame
*f
= SELECTED_FRAME ();
4233 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4241 XFlush (FRAME_MAC_DISPLAY (f
));
4247 /* Specify how many text lines, from the top of the window,
4248 should be affected by insert-lines and delete-lines operations.
4249 This, and those operations, are used only within an update
4250 that is bounded by calls to x_update_begin and x_update_end. */
4253 XTset_terminal_window (n
)
4256 /* This function intentionally left blank. */
4261 /***********************************************************************
4263 ***********************************************************************/
4265 /* Perform an insert-lines or delete-lines operation, inserting N
4266 lines or deleting -N lines at vertical position VPOS. */
4269 x_ins_del_lines (vpos
, n
)
4276 /* Scroll part of the display as described by RUN. */
4279 x_scroll_run (w
, run
)
4283 struct frame
*f
= XFRAME (w
->frame
);
4284 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4286 /* Get frame-relative bounding box of the text display area of W,
4287 without mode lines. Include in this box the left and right
4289 window_box (w
, -1, &x
, &y
, &width
, &height
);
4291 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4292 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4293 bottom_y
= y
+ height
;
4297 /* Scrolling up. Make sure we don't copy part of the mode
4298 line at the bottom. */
4299 if (from_y
+ run
->height
> bottom_y
)
4300 height
= bottom_y
- from_y
;
4302 height
= run
->height
;
4306 /* Scolling down. Make sure we don't copy over the mode line.
4308 if (to_y
+ run
->height
> bottom_y
)
4309 height
= bottom_y
- to_y
;
4311 height
= run
->height
;
4316 /* Cursor off. Will be switched on again in x_update_window_end. */
4320 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4330 /***********************************************************************
4332 ***********************************************************************/
4340 ControlRef root_control
;
4343 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4345 ActivateControl (root_control
);
4347 x_update_cursor (f
, 1);
4351 frame_unhighlight (f
)
4355 ControlRef root_control
;
4358 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4360 DeactivateControl (root_control
);
4362 x_update_cursor (f
, 1);
4365 /* The focus has changed. Update the frames as necessary to reflect
4366 the new situation. Note that we can't change the selected frame
4367 here, because the Lisp code we are interrupting might become confused.
4368 Each event gets marked with the frame in which it occurred, so the
4369 Lisp code can tell when the switch took place by examining the events. */
4372 x_new_focus_frame (dpyinfo
, frame
)
4373 struct x_display_info
*dpyinfo
;
4374 struct frame
*frame
;
4376 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4378 if (frame
!= dpyinfo
->x_focus_frame
)
4380 /* Set this before calling other routines, so that they see
4381 the correct value of x_focus_frame. */
4382 dpyinfo
->x_focus_frame
= frame
;
4384 if (old_focus
&& old_focus
->auto_lower
)
4385 x_lower_frame (old_focus
);
4388 selected_frame
= frame
;
4389 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4391 Fselect_window (selected_frame
->selected_window
, Qnil
);
4392 choose_minibuf_frame ();
4395 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4396 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4398 pending_autoraise_frame
= 0;
4400 #if USE_MAC_FONT_PANEL
4402 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4406 x_frame_rehighlight (dpyinfo
);
4409 /* Handle FocusIn and FocusOut state changes for FRAME.
4410 If FRAME has focus and there exists more than one frame, puts
4411 a FOCUS_IN_EVENT into *BUFP. */
4414 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4416 struct mac_display_info
*dpyinfo
;
4417 struct frame
*frame
;
4418 struct input_event
*bufp
;
4420 if (type
== activeFlag
)
4422 if (dpyinfo
->x_focus_event_frame
!= frame
)
4424 x_new_focus_frame (dpyinfo
, frame
);
4425 dpyinfo
->x_focus_event_frame
= frame
;
4427 /* Don't stop displaying the initial startup message
4428 for a switch-frame event we don't need. */
4429 if (NILP (Vterminal_frame
)
4430 && CONSP (Vframe_list
)
4431 && !NILP (XCDR (Vframe_list
)))
4433 bufp
->kind
= FOCUS_IN_EVENT
;
4434 XSETFRAME (bufp
->frame_or_window
, frame
);
4440 if (dpyinfo
->x_focus_event_frame
== frame
)
4442 dpyinfo
->x_focus_event_frame
= 0;
4443 x_new_focus_frame (dpyinfo
, 0);
4448 /* The focus may have changed. Figure out if it is a real focus change,
4449 by checking both FocusIn/Out and Enter/LeaveNotify events.
4451 Returns FOCUS_IN_EVENT event in *BUFP. */
4454 x_detect_focus_change (dpyinfo
, event
, bufp
)
4455 struct mac_display_info
*dpyinfo
;
4456 const EventRecord
*event
;
4457 struct input_event
*bufp
;
4459 struct frame
*frame
;
4461 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4465 /* On Mac, this is only called from focus events, so no switch needed. */
4466 mac_focus_changed ((event
->modifiers
& activeFlag
),
4467 dpyinfo
, frame
, bufp
);
4471 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4474 x_mouse_leave (dpyinfo
)
4475 struct x_display_info
*dpyinfo
;
4477 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4480 /* The focus has changed, or we have redirected a frame's focus to
4481 another frame (this happens when a frame uses a surrogate
4482 mini-buffer frame). Shift the highlight as appropriate.
4484 The FRAME argument doesn't necessarily have anything to do with which
4485 frame is being highlighted or un-highlighted; we only use it to find
4486 the appropriate X display info. */
4489 XTframe_rehighlight (frame
)
4490 struct frame
*frame
;
4492 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4496 x_frame_rehighlight (dpyinfo
)
4497 struct x_display_info
*dpyinfo
;
4499 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4501 if (dpyinfo
->x_focus_frame
)
4503 dpyinfo
->x_highlight_frame
4504 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4505 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4506 : dpyinfo
->x_focus_frame
);
4507 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4509 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4510 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4514 dpyinfo
->x_highlight_frame
= 0;
4516 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4519 frame_unhighlight (old_highlight
);
4520 if (dpyinfo
->x_highlight_frame
)
4521 frame_highlight (dpyinfo
->x_highlight_frame
);
4527 /* Convert a keysym to its name. */
4530 x_get_keysym_name (keysym
)
4537 value
= XKeysymToString (keysym
);
4548 /* Function to report a mouse movement to the mainstream Emacs code.
4549 The input handler calls this.
4551 We have received a mouse movement event, which is given in *event.
4552 If the mouse is over a different glyph than it was last time, tell
4553 the mainstream emacs code by setting mouse_moved. If not, ask for
4554 another motion event, so we can check again the next time it moves. */
4556 static Point last_mouse_motion_position
;
4557 static Lisp_Object last_mouse_motion_frame
;
4560 note_mouse_movement (frame
, pos
)
4564 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4565 #if TARGET_API_MAC_CARBON
4569 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4570 last_mouse_motion_position
= *pos
;
4571 XSETFRAME (last_mouse_motion_frame
, frame
);
4573 if (frame
== dpyinfo
->mouse_face_mouse_frame
4574 #if TARGET_API_MAC_CARBON
4575 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4577 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4581 /* This case corresponds to LeaveNotify in X11. If we move
4582 outside the frame, then we're certainly no longer on any text
4584 clear_mouse_face (dpyinfo
);
4585 dpyinfo
->mouse_face_mouse_frame
= 0;
4586 if (!dpyinfo
->grabbed
)
4587 rif
->define_frame_cursor (frame
,
4588 frame
->output_data
.mac
->nontext_cursor
);
4591 /* Has the mouse moved off the glyph it was on at the last sighting? */
4592 if (frame
!= last_mouse_glyph_frame
4593 || !PtInRect (*pos
, &last_mouse_glyph
))
4595 frame
->mouse_moved
= 1;
4596 last_mouse_scroll_bar
= Qnil
;
4597 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4598 /* Remember which glyph we're now on. */
4599 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4600 last_mouse_glyph_frame
= frame
;
4608 /************************************************************************
4610 ************************************************************************/
4612 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4615 redo_mouse_highlight ()
4617 if (!NILP (last_mouse_motion_frame
)
4618 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4619 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4620 last_mouse_motion_position
.h
,
4621 last_mouse_motion_position
.v
);
4625 static struct frame
*
4626 mac_focus_frame (dpyinfo
)
4627 struct mac_display_info
*dpyinfo
;
4629 if (dpyinfo
->x_focus_frame
)
4630 return dpyinfo
->x_focus_frame
;
4632 /* Mac version may get events, such as a menu bar click, even when
4633 all the frames are invisible. In this case, we regard the
4634 event came to the selected frame. */
4635 return SELECTED_FRAME ();
4639 /* Return the current position of the mouse.
4640 *FP should be a frame which indicates which display to ask about.
4642 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4643 and *PART to the frame, window, and scroll bar part that the mouse
4644 is over. Set *X and *Y to the portion and whole of the mouse's
4645 position on the scroll bar.
4647 If the mouse movement started elsewhere, set *FP to the frame the
4648 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4651 Set *TIME to the server time-stamp for the time at which the mouse
4652 was at this position.
4654 Don't store anything if we don't have a valid set of values to report.
4656 This clears the mouse_moved flag, so we can wait for the next mouse
4660 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4663 Lisp_Object
*bar_window
;
4664 enum scroll_bar_part
*part
;
4666 unsigned long *time
;
4672 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4673 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4676 Lisp_Object frame
, tail
;
4678 /* Clear the mouse-moved flag for every frame on this display. */
4679 FOR_EACH_FRAME (tail
, frame
)
4680 XFRAME (frame
)->mouse_moved
= 0;
4682 last_mouse_scroll_bar
= Qnil
;
4684 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4685 && FRAME_LIVE_P (last_mouse_frame
))
4686 f1
= last_mouse_frame
;
4688 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4692 /* Ok, we found a frame. Store all the values.
4693 last_mouse_glyph is a rectangle used to reduce the
4694 generation of mouse events. To not miss any motion
4695 events, we must divide the frame into rectangles of the
4696 size of the smallest character that could be displayed
4697 on it, i.e. into the same rectangles that matrices on
4698 the frame are divided into. */
4701 #if TARGET_API_MAC_CARBON
4702 GetGlobalMouse (&mouse_pos
);
4703 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4704 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4706 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4707 GetMouse (&mouse_pos
);
4709 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4711 last_mouse_glyph_frame
= f1
;
4716 XSETINT (*x
, mouse_pos
.h
);
4717 XSETINT (*y
, mouse_pos
.v
);
4718 *time
= last_mouse_movement_time
;
4726 /************************************************************************
4728 ************************************************************************/
4730 #ifdef USE_TOOLKIT_SCROLL_BARS
4732 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4733 static OSStatus install_scroll_bar_timer
P_ ((void));
4734 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4735 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4736 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4737 struct input_event
*));
4738 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4740 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4741 ControlPartCode
, Point
,
4742 struct input_event
*));
4743 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4744 struct input_event
*));
4745 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4746 Point
, struct input_event
*));
4747 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4750 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4752 static int last_scroll_bar_part
;
4754 static EventLoopTimerRef scroll_bar_timer
;
4756 static int scroll_bar_timer_event_posted_p
;
4758 #define SCROLL_BAR_FIRST_DELAY 0.5
4759 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4762 scroll_bar_timer_callback (timer
, data
)
4763 EventLoopTimerRef timer
;
4768 err
= mac_post_mouse_moved_event ();
4770 scroll_bar_timer_event_posted_p
= 1;
4774 install_scroll_bar_timer ()
4776 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4778 if (scroll_bar_timer_callbackUPP
== NULL
)
4779 scroll_bar_timer_callbackUPP
=
4780 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4782 if (scroll_bar_timer
== NULL
)
4783 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4784 kEventDurationForever as delays. */
4786 InstallEventLoopTimer (GetCurrentEventLoop (),
4787 kEventDurationForever
, kEventDurationForever
,
4788 scroll_bar_timer_callbackUPP
, NULL
,
4793 set_scroll_bar_timer (delay
)
4794 EventTimerInterval delay
;
4796 if (scroll_bar_timer
== NULL
)
4797 install_scroll_bar_timer ();
4799 scroll_bar_timer_event_posted_p
= 0;
4801 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4805 control_part_code_to_scroll_bar_part (part_code
)
4806 ControlPartCode part_code
;
4810 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4811 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4812 case kControlPageUpPart
: return scroll_bar_above_handle
;
4813 case kControlPageDownPart
: return scroll_bar_below_handle
;
4814 case kControlIndicatorPart
: return scroll_bar_handle
;
4821 construct_scroll_bar_click (bar
, part
, bufp
)
4822 struct scroll_bar
*bar
;
4824 struct input_event
*bufp
;
4826 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4827 bufp
->frame_or_window
= bar
->window
;
4831 XSETINT (bufp
->x
, 0);
4832 XSETINT (bufp
->y
, 0);
4833 bufp
->modifiers
= 0;
4837 get_control_part_bounds (ch
, part_code
, rect
)
4839 ControlPartCode part_code
;
4842 RgnHandle region
= NewRgn ();
4845 err
= GetControlRegion (ch
, part_code
, region
);
4847 GetRegionBounds (region
, rect
);
4848 DisposeRgn (region
);
4854 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4855 struct scroll_bar
*bar
;
4856 ControlPartCode part_code
;
4858 struct input_event
*bufp
;
4860 int part
= control_part_code_to_scroll_bar_part (part_code
);
4865 if (part
!= scroll_bar_handle
)
4867 construct_scroll_bar_click (bar
, part
, bufp
);
4868 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4869 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4870 bar
->dragging
= Qnil
;
4876 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4877 kControlIndicatorPart
, &r
);
4878 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4881 last_scroll_bar_part
= part
;
4882 tracked_scroll_bar
= bar
;
4886 x_scroll_bar_handle_release (bar
, bufp
)
4887 struct scroll_bar
*bar
;
4888 struct input_event
*bufp
;
4890 if (last_scroll_bar_part
!= scroll_bar_handle
4891 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4892 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4894 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4895 set_scroll_bar_timer (kEventDurationForever
);
4897 last_scroll_bar_part
= -1;
4898 bar
->dragging
= Qnil
;
4899 tracked_scroll_bar
= NULL
;
4903 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4905 struct scroll_bar
*bar
;
4907 struct input_event
*bufp
;
4909 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4911 if (last_scroll_bar_part
== scroll_bar_handle
)
4916 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4917 kControlIndicatorPart
, &r
);
4919 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4920 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4922 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4923 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4927 if (top
> top_range
)
4930 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4931 XSETINT (bufp
->x
, top
);
4932 XSETINT (bufp
->y
, top_range
);
4936 ControlPartCode part_code
;
4937 int unhilite_p
= 0, part
;
4939 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4943 part
= control_part_code_to_scroll_bar_part (part_code
);
4945 switch (last_scroll_bar_part
)
4947 case scroll_bar_above_handle
:
4948 case scroll_bar_below_handle
:
4949 if (part
!= scroll_bar_above_handle
4950 && part
!= scroll_bar_below_handle
)
4954 case scroll_bar_up_arrow
:
4955 case scroll_bar_down_arrow
:
4956 if (part
!= scroll_bar_up_arrow
4957 && part
!= scroll_bar_down_arrow
)
4964 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4965 else if (part
!= last_scroll_bar_part
4966 || scroll_bar_timer_event_posted_p
)
4968 construct_scroll_bar_click (bar
, part
, bufp
);
4969 last_scroll_bar_part
= part
;
4970 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4971 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4976 /* Set the thumb size and position of scroll bar BAR. We are currently
4977 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4980 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4981 struct scroll_bar
*bar
;
4982 int portion
, position
, whole
;
4984 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4985 int value
, viewsize
, maximum
;
4987 if (XINT (bar
->track_height
) == 0)
4990 if (whole
<= portion
)
4991 value
= 0, viewsize
= 1, maximum
= 0;
4996 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4997 scale
= (float) maximum
/ (whole
- portion
);
4998 value
= position
* scale
+ 0.5f
;
4999 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
5004 if (GetControlViewSize (ch
) != viewsize
5005 || GetControl32BitValue (ch
) != value
5006 || GetControl32BitMaximum (ch
) != maximum
)
5008 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5009 SetControlVisibility (ch
, false, false);
5011 SetControl32BitMaximum (ch
, maximum
);
5012 SetControl32BitValue (ch
, value
);
5013 SetControlViewSize (ch
, viewsize
);
5015 SetControlVisibility (ch
, true, true);
5021 #endif /* USE_TOOLKIT_SCROLL_BARS */
5025 /************************************************************************
5026 Scroll bars, general
5027 ************************************************************************/
5029 /* Create a scroll bar and return the scroll bar vector for it. W is
5030 the Emacs window on which to create the scroll bar. TOP, LEFT,
5031 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5034 static struct scroll_bar
*
5035 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5037 int top
, left
, width
, height
, disp_top
, disp_height
;
5039 struct frame
*f
= XFRAME (w
->frame
);
5040 struct scroll_bar
*bar
5041 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5049 r
.right
= left
+ width
;
5050 r
.bottom
= disp_top
+ disp_height
;
5053 mac_prepare_for_quickdraw (f
);
5055 #if TARGET_API_MAC_CARBON
5056 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5057 #ifdef USE_TOOLKIT_SCROLL_BARS
5060 width
< disp_height
,
5062 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5064 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5065 0, 0, 0, scrollBarProc
, (long) bar
);
5067 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5069 XSETWINDOW (bar
->window
, w
);
5070 XSETINT (bar
->top
, top
);
5071 XSETINT (bar
->left
, left
);
5072 XSETINT (bar
->width
, width
);
5073 XSETINT (bar
->height
, height
);
5074 XSETINT (bar
->start
, 0);
5075 XSETINT (bar
->end
, 0);
5076 bar
->dragging
= Qnil
;
5078 bar
->fringe_extended_p
= Qnil
;
5080 #ifdef USE_TOOLKIT_SCROLL_BARS
5081 bar
->track_top
= Qnil
;
5082 bar
->track_height
= Qnil
;
5083 bar
->min_handle
= Qnil
;
5086 /* Add bar to its frame's list of scroll bars. */
5087 bar
->next
= FRAME_SCROLL_BARS (f
);
5089 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5090 if (!NILP (bar
->next
))
5091 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5098 /* Draw BAR's handle in the proper position.
5100 If the handle is already drawn from START to END, don't bother
5101 redrawing it, unless REBUILD is non-zero; in that case, always
5102 redraw it. (REBUILD is handy for drawing the handle after expose
5105 Normally, we want to constrain the start and end of the handle to
5106 fit inside its rectangle, but if the user is dragging the scroll
5107 bar handle, we want to let them drag it down all the way, so that
5108 the bar's top is as far down as it goes; otherwise, there's no way
5109 to move to the very end of the buffer. */
5111 #ifndef USE_TOOLKIT_SCROLL_BARS
5114 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5115 struct scroll_bar
*bar
;
5119 int dragging
= ! NILP (bar
->dragging
);
5120 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5121 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5122 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5123 int length
= end
- start
;
5125 /* If the display is already accurate, do nothing. */
5127 && start
== XINT (bar
->start
)
5128 && end
== XINT (bar
->end
))
5133 /* Make sure the values are reasonable, and try to preserve the
5134 distance between start and end. */
5137 else if (start
> top_range
)
5139 end
= start
+ length
;
5143 else if (end
> top_range
&& ! dragging
)
5146 /* Store the adjusted setting in the scroll bar. */
5147 XSETINT (bar
->start
, start
);
5148 XSETINT (bar
->end
, end
);
5150 /* Clip the end position, just for display. */
5151 if (end
> top_range
)
5154 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5155 top positions, to make sure the handle is always at least that
5156 many pixels tall. */
5157 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5159 SetControlMinimum (ch
, 0);
5160 /* Don't inadvertently activate deactivated scroll bars */
5161 if (GetControlMaximum (ch
) != -1)
5162 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5164 SetControlValue (ch
, start
);
5165 #if TARGET_API_MAC_CARBON
5166 SetControlViewSize (ch
, end
- start
);
5172 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5174 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5178 x_scroll_bar_remove (bar
)
5179 struct scroll_bar
*bar
;
5181 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5186 mac_prepare_for_quickdraw (f
);
5188 /* Destroy the Mac scroll bar control */
5189 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5191 /* Disassociate this scroll bar from its window. */
5192 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5198 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5199 that we are displaying PORTION characters out of a total of WHOLE
5200 characters, starting at POSITION. If WINDOW has no scroll bar,
5204 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5206 int portion
, whole
, position
;
5208 struct frame
*f
= XFRAME (w
->frame
);
5209 struct scroll_bar
*bar
;
5210 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5211 int window_y
, window_height
;
5213 int fringe_extended_p
;
5216 /* Get window dimensions. */
5217 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5219 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5220 height
= window_height
;
5222 /* Compute the left edge of the scroll bar area. */
5223 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5225 /* Compute the width of the scroll bar which might be less than
5226 the width of the area reserved for the scroll bar. */
5227 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5228 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5232 /* Compute the left edge of the scroll bar. */
5233 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5234 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5236 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5238 /* Adjustments according to Inside Macintosh to make it look nice */
5240 disp_height
= height
;
5247 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5253 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5258 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5259 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5260 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5261 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5262 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5264 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5265 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5266 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5267 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5270 /* Does the scroll bar exist yet? */
5271 if (NILP (w
->vertical_scroll_bar
))
5275 if (fringe_extended_p
)
5276 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5279 mac_clear_area (f
, left
, top
, width
, height
);
5281 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5283 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5287 /* It may just need to be moved and resized. */
5290 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5291 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5295 /* If already correctly positioned, do nothing. */
5296 if (!(XINT (bar
->left
) == sb_left
5297 && XINT (bar
->top
) == top
5298 && XINT (bar
->width
) == sb_width
5299 && XINT (bar
->height
) == height
5301 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5305 /* Since toolkit scroll bars are smaller than the space reserved
5306 for them on the frame, we have to clear "under" them. */
5308 if (fringe_extended_p
)
5309 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5312 mac_clear_area (f
, left
, top
, width
, height
);
5315 mac_prepare_for_quickdraw (f
);
5318 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5319 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5321 #ifndef USE_TOOLKIT_SCROLL_BARS
5322 if (sb_width
< disp_height
)
5326 /* Remember new settings. */
5327 XSETINT (bar
->left
, sb_left
);
5328 XSETINT (bar
->top
, top
);
5329 XSETINT (bar
->width
, sb_width
);
5330 XSETINT (bar
->height
, height
);
5331 #ifdef USE_TOOLKIT_SCROLL_BARS
5332 bar
->track_top
= Qnil
;
5333 bar
->track_height
= Qnil
;
5334 bar
->min_handle
= Qnil
;
5342 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5345 #ifdef USE_TOOLKIT_SCROLL_BARS
5346 if (NILP (bar
->track_top
))
5348 if (sb_width
>= disp_height
5350 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5354 XSETINT (bar
->track_top
, 0);
5355 XSETINT (bar
->track_height
, 0);
5356 XSETINT (bar
->min_handle
, 0);
5360 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5365 SetControl32BitMinimum (ch
, 0);
5366 SetControl32BitMaximum (ch
, 1 << 30);
5367 SetControlViewSize (ch
, 1);
5369 /* Move the scroll bar thumb to the top. */
5370 SetControl32BitValue (ch
, 0);
5371 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5373 /* Move the scroll bar thumb to the bottom. */
5374 SetControl32BitValue (ch
, 1 << 30);
5375 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5377 UnionRect (&r0
, &r1
, &r0
);
5378 XSETINT (bar
->track_top
, r0
.top
);
5379 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5380 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5382 /* Don't show the scroll bar if its height is not enough to
5383 display the scroll bar thumb. */
5384 if (r0
.bottom
- r0
.top
> 0)
5391 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5392 #else /* not USE_TOOLKIT_SCROLL_BARS */
5393 /* Set the scroll bar's current state, unless we're currently being
5395 if (NILP (bar
->dragging
))
5397 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5400 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5403 int start
= ((double) position
* top_range
) / whole
;
5404 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5405 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5408 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5412 /* The following three hooks are used when we're doing a thorough
5413 redisplay of the frame. We don't explicitly know which scroll bars
5414 are going to be deleted, because keeping track of when windows go
5415 away is a real pain - "Can you say set-window-configuration, boys
5416 and girls?" Instead, we just assert at the beginning of redisplay
5417 that *all* scroll bars are to be removed, and then save a scroll bar
5418 from the fiery pit when we actually redisplay its window. */
5420 /* Arrange for all scroll bars on FRAME to be removed at the next call
5421 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5422 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5425 XTcondemn_scroll_bars (frame
)
5428 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5429 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5432 bar
= FRAME_SCROLL_BARS (frame
);
5433 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5434 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5435 XSCROLL_BAR (bar
)->prev
= Qnil
;
5436 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5437 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5438 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5443 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5444 Note that WINDOW isn't necessarily condemned at all. */
5447 XTredeem_scroll_bar (window
)
5448 struct window
*window
;
5450 struct scroll_bar
*bar
;
5453 /* We can't redeem this window's scroll bar if it doesn't have one. */
5454 if (NILP (window
->vertical_scroll_bar
))
5457 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5459 /* Unlink it from the condemned list. */
5460 f
= XFRAME (WINDOW_FRAME (window
));
5461 if (NILP (bar
->prev
))
5463 /* If the prev pointer is nil, it must be the first in one of
5465 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5466 /* It's not condemned. Everything's fine. */
5468 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5469 window
->vertical_scroll_bar
))
5470 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5472 /* If its prev pointer is nil, it must be at the front of
5473 one or the other! */
5477 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5479 if (! NILP (bar
->next
))
5480 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5482 bar
->next
= FRAME_SCROLL_BARS (f
);
5484 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5485 if (! NILP (bar
->next
))
5486 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5489 /* Remove all scroll bars on FRAME that haven't been saved since the
5490 last call to `*condemn_scroll_bars_hook'. */
5493 XTjudge_scroll_bars (f
)
5496 Lisp_Object bar
, next
;
5498 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5500 /* Clear out the condemned list now so we won't try to process any
5501 more events on the hapless scroll bars. */
5502 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5504 for (; ! NILP (bar
); bar
= next
)
5506 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5508 x_scroll_bar_remove (b
);
5511 b
->next
= b
->prev
= Qnil
;
5514 /* Now there should be no references to the condemned scroll bars,
5515 and they should get garbage-collected. */
5519 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5520 is set to something other than NO_EVENT, it is enqueued.
5522 This may be called from a signal handler, so we have to ignore GC
5526 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5527 struct scroll_bar
*bar
;
5528 ControlPartCode part_code
;
5529 const EventRecord
*er
;
5530 struct input_event
*bufp
;
5532 int win_y
, top_range
;
5534 if (! WINDOWP (bar
->window
))
5537 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5538 bufp
->frame_or_window
= bar
->window
;
5541 bar
->dragging
= Qnil
;
5545 case kControlUpButtonPart
:
5546 bufp
->part
= scroll_bar_up_arrow
;
5548 case kControlDownButtonPart
:
5549 bufp
->part
= scroll_bar_down_arrow
;
5551 case kControlPageUpPart
:
5552 bufp
->part
= scroll_bar_above_handle
;
5554 case kControlPageDownPart
:
5555 bufp
->part
= scroll_bar_below_handle
;
5557 #if TARGET_API_MAC_CARBON
5560 case kControlIndicatorPart
:
5562 if (er
->what
== mouseDown
)
5563 bar
->dragging
= make_number (0);
5564 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5565 bufp
->part
= scroll_bar_handle
;
5569 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5570 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5572 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5576 if (! NILP (bar
->dragging
))
5577 win_y
-= XINT (bar
->dragging
);
5581 if (win_y
> top_range
)
5584 XSETINT (bufp
->x
, win_y
);
5585 XSETINT (bufp
->y
, top_range
);
5588 #ifndef USE_TOOLKIT_SCROLL_BARS
5590 /* Handle some mouse motion while someone is dragging the scroll bar.
5592 This may be called from a signal handler, so we have to ignore GC
5596 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5597 struct scroll_bar
*bar
;
5601 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5603 last_mouse_movement_time
= t
;
5606 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5608 /* If we're dragging the bar, display it. */
5609 if (! NILP (bar
->dragging
))
5611 /* Where should the handle be now? */
5612 int new_start
= y_pos
- 24;
5614 if (new_start
!= XINT (bar
->start
))
5616 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5618 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5623 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5625 /* Return information to the user about the current position of the mouse
5626 on the scroll bar. */
5629 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5631 Lisp_Object
*bar_window
;
5632 enum scroll_bar_part
*part
;
5634 unsigned long *time
;
5636 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5637 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5638 #if TARGET_API_MAC_CARBON
5639 WindowRef wp
= GetControlOwner (ch
);
5641 WindowRef wp
= (*ch
)->contrlOwner
;
5644 struct frame
*f
= mac_window_to_frame (wp
);
5645 int win_y
, top_range
;
5647 #if TARGET_API_MAC_CARBON
5648 GetGlobalMouse (&mouse_pos
);
5649 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5650 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5652 SetPortWindowPort (wp
);
5653 GetMouse (&mouse_pos
);
5656 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5657 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5659 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5663 if (! NILP (bar
->dragging
))
5664 win_y
-= XINT (bar
->dragging
);
5668 if (win_y
> top_range
)
5672 *bar_window
= bar
->window
;
5674 if (! NILP (bar
->dragging
))
5675 *part
= scroll_bar_handle
;
5676 else if (win_y
< XINT (bar
->start
))
5677 *part
= scroll_bar_above_handle
;
5678 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5679 *part
= scroll_bar_handle
;
5681 *part
= scroll_bar_below_handle
;
5683 XSETINT (*x
, win_y
);
5684 XSETINT (*y
, top_range
);
5687 last_mouse_scroll_bar
= Qnil
;
5689 *time
= last_mouse_movement_time
;
5693 /* The screen has been cleared so we may have changed foreground or
5694 background colors, and the scroll bars may need to be redrawn.
5695 Clear out the scroll bars, and ask for expose events, so we can
5699 x_scroll_bar_clear (f
)
5702 XTcondemn_scroll_bars (f
);
5703 XTjudge_scroll_bars (f
);
5707 /***********************************************************************
5709 ***********************************************************************/
5712 /* In identifiers such as function/variable names, Emacs tool bar is
5713 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5715 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5716 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5718 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5719 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5720 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5721 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5722 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5723 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5724 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5726 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5727 static void mac_handle_origin_change
P_ ((struct frame
*));
5728 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5732 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5739 mac_get_window_bounds (f
, &inner
, &outer
);
5741 switch (win_gravity
)
5743 case NorthWestGravity
:
5745 case SouthWestGravity
:
5746 left
+= inner
.left
- outer
.left
;
5752 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5755 case NorthEastGravity
:
5757 case SouthEastGravity
:
5758 left
+= inner
.right
- outer
.right
;
5762 switch (win_gravity
)
5764 case NorthWestGravity
:
5766 case NorthEastGravity
:
5767 top
+= inner
.top
- outer
.top
;
5773 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5776 case SouthWestGravity
:
5778 case SouthEastGravity
:
5779 top
+= inner
.bottom
- outer
.bottom
;
5783 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5787 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5794 mac_get_window_bounds (f
, &inner
, &outer
);
5796 switch (win_gravity
)
5798 case NorthWestGravity
:
5800 case SouthWestGravity
:
5807 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5808 - (inner
.right
- inner
.left
)) / 2;
5811 case NorthEastGravity
:
5813 case SouthEastGravity
:
5814 *left
= outer
.right
- (inner
.right
- inner
.left
);
5818 switch (win_gravity
)
5820 case NorthWestGravity
:
5822 case NorthEastGravity
:
5829 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5830 - (inner
.bottom
- inner
.top
)) / 2;
5833 case SouthWestGravity
:
5835 case SouthEastGravity
:
5836 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5842 mac_handle_toolbar_event (next_handler
, event
, data
)
5843 EventHandlerCallRef next_handler
;
5847 OSStatus err
, result
= eventNotHandledErr
;
5849 switch (GetEventKind (event
))
5851 case kEventToolbarGetDefaultIdentifiers
:
5855 case kEventToolbarGetAllowedIdentifiers
:
5857 CFMutableArrayRef array
;
5859 GetEventParameter (event
, kEventParamMutableArray
,
5860 typeCFMutableArrayRef
, NULL
,
5861 sizeof (CFMutableArrayRef
), NULL
, &array
);
5862 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5867 case kEventToolbarCreateItemWithIdentifier
:
5869 CFStringRef identifier
;
5870 HIToolbarItemRef item
= NULL
;
5872 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
5873 typeCFStringRef
, NULL
,
5874 sizeof (CFStringRef
), NULL
, &identifier
);
5876 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
5877 == kCFCompareEqualTo
)
5878 HIToolbarItemCreate (identifier
,
5879 kHIToolbarItemAllowDuplicates
5880 | kHIToolbarItemCantBeRemoved
, &item
);
5884 SetEventParameter (event
, kEventParamToolbarItem
,
5885 typeHIToolbarItemRef
,
5886 sizeof (HIToolbarItemRef
), &item
);
5900 mac_image_spec_to_cg_image (f
, image
)
5904 if (!valid_image_p (image
))
5908 int img_id
= lookup_image (f
, image
);
5909 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
5911 prepare_image_for_display (f
, img
);
5913 return img
->data
.ptr_val
;
5917 /* Create a tool bar for frame F. */
5920 mac_create_frame_tool_bar (f
)
5924 HIToolbarRef toolbar
;
5926 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
5930 static const EventTypeSpec specs
[] =
5931 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
5932 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
5933 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
5935 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
5936 mac_handle_toolbar_event
,
5937 GetEventTypeCount (specs
), specs
,
5942 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
5945 static const EventTypeSpec specs
[] =
5946 {{kEventClassCommand
, kEventCommandProcess
}};
5948 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
5949 mac_handle_toolbar_command_event
,
5950 GetEventTypeCount (specs
),
5954 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
5957 CFRelease (toolbar
);
5962 /* Update the tool bar for frame F. Add new buttons and remove old. */
5965 update_frame_tool_bar (f
)
5968 HIToolbarRef toolbar
= NULL
;
5970 CFArrayRef old_items
= NULL
;
5972 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
5973 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5977 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5978 if (toolbar
== NULL
)
5980 mac_create_frame_tool_bar (f
);
5981 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5982 if (toolbar
== NULL
)
5984 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
5985 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
5988 HIToolbarCopyItems (toolbar
, &old_items
);
5989 if (old_items
== NULL
)
5992 old_count
= CFArrayGetCount (old_items
);
5994 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
5996 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5998 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
5999 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
6002 CGImageRef cg_image
;
6004 HIToolbarItemRef item
;
6006 /* If image is a vector, choose the image according to the
6008 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6009 if (VECTORP (image
))
6013 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6014 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6017 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6018 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6020 xassert (ASIZE (image
) >= idx
);
6021 image
= AREF (image
, idx
);
6026 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6027 /* Ignore invalid image specifications. */
6028 if (cg_image
== NULL
)
6031 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6035 if (pos
< old_count
)
6037 CGImageRef old_cg_image
= NULL
;
6038 CFStringRef old_label
= NULL
;
6039 Boolean old_enabled_p
;
6041 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6043 HIToolbarItemCopyImage (item
, &old_cg_image
);
6044 if (cg_image
!= old_cg_image
)
6045 HIToolbarItemSetImage (item
, cg_image
);
6046 CGImageRelease (old_cg_image
);
6048 HIToolbarItemCopyLabel (item
, &old_label
);
6049 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6050 HIToolbarItemSetLabel (item
, label
);
6051 CFRelease (old_label
);
6053 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6054 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6055 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6060 HIToolbarCreateItemWithIdentifier (toolbar
,
6061 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6065 HIToolbarItemSetImage (item
, cg_image
);
6066 HIToolbarItemSetLabel (item
, label
);
6067 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6068 HIToolbarAppendItem (toolbar
, item
);
6076 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6081 CFRelease (old_items
);
6083 while (pos
< old_count
)
6084 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6086 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6087 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6088 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6089 toolbar visibility change. */
6090 mac_handle_origin_change (f
);
6091 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6093 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6094 /* If the title bar is completely outside the screen, adjust the
6096 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6097 kWindowConstrainMoveRegardlessOfFit
6098 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6099 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6106 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6107 doesn't deallocate the resources. */
6110 free_frame_tool_bar (f
)
6113 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6115 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6118 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6119 f
== mac_focus_frame (dpyinfo
));
6120 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6121 on toolbar visibility change. */
6122 mac_handle_origin_change (f
);
6128 mac_tool_bar_note_mouse_movement (f
, event
)
6133 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6135 HIViewRef item_view
;
6138 mouse_down_p
= (dpyinfo
->grabbed
6139 && f
== last_mouse_frame
6140 && FRAME_LIVE_P (f
));
6144 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6146 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6147 toolbar item view seems to have the same command ID with that of
6148 the toolbar item. */
6150 err
= GetControlCommandID (item_view
, &command_id
);
6151 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6153 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6155 if (i
< f
->n_tool_bar_items
)
6158 HIViewRef content_view
;
6160 err
= HIViewGetBounds (item_view
, &bounds
);
6162 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6163 kHIViewWindowContentID
, &content_view
);
6165 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6167 SetRect (&last_mouse_glyph
,
6168 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6169 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6171 help_echo_object
= help_echo_window
= Qnil
;
6173 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6174 if (NILP (help_echo_string
))
6175 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6181 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6182 EventHandlerCallRef next_handler
;
6186 OSStatus err
, result
= eventNotHandledErr
;
6187 struct frame
*f
= (struct frame
*) data
;
6190 err
= GetEventParameter (event
, kEventParamDirectObject
,
6191 typeHICommand
, NULL
,
6192 sizeof (HICommand
), NULL
, &command
);
6196 switch (GetEventKind (event
))
6198 case kEventCommandProcess
:
6199 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6200 result
= CallNextEventHandler (next_handler
, event
);
6203 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6205 if (i
< f
->n_tool_bar_items
6206 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6209 struct input_event buf
;
6213 XSETFRAME (frame
, f
);
6214 buf
.kind
= TOOL_BAR_EVENT
;
6215 buf
.frame_or_window
= frame
;
6217 kbd_buffer_store_event (&buf
);
6219 buf
.kind
= TOOL_BAR_EVENT
;
6220 buf
.frame_or_window
= frame
;
6221 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6222 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6223 kbd_buffer_store_event (&buf
);
6237 #endif /* USE_MAC_TOOLBAR */
6240 /***********************************************************************
6242 ***********************************************************************/
6244 /* Set clipping for output in glyph row ROW. W is the window in which
6245 we operate. GC is the graphics context to set clipping in.
6247 ROW may be a text row or, e.g., a mode line. Text rows must be
6248 clipped to the interior of the window dedicated to text display,
6249 mode lines must be clipped to the whole window. */
6252 x_clip_to_row (w
, row
, area
, gc
)
6254 struct glyph_row
*row
;
6258 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6260 int window_x
, window_y
, window_width
;
6262 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6264 clip_rect
.left
= window_x
;
6265 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6266 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6267 clip_rect
.right
= clip_rect
.left
+ window_width
;
6268 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6270 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6274 /* Draw a hollow box cursor on window W in glyph row ROW. */
6277 x_draw_hollow_cursor (w
, row
)
6279 struct glyph_row
*row
;
6281 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6282 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6283 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6286 struct glyph
*cursor_glyph
;
6289 /* Get the glyph the cursor is on. If we can't tell because
6290 the current matrix is invalid or such, give up. */
6291 cursor_glyph
= get_phys_cursor_glyph (w
);
6292 if (cursor_glyph
== NULL
)
6295 /* Compute frame-relative coordinates for phys cursor. */
6296 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6297 wd
= w
->phys_cursor_width
;
6299 /* The foreground of cursor_gc is typically the same as the normal
6300 background color, which can cause the cursor box to be invisible. */
6301 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6302 if (dpyinfo
->scratch_cursor_gc
)
6303 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6305 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6306 GCForeground
, &xgcv
);
6307 gc
= dpyinfo
->scratch_cursor_gc
;
6309 /* Set clipping, draw the rectangle, and reset clipping again. */
6310 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6311 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6312 mac_reset_clip_rectangles (dpy
, gc
);
6316 /* Draw a bar cursor on window W in glyph row ROW.
6318 Implementation note: One would like to draw a bar cursor with an
6319 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6320 Unfortunately, I didn't find a font yet that has this property set.
6324 x_draw_bar_cursor (w
, row
, width
, kind
)
6326 struct glyph_row
*row
;
6328 enum text_cursor_kinds kind
;
6330 struct frame
*f
= XFRAME (w
->frame
);
6331 struct glyph
*cursor_glyph
;
6333 /* If cursor is out of bounds, don't draw garbage. This can happen
6334 in mini-buffer windows when switching between echo area glyphs
6336 cursor_glyph
= get_phys_cursor_glyph (w
);
6337 if (cursor_glyph
== NULL
)
6340 /* If on an image, draw like a normal cursor. That's usually better
6341 visible than drawing a bar, esp. if the image is large so that
6342 the bar might not be in the window. */
6343 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6345 struct glyph_row
*row
;
6346 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6347 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6351 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6352 Window window
= FRAME_MAC_WINDOW (f
);
6353 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6354 unsigned long mask
= GCForeground
| GCBackground
;
6355 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6358 /* If the glyph's background equals the color we normally draw
6359 the bar cursor in, the bar cursor in its normal color is
6360 invisible. Use the glyph's foreground color instead in this
6361 case, on the assumption that the glyph's colors are chosen so
6362 that the glyph is legible. */
6363 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6364 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6366 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6369 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6372 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6373 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6377 width
= FRAME_CURSOR_WIDTH (f
);
6378 width
= min (cursor_glyph
->pixel_width
, width
);
6380 w
->phys_cursor_width
= width
;
6381 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6383 if (kind
== BAR_CURSOR
)
6384 mac_fill_rectangle (f
, gc
,
6385 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6386 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6387 width
, row
->height
);
6389 mac_fill_rectangle (f
, gc
,
6390 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6391 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6392 row
->height
- width
),
6393 cursor_glyph
->pixel_width
,
6396 mac_reset_clip_rectangles (dpy
, gc
);
6401 /* RIF: Define cursor CURSOR on frame F. */
6404 mac_define_frame_cursor (f
, cursor
)
6408 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6410 if (dpyinfo
->x_focus_frame
== f
)
6411 SetThemeCursor (cursor
);
6415 /* RIF: Clear area on frame F. */
6418 mac_clear_frame_area (f
, x
, y
, width
, height
)
6420 int x
, y
, width
, height
;
6422 mac_clear_area (f
, x
, y
, width
, height
);
6426 /* RIF: Draw cursor on window W. */
6429 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6431 struct glyph_row
*glyph_row
;
6433 int cursor_type
, cursor_width
;
6438 w
->phys_cursor_type
= cursor_type
;
6439 w
->phys_cursor_on_p
= 1;
6441 if (glyph_row
->exact_window_width_line_p
6442 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6444 glyph_row
->cursor_in_fringe_p
= 1;
6445 draw_fringe_bitmap (w
, glyph_row
, 0);
6448 switch (cursor_type
)
6450 case HOLLOW_BOX_CURSOR
:
6451 x_draw_hollow_cursor (w
, glyph_row
);
6454 case FILLED_BOX_CURSOR
:
6455 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6459 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6463 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6467 w
->phys_cursor_width
= 0;
6479 #if 0 /* MAC_TODO: no icon support yet. */
6481 x_bitmap_icon (f
, icon
)
6487 if (FRAME_W32_WINDOW (f
) == 0)
6491 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6492 else if (STRINGP (icon
))
6493 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6494 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6495 else if (SYMBOLP (icon
))
6499 if (EQ (icon
, intern ("application")))
6500 name
= (LPCTSTR
) IDI_APPLICATION
;
6501 else if (EQ (icon
, intern ("hand")))
6502 name
= (LPCTSTR
) IDI_HAND
;
6503 else if (EQ (icon
, intern ("question")))
6504 name
= (LPCTSTR
) IDI_QUESTION
;
6505 else if (EQ (icon
, intern ("exclamation")))
6506 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6507 else if (EQ (icon
, intern ("asterisk")))
6508 name
= (LPCTSTR
) IDI_ASTERISK
;
6509 else if (EQ (icon
, intern ("winlogo")))
6510 name
= (LPCTSTR
) IDI_WINLOGO
;
6514 hicon
= LoadIcon (NULL
, name
);
6522 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6527 #endif /* MAC_TODO */
6529 /************************************************************************
6531 ************************************************************************/
6533 /* Display Error Handling functions not used on W32. Listing them here
6534 helps diff stay in step when comparing w32term.c with xterm.c.
6536 x_error_catcher (display, error)
6537 x_catch_errors (dpy)
6538 x_catch_errors_unwind (old_val)
6539 x_check_errors (dpy, format)
6540 x_had_errors_p (dpy)
6541 x_clear_errors (dpy)
6542 x_uncatch_errors (dpy, count)
6544 x_connection_signal (signalnum)
6545 x_connection_closed (dpy, error_message)
6546 x_error_quitter (display, error)
6547 x_error_handler (display, error)
6548 x_io_error_quitter (display)
6553 /* Changing the font of the frame. */
6555 /* Give frame F the font named FONTNAME as its default font, and
6556 return the full name of that font. FONTNAME may be a wildcard
6557 pattern; in that case, we choose some font that fits the pattern.
6558 The return value shows which font we chose. */
6561 x_new_font (f
, fontname
)
6563 register char *fontname
;
6565 struct font_info
*fontp
6566 = FS_LOAD_FONT (f
, fontname
);
6571 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
6572 /* This font is already set in frame F. There's nothing more to
6574 return build_string (fontp
->full_name
);
6576 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6577 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6578 FRAME_FONTSET (f
) = -1;
6580 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6581 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6582 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6584 compute_fringe_widths (f
, 1);
6586 /* Compute the scroll bar width in character columns. */
6587 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6589 int wid
= FRAME_COLUMN_WIDTH (f
);
6590 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6591 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6595 int wid
= FRAME_COLUMN_WIDTH (f
);
6596 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6599 /* Now make the frame display the given font. */
6600 if (FRAME_MAC_WINDOW (f
) != 0)
6602 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6604 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6606 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6609 /* Don't change the size of a tip frame; there's no point in
6610 doing it because it's done in Fx_show_tip, and it leads to
6611 problems because the tip frame has no widget. */
6612 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6613 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6616 return build_string (fontp
->full_name
);
6619 /* Give frame F the fontset named FONTSETNAME as its default fontset,
6620 and return the full name of that fontset. FONTSETNAME may be a
6621 wildcard pattern; in that case, we choose some fontset that fits
6622 the pattern. FONTSETNAME may be a font name for ASCII characters;
6623 in that case, we create a fontset from that font name.
6625 The return value shows which fontset we chose.
6626 If FONTSETNAME specifies the default fontset, return Qt.
6627 If an ASCII font in the specified fontset can't be loaded, return
6631 x_new_fontset (f
, fontsetname
)
6633 Lisp_Object fontsetname
;
6635 int fontset
= fs_query_fontset (fontsetname
, 0);
6638 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
6639 /* This fontset is already set in frame F. There's nothing more
6641 return fontset_name (fontset
);
6642 else if (fontset
== 0)
6643 /* The default fontset can't be the default font. */
6647 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6649 result
= x_new_font (f
, SDATA (fontsetname
));
6651 if (!STRINGP (result
))
6652 /* Can't load ASCII font. */
6656 fontset
= new_fontset_from_font_name (result
);
6658 /* Since x_new_font doesn't update any fontset information, do it now. */
6659 FRAME_FONTSET (f
) = fontset
;
6661 return fontset_name (fontset
);
6665 /***********************************************************************
6666 TODO: W32 Input Methods
6667 ***********************************************************************/
6668 /* Listing missing functions from xterm.c helps diff stay in step.
6670 xim_destroy_callback (xim, client_data, call_data)
6671 xim_open_dpy (dpyinfo, resource_name)
6673 xim_instantiate_callback (display, client_data, call_data)
6674 xim_initialize (dpyinfo, resource_name)
6675 xim_close_dpy (dpyinfo)
6681 mac_get_window_bounds (f
, inner
, outer
)
6683 Rect
*inner
, *outer
;
6685 #if TARGET_API_MAC_CARBON
6686 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6687 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6688 #else /* not TARGET_API_MAC_CARBON */
6689 RgnHandle region
= NewRgn ();
6691 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6692 *inner
= (*region
)->rgnBBox
;
6693 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6694 *outer
= (*region
)->rgnBBox
;
6695 DisposeRgn (region
);
6696 #endif /* not TARGET_API_MAC_CARBON */
6700 mac_handle_origin_change (f
)
6703 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6707 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6709 int pixelwidth
, pixelheight
;
6713 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6714 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6716 if (cols
!= FRAME_COLS (f
)
6717 || rows
!= FRAME_LINES (f
)
6718 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6719 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6721 /* We pass 1 for DELAY since we can't run Lisp code inside of
6723 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6724 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6725 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6726 SET_FRAME_GARBAGED (f
);
6728 /* If cursor was outside the new size, mark it as off. */
6729 mark_window_cursors_off (XWINDOW (f
->root_window
));
6731 /* Clear out any recollection of where the mouse highlighting
6732 was, since it might be in a place that's outside the new
6733 frame size. Actually checking whether it is outside is a
6734 pain in the neck, so don't try--just let the highlighting be
6735 done afresh with new size. */
6736 cancel_mouse_face (f
);
6738 #if TARGET_API_MAC_CARBON
6739 if (f
->output_data
.mac
->hourglass_control
)
6742 mac_prepare_for_quickdraw (f
);
6744 MoveControl (f
->output_data
.mac
->hourglass_control
,
6745 pixelwidth
- HOURGLASS_WIDTH
, 0);
6752 /* Calculate the absolute position in frame F
6753 from its current recorded position values and gravity. */
6756 x_calc_absolute_position (f
)
6759 int width_diff
= 0, height_diff
= 0;
6760 int flags
= f
->size_hint_flags
;
6763 /* We have nothing to do if the current position
6764 is already for the top-left corner. */
6765 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6768 /* Find the offsets of the outside upper-left corner of
6769 the inner window, with respect to the outer window. */
6771 mac_get_window_bounds (f
, &inner
, &outer
);
6774 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6775 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6777 /* Treat negative positions as relative to the leftmost bottommost
6778 position that fits on the screen. */
6779 if (flags
& XNegative
)
6780 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6782 - FRAME_PIXEL_WIDTH (f
)
6785 if (flags
& YNegative
)
6786 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6788 - FRAME_PIXEL_HEIGHT (f
)
6791 /* The left_pos and top_pos
6792 are now relative to the top and left screen edges,
6793 so the flags should correspond. */
6794 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6797 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6798 to really change the position, and 0 when calling from
6799 x_make_frame_visible (in that case, XOFF and YOFF are the current
6800 position values). It is -1 when calling from x_set_frame_parameters,
6801 which means, do adjust for borders but don't change the gravity. */
6804 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6806 register int xoff
, yoff
;
6809 if (change_gravity
> 0)
6813 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6815 f
->size_hint_flags
|= XNegative
;
6817 f
->size_hint_flags
|= YNegative
;
6818 f
->win_gravity
= NorthWestGravity
;
6820 x_calc_absolute_position (f
);
6823 x_wm_set_size_hint (f
, (long) 0, 0);
6825 #if TARGET_API_MAC_CARBON
6826 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6827 /* If the title bar is completely outside the screen, adjust the
6829 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6830 kWindowConstrainMoveRegardlessOfFit
6831 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6832 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6833 mac_handle_origin_change (f
);
6836 Rect inner
, outer
, screen_rect
, dummy
;
6837 RgnHandle region
= NewRgn ();
6839 mac_get_window_bounds (f
, &inner
, &outer
);
6840 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6841 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6842 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6843 f
->top_pos
+ f
->y_pixels_diff
, false);
6845 /* If the title bar is completely outside the screen, adjust the
6846 position. The variable `outer' holds the title bar rectangle.
6847 The variable `inner' holds slightly smaller one than `outer',
6848 so that the calculation of overlapping may not become too
6850 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6851 outer
= (*region
)->rgnBBox
;
6852 DisposeRgn (region
);
6854 InsetRect (&inner
, 8, 8);
6855 screen_rect
= qd
.screenBits
.bounds
;
6856 screen_rect
.top
+= GetMBarHeight ();
6858 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6860 if (inner
.right
<= screen_rect
.left
)
6861 f
->left_pos
= screen_rect
.left
;
6862 else if (inner
.left
>= screen_rect
.right
)
6863 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6865 if (inner
.bottom
<= screen_rect
.top
)
6866 f
->top_pos
= screen_rect
.top
;
6867 else if (inner
.top
>= screen_rect
.bottom
)
6868 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6870 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6871 f
->top_pos
+ f
->y_pixels_diff
, false);
6879 /* Call this to change the size of frame F's x-window.
6880 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6881 for this size change and subsequent size changes.
6882 Otherwise we leave the window gravity unchanged. */
6885 x_set_window_size (f
, change_gravity
, cols
, rows
)
6890 int pixelwidth
, pixelheight
;
6894 check_frame_size (f
, &rows
, &cols
);
6895 f
->scroll_bar_actual_width
6896 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6898 compute_fringe_widths (f
, 0);
6900 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6901 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6903 f
->win_gravity
= NorthWestGravity
;
6904 x_wm_set_size_hint (f
, (long) 0, 0);
6906 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6908 #if TARGET_API_MAC_CARBON
6909 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6911 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6913 if (f
->output_data
.mac
->internal_border_width
6914 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6916 mac_clear_window (f
);
6917 f
->output_data
.mac
->internal_border_width
6918 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6921 SET_FRAME_GARBAGED (f
);
6926 /* Mouse warping. */
6928 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6931 x_set_mouse_position (f
, x
, y
)
6937 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6938 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6940 if (pix_x
< 0) pix_x
= 0;
6941 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6943 if (pix_y
< 0) pix_y
= 0;
6944 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6946 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6950 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6955 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
6956 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
6959 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
6962 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6965 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6966 0, 0, 0, 0, pix_x
, pix_y
);
6972 /* focus shifting, raising and lowering. */
6975 x_focus_on_frame (f
)
6978 #if 0 /* This proves to be unpleasant. */
6982 /* I don't think that the ICCCM allows programs to do things like this
6983 without the interaction of the window manager. Whatever you end up
6984 doing with this code, do it to x_unfocus_frame too. */
6985 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6986 RevertToPointerRoot
, CurrentTime
);
6996 /* Raise frame F. */
7002 if (f
->async_visible
)
7005 BringToFront (FRAME_MAC_WINDOW (f
));
7010 /* Lower frame F. */
7016 if (f
->async_visible
)
7019 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7025 XTframe_raise_lower (f
, raise_flag
)
7035 /* Change of visibility. */
7038 mac_handle_visibility_change (f
)
7041 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7042 int visible
= 0, iconified
= 0;
7043 struct input_event buf
;
7045 if (IsWindowVisible (wp
))
7047 if (IsWindowCollapsed (wp
))
7053 if (!f
->async_visible
&& visible
)
7057 /* wait_reading_process_output will notice this and update
7058 the frame's display structures. If we were made
7059 invisible, we should not set garbaged, because that stops
7060 redrawing on Update events. */
7061 SET_FRAME_GARBAGED (f
);
7064 buf
.kind
= DEICONIFY_EVENT
;
7065 XSETFRAME (buf
.frame_or_window
, f
);
7067 kbd_buffer_store_event (&buf
);
7069 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7070 /* Force a redisplay sooner or later to update the
7071 frame titles in case this is the second frame. */
7072 record_asynch_buffer_change ();
7074 else if (f
->async_visible
&& !visible
)
7078 buf
.kind
= ICONIFY_EVENT
;
7079 XSETFRAME (buf
.frame_or_window
, f
);
7081 kbd_buffer_store_event (&buf
);
7084 f
->async_visible
= visible
;
7085 f
->async_iconified
= iconified
;
7088 /* This tries to wait until the frame is really visible.
7089 However, if the window manager asks the user where to position
7090 the frame, this will return before the user finishes doing that.
7091 The frame will not actually be visible at that time,
7092 but it will become visible later when the window manager
7093 finishes with it. */
7096 x_make_frame_visible (f
)
7101 if (! FRAME_VISIBLE_P (f
))
7103 /* We test FRAME_GARBAGED_P here to make sure we don't
7104 call x_set_offset a second time
7105 if we get to x_make_frame_visible a second time
7106 before the window gets really visible. */
7107 if (! FRAME_ICONIFIED_P (f
)
7108 && ! f
->output_data
.mac
->asked_for_visible
)
7109 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7111 f
->output_data
.mac
->asked_for_visible
= 1;
7113 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7114 ShowWindow (FRAME_MAC_WINDOW (f
));
7117 XFlush (FRAME_MAC_DISPLAY (f
));
7119 /* Synchronize to ensure Emacs knows the frame is visible
7120 before we do anything else. We do this loop with input not blocked
7121 so that incoming events are handled. */
7126 /* This must come after we set COUNT. */
7129 XSETFRAME (frame
, f
);
7131 /* Wait until the frame is visible. Process X events until a
7132 MapNotify event has been seen, or until we think we won't get a
7133 MapNotify at all.. */
7134 for (count
= input_signal_count
+ 10;
7135 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7137 /* Force processing of queued events. */
7140 /* Machines that do polling rather than SIGIO have been
7141 observed to go into a busy-wait here. So we'll fake an
7142 alarm signal to let the handler know that there's something
7143 to be read. We used to raise a real alarm, but it seems
7144 that the handler isn't always enabled here. This is
7146 if (input_polling_used ())
7148 /* It could be confusing if a real alarm arrives while
7149 processing the fake one. Turn it off and let the
7150 handler reset it. */
7151 extern void poll_for_input_1
P_ ((void));
7152 int old_poll_suppress_count
= poll_suppress_count
;
7153 poll_suppress_count
= 1;
7154 poll_for_input_1 ();
7155 poll_suppress_count
= old_poll_suppress_count
;
7158 /* See if a MapNotify event has been processed. */
7159 FRAME_SAMPLE_VISIBILITY (f
);
7164 /* Change from mapped state to withdrawn state. */
7166 /* Make the frame visible (mapped and not iconified). */
7169 x_make_frame_invisible (f
)
7172 /* A deactivate event does not occur when the last visible frame is
7173 made invisible. So if we clear the highlight here, it will not
7174 be rehighlighted when it is made visible. */
7176 /* Don't keep the highlight on an invisible frame. */
7177 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7178 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7183 #if !TARGET_API_MAC_CARBON
7184 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7185 that the current position of the window is user-specified, rather than
7186 program-specified, so that when the window is mapped again, it will be
7187 placed at the same location, without forcing the user to position it
7188 by hand again (they have already done that once for this window.) */
7189 x_wm_set_size_hint (f
, (long) 0, 1);
7192 HideWindow (FRAME_MAC_WINDOW (f
));
7196 #if !TARGET_API_MAC_CARBON
7197 mac_handle_visibility_change (f
);
7201 /* Change window state from mapped to iconified. */
7209 /* A deactivate event does not occur when the last visible frame is
7210 iconified. So if we clear the highlight here, it will not be
7211 rehighlighted when it is deiconified. */
7213 /* Don't keep the highlight on an invisible frame. */
7214 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7215 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7218 if (f
->async_iconified
)
7223 FRAME_SAMPLE_VISIBILITY (f
);
7225 if (! FRAME_VISIBLE_P (f
))
7226 ShowWindow (FRAME_MAC_WINDOW (f
));
7228 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7233 error ("Can't notify window manager of iconification");
7235 #if !TARGET_API_MAC_CARBON
7236 mac_handle_visibility_change (f
);
7241 /* Free X resources of frame F. */
7244 x_free_frame_resources (f
)
7247 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7248 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7252 if (wp
!= tip_window
)
7253 remove_window_handler (wp
);
7256 mac_prepare_for_quickdraw (f
);
7259 if (wp
== tip_window
)
7260 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7261 closed' event. So we reset tip_window here. */
7264 free_frame_menubar (f
);
7266 if (FRAME_FACE_CACHE (f
))
7267 free_frame_faces (f
);
7271 if (FRAME_SIZE_HINTS (f
))
7272 xfree (FRAME_SIZE_HINTS (f
));
7274 xfree (f
->output_data
.mac
);
7275 f
->output_data
.mac
= NULL
;
7277 if (f
== dpyinfo
->x_focus_frame
)
7279 dpyinfo
->x_focus_frame
= 0;
7280 #if USE_MAC_FONT_PANEL
7281 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7284 if (f
== dpyinfo
->x_focus_event_frame
)
7285 dpyinfo
->x_focus_event_frame
= 0;
7286 if (f
== dpyinfo
->x_highlight_frame
)
7287 dpyinfo
->x_highlight_frame
= 0;
7289 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7291 dpyinfo
->mouse_face_beg_row
7292 = dpyinfo
->mouse_face_beg_col
= -1;
7293 dpyinfo
->mouse_face_end_row
7294 = dpyinfo
->mouse_face_end_col
= -1;
7295 dpyinfo
->mouse_face_window
= Qnil
;
7296 dpyinfo
->mouse_face_deferred_gc
= 0;
7297 dpyinfo
->mouse_face_mouse_frame
= 0;
7304 /* Destroy the X window of frame F. */
7307 x_destroy_window (f
)
7310 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7312 x_free_frame_resources (f
);
7314 dpyinfo
->reference_count
--;
7318 /* Setting window manager hints. */
7320 /* Set the normal size hints for the window manager, for frame F.
7321 FLAGS is the flags word to use--or 0 meaning preserve the flags
7322 that the window now has.
7323 If USER_POSITION is nonzero, we set the USPosition
7324 flag (this is useful when FLAGS is 0). */
7326 x_wm_set_size_hint (f
, flags
, user_position
)
7331 int base_width
, base_height
, width_inc
, height_inc
;
7332 int min_rows
= 0, min_cols
= 0;
7333 XSizeHints
*size_hints
;
7335 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7336 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7337 width_inc
= FRAME_COLUMN_WIDTH (f
);
7338 height_inc
= FRAME_LINE_HEIGHT (f
);
7340 check_frame_size (f
, &min_rows
, &min_cols
);
7342 size_hints
= FRAME_SIZE_HINTS (f
);
7343 if (size_hints
== NULL
)
7345 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7346 bzero (size_hints
, sizeof (XSizeHints
));
7349 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7350 size_hints
->width_inc
= width_inc
;
7351 size_hints
->height_inc
= height_inc
;
7352 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7353 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7354 size_hints
->base_width
= base_width
;
7355 size_hints
->base_height
= base_height
;
7358 size_hints
->flags
= flags
;
7359 else if (user_position
)
7361 size_hints
->flags
&= ~ PPosition
;
7362 size_hints
->flags
|= USPosition
;
7366 #if 0 /* MAC_TODO: hide application instead of iconify? */
7367 /* Used for IconicState or NormalState */
7370 x_wm_set_window_state (f
, state
)
7374 #ifdef USE_X_TOOLKIT
7377 XtSetArg (al
[0], XtNinitialState
, state
);
7378 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7379 #else /* not USE_X_TOOLKIT */
7380 Window window
= FRAME_X_WINDOW (f
);
7382 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7383 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7385 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7386 #endif /* not USE_X_TOOLKIT */
7390 x_wm_set_icon_pixmap (f
, pixmap_id
)
7396 #ifndef USE_X_TOOLKIT
7397 Window window
= FRAME_X_WINDOW (f
);
7402 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7403 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7407 /* It seems there is no way to turn off use of an icon pixmap.
7408 The following line does it, only if no icon has yet been created,
7409 for some window managers. But with mwm it crashes.
7410 Some people say it should clear the IconPixmapHint bit in this case,
7411 but that doesn't work, and the X consortium said it isn't the
7412 right thing at all. Since there is no way to win,
7413 best to explicitly give up. */
7415 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7421 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7425 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7426 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7429 #else /* not USE_X_TOOLKIT */
7431 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7432 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7434 #endif /* not USE_X_TOOLKIT */
7437 #endif /* MAC_TODO */
7440 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7444 #if 0 /* MAC_TODO: no icons on Mac */
7445 #ifdef USE_X_TOOLKIT
7446 Window window
= XtWindow (f
->output_data
.x
->widget
);
7448 Window window
= FRAME_X_WINDOW (f
);
7451 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7452 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7453 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7455 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7456 #endif /* MAC_TODO */
7460 /***********************************************************************
7462 ***********************************************************************/
7464 /* An XLFD pattern is divided into blocks delimited by '*'. This
7465 structure holds information for each block. */
7466 struct xlfdpat_block
7468 /* Length of the pattern string in this block. Non-zero except for
7469 the first and the last blocks. */
7472 /* Pattern string except the last character in this block. The last
7473 character is replaced with NUL in order to use it as a
7475 unsigned char *pattern
;
7477 /* Last character of the pattern string. Must not be '?'. */
7478 unsigned char last_char
;
7480 /* One of the tables for the Boyer-Moore string search. It
7481 specifies the number of positions to proceed for each character
7482 with which the match fails. */
7485 /* The skip value for the last character in the above `skip' is
7486 assigned to `infinity' in order to simplify a loop condition.
7487 The original value is saved here. */
7493 /* Normalized pattern string. "Normalized" means that capital
7494 letters are lowered, blocks are not empty except the first and
7495 the last ones, and trailing '?'s in a block that is not the last
7496 one are moved to the next one. The last character in each block
7497 is replaced with NUL. */
7500 /* Number of characters except '*'s and trailing '?'s in the
7501 normalized pattern string. */
7504 /* Number of trailing '?'s in the normalized pattern string. */
7505 int trailing_anychars
;
7507 /* Number of blocks and information for each block. The latter is
7508 NULL if the pattern is exact (no '*' or '?' in it). */
7510 struct xlfdpat_block
*blocks
;
7514 xlfdpat_destroy (pat
)
7515 struct xlfdpat
*pat
;
7522 xfree (pat
->blocks
);
7529 static struct xlfdpat
*
7530 xlfdpat_create (pattern
)
7531 const char *pattern
;
7533 struct xlfdpat
*pat
;
7534 int nblocks
, i
, skip
;
7535 unsigned char last_char
, *p
, *q
, *anychar_head
;
7536 const unsigned char *ptr
;
7537 struct xlfdpat_block
*blk
;
7539 pat
= xmalloc (sizeof (struct xlfdpat
));
7540 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7542 /* Normalize the pattern string and store it to `pat->buf'. */
7544 anychar_head
= NULL
;
7547 for (ptr
= pattern
; *ptr
; ptr
++)
7549 unsigned char c
= *ptr
;
7552 if (last_char
== '*')
7553 /* ...a** -> ...a* */
7557 if (last_char
== '?')
7559 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7560 /* ...*??* -> ...*?? */
7563 /* ...a??* -> ...a*?? */
7565 *anychar_head
++ = '*';
7573 if (last_char
!= '?')
7577 /* On Mac OS X 10.3, tolower also converts non-ASCII
7578 characters for some locales. */
7582 *q
++ = last_char
= c
;
7586 pat
->nblocks
= nblocks
;
7587 if (last_char
!= '?')
7588 pat
->trailing_anychars
= 0;
7591 pat
->trailing_anychars
= q
- anychar_head
;
7594 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7596 if (anychar_head
== NULL
&& nblocks
== 1)
7598 /* The pattern is exact. */
7603 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7605 /* Divide the normalized pattern into blocks. */
7607 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7612 blk
->len
= p
- blk
->pattern
;
7616 blk
->len
= q
- blk
->pattern
;
7618 /* Setup a table for the Boyer-Moore string search. */
7619 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7622 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7623 blk
->pattern
[blk
->len
- 1] = '\0';
7625 for (skip
= 1; skip
< blk
->len
; skip
++)
7626 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7629 for (i
= 0; i
< 256; i
++)
7630 blk
->skip
[i
] = skip
;
7632 p
= blk
->pattern
+ (blk
->len
- skip
);
7634 blk
->skip
[*p
++] = skip
;
7636 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7643 xlfdpat_exact_p (pat
)
7644 struct xlfdpat
*pat
;
7646 return pat
->blocks
== NULL
;
7649 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7650 that the pattern in *BLK matches with its prefix. Return NULL
7651 there is no such strings. STRING must be lowered in advance. */
7654 xlfdpat_block_match_1 (blk
, string
, start_max
)
7655 struct xlfdpat_block
*blk
;
7656 const unsigned char *string
;
7659 int start
, infinity
;
7661 const unsigned char *s
;
7663 xassert (blk
->len
> 0);
7664 xassert (start_max
+ blk
->len
<= strlen (string
));
7665 xassert (blk
->last_char
!= '?');
7667 /* See the comments in the function `boyer_moore' (search.c) for the
7668 use of `infinity'. */
7669 infinity
= start_max
+ blk
->len
+ 1;
7670 blk
->skip
[blk
->last_char
] = infinity
;
7675 /* Check the last character of the pattern. */
7676 s
= string
+ blk
->len
- 1;
7679 start
+= blk
->skip
[*(s
+ start
)];
7681 while (start
<= start_max
);
7683 if (start
< infinity
)
7684 /* Couldn't find the last character. */
7687 /* No less than `infinity' means we could find the last
7688 character at `s[start - infinity]'. */
7691 /* Check the remaining characters. We prefer making no-'?'
7692 cases faster because the use of '?' is really rare. */
7697 while (*p
++ == *s
++)
7700 while (*(p
- 1) == '?');
7702 if (*(p
- 1) == '\0')
7704 return string
+ start
;
7707 start
+= blk
->last_char_skip
;
7709 while (start
<= start_max
);
7714 #define xlfdpat_block_match(b, s, m) \
7715 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7716 : xlfdpat_block_match_1 (b, s, m))
7718 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7719 matches with STRING. STRING must be lowered in advance. */
7722 xlfdpat_match (pat
, string
)
7723 struct xlfdpat
*pat
;
7724 const unsigned char *string
;
7726 int str_len
, nblocks
, i
, start_max
;
7727 struct xlfdpat_block
*blk
;
7728 const unsigned char *s
;
7730 xassert (pat
->nblocks
> 0);
7732 if (xlfdpat_exact_p (pat
))
7733 return strcmp (pat
->buf
, string
) == 0;
7735 /* The number of the characters in the string must not be smaller
7736 than that in the pattern. */
7737 str_len
= strlen (string
);
7738 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7741 /* Chop off the trailing '?'s. */
7742 str_len
-= pat
->trailing_anychars
;
7744 /* The last block. When it is non-empty, it must match at the end
7746 nblocks
= pat
->nblocks
;
7747 blk
= pat
->blocks
+ (nblocks
- 1);
7749 /* The last block is also the first one. */
7750 return (str_len
== blk
->len
7751 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7752 else if (blk
->len
!= 0)
7753 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7756 /* The first block. When it is non-empty, it must match at the
7757 beginning of the string. */
7761 s
= xlfdpat_block_match (blk
, string
, 0);
7764 string
= s
+ blk
->len
;
7767 /* The rest of the blocks. */
7768 start_max
= str_len
- pat
->nchars
;
7769 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7771 s
= xlfdpat_block_match (blk
, string
, start_max
);
7774 start_max
-= s
- string
;
7775 string
= s
+ blk
->len
;
7782 /***********************************************************************
7784 ***********************************************************************/
7786 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7789 x_get_font_info (f
, font_idx
)
7793 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7796 /* the global font name table */
7797 static char **font_name_table
= NULL
;
7798 static int font_name_table_size
= 0;
7799 static int font_name_count
= 0;
7801 /* Alist linking font family names to Font Manager font family
7802 references (which can also be used as QuickDraw font IDs). We use
7803 an alist because hash tables are not ready when the terminal frame
7804 for Mac OS Classic is created. */
7805 static Lisp_Object fm_font_family_alist
;
7807 /* Hash table linking font family names to ATSU font IDs. */
7808 static Lisp_Object atsu_font_id_hash
;
7809 /* Alist linking Font Manager style to face attributes. */
7810 static Lisp_Object fm_style_face_attributes_alist
;
7811 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7814 /* Alist linking character set strings to Mac text encoding and Emacs
7816 static Lisp_Object Vmac_charset_info_alist
;
7819 create_text_encoding_info_alist ()
7821 Lisp_Object result
= Qnil
, rest
;
7823 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7825 Lisp_Object charset_info
= XCAR (rest
);
7826 Lisp_Object charset
, coding_system
, text_encoding
;
7827 Lisp_Object existing_info
;
7829 if (!(CONSP (charset_info
)
7830 && (charset
= XCAR (charset_info
),
7832 && CONSP (XCDR (charset_info
))
7833 && (text_encoding
= XCAR (XCDR (charset_info
)),
7834 INTEGERP (text_encoding
))
7835 && CONSP (XCDR (XCDR (charset_info
)))
7836 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7837 SYMBOLP (coding_system
))))
7840 existing_info
= assq_no_quit (text_encoding
, result
);
7841 if (NILP (existing_info
))
7842 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7845 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7846 XSETCDR (XCDR (existing_info
),
7847 Fcons (charset
, XCDR (XCDR (existing_info
))));
7855 decode_mac_font_name (name
, size
, coding_system
)
7858 Lisp_Object coding_system
;
7860 struct coding_system coding
;
7863 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7865 for (p
= name
; *p
; p
++)
7866 if (!isascii (*p
) || iscntrl (*p
))
7871 setup_coding_system (coding_system
, &coding
);
7872 coding
.src_multibyte
= 0;
7873 coding
.dst_multibyte
= 1;
7874 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7875 coding
.dst_bytes
= size
;
7876 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
7878 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
7879 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
7880 name
[min (coding
.produced
, size
)] = '\0';
7884 /* If there's just one occurrence of '-' in the family name, it is
7885 replaced with '_'. (More than one occurrence of '-' means a
7886 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7887 p
= strchr (name
, '-');
7888 if (p
&& strchr (p
+ 1, '-') == NULL
)
7891 for (p
= name
; *p
; p
++)
7892 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7893 for some locales. */
7900 mac_to_x_fontname (name
, size
, style
, charset
)
7908 char xf
[256], *result
;
7911 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7915 strcpy(foundry
, "Apple");
7916 strcpy(family
, name
);
7919 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7920 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7921 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7923 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7924 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7925 for (p
= result
; *p
; p
++)
7926 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7927 for some locales. */
7934 /* Parse fully-specified and instantiated X11 font spec XF, and store
7935 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7936 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7937 caller must allocate at least 256 and 32 bytes respectively. For
7938 ordinary Mac fonts, the value stored to FAMILY should just be their
7939 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7940 intlfonts collection contain their charset designation in their
7941 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7942 types of font names are handled accordingly. */
7944 const int kDefaultFontSize
= 12;
7947 parse_x_font_name (xf
, family
, size
, style
, charset
)
7954 Str31 foundry
, weight
;
7955 int point_size
, avgwidth
;
7958 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7959 foundry
, family
, weight
, slant
, size
,
7960 &point_size
, &avgwidth
, charset
) != 8
7961 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7962 foundry
, family
, weight
, slant
, size
,
7963 &point_size
, &avgwidth
, charset
) != 8)
7969 *size
= point_size
/ 10;
7970 else if (avgwidth
> 0)
7971 *size
= avgwidth
/ 10;
7974 *size
= kDefaultFontSize
;
7977 if (strcmp (weight
, "bold") == 0)
7982 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7984 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7986 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7988 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7989 but take overlap into account. */
7990 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7991 memcpy (family
, foundry
, foundry_len
);
7992 family
[foundry_len
] = '-';
7993 family
[foundry_len
+ 1 + family_len
] = '-';
7994 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
8000 for (p
= family
; *p
; p
++)
8001 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8002 for some locales. */
8011 add_font_name_table_entry (char *font_name
)
8013 if (font_name_table_size
== 0)
8015 font_name_table_size
= 256;
8016 font_name_table
= (char **)
8017 xmalloc (font_name_table_size
* sizeof (char *));
8019 else if (font_name_count
+ 1 >= font_name_table_size
)
8021 font_name_table_size
*= 2;
8022 font_name_table
= (char **)
8023 xrealloc (font_name_table
,
8024 font_name_table_size
* sizeof (char *));
8027 font_name_table
[font_name_count
++] = font_name
;
8031 add_mac_font_name (name
, size
, style
, charset
)
8035 const char *charset
;
8038 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8041 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8042 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8043 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8044 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8051 fm_get_style_from_font (font
)
8055 FMFontStyle style
= normal
;
8058 FMFontFamily font_family
;
8059 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8061 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8062 some font (e.g., Optima) even if it is `bold'. */
8063 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8064 sizeof (mac_style
), &mac_style
, &len
);
8066 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8067 style
= EndianU16_BtoN (mac_style
);
8069 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8075 atsu_find_font_from_family_name (family
)
8078 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8081 Lisp_Object rest
, best
;
8082 FMFontStyle min_style
, style
;
8084 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8087 return kATSUInvalidFontID
;
8089 rest
= HASH_VALUE (h
, i
);
8090 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8091 return cons_to_long (rest
);
8093 rest
= Fnreverse (rest
);
8097 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8100 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8101 if (style
< min_style
)
8104 if (style
== normal
)
8111 while (!NILP (rest
));
8113 HASH_VALUE (h
, i
) = best
;
8114 return cons_to_long (best
);
8118 fm_style_to_face_attributes (fm_style
)
8119 FMFontStyle fm_style
;
8123 fm_style
&= (bold
| italic
);
8124 tem
= assq_no_quit (make_number (fm_style
),
8125 fm_style_face_attributes_alist
);
8129 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8130 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8131 fm_style_face_attributes_alist
=
8132 Fcons (Fcons (make_number (fm_style
), tem
),
8133 fm_style_face_attributes_alist
);
8139 atsu_find_font_family_name (font_id
)
8144 Lisp_Object family
= Qnil
;
8146 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8147 kFontMacintoshPlatform
, kFontNoScript
,
8148 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8151 family
= make_uninit_string (len
);
8152 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8153 kFontMacintoshPlatform
, kFontNoScript
,
8154 kFontNoLanguage
, len
, SDATA (family
),
8158 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8164 mac_atsu_font_face_attributes (font_id
)
8167 Lisp_Object family
, style_attrs
;
8169 family
= atsu_find_font_family_name (font_id
);
8172 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8173 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8177 /* Sets up the table font_name_table to contain the list of all fonts
8178 in the system the first time the table is used so that the Resource
8179 Manager need not be accessed every time this information is
8183 init_font_name_table ()
8185 #if TARGET_API_MAC_CARBON
8186 FMFontFamilyIterator ffi
;
8187 FMFontFamilyInstanceIterator ffii
;
8189 Lisp_Object text_encoding_info_alist
;
8190 struct gcpro gcpro1
;
8192 text_encoding_info_alist
= create_text_encoding_info_alist ();
8195 #if USE_CG_TEXT_DRAWING
8196 init_cg_text_anti_aliasing_threshold ();
8198 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8199 text_encoding_info_alist
)))
8202 struct Lisp_Hash_Table
*h
;
8204 ItemCount nfonts
, i
;
8205 ATSUFontID
*font_ids
= NULL
;
8206 Lisp_Object prev_family
= Qnil
;
8210 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8211 make_float (DEFAULT_REHASH_SIZE
),
8212 make_float (DEFAULT_REHASH_THRESHOLD
),
8214 h
= XHASH_TABLE (atsu_font_id_hash
);
8216 err
= ATSUFontCount (&nfonts
);
8219 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8220 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8223 for (i
= 0; i
< nfonts
; i
++)
8227 family
= atsu_find_font_family_name (font_ids
[i
]);
8228 if (NILP (family
) || SREF (family
, 0) == '.')
8230 if (!NILP (Fequal (prev_family
, family
)))
8231 family
= prev_family
;
8233 j
= hash_lookup (h
, family
, &hash_code
);
8236 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8237 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8240 else if (EQ (prev_family
, family
))
8241 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8243 prev_family
= family
;
8250 /* Create a dummy instance iterator here to avoid creating and
8251 destroying it in the loop. */
8252 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8254 /* Create an iterator to enumerate the font families. */
8255 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8258 FMDisposeFontFamilyInstanceIterator (&ffii
);
8262 GCPRO1 (text_encoding_info_alist
);
8264 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8270 TextEncoding encoding
;
8271 TextEncodingBase sc
;
8272 Lisp_Object text_encoding_info
, family
;
8274 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8280 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8282 sc
= GetTextEncodingBase (encoding
);
8283 text_encoding_info
= assq_no_quit (make_number (sc
),
8284 text_encoding_info_alist
);
8285 if (NILP (text_encoding_info
))
8286 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8287 text_encoding_info_alist
);
8288 decode_mac_font_name (name
, sizeof (name
),
8289 XCAR (XCDR (text_encoding_info
)));
8290 family
= build_string (name
);
8291 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8293 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8294 fm_font_family_alist
);
8296 /* Point the instance iterator at the current font family. */
8297 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8300 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8303 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8305 if (size
> 0 || style
== normal
)
8306 for (; !NILP (rest
); rest
= XCDR (rest
))
8307 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8313 /* Dispose of the iterators. */
8314 FMDisposeFontFamilyIterator (&ffi
);
8315 FMDisposeFontFamilyInstanceIterator (&ffii
);
8316 #else /* !TARGET_API_MAC_CARBON */
8318 SInt16 fontnum
, old_fontnum
;
8319 int num_mac_fonts
= CountResources('FOND');
8321 Handle font_handle
, font_handle_2
;
8322 short id
, scriptcode
;
8325 struct FontAssoc
*fat
;
8326 struct AsscEntry
*assc_entry
;
8327 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8328 struct gcpro gcpro1
;
8330 GetPort (&port
); /* save the current font number used */
8331 old_fontnum
= port
->txFont
;
8333 text_encoding_info_alist
= create_text_encoding_info_alist ();
8335 GCPRO1 (text_encoding_info_alist
);
8337 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8339 font_handle
= GetIndResource ('FOND', i
);
8343 GetResInfo (font_handle
, &id
, &type
, name
);
8344 GetFNum (name
, &fontnum
);
8346 if (fontnum
== 0 || *name
== '.')
8350 scriptcode
= FontToScript (fontnum
);
8351 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8352 text_encoding_info_alist
);
8353 if (NILP (text_encoding_info
))
8354 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8355 text_encoding_info_alist
);
8356 decode_mac_font_name (name
, sizeof (name
),
8357 XCAR (XCDR (text_encoding_info
)));
8358 family
= build_string (name
);
8359 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8361 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8362 fm_font_family_alist
);
8365 HLock (font_handle
);
8367 if (GetResourceSizeOnDisk (font_handle
)
8368 >= sizeof (struct FamRec
))
8370 fat
= (struct FontAssoc
*) (*font_handle
8371 + sizeof (struct FamRec
));
8373 = (struct AsscEntry
*) (*font_handle
8374 + sizeof (struct FamRec
)
8375 + sizeof (struct FontAssoc
));
8377 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8379 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8381 for (; !NILP (rest
); rest
= XCDR (rest
))
8382 add_mac_font_name (name
, assc_entry
->fontSize
,
8383 assc_entry
->fontStyle
,
8384 SDATA (XCAR (rest
)));
8388 HUnlock (font_handle
);
8389 font_handle_2
= GetNextFOND (font_handle
);
8390 ReleaseResource (font_handle
);
8391 font_handle
= font_handle_2
;
8393 while (ResError () == noErr
&& font_handle
);
8398 TextFont (old_fontnum
);
8399 #endif /* !TARGET_API_MAC_CARBON */
8404 mac_clear_font_name_table ()
8408 for (i
= 0; i
< font_name_count
; i
++)
8409 xfree (font_name_table
[i
]);
8410 xfree (font_name_table
);
8411 font_name_table
= NULL
;
8412 font_name_table_size
= font_name_count
= 0;
8413 fm_font_family_alist
= Qnil
;
8417 enum xlfd_scalable_field_index
8419 XLFD_SCL_PIXEL_SIZE
,
8420 XLFD_SCL_POINT_SIZE
,
8425 static const int xlfd_scalable_fields
[] =
8434 mac_do_list_fonts (pattern
, maxnames
)
8435 const char *pattern
;
8439 Lisp_Object font_list
= Qnil
;
8440 struct xlfdpat
*pat
;
8443 int scl_val
[XLFD_SCL_LAST
], *val
;
8447 if (font_name_table
== NULL
) /* Initialize when first used. */
8448 init_font_name_table ();
8450 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8453 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8454 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8455 fonts are scaled according to the specified size. */
8458 field
= xlfd_scalable_fields
;
8466 if ('0' <= *ptr
&& *ptr
<= '9')
8468 *val
= *ptr
++ - '0';
8469 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8470 *val
= *val
* 10 + *ptr
++ - '0';
8477 ptr
= strchr (ptr
, '-');
8480 while (ptr
&& i
< 14);
8482 if (i
== 14 && ptr
== NULL
)
8484 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8485 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8486 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8487 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8489 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8490 scl_val
[XLFD_SCL_POINT_SIZE
] =
8491 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8492 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8494 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8495 scl_val
[XLFD_SCL_AVGWIDTH
] =
8496 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8497 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8501 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8503 pat
= xlfdpat_create (pattern
);
8507 exact
= xlfdpat_exact_p (pat
);
8509 for (i
= 0; i
< font_name_count
; i
++)
8511 if (xlfdpat_match (pat
, font_name_table
[i
]))
8513 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8514 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8517 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8518 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8520 int former_len
= ptr
- font_name_table
[i
];
8522 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8523 memcpy (scaled
, font_name_table
[i
], former_len
);
8524 sprintf (scaled
+ former_len
,
8525 "-%d-%d-72-72-m-%d-%s",
8526 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8527 scl_val
[XLFD_SCL_POINT_SIZE
],
8528 scl_val
[XLFD_SCL_AVGWIDTH
],
8529 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8531 if (xlfdpat_match (pat
, scaled
))
8533 font_list
= Fcons (build_string (scaled
), font_list
);
8535 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8543 xlfdpat_destroy (pat
);
8548 /* Return a list of names of available fonts matching PATTERN on frame F.
8550 Frame F null means we have not yet created any frame on Mac, and
8551 consult the first display in x_display_list. MAXNAMES sets a limit
8552 on how many fonts to match. */
8555 x_list_fonts (f
, pattern
, size
, maxnames
)
8557 Lisp_Object pattern
;
8560 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8561 struct mac_display_info
*dpyinfo
8562 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8564 xassert (size
<= 0);
8566 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8567 if (NILP (patterns
))
8568 patterns
= Fcons (pattern
, Qnil
);
8570 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8572 pattern
= XCAR (patterns
);
8574 if (!STRINGP (pattern
))
8577 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8578 key
= Fcons (pattern
, make_number (maxnames
));
8580 list
= Fassoc (key
, tem
);
8583 list
= Fcdr_safe (list
);
8584 /* We have a cashed list. Don't have to get the list again. */
8589 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8592 /* MAC_TODO: add code for matching outline fonts here */
8594 /* Now store the result in the cache. */
8595 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8596 Fcons (Fcons (key
, list
),
8597 XCAR (XCDR (dpyinfo
->name_list_element
))));
8600 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8609 /* Check that FONT is valid on frame F. It is if it can be found in F's
8613 x_check_font (f
, font
)
8618 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8620 xassert (font
!= NULL
);
8622 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8623 if (dpyinfo
->font_table
[i
].name
8624 && font
== dpyinfo
->font_table
[i
].font
)
8627 xassert (i
< dpyinfo
->n_fonts
);
8630 #endif /* GLYPH_DEBUG != 0 */
8632 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8633 Note: There are (broken) X fonts out there with invalid XFontStruct
8634 min_bounds contents. For example, handa@etl.go.jp reports that
8635 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8636 have font->min_bounds.width == 0. */
8639 x_font_min_bounds (font
, w
, h
)
8640 MacFontStruct
*font
;
8643 *h
= FONT_HEIGHT (font
);
8644 *w
= font
->min_bounds
.width
;
8648 /* Compute the smallest character width and smallest font height over
8649 all fonts available on frame F. Set the members smallest_char_width
8650 and smallest_font_height in F's x_display_info structure to
8651 the values computed. Value is non-zero if smallest_font_height or
8652 smallest_char_width become smaller than they were before. */
8655 x_compute_min_glyph_bounds (f
)
8659 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8660 MacFontStruct
*font
;
8661 int old_width
= dpyinfo
->smallest_char_width
;
8662 int old_height
= dpyinfo
->smallest_font_height
;
8664 dpyinfo
->smallest_font_height
= 100000;
8665 dpyinfo
->smallest_char_width
= 100000;
8667 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8668 if (dpyinfo
->font_table
[i
].name
)
8670 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8673 font
= (MacFontStruct
*) fontp
->font
;
8674 xassert (font
!= (MacFontStruct
*) ~0);
8675 x_font_min_bounds (font
, &w
, &h
);
8677 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8678 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8681 xassert (dpyinfo
->smallest_char_width
> 0
8682 && dpyinfo
->smallest_font_height
> 0);
8684 return (dpyinfo
->n_fonts
== 1
8685 || dpyinfo
->smallest_char_width
< old_width
8686 || dpyinfo
->smallest_font_height
< old_height
);
8690 /* Determine whether given string is a fully-specified XLFD: all 14
8691 fields are present, none is '*'. */
8694 is_fully_specified_xlfd (p
)
8703 for (i
= 0; i
< 13; i
++)
8705 q
= strchr (p
+ 1, '-');
8708 if (q
- p
== 2 && *(p
+ 1) == '*')
8713 if (strchr (p
+ 1, '-') != NULL
)
8716 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8723 /* mac_load_query_font creates and returns an internal representation
8724 for a font in a MacFontStruct struct. There is really no concept
8725 corresponding to "loading" a font on the Mac. But we check its
8726 existence and find the font number and all other information for it
8727 and store them in the returned MacFontStruct. */
8729 static MacFontStruct
*
8730 mac_load_query_font (f
, fontname
)
8740 static ATSUFontID font_id
;
8741 ATSUStyle mac_style
= NULL
;
8744 #if TARGET_API_MAC_CARBON
8745 TextEncoding encoding
;
8750 MacFontStruct
*font
;
8751 XCharStruct
*space_bounds
= NULL
, *pcm
;
8753 if (is_fully_specified_xlfd (fontname
))
8757 Lisp_Object matched_fonts
;
8759 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8760 if (NILP (matched_fonts
))
8762 name
= SDATA (XCAR (matched_fonts
));
8765 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8769 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8772 static const ATSUAttributeTag tags
[] =
8773 {kATSUFontTag
, kATSUSizeTag
,
8774 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8775 static const ByteCount sizes
[] =
8776 {sizeof (ATSUFontID
), sizeof (Fixed
),
8777 sizeof (Boolean
), sizeof (Boolean
)};
8778 static Fixed size_fixed
;
8779 static Boolean bold_p
, italic_p
;
8780 static const ATSUAttributeValuePtr values
[] =
8781 {&font_id
, &size_fixed
,
8782 &bold_p
, &italic_p
};
8783 static const ATSUFontFeatureType types
[] =
8784 {kAllTypographicFeaturesType
, kDiacriticsType
};
8785 static const ATSUFontFeatureSelector selectors
[] =
8786 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8789 font_id
= atsu_find_font_from_family_name (family
);
8790 if (font_id
== kATSUInvalidFontID
)
8792 size_fixed
= Long2Fix (size
);
8793 bold_p
= (fontface
& bold
) != 0;
8794 italic_p
= (fontface
& italic
) != 0;
8795 err
= ATSUCreateStyle (&mac_style
);
8798 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8802 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8803 tags
, sizes
, values
);
8806 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8809 scriptcode
= kTextEncodingMacUnicode
;
8814 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8818 fontnum
= XINT (XCDR (tmp
));
8819 #if TARGET_API_MAC_CARBON
8820 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8822 scriptcode
= GetTextEncodingBase (encoding
);
8824 scriptcode
= FontToScript (fontnum
);
8828 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8830 font
->mac_fontnum
= fontnum
;
8831 font
->mac_fontsize
= size
;
8832 font
->mac_fontface
= fontface
;
8833 font
->mac_scriptcode
= scriptcode
;
8835 font
->mac_style
= mac_style
;
8836 #if USE_CG_TEXT_DRAWING
8837 font
->cg_font
= NULL
;
8838 font
->cg_glyphs
= NULL
;
8842 /* Apple Japanese (SJIS) font is listed as both
8843 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8844 (Roman script) in init_font_name_table (). The latter should be
8845 treated as a one-byte font. */
8846 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8847 font
->mac_scriptcode
= smRoman
;
8849 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8852 if (font
->mac_style
)
8857 font
->min_byte1
= 0;
8858 font
->max_byte1
= 0xff;
8859 font
->min_char_or_byte2
= 0;
8860 font
->max_char_or_byte2
= 0xff;
8862 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8863 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8864 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8865 pcm_init (font
->bounds
.rows
[0], 0x100);
8867 #if USE_CG_TEXT_DRAWING
8871 ATSFontRef ats_font
;
8873 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8875 /* Use CG text drawing if italic/bold is not synthesized. */
8876 if (err
== noErr
&& style
== fontface
)
8878 ats_font
= FMGetATSFontRefFromFont (font_id
);
8879 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8885 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8886 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8889 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8890 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8891 &font
->ascent
, &font
->descent
,
8893 #if USE_CG_TEXT_DRAWING
8894 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8901 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8903 mac_unload_font (&one_mac_display_info
, font
);
8907 pcm
= font
->bounds
.rows
[0];
8908 for (c
= 0x21; c
<= 0xff; c
++)
8911 /* Soft hyphen is not supported in ATSUI. */
8915 #if USE_CG_TEXT_DRAWING
8916 if (font
->cg_glyphs
)
8926 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8927 pcm
? pcm
+ c
: NULL
,
8928 #if USE_CG_TEXT_DRAWING
8929 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8936 #if USE_CG_TEXT_DRAWING
8937 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8939 /* Don't use CG text drawing if font substitution occurs in
8940 ASCII or Latin-1 characters. */
8941 CGFontRelease (font
->cg_font
);
8942 font
->cg_font
= NULL
;
8943 xfree (font
->cg_glyphs
);
8944 font
->cg_glyphs
= NULL
;
8955 FontInfo the_fontinfo
;
8956 int is_two_byte_font
;
8959 mac_prepare_for_quickdraw (f
);
8961 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8965 TextFace (fontface
);
8967 GetFontInfo (&the_fontinfo
);
8969 font
->ascent
= the_fontinfo
.ascent
;
8970 font
->descent
= the_fontinfo
.descent
;
8972 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8973 || font
->mac_scriptcode
== smTradChinese
8974 || font
->mac_scriptcode
== smSimpChinese
8975 || font
->mac_scriptcode
== smKorean
);
8977 if (is_two_byte_font
)
8981 font
->min_byte1
= 0xa1;
8982 font
->max_byte1
= 0xfe;
8983 font
->min_char_or_byte2
= 0xa1;
8984 font
->max_char_or_byte2
= 0xfe;
8986 /* Use the width of an "ideographic space" of that font
8987 because the_fontinfo.widMax returns the wrong width for
8989 switch (font
->mac_scriptcode
)
8992 font
->min_byte1
= 0x81;
8993 font
->max_byte1
= 0xfc;
8994 font
->min_char_or_byte2
= 0x40;
8995 font
->max_char_or_byte2
= 0xfc;
8996 char_width
= StringWidth("\p\x81\x40");
8999 font
->min_char_or_byte2
= 0x40;
9000 char_width
= StringWidth("\p\xa1\x40");
9003 char_width
= StringWidth("\p\xa1\xa1");
9006 char_width
= StringWidth("\p\xa1\xa1");
9010 font
->bounds
.per_char
= NULL
;
9012 if (fontface
& italic
)
9013 font
->max_bounds
.rbearing
= char_width
+ 1;
9015 font
->max_bounds
.rbearing
= char_width
;
9016 font
->max_bounds
.lbearing
= 0;
9017 font
->max_bounds
.width
= char_width
;
9018 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
9019 font
->max_bounds
.descent
= the_fontinfo
.descent
;
9021 font
->min_bounds
= font
->max_bounds
;
9027 font
->min_byte1
= font
->max_byte1
= 0;
9028 font
->min_char_or_byte2
= 0x20;
9029 font
->max_char_or_byte2
= 0xff;
9031 font
->bounds
.per_char
=
9032 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9033 bzero (font
->bounds
.per_char
,
9034 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9036 space_bounds
= font
->bounds
.per_char
;
9037 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9038 &font
->descent
, space_bounds
, NULL
);
9039 if (err
!= noErr
|| space_bounds
->width
<= 0)
9041 mac_unload_font (&one_mac_display_info
, font
);
9045 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9046 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9054 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9055 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9058 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9060 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9062 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9064 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9066 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9069 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9071 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9073 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9075 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9077 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9082 font
->mac_style
== NULL
&&
9084 font
->max_bounds
.width
== font
->min_bounds
.width
9085 && font
->min_bounds
.lbearing
>= 0
9086 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9088 /* Fixed width and no overhangs. */
9089 xfree (font
->bounds
.per_char
);
9090 font
->bounds
.per_char
= NULL
;
9094 #if !defined (MAC_OS8) || USE_ATSUI
9095 /* AppKit and WebKit do some adjustment to the heights of Courier,
9096 Helvetica, and Times. This only works on the environments where
9097 srcCopy text transfer mode is never used. */
9099 #ifdef MAC_OS8 /* implies USE_ATSUI */
9102 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9103 || strcmp (family
, "times") == 0))
9104 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9112 mac_unload_font (dpyinfo
, font
)
9113 struct mac_display_info
*dpyinfo
;
9116 xfree (font
->full_name
);
9118 if (font
->mac_style
)
9122 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9123 if (font
->bounds
.rows
[i
])
9124 xfree (font
->bounds
.rows
[i
]);
9125 xfree (font
->bounds
.rows
);
9126 ATSUDisposeStyle (font
->mac_style
);
9130 if (font
->bounds
.per_char
)
9131 xfree (font
->bounds
.per_char
);
9132 #if USE_CG_TEXT_DRAWING
9134 CGFontRelease (font
->cg_font
);
9135 if (font
->cg_glyphs
)
9136 xfree (font
->cg_glyphs
);
9142 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9143 pointer to the structure font_info while allocating it dynamically.
9144 If SIZE is 0, load any size of font.
9145 If loading is failed, return NULL. */
9148 x_load_font (f
, fontname
, size
)
9150 register char *fontname
;
9153 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9154 Lisp_Object font_names
;
9156 /* Get a list of all the fonts that match this name. Once we
9157 have a list of matching fonts, we compare them against the fonts
9158 we already have by comparing names. */
9159 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9161 if (!NILP (font_names
))
9166 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9167 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9168 if (dpyinfo
->font_table
[i
].name
9169 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9170 SDATA (XCAR (tail
)))
9171 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9172 SDATA (XCAR (tail
)))))
9173 return (dpyinfo
->font_table
+ i
);
9178 /* Load the font and add it to the table. */
9180 struct MacFontStruct
*font
;
9181 struct font_info
*fontp
;
9184 fontname
= (char *) SDATA (XCAR (font_names
));
9187 font
= mac_load_query_font (f
, fontname
);
9192 /* Find a free slot in the font table. */
9193 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9194 if (dpyinfo
->font_table
[i
].name
== NULL
)
9197 /* If no free slot found, maybe enlarge the font table. */
9198 if (i
== dpyinfo
->n_fonts
9199 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9202 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9203 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9205 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9208 fontp
= dpyinfo
->font_table
+ i
;
9209 if (i
== dpyinfo
->n_fonts
)
9212 /* Now fill in the slots of *FONTP. */
9214 bzero (fontp
, sizeof (*fontp
));
9216 fontp
->font_idx
= i
;
9217 fontp
->charset
= -1; /* fs_load_font sets it. */
9218 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9219 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9221 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9223 /* Fixed width font. */
9224 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9231 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9232 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9234 fontp
->space_width
= pcm
->width
;
9236 fontp
->space_width
= FONT_WIDTH (font
);
9240 int width
= pcm
->width
;
9241 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9242 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9243 width
+= pcm
->width
;
9244 fontp
->average_width
= width
/ 95;
9247 fontp
->average_width
= FONT_WIDTH (font
);
9250 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9251 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9253 fontp
->size
= font
->max_bounds
.width
;
9254 fontp
->height
= FONT_HEIGHT (font
);
9256 /* For some font, ascent and descent in max_bounds field is
9257 larger than the above value. */
9258 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9259 if (max_height
> fontp
->height
)
9260 fontp
->height
= max_height
;
9263 /* MAC_TODO: The script encoding is irrelevant in unicode? */
9264 /* The slot `encoding' specifies how to map a character
9265 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9266 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9267 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9268 2:0xA020..0xFF7F). For the moment, we don't know which charset
9269 uses this font. So, we set information in fontp->encoding_type
9270 which is never used by any charset. If mapping can't be
9271 decided, set FONT_ENCODING_NOT_DECIDED. */
9272 if (font
->mac_scriptcode
== smJapanese
)
9273 fontp
->encoding_type
= 4;
9276 fontp
->encoding_type
9277 = (font
->max_byte1
== 0
9279 ? (font
->min_char_or_byte2
< 0x80
9280 ? (font
->max_char_or_byte2
< 0x80
9281 ? 0 /* 0x20..0x7F */
9282 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9283 : 1) /* 0xA0..0xFF */
9285 : (font
->min_byte1
< 0x80
9286 ? (font
->max_byte1
< 0x80
9287 ? (font
->min_char_or_byte2
< 0x80
9288 ? (font
->max_char_or_byte2
< 0x80
9289 ? 0 /* 0x2020..0x7F7F */
9290 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9291 : 3) /* 0x20A0..0x7FFF */
9292 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9293 : (font
->min_char_or_byte2
< 0x80
9294 ? (font
->max_char_or_byte2
< 0x80
9295 ? 2 /* 0xA020..0xFF7F */
9296 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9297 : 1))); /* 0xA0A0..0xFFFF */
9300 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9301 fontp
->baseline_offset
9302 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9303 ? (long) value
: 0);
9304 fontp
->relative_compose
9305 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9306 ? (long) value
: 0);
9307 fontp
->default_ascent
9308 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9309 ? (long) value
: 0);
9311 fontp
->baseline_offset
= 0;
9312 fontp
->relative_compose
= 0;
9313 fontp
->default_ascent
= 0;
9316 /* Set global flag fonts_changed_p to non-zero if the font loaded
9317 has a character with a smaller width than any other character
9318 before, or if the font loaded has a smaller height than any
9319 other font loaded before. If this happens, it will make a
9320 glyph matrix reallocation necessary. */
9321 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9328 /* Return a pointer to struct font_info of a font named FONTNAME for
9329 frame F. If no such font is loaded, return NULL. */
9332 x_query_font (f
, fontname
)
9334 register char *fontname
;
9336 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9339 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9340 if (dpyinfo
->font_table
[i
].name
9341 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9342 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9343 return (dpyinfo
->font_table
+ i
);
9348 /* Find a CCL program for a font specified by FONTP, and set the member
9349 `encoder' of the structure. */
9352 x_find_ccl_program (fontp
)
9353 struct font_info
*fontp
;
9355 Lisp_Object list
, elt
;
9357 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9361 && STRINGP (XCAR (elt
))
9362 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9368 struct ccl_program
*ccl
9369 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9371 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9374 fontp
->font_encoder
= ccl
;
9378 #if USE_MAC_FONT_PANEL
9379 /* Whether Font Panel has been shown before. The first call to font
9380 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9381 slow. This variable is used for deferring such a call as much as
9383 static int font_panel_shown_p
= 0;
9385 extern Lisp_Object Qfont
;
9386 static Lisp_Object Qpanel_closed
, Qselection
;
9388 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9392 const EventParamName
*,
9393 const EventParamType
*));
9396 mac_font_panel_visible_p ()
9398 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9401 static pascal OSStatus
9402 mac_handle_font_event (next_handler
, event
, data
)
9403 EventHandlerCallRef next_handler
;
9407 OSStatus result
, err
;
9410 const EventParamName
*names
;
9411 const EventParamType
*types
;
9412 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9413 kEventParamATSUFontSize
,
9414 kEventParamFMFontFamily
,
9415 kEventParamFMFontSize
,
9416 kEventParamFontColor
};
9417 static const EventParamType types_sel
[] = {typeATSUFontID
,
9423 result
= CallNextEventHandler (next_handler
, event
);
9424 if (result
!= eventNotHandledErr
)
9427 switch (GetEventKind (event
))
9429 case kEventFontPanelClosed
:
9430 id_key
= Qpanel_closed
;
9436 case kEventFontSelection
:
9437 id_key
= Qselection
;
9438 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9444 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9454 mac_show_hide_font_panel ()
9456 if (!font_panel_shown_p
)
9460 static const EventTypeSpec specs
[] =
9461 {{kEventClassFont
, kEventFontPanelClosed
},
9462 {kEventClassFont
, kEventFontSelection
}};
9464 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9465 GetEventTypeCount (specs
),
9470 font_panel_shown_p
= 1;
9473 return FPShowHideFontPanel ();
9477 mac_set_font_info_for_selection (f
, face_id
, c
)
9482 EventTargetRef target
= NULL
;
9483 XFontStruct
*font
= NULL
;
9485 if (!mac_font_panel_visible_p ())
9490 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9492 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9496 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9497 face
= FACE_FROM_ID (f
, face_id
);
9503 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9506 if (font
->mac_fontnum
!= -1)
9508 FontSelectionQDStyle qd_style
;
9510 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9511 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9512 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9513 qd_style
.size
= font
->mac_fontsize
;
9514 qd_style
.hasColor
= false;
9516 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9517 1, &qd_style
, target
);
9520 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9521 1, &font
->mac_style
, target
);
9529 /* The Mac Event loop code */
9531 #if !TARGET_API_MAC_CARBON
9533 #include <Quickdraw.h>
9534 #include <Balloons.h>
9535 #include <Devices.h>
9537 #include <Gestalt.h>
9539 #include <Processes.h>
9541 #include <ToolUtils.h>
9542 #include <TextUtils.h>
9543 #include <Dialogs.h>
9546 #include <Resources.h>
9551 #endif /* ! TARGET_API_MAC_CARBON */
9556 #define DEFAULT_NUM_COLS 80
9558 #define MIN_DOC_SIZE 64
9559 #define MAX_DOC_SIZE 32767
9561 #define EXTRA_STACK_ALLOC (256 * 1024)
9563 #define ARGV_STRING_LIST_ID 129
9564 #define ABOUT_ALERT_ID 128
9565 #define RAM_TOO_LARGE_ALERT_ID 129
9567 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9568 Lisp_Object Qreverse
;
9571 /* Modifier associated with the control key, or nil to ignore. */
9572 Lisp_Object Vmac_control_modifier
;
9574 /* Modifier associated with the option key, or nil to ignore. */
9575 Lisp_Object Vmac_option_modifier
;
9577 /* Modifier associated with the command key, or nil to ignore. */
9578 Lisp_Object Vmac_command_modifier
;
9580 /* Modifier associated with the function key, or nil to ignore. */
9581 Lisp_Object Vmac_function_modifier
;
9583 /* True if the option and command modifiers should be used to emulate
9584 a three button mouse */
9585 Lisp_Object Vmac_emulate_three_button_mouse
;
9587 #if TARGET_API_MAC_CARBON
9588 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9589 mouse-2, instead of mouse-3. */
9590 int mac_wheel_button_is_mouse_2
;
9592 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9593 for processing before Emacs sees it. */
9594 int mac_pass_command_to_system
;
9596 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9597 for processing before Emacs sees it. */
9598 int mac_pass_control_to_system
;
9601 /* Points to the variable `inev' in the function XTread_socket. It is
9602 used for passing an input event to the function back from
9603 Carbon/Apple event handlers. */
9604 static struct input_event
*read_socket_inev
= NULL
;
9606 /* Whether or not the screen configuration has changed. */
9607 static int mac_screen_config_changed
= 0;
9609 Point saved_menu_event_location
;
9612 #if TARGET_API_MAC_CARBON
9613 static Lisp_Object Qhi_command
;
9615 extern Lisp_Object Qwindow
;
9616 static Lisp_Object Qtoolbar_switch_mode
;
9619 static TSMDocumentID tsm_document_id
;
9620 static Lisp_Object Qtext_input
;
9621 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9622 static Lisp_Object Vmac_ts_active_input_overlay
;
9623 extern Lisp_Object Qbefore_string
;
9624 static Lisp_Object Vmac_ts_script_language_on_focus
;
9625 static Lisp_Object saved_ts_script_language_on_focus
;
9626 static ScriptLanguageRecord saved_ts_language
;
9627 static Component saved_ts_component
;
9629 #endif /* TARGET_API_MAC_CARBON */
9630 extern int mac_ready_for_apple_events
;
9631 extern Lisp_Object Qundefined
;
9632 extern void init_apple_event_handler
P_ ((void));
9633 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9634 Lisp_Object
*, Lisp_Object
*,
9636 extern OSErr init_coercion_handler
P_ ((void));
9639 extern OSErr install_drag_handler
P_ ((WindowRef
));
9640 extern void remove_drag_handler
P_ ((WindowRef
));
9642 #if TARGET_API_MAC_CARBON
9643 /* Showing help echo string during menu tracking */
9644 extern OSStatus install_menu_target_item_handler
P_ ((void));
9647 extern OSStatus
install_service_handler ();
9648 static Lisp_Object Qservice
, Qpaste
, Qperform
;
9652 extern void init_emacs_passwd_dir ();
9653 extern int emacs_main (int, char **, char **);
9655 extern void initialize_applescript();
9656 extern void terminate_applescript();
9658 /* Table for translating Mac keycode to X keysym values. Contributed
9660 Mapping for special keys is now identical to that in Apple X11
9661 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9662 on the right of the Cmd key on laptops, and fn + `enter' (->
9664 static const unsigned char keycode_to_xkeysym_table
[] = {
9665 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9666 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9667 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9669 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9670 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9671 /*0x38*/ 0, 0, 0, 0,
9672 /*0x3C*/ 0, 0, 0, 0,
9674 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9675 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9676 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9677 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9679 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9680 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9681 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9682 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9684 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9685 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9686 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9687 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9689 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9690 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9691 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9692 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9696 /* Table for translating Mac keycode with the laptop `fn' key to that
9697 without it. Destination symbols in comments are keys on US
9698 keyboard, and they may not be the same on other types of keyboards.
9699 If the destination is identical to the source (f1 ... f12), it
9700 doesn't map `fn' key to a modifier. */
9701 static const unsigned char fn_keycode_to_keycode_table
[] = {
9702 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9703 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9704 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9706 /*0x30*/ 0, 0, 0, 0,
9707 /*0x34*/ 0, 0, 0, 0,
9708 /*0x38*/ 0, 0, 0, 0,
9709 /*0x3C*/ 0, 0, 0, 0,
9711 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9712 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9713 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9714 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9716 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9717 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9718 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9719 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9721 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9722 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9723 /*0x68*/ 0, 0, 0, 0,
9724 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9726 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9727 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9728 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9731 #endif /* MAC_OSX */
9734 #if TARGET_API_MAC_CARBON
9735 mac_to_emacs_modifiers (UInt32 mods
)
9737 mac_to_emacs_modifiers (EventModifiers mods
)
9740 unsigned int result
= 0;
9741 if (mods
& shiftKey
)
9742 result
|= shift_modifier
;
9744 /* Deactivated to simplify configuration:
9745 if Vmac_option_modifier is non-NIL, we fully process the Option
9746 key. Otherwise, we only process it if an additional Ctrl or Command
9747 is pressed. That way the system may convert the character to a
9749 if ((mods & optionKey) &&
9750 (( !NILP(Vmac_option_modifier) ||
9751 ((mods & cmdKey) || (mods & controlKey))))) */
9753 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9754 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9756 result
|= XUINT(val
);
9758 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9759 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9761 result
|= XUINT(val
);
9763 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9764 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9766 result
|= XUINT(val
);
9770 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9771 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9773 result
|= XUINT(val
);
9781 mac_mapped_modifiers (modifiers
)
9784 UInt32 mapped_modifiers_all
=
9785 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9786 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9787 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9790 mapped_modifiers_all
|=
9791 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9794 return mapped_modifiers_all
& modifiers
;
9798 mac_get_emulated_btn ( UInt32 modifiers
)
9801 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9802 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9803 if (modifiers
& cmdKey
)
9804 result
= cmdIs3
? 2 : 1;
9805 else if (modifiers
& optionKey
)
9806 result
= cmdIs3
? 1 : 2;
9811 #if TARGET_API_MAC_CARBON
9812 /***** Code to handle C-g testing *****/
9813 extern int quit_char
;
9814 extern int make_ctrl_char
P_ ((int));
9817 mac_quit_char_key_p (modifiers
, key_code
)
9818 UInt32 modifiers
, key_code
;
9821 unsigned long some_state
= 0;
9822 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9823 int c
, emacs_modifiers
;
9825 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9826 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9827 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9828 if (char_code
& ~0xff)
9831 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9832 if (emacs_modifiers
& ctrl_modifier
)
9833 c
= make_ctrl_char (char_code
);
9835 c
|= (emacs_modifiers
9836 & (meta_modifier
| alt_modifier
9837 | hyper_modifier
| super_modifier
));
9839 return c
== quit_char
;
9843 #if TARGET_API_MAC_CARBON
9844 /* Obtains the event modifiers from the event ref and then calls
9845 mac_to_emacs_modifiers. */
9847 mac_event_to_emacs_modifiers (EventRef eventRef
)
9849 UInt32 mods
= 0, class;
9851 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9852 sizeof (UInt32
), NULL
, &mods
);
9853 class = GetEventClass (eventRef
);
9854 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9855 (class == kEventClassMouse
|| class == kEventClassCommand
))
9857 mods
&= ~(optionKey
| cmdKey
);
9859 return mac_to_emacs_modifiers (mods
);
9862 /* Given an event ref, return the code to use for the mouse button
9863 code in the emacs input_event. */
9865 mac_get_mouse_btn (EventRef ref
)
9867 EventMouseButton result
= kEventMouseButtonPrimary
;
9868 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9869 sizeof (EventMouseButton
), NULL
, &result
);
9872 case kEventMouseButtonPrimary
:
9873 if (NILP (Vmac_emulate_three_button_mouse
))
9877 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9878 sizeof (UInt32
), NULL
, &mods
);
9879 return mac_get_emulated_btn(mods
);
9881 case kEventMouseButtonSecondary
:
9882 return mac_wheel_button_is_mouse_2
? 2 : 1;
9883 case kEventMouseButtonTertiary
:
9884 case 4: /* 4 is the number for the mouse wheel button */
9885 return mac_wheel_button_is_mouse_2
? 1 : 2;
9891 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9892 events. However the click of the mouse wheel is not converted to a
9893 mouseDown or mouseUp event. Likewise for dead key events. This
9894 calls ConvertEventRefToEventRecord, but then checks to see if it is
9895 a mouse up/down, or a dead key Carbon event that has not been
9896 converted, and if so, converts it by hand (to be picked up in the
9897 XTread_socket loop). */
9898 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9901 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9907 switch (GetEventClass (eventRef
))
9909 case kEventClassMouse
:
9910 switch (GetEventKind (eventRef
))
9912 case kEventMouseDown
:
9913 eventRec
->what
= mouseDown
;
9918 eventRec
->what
= mouseUp
;
9927 case kEventClassKeyboard
:
9928 switch (GetEventKind (eventRef
))
9930 case kEventRawKeyDown
:
9932 goto keystroke_common
;
9933 case kEventRawKeyRepeat
:
9935 goto keystroke_common
;
9936 case kEventRawKeyUp
:
9940 unsigned char char_codes
;
9943 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9944 typeChar
, NULL
, sizeof (char),
9947 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9948 typeUInt32
, NULL
, sizeof (UInt32
),
9952 eventRec
->what
= action
;
9953 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9970 /* Need where and when. */
9973 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9974 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9975 /* Use two step process because new event modifiers are 32-bit
9976 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9977 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9978 NULL
, sizeof (UInt32
), NULL
, &mods
);
9979 eventRec
->modifiers
= mods
;
9981 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9993 Handle menubar_handle
;
9996 menubar_handle
= GetNewMBar (128);
9997 if(menubar_handle
== NULL
)
9999 SetMenuBar (menubar_handle
);
10002 #if !TARGET_API_MAC_CARBON
10003 menu
= GetMenuRef (M_APPLE
);
10005 AppendResMenu (menu
, 'DRVR');
10013 do_init_managers (void)
10015 #if !TARGET_API_MAC_CARBON
10016 InitGraf (&qd
.thePort
);
10018 FlushEvents (everyEvent
, 0);
10022 InitDialogs (NULL
);
10023 #endif /* !TARGET_API_MAC_CARBON */
10026 #if !TARGET_API_MAC_CARBON
10027 /* set up some extra stack space for use by emacs */
10028 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10030 /* MaxApplZone must be called for AppleScript to execute more
10031 complicated scripts */
10034 #endif /* !TARGET_API_MAC_CARBON */
10038 do_check_ram_size (void)
10040 SInt32 physical_ram_size
, logical_ram_size
;
10042 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10043 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10044 || physical_ram_size
> (1 << VALBITS
)
10045 || logical_ram_size
> (1 << VALBITS
))
10047 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10051 #endif /* MAC_OS8 */
10054 do_window_update (WindowRef win
)
10056 struct frame
*f
= mac_window_to_frame (win
);
10060 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10062 if (win
!= tip_window
)
10064 if (f
->async_visible
== 0)
10066 /* Update events may occur when a frame gets iconified. */
10068 f
->async_visible
= 1;
10069 f
->async_iconified
= 0;
10070 SET_FRAME_GARBAGED (f
);
10076 #if TARGET_API_MAC_CARBON
10077 RgnHandle region
= NewRgn ();
10079 GetPortVisibleRegion (GetWindowPort (win
), region
);
10080 GetRegionBounds (region
, &r
);
10081 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10083 mac_prepare_for_quickdraw (f
);
10085 UpdateControls (win
, region
);
10086 DisposeRgn (region
);
10088 r
= (*win
->visRgn
)->rgnBBox
;
10089 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10090 UpdateControls (win
, win
->visRgn
);
10099 is_emacs_window (WindowRef win
)
10101 Lisp_Object tail
, frame
;
10106 FOR_EACH_FRAME (tail
, frame
)
10107 if (FRAME_MAC_P (XFRAME (frame
)))
10108 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10119 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10121 err
= ActivateTSMDocument (tsm_document_id
);
10125 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10126 && EQ (saved_ts_script_language_on_focus
, Qt
))
10127 slptr
= &saved_ts_language
;
10128 else if (CONSP (Vmac_ts_script_language_on_focus
)
10129 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10130 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10131 && CONSP (saved_ts_script_language_on_focus
)
10132 && EQ (XCAR (saved_ts_script_language_on_focus
),
10133 XCAR (Vmac_ts_script_language_on_focus
))
10134 && EQ (XCDR (saved_ts_script_language_on_focus
),
10135 XCDR (Vmac_ts_script_language_on_focus
)))
10137 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10138 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10145 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10146 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10147 kKeyboardInputMethodClass
);
10149 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10152 err
= SetTextServiceLanguage (slptr
);
10154 /* Seems to be needed on Mac OS X 10.2. */
10156 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10166 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10168 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10170 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10172 err
= GetTextServiceLanguage (&saved_ts_language
);
10174 slptr
= &saved_ts_language
;
10176 else if (CONSP (Vmac_ts_script_language_on_focus
)
10177 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10178 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10180 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10181 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10187 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10188 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10189 kKeyboardInputMethodClass
);
10191 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10195 err
= DeactivateTSMDocument (tsm_document_id
);
10201 #if !TARGET_API_MAC_CARBON
10203 do_apple_menu (SInt16 menu_item
)
10206 SInt16 da_driver_refnum
;
10208 if (menu_item
== I_ABOUT
)
10209 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10212 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10213 da_driver_refnum
= OpenDeskAcc (item_name
);
10216 #endif /* !TARGET_API_MAC_CARBON */
10218 /* Handle drags in size box. Based on code contributed by Ben
10219 Mesander and IM - Window Manager A. */
10222 do_grow_window (w
, e
)
10224 const EventRecord
*e
;
10227 int rows
, columns
, width
, height
;
10228 struct frame
*f
= mac_window_to_frame (w
);
10229 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10230 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10231 #if TARGET_API_MAC_CARBON
10237 if (size_hints
->flags
& PMinSize
)
10239 min_width
= size_hints
->min_width
;
10240 min_height
= size_hints
->min_height
;
10242 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10244 #if TARGET_API_MAC_CARBON
10245 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10247 height
= new_rect
.bottom
- new_rect
.top
;
10248 width
= new_rect
.right
- new_rect
.left
;
10250 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10251 /* see if it really changed size */
10252 if (grow_size
== 0)
10254 height
= HiWord (grow_size
);
10255 width
= LoWord (grow_size
);
10258 if (width
!= FRAME_PIXEL_WIDTH (f
)
10259 || height
!= FRAME_PIXEL_HEIGHT (f
))
10261 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10262 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10264 x_set_window_size (f
, 0, columns
, rows
);
10269 #if TARGET_API_MAC_CARBON
10271 mac_get_ideal_size (f
)
10274 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10275 WindowRef w
= FRAME_MAC_WINDOW (f
);
10277 Rect standard_rect
;
10278 int height
, width
, columns
, rows
;
10280 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10281 ideal_size
.v
= dpyinfo
->height
;
10282 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10283 /* Adjust the standard size according to character boundaries. */
10284 width
= standard_rect
.right
- standard_rect
.left
;
10285 height
= standard_rect
.bottom
- standard_rect
.top
;
10286 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10287 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10288 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10289 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10295 /* Handle clicks in zoom box. Calculation of "standard state" based
10296 on code in IM - Window Manager A and code contributed by Ben
10297 Mesander. The standard state of an Emacs window is 80-characters
10298 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10301 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10303 Rect zoom_rect
, port_rect
;
10305 struct frame
*f
= mac_window_to_frame (w
);
10306 #if TARGET_API_MAC_CARBON
10307 Point ideal_size
= mac_get_ideal_size (f
);
10309 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10310 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10311 && port_rect
.left
== zoom_rect
.left
10312 && port_rect
.top
== zoom_rect
.top
)
10313 zoom_in_or_out
= inZoomIn
;
10315 zoom_in_or_out
= inZoomOut
;
10318 mac_clear_window (f
);
10320 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10321 #else /* not TARGET_API_MAC_CARBON */
10324 int w_title_height
, rows
;
10325 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10327 GetPort (&save_port
);
10329 SetPortWindowPort (w
);
10331 /* Clear window to avoid flicker. */
10332 EraseRect (&(w
->portRect
));
10333 if (zoom_in_or_out
== inZoomOut
)
10335 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10336 LocalToGlobal (&top_left
);
10338 /* calculate height of window's title bar */
10339 w_title_height
= top_left
.v
- 1
10340 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10342 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10343 zoom_rect
= qd
.screenBits
.bounds
;
10344 zoom_rect
.top
+= w_title_height
;
10345 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10347 zoom_rect
.right
= zoom_rect
.left
10348 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10350 /* Adjust the standard size according to character boundaries. */
10351 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10353 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10355 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10359 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10361 SetPort (save_port
);
10362 #endif /* not TARGET_API_MAC_CARBON */
10364 #if !TARGET_API_MAC_CARBON
10365 /* retrieve window size and update application values */
10366 port_rect
= w
->portRect
;
10367 height
= port_rect
.bottom
- port_rect
.top
;
10368 width
= port_rect
.right
- port_rect
.left
;
10370 mac_handle_size_change (f
, width
, height
);
10371 mac_handle_origin_change (f
);
10376 mac_set_unicode_keystroke_event (code
, buf
)
10378 struct input_event
*buf
;
10380 int charset_id
, c1
, c2
;
10384 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10387 else if (code
< 0x100)
10390 charset_id
= CHARSET_8_BIT_CONTROL
;
10392 charset_id
= charset_latin_iso8859_1
;
10393 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10394 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10399 charset_id
= charset_mule_unicode_0100_24ff
,
10401 else if (code
< 0x33FF)
10402 charset_id
= charset_mule_unicode_2500_33ff
,
10404 else if (code
>= 0xE000)
10405 charset_id
= charset_mule_unicode_e000_ffff
,
10407 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10408 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10409 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10414 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10416 unsigned char char_code
;
10417 UInt32 key_code
, modifiers
;
10418 unsigned long timestamp
;
10419 struct input_event
*buf
;
10421 static SInt16 last_key_script
= -1;
10422 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10423 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10426 if (mapped_modifiers
& kEventKeyModifierFnMask
10427 && key_code
<= 0x7f
10428 && fn_keycode_to_keycode_table
[key_code
])
10429 key_code
= fn_keycode_to_keycode_table
[key_code
];
10432 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10434 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10435 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10437 if (modifiers
& kEventKeyModifierFnMask
10438 && key_code
<= 0x7f
10439 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10440 modifiers
&= ~kEventKeyModifierFnMask
;
10443 else if (mapped_modifiers
)
10445 /* translate the keycode back to determine the original key */
10447 UCKeyboardLayout
*uchr_ptr
= NULL
;
10448 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10450 KeyboardLayoutRef layout
;
10452 err
= KLGetCurrentKeyboardLayout (&layout
);
10454 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10455 (const void **) &uchr_ptr
);
10457 static SInt16 last_key_layout_id
= 0;
10458 static Handle uchr_handle
= (Handle
)-1;
10459 SInt16 current_key_layout_id
=
10460 GetScriptVariable (current_key_script
, smScriptKeys
);
10462 if (uchr_handle
== (Handle
)-1
10463 || last_key_layout_id
!= current_key_layout_id
)
10465 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10466 last_key_layout_id
= current_key_layout_id
;
10469 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10475 UInt16 key_action
= action
- keyDown
;
10476 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10477 UInt32 keyboard_type
= LMGetKbdType ();
10478 SInt32 dead_key_state
= 0;
10480 UniCharCount actual_length
;
10482 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10483 modifier_key_state
, keyboard_type
,
10484 kUCKeyTranslateNoDeadKeysMask
,
10486 1, &actual_length
, &code
);
10487 if (status
== noErr
&& actual_length
== 1)
10488 mac_set_unicode_keystroke_event (code
, buf
);
10490 #endif /* MAC_OSX */
10492 if (buf
->kind
== NO_EVENT
)
10494 /* This code comes from Keyboard Resource, Appendix C of IM
10495 - Text. This is necessary since shift is ignored in KCHR
10496 table translation when option or command is pressed. It
10497 also does not translate correctly control-shift chars
10498 like C-% so mask off shift here also. */
10499 /* Mask off modifier keys that are mapped to some Emacs
10501 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10502 /* set high byte of keycode to modifier high byte*/
10503 int new_key_code
= key_code
| new_modifiers
;
10504 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10505 unsigned long some_state
= 0;
10506 UInt32 new_char_code
;
10508 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10509 if (new_char_code
== 0)
10510 /* Seems like a dead key. Append up-stroke. */
10511 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10515 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10516 buf
->code
= new_char_code
& 0xff;
10521 if (buf
->kind
== NO_EVENT
)
10523 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10524 buf
->code
= char_code
;
10527 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10528 buf
->modifiers
|= (extra_keyboard_modifiers
10529 & (meta_modifier
| alt_modifier
10530 | hyper_modifier
| super_modifier
));
10532 #if TARGET_API_MAC_CARBON
10533 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10534 && buf
->code
>= 0x80 && buf
->modifiers
)
10537 TextEncoding encoding
= kTextEncodingMacRoman
;
10538 TextToUnicodeInfo ttu_info
;
10540 UpgradeScriptInfoToTextEncoding (current_key_script
,
10541 kTextLanguageDontCare
,
10542 kTextRegionDontCare
,
10544 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10549 ByteCount unicode_len
;
10552 pstr
[1] = buf
->code
;
10553 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10555 &unicode_len
, &code
);
10556 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10557 mac_set_unicode_keystroke_event (code
, buf
);
10558 DisposeTextToUnicodeInfo (&ttu_info
);
10563 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10564 && buf
->code
>= 0x80
10565 && last_key_script
!= current_key_script
)
10567 struct input_event event
;
10569 EVENT_INIT (event
);
10570 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10572 event
.code
= current_key_script
;
10573 event
.timestamp
= timestamp
;
10574 kbd_buffer_store_event (&event
);
10575 last_key_script
= current_key_script
;
10580 mac_store_apple_event (class, id
, desc
)
10581 Lisp_Object
class, id
;
10582 const AEDesc
*desc
;
10584 struct input_event buf
;
10588 buf
.kind
= MAC_APPLE_EVENT
;
10591 XSETFRAME (buf
.frame_or_window
,
10592 mac_focus_frame (&one_mac_display_info
));
10593 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10594 is safe to use them during read_socket_hook. */
10595 buf
.arg
= mac_aedesc_to_lisp (desc
);
10596 kbd_buffer_store_event (&buf
);
10599 #if TARGET_API_MAC_CARBON
10601 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10602 event
, num_params
, names
, types
)
10603 AEEventClass
class;
10605 Lisp_Object class_key
, id_key
;
10608 const EventParamName
*names
;
10609 const EventParamType
*types
;
10611 OSStatus err
= eventNotHandledErr
;
10612 Lisp_Object binding
;
10614 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10615 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10617 if (INTEGERP (binding
))
10618 err
= XINT (binding
);
10621 AppleEvent apple_event
;
10622 err
= create_apple_event_from_event_ref (event
, num_params
,
10627 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10628 AEDisposeDesc (&apple_event
);
10629 mac_wakeup_from_rne ();
10638 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10642 const AEDesc
*desc
;
10644 struct input_event buf
;
10648 buf
.kind
= DRAG_N_DROP_EVENT
;
10649 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10650 buf
.timestamp
= TickCount () * (1000 / 60);
10651 XSETINT (buf
.x
, mouse_pos
.h
);
10652 XSETINT (buf
.y
, mouse_pos
.v
);
10653 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10654 buf
.arg
= mac_aedesc_to_lisp (desc
);
10655 kbd_buffer_store_event (&buf
);
10660 mac_store_service_event (event
)
10664 Lisp_Object id_key
;
10666 const EventParamName
*names
;
10667 const EventParamType
*types
;
10668 static const EventParamName names_pfm
[] =
10669 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10670 static const EventParamType types_pfm
[] =
10671 {typeCFStringRef
, typeCFStringRef
};
10673 switch (GetEventKind (event
))
10675 case kEventServicePaste
:
10682 case kEventServicePerform
:
10684 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10693 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10699 #endif /* MAC_OSX */
10701 static pascal OSStatus
10702 mac_handle_window_event (next_handler
, event
, data
)
10703 EventHandlerCallRef next_handler
;
10708 OSStatus err
, result
= eventNotHandledErr
;
10711 XSizeHints
*size_hints
;
10713 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
10714 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10716 return eventNotHandledErr
;
10718 f
= mac_window_to_frame (wp
);
10719 switch (GetEventKind (event
))
10721 /* -- window refresh events -- */
10723 case kEventWindowUpdate
:
10724 result
= CallNextEventHandler (next_handler
, event
);
10725 if (result
!= eventNotHandledErr
)
10728 do_window_update (wp
);
10732 /* -- window state change events -- */
10734 case kEventWindowShowing
:
10735 size_hints
= FRAME_SIZE_HINTS (f
);
10736 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
10738 struct frame
*sf
= SELECTED_FRAME ();
10740 if (!(FRAME_MAC_P (sf
)))
10741 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
10744 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
10745 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10746 kWindowCascadeStartAtParentWindowScreen
10748 kWindowCascadeOnParentWindowScreen
10751 #if USE_MAC_TOOLBAR
10752 /* This is a workaround. RepositionWindow fails to put
10753 a window at the cascading position when its parent
10754 window has a Carbon HIToolbar. */
10755 if (f
->top_pos
== sf
->top_pos
&& f
->left_pos
== sf
->left_pos
)
10756 MoveWindowStructure (wp
, f
->left_pos
+ 10, f
->top_pos
+ 32);
10763 case kEventWindowHiding
:
10764 /* Before unmapping the window, update the WM_SIZE_HINTS
10765 property to claim that the current position of the window is
10766 user-specified, rather than program-specified, so that when
10767 the window is mapped again, it will be placed at the same
10768 location, without forcing the user to position it by hand
10769 again (they have already done that once for this window.) */
10770 x_wm_set_size_hint (f
, (long) 0, 1);
10774 case kEventWindowShown
:
10775 case kEventWindowHidden
:
10776 case kEventWindowCollapsed
:
10777 case kEventWindowExpanded
:
10778 mac_handle_visibility_change (f
);
10782 case kEventWindowBoundsChanging
:
10783 result
= CallNextEventHandler (next_handler
, event
);
10784 if (result
!= eventNotHandledErr
)
10787 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10788 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10792 size_hints
= FRAME_SIZE_HINTS (f
);
10793 if ((attributes
& kWindowBoundsChangeUserResize
)
10794 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
10795 == (PResizeInc
| PBaseSize
| PMinSize
)))
10800 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10801 typeQDRectangle
, NULL
, sizeof (Rect
),
10806 width
= bounds
.right
- bounds
.left
;
10807 height
= bounds
.bottom
- bounds
.top
;
10809 if (width
< size_hints
->min_width
)
10810 width
= size_hints
->min_width
;
10812 width
= size_hints
->base_width
10813 + (int) ((width
- size_hints
->base_width
)
10814 / (float) size_hints
->width_inc
+ .5)
10815 * size_hints
->width_inc
;
10817 if (height
< size_hints
->min_height
)
10818 height
= size_hints
->min_height
;
10820 height
= size_hints
->base_height
10821 + (int) ((height
- size_hints
->base_height
)
10822 / (float) size_hints
->height_inc
+ .5)
10823 * size_hints
->height_inc
;
10825 bounds
.right
= bounds
.left
+ width
;
10826 bounds
.bottom
= bounds
.top
+ height
;
10827 SetEventParameter (event
, kEventParamCurrentBounds
,
10828 typeQDRectangle
, sizeof (Rect
), &bounds
);
10833 case kEventWindowBoundsChanged
:
10834 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10835 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10839 if (attributes
& kWindowBoundsChangeSizeChanged
)
10843 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10844 typeQDRectangle
, NULL
, sizeof (Rect
),
10850 width
= bounds
.right
- bounds
.left
;
10851 height
= bounds
.bottom
- bounds
.top
;
10852 mac_handle_size_change (f
, width
, height
);
10853 mac_wakeup_from_rne ();
10857 if (attributes
& kWindowBoundsChangeOriginChanged
)
10858 mac_handle_origin_change (f
);
10863 /* -- window action events -- */
10865 case kEventWindowClose
:
10867 struct input_event buf
;
10870 buf
.kind
= DELETE_WINDOW_EVENT
;
10871 XSETFRAME (buf
.frame_or_window
, f
);
10873 kbd_buffer_store_event (&buf
);
10878 case kEventWindowGetIdealSize
:
10879 result
= CallNextEventHandler (next_handler
, event
);
10880 if (result
!= eventNotHandledErr
)
10884 Point ideal_size
= mac_get_ideal_size (f
);
10886 err
= SetEventParameter (event
, kEventParamDimensions
,
10887 typeQDPoint
, sizeof (Point
), &ideal_size
);
10894 case kEventWindowToolbarSwitchMode
:
10896 static const EventParamName names
[] = {kEventParamDirectObject
,
10897 kEventParamWindowMouseLocation
,
10898 kEventParamKeyModifiers
,
10899 kEventParamMouseButton
,
10900 kEventParamClickCount
,
10901 kEventParamMouseChord
};
10902 static const EventParamType types
[] = {typeWindowRef
,
10908 int num_params
= sizeof (names
) / sizeof (names
[0]);
10910 err
= mac_store_event_ref_as_apple_event (0, 0,
10912 Qtoolbar_switch_mode
,
10922 /* -- window focus events -- */
10924 case kEventWindowFocusAcquired
:
10925 err
= mac_tsm_resume ();
10930 case kEventWindowFocusRelinquish
:
10931 err
= mac_tsm_suspend ();
10944 static pascal OSStatus
10945 mac_handle_application_event (next_handler
, event
, data
)
10946 EventHandlerCallRef next_handler
;
10950 OSStatus err
, result
= eventNotHandledErr
;
10952 switch (GetEventKind (event
))
10955 case kEventAppActivated
:
10956 err
= mac_tsm_resume ();
10959 case kEventAppDeactivated
:
10960 err
= mac_tsm_suspend ();
10974 static pascal OSStatus
10975 mac_handle_keyboard_event (next_handler
, event
, data
)
10976 EventHandlerCallRef next_handler
;
10980 OSStatus err
, result
= eventNotHandledErr
;
10981 UInt32 event_kind
, key_code
, modifiers
, mapped_modifiers
;
10982 unsigned char char_code
;
10984 event_kind
= GetEventKind (event
);
10985 switch (event_kind
)
10987 case kEventRawKeyDown
:
10988 case kEventRawKeyRepeat
:
10989 case kEventRawKeyUp
:
10990 if (read_socket_inev
== NULL
)
10992 result
= CallNextEventHandler (next_handler
, event
);
10996 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
10998 sizeof (UInt32
), NULL
, &modifiers
);
11002 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
11004 /* When using Carbon Events, we need to pass raw keyboard events
11005 to the TSM ourselves. If TSM handles it, it will pass back
11006 noErr, otherwise it will pass back "eventNotHandledErr" and
11007 we can process it normally. */
11008 if (!(mapped_modifiers
11009 & ~(mac_pass_command_to_system
? cmdKey
: 0)
11010 & ~(mac_pass_control_to_system
? controlKey
: 0)))
11012 result
= CallNextEventHandler (next_handler
, event
);
11013 if (result
!= eventNotHandledErr
)
11018 if (read_socket_inev
->kind
!= NO_EVENT
)
11025 if (event_kind
== kEventRawKeyUp
)
11028 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11030 sizeof (char), NULL
, &char_code
);
11034 err
= GetEventParameter (event
, kEventParamKeyCode
,
11036 sizeof (UInt32
), NULL
, &key_code
);
11040 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11041 char_code
, key_code
, modifiers
,
11043 (GetEventTime (event
) / kEventDurationMillisecond
)),
11055 static pascal OSStatus
11056 mac_handle_command_event (next_handler
, event
, data
)
11057 EventHandlerCallRef next_handler
;
11061 OSStatus err
, result
= eventNotHandledErr
;
11063 static const EventParamName names
[] =
11064 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11065 static const EventParamType types
[] =
11066 {typeHICommand
, typeUInt32
};
11067 int num_params
= sizeof (names
) / sizeof (names
[0]);
11069 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11070 NULL
, sizeof (HICommand
), NULL
, &command
);
11072 return eventNotHandledErr
;
11074 switch (GetEventKind (event
))
11076 case kEventCommandProcess
:
11077 result
= CallNextEventHandler (next_handler
, event
);
11078 if (result
!= eventNotHandledErr
)
11081 err
= GetEventParameter (event
, kEventParamDirectObject
,
11082 typeHICommand
, NULL
,
11083 sizeof (HICommand
), NULL
, &command
);
11085 if (err
!= noErr
|| command
.commandID
== 0)
11088 /* A HI command event is mapped to an Apple event whose event
11089 class symbol is `hi-command' and event ID is its command
11091 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11106 static pascal OSStatus
11107 mac_handle_mouse_event (next_handler
, event
, data
)
11108 EventHandlerCallRef next_handler
;
11112 OSStatus err
, result
= eventNotHandledErr
;
11114 switch (GetEventKind (event
))
11116 case kEventMouseWheelMoved
:
11120 EventMouseWheelAxis axis
;
11124 result
= CallNextEventHandler (next_handler
, event
);
11125 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11128 f
= mac_focus_frame (&one_mac_display_info
);
11130 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11131 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11133 || wp
!= FRAME_MAC_WINDOW (f
))
11136 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11137 typeMouseWheelAxis
, NULL
,
11138 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11139 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11142 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11143 typeQDPoint
, NULL
, sizeof (Point
),
11148 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11149 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11150 if (point
.h
< 0 || point
.v
< 0
11151 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11152 f
->tool_bar_window
))
11155 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11156 typeSInt32
, NULL
, sizeof (SInt32
),
11161 read_socket_inev
->kind
= WHEEL_EVENT
;
11162 read_socket_inev
->code
= 0;
11163 read_socket_inev
->modifiers
=
11164 (mac_event_to_emacs_modifiers (event
)
11165 | ((delta
< 0) ? down_modifier
: up_modifier
));
11166 XSETINT (read_socket_inev
->x
, point
.h
);
11167 XSETINT (read_socket_inev
->y
, point
.v
);
11168 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11182 static pascal OSStatus
11183 mac_handle_text_input_event (next_handler
, event
, data
)
11184 EventHandlerCallRef next_handler
;
11188 OSStatus err
, result
;
11189 Lisp_Object id_key
= Qnil
;
11191 const EventParamName
*names
;
11192 const EventParamType
*types
;
11193 static UInt32 seqno_uaia
= 0;
11194 static const EventParamName names_uaia
[] =
11195 {kEventParamTextInputSendComponentInstance
,
11196 kEventParamTextInputSendRefCon
,
11197 kEventParamTextInputSendSLRec
,
11198 kEventParamTextInputSendFixLen
,
11199 kEventParamTextInputSendText
,
11200 kEventParamTextInputSendUpdateRng
,
11201 kEventParamTextInputSendHiliteRng
,
11202 kEventParamTextInputSendClauseRng
,
11203 kEventParamTextInputSendPinRng
,
11204 kEventParamTextInputSendTextServiceEncoding
,
11205 kEventParamTextInputSendTextServiceMacEncoding
,
11206 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11207 static const EventParamType types_uaia
[] =
11208 {typeComponentInstance
,
11210 typeIntlWritingCode
,
11217 typeTextRangeArray
,
11218 typeTextRangeArray
,
11224 static const EventParamName names_ufke
[] =
11225 {kEventParamTextInputSendComponentInstance
,
11226 kEventParamTextInputSendRefCon
,
11227 kEventParamTextInputSendSLRec
,
11228 kEventParamTextInputSendText
};
11229 static const EventParamType types_ufke
[] =
11230 {typeComponentInstance
,
11232 typeIntlWritingCode
,
11235 result
= CallNextEventHandler (next_handler
, event
);
11236 if (result
!= eventNotHandledErr
)
11239 switch (GetEventKind (event
))
11241 case kEventTextInputUpdateActiveInputArea
:
11242 id_key
= Qupdate_active_input_area
;
11243 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11244 names
= names_uaia
;
11245 types
= types_uaia
;
11246 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11247 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11252 case kEventTextInputUnicodeForKeyEvent
:
11254 EventRef kbd_event
;
11255 UInt32 actual_size
, modifiers
;
11257 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11258 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11261 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11263 sizeof (UInt32
), NULL
, &modifiers
);
11264 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11265 /* There're mapped modifier keys. Process it in
11269 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11270 typeUnicodeText
, NULL
, 0, &actual_size
,
11272 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11276 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11277 typeUnicodeText
, NULL
,
11278 sizeof (UniChar
), NULL
, &code
);
11279 if (err
== noErr
&& code
< 0x80)
11281 /* ASCII character. Process it in do_keystroke. */
11282 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11286 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11287 typeUInt32
, NULL
, sizeof (UInt32
),
11289 if (!(err
== noErr
&& key_code
<= 0x7f
11290 && keycode_to_xkeysym_table
[key_code
]))
11293 mac_focus_frame (&one_mac_display_info
);
11295 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11296 read_socket_inev
->code
= code
;
11297 read_socket_inev
->modifiers
=
11298 mac_to_emacs_modifiers (modifiers
);
11299 read_socket_inev
->modifiers
|=
11300 (extra_keyboard_modifiers
11301 & (meta_modifier
| alt_modifier
11302 | hyper_modifier
| super_modifier
));
11303 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11311 /* Non-ASCII keystrokes without mapped modifiers are
11312 processed at the Lisp level. */
11313 id_key
= Qunicode_for_key_event
;
11314 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11315 names
= names_ufke
;
11316 types
= types_ufke
;
11322 case kEventTextInputOffsetToPos
:
11328 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11331 /* Strictly speaking, this is not always correct because
11332 previous events may change some states about display. */
11333 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11335 /* Active input area is displayed around the current point. */
11336 f
= SELECTED_FRAME ();
11337 w
= XWINDOW (f
->selected_window
);
11339 else if (WINDOWP (echo_area_window
))
11341 /* Active input area is displayed in the echo area. */
11342 w
= XWINDOW (echo_area_window
);
11343 f
= WINDOW_XFRAME (w
);
11348 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11349 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11350 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11351 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11352 + FONT_BASE (FRAME_FONT (f
))
11353 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11354 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11355 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11365 if (!NILP (id_key
))
11366 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11372 #endif /* TARGET_API_MAC_CARBON */
11376 install_window_handler (window
)
11379 OSStatus err
= noErr
;
11381 #if TARGET_API_MAC_CARBON
11384 static const EventTypeSpec specs
[] =
11386 /* -- window refresh events -- */
11387 {kEventClassWindow
, kEventWindowUpdate
},
11388 /* -- window state change events -- */
11389 {kEventClassWindow
, kEventWindowShowing
},
11390 {kEventClassWindow
, kEventWindowHiding
},
11391 {kEventClassWindow
, kEventWindowShown
},
11392 {kEventClassWindow
, kEventWindowHidden
},
11393 {kEventClassWindow
, kEventWindowCollapsed
},
11394 {kEventClassWindow
, kEventWindowExpanded
},
11395 {kEventClassWindow
, kEventWindowBoundsChanging
},
11396 {kEventClassWindow
, kEventWindowBoundsChanged
},
11397 /* -- window action events -- */
11398 {kEventClassWindow
, kEventWindowClose
},
11399 {kEventClassWindow
, kEventWindowGetIdealSize
},
11401 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11404 /* -- window focus events -- */
11405 {kEventClassWindow
, kEventWindowFocusAcquired
},
11406 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11409 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11411 if (handle_window_eventUPP
== NULL
)
11412 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11414 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11415 GetEventTypeCount (specs
),
11416 specs
, NULL
, NULL
);
11421 err
= install_drag_handler (window
);
11427 remove_window_handler (window
)
11430 remove_drag_handler (window
);
11433 #if TARGET_API_MAC_CARBON
11435 install_application_handler ()
11437 OSStatus err
= noErr
;
11441 static const EventTypeSpec specs
[] = {
11443 {kEventClassApplication
, kEventAppActivated
},
11444 {kEventClassApplication
, kEventAppDeactivated
},
11448 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11449 (mac_handle_application_event
),
11450 GetEventTypeCount (specs
),
11451 specs
, NULL
, NULL
);
11456 static const EventTypeSpec specs
[] =
11457 {{kEventClassKeyboard
, kEventRawKeyDown
},
11458 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11459 {kEventClassKeyboard
, kEventRawKeyUp
}};
11461 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11462 (mac_handle_keyboard_event
),
11463 GetEventTypeCount (specs
),
11464 specs
, NULL
, NULL
);
11469 static const EventTypeSpec specs
[] =
11470 {{kEventClassCommand
, kEventCommandProcess
}};
11472 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11473 (mac_handle_command_event
),
11474 GetEventTypeCount (specs
),
11475 specs
, NULL
, NULL
);
11480 static const EventTypeSpec specs
[] =
11481 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11483 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11484 (mac_handle_mouse_event
),
11485 GetEventTypeCount (specs
),
11486 specs
, NULL
, NULL
);
11492 static const EventTypeSpec spec
[] =
11493 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11494 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11495 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11497 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11498 (mac_handle_text_input_event
),
11499 GetEventTypeCount (spec
),
11505 err
= install_menu_target_item_handler ();
11509 err
= install_service_handler ();
11517 mac_handle_dm_notification (event
)
11520 mac_screen_config_changed
= 1;
11523 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11525 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11526 CGDirectDisplayID display
;
11527 CGDisplayChangeSummaryFlags flags
;
11530 mac_screen_config_changed
= 1;
11535 init_dm_notification_handler ()
11539 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11540 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11541 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11544 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11547 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11548 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11550 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11551 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11553 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11554 ProcessSerialNumber psn
;
11556 if (handle_dm_notificationUPP
== NULL
)
11557 handle_dm_notificationUPP
=
11558 NewDMNotificationUPP (mac_handle_dm_notification
);
11560 err
= GetCurrentProcess (&psn
);
11562 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11570 mac_get_screen_info (dpyinfo
)
11571 struct mac_display_info
*dpyinfo
;
11574 /* HasDepth returns true if it is possible to have a 32 bit display,
11575 but this may not be what is actually used. Mac OSX can do better. */
11576 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11577 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11580 CGDisplayCount ndisps
;
11581 CGDirectDisplayID
*displays
;
11583 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11586 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11587 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11591 CGRect bounds
= CGRectZero
;
11593 while (ndisps
-- > 0)
11594 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11595 dpyinfo
->height
= CGRectGetHeight (bounds
);
11596 dpyinfo
->width
= CGRectGetWidth (bounds
);
11600 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11601 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11604 #else /* !MAC_OSX */
11606 GDHandle gdh
= GetMainDevice ();
11607 Rect rect
= (**gdh
).gdRect
;
11609 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11610 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11611 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11614 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11615 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11616 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11618 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11619 dpyinfo
->width
= rect
.right
- rect
.left
;
11621 #endif /* !MAC_OSX */
11627 profiler_exit_proc ()
11629 ProfilerDump ("\pEmacs.prof");
11634 /* These few functions implement Emacs as a normal Mac application
11635 (almost): set up the heap and the Toolbox, handle necessary system
11636 events plus a few simple menu events. They also set up Emacs's
11637 access to functions defined in the rest of this file. Emacs uses
11638 function hooks to perform all its terminal I/O. A complete list of
11639 these functions appear in termhooks.h. For what they do, read the
11640 comments there and see also w32term.c and xterm.c. What's
11641 noticeably missing here is the event loop, which is normally
11642 present in most Mac application. After performing the necessary
11643 Mac initializations, main passes off control to emacs_main
11644 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11645 (defined further below) to read input. This is where
11646 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11653 #if __profile__ /* is the profiler on? */
11654 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11659 /* set creator and type for files created by MSL */
11660 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11664 do_init_managers ();
11668 #ifndef USE_LSB_TAG
11669 do_check_ram_size ();
11672 init_emacs_passwd_dir ();
11676 init_coercion_handler ();
11678 initialize_applescript ();
11680 init_apple_event_handler ();
11682 init_dm_notification_handler ();
11688 /* set up argv array from STR# resource */
11689 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
11693 /* free up AppleScript resources on exit */
11694 atexit (terminate_applescript
);
11696 #if __profile__ /* is the profiler on? */
11697 atexit (profiler_exit_proc
);
11700 /* 3rd param "envp" never used in emacs_main */
11701 (void) emacs_main (argc
, argv
, 0);
11704 /* Never reached - real exit in Fkill_emacs */
11709 #if !TARGET_API_MAC_CARBON
11710 static RgnHandle mouse_region
= NULL
;
11713 mac_wait_next_event (er
, sleep_time
, dequeue
)
11718 static EventRecord er_buf
= {nullEvent
};
11719 UInt32 target_tick
, current_tick
;
11720 EventMask event_mask
;
11722 if (mouse_region
== NULL
)
11723 mouse_region
= NewRgn ();
11725 event_mask
= everyEvent
;
11726 if (!mac_ready_for_apple_events
)
11727 event_mask
-= highLevelEventMask
;
11729 current_tick
= TickCount ();
11730 target_tick
= current_tick
+ sleep_time
;
11732 if (er_buf
.what
== nullEvent
)
11733 while (!WaitNextEvent (event_mask
, &er_buf
,
11734 target_tick
- current_tick
, mouse_region
))
11736 current_tick
= TickCount ();
11737 if (target_tick
<= current_tick
)
11743 er_buf
.what
= nullEvent
;
11746 #endif /* not TARGET_API_MAC_CARBON */
11748 #if TARGET_API_MAC_CARBON
11750 mac_post_mouse_moved_event ()
11752 EventRef event
= NULL
;
11755 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
11756 kEventAttributeNone
, &event
);
11761 GetGlobalMouse (&mouse_pos
);
11762 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
11763 sizeof (Point
), &mouse_pos
);
11767 UInt32 modifiers
= GetCurrentKeyModifiers ();
11769 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
11770 sizeof (UInt32
), &modifiers
);
11773 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
11774 kEventPriorityStandard
);
11776 ReleaseEvent (event
);
11782 /* Emacs calls this whenever it wants to read an input event from the
11785 XTread_socket (sd
, expected
, hold_quit
)
11787 struct input_event
*hold_quit
;
11789 struct input_event inev
;
11791 #if TARGET_API_MAC_CARBON
11793 EventTargetRef toolbox_dispatcher
;
11796 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11798 if (interrupt_input_blocked
)
11800 interrupt_input_pending
= 1;
11804 interrupt_input_pending
= 0;
11807 /* So people can tell when we have read the available input. */
11808 input_signal_count
++;
11812 #if TARGET_API_MAC_CARBON
11813 toolbox_dispatcher
= GetEventDispatcherTarget ();
11817 mac_prepare_for_quickdraw (NULL
),
11819 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
11820 kEventRemoveFromQueue
, &eventRef
))
11821 #else /* !TARGET_API_MAC_CARBON */
11822 while (mac_wait_next_event (&er
, 0, true))
11823 #endif /* !TARGET_API_MAC_CARBON */
11827 unsigned long timestamp
;
11830 inev
.kind
= NO_EVENT
;
11833 #if TARGET_API_MAC_CARBON
11834 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
11836 if (!mac_convert_event_ref (eventRef
, &er
))
11838 #else /* !TARGET_API_MAC_CARBON */
11839 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
11840 #endif /* !TARGET_API_MAC_CARBON */
11847 WindowRef window_ptr
;
11848 ControlPartCode part_code
;
11849 int tool_bar_p
= 0;
11851 #if TARGET_API_MAC_CARBON
11854 /* This is needed to send mouse events like aqua window
11855 buttons to the correct handler. */
11856 read_socket_inev
= &inev
;
11857 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11858 read_socket_inev
= NULL
;
11859 if (err
!= eventNotHandledErr
)
11862 last_mouse_glyph_frame
= 0;
11864 if (dpyinfo
->grabbed
&& last_mouse_frame
11865 && FRAME_LIVE_P (last_mouse_frame
))
11867 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
11868 part_code
= inContent
;
11872 part_code
= FindWindow (er
.where
, &window_ptr
);
11873 if (tip_window
&& window_ptr
== tip_window
)
11875 HideWindow (tip_window
);
11876 part_code
= FindWindow (er
.where
, &window_ptr
);
11880 if (er
.what
!= mouseDown
&&
11881 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
11887 f
= mac_focus_frame (dpyinfo
);
11888 saved_menu_event_location
= er
.where
;
11889 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
11890 XSETFRAME (inev
.frame_or_window
, f
);
11895 #if TARGET_API_MAC_CARBON
11896 FrontNonFloatingWindow ()
11901 || (mac_window_to_frame (window_ptr
)
11902 != dpyinfo
->x_focus_frame
))
11903 SelectWindow (window_ptr
);
11906 ControlPartCode control_part_code
;
11910 ControlKind control_kind
;
11913 f
= mac_window_to_frame (window_ptr
);
11914 /* convert to local coordinates of new window */
11915 mouse_loc
.h
= (er
.where
.h
11917 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
11918 mouse_loc
.v
= (er
.where
.v
11920 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
11921 #if TARGET_API_MAC_CARBON
11922 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
11923 &control_part_code
);
11926 GetControlKind (ch
, &control_kind
);
11929 control_part_code
= FindControl (mouse_loc
, window_ptr
,
11933 #if TARGET_API_MAC_CARBON
11934 inev
.code
= mac_get_mouse_btn (eventRef
);
11935 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
11937 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
11938 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
11940 XSETINT (inev
.x
, mouse_loc
.h
);
11941 XSETINT (inev
.y
, mouse_loc
.v
);
11943 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
11945 #ifndef USE_TOOLKIT_SCROLL_BARS
11946 /* control_part_code becomes kControlNoPart if
11947 a progress indicator is clicked. */
11948 && control_part_code
!= kControlNoPart
11949 #else /* USE_TOOLKIT_SCROLL_BARS */
11951 && control_kind
.kind
== kControlKindScrollBar
11952 #endif /* MAC_OSX */
11953 #endif /* USE_TOOLKIT_SCROLL_BARS */
11956 struct scroll_bar
*bar
;
11958 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11960 bar
= tracked_scroll_bar
;
11961 #ifndef USE_TOOLKIT_SCROLL_BARS
11962 control_part_code
= kControlIndicatorPart
;
11966 bar
= (struct scroll_bar
*) GetControlReference (ch
);
11967 #ifdef USE_TOOLKIT_SCROLL_BARS
11968 /* Make the "Ctrl-Mouse-2 splits window" work
11969 for toolkit scroll bars. */
11970 if (inev
.modifiers
& ctrl_modifier
)
11971 x_scroll_bar_handle_click (bar
, control_part_code
,
11973 else if (er
.what
== mouseDown
)
11974 x_scroll_bar_handle_press (bar
, control_part_code
,
11977 x_scroll_bar_handle_release (bar
, &inev
);
11978 #else /* not USE_TOOLKIT_SCROLL_BARS */
11979 x_scroll_bar_handle_click (bar
, control_part_code
,
11981 if (er
.what
== mouseDown
11982 && control_part_code
== kControlIndicatorPart
)
11983 tracked_scroll_bar
= bar
;
11985 tracked_scroll_bar
= NULL
;
11986 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11990 Lisp_Object window
;
11991 int x
= mouse_loc
.h
;
11992 int y
= mouse_loc
.v
;
11994 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
11995 if (EQ (window
, f
->tool_bar_window
))
11997 if (er
.what
== mouseDown
)
11998 handle_tool_bar_click (f
, x
, y
, 1, 0);
12000 handle_tool_bar_click (f
, x
, y
, 0,
12006 XSETFRAME (inev
.frame_or_window
, f
);
12007 inev
.kind
= MOUSE_CLICK_EVENT
;
12011 if (er
.what
== mouseDown
)
12013 dpyinfo
->grabbed
|= (1 << inev
.code
);
12014 last_mouse_frame
= f
;
12017 last_tool_bar_item
= -1;
12021 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
12022 /* If a button is released though it was not
12023 previously pressed, that would be because
12024 of multi-button emulation. */
12025 dpyinfo
->grabbed
= 0;
12027 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
12030 /* Ignore any mouse motion that happened before
12031 this event; any subsequent mouse-movement Emacs
12032 events should reflect only motion after the
12035 f
->mouse_moved
= 0;
12037 #ifdef USE_TOOLKIT_SCROLL_BARS
12038 if (inev
.kind
== MOUSE_CLICK_EVENT
12039 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12040 && (inev
.modifiers
& ctrl_modifier
)))
12045 inev
.modifiers
|= down_modifier
;
12048 inev
.modifiers
|= up_modifier
;
12055 #if TARGET_API_MAC_CARBON
12057 if (IsWindowPathSelectClick (window_ptr
, &er
))
12059 WindowPathSelect (window_ptr
, NULL
, NULL
);
12062 if (part_code
== inProxyIcon
12063 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12064 != errUserWantsToDragWindow
))
12066 DragWindow (window_ptr
, er
.where
, NULL
);
12067 #else /* not TARGET_API_MAC_CARBON */
12068 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12069 /* Update the frame parameters. */
12071 struct frame
*f
= mac_window_to_frame (window_ptr
);
12073 if (f
&& !f
->async_iconified
)
12074 mac_handle_origin_change (f
);
12076 #endif /* not TARGET_API_MAC_CARBON */
12080 if (TrackGoAway (window_ptr
, er
.where
))
12082 inev
.kind
= DELETE_WINDOW_EVENT
;
12083 XSETFRAME (inev
.frame_or_window
,
12084 mac_window_to_frame (window_ptr
));
12088 /* window resize handling added --ben */
12090 do_grow_window (window_ptr
, &er
);
12093 /* window zoom handling added --ben */
12096 if (TrackBox (window_ptr
, er
.where
, part_code
))
12097 do_zoom_window (window_ptr
, part_code
);
12100 #if USE_MAC_TOOLBAR
12106 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12108 /* This doesn't work on Mac OS X 10.2. */
12110 HIViewClick (ch
, eventRef
);
12113 #endif /* USE_MAC_TOOLBAR */
12121 #if !TARGET_API_MAC_CARBON
12123 do_window_update ((WindowRef
) er
.message
);
12128 switch ((er
.message
>> 24) & 0x000000FF)
12130 case mouseMovedMessage
:
12131 #if !TARGET_API_MAC_CARBON
12132 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12133 er
.where
.h
+ 1, er
.where
.v
+ 1);
12135 previous_help_echo_string
= help_echo_string
;
12136 help_echo_string
= Qnil
;
12138 if (dpyinfo
->grabbed
&& last_mouse_frame
12139 && FRAME_LIVE_P (last_mouse_frame
))
12140 f
= last_mouse_frame
;
12142 f
= dpyinfo
->x_focus_frame
;
12144 if (dpyinfo
->mouse_face_hidden
)
12146 dpyinfo
->mouse_face_hidden
= 0;
12147 clear_mouse_face (dpyinfo
);
12152 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12155 mouse_pos
.h
= (er
.where
.h
12157 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12158 mouse_pos
.v
= (er
.where
.v
12160 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12161 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12162 #ifdef USE_TOOLKIT_SCROLL_BARS
12163 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12165 #else /* not USE_TOOLKIT_SCROLL_BARS */
12166 x_scroll_bar_note_movement (tracked_scroll_bar
,
12168 - XINT (tracked_scroll_bar
->top
),
12169 er
.when
* (1000 / 60));
12170 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12173 /* Generate SELECT_WINDOW_EVENTs when needed. */
12174 if (!NILP (Vmouse_autoselect_window
))
12176 Lisp_Object window
;
12178 window
= window_from_coordinates (f
,
12183 /* Window will be selected only when it is
12184 not selected now and last mouse movement
12185 event was not in it. Minibuffer window
12186 will be selected iff it is active. */
12187 if (WINDOWP (window
)
12188 && !EQ (window
, last_window
)
12189 && !EQ (window
, selected_window
))
12191 inev
.kind
= SELECT_WINDOW_EVENT
;
12192 inev
.frame_or_window
= window
;
12195 last_window
=window
;
12197 if (!note_mouse_movement (f
, &mouse_pos
))
12198 help_echo_string
= previous_help_echo_string
;
12199 #if USE_MAC_TOOLBAR
12201 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12206 /* If the contents of the global variable
12207 help_echo_string has changed, generate a
12209 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12220 WindowRef window_ptr
= (WindowRef
) er
.message
;
12222 if (window_ptr
== tip_window
)
12224 HideWindow (tip_window
);
12228 if (!is_emacs_window (window_ptr
))
12231 f
= mac_window_to_frame (window_ptr
);
12233 if ((er
.modifiers
& activeFlag
) != 0)
12235 /* A window has been activated */
12238 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12240 mouse_loc
.h
= (er
.where
.h
12242 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12243 mouse_loc
.v
= (er
.where
.v
12245 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12246 /* Window-activated event counts as mouse movement,
12247 so update things that depend on mouse position. */
12248 note_mouse_movement (f
, &mouse_loc
);
12252 /* A window has been deactivated */
12253 #ifdef USE_TOOLKIT_SCROLL_BARS
12254 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12256 struct input_event event
;
12258 EVENT_INIT (event
);
12259 event
.kind
= NO_EVENT
;
12260 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12261 if (event
.kind
!= NO_EVENT
)
12263 event
.timestamp
= timestamp
;
12264 kbd_buffer_store_event_hold (&event
, hold_quit
);
12269 dpyinfo
->grabbed
= 0;
12271 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12273 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12275 /* If we move outside the frame, then we're
12276 certainly no longer on any text in the
12278 clear_mouse_face (dpyinfo
);
12279 dpyinfo
->mouse_face_mouse_frame
= 0;
12282 /* Generate a nil HELP_EVENT to cancel a help-echo.
12283 Do it only if there's something to cancel.
12284 Otherwise, the startup message is cleared when the
12285 mouse leaves the frame. */
12286 if (any_help_event_p
)
12297 f
= mac_focus_frame (dpyinfo
);
12298 XSETFRAME (inev
.frame_or_window
, f
);
12300 /* If mouse-highlight is an integer, input clears out mouse
12302 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12303 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12305 clear_mouse_face (dpyinfo
);
12306 dpyinfo
->mouse_face_hidden
= 1;
12308 #if TARGET_API_MAC_CARBON
12311 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12312 (er
.message
& keyCodeMask
) >> 8,
12313 er
.modifiers
, timestamp
, &inev
);
12317 case kHighLevelEvent
:
12318 AEProcessAppleEvent (&er
);
12323 #if TARGET_API_MAC_CARBON
12327 read_socket_inev
= &inev
;
12328 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12329 read_socket_inev
= NULL
;
12334 #if TARGET_API_MAC_CARBON
12335 ReleaseEvent (eventRef
);
12338 if (inev
.kind
!= NO_EVENT
)
12340 inev
.timestamp
= timestamp
;
12341 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12346 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12351 XSETFRAME (frame
, f
);
12357 any_help_event_p
= 1;
12358 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12359 help_echo_object
, help_echo_pos
);
12363 help_echo_string
= Qnil
;
12364 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12371 /* If the focus was just given to an autoraising frame,
12373 /* ??? This ought to be able to handle more than one such frame. */
12374 if (pending_autoraise_frame
)
12376 x_raise_frame (pending_autoraise_frame
);
12377 pending_autoraise_frame
= 0;
12380 if (mac_screen_config_changed
)
12382 mac_get_screen_info (dpyinfo
);
12383 mac_screen_config_changed
= 0;
12386 #if !TARGET_API_MAC_CARBON
12387 /* Check which frames are still visible. We do this here because
12388 there doesn't seem to be any direct notification from the Window
12389 Manager that the visibility of a window has changed (at least,
12390 not in all cases). */
12392 Lisp_Object tail
, frame
;
12394 FOR_EACH_FRAME (tail
, frame
)
12396 struct frame
*f
= XFRAME (frame
);
12398 /* The tooltip has been drawn already. Avoid the
12399 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12400 if (EQ (frame
, tip_frame
))
12403 if (FRAME_MAC_P (f
))
12404 mac_handle_visibility_change (f
);
12415 /* Need to override CodeWarrior's input function so no conversion is
12416 done on newlines Otherwise compiled functions in .elc files will be
12417 read incorrectly. Defined in ...:MSL C:MSL
12418 Common:Source:buffer_io.c. */
12421 __convert_to_newlines (unsigned char * p
, size_t * n
)
12423 #pragma unused(p,n)
12427 __convert_from_newlines (unsigned char * p
, size_t * n
)
12429 #pragma unused(p,n)
12435 make_mac_terminal_frame (struct frame
*f
)
12440 XSETFRAME (frame
, f
);
12442 f
->output_method
= output_mac
;
12443 f
->output_data
.mac
= (struct mac_output
*)
12444 xmalloc (sizeof (struct mac_output
));
12445 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12447 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12449 FRAME_COLS (f
) = 96;
12450 FRAME_LINES (f
) = 4;
12452 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12453 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12455 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12457 f
->output_data
.mac
->cursor_pixel
= 0;
12458 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12459 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12460 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12462 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12463 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12464 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12465 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12466 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12467 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12469 FRAME_FONTSET (f
) = -1;
12470 f
->output_data
.mac
->explicit_parent
= 0;
12473 f
->border_width
= 0;
12475 f
->internal_border_width
= 0;
12480 f
->new_text_cols
= 0;
12481 f
->new_text_lines
= 0;
12483 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12484 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12485 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12489 if (!(FRAME_MAC_WINDOW (f
) =
12490 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12491 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12493 /* so that update events can find this mac_output struct */
12494 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12500 /* Need to be initialized for unshow_buffer in window.c. */
12501 selected_window
= f
->selected_window
;
12503 Fmodify_frame_parameters (frame
,
12504 Fcons (Fcons (Qfont
,
12505 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12506 Fmodify_frame_parameters (frame
,
12507 Fcons (Fcons (Qforeground_color
,
12508 build_string ("black")), Qnil
));
12509 Fmodify_frame_parameters (frame
,
12510 Fcons (Fcons (Qbackground_color
,
12511 build_string ("white")), Qnil
));
12516 /***********************************************************************
12518 ***********************************************************************/
12520 static int mac_initialized
= 0;
12523 mac_make_rdb (xrm_option
)
12524 const char *xrm_option
;
12526 XrmDatabase database
;
12528 database
= xrm_get_preference_database (NULL
);
12530 xrm_merge_string_database (database
, xrm_option
);
12535 struct mac_display_info
*
12536 mac_term_init (display_name
, xrm_option
, resource_name
)
12537 Lisp_Object display_name
;
12539 char *resource_name
;
12541 struct mac_display_info
*dpyinfo
;
12545 if (!mac_initialized
)
12548 mac_initialized
= 1;
12551 if (x_display_list
)
12552 error ("Sorry, this version can only handle one display");
12554 dpyinfo
= &one_mac_display_info
;
12555 bzero (dpyinfo
, sizeof (*dpyinfo
));
12558 dpyinfo
->mac_id_name
12559 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12560 + SCHARS (Vsystem_name
)
12562 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12563 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12565 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12566 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12569 dpyinfo
->reference_count
= 0;
12570 dpyinfo
->resx
= 72.0;
12571 dpyinfo
->resy
= 72.0;
12573 mac_get_screen_info (dpyinfo
);
12575 dpyinfo
->grabbed
= 0;
12576 dpyinfo
->root_window
= NULL
;
12577 dpyinfo
->image_cache
= make_image_cache ();
12579 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12580 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12581 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12582 dpyinfo
->mouse_face_window
= Qnil
;
12583 dpyinfo
->mouse_face_overlay
= Qnil
;
12584 dpyinfo
->mouse_face_hidden
= 0;
12586 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12588 /* Put this display on the chain. */
12589 dpyinfo
->next
= x_display_list
;
12590 x_display_list
= dpyinfo
;
12592 /* Put it on x_display_name_list. */
12593 x_display_name_list
= Fcons (Fcons (display_name
,
12594 Fcons (Qnil
, dpyinfo
->xrdb
)),
12595 x_display_name_list
);
12596 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12603 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12606 x_delete_display (dpyinfo
)
12607 struct mac_display_info
*dpyinfo
;
12611 /* Discard this display from x_display_name_list and x_display_list.
12612 We can't use Fdelq because that can quit. */
12613 if (! NILP (x_display_name_list
)
12614 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12615 x_display_name_list
= XCDR (x_display_name_list
);
12620 tail
= x_display_name_list
;
12621 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12623 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
12625 XSETCDR (tail
, XCDR (XCDR (tail
)));
12628 tail
= XCDR (tail
);
12632 if (x_display_list
== dpyinfo
)
12633 x_display_list
= dpyinfo
->next
;
12636 struct x_display_info
*tail
;
12638 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12639 if (tail
->next
== dpyinfo
)
12640 tail
->next
= tail
->next
->next
;
12643 /* Free the font names in the font table. */
12644 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12645 if (dpyinfo
->font_table
[i
].name
)
12647 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
12648 xfree (dpyinfo
->font_table
[i
].full_name
);
12649 xfree (dpyinfo
->font_table
[i
].name
);
12652 if (dpyinfo
->font_table
)
12654 if (dpyinfo
->font_table
->font_encoder
)
12655 xfree (dpyinfo
->font_table
->font_encoder
);
12656 xfree (dpyinfo
->font_table
);
12658 if (dpyinfo
->mac_id_name
)
12659 xfree (dpyinfo
->mac_id_name
);
12661 if (x_display_list
== 0)
12663 mac_clear_font_name_table ();
12664 bzero (dpyinfo
, sizeof (*dpyinfo
));
12675 MenuItemIndex menu_index
;
12677 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
12678 &menu
, &menu_index
);
12680 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12681 EnableMenuCommand (NULL
, kHICommandPreferences
);
12682 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
12683 &menu
, &menu_index
);
12686 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12687 InsertMenuItemTextWithCFString (menu
, NULL
,
12688 0, kMenuItemAttrSeparator
, 0);
12689 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
12690 0, 0, kHICommandAbout
);
12692 #else /* !MAC_OSX */
12693 #if TARGET_API_MAC_CARBON
12694 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
12704 static InterfaceTypeList types
= {kUnicodeDocument
};
12706 static InterfaceTypeList types
= {kTextService
};
12709 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
12710 &tsm_document_id
, 0);
12714 /* Set up use of X before we make the first connection. */
12716 extern frame_parm_handler mac_frame_parm_handlers
[];
12718 static struct redisplay_interface x_redisplay_interface
=
12720 mac_frame_parm_handlers
,
12724 x_clear_end_of_line
,
12726 x_after_update_window_line
,
12727 x_update_window_begin
,
12728 x_update_window_end
,
12732 mac_flush_display_optional
,
12734 0, /* flush_display_optional */
12736 x_clear_window_mouse_face
,
12737 x_get_glyph_overhangs
,
12738 x_fix_overlapping_area
,
12739 x_draw_fringe_bitmap
,
12741 mac_define_fringe_bitmap
,
12742 mac_destroy_fringe_bitmap
,
12744 0, /* define_fringe_bitmap */
12745 0, /* destroy_fringe_bitmap */
12747 mac_per_char_metric
,
12749 mac_compute_glyph_string_overhangs
,
12750 x_draw_glyph_string
,
12751 mac_define_frame_cursor
,
12752 mac_clear_frame_area
,
12753 mac_draw_window_cursor
,
12754 mac_draw_vertical_window_border
,
12755 mac_shift_glyphs_for_insert
12761 rif
= &x_redisplay_interface
;
12763 clear_frame_hook
= x_clear_frame
;
12764 ins_del_lines_hook
= x_ins_del_lines
;
12765 delete_glyphs_hook
= x_delete_glyphs
;
12766 ring_bell_hook
= XTring_bell
;
12767 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12768 set_terminal_modes_hook
= XTset_terminal_modes
;
12769 update_begin_hook
= x_update_begin
;
12770 update_end_hook
= x_update_end
;
12771 set_terminal_window_hook
= XTset_terminal_window
;
12772 read_socket_hook
= XTread_socket
;
12773 frame_up_to_date_hook
= XTframe_up_to_date
;
12774 mouse_position_hook
= XTmouse_position
;
12775 frame_rehighlight_hook
= XTframe_rehighlight
;
12776 frame_raise_lower_hook
= XTframe_raise_lower
;
12778 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12779 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12780 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12781 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12783 scroll_region_ok
= 1; /* we'll scroll partial frames */
12784 char_ins_del_ok
= 1;
12785 line_ins_del_ok
= 1; /* we'll just blt 'em */
12786 fast_clear_end_of_line
= 1; /* X does this well */
12787 memory_below_frame
= 0; /* we don't remember what scrolls
12791 last_tool_bar_item
= -1;
12792 any_help_event_p
= 0;
12794 /* Try to use interrupt input; if we can't, then start polling. */
12795 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
12799 #if TARGET_API_MAC_CARBON
12801 install_application_handler ();
12810 init_coercion_handler ();
12812 init_apple_event_handler ();
12814 init_dm_notification_handler ();
12816 if (!inhibit_window_system
)
12818 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
12820 SetFrontProcess (&psn
);
12828 mac_init_fringe ();
12839 staticpro (&x_error_message_string
);
12840 x_error_message_string
= Qnil
;
12843 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
12844 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
12845 Qalt
= intern ("alt"); staticpro (&Qalt
);
12846 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
12847 Qsuper
= intern ("super"); staticpro (&Qsuper
);
12848 Qmodifier_value
= intern ("modifier-value");
12849 staticpro (&Qmodifier_value
);
12851 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
12852 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12853 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12854 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12855 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12857 #if TARGET_API_MAC_CARBON
12858 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
12860 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
12861 staticpro (&Qtoolbar_switch_mode
);
12862 #if USE_MAC_FONT_PANEL
12863 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12864 Qselection
= intern ("selection"); staticpro (&Qselection
);
12867 Qservice
= intern ("service"); staticpro (&Qservice
);
12868 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12869 Qperform
= intern ("perform"); staticpro (&Qperform
);
12872 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12873 Qupdate_active_input_area
= intern ("update-active-input-area");
12874 staticpro (&Qupdate_active_input_area
);
12875 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12876 staticpro (&Qunicode_for_key_event
);
12881 Fprovide (intern ("mac-carbon"), Qnil
);
12884 staticpro (&Qreverse
);
12885 Qreverse
= intern ("reverse");
12887 staticpro (&x_display_name_list
);
12888 x_display_name_list
= Qnil
;
12890 staticpro (&last_mouse_scroll_bar
);
12891 last_mouse_scroll_bar
= Qnil
;
12893 staticpro (&fm_font_family_alist
);
12894 fm_font_family_alist
= Qnil
;
12897 staticpro (&atsu_font_id_hash
);
12898 atsu_font_id_hash
= Qnil
;
12900 staticpro (&fm_style_face_attributes_alist
);
12901 fm_style_face_attributes_alist
= Qnil
;
12905 staticpro (&saved_ts_script_language_on_focus
);
12906 saved_ts_script_language_on_focus
= Qnil
;
12909 /* We don't yet support this, but defining this here avoids whining
12910 from cus-start.el and other places, like "M-x set-variable". */
12911 DEFVAR_BOOL ("x-use-underline-position-properties",
12912 &x_use_underline_position_properties
,
12913 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12914 A value of nil means ignore them. If you encounter fonts with bogus
12915 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12916 to 4.1, set this to nil.
12918 NOTE: Not supported on Mac yet. */);
12919 x_use_underline_position_properties
= 0;
12921 DEFVAR_BOOL ("x-underline-at-descent-line",
12922 &x_underline_at_descent_line
,
12923 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12924 A value of nil means to draw the underline according to the value of the
12925 variable `x-use-underline-position-properties', which is usually at the
12926 baseline level. The default value is nil. */);
12927 x_underline_at_descent_line
= 0;
12929 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12930 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12931 #ifdef USE_TOOLKIT_SCROLL_BARS
12932 Vx_toolkit_scroll_bars
= Qt
;
12934 Vx_toolkit_scroll_bars
= Qnil
;
12937 staticpro (&last_mouse_motion_frame
);
12938 last_mouse_motion_frame
= Qnil
;
12940 /* Variables to configure modifier key assignment. */
12942 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12943 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12944 The value can be `control', `meta', `alt', `hyper', or `super' for the
12945 respective modifier. The default is `control'. */);
12946 Vmac_control_modifier
= Qcontrol
;
12948 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12949 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12950 The value can be `control', `meta', `alt', `hyper', or `super' for the
12951 respective modifier. If the value is nil then the key will act as the
12952 normal Mac control modifier, and the option key can be used to compose
12953 characters depending on the chosen Mac keyboard setting. */);
12954 Vmac_option_modifier
= Qnil
;
12956 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12957 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12958 The value can be `control', `meta', `alt', `hyper', or `super' for the
12959 respective modifier. The default is `meta'. */);
12960 Vmac_command_modifier
= Qmeta
;
12962 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12963 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12964 The value can be `control', `meta', `alt', `hyper', or `super' for the
12965 respective modifier. Note that remapping the function key may lead to
12966 unexpected results for some keys on non-US/GB keyboards. */);
12967 Vmac_function_modifier
= Qnil
;
12969 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12970 &Vmac_emulate_three_button_mouse
,
12971 doc
: /* *Specify a way of three button mouse emulation.
12972 The value can be nil, t, or the symbol `reverse'.
12973 A value of nil means that no emulation should be done and the modifiers
12974 should be placed on the mouse-1 event.
12975 t means that when the option-key is held down while pressing the mouse
12976 button, the click will register as mouse-2 and while the command-key
12977 is held down, the click will register as mouse-3.
12978 The symbol `reverse' means that the option-key will register for
12979 mouse-3 and the command-key will register for mouse-2. */);
12980 Vmac_emulate_three_button_mouse
= Qnil
;
12982 #if TARGET_API_MAC_CARBON
12983 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12984 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12985 Otherwise, the right click will be treated as mouse-2 and the wheel
12986 button will be mouse-3. */);
12987 mac_wheel_button_is_mouse_2
= 1;
12989 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12990 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12991 mac_pass_command_to_system
= 1;
12993 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12994 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12995 mac_pass_control_to_system
= 1;
12999 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
13000 doc
: /* *If non-nil, allow anti-aliasing.
13001 The text will be rendered using Core Graphics text rendering which
13002 may anti-alias the text. */);
13004 mac_use_core_graphics
= 1;
13006 mac_use_core_graphics
= 0;
13009 /* Register an entry for `mac-roman' so that it can be used when
13010 creating the terminal frame on Mac OS 9 before loading
13011 term/mac-win.elc. */
13012 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
13013 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
13014 Each entry should be of the form:
13016 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13018 where CHARSET-NAME is a string used in font names to identify the
13019 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13020 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13021 Vmac_charset_info_alist
=
13022 Fcons (list3 (build_string ("mac-roman"),
13023 make_number (smRoman
), Qnil
), Qnil
);
13026 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13027 doc
: /* Overlay used to display Mac TSM active input area. */);
13028 Vmac_ts_active_input_overlay
= Qnil
;
13030 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13031 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13032 If the value is t, the input script and language are restored to those
13033 used in the last focus frame. If the value is a pair of integers, the
13034 input script and language codes, which are defined in the Script
13035 Manager, are set to its car and cdr parts, respectively. Otherwise,
13036 Emacs doesn't set them and thus follows the system default behavior. */);
13037 Vmac_ts_script_language_on_focus
= Qnil
;
13041 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13042 (do not change this comment) */