1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
62 #endif /* not TARGET_API_MAC_CARBON */
75 #include "dispextern.h"
77 #include "termhooks.h"
84 #include "intervals.h"
90 /* Non-nil means Emacs uses toolkit scroll bars. */
92 Lisp_Object Vx_toolkit_scroll_bars
;
94 /* If non-zero, the text will be rendered using Core Graphics text
95 rendering which may anti-alias the text. */
96 int mac_use_core_graphics
;
99 /* Non-zero means that a HELP_EVENT has been generated since Emacs
102 static int any_help_event_p
;
104 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
105 static Lisp_Object last_window
;
107 /* Non-zero means make use of UNDERLINE_POSITION font properties.
108 (Not yet supported.) */
109 int x_use_underline_position_properties
;
111 /* Non-zero means to draw the underline at the same place as the descent line. */
113 int x_underline_at_descent_line
;
115 /* This is a chain of structures for all the X displays currently in
118 struct x_display_info
*x_display_list
;
120 /* This is a list of cons cells, each of the form (NAME
121 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
122 x_display_list and in the same order. NAME is the name of the
123 frame. FONT-LIST-CACHE records previous values returned by
124 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
125 equivalent, which is implemented with a Lisp object, for the
128 Lisp_Object x_display_name_list
;
130 /* This is display since Mac does not support multiple ones. */
131 struct mac_display_info one_mac_display_info
;
133 /* Frame being updated by update_frame. This is declared in term.c.
134 This is set by update_begin and looked at by all the XT functions.
135 It is zero while not inside an update. In that case, the XT
136 functions assume that `selected_frame' is the frame to apply to. */
138 extern struct frame
*updating_frame
;
140 /* This is a frame waiting to be auto-raised, within XTread_socket. */
142 struct frame
*pending_autoraise_frame
;
146 Formerly, we used PointerMotionHintMask (in standard_event_mask)
147 so that we would have to call XQueryPointer after each MotionNotify
148 event to ask for another such event. However, this made mouse tracking
149 slow, and there was a bug that made it eventually stop.
151 Simply asking for MotionNotify all the time seems to work better.
153 In order to avoid asking for motion events and then throwing most
154 of them away or busy-polling the server for mouse positions, we ask
155 the server for pointer motion hints. This means that we get only
156 one event per group of mouse movements. "Groups" are delimited by
157 other kinds of events (focus changes and button clicks, for
158 example), or by XQueryPointer calls; when one of these happens, we
159 get another MotionNotify event the next time the mouse moves. This
160 is at least as efficient as getting motion events when mouse
161 tracking is on, and I suspect only negligibly worse when tracking
164 /* Where the mouse was last time we reported a mouse event. */
166 static Rect last_mouse_glyph
;
167 static FRAME_PTR last_mouse_glyph_frame
;
169 /* The scroll bar in which the last X motion event occurred.
171 If the last X motion event occurred in a scroll bar, we set this so
172 XTmouse_position can know whether to report a scroll bar motion or
175 If the last X motion event didn't occur in a scroll bar, we set
176 this to Qnil, to tell XTmouse_position to return an ordinary motion
179 static Lisp_Object last_mouse_scroll_bar
;
181 /* This is a hack. We would really prefer that XTmouse_position would
182 return the time associated with the position it returns, but there
183 doesn't seem to be any way to wrest the time-stamp from the server
184 along with the position query. So, we just keep track of the time
185 of the last movement we received, and return that in hopes that
186 it's somewhat accurate. */
188 static Time last_mouse_movement_time
;
190 struct scroll_bar
*tracked_scroll_bar
= NULL
;
192 /* Incremented by XTread_socket whenever it really tries to read
196 static int volatile input_signal_count
;
198 static int input_signal_count
;
201 extern Lisp_Object Vsystem_name
;
203 extern Lisp_Object Qeql
;
205 /* A mask of extra modifier bits to put into every keyboard char. */
207 extern EMACS_INT extra_keyboard_modifiers
;
209 /* The keysyms to use for the various modifiers. */
211 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
213 extern int inhibit_window_system
;
215 #if __MRC__ && !TARGET_API_MAC_CARBON
216 QDGlobals qd
; /* QuickDraw global information structure. */
219 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
221 struct mac_display_info
*mac_display_info_for_display (Display
*);
222 static void x_update_window_end
P_ ((struct window
*, int, int));
223 int x_catch_errors
P_ ((Display
*));
224 void x_uncatch_errors
P_ ((Display
*, int));
225 void x_lower_frame
P_ ((struct frame
*));
226 void x_scroll_bar_clear
P_ ((struct frame
*));
227 int x_had_errors_p
P_ ((Display
*));
228 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
229 void x_raise_frame
P_ ((struct frame
*));
230 void x_set_window_size
P_ ((struct frame
*, int, int, int));
231 void x_wm_set_window_state
P_ ((struct frame
*, int));
232 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
233 void mac_initialize
P_ ((void));
234 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
235 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
236 static void x_update_end
P_ ((struct frame
*));
237 static void XTframe_up_to_date
P_ ((struct frame
*));
238 static void XTset_terminal_modes
P_ ((void));
239 static void XTreset_terminal_modes
P_ ((void));
240 static void x_clear_frame
P_ ((void));
241 static void frame_highlight
P_ ((struct frame
*));
242 static void frame_unhighlight
P_ ((struct frame
*));
243 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
244 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
245 struct frame
*, struct input_event
*));
246 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
248 struct input_event
*));
249 static void XTframe_rehighlight
P_ ((struct frame
*));
250 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
251 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
252 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
253 enum text_cursor_kinds
));
255 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
256 static void x_flush
P_ ((struct frame
*f
));
257 static void x_update_begin
P_ ((struct frame
*));
258 static void x_update_window_begin
P_ ((struct window
*));
259 static void x_after_update_window_line
P_ ((struct glyph_row
*));
260 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
261 enum scroll_bar_part
*,
262 Lisp_Object
*, Lisp_Object
*,
265 static int is_emacs_window
P_ ((WindowPtr
));
266 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
267 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
269 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
270 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
271 #define GC_FONT(gc) ((gc)->xgcv.font)
272 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
274 #define CG_SET_FILL_COLOR(context, color) \
275 CGContextSetRGBFillColor (context, \
276 RED_FROM_ULONG (color) / 255.0f, \
277 GREEN_FROM_ULONG (color) / 255.0f, \
278 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
279 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
280 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
281 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
283 if (CGColorGetTypeID != NULL) \
284 CGContextSetFillColorWithColor (context, cg_color); \
286 CG_SET_FILL_COLOR (context, color); \
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CGContextSetFillColorWithColor (context, cg_color)
293 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
294 CG_SET_FILL_COLOR (context, color)
296 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
297 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
299 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
300 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
304 #define CG_SET_STROKE_COLOR(context, color) \
305 CGContextSetRGBStrokeColor (context, \
306 RED_FROM_ULONG (color) / 255.0f, \
307 GREEN_FROM_ULONG (color) / 255.0f, \
308 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
309 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
310 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
311 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
313 if (CGColorGetTypeID != NULL) \
314 CGContextSetStrokeColorWithColor (context, cg_color); \
316 CG_SET_STROKE_COLOR (context, color); \
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CGContextSetStrokeColorWithColor (context, cg_color)
323 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
324 CG_SET_STROKE_COLOR (context, color)
326 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
327 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
331 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
333 /* Fringe bitmaps. */
335 static int max_fringe_bmp
= 0;
336 static CGImageRef
*fringe_bmp
= 0;
338 static CGColorSpaceRef mac_cg_color_space_rgb
;
339 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
340 static CGColorRef mac_cg_color_black
;
346 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
347 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
348 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
349 /* Don't check the availability of CGColorCreate; this symbol is
350 defined even in Mac OS X 10.1. */
351 if (CGColorGetTypeID
!= NULL
)
354 float rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
356 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
362 mac_begin_cg_clip (f
, gc
)
366 CGContextRef context
= FRAME_CG_CONTEXT (f
);
370 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
371 FRAME_CG_CONTEXT (f
) = context
;
374 CGContextSaveGState (context
);
375 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
376 CGContextScaleCTM (context
, 1, -1);
377 if (gc
&& gc
->n_clip_rects
)
378 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
387 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
391 mac_prepare_for_quickdraw (f
)
396 Lisp_Object rest
, frame
;
397 FOR_EACH_FRAME (rest
, frame
)
398 if (FRAME_MAC_P (XFRAME (frame
)))
399 mac_prepare_for_quickdraw (XFRAME (frame
));
403 CGContextRef context
= FRAME_CG_CONTEXT (f
);
407 CGContextSynchronize (context
);
408 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
409 &FRAME_CG_CONTEXT (f
));
415 static RgnHandle saved_port_clip_region
= NULL
;
421 static RgnHandle new_region
= NULL
;
423 if (saved_port_clip_region
== NULL
)
424 saved_port_clip_region
= NewRgn ();
425 if (new_region
== NULL
)
426 new_region
= NewRgn ();
428 if (gc
->n_clip_rects
)
430 GetClip (saved_port_clip_region
);
431 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
432 SetClip (new_region
);
440 if (gc
->n_clip_rects
)
441 SetClip (saved_port_clip_region
);
445 /* X display function emulation */
448 XFreePixmap (display
, pixmap
)
449 Display
*display
; /* not used */
452 DisposeGWorld (pixmap
);
456 /* Mac version of XDrawLine. */
459 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
465 CGContextRef context
;
466 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
469 gx1
+= 0.5f
, gx2
+= 0.5f
;
471 gy1
+= 0.5f
, gy2
+= 0.5f
;
473 context
= mac_begin_cg_clip (f
, gc
);
474 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
475 CGContextBeginPath (context
);
476 CGContextMoveToPoint (context
, gx1
, gy1
);
477 CGContextAddLineToPoint (context
, gx2
, gy2
);
478 CGContextClosePath (context
);
479 CGContextStrokePath (context
);
497 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
499 RGBForeColor (GC_FORE_COLOR (gc
));
509 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
533 GetGWorld (&old_port
, &old_gdh
);
536 RGBForeColor (GC_FORE_COLOR (gc
));
538 LockPixels (GetGWorldPixMap (p
));
541 UnlockPixels (GetGWorldPixMap (p
));
543 SetGWorld (old_port
, old_gdh
);
548 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
552 unsigned int width
, height
;
555 CGContextRef context
;
557 context
= mac_begin_cg_clip (f
, gc
);
558 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
559 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
564 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
566 RGBBackColor (GC_BACK_COLOR (gc
));
567 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
573 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
578 /* Mac version of XClearArea. */
581 mac_clear_area (f
, x
, y
, width
, height
)
584 unsigned int width
, height
;
586 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
589 /* Mac version of XClearWindow. */
596 CGContextRef context
;
597 GC gc
= FRAME_NORMAL_GC (f
);
599 context
= mac_begin_cg_clip (f
, NULL
);
600 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
601 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
602 FRAME_PIXEL_HEIGHT (f
)));
605 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
607 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
609 #if TARGET_API_MAC_CARBON
613 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
616 #else /* not TARGET_API_MAC_CARBON */
617 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
618 #endif /* not TARGET_API_MAC_CARBON */
623 /* Mac replacement for XCopyArea. */
627 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
628 dest_x
, dest_y
, overlay_p
)
633 unsigned int width
, height
;
634 int dest_x
, dest_y
, overlay_p
;
636 CGContextRef context
;
637 float port_height
= FRAME_PIXEL_HEIGHT (f
);
638 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
640 context
= mac_begin_cg_clip (f
, gc
);
643 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
644 CGContextFillRect (context
, dest_rect
);
646 CGContextClipToRect (context
, dest_rect
);
647 CGContextScaleCTM (context
, 1, -1);
648 CGContextTranslateCTM (context
, 0, -port_height
);
649 if (CGImageIsMask (image
))
650 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
651 CGContextDrawImage (context
,
652 CGRectMake (dest_x
- src_x
,
653 port_height
- (dest_y
- src_y
654 + CGImageGetHeight (image
)),
655 CGImageGetWidth (image
),
656 CGImageGetHeight (image
)),
661 #else /* !USE_CG_DRAWING */
664 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
667 int x
, y
, width
, height
;
668 unsigned short *bits
;
674 bitmap
.rowBytes
= sizeof(unsigned short);
675 bitmap
.baseAddr
= (char *)bits
;
676 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
678 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
680 RGBForeColor (GC_FORE_COLOR (gc
));
681 RGBBackColor (GC_BACK_COLOR (gc
));
682 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
685 #if TARGET_API_MAC_CARBON
691 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
692 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
693 UnlockPortBits (port
);
695 #else /* not TARGET_API_MAC_CARBON */
696 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
697 overlay_p
? srcOr
: srcCopy
, 0);
698 #endif /* not TARGET_API_MAC_CARBON */
701 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
703 #endif /* !USE_CG_DRAWING */
706 /* Mac replacement for XCreateBitmapFromBitmapData. */
709 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
714 static const unsigned char swap_nibble
[16]
715 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
716 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
717 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
718 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
722 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
723 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
724 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
725 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
726 for (i
= 0; i
< h
; i
++)
728 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
729 for (j
= 0; j
< w1
; j
++)
731 /* Bitswap XBM bytes to match how Mac does things. */
732 unsigned char c
= *bits
++;
733 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
734 | (swap_nibble
[(c
>>4) & 0xf]));;
738 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
743 mac_free_bitmap (bitmap
)
746 xfree (bitmap
->baseAddr
);
751 XCreatePixmap (display
, w
, width
, height
, depth
)
752 Display
*display
; /* not used */
754 unsigned int width
, height
;
761 SetPortWindowPort (w
);
763 SetRect (&r
, 0, 0, width
, height
);
764 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
767 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
768 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
770 /* CreateCGImageFromPixMaps requires ARGB format. */
771 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
780 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
781 Display
*display
; /* not used */
784 unsigned int width
, height
;
785 unsigned long fg
, bg
;
792 static GC gc
= NULL
; /* not reentrant */
795 gc
= XCreateGC (display
, w
, 0, NULL
);
797 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
801 GetGWorld (&old_port
, &old_gdh
);
802 SetGWorld (pixmap
, NULL
);
803 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
804 XSetForeground (display
, gc
, fg
);
805 XSetBackground (display
, gc
, bg
);
806 RGBForeColor (GC_FORE_COLOR (gc
));
807 RGBBackColor (GC_BACK_COLOR (gc
));
808 LockPixels (GetGWorldPixMap (pixmap
));
809 #if TARGET_API_MAC_CARBON
810 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
811 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
812 #else /* not TARGET_API_MAC_CARBON */
813 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
814 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
815 #endif /* not TARGET_API_MAC_CARBON */
816 UnlockPixels (GetGWorldPixMap (pixmap
));
817 SetGWorld (old_port
, old_gdh
);
818 mac_free_bitmap (&bitmap
);
824 /* Mac replacement for XFillRectangle. */
827 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
831 unsigned int width
, height
;
834 CGContextRef context
;
836 context
= mac_begin_cg_clip (f
, gc
);
837 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
838 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
843 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
845 RGBForeColor (GC_FORE_COLOR (gc
));
846 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
849 PaintRect (&r
); /* using foreground color of gc */
855 /* Mac replacement for XDrawRectangle: dest is a window. */
858 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
862 unsigned int width
, height
;
865 CGContextRef context
;
867 context
= mac_begin_cg_clip (f
, gc
);
868 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
869 CGContextStrokeRect (context
,
870 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
875 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
877 RGBForeColor (GC_FORE_COLOR (gc
));
878 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
881 FrameRect (&r
); /* using foreground color of gc */
889 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
890 ConstUniCharArrayPtr text
;
891 UniCharCount text_length
;
893 ATSUTextLayout
*text_layout
;
896 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
898 if (saved_text_layout
== NULL
)
900 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
901 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
902 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
903 static ATSLineLayoutOptions line_layout
=
904 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
905 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
906 | kATSLineUseQDRendering
908 kATSLineIsDisplayOnly
| kATSLineFractDisable
911 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
913 err
= ATSUCreateTextLayoutWithTextPtr (text
,
914 kATSUFromTextBeginning
,
920 err
= ATSUSetLayoutControls (saved_text_layout
,
921 sizeof (tags
) / sizeof (tags
[0]),
922 tags
, sizes
, values
);
923 /* XXX: Should we do this? */
925 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
929 err
= ATSUSetRunStyle (saved_text_layout
, style
,
930 kATSUFromTextBeginning
, kATSUToTextEnd
);
932 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
933 kATSUFromTextBeginning
,
939 *text_layout
= saved_text_layout
;
946 mac_invert_rectangle (f
, x
, y
, width
, height
)
949 unsigned int width
, height
;
954 mac_prepare_for_quickdraw (f
);
956 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
958 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
965 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
966 overstrike_p
, bytes_per_char
)
971 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
973 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
976 if (GC_FONT (gc
)->mac_style
)
979 ATSUTextLayout text_layout
;
981 xassert (bytes_per_char
== 2);
983 #ifndef WORDS_BIG_ENDIAN
986 UniChar
*text
= (UniChar
*)buf
;
988 for (i
= 0; i
< nchars
; i
++)
989 text
[i
] = EndianU16_BtoN (text
[i
]);
992 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
994 GC_FONT (gc
)->mac_style
,
999 if (!mac_use_core_graphics
)
1003 mac_prepare_for_quickdraw (f
);
1005 mac_begin_clip (gc
);
1006 RGBForeColor (GC_FORE_COLOR (gc
));
1011 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1012 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1013 RGBBackColor (GC_BACK_COLOR (gc
));
1015 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1018 ATSUDrawText (text_layout
,
1019 kATSUFromTextBeginning
, kATSUToTextEnd
,
1020 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1024 ATSUDrawText (text_layout
,
1025 kATSUFromTextBeginning
, kATSUToTextEnd
,
1026 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1034 static CGContextRef context
;
1035 float port_height
= FRAME_PIXEL_HEIGHT (f
);
1036 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1037 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1038 static const ATSUAttributeValuePtr values
[] = {&context
};
1041 context
= mac_begin_cg_clip (f
, gc
);
1044 QDBeginCGContext (port
, &context
);
1045 if (gc
->n_clip_rects
|| bg_width
)
1047 CGContextTranslateCTM (context
, 0, port_height
);
1048 CGContextScaleCTM (context
, 1, -1);
1049 if (gc
->n_clip_rects
)
1050 CGContextClipToRects (context
, gc
->clip_rects
,
1055 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1058 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
1059 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1061 CGContextScaleCTM (context
, 1, -1);
1062 CGContextTranslateCTM (context
, 0, -port_height
);
1066 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1067 err
= ATSUSetLayoutControls (text_layout
,
1068 sizeof (tags
) / sizeof (tags
[0]),
1069 tags
, sizes
, values
);
1072 ATSUDrawText (text_layout
,
1073 kATSUFromTextBeginning
, kATSUToTextEnd
,
1074 Long2Fix (x
), Long2Fix (port_height
- y
));
1076 ATSUDrawText (text_layout
,
1077 kATSUFromTextBeginning
, kATSUToTextEnd
,
1078 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1081 mac_end_cg_clip (f
);
1084 CGContextSynchronize (context
);
1085 QDEndCGContext (port
, &context
);
1088 /* This doesn't work on Mac OS X 10.1. */
1089 ATSUClearLayoutControls (text_layout
,
1090 sizeof (tags
) / sizeof (tags
[0]), tags
);
1092 ATSUSetLayoutControls (text_layout
,
1093 sizeof (tags
) / sizeof (tags
[0]),
1094 tags
, sizes
, values
);
1097 #endif /* MAC_OSX */
1100 #endif /* USE_ATSUI */
1102 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1105 if (mac_use_core_graphics
)
1106 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1109 mac_prepare_for_quickdraw (f
);
1111 mac_begin_clip (gc
);
1112 RGBForeColor (GC_FORE_COLOR (gc
));
1116 RGBBackColor (GC_BACK_COLOR (gc
));
1122 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1124 - Screen is double-buffered. (In srcCopy mode, a text is
1125 drawn into an offscreen graphics world first. So
1126 performance gain cannot be expected.)
1127 - It lowers rendering quality.
1128 - Some fonts leave garbage on cursor movement. */
1133 RGBBackColor (GC_BACK_COLOR (gc
));
1134 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1135 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1140 TextFont (GC_FONT (gc
)->mac_fontnum
);
1141 TextSize (GC_FONT (gc
)->mac_fontsize
);
1142 TextFace (GC_FONT (gc
)->mac_fontface
);
1144 DrawText (buf
, 0, nchars
* bytes_per_char
);
1149 DrawText (buf
, 0, nchars
* bytes_per_char
);
1152 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1155 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1156 if (mac_use_core_graphics
)
1157 SwapQDTextFlags(savedFlags
);
1163 /* Mac replacement for XDrawImageString. */
1166 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1171 int nchars
, bg_width
, overstrike_p
;
1173 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1178 /* Mac replacement for XDrawImageString16. */
1181 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1186 int nchars
, bg_width
, overstrike_p
;
1188 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1193 /* Mac replacement for XQueryTextExtents, but takes a character. If
1194 STYLE is NULL, measurement is done by QuickDraw Text routines for
1195 the font of the current graphics port. If CG_GLYPH is not NULL,
1196 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1199 mac_query_char_extents (style
, c
,
1200 font_ascent_return
, font_descent_return
,
1201 overall_return
, cg_glyph
)
1208 int *font_ascent_return
, *font_descent_return
;
1209 XCharStruct
*overall_return
;
1210 #if USE_CG_TEXT_DRAWING
1216 OSStatus err
= noErr
;
1223 ATSUTextLayout text_layout
;
1226 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1228 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1230 ATSTrapezoid glyph_bounds
;
1232 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1233 kATSUFromTextBeginning
, kATSUToTextEnd
,
1234 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1235 kATSUseFractionalOrigins
,
1237 kATSUseDeviceOrigins
,
1239 1, &glyph_bounds
, NULL
);
1242 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1243 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1245 width
= Fix2Long (glyph_bounds
.upperRight
.x
1246 - glyph_bounds
.upperLeft
.x
);
1247 if (font_ascent_return
)
1248 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1249 if (font_descent_return
)
1250 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1253 if (err
== noErr
&& overall_return
)
1255 err
= ATSUMeasureTextImage (text_layout
,
1256 kATSUFromTextBeginning
, kATSUToTextEnd
,
1257 0, 0, &char_bounds
);
1259 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1260 #if USE_CG_TEXT_DRAWING
1261 if (err
== noErr
&& cg_glyph
)
1264 ATSUGlyphInfoArray glyph_info_array
;
1265 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1267 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1268 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1270 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1271 kATSUToTextEnd
, &count
,
1274 /* Make sure that we don't have to make layout
1276 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1277 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1278 && glyph_info_array
.glyphs
[0].screenX
== 0)
1280 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1281 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1292 if (font_ascent_return
|| font_descent_return
)
1296 GetFontInfo (&font_info
);
1297 if (font_ascent_return
)
1298 *font_ascent_return
= font_info
.ascent
;
1299 if (font_descent_return
)
1300 *font_descent_return
= font_info
.descent
;
1306 width
= CharWidth (ch
);
1307 QDTextBounds (1, &ch
, &char_bounds
);
1308 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1316 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1319 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1320 XFontStruct
*font_struct
;
1323 XCharStruct
*overall_return
;
1326 short width
= 0, lbearing
= 0, rbearing
= 0;
1329 for (i
= 0; i
< nchars
; i
++)
1331 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1333 width
+= FONT_WIDTH (font_struct
);
1336 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1337 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1338 width
+= pcm
->width
;
1343 overall_return
->lbearing
= lbearing
;
1344 overall_return
->rbearing
= rbearing
;
1345 overall_return
->width
= width
;
1347 /* What's the meaning of the return value of XTextExtents16? */
1351 #if USE_CG_TEXT_DRAWING
1352 static int cg_text_anti_aliasing_threshold
= 8;
1355 init_cg_text_anti_aliasing_threshold ()
1361 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1362 kCFPreferencesCurrentApplication
,
1365 cg_text_anti_aliasing_threshold
= threshold
;
1369 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1374 int nchars
, bg_width
, overstrike_p
;
1377 float port_height
, gx
, gy
;
1379 CGContextRef context
;
1383 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1386 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1387 port_height
= FRAME_PIXEL_HEIGHT (f
);
1389 gy
= port_height
- y
;
1390 glyphs
= (CGGlyph
*)buf
;
1391 advances
= alloca (sizeof (CGSize
) * nchars
);
1392 if (advances
== NULL
)
1394 for (i
= 0; i
< nchars
; i
++)
1396 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1398 advances
[i
].width
= pcm
->width
;
1399 advances
[i
].height
= 0;
1400 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1405 context
= mac_begin_cg_clip (f
, gc
);
1407 QDBeginCGContext (port
, &context
);
1408 if (gc
->n_clip_rects
|| bg_width
)
1410 CGContextTranslateCTM (context
, 0, port_height
);
1411 CGContextScaleCTM (context
, 1, -1);
1412 if (gc
->n_clip_rects
)
1413 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1417 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1420 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1421 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1423 CGContextScaleCTM (context
, 1, -1);
1424 CGContextTranslateCTM (context
, 0, -port_height
);
1428 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1429 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1430 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1431 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1432 CGContextSetShouldAntialias (context
, false);
1433 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1434 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1435 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1438 CGContextSetTextPosition (context
, gx
, gy
);
1439 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1442 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1443 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1446 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1449 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1450 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1452 for (i
= 0; i
< nchars
; i
++)
1454 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1456 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1457 gx
+= advances
[i
].width
;
1462 mac_end_cg_clip (f
);
1464 CGContextSynchronize (context
);
1465 QDEndCGContext (port
, &context
);
1474 /* Mac replacement for XCopyArea: dest must be window. */
1477 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1482 unsigned int width
, height
;
1487 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1489 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1490 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1492 ForeColor (blackColor
);
1493 BackColor (whiteColor
);
1495 mac_begin_clip (gc
);
1496 LockPixels (GetGWorldPixMap (src
));
1497 #if TARGET_API_MAC_CARBON
1502 LockPortBits (port
);
1503 CopyBits (GetPortBitMapForCopyBits (src
),
1504 GetPortBitMapForCopyBits (port
),
1505 &src_r
, &dest_r
, srcCopy
, 0);
1506 UnlockPortBits (port
);
1508 #else /* not TARGET_API_MAC_CARBON */
1509 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1510 &src_r
, &dest_r
, srcCopy
, 0);
1511 #endif /* not TARGET_API_MAC_CARBON */
1512 UnlockPixels (GetGWorldPixMap (src
));
1515 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1520 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1521 width
, height
, dest_x
, dest_y
)
1526 unsigned int width
, height
;
1531 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1533 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1534 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1536 ForeColor (blackColor
);
1537 BackColor (whiteColor
);
1539 mac_begin_clip (gc
);
1540 LockPixels (GetGWorldPixMap (src
));
1541 LockPixels (GetGWorldPixMap (mask
));
1542 #if TARGET_API_MAC_CARBON
1547 LockPortBits (port
);
1548 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1549 GetPortBitMapForCopyBits (port
),
1550 &src_r
, &src_r
, &dest_r
);
1551 UnlockPortBits (port
);
1553 #else /* not TARGET_API_MAC_CARBON */
1554 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1555 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1556 #endif /* not TARGET_API_MAC_CARBON */
1557 UnlockPixels (GetGWorldPixMap (mask
));
1558 UnlockPixels (GetGWorldPixMap (src
));
1561 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1563 #endif /* !USE_CG_DRAWING */
1566 /* Mac replacement for XCopyArea: used only for scrolling. */
1569 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1573 unsigned int width
, height
;
1576 #if TARGET_API_MAC_CARBON
1578 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1580 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1582 mac_prepare_for_quickdraw (f
);
1584 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1585 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1586 kScrollWindowNoOptions
, dummy
);
1588 #else /* not TARGET_API_MAC_CARBON */
1590 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1594 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1595 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1597 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1598 color mapping in CopyBits. Otherwise, it will be slow. */
1599 ForeColor (blackColor
);
1600 BackColor (whiteColor
);
1601 mac_begin_clip (gc
);
1602 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1605 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1606 #endif /* not TARGET_API_MAC_CARBON */
1610 /* Mac replacement for XChangeGC. */
1613 XChangeGC (display
, gc
, mask
, xgcv
)
1619 if (mask
& GCForeground
)
1620 XSetForeground (display
, gc
, xgcv
->foreground
);
1621 if (mask
& GCBackground
)
1622 XSetBackground (display
, gc
, xgcv
->background
);
1624 XSetFont (display
, gc
, xgcv
->font
);
1628 /* Mac replacement for XCreateGC. */
1631 XCreateGC (display
, window
, mask
, xgcv
)
1637 GC gc
= xmalloc (sizeof (*gc
));
1639 bzero (gc
, sizeof (*gc
));
1640 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1641 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1642 if (CGColorGetTypeID
!= NULL
)
1645 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1646 CGColorRetain (gc
->cg_fore_color
);
1647 CGColorRetain (gc
->cg_back_color
);
1650 XChangeGC (display
, gc
, mask
, xgcv
);
1656 /* Used in xfaces.c. */
1659 XFreeGC (display
, gc
)
1663 if (gc
->clip_region
)
1664 DisposeRgn (gc
->clip_region
);
1665 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1666 CGColorRelease (gc
->cg_fore_color
);
1667 CGColorRelease (gc
->cg_back_color
);
1673 /* Mac replacement for XGetGCValues. */
1676 XGetGCValues (display
, gc
, mask
, xgcv
)
1682 if (mask
& GCForeground
)
1683 xgcv
->foreground
= gc
->xgcv
.foreground
;
1684 if (mask
& GCBackground
)
1685 xgcv
->background
= gc
->xgcv
.background
;
1687 xgcv
->font
= gc
->xgcv
.font
;
1691 /* Mac replacement for XSetForeground. */
1694 XSetForeground (display
, gc
, color
)
1697 unsigned long color
;
1699 if (gc
->xgcv
.foreground
!= color
)
1701 gc
->xgcv
.foreground
= color
;
1702 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1703 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1704 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1705 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1706 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1707 if (CGColorGetTypeID
!= NULL
)
1710 CGColorRelease (gc
->cg_fore_color
);
1713 gc
->cg_fore_color
= mac_cg_color_black
;
1714 CGColorRetain (gc
->cg_fore_color
);
1720 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1721 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1722 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1724 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1732 /* Mac replacement for XSetBackground. */
1735 XSetBackground (display
, gc
, color
)
1738 unsigned long color
;
1740 if (gc
->xgcv
.background
!= color
)
1742 gc
->xgcv
.background
= color
;
1743 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1744 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1745 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1746 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1747 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1748 if (CGColorGetTypeID
!= NULL
)
1751 CGColorRelease (gc
->cg_back_color
);
1754 gc
->cg_back_color
= mac_cg_color_black
;
1755 CGColorRetain (gc
->cg_back_color
);
1761 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1762 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1763 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1765 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1773 /* Mac replacement for XSetFont. */
1776 XSetFont (display
, gc
, font
)
1781 gc
->xgcv
.font
= font
;
1785 /* Mac replacement for XSetClipRectangles. */
1788 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1796 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1798 gc
->n_clip_rects
= n
;
1801 if (gc
->clip_region
== NULL
)
1802 gc
->clip_region
= NewRgn ();
1803 RectRgn (gc
->clip_region
, rectangles
);
1806 RgnHandle region
= NewRgn ();
1808 for (i
= 1; i
< n
; i
++)
1810 RectRgn (region
, rectangles
+ i
);
1811 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1813 DisposeRgn (region
);
1816 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1817 for (i
= 0; i
< n
; i
++)
1819 Rect
*rect
= rectangles
+ i
;
1821 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1822 rect
->right
- rect
->left
,
1823 rect
->bottom
- rect
->top
);
1829 /* Mac replacement for XSetClipMask. */
1832 mac_reset_clip_rectangles (display
, gc
)
1836 gc
->n_clip_rects
= 0;
1840 /* Mac replacement for XSetWindowBackground. */
1843 XSetWindowBackground (display
, w
, color
)
1846 unsigned long color
;
1848 #if !TARGET_API_MAC_CARBON
1849 AuxWinHandle aw_handle
;
1850 CTabHandle ctab_handle
;
1851 ColorSpecPtr ct_table
;
1856 bg_color
.red
= RED16_FROM_ULONG (color
);
1857 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1858 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1860 #if TARGET_API_MAC_CARBON
1861 SetWindowContentColor (w
, &bg_color
);
1863 if (GetAuxWin (w
, &aw_handle
))
1865 ctab_handle
= (*aw_handle
)->awCTable
;
1866 HandToHand ((Handle
*) &ctab_handle
);
1867 ct_table
= (*ctab_handle
)->ctTable
;
1868 ct_size
= (*ctab_handle
)->ctSize
;
1869 while (ct_size
> -1)
1871 if (ct_table
->value
== 0)
1873 ct_table
->rgb
= bg_color
;
1874 CTabChanged (ctab_handle
);
1875 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1883 /* Flush display of frame F, or of all frames if F is null. */
1889 #if TARGET_API_MAC_CARBON
1892 mac_prepare_for_quickdraw (f
);
1895 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1897 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1903 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1904 Calls to XFlush should be unnecessary because the X output buffer
1905 is flushed automatically as needed by calls to XPending,
1906 XNextEvent, or XWindowEvent according to the XFlush man page.
1907 XTread_socket calls XPending. Removing XFlush improves
1910 #define XFlush(DISPLAY) (void) 0
1913 /* Return the struct mac_display_info corresponding to DPY. There's
1916 struct mac_display_info
*
1917 mac_display_info_for_display (dpy
)
1920 return &one_mac_display_info
;
1925 /***********************************************************************
1926 Starting and ending an update
1927 ***********************************************************************/
1929 /* Start an update of frame F. This function is installed as a hook
1930 for update_begin, i.e. it is called when update_begin is called.
1931 This function is called prior to calls to x_update_window_begin for
1932 each window being updated. */
1938 #if TARGET_API_MAC_CARBON
1939 /* During update of a frame, availability of input events is
1940 periodically checked with ReceiveNextEvent if
1941 redisplay-dont-pause is nil. That normally flushes window buffer
1942 changes for every check, and thus screen update looks waving even
1943 if no input is available. So we disable screen updates during
1944 update of a frame. */
1946 DisableScreenUpdates ();
1952 /* Start update of window W. Set the global variable updated_window
1953 to the window being updated and set output_cursor to the cursor
1957 x_update_window_begin (w
)
1960 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1961 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1964 set_output_cursor (&w
->cursor
);
1968 if (f
== display_info
->mouse_face_mouse_frame
)
1970 /* Don't do highlighting for mouse motion during the update. */
1971 display_info
->mouse_face_defer
= 1;
1973 /* If F needs to be redrawn, simply forget about any prior mouse
1975 if (FRAME_GARBAGED_P (f
))
1976 display_info
->mouse_face_window
= Qnil
;
1978 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1979 their mouse_face_p flag set, which means that they are always
1980 unequal to rows in a desired matrix which never have that
1981 flag set. So, rows containing mouse-face glyphs are never
1982 scrolled, and we don't have to switch the mouse highlight off
1983 here to prevent it from being scrolled. */
1985 /* Can we tell that this update does not affect the window
1986 where the mouse highlight is? If so, no need to turn off.
1987 Likewise, don't do anything if the frame is garbaged;
1988 in that case, the frame's current matrix that we would use
1989 is all wrong, and we will redisplay that line anyway. */
1990 if (!NILP (display_info
->mouse_face_window
)
1991 && w
== XWINDOW (display_info
->mouse_face_window
))
1995 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1996 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1999 if (i
< w
->desired_matrix
->nrows
)
2000 clear_mouse_face (display_info
);
2009 /* Draw a vertical window border from (x,y0) to (x,y1) */
2012 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2016 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2019 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2021 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2024 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2027 /* End update of window W (which is equal to updated_window).
2029 Draw vertical borders between horizontally adjacent windows, and
2030 display W's cursor if CURSOR_ON_P is non-zero.
2032 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2033 glyphs in mouse-face were overwritten. In that case we have to
2034 make sure that the mouse-highlight is properly redrawn.
2036 W may be a menu bar pseudo-window in case we don't have X toolkit
2037 support. Such windows don't have a cursor, so don't display it
2041 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2043 int cursor_on_p
, mouse_face_overwritten_p
;
2045 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2047 if (!w
->pseudo_window_p
)
2052 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2054 output_cursor
.x
, output_cursor
.y
);
2056 if (draw_window_fringes (w
, 1))
2057 x_draw_vertical_border (w
);
2062 /* If a row with mouse-face was overwritten, arrange for
2063 XTframe_up_to_date to redisplay the mouse highlight. */
2064 if (mouse_face_overwritten_p
)
2066 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2067 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2068 dpyinfo
->mouse_face_window
= Qnil
;
2071 updated_window
= NULL
;
2075 /* End update of frame F. This function is installed as a hook in
2082 /* Mouse highlight may be displayed again. */
2083 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2086 #if TARGET_API_MAC_CARBON
2087 EnableScreenUpdates ();
2089 XFlush (FRAME_MAC_DISPLAY (f
));
2094 /* This function is called from various places in xdisp.c whenever a
2095 complete update has been performed. The global variable
2096 updated_window is not available here. */
2099 XTframe_up_to_date (f
)
2102 if (FRAME_MAC_P (f
))
2104 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2106 if (dpyinfo
->mouse_face_deferred_gc
2107 || f
== dpyinfo
->mouse_face_mouse_frame
)
2110 if (dpyinfo
->mouse_face_mouse_frame
)
2111 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2112 dpyinfo
->mouse_face_mouse_x
,
2113 dpyinfo
->mouse_face_mouse_y
);
2114 dpyinfo
->mouse_face_deferred_gc
= 0;
2121 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2122 arrow bitmaps, or clear the fringes if no bitmaps are required
2123 before DESIRED_ROW is made current. The window being updated is
2124 found in updated_window. This function is called from
2125 update_window_line only if it is known that there are differences
2126 between bitmaps to be drawn between current row and DESIRED_ROW. */
2129 x_after_update_window_line (desired_row
)
2130 struct glyph_row
*desired_row
;
2132 struct window
*w
= updated_window
;
2138 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2139 desired_row
->redraw_fringe_bitmaps_p
= 1;
2141 /* When a window has disappeared, make sure that no rest of
2142 full-width rows stays visible in the internal border. Could
2143 check here if updated_window is the leftmost/rightmost window,
2144 but I guess it's not worth doing since vertically split windows
2145 are almost never used, internal border is rarely set, and the
2146 overhead is very small. */
2147 if (windows_or_buffers_changed
2148 && desired_row
->full_width_p
2149 && (f
= XFRAME (w
->frame
),
2150 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2152 && (height
= desired_row
->visible_height
,
2155 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2157 /* Internal border is drawn below the tool bar. */
2158 if (WINDOWP (f
->tool_bar_window
)
2159 && w
== XWINDOW (f
->tool_bar_window
))
2163 mac_clear_area (f
, 0, y
, width
, height
);
2164 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2170 /* Draw the bitmap WHICH in one of the left or right fringes of
2171 window W. ROW is the glyph row for which to display the bitmap; it
2172 determines the vertical position at which the bitmap has to be
2176 x_draw_fringe_bitmap (w
, row
, p
)
2178 struct glyph_row
*row
;
2179 struct draw_fringe_bitmap_params
*p
;
2181 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2182 Display
*display
= FRAME_MAC_DISPLAY (f
);
2183 struct face
*face
= p
->face
;
2186 /* Must clip because of partially visible lines. */
2187 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2190 /* Adjust position of "bottom aligned" bitmap on partially
2191 visible last row. */
2193 int oldVH
= row
->visible_height
;
2194 row
->visible_height
= p
->h
;
2195 row
->y
-= rowY
- p
->y
;
2196 x_clip_to_row (w
, row
, -1, face
->gc
);
2198 row
->visible_height
= oldVH
;
2201 x_clip_to_row (w
, row
, -1, face
->gc
);
2203 if (p
->bx
>= 0 && !p
->overlay_p
)
2205 #if 0 /* MAC_TODO: stipple */
2206 /* In case the same realized face is used for fringes and
2207 for something displayed in the text (e.g. face `region' on
2208 mono-displays, the fill style may have been changed to
2209 FillSolid in x_draw_glyph_string_background. */
2211 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2213 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2216 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2218 #if 0 /* MAC_TODO: stipple */
2220 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2226 && p
->which
< max_fringe_bmp
2232 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2233 XSetForeground (display
, face
->gc
,
2235 ? (p
->overlay_p
? face
->background
2236 : f
->output_data
.mac
->cursor_pixel
)
2237 : face
->foreground
));
2239 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2240 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
2242 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2243 p
->wd
, p
->h
, p
->bits
+ p
->dh
, p
->overlay_p
);
2245 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2248 mac_reset_clip_rectangles (display
, face
->gc
);
2253 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2255 unsigned short *bits
;
2259 CGDataProviderRef provider
;
2261 if (which
>= max_fringe_bmp
)
2264 max_fringe_bmp
= which
+ 20;
2265 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2266 while (i
< max_fringe_bmp
)
2267 fringe_bmp
[i
++] = 0;
2270 for (i
= 0; i
< h
; i
++)
2272 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2273 sizeof (unsigned short) * h
, NULL
);
2276 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2277 sizeof (unsigned short),
2279 CGDataProviderRelease (provider
);
2284 mac_destroy_fringe_bitmap (which
)
2287 if (which
>= max_fringe_bmp
)
2290 if (fringe_bmp
[which
])
2291 CGImageRelease (fringe_bmp
[which
]);
2292 fringe_bmp
[which
] = 0;
2297 /* This is called when starting Emacs and when restarting after
2298 suspend. When starting Emacs, no window is mapped. And nothing
2299 must be done to Emacs's own window if it is suspended (though that
2303 XTset_terminal_modes ()
2307 /* This is called when exiting or suspending Emacs. Exiting will make
2308 the windows go away, and suspending requires no action. */
2311 XTreset_terminal_modes ()
2317 /***********************************************************************
2319 ***********************************************************************/
2321 /* Function prototypes of this page. */
2323 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2324 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2328 pcm_init (pcm
, count
)
2332 bzero (pcm
, sizeof (XCharStruct
) * count
);
2333 while (--count
>= 0)
2335 pcm
->descent
= PCM_INVALID
;
2340 static enum pcm_status
2341 pcm_get_status (pcm
)
2342 const XCharStruct
*pcm
;
2344 int height
= pcm
->ascent
+ pcm
->descent
;
2346 /* Negative height means some special status. */
2347 return height
>= 0 ? PCM_VALID
: height
;
2350 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2351 is not contained in the font. */
2353 static INLINE XCharStruct
*
2354 x_per_char_metric (font
, char2b
)
2358 /* The result metric information. */
2359 XCharStruct
*pcm
= NULL
;
2361 xassert (font
&& char2b
);
2364 if (font
->mac_style
)
2366 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2370 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2371 pcm_init (*row
, 0x100);
2373 pcm
= *row
+ char2b
->byte2
;
2374 if (pcm_get_status (pcm
) != PCM_VALID
)
2377 mac_query_char_extents (font
->mac_style
,
2378 (char2b
->byte1
<< 8) + char2b
->byte2
,
2379 NULL
, NULL
, pcm
, NULL
);
2386 if (font
->bounds
.per_char
!= NULL
)
2388 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2390 /* min_char_or_byte2 specifies the linear character index
2391 corresponding to the first element of the per_char array,
2392 max_char_or_byte2 is the index of the last character. A
2393 character with non-zero CHAR2B->byte1 is not in the font.
2394 A character with byte2 less than min_char_or_byte2 or
2395 greater max_char_or_byte2 is not in the font. */
2396 if (char2b
->byte1
== 0
2397 && char2b
->byte2
>= font
->min_char_or_byte2
2398 && char2b
->byte2
<= font
->max_char_or_byte2
)
2399 pcm
= font
->bounds
.per_char
2400 + (char2b
->byte2
- font
->min_char_or_byte2
);
2404 /* If either min_byte1 or max_byte1 are nonzero, both
2405 min_char_or_byte2 and max_char_or_byte2 are less than
2406 256, and the 2-byte character index values corresponding
2407 to the per_char array element N (counting from 0) are:
2409 byte1 = N/D + min_byte1
2410 byte2 = N\D + min_char_or_byte2
2414 D = max_char_or_byte2 - min_char_or_byte2 + 1
2415 / = integer division
2416 \ = integer modulus */
2417 if (char2b
->byte1
>= font
->min_byte1
2418 && char2b
->byte1
<= font
->max_byte1
2419 && char2b
->byte2
>= font
->min_char_or_byte2
2420 && char2b
->byte2
<= font
->max_char_or_byte2
)
2422 pcm
= (font
->bounds
.per_char
2423 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2424 * (char2b
->byte1
- font
->min_byte1
))
2425 + (char2b
->byte2
- font
->min_char_or_byte2
));
2431 /* If the per_char pointer is null, all glyphs between the first
2432 and last character indexes inclusive have the same
2433 information, as given by both min_bounds and max_bounds. */
2434 if (char2b
->byte2
>= font
->min_char_or_byte2
2435 && char2b
->byte2
<= font
->max_char_or_byte2
)
2436 pcm
= &font
->max_bounds
;
2442 return ((pcm
== NULL
2444 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2445 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2454 static XCharStruct
*
2455 mac_per_char_metric (font
, char2b
, font_type
)
2460 return x_per_char_metric (font
, char2b
);
2464 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2465 the two-byte form of C. Encoding is returned in *CHAR2B. */
2468 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2471 struct font_info
*font_info
;
2474 int charset
= CHAR_CHARSET (c
);
2475 XFontStruct
*font
= font_info
->font
;
2477 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2478 This may be either a program in a special encoder language or a
2480 if (font_info
->font_encoder
)
2482 /* It's a program. */
2483 struct ccl_program
*ccl
= font_info
->font_encoder
;
2485 check_ccl_update (ccl
);
2486 if (CHARSET_DIMENSION (charset
) == 1)
2488 ccl
->reg
[0] = charset
;
2489 ccl
->reg
[1] = char2b
->byte2
;
2494 ccl
->reg
[0] = charset
;
2495 ccl
->reg
[1] = char2b
->byte1
;
2496 ccl
->reg
[2] = char2b
->byte2
;
2499 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2501 /* We assume that MSBs are appropriately set/reset by CCL
2503 if (font
->max_byte1
== 0) /* 1-byte font */
2504 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2506 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2508 else if (font_info
->encoding
[charset
])
2510 /* Fixed encoding scheme. See fontset.h for the meaning of the
2511 encoding numbers. */
2512 int enc
= font_info
->encoding
[charset
];
2514 if ((enc
== 1 || enc
== 2)
2515 && CHARSET_DIMENSION (charset
) == 2)
2516 char2b
->byte1
|= 0x80;
2518 if (enc
== 1 || enc
== 3)
2519 char2b
->byte2
|= 0x80;
2525 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2526 char2b
->byte1
= sjis1
;
2527 char2b
->byte2
= sjis2
;
2532 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2534 return FONT_TYPE_UNKNOWN
;
2539 /***********************************************************************
2541 ***********************************************************************/
2545 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2546 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2547 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2549 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2550 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2551 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2552 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2553 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2554 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2555 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2556 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2557 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2558 unsigned long *, double, int));*/
2559 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2560 double, int, unsigned long));
2561 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2562 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2563 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2564 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2565 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2567 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2568 int, int, int, int, int, int,
2570 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2571 int, int, int, Rect
*));
2574 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2578 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2583 struct glyph_string
*s
;
2585 if (s
->font
== FRAME_FONT (s
->f
)
2586 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2587 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2589 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2592 /* Cursor on non-default face: must merge. */
2596 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2597 xgcv
.foreground
= s
->face
->background
;
2599 /* If the glyph would be invisible, try a different foreground. */
2600 if (xgcv
.foreground
== xgcv
.background
)
2601 xgcv
.foreground
= s
->face
->foreground
;
2602 if (xgcv
.foreground
== xgcv
.background
)
2603 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2604 if (xgcv
.foreground
== xgcv
.background
)
2605 xgcv
.foreground
= s
->face
->foreground
;
2607 /* Make sure the cursor is distinct from text in this face. */
2608 if (xgcv
.background
== s
->face
->background
2609 && xgcv
.foreground
== s
->face
->foreground
)
2611 xgcv
.background
= s
->face
->foreground
;
2612 xgcv
.foreground
= s
->face
->background
;
2615 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2616 xgcv
.font
= s
->font
;
2617 mask
= GCForeground
| GCBackground
| GCFont
;
2619 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2620 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2623 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2624 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2626 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2631 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2634 x_set_mouse_face_gc (s
)
2635 struct glyph_string
*s
;
2640 /* What face has to be used last for the mouse face? */
2641 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2642 face
= FACE_FROM_ID (s
->f
, face_id
);
2644 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2646 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2647 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2649 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2650 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2651 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2653 /* If font in this face is same as S->font, use it. */
2654 if (s
->font
== s
->face
->font
)
2655 s
->gc
= s
->face
->gc
;
2658 /* Otherwise construct scratch_cursor_gc with values from FACE
2663 xgcv
.background
= s
->face
->background
;
2664 xgcv
.foreground
= s
->face
->foreground
;
2665 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2666 xgcv
.font
= s
->font
;
2667 mask
= GCForeground
| GCBackground
| GCFont
;
2669 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2670 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2673 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2674 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2676 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2679 xassert (s
->gc
!= 0);
2683 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2684 Faces to use in the mode line have already been computed when the
2685 matrix was built, so there isn't much to do, here. */
2688 x_set_mode_line_face_gc (s
)
2689 struct glyph_string
*s
;
2691 s
->gc
= s
->face
->gc
;
2695 /* Set S->gc of glyph string S for drawing that glyph string. Set
2696 S->stippled_p to a non-zero value if the face of S has a stipple
2700 x_set_glyph_string_gc (s
)
2701 struct glyph_string
*s
;
2703 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2705 if (s
->hl
== DRAW_NORMAL_TEXT
)
2707 s
->gc
= s
->face
->gc
;
2708 s
->stippled_p
= s
->face
->stipple
!= 0;
2710 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2712 x_set_mode_line_face_gc (s
);
2713 s
->stippled_p
= s
->face
->stipple
!= 0;
2715 else if (s
->hl
== DRAW_CURSOR
)
2717 x_set_cursor_gc (s
);
2720 else if (s
->hl
== DRAW_MOUSE_FACE
)
2722 x_set_mouse_face_gc (s
);
2723 s
->stippled_p
= s
->face
->stipple
!= 0;
2725 else if (s
->hl
== DRAW_IMAGE_RAISED
2726 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2728 s
->gc
= s
->face
->gc
;
2729 s
->stippled_p
= s
->face
->stipple
!= 0;
2733 s
->gc
= s
->face
->gc
;
2734 s
->stippled_p
= s
->face
->stipple
!= 0;
2737 /* GC must have been set. */
2738 xassert (s
->gc
!= 0);
2742 /* Set clipping for output of glyph string S. S may be part of a mode
2743 line or menu if we don't have X toolkit support. */
2746 x_set_glyph_string_clipping (s
)
2747 struct glyph_string
*s
;
2749 Rect rects
[MAX_CLIP_RECTS
];
2752 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2753 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2758 Compute left and right overhang of glyph string S. If S is a glyph
2759 string for a composition, assume overhangs don't exist. */
2762 mac_compute_glyph_string_overhangs (s
)
2763 struct glyph_string
*s
;
2765 if (!(s
->cmp
== NULL
2766 && s
->first_glyph
->type
== CHAR_GLYPH
))
2771 || s
->font
->mac_style
2777 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2778 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2779 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2784 MacFontStruct
*font
= s
->font
;
2787 mac_prepare_for_quickdraw (s
->f
);
2789 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2791 TextFont (font
->mac_fontnum
);
2792 TextSize (font
->mac_fontsize
);
2793 TextFace (font
->mac_fontface
);
2795 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2797 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2798 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2803 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2806 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2807 struct glyph_string
*s
;
2810 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2814 /* Draw the background of glyph_string S. If S->background_filled_p
2815 is non-zero don't draw it. FORCE_P non-zero means draw the
2816 background even if it wouldn't be drawn normally. This is used
2817 when a string preceding S draws into the background of S, or S
2818 contains the first component of a composition. */
2821 x_draw_glyph_string_background (s
, force_p
)
2822 struct glyph_string
*s
;
2825 /* Nothing to do if background has already been drawn or if it
2826 shouldn't be drawn in the first place. */
2827 if (!s
->background_filled_p
)
2829 int box_line_width
= max (s
->face
->box_line_width
, 0);
2831 #if 0 /* MAC_TODO: stipple */
2834 /* Fill background with a stipple pattern. */
2835 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2836 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2837 s
->y
+ box_line_width
,
2838 s
->background_width
,
2839 s
->height
- 2 * box_line_width
);
2840 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2841 s
->background_filled_p
= 1;
2845 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2846 || s
->font_not_found_p
2847 || s
->extends_to_end_of_line_p
2850 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2851 s
->background_width
,
2852 s
->height
- 2 * box_line_width
);
2853 s
->background_filled_p
= 1;
2859 /* Draw the foreground of glyph string S. */
2862 x_draw_glyph_string_foreground (s
)
2863 struct glyph_string
*s
;
2867 /* If first glyph of S has a left box line, start drawing the text
2868 of S to the right of that box line. */
2869 if (s
->face
->box
!= FACE_NO_BOX
2870 && s
->first_glyph
->left_box_line_p
)
2871 x
= s
->x
+ abs (s
->face
->box_line_width
);
2875 /* Draw characters of S as rectangles if S's font could not be
2877 if (s
->font_not_found_p
)
2879 for (i
= 0; i
< s
->nchars
; ++i
)
2881 struct glyph
*g
= s
->first_glyph
+ i
;
2882 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2883 g
->pixel_width
- 1, s
->height
- 1);
2884 x
+= g
->pixel_width
;
2889 char *char1b
= (char *) s
->char2b
;
2890 int boff
= s
->font_info
->baseline_offset
;
2892 if (s
->font_info
->vertical_centering
)
2893 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2895 /* If we can use 8-bit functions, condense S->char2b. */
2898 && GC_FONT (s
->gc
)->mac_style
== NULL
2901 for (i
= 0; i
< s
->nchars
; ++i
)
2902 char1b
[i
] = s
->char2b
[i
].byte2
;
2904 /* Draw text with XDrawString if background has already been
2905 filled. Otherwise, use XDrawImageString. (Note that
2906 XDrawImageString is usually faster than XDrawString.) Always
2907 use XDrawImageString when drawing the cursor so that there is
2908 no chance that characters under a box cursor are invisible. */
2910 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2911 bg_width
= 0; /* Corresponds to XDrawString. */
2913 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2917 || GC_FONT (s
->gc
)->mac_style
2920 #if USE_CG_TEXT_DRAWING
2922 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2923 s
->char2b
, s
->nchars
, bg_width
,
2924 s
->face
->overstrike
))
2928 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2929 s
->char2b
, s
->nchars
, bg_width
,
2930 s
->face
->overstrike
);
2932 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2933 char1b
, s
->nchars
, bg_width
,
2934 s
->face
->overstrike
);
2938 /* Draw the foreground of composite glyph string S. */
2941 x_draw_composite_glyph_string_foreground (s
)
2942 struct glyph_string
*s
;
2946 /* If first glyph of S has a left box line, start drawing the text
2947 of S to the right of that box line. */
2948 if (s
->face
->box
!= FACE_NO_BOX
2949 && s
->first_glyph
->left_box_line_p
)
2950 x
= s
->x
+ abs (s
->face
->box_line_width
);
2954 /* S is a glyph string for a composition. S->gidx is the index of
2955 the first character drawn for glyphs of this composition.
2956 S->gidx == 0 means we are drawing the very first character of
2957 this composition. */
2959 /* Draw a rectangle for the composition if the font for the very
2960 first character of the composition could not be loaded. */
2961 if (s
->font_not_found_p
)
2964 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2965 s
->width
- 1, s
->height
- 1);
2969 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2970 mac_draw_image_string_16 (s
->f
, s
->gc
,
2971 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2972 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2973 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
2978 #ifdef USE_X_TOOLKIT
2980 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2983 /* Return the frame on which widget WIDGET is used.. Abort if frame
2984 cannot be determined. */
2986 static struct frame
*
2987 x_frame_of_widget (widget
)
2990 struct x_display_info
*dpyinfo
;
2994 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2996 /* Find the top-level shell of the widget. Note that this function
2997 can be called when the widget is not yet realized, so XtWindow
2998 (widget) == 0. That's the reason we can't simply use
2999 x_any_window_to_frame. */
3000 while (!XtIsTopLevelShell (widget
))
3001 widget
= XtParent (widget
);
3003 /* Look for a frame with that top-level widget. Allocate the color
3004 on that frame to get the right gamma correction value. */
3005 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3006 if (GC_FRAMEP (XCAR (tail
))
3007 && (f
= XFRAME (XCAR (tail
)),
3008 (f
->output_data
.nothing
!= 1
3009 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3010 && f
->output_data
.x
->widget
== widget
)
3017 /* Allocate the color COLOR->pixel on the screen and display of
3018 widget WIDGET in colormap CMAP. If an exact match cannot be
3019 allocated, try the nearest color available. Value is non-zero
3020 if successful. This is called from lwlib. */
3023 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3028 struct frame
*f
= x_frame_of_widget (widget
);
3029 return x_alloc_nearest_color (f
, cmap
, color
);
3033 #endif /* USE_X_TOOLKIT */
3035 #if 0 /* MAC_TODO */
3037 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3038 CMAP. If an exact match can't be allocated, try the nearest color
3039 available. Value is non-zero if successful. Set *COLOR to the
3043 x_alloc_nearest_color (f
, cmap
, color
)
3048 Display
*display
= FRAME_X_DISPLAY (f
);
3049 Screen
*screen
= FRAME_X_SCREEN (f
);
3052 gamma_correct (f
, color
);
3053 rc
= XAllocColor (display
, cmap
, color
);
3056 /* If we got to this point, the colormap is full, so we're going
3057 to try to get the next closest color. The algorithm used is
3058 a least-squares matching, which is what X uses for closest
3059 color matching with StaticColor visuals. */
3061 unsigned long nearest_delta
= ~0;
3062 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3063 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3065 for (i
= 0; i
< ncells
; ++i
)
3067 XQueryColors (display
, cmap
, cells
, ncells
);
3069 for (nearest
= i
= 0; i
< ncells
; ++i
)
3071 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3072 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3073 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3074 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3076 if (delta
< nearest_delta
)
3079 nearest_delta
= delta
;
3083 color
->red
= cells
[nearest
].red
;
3084 color
->green
= cells
[nearest
].green
;
3085 color
->blue
= cells
[nearest
].blue
;
3086 rc
= XAllocColor (display
, cmap
, color
);
3089 #ifdef DEBUG_X_COLORS
3091 register_color (color
->pixel
);
3092 #endif /* DEBUG_X_COLORS */
3098 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3099 It's necessary to do this instead of just using PIXEL directly to
3100 get color reference counts right. */
3103 x_copy_color (f
, pixel
)
3105 unsigned long pixel
;
3109 color
.pixel
= pixel
;
3111 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3112 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3114 #ifdef DEBUG_X_COLORS
3115 register_color (pixel
);
3121 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3122 It's necessary to do this instead of just using PIXEL directly to
3123 get color reference counts right. */
3126 x_copy_dpy_color (dpy
, cmap
, pixel
)
3129 unsigned long pixel
;
3133 color
.pixel
= pixel
;
3135 XQueryColor (dpy
, cmap
, &color
);
3136 XAllocColor (dpy
, cmap
, &color
);
3138 #ifdef DEBUG_X_COLORS
3139 register_color (pixel
);
3144 #endif /* MAC_TODO */
3147 /* Brightness beyond which a color won't have its highlight brightness
3150 Nominally, highlight colors for `3d' faces are calculated by
3151 brightening an object's color by a constant scale factor, but this
3152 doesn't yield good results for dark colors, so for colors who's
3153 brightness is less than this value (on a scale of 0-255) have to
3154 use an additional additive factor.
3156 The value here is set so that the default menu-bar/mode-line color
3157 (grey75) will not have its highlights changed at all. */
3158 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3161 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3162 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3163 If this produces the same color as COLOR, try a color where all RGB
3164 values have DELTA added. Return the allocated color in *COLOR.
3165 DISPLAY is the X display, CMAP is the colormap to operate on.
3166 Value is non-zero if successful. */
3169 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3171 unsigned long *color
;
3178 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3181 /* Change RGB values by specified FACTOR. Avoid overflow! */
3182 xassert (factor
>= 0);
3183 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3184 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3185 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3187 /* Calculate brightness of COLOR. */
3188 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3189 + BLUE_FROM_ULONG (*color
)) / 6;
3191 /* We only boost colors that are darker than
3192 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3193 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3194 /* Make an additive adjustment to NEW, because it's dark enough so
3195 that scaling by FACTOR alone isn't enough. */
3197 /* How far below the limit this color is (0 - 1, 1 being darker). */
3198 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3199 /* The additive adjustment. */
3200 int min_delta
= delta
* dimness
* factor
/ 2;
3203 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3204 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3205 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3207 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3208 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3209 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3213 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3214 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3215 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3217 /* MAC_TODO: Map to palette and retry with delta if same? */
3218 /* MAC_TODO: Free colors (if using palette)? */
3229 /* Set up the foreground color for drawing relief lines of glyph
3230 string S. RELIEF is a pointer to a struct relief containing the GC
3231 with which lines will be drawn. Use a color that is FACTOR or
3232 DELTA lighter or darker than the relief's background which is found
3233 in S->f->output_data.x->relief_background. If such a color cannot
3234 be allocated, use DEFAULT_PIXEL, instead. */
3237 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3239 struct relief
*relief
;
3242 unsigned long default_pixel
;
3245 struct mac_output
*di
= f
->output_data
.mac
;
3246 unsigned long mask
= GCForeground
;
3247 unsigned long pixel
;
3248 unsigned long background
= di
->relief_background
;
3249 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3251 /* MAC_TODO: Free colors (if using palette)? */
3253 /* Allocate new color. */
3254 xgcv
.foreground
= default_pixel
;
3256 if (dpyinfo
->n_planes
!= 1
3257 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3259 relief
->allocated_p
= 1;
3260 xgcv
.foreground
= relief
->pixel
= pixel
;
3263 if (relief
->gc
== 0)
3265 #if 0 /* MAC_TODO: stipple */
3266 xgcv
.stipple
= dpyinfo
->gray
;
3269 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3272 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3276 /* Set up colors for the relief lines around glyph string S. */
3279 x_setup_relief_colors (s
)
3280 struct glyph_string
*s
;
3282 struct mac_output
*di
= s
->f
->output_data
.mac
;
3283 unsigned long color
;
3285 if (s
->face
->use_box_color_for_shadows_p
)
3286 color
= s
->face
->box_color
;
3287 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3289 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3290 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3295 /* Get the background color of the face. */
3296 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3297 color
= xgcv
.background
;
3300 if (di
->white_relief
.gc
== 0
3301 || color
!= di
->relief_background
)
3303 di
->relief_background
= color
;
3304 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3305 WHITE_PIX_DEFAULT (s
->f
));
3306 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3307 BLACK_PIX_DEFAULT (s
->f
));
3312 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3313 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3314 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3315 relief. LEFT_P non-zero means draw a relief on the left side of
3316 the rectangle. RIGHT_P non-zero means draw a relief on the right
3317 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3321 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3322 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3324 int left_x
, top_y
, right_x
, bottom_y
, width
;
3325 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3328 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3333 gc
= f
->output_data
.mac
->white_relief
.gc
;
3335 gc
= f
->output_data
.mac
->black_relief
.gc
;
3336 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3340 for (i
= 0; i
< width
; ++i
)
3341 mac_draw_line (f
, gc
,
3342 left_x
+ i
* left_p
, top_y
+ i
,
3343 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3347 for (i
= 0; i
< width
; ++i
)
3348 mac_draw_line (f
, gc
,
3349 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3351 mac_reset_clip_rectangles (dpy
, gc
);
3353 gc
= f
->output_data
.mac
->black_relief
.gc
;
3355 gc
= f
->output_data
.mac
->white_relief
.gc
;
3356 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3360 for (i
= 0; i
< width
; ++i
)
3361 mac_draw_line (f
, gc
,
3362 left_x
+ i
* left_p
, bottom_y
- i
,
3363 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3367 for (i
= 0; i
< width
; ++i
)
3368 mac_draw_line (f
, gc
,
3369 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3371 mac_reset_clip_rectangles (dpy
, gc
);
3375 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3376 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3377 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3378 left side of the rectangle. RIGHT_P non-zero means draw a line
3379 on the right side of the rectangle. CLIP_RECT is the clipping
3380 rectangle to use when drawing. */
3383 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3384 left_p
, right_p
, clip_rect
)
3385 struct glyph_string
*s
;
3386 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3391 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3392 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3393 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3396 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3397 right_x
- left_x
+ 1, width
);
3401 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3402 width
, bottom_y
- top_y
+ 1);
3405 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3406 right_x
- left_x
+ 1, width
);
3410 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3411 top_y
, width
, bottom_y
- top_y
+ 1);
3413 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3414 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3418 /* Draw a box around glyph string S. */
3421 x_draw_glyph_string_box (s
)
3422 struct glyph_string
*s
;
3424 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3425 int left_p
, right_p
;
3426 struct glyph
*last_glyph
;
3429 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3430 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3431 : window_box_right (s
->w
, s
->area
));
3433 /* The glyph that may have a right box line. */
3434 last_glyph
= (s
->cmp
|| s
->img
3436 : s
->first_glyph
+ s
->nchars
- 1);
3438 width
= abs (s
->face
->box_line_width
);
3439 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3441 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3443 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3445 bottom_y
= top_y
+ s
->height
- 1;
3447 left_p
= (s
->first_glyph
->left_box_line_p
3448 || (s
->hl
== DRAW_MOUSE_FACE
3450 || s
->prev
->hl
!= s
->hl
)));
3451 right_p
= (last_glyph
->right_box_line_p
3452 || (s
->hl
== DRAW_MOUSE_FACE
3454 || s
->next
->hl
!= s
->hl
)));
3456 get_glyph_string_clip_rect (s
, &clip_rect
);
3458 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3459 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3460 left_p
, right_p
, &clip_rect
);
3463 x_setup_relief_colors (s
);
3464 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3465 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3470 /* Draw foreground of image glyph string S. */
3473 x_draw_image_foreground (s
)
3474 struct glyph_string
*s
;
3477 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3479 /* If first glyph of S has a left box line, start drawing it to the
3480 right of that line. */
3481 if (s
->face
->box
!= FACE_NO_BOX
3482 && s
->first_glyph
->left_box_line_p
3484 x
+= abs (s
->face
->box_line_width
);
3486 /* If there is a margin around the image, adjust x- and y-position
3488 if (s
->slice
.x
== 0)
3489 x
+= s
->img
->hmargin
;
3490 if (s
->slice
.y
== 0)
3491 y
+= s
->img
->vmargin
;
3495 x_set_glyph_string_clipping (s
);
3498 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3499 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3500 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3504 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3505 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3506 s
->slice
.width
, s
->slice
.height
, x
, y
);
3513 mac_copy_area (s
->img
->pixmap
,
3514 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3515 s
->slice
.width
, s
->slice
.height
, x
, y
);
3518 /* When the image has a mask, we can expect that at
3519 least part of a mouse highlight or a block cursor will
3520 be visible. If the image doesn't have a mask, make
3521 a block cursor visible by drawing a rectangle around
3522 the image. I believe it's looking better if we do
3523 nothing here for mouse-face. */
3524 if (s
->hl
== DRAW_CURSOR
)
3526 int r
= s
->img
->relief
;
3528 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3529 s
->slice
.width
+ r
*2 - 1,
3530 s
->slice
.height
+ r
*2 - 1);
3535 /* Draw a rectangle if image could not be loaded. */
3536 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3537 s
->slice
.width
- 1, s
->slice
.height
- 1);
3541 /* Draw a relief around the image glyph string S. */
3544 x_draw_image_relief (s
)
3545 struct glyph_string
*s
;
3547 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3550 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3552 /* If first glyph of S has a left box line, start drawing it to the
3553 right of that line. */
3554 if (s
->face
->box
!= FACE_NO_BOX
3555 && s
->first_glyph
->left_box_line_p
3557 x
+= abs (s
->face
->box_line_width
);
3559 /* If there is a margin around the image, adjust x- and y-position
3561 if (s
->slice
.x
== 0)
3562 x
+= s
->img
->hmargin
;
3563 if (s
->slice
.y
== 0)
3564 y
+= s
->img
->vmargin
;
3566 if (s
->hl
== DRAW_IMAGE_SUNKEN
3567 || s
->hl
== DRAW_IMAGE_RAISED
)
3569 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3570 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3574 thick
= abs (s
->img
->relief
);
3575 raised_p
= s
->img
->relief
> 0;
3580 x1
= x
+ s
->slice
.width
+ thick
- 1;
3581 y1
= y
+ s
->slice
.height
+ thick
- 1;
3583 x_setup_relief_colors (s
);
3584 get_glyph_string_clip_rect (s
, &r
);
3585 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3587 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3589 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3594 /* Draw part of the background of glyph string S. X, Y, W, and H
3595 give the rectangle to draw. */
3598 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3599 struct glyph_string
*s
;
3602 #if 0 /* MAC_TODO: stipple */
3605 /* Fill background with a stipple pattern. */
3606 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3607 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3608 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3611 #endif /* MAC_TODO */
3612 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3616 /* Draw image glyph string S.
3619 s->x +-------------------------
3622 | +-------------------------
3625 | | +-------------------
3631 x_draw_image_glyph_string (s
)
3632 struct glyph_string
*s
;
3635 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3636 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3639 height
= s
->height
- 2 * box_line_vwidth
;
3642 /* Fill background with face under the image. Do it only if row is
3643 taller than image or if image has a clip mask to reduce
3645 s
->stippled_p
= s
->face
->stipple
!= 0;
3646 if (height
> s
->slice
.height
3650 || s
->img
->pixmap
== 0
3651 || s
->width
!= s
->background_width
)
3654 if (s
->first_glyph
->left_box_line_p
3656 x
+= box_line_hwidth
;
3659 if (s
->slice
.y
== 0)
3660 y
+= box_line_vwidth
;
3662 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3664 s
->background_filled_p
= 1;
3667 /* Draw the foreground. */
3668 x_draw_image_foreground (s
);
3670 /* If we must draw a relief around the image, do it. */
3672 || s
->hl
== DRAW_IMAGE_RAISED
3673 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3674 x_draw_image_relief (s
);
3678 /* Draw stretch glyph string S. */
3681 x_draw_stretch_glyph_string (s
)
3682 struct glyph_string
*s
;
3684 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3685 s
->stippled_p
= s
->face
->stipple
!= 0;
3687 if (s
->hl
== DRAW_CURSOR
3688 && !x_stretch_cursor_p
)
3690 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3691 as wide as the stretch glyph. */
3692 int width
, background_width
= s
->background_width
;
3693 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3697 background_width
-= left_x
- x
;
3700 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3703 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3705 /* Clear rest using the GC of the original non-cursor face. */
3706 if (width
< background_width
)
3709 int w
= background_width
- width
, h
= s
->height
;
3714 if (s
->row
->mouse_face_p
3715 && cursor_in_mouse_face_p (s
->w
))
3717 x_set_mouse_face_gc (s
);
3723 get_glyph_string_clip_rect (s
, &r
);
3724 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3726 #if 0 /* MAC_TODO: stipple */
3727 if (s
->face
->stipple
)
3729 /* Fill background with a stipple pattern. */
3730 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3731 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3732 XSetFillStyle (s
->display
, gc
, FillSolid
);
3735 #endif /* MAC_TODO */
3736 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3739 else if (!s
->background_filled_p
)
3741 int background_width
= s
->background_width
;
3742 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3744 /* Don't draw into left margin, fringe or scrollbar area
3745 except for header line and mode line. */
3746 if (x
< left_x
&& !s
->row
->mode_line_p
)
3748 background_width
-= left_x
- x
;
3751 if (background_width
> 0)
3752 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3755 s
->background_filled_p
= 1;
3759 /* Draw glyph string S. */
3762 x_draw_glyph_string (s
)
3763 struct glyph_string
*s
;
3765 int relief_drawn_p
= 0;
3767 /* If S draws into the background of its successor that does not
3768 draw a cursor, draw the background of the successor first so that
3769 S can draw into it. This makes S->next use XDrawString instead
3770 of XDrawImageString. */
3771 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3772 && s
->next
->hl
!= DRAW_CURSOR
)
3774 xassert (s
->next
->img
== NULL
);
3775 x_set_glyph_string_gc (s
->next
);
3776 x_set_glyph_string_clipping (s
->next
);
3777 x_draw_glyph_string_background (s
->next
, 1);
3780 /* Set up S->gc, set clipping and draw S. */
3781 x_set_glyph_string_gc (s
);
3783 /* Draw relief (if any) in advance for char/composition so that the
3784 glyph string can be drawn over it. */
3785 if (!s
->for_overlaps
3786 && s
->face
->box
!= FACE_NO_BOX
3787 && (s
->first_glyph
->type
== CHAR_GLYPH
3788 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3791 x_set_glyph_string_clipping (s
);
3792 x_draw_glyph_string_background (s
, 1);
3793 x_draw_glyph_string_box (s
);
3794 x_set_glyph_string_clipping (s
);
3798 x_set_glyph_string_clipping (s
);
3800 switch (s
->first_glyph
->type
)
3803 x_draw_image_glyph_string (s
);
3807 x_draw_stretch_glyph_string (s
);
3811 if (s
->for_overlaps
)
3812 s
->background_filled_p
= 1;
3814 x_draw_glyph_string_background (s
, 0);
3815 x_draw_glyph_string_foreground (s
);
3818 case COMPOSITE_GLYPH
:
3819 if (s
->for_overlaps
|| s
->gidx
> 0)
3820 s
->background_filled_p
= 1;
3822 x_draw_glyph_string_background (s
, 1);
3823 x_draw_composite_glyph_string_foreground (s
);
3830 if (!s
->for_overlaps
)
3832 /* Draw underline. */
3833 if (s
->face
->underline_p
)
3835 unsigned long tem
, h
;
3839 /* Get the underline thickness. Default is 1 pixel. */
3840 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3844 y
= s
->y
+ s
->height
- h
;
3845 if (!x_underline_at_descent_line
)
3847 /* Get the underline position. This is the recommended
3848 vertical offset in pixels from the baseline to the top of
3849 the underline. This is a signed value according to the
3850 specs, and its default is
3852 ROUND ((maximum descent) / 2), with
3853 ROUND(x) = floor (x + 0.5) */
3856 if (x_use_underline_position_properties
3857 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3858 y
= s
->ybase
+ (long) tem
;
3862 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3865 if (s
->face
->underline_defaulted_p
)
3866 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3867 s
->background_width
, h
);
3871 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3872 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3873 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3874 s
->background_width
, h
);
3875 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3879 /* Draw overline. */
3880 if (s
->face
->overline_p
)
3882 unsigned long dy
= 0, h
= 1;
3884 if (s
->face
->overline_color_defaulted_p
)
3885 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3886 s
->background_width
, h
);
3890 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3891 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3892 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3893 s
->background_width
, h
);
3894 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3898 /* Draw strike-through. */
3899 if (s
->face
->strike_through_p
)
3901 unsigned long h
= 1;
3902 unsigned long dy
= (s
->height
- h
) / 2;
3904 if (s
->face
->strike_through_color_defaulted_p
)
3905 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3910 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3911 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3912 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3914 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3918 /* Draw relief if not yet drawn. */
3919 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3920 x_draw_glyph_string_box (s
);
3923 /* Reset clipping. */
3924 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3927 /* Shift display to make room for inserted glyphs. */
3930 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3932 int x
, y
, width
, height
, shift_by
;
3934 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3935 x
, y
, width
, height
,
3939 /* Delete N glyphs at the nominal cursor position. Not implemented
3950 /* Clear entire frame. If updating_frame is non-null, clear that
3951 frame. Otherwise clear the selected frame. */
3961 f
= SELECTED_FRAME ();
3963 /* Clearing the frame will erase any cursor, so mark them all as no
3965 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3966 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3967 output_cursor
.x
= -1;
3969 /* We don't set the output cursor here because there will always
3970 follow an explicit cursor_to. */
3972 mac_clear_window (f
);
3974 /* We have to clear the scroll bars, too. If we have changed
3975 colors or something like that, then they should be notified. */
3976 x_scroll_bar_clear (f
);
3978 XFlush (FRAME_MAC_DISPLAY (f
));
3984 /* Invert the middle quarter of the frame for .15 sec. */
3986 /* We use the select system call to do the waiting, so we have to make
3987 sure it's available. If it isn't, we just won't do visual bells. */
3989 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3992 /* Subtract the `struct timeval' values X and Y, storing the result in
3993 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3996 timeval_subtract (result
, x
, y
)
3997 struct timeval
*result
, x
, y
;
3999 /* Perform the carry for the later subtraction by updating y. This
4000 is safer because on some systems the tv_sec member is unsigned. */
4001 if (x
.tv_usec
< y
.tv_usec
)
4003 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4004 y
.tv_usec
-= 1000000 * nsec
;
4008 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4010 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4011 y
.tv_usec
+= 1000000 * nsec
;
4015 /* Compute the time remaining to wait. tv_usec is certainly
4017 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4018 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4020 /* Return indication of whether the result should be considered
4022 return x
.tv_sec
< y
.tv_sec
;
4029 /* Get the height not including a menu bar widget. */
4030 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4031 /* Height of each line to flash. */
4032 int flash_height
= FRAME_LINE_HEIGHT (f
);
4033 /* These will be the left and right margins of the rectangles. */
4034 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4035 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4039 /* Don't flash the area between a scroll bar and the frame
4040 edge it is next to. */
4041 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4043 case vertical_scroll_bar_left
:
4044 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4047 case vertical_scroll_bar_right
:
4048 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4055 width
= flash_right
- flash_left
;
4059 /* If window is tall, flash top and bottom line. */
4060 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4062 mac_invert_rectangle (f
, flash_left
,
4063 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4064 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4065 width
, flash_height
);
4066 mac_invert_rectangle (f
, flash_left
,
4067 (height
- flash_height
4068 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4069 width
, flash_height
);
4072 /* If it is short, flash it all. */
4073 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4074 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4079 struct timeval wakeup
;
4081 EMACS_GET_TIME (wakeup
);
4083 /* Compute time to wait until, propagating carry from usecs. */
4084 wakeup
.tv_usec
+= 150000;
4085 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4086 wakeup
.tv_usec
%= 1000000;
4088 /* Keep waiting until past the time wakeup or any input gets
4090 while (! detect_input_pending ())
4092 struct timeval current
;
4093 struct timeval timeout
;
4095 EMACS_GET_TIME (current
);
4097 /* Break if result would be negative. */
4098 if (timeval_subtract (¤t
, wakeup
, current
))
4101 /* How long `select' should wait. */
4103 timeout
.tv_usec
= 10000;
4105 /* Try to wait that long--but we might wake up sooner. */
4106 select (0, NULL
, NULL
, NULL
, &timeout
);
4110 /* If window is tall, flash top and bottom line. */
4111 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4113 mac_invert_rectangle (f
, flash_left
,
4114 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4115 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4116 width
, flash_height
);
4117 mac_invert_rectangle (f
, flash_left
,
4118 (height
- flash_height
4119 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4120 width
, flash_height
);
4123 /* If it is short, flash it all. */
4124 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4125 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4132 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4135 /* Make audible bell. */
4140 struct frame
*f
= SELECTED_FRAME ();
4142 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4150 XFlush (FRAME_MAC_DISPLAY (f
));
4156 /* Specify how many text lines, from the top of the window,
4157 should be affected by insert-lines and delete-lines operations.
4158 This, and those operations, are used only within an update
4159 that is bounded by calls to x_update_begin and x_update_end. */
4162 XTset_terminal_window (n
)
4165 /* This function intentionally left blank. */
4170 /***********************************************************************
4172 ***********************************************************************/
4174 /* Perform an insert-lines or delete-lines operation, inserting N
4175 lines or deleting -N lines at vertical position VPOS. */
4178 x_ins_del_lines (vpos
, n
)
4185 /* Scroll part of the display as described by RUN. */
4188 x_scroll_run (w
, run
)
4192 struct frame
*f
= XFRAME (w
->frame
);
4193 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4195 /* Get frame-relative bounding box of the text display area of W,
4196 without mode lines. Include in this box the left and right
4198 window_box (w
, -1, &x
, &y
, &width
, &height
);
4200 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4201 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4202 bottom_y
= y
+ height
;
4206 /* Scrolling up. Make sure we don't copy part of the mode
4207 line at the bottom. */
4208 if (from_y
+ run
->height
> bottom_y
)
4209 height
= bottom_y
- from_y
;
4211 height
= run
->height
;
4215 /* Scolling down. Make sure we don't copy over the mode line.
4217 if (to_y
+ run
->height
> bottom_y
)
4218 height
= bottom_y
- to_y
;
4220 height
= run
->height
;
4225 /* Cursor off. Will be switched on again in x_update_window_end. */
4229 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4239 /***********************************************************************
4241 ***********************************************************************/
4249 ControlRef root_control
;
4252 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4254 ActivateControl (root_control
);
4256 x_update_cursor (f
, 1);
4260 frame_unhighlight (f
)
4264 ControlRef root_control
;
4267 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4269 DeactivateControl (root_control
);
4271 x_update_cursor (f
, 1);
4274 /* The focus has changed. Update the frames as necessary to reflect
4275 the new situation. Note that we can't change the selected frame
4276 here, because the Lisp code we are interrupting might become confused.
4277 Each event gets marked with the frame in which it occurred, so the
4278 Lisp code can tell when the switch took place by examining the events. */
4281 x_new_focus_frame (dpyinfo
, frame
)
4282 struct x_display_info
*dpyinfo
;
4283 struct frame
*frame
;
4285 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4287 if (frame
!= dpyinfo
->x_focus_frame
)
4289 /* Set this before calling other routines, so that they see
4290 the correct value of x_focus_frame. */
4291 dpyinfo
->x_focus_frame
= frame
;
4293 if (old_focus
&& old_focus
->auto_lower
)
4294 x_lower_frame (old_focus
);
4297 selected_frame
= frame
;
4298 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4300 Fselect_window (selected_frame
->selected_window
, Qnil
);
4301 choose_minibuf_frame ();
4304 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4305 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4307 pending_autoraise_frame
= 0;
4309 #if USE_MAC_FONT_PANEL
4311 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4315 x_frame_rehighlight (dpyinfo
);
4318 /* Handle FocusIn and FocusOut state changes for FRAME.
4319 If FRAME has focus and there exists more than one frame, puts
4320 a FOCUS_IN_EVENT into *BUFP. */
4323 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4325 struct mac_display_info
*dpyinfo
;
4326 struct frame
*frame
;
4327 struct input_event
*bufp
;
4329 if (type
== activeFlag
)
4331 if (dpyinfo
->x_focus_event_frame
!= frame
)
4333 x_new_focus_frame (dpyinfo
, frame
);
4334 dpyinfo
->x_focus_event_frame
= frame
;
4336 /* Don't stop displaying the initial startup message
4337 for a switch-frame event we don't need. */
4338 if (GC_NILP (Vterminal_frame
)
4339 && GC_CONSP (Vframe_list
)
4340 && !GC_NILP (XCDR (Vframe_list
)))
4342 bufp
->kind
= FOCUS_IN_EVENT
;
4343 XSETFRAME (bufp
->frame_or_window
, frame
);
4349 if (dpyinfo
->x_focus_event_frame
== frame
)
4351 dpyinfo
->x_focus_event_frame
= 0;
4352 x_new_focus_frame (dpyinfo
, 0);
4357 /* The focus may have changed. Figure out if it is a real focus change,
4358 by checking both FocusIn/Out and Enter/LeaveNotify events.
4360 Returns FOCUS_IN_EVENT event in *BUFP. */
4363 x_detect_focus_change (dpyinfo
, event
, bufp
)
4364 struct mac_display_info
*dpyinfo
;
4365 const EventRecord
*event
;
4366 struct input_event
*bufp
;
4368 struct frame
*frame
;
4370 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4374 /* On Mac, this is only called from focus events, so no switch needed. */
4375 mac_focus_changed ((event
->modifiers
& activeFlag
),
4376 dpyinfo
, frame
, bufp
);
4380 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4383 x_mouse_leave (dpyinfo
)
4384 struct x_display_info
*dpyinfo
;
4386 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4389 /* The focus has changed, or we have redirected a frame's focus to
4390 another frame (this happens when a frame uses a surrogate
4391 mini-buffer frame). Shift the highlight as appropriate.
4393 The FRAME argument doesn't necessarily have anything to do with which
4394 frame is being highlighted or un-highlighted; we only use it to find
4395 the appropriate X display info. */
4398 XTframe_rehighlight (frame
)
4399 struct frame
*frame
;
4401 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4405 x_frame_rehighlight (dpyinfo
)
4406 struct x_display_info
*dpyinfo
;
4408 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4410 if (dpyinfo
->x_focus_frame
)
4412 dpyinfo
->x_highlight_frame
4413 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4414 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4415 : dpyinfo
->x_focus_frame
);
4416 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4418 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4419 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4423 dpyinfo
->x_highlight_frame
= 0;
4425 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4428 frame_unhighlight (old_highlight
);
4429 if (dpyinfo
->x_highlight_frame
)
4430 frame_highlight (dpyinfo
->x_highlight_frame
);
4436 /* Convert a keysym to its name. */
4439 x_get_keysym_name (keysym
)
4446 value
= XKeysymToString (keysym
);
4457 /* Function to report a mouse movement to the mainstream Emacs code.
4458 The input handler calls this.
4460 We have received a mouse movement event, which is given in *event.
4461 If the mouse is over a different glyph than it was last time, tell
4462 the mainstream emacs code by setting mouse_moved. If not, ask for
4463 another motion event, so we can check again the next time it moves. */
4465 static Point last_mouse_motion_position
;
4466 static Lisp_Object last_mouse_motion_frame
;
4469 note_mouse_movement (frame
, pos
)
4473 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4474 #if TARGET_API_MAC_CARBON
4478 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4479 last_mouse_motion_position
= *pos
;
4480 XSETFRAME (last_mouse_motion_frame
, frame
);
4482 #if TARGET_API_MAC_CARBON
4483 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4485 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4488 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4489 /* This case corresponds to LeaveNotify in X11. */
4491 /* If we move outside the frame, then we're certainly no
4492 longer on any text in the frame. */
4493 clear_mouse_face (dpyinfo
);
4494 dpyinfo
->mouse_face_mouse_frame
= 0;
4495 if (!dpyinfo
->grabbed
)
4496 rif
->define_frame_cursor (frame
,
4497 frame
->output_data
.mac
->nontext_cursor
);
4501 /* Has the mouse moved off the glyph it was on at the last sighting? */
4502 if (frame
!= last_mouse_glyph_frame
4503 || !PtInRect (*pos
, &last_mouse_glyph
))
4505 frame
->mouse_moved
= 1;
4506 last_mouse_scroll_bar
= Qnil
;
4507 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4508 /* Remember which glyph we're now on. */
4509 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4510 last_mouse_glyph_frame
= frame
;
4518 /************************************************************************
4520 ************************************************************************/
4522 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4525 redo_mouse_highlight ()
4527 if (!NILP (last_mouse_motion_frame
)
4528 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4529 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4530 last_mouse_motion_position
.h
,
4531 last_mouse_motion_position
.v
);
4535 static struct frame
*
4536 mac_focus_frame (dpyinfo
)
4537 struct mac_display_info
*dpyinfo
;
4539 if (dpyinfo
->x_focus_frame
)
4540 return dpyinfo
->x_focus_frame
;
4542 /* Mac version may get events, such as a menu bar click, even when
4543 all the frames are invisible. In this case, we regard the
4544 event came to the selected frame. */
4545 return SELECTED_FRAME ();
4549 /* Return the current position of the mouse.
4550 *FP should be a frame which indicates which display to ask about.
4552 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4553 and *PART to the frame, window, and scroll bar part that the mouse
4554 is over. Set *X and *Y to the portion and whole of the mouse's
4555 position on the scroll bar.
4557 If the mouse movement started elsewhere, set *FP to the frame the
4558 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4561 Set *TIME to the server time-stamp for the time at which the mouse
4562 was at this position.
4564 Don't store anything if we don't have a valid set of values to report.
4566 This clears the mouse_moved flag, so we can wait for the next mouse
4570 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4573 Lisp_Object
*bar_window
;
4574 enum scroll_bar_part
*part
;
4576 unsigned long *time
;
4582 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4583 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4586 Lisp_Object frame
, tail
;
4588 /* Clear the mouse-moved flag for every frame on this display. */
4589 FOR_EACH_FRAME (tail
, frame
)
4590 XFRAME (frame
)->mouse_moved
= 0;
4592 last_mouse_scroll_bar
= Qnil
;
4594 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4595 && FRAME_LIVE_P (last_mouse_frame
))
4596 f1
= last_mouse_frame
;
4598 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4602 /* Ok, we found a frame. Store all the values.
4603 last_mouse_glyph is a rectangle used to reduce the
4604 generation of mouse events. To not miss any motion
4605 events, we must divide the frame into rectangles of the
4606 size of the smallest character that could be displayed
4607 on it, i.e. into the same rectangles that matrices on
4608 the frame are divided into. */
4611 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4612 GetMouse (&mouse_pos
);
4613 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4615 last_mouse_glyph_frame
= f1
;
4620 XSETINT (*x
, mouse_pos
.h
);
4621 XSETINT (*y
, mouse_pos
.v
);
4622 *time
= last_mouse_movement_time
;
4630 /************************************************************************
4632 ************************************************************************/
4634 #ifdef USE_TOOLKIT_SCROLL_BARS
4636 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4637 static OSStatus install_scroll_bar_timer
P_ ((void));
4638 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4639 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4640 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4641 struct input_event
*));
4642 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4644 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4646 struct input_event
*));
4647 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4648 struct input_event
*));
4649 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4650 Point
, struct input_event
*));
4651 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4654 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4656 static int last_scroll_bar_part
;
4658 static EventLoopTimerRef scroll_bar_timer
;
4660 static int scroll_bar_timer_event_posted_p
;
4662 #define SCROLL_BAR_FIRST_DELAY 0.5
4663 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4666 scroll_bar_timer_callback (timer
, data
)
4667 EventLoopTimerRef timer
;
4672 err
= mac_post_mouse_moved_event ();
4674 scroll_bar_timer_event_posted_p
= 1;
4678 install_scroll_bar_timer ()
4680 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4682 if (scroll_bar_timer_callbackUPP
== NULL
)
4683 scroll_bar_timer_callbackUPP
=
4684 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4686 if (scroll_bar_timer
== NULL
)
4687 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4688 kEventDurationForever as delays. */
4690 InstallEventLoopTimer (GetCurrentEventLoop (),
4691 kEventDurationForever
, kEventDurationForever
,
4692 scroll_bar_timer_callbackUPP
, NULL
,
4697 set_scroll_bar_timer (delay
)
4698 EventTimerInterval delay
;
4700 if (scroll_bar_timer
== NULL
)
4701 install_scroll_bar_timer ();
4703 scroll_bar_timer_event_posted_p
= 0;
4705 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4709 control_part_code_to_scroll_bar_part (part_code
)
4710 ControlPartCode part_code
;
4714 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4715 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4716 case kControlPageUpPart
: return scroll_bar_above_handle
;
4717 case kControlPageDownPart
: return scroll_bar_below_handle
;
4718 case kControlIndicatorPart
: return scroll_bar_handle
;
4725 construct_scroll_bar_click (bar
, part
, bufp
)
4726 struct scroll_bar
*bar
;
4728 struct input_event
*bufp
;
4730 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4731 bufp
->frame_or_window
= bar
->window
;
4735 XSETINT (bufp
->x
, 0);
4736 XSETINT (bufp
->y
, 0);
4737 bufp
->modifiers
= 0;
4741 get_control_part_bounds (ch
, part_code
, rect
)
4743 ControlPartCode part_code
;
4746 RgnHandle region
= NewRgn ();
4749 err
= GetControlRegion (ch
, part_code
, region
);
4751 GetRegionBounds (region
, rect
);
4752 DisposeRgn (region
);
4758 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4759 struct scroll_bar
*bar
;
4760 ControlPartCode part_code
;
4761 struct input_event
*bufp
;
4763 int part
= control_part_code_to_scroll_bar_part (part_code
);
4768 if (part
!= scroll_bar_handle
)
4770 construct_scroll_bar_click (bar
, part
, bufp
);
4771 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4772 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4775 last_scroll_bar_part
= part
;
4776 bar
->dragging
= Qnil
;
4777 tracked_scroll_bar
= bar
;
4781 x_scroll_bar_handle_release (bar
, bufp
)
4782 struct scroll_bar
*bar
;
4783 struct input_event
*bufp
;
4785 if (last_scroll_bar_part
!= scroll_bar_handle
4786 || !GC_NILP (bar
->dragging
))
4787 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4789 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4790 set_scroll_bar_timer (kEventDurationForever
);
4792 last_scroll_bar_part
= -1;
4793 bar
->dragging
= Qnil
;
4794 tracked_scroll_bar
= NULL
;
4798 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4800 struct scroll_bar
*bar
;
4802 struct input_event
*bufp
;
4804 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4806 if (last_scroll_bar_part
== scroll_bar_handle
)
4811 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4812 kControlIndicatorPart
, &r
);
4814 if (GC_NILP (bar
->dragging
))
4815 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4817 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4818 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4819 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4824 if (top
> top_range
)
4827 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4828 XSETINT (bufp
->x
, top
);
4829 XSETINT (bufp
->y
, top_range
);
4833 ControlPartCode part_code
;
4834 int unhilite_p
= 0, part
;
4836 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4840 part
= control_part_code_to_scroll_bar_part (part_code
);
4842 switch (last_scroll_bar_part
)
4844 case scroll_bar_above_handle
:
4845 case scroll_bar_below_handle
:
4846 if (part
!= scroll_bar_above_handle
4847 && part
!= scroll_bar_below_handle
)
4851 case scroll_bar_up_arrow
:
4852 case scroll_bar_down_arrow
:
4853 if (part
!= scroll_bar_up_arrow
4854 && part
!= scroll_bar_down_arrow
)
4861 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4862 else if (part
!= last_scroll_bar_part
4863 || scroll_bar_timer_event_posted_p
)
4865 construct_scroll_bar_click (bar
, part
, bufp
);
4866 last_scroll_bar_part
= part
;
4867 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4868 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4873 /* Set the thumb size and position of scroll bar BAR. We are currently
4874 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4877 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4878 struct scroll_bar
*bar
;
4879 int portion
, position
, whole
;
4881 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4882 int value
, viewsize
, maximum
;
4884 if (XINT (bar
->track_height
) == 0)
4888 value
= 0, viewsize
= 1, maximum
= 0;
4893 maximum
= max (0, whole
- portion
);
4898 if (GetControlViewSize (ch
) != viewsize
4899 || GetControl32BitValue (ch
) != value
4900 || GetControl32BitMaximum (ch
) != maximum
)
4902 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4903 SetControlVisibility (ch
, false, false);
4905 SetControl32BitMaximum (ch
, maximum
);
4906 SetControl32BitValue (ch
, value
);
4907 SetControlViewSize (ch
, viewsize
);
4909 SetControlVisibility (ch
, true, true);
4915 #endif /* USE_TOOLKIT_SCROLL_BARS */
4919 /************************************************************************
4920 Scroll bars, general
4921 ************************************************************************/
4923 /* Create a scroll bar and return the scroll bar vector for it. W is
4924 the Emacs window on which to create the scroll bar. TOP, LEFT,
4925 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4928 static struct scroll_bar
*
4929 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4931 int top
, left
, width
, height
, disp_top
, disp_height
;
4933 struct frame
*f
= XFRAME (w
->frame
);
4934 struct scroll_bar
*bar
4935 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4943 r
.right
= left
+ width
;
4944 r
.bottom
= disp_top
+ disp_height
;
4947 mac_prepare_for_quickdraw (f
);
4949 #if TARGET_API_MAC_CARBON
4950 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4951 #if USE_TOOLKIT_SCROLL_BARS
4954 width
< disp_height
,
4956 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4958 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4959 0, 0, 0, scrollBarProc
, (long) bar
);
4961 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4963 XSETWINDOW (bar
->window
, w
);
4964 XSETINT (bar
->top
, top
);
4965 XSETINT (bar
->left
, left
);
4966 XSETINT (bar
->width
, width
);
4967 XSETINT (bar
->height
, height
);
4968 XSETINT (bar
->start
, 0);
4969 XSETINT (bar
->end
, 0);
4970 bar
->dragging
= Qnil
;
4971 #ifdef USE_TOOLKIT_SCROLL_BARS
4972 bar
->track_top
= Qnil
;
4973 bar
->track_height
= Qnil
;
4976 /* Add bar to its frame's list of scroll bars. */
4977 bar
->next
= FRAME_SCROLL_BARS (f
);
4979 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4980 if (!NILP (bar
->next
))
4981 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4988 /* Draw BAR's handle in the proper position.
4990 If the handle is already drawn from START to END, don't bother
4991 redrawing it, unless REBUILD is non-zero; in that case, always
4992 redraw it. (REBUILD is handy for drawing the handle after expose
4995 Normally, we want to constrain the start and end of the handle to
4996 fit inside its rectangle, but if the user is dragging the scroll
4997 bar handle, we want to let them drag it down all the way, so that
4998 the bar's top is as far down as it goes; otherwise, there's no way
4999 to move to the very end of the buffer. */
5001 #ifndef USE_TOOLKIT_SCROLL_BARS
5004 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5005 struct scroll_bar
*bar
;
5009 int dragging
= ! NILP (bar
->dragging
);
5010 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5011 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5012 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5013 int length
= end
- start
;
5015 /* If the display is already accurate, do nothing. */
5017 && start
== XINT (bar
->start
)
5018 && end
== XINT (bar
->end
))
5023 /* Make sure the values are reasonable, and try to preserve the
5024 distance between start and end. */
5027 else if (start
> top_range
)
5029 end
= start
+ length
;
5033 else if (end
> top_range
&& ! dragging
)
5036 /* Store the adjusted setting in the scroll bar. */
5037 XSETINT (bar
->start
, start
);
5038 XSETINT (bar
->end
, end
);
5040 /* Clip the end position, just for display. */
5041 if (end
> top_range
)
5044 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5045 top positions, to make sure the handle is always at least that
5046 many pixels tall. */
5047 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5049 SetControlMinimum (ch
, 0);
5050 /* Don't inadvertently activate deactivated scroll bars */
5051 if (GetControlMaximum (ch
) != -1)
5052 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5054 SetControlValue (ch
, start
);
5055 #if TARGET_API_MAC_CARBON
5056 SetControlViewSize (ch
, end
- start
);
5062 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5064 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5068 x_scroll_bar_remove (bar
)
5069 struct scroll_bar
*bar
;
5071 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5076 mac_prepare_for_quickdraw (f
);
5078 /* Destroy the Mac scroll bar control */
5079 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
5081 /* Disassociate this scroll bar from its window. */
5082 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5088 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5089 that we are displaying PORTION characters out of a total of WHOLE
5090 characters, starting at POSITION. If WINDOW has no scroll bar,
5094 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5096 int portion
, whole
, position
;
5098 struct frame
*f
= XFRAME (w
->frame
);
5099 struct scroll_bar
*bar
;
5100 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5101 int window_y
, window_height
;
5103 /* Get window dimensions. */
5104 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5106 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5107 height
= window_height
;
5109 /* Compute the left edge of the scroll bar area. */
5110 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5112 /* Compute the width of the scroll bar which might be less than
5113 the width of the area reserved for the scroll bar. */
5114 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5115 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5119 /* Compute the left edge of the scroll bar. */
5120 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5123 sb_left
= left
+ width
- sb_width
;
5125 /* Adjustments according to Inside Macintosh to make it look nice */
5127 disp_height
= height
;
5134 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5140 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5144 /* Does the scroll bar exist yet? */
5145 if (NILP (w
->vertical_scroll_bar
))
5148 mac_clear_area (f
, left
, top
, width
, height
);
5150 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5152 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5156 /* It may just need to be moved and resized. */
5159 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5160 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5164 /* If already correctly positioned, do nothing. */
5165 if (!(XINT (bar
->left
) == sb_left
5166 && XINT (bar
->top
) == top
5167 && XINT (bar
->width
) == sb_width
5168 && XINT (bar
->height
) == height
))
5170 /* Since toolkit scroll bars are smaller than the space reserved
5171 for them on the frame, we have to clear "under" them. */
5172 mac_clear_area (f
, left
, top
, width
, height
);
5175 mac_prepare_for_quickdraw (f
);
5178 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5179 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5181 #ifndef USE_TOOLKIT_SCROLL_BARS
5182 if (sb_width
< disp_height
)
5186 /* Remember new settings. */
5187 XSETINT (bar
->left
, sb_left
);
5188 XSETINT (bar
->top
, top
);
5189 XSETINT (bar
->width
, sb_width
);
5190 XSETINT (bar
->height
, height
);
5191 #ifdef USE_TOOLKIT_SCROLL_BARS
5192 bar
->track_top
= Qnil
;
5193 bar
->track_height
= Qnil
;
5200 #ifdef USE_TOOLKIT_SCROLL_BARS
5201 if (NILP (bar
->track_top
))
5203 if (sb_width
>= disp_height
)
5205 XSETINT (bar
->track_top
, 0);
5206 XSETINT (bar
->track_height
, 0);
5210 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5215 SetControl32BitMinimum (ch
, 0);
5216 SetControl32BitMaximum (ch
, 1);
5217 SetControlViewSize (ch
, 1);
5219 /* Move the scroll bar thumb to the top. */
5220 SetControl32BitValue (ch
, 0);
5221 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5223 /* Move the scroll bar thumb to the bottom. */
5224 SetControl32BitValue (ch
, 1);
5225 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5227 UnionRect (&r0
, &r1
, &r0
);
5228 XSETINT (bar
->track_top
, r0
.top
);
5229 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5231 /* Don't show the scroll bar if its height is not enough to
5232 display the scroll bar thumb. */
5233 if (r0
.bottom
- r0
.top
> 0)
5240 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5241 #else /* not USE_TOOLKIT_SCROLL_BARS */
5242 /* Set the scroll bar's current state, unless we're currently being
5244 if (NILP (bar
->dragging
))
5246 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5249 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5252 int start
= ((double) position
* top_range
) / whole
;
5253 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5254 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5257 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5261 /* The following three hooks are used when we're doing a thorough
5262 redisplay of the frame. We don't explicitly know which scroll bars
5263 are going to be deleted, because keeping track of when windows go
5264 away is a real pain - "Can you say set-window-configuration, boys
5265 and girls?" Instead, we just assert at the beginning of redisplay
5266 that *all* scroll bars are to be removed, and then save a scroll bar
5267 from the fiery pit when we actually redisplay its window. */
5269 /* Arrange for all scroll bars on FRAME to be removed at the next call
5270 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5271 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5274 XTcondemn_scroll_bars (frame
)
5277 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5278 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5281 bar
= FRAME_SCROLL_BARS (frame
);
5282 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5283 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5284 XSCROLL_BAR (bar
)->prev
= Qnil
;
5285 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5286 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5287 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5292 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5293 Note that WINDOW isn't necessarily condemned at all. */
5296 XTredeem_scroll_bar (window
)
5297 struct window
*window
;
5299 struct scroll_bar
*bar
;
5302 /* We can't redeem this window's scroll bar if it doesn't have one. */
5303 if (NILP (window
->vertical_scroll_bar
))
5306 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5308 /* Unlink it from the condemned list. */
5309 f
= XFRAME (WINDOW_FRAME (window
));
5310 if (NILP (bar
->prev
))
5312 /* If the prev pointer is nil, it must be the first in one of
5314 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5315 /* It's not condemned. Everything's fine. */
5317 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5318 window
->vertical_scroll_bar
))
5319 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5321 /* If its prev pointer is nil, it must be at the front of
5322 one or the other! */
5326 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5328 if (! NILP (bar
->next
))
5329 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5331 bar
->next
= FRAME_SCROLL_BARS (f
);
5333 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5334 if (! NILP (bar
->next
))
5335 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5338 /* Remove all scroll bars on FRAME that haven't been saved since the
5339 last call to `*condemn_scroll_bars_hook'. */
5342 XTjudge_scroll_bars (f
)
5345 Lisp_Object bar
, next
;
5347 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5349 /* Clear out the condemned list now so we won't try to process any
5350 more events on the hapless scroll bars. */
5351 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5353 for (; ! NILP (bar
); bar
= next
)
5355 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5357 x_scroll_bar_remove (b
);
5360 b
->next
= b
->prev
= Qnil
;
5363 /* Now there should be no references to the condemned scroll bars,
5364 and they should get garbage-collected. */
5368 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5369 is set to something other than NO_EVENT, it is enqueued.
5371 This may be called from a signal handler, so we have to ignore GC
5375 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5376 struct scroll_bar
*bar
;
5377 ControlPartCode part_code
;
5378 const EventRecord
*er
;
5379 struct input_event
*bufp
;
5381 int win_y
, top_range
;
5383 if (! GC_WINDOWP (bar
->window
))
5386 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5387 bufp
->frame_or_window
= bar
->window
;
5390 bar
->dragging
= Qnil
;
5394 case kControlUpButtonPart
:
5395 bufp
->part
= scroll_bar_up_arrow
;
5397 case kControlDownButtonPart
:
5398 bufp
->part
= scroll_bar_down_arrow
;
5400 case kControlPageUpPart
:
5401 bufp
->part
= scroll_bar_above_handle
;
5403 case kControlPageDownPart
:
5404 bufp
->part
= scroll_bar_below_handle
;
5406 #if TARGET_API_MAC_CARBON
5409 case kControlIndicatorPart
:
5411 if (er
->what
== mouseDown
)
5412 bar
->dragging
= make_number (0);
5413 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5414 bufp
->part
= scroll_bar_handle
;
5418 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5419 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5421 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5425 if (! NILP (bar
->dragging
))
5426 win_y
-= XINT (bar
->dragging
);
5430 if (win_y
> top_range
)
5433 XSETINT (bufp
->x
, win_y
);
5434 XSETINT (bufp
->y
, top_range
);
5437 #ifndef USE_TOOLKIT_SCROLL_BARS
5439 /* Handle some mouse motion while someone is dragging the scroll bar.
5441 This may be called from a signal handler, so we have to ignore GC
5445 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5446 struct scroll_bar
*bar
;
5450 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5452 last_mouse_movement_time
= t
;
5455 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5457 /* If we're dragging the bar, display it. */
5458 if (! GC_NILP (bar
->dragging
))
5460 /* Where should the handle be now? */
5461 int new_start
= y_pos
- 24;
5463 if (new_start
!= XINT (bar
->start
))
5465 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5467 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5472 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5474 /* Return information to the user about the current position of the mouse
5475 on the scroll bar. */
5478 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5480 Lisp_Object
*bar_window
;
5481 enum scroll_bar_part
*part
;
5483 unsigned long *time
;
5485 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5486 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5487 #if TARGET_API_MAC_CARBON
5488 WindowPtr wp
= GetControlOwner (ch
);
5490 WindowPtr wp
= (*ch
)->contrlOwner
;
5493 struct frame
*f
= mac_window_to_frame (wp
);
5494 int win_y
, top_range
;
5496 SetPortWindowPort (wp
);
5498 GetMouse (&mouse_pos
);
5500 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5501 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5503 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5507 if (! NILP (bar
->dragging
))
5508 win_y
-= XINT (bar
->dragging
);
5512 if (win_y
> top_range
)
5516 *bar_window
= bar
->window
;
5518 if (! NILP (bar
->dragging
))
5519 *part
= scroll_bar_handle
;
5520 else if (win_y
< XINT (bar
->start
))
5521 *part
= scroll_bar_above_handle
;
5522 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5523 *part
= scroll_bar_handle
;
5525 *part
= scroll_bar_below_handle
;
5527 XSETINT (*x
, win_y
);
5528 XSETINT (*y
, top_range
);
5531 last_mouse_scroll_bar
= Qnil
;
5533 *time
= last_mouse_movement_time
;
5537 /* The screen has been cleared so we may have changed foreground or
5538 background colors, and the scroll bars may need to be redrawn.
5539 Clear out the scroll bars, and ask for expose events, so we can
5543 x_scroll_bar_clear (f
)
5546 XTcondemn_scroll_bars (f
);
5547 XTjudge_scroll_bars (f
);
5551 /***********************************************************************
5553 ***********************************************************************/
5555 /* Set clipping for output in glyph row ROW. W is the window in which
5556 we operate. GC is the graphics context to set clipping in.
5558 ROW may be a text row or, e.g., a mode line. Text rows must be
5559 clipped to the interior of the window dedicated to text display,
5560 mode lines must be clipped to the whole window. */
5563 x_clip_to_row (w
, row
, area
, gc
)
5565 struct glyph_row
*row
;
5569 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5571 int window_x
, window_y
, window_width
;
5573 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5575 clip_rect
.left
= window_x
;
5576 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5577 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5578 clip_rect
.right
= clip_rect
.left
+ window_width
;
5579 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5581 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5585 /* Draw a hollow box cursor on window W in glyph row ROW. */
5588 x_draw_hollow_cursor (w
, row
)
5590 struct glyph_row
*row
;
5592 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5593 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5594 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5597 struct glyph
*cursor_glyph
;
5600 /* Get the glyph the cursor is on. If we can't tell because
5601 the current matrix is invalid or such, give up. */
5602 cursor_glyph
= get_phys_cursor_glyph (w
);
5603 if (cursor_glyph
== NULL
)
5606 /* Compute frame-relative coordinates for phys cursor. */
5607 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5608 wd
= w
->phys_cursor_width
;
5610 /* The foreground of cursor_gc is typically the same as the normal
5611 background color, which can cause the cursor box to be invisible. */
5612 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5613 if (dpyinfo
->scratch_cursor_gc
)
5614 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5616 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5617 GCForeground
, &xgcv
);
5618 gc
= dpyinfo
->scratch_cursor_gc
;
5620 /* Set clipping, draw the rectangle, and reset clipping again. */
5621 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5622 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5623 mac_reset_clip_rectangles (dpy
, gc
);
5627 /* Draw a bar cursor on window W in glyph row ROW.
5629 Implementation note: One would like to draw a bar cursor with an
5630 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5631 Unfortunately, I didn't find a font yet that has this property set.
5635 x_draw_bar_cursor (w
, row
, width
, kind
)
5637 struct glyph_row
*row
;
5639 enum text_cursor_kinds kind
;
5641 struct frame
*f
= XFRAME (w
->frame
);
5642 struct glyph
*cursor_glyph
;
5644 /* If cursor is out of bounds, don't draw garbage. This can happen
5645 in mini-buffer windows when switching between echo area glyphs
5647 cursor_glyph
= get_phys_cursor_glyph (w
);
5648 if (cursor_glyph
== NULL
)
5651 /* If on an image, draw like a normal cursor. That's usually better
5652 visible than drawing a bar, esp. if the image is large so that
5653 the bar might not be in the window. */
5654 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5656 struct glyph_row
*row
;
5657 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5658 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5662 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5663 Window window
= FRAME_MAC_WINDOW (f
);
5664 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5665 unsigned long mask
= GCForeground
| GCBackground
;
5666 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5669 /* If the glyph's background equals the color we normally draw
5670 the bar cursor in, the bar cursor in its normal color is
5671 invisible. Use the glyph's foreground color instead in this
5672 case, on the assumption that the glyph's colors are chosen so
5673 that the glyph is legible. */
5674 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5675 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5677 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5680 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5683 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5684 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5688 width
= FRAME_CURSOR_WIDTH (f
);
5689 width
= min (cursor_glyph
->pixel_width
, width
);
5691 w
->phys_cursor_width
= width
;
5692 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5694 if (kind
== BAR_CURSOR
)
5695 mac_fill_rectangle (f
, gc
,
5696 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5697 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5698 width
, row
->height
);
5700 mac_fill_rectangle (f
, gc
,
5701 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5702 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5703 row
->height
- width
),
5704 cursor_glyph
->pixel_width
,
5707 mac_reset_clip_rectangles (dpy
, gc
);
5712 /* RIF: Define cursor CURSOR on frame F. */
5715 mac_define_frame_cursor (f
, cursor
)
5719 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5721 if (dpyinfo
->x_focus_frame
== f
)
5722 SetThemeCursor (cursor
);
5726 /* RIF: Clear area on frame F. */
5729 mac_clear_frame_area (f
, x
, y
, width
, height
)
5731 int x
, y
, width
, height
;
5733 mac_clear_area (f
, x
, y
, width
, height
);
5737 /* RIF: Draw cursor on window W. */
5740 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5742 struct glyph_row
*glyph_row
;
5744 int cursor_type
, cursor_width
;
5749 w
->phys_cursor_type
= cursor_type
;
5750 w
->phys_cursor_on_p
= 1;
5752 if (glyph_row
->exact_window_width_line_p
5753 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5755 glyph_row
->cursor_in_fringe_p
= 1;
5756 draw_fringe_bitmap (w
, glyph_row
, 0);
5759 switch (cursor_type
)
5761 case HOLLOW_BOX_CURSOR
:
5762 x_draw_hollow_cursor (w
, glyph_row
);
5765 case FILLED_BOX_CURSOR
:
5766 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5770 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5774 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5778 w
->phys_cursor_width
= 0;
5790 #if 0 /* MAC_TODO: no icon support yet. */
5792 x_bitmap_icon (f
, icon
)
5798 if (FRAME_W32_WINDOW (f
) == 0)
5802 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5803 else if (STRINGP (icon
))
5804 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5805 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5806 else if (SYMBOLP (icon
))
5810 if (EQ (icon
, intern ("application")))
5811 name
= (LPCTSTR
) IDI_APPLICATION
;
5812 else if (EQ (icon
, intern ("hand")))
5813 name
= (LPCTSTR
) IDI_HAND
;
5814 else if (EQ (icon
, intern ("question")))
5815 name
= (LPCTSTR
) IDI_QUESTION
;
5816 else if (EQ (icon
, intern ("exclamation")))
5817 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5818 else if (EQ (icon
, intern ("asterisk")))
5819 name
= (LPCTSTR
) IDI_ASTERISK
;
5820 else if (EQ (icon
, intern ("winlogo")))
5821 name
= (LPCTSTR
) IDI_WINLOGO
;
5825 hicon
= LoadIcon (NULL
, name
);
5833 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5838 #endif /* MAC_TODO */
5840 /************************************************************************
5842 ************************************************************************/
5844 /* Display Error Handling functions not used on W32. Listing them here
5845 helps diff stay in step when comparing w32term.c with xterm.c.
5847 x_error_catcher (display, error)
5848 x_catch_errors (dpy)
5849 x_catch_errors_unwind (old_val)
5850 x_check_errors (dpy, format)
5851 x_had_errors_p (dpy)
5852 x_clear_errors (dpy)
5853 x_uncatch_errors (dpy, count)
5855 x_connection_signal (signalnum)
5856 x_connection_closed (dpy, error_message)
5857 x_error_quitter (display, error)
5858 x_error_handler (display, error)
5859 x_io_error_quitter (display)
5864 /* Changing the font of the frame. */
5866 /* Give frame F the font named FONTNAME as its default font, and
5867 return the full name of that font. FONTNAME may be a wildcard
5868 pattern; in that case, we choose some font that fits the pattern.
5869 The return value shows which font we chose. */
5872 x_new_font (f
, fontname
)
5874 register char *fontname
;
5876 struct font_info
*fontp
5877 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5882 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5883 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5884 FRAME_FONTSET (f
) = -1;
5886 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5887 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5888 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5890 compute_fringe_widths (f
, 1);
5892 /* Compute the scroll bar width in character columns. */
5893 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5895 int wid
= FRAME_COLUMN_WIDTH (f
);
5896 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5897 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5901 int wid
= FRAME_COLUMN_WIDTH (f
);
5902 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5905 /* Now make the frame display the given font. */
5906 if (FRAME_MAC_WINDOW (f
) != 0)
5908 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5910 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5912 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5915 /* Don't change the size of a tip frame; there's no point in
5916 doing it because it's done in Fx_show_tip, and it leads to
5917 problems because the tip frame has no widget. */
5918 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5919 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5922 return build_string (fontp
->full_name
);
5925 /* Give frame F the fontset named FONTSETNAME as its default font, and
5926 return the full name of that fontset. FONTSETNAME may be a wildcard
5927 pattern; in that case, we choose some fontset that fits the pattern.
5928 The return value shows which fontset we chose. */
5931 x_new_fontset (f
, fontsetname
)
5935 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5941 if (FRAME_FONTSET (f
) == fontset
)
5942 /* This fontset is already set in frame F. There's nothing more
5944 return fontset_name (fontset
);
5946 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5948 if (!STRINGP (result
))
5949 /* Can't load ASCII font. */
5952 /* Since x_new_font doesn't update any fontset information, do it now. */
5953 FRAME_FONTSET (f
) = fontset
;
5955 return build_string (fontsetname
);
5959 /***********************************************************************
5960 TODO: W32 Input Methods
5961 ***********************************************************************/
5962 /* Listing missing functions from xterm.c helps diff stay in step.
5964 xim_destroy_callback (xim, client_data, call_data)
5965 xim_open_dpy (dpyinfo, resource_name)
5967 xim_instantiate_callback (display, client_data, call_data)
5968 xim_initialize (dpyinfo, resource_name)
5969 xim_close_dpy (dpyinfo)
5975 mac_get_window_bounds (f
, inner
, outer
)
5977 Rect
*inner
, *outer
;
5979 #if TARGET_API_MAC_CARBON
5980 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5981 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5982 #else /* not TARGET_API_MAC_CARBON */
5983 RgnHandle region
= NewRgn ();
5985 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5986 *inner
= (*region
)->rgnBBox
;
5987 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5988 *outer
= (*region
)->rgnBBox
;
5989 DisposeRgn (region
);
5990 #endif /* not TARGET_API_MAC_CARBON */
5994 mac_handle_origin_change (f
)
5997 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6001 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6003 int pixelwidth
, pixelheight
;
6007 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6008 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6010 if (cols
!= FRAME_COLS (f
)
6011 || rows
!= FRAME_LINES (f
)
6012 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6013 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6015 /* We pass 1 for DELAY since we can't run Lisp code inside of
6017 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6018 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6019 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6020 SET_FRAME_GARBAGED (f
);
6022 /* If cursor was outside the new size, mark it as off. */
6023 mark_window_cursors_off (XWINDOW (f
->root_window
));
6025 /* Clear out any recollection of where the mouse highlighting
6026 was, since it might be in a place that's outside the new
6027 frame size. Actually checking whether it is outside is a
6028 pain in the neck, so don't try--just let the highlighting be
6029 done afresh with new size. */
6030 cancel_mouse_face (f
);
6032 #if TARGET_API_MAC_CARBON
6033 if (f
->output_data
.mac
->hourglass_control
)
6036 mac_prepare_for_quickdraw (f
);
6038 MoveControl (f
->output_data
.mac
->hourglass_control
,
6039 pixelwidth
- HOURGLASS_WIDTH
, 0);
6046 /* Calculate the absolute position in frame F
6047 from its current recorded position values and gravity. */
6050 x_calc_absolute_position (f
)
6053 int width_diff
= 0, height_diff
= 0;
6054 int flags
= f
->size_hint_flags
;
6057 /* We have nothing to do if the current position
6058 is already for the top-left corner. */
6059 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6062 /* Find the offsets of the outside upper-left corner of
6063 the inner window, with respect to the outer window. */
6064 mac_get_window_bounds (f
, &inner
, &outer
);
6066 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6067 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6069 /* Treat negative positions as relative to the leftmost bottommost
6070 position that fits on the screen. */
6071 if (flags
& XNegative
)
6072 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6074 - FRAME_PIXEL_WIDTH (f
)
6077 if (flags
& YNegative
)
6078 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6080 - FRAME_PIXEL_HEIGHT (f
)
6083 /* The left_pos and top_pos
6084 are now relative to the top and left screen edges,
6085 so the flags should correspond. */
6086 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6089 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6090 to really change the position, and 0 when calling from
6091 x_make_frame_visible (in that case, XOFF and YOFF are the current
6092 position values). It is -1 when calling from x_set_frame_parameters,
6093 which means, do adjust for borders but don't change the gravity. */
6096 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6098 register int xoff
, yoff
;
6101 if (change_gravity
> 0)
6105 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6107 f
->size_hint_flags
|= XNegative
;
6109 f
->size_hint_flags
|= YNegative
;
6110 f
->win_gravity
= NorthWestGravity
;
6112 x_calc_absolute_position (f
);
6115 x_wm_set_size_hint (f
, (long) 0, 0);
6117 #if TARGET_API_MAC_CARBON
6118 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6119 /* If the title bar is completely outside the screen, adjust the
6121 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6122 kWindowConstrainMoveRegardlessOfFit
6123 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6124 #if USE_CARBON_EVENTS
6125 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6127 mac_handle_origin_change (f
);
6130 Rect inner
, outer
, screen_rect
, dummy
;
6131 RgnHandle region
= NewRgn ();
6133 mac_get_window_bounds (f
, &inner
, &outer
);
6134 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6135 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6136 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6137 f
->top_pos
+ f
->y_pixels_diff
, false);
6139 /* If the title bar is completely outside the screen, adjust the
6140 position. The variable `outer' holds the title bar rectangle.
6141 The variable `inner' holds slightly smaller one than `outer',
6142 so that the calculation of overlapping may not become too
6144 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6145 outer
= (*region
)->rgnBBox
;
6146 DisposeRgn (region
);
6148 InsetRect (&inner
, 8, 8);
6149 screen_rect
= qd
.screenBits
.bounds
;
6150 screen_rect
.top
+= GetMBarHeight ();
6152 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6154 if (inner
.right
<= screen_rect
.left
)
6155 f
->left_pos
= screen_rect
.left
;
6156 else if (inner
.left
>= screen_rect
.right
)
6157 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6159 if (inner
.bottom
<= screen_rect
.top
)
6160 f
->top_pos
= screen_rect
.top
;
6161 else if (inner
.top
>= screen_rect
.bottom
)
6162 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6164 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6165 f
->top_pos
+ f
->y_pixels_diff
, false);
6173 /* Call this to change the size of frame F's x-window.
6174 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6175 for this size change and subsequent size changes.
6176 Otherwise we leave the window gravity unchanged. */
6179 x_set_window_size (f
, change_gravity
, cols
, rows
)
6184 int pixelwidth
, pixelheight
;
6188 check_frame_size (f
, &rows
, &cols
);
6189 f
->scroll_bar_actual_width
6190 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6192 compute_fringe_widths (f
, 0);
6194 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6195 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6197 f
->win_gravity
= NorthWestGravity
;
6198 x_wm_set_size_hint (f
, (long) 0, 0);
6200 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6202 #if USE_CARBON_EVENTS
6203 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6205 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6210 /* Mouse warping. */
6212 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6215 x_set_mouse_position (f
, x
, y
)
6221 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6222 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6224 if (pix_x
< 0) pix_x
= 0;
6225 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6227 if (pix_y
< 0) pix_y
= 0;
6228 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6230 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6234 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6243 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
6249 CGWarpMouseCursorPosition (point
);
6252 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6255 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6256 0, 0, 0, 0, pix_x
, pix_y
);
6262 /* focus shifting, raising and lowering. */
6265 x_focus_on_frame (f
)
6268 #if 0 /* This proves to be unpleasant. */
6272 /* I don't think that the ICCCM allows programs to do things like this
6273 without the interaction of the window manager. Whatever you end up
6274 doing with this code, do it to x_unfocus_frame too. */
6275 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6276 RevertToPointerRoot
, CurrentTime
);
6286 /* Raise frame F. */
6292 if (f
->async_visible
)
6295 BringToFront (FRAME_MAC_WINDOW (f
));
6300 /* Lower frame F. */
6306 if (f
->async_visible
)
6309 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6315 XTframe_raise_lower (f
, raise_flag
)
6325 /* Change of visibility. */
6328 mac_handle_visibility_change (f
)
6331 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6332 int visible
= 0, iconified
= 0;
6333 struct input_event buf
;
6335 if (IsWindowVisible (wp
))
6337 if (IsWindowCollapsed (wp
))
6343 if (!f
->async_visible
&& visible
)
6347 /* wait_reading_process_output will notice this and update
6348 the frame's display structures. If we were made
6349 invisible, we should not set garbaged, because that stops
6350 redrawing on Update events. */
6351 SET_FRAME_GARBAGED (f
);
6354 buf
.kind
= DEICONIFY_EVENT
;
6355 XSETFRAME (buf
.frame_or_window
, f
);
6357 kbd_buffer_store_event (&buf
);
6359 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6360 /* Force a redisplay sooner or later to update the
6361 frame titles in case this is the second frame. */
6362 record_asynch_buffer_change ();
6364 else if (f
->async_visible
&& !visible
)
6368 buf
.kind
= ICONIFY_EVENT
;
6369 XSETFRAME (buf
.frame_or_window
, f
);
6371 kbd_buffer_store_event (&buf
);
6374 f
->async_visible
= visible
;
6375 f
->async_iconified
= iconified
;
6378 /* This tries to wait until the frame is really visible.
6379 However, if the window manager asks the user where to position
6380 the frame, this will return before the user finishes doing that.
6381 The frame will not actually be visible at that time,
6382 but it will become visible later when the window manager
6383 finishes with it. */
6386 x_make_frame_visible (f
)
6391 if (! FRAME_VISIBLE_P (f
))
6393 /* We test FRAME_GARBAGED_P here to make sure we don't
6394 call x_set_offset a second time
6395 if we get to x_make_frame_visible a second time
6396 before the window gets really visible. */
6397 if (! FRAME_ICONIFIED_P (f
)
6398 && ! f
->output_data
.mac
->asked_for_visible
)
6400 #if TARGET_API_MAC_CARBON
6401 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6403 struct frame
*sf
= SELECTED_FRAME ();
6404 if (!FRAME_MAC_P (sf
))
6405 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6406 kWindowCenterOnMainScreen
);
6408 RepositionWindow (FRAME_MAC_WINDOW (f
),
6409 FRAME_MAC_WINDOW (sf
),
6410 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6411 kWindowCascadeStartAtParentWindowScreen
6413 kWindowCascadeOnParentWindowScreen
6416 #if USE_CARBON_EVENTS
6417 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6419 mac_handle_origin_change (f
);
6423 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6426 f
->output_data
.mac
->asked_for_visible
= 1;
6428 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6429 ShowWindow (FRAME_MAC_WINDOW (f
));
6432 XFlush (FRAME_MAC_DISPLAY (f
));
6434 /* Synchronize to ensure Emacs knows the frame is visible
6435 before we do anything else. We do this loop with input not blocked
6436 so that incoming events are handled. */
6441 /* This must come after we set COUNT. */
6444 XSETFRAME (frame
, f
);
6446 /* Wait until the frame is visible. Process X events until a
6447 MapNotify event has been seen, or until we think we won't get a
6448 MapNotify at all.. */
6449 for (count
= input_signal_count
+ 10;
6450 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6452 /* Force processing of queued events. */
6455 /* Machines that do polling rather than SIGIO have been
6456 observed to go into a busy-wait here. So we'll fake an
6457 alarm signal to let the handler know that there's something
6458 to be read. We used to raise a real alarm, but it seems
6459 that the handler isn't always enabled here. This is
6461 if (input_polling_used ())
6463 /* It could be confusing if a real alarm arrives while
6464 processing the fake one. Turn it off and let the
6465 handler reset it. */
6466 extern void poll_for_input_1
P_ ((void));
6467 int old_poll_suppress_count
= poll_suppress_count
;
6468 poll_suppress_count
= 1;
6469 poll_for_input_1 ();
6470 poll_suppress_count
= old_poll_suppress_count
;
6473 /* See if a MapNotify event has been processed. */
6474 FRAME_SAMPLE_VISIBILITY (f
);
6479 /* Change from mapped state to withdrawn state. */
6481 /* Make the frame visible (mapped and not iconified). */
6484 x_make_frame_invisible (f
)
6487 /* A deactivate event does not occur when the last visible frame is
6488 made invisible. So if we clear the highlight here, it will not
6489 be rehighlighted when it is made visible. */
6491 /* Don't keep the highlight on an invisible frame. */
6492 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6493 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6498 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6499 that the current position of the window is user-specified, rather than
6500 program-specified, so that when the window is mapped again, it will be
6501 placed at the same location, without forcing the user to position it
6502 by hand again (they have already done that once for this window.) */
6503 x_wm_set_size_hint (f
, (long) 0, 1);
6505 HideWindow (FRAME_MAC_WINDOW (f
));
6509 #if !USE_CARBON_EVENTS
6510 mac_handle_visibility_change (f
);
6514 /* Change window state from mapped to iconified. */
6522 /* A deactivate event does not occur when the last visible frame is
6523 iconified. So if we clear the highlight here, it will not be
6524 rehighlighted when it is deiconified. */
6526 /* Don't keep the highlight on an invisible frame. */
6527 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6528 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6531 if (f
->async_iconified
)
6536 FRAME_SAMPLE_VISIBILITY (f
);
6538 if (! FRAME_VISIBLE_P (f
))
6539 ShowWindow (FRAME_MAC_WINDOW (f
));
6541 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6546 error ("Can't notify window manager of iconification");
6548 #if !USE_CARBON_EVENTS
6549 mac_handle_visibility_change (f
);
6554 /* Free X resources of frame F. */
6557 x_free_frame_resources (f
)
6560 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6561 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6565 if (wp
!= tip_window
)
6566 remove_window_handler (wp
);
6569 if (wp
== tip_window
)
6570 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6571 closed' event. So we reset tip_window here. */
6574 free_frame_menubar (f
);
6576 if (FRAME_FACE_CACHE (f
))
6577 free_frame_faces (f
);
6581 if (FRAME_SIZE_HINTS (f
))
6582 xfree (FRAME_SIZE_HINTS (f
));
6584 xfree (f
->output_data
.mac
);
6585 f
->output_data
.mac
= NULL
;
6587 if (f
== dpyinfo
->x_focus_frame
)
6589 dpyinfo
->x_focus_frame
= 0;
6590 #if USE_MAC_FONT_PANEL
6591 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6594 if (f
== dpyinfo
->x_focus_event_frame
)
6595 dpyinfo
->x_focus_event_frame
= 0;
6596 if (f
== dpyinfo
->x_highlight_frame
)
6597 dpyinfo
->x_highlight_frame
= 0;
6599 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6601 dpyinfo
->mouse_face_beg_row
6602 = dpyinfo
->mouse_face_beg_col
= -1;
6603 dpyinfo
->mouse_face_end_row
6604 = dpyinfo
->mouse_face_end_col
= -1;
6605 dpyinfo
->mouse_face_window
= Qnil
;
6606 dpyinfo
->mouse_face_deferred_gc
= 0;
6607 dpyinfo
->mouse_face_mouse_frame
= 0;
6614 /* Destroy the X window of frame F. */
6617 x_destroy_window (f
)
6620 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6622 x_free_frame_resources (f
);
6624 dpyinfo
->reference_count
--;
6628 /* Setting window manager hints. */
6630 /* Set the normal size hints for the window manager, for frame F.
6631 FLAGS is the flags word to use--or 0 meaning preserve the flags
6632 that the window now has.
6633 If USER_POSITION is nonzero, we set the USPosition
6634 flag (this is useful when FLAGS is 0). */
6636 x_wm_set_size_hint (f
, flags
, user_position
)
6641 int base_width
, base_height
, width_inc
, height_inc
;
6642 int min_rows
= 0, min_cols
= 0;
6643 XSizeHints
*size_hints
;
6645 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6646 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6647 width_inc
= FRAME_COLUMN_WIDTH (f
);
6648 height_inc
= FRAME_LINE_HEIGHT (f
);
6650 check_frame_size (f
, &min_rows
, &min_cols
);
6652 size_hints
= FRAME_SIZE_HINTS (f
);
6653 if (size_hints
== NULL
)
6655 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6656 bzero (size_hints
, sizeof (XSizeHints
));
6659 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6660 size_hints
->width_inc
= width_inc
;
6661 size_hints
->height_inc
= height_inc
;
6662 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6663 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6664 size_hints
->base_width
= base_width
;
6665 size_hints
->base_height
= base_height
;
6668 size_hints
->flags
= flags
;
6669 else if (user_position
)
6671 size_hints
->flags
&= ~ PPosition
;
6672 size_hints
->flags
|= USPosition
;
6676 #if 0 /* MAC_TODO: hide application instead of iconify? */
6677 /* Used for IconicState or NormalState */
6680 x_wm_set_window_state (f
, state
)
6684 #ifdef USE_X_TOOLKIT
6687 XtSetArg (al
[0], XtNinitialState
, state
);
6688 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6689 #else /* not USE_X_TOOLKIT */
6690 Window window
= FRAME_X_WINDOW (f
);
6692 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6693 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6695 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6696 #endif /* not USE_X_TOOLKIT */
6700 x_wm_set_icon_pixmap (f
, pixmap_id
)
6706 #ifndef USE_X_TOOLKIT
6707 Window window
= FRAME_X_WINDOW (f
);
6712 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6713 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6717 /* It seems there is no way to turn off use of an icon pixmap.
6718 The following line does it, only if no icon has yet been created,
6719 for some window managers. But with mwm it crashes.
6720 Some people say it should clear the IconPixmapHint bit in this case,
6721 but that doesn't work, and the X consortium said it isn't the
6722 right thing at all. Since there is no way to win,
6723 best to explicitly give up. */
6725 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6731 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6735 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6736 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6739 #else /* not USE_X_TOOLKIT */
6741 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6742 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6744 #endif /* not USE_X_TOOLKIT */
6747 #endif /* MAC_TODO */
6750 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6754 #if 0 /* MAC_TODO: no icons on Mac */
6755 #ifdef USE_X_TOOLKIT
6756 Window window
= XtWindow (f
->output_data
.x
->widget
);
6758 Window window
= FRAME_X_WINDOW (f
);
6761 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6762 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6763 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6765 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6766 #endif /* MAC_TODO */
6770 /***********************************************************************
6772 ***********************************************************************/
6774 /* An XLFD pattern is divided into blocks delimited by '*'. This
6775 structure holds information for each block. */
6776 struct xlfdpat_block
6778 /* Length of the pattern string in this block. Non-zero except for
6779 the first and the last blocks. */
6782 /* Pattern string except the last character in this block. The last
6783 character is replaced with NUL in order to use it as a
6785 unsigned char *pattern
;
6787 /* Last character of the pattern string. Must not be '?'. */
6788 unsigned char last_char
;
6790 /* One of the tables for the Boyer-Moore string search. It
6791 specifies the number of positions to proceed for each character
6792 with which the match fails. */
6795 /* The skip value for the last character in the above `skip' is
6796 assigned to `infinity' in order to simplify a loop condition.
6797 The original value is saved here. */
6803 /* Normalized pattern string. "Normalized" means that capital
6804 letters are lowered, blocks are not empty except the first and
6805 the last ones, and trailing '?'s in a block that is not the last
6806 one are moved to the next one. The last character in each block
6807 is replaced with NUL. */
6810 /* Number of characters except '*'s and trailing '?'s in the
6811 normalized pattern string. */
6814 /* Number of trailing '?'s in the normalized pattern string. */
6815 int trailing_anychars
;
6817 /* Number of blocks and information for each block. The latter is
6818 NULL if the pattern is exact (no '*' or '?' in it). */
6820 struct xlfdpat_block
*blocks
;
6824 xlfdpat_destroy (pat
)
6825 struct xlfdpat
*pat
;
6832 xfree (pat
->blocks
);
6839 static struct xlfdpat
*
6840 xlfdpat_create (pattern
)
6841 const char *pattern
;
6843 struct xlfdpat
*pat
;
6844 int nblocks
, i
, skip
;
6845 unsigned char last_char
, *p
, *q
, *anychar_head
;
6846 const unsigned char *ptr
;
6847 struct xlfdpat_block
*blk
;
6849 pat
= xmalloc (sizeof (struct xlfdpat
));
6850 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6852 /* Normalize the pattern string and store it to `pat->buf'. */
6854 anychar_head
= NULL
;
6857 for (ptr
= pattern
; *ptr
; ptr
++)
6859 unsigned char c
= *ptr
;
6862 if (last_char
== '*')
6863 /* ...a** -> ...a* */
6867 if (last_char
== '?')
6869 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6870 /* ...*??* -> ...*?? */
6873 /* ...a??* -> ...a*?? */
6875 *anychar_head
++ = '*';
6883 if (last_char
!= '?')
6887 /* On Mac OS X 10.3, tolower also converts non-ASCII
6888 characters for some locales. */
6892 *q
++ = last_char
= c
;
6896 pat
->nblocks
= nblocks
;
6897 if (last_char
!= '?')
6898 pat
->trailing_anychars
= 0;
6901 pat
->trailing_anychars
= q
- anychar_head
;
6904 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6906 if (anychar_head
== NULL
&& nblocks
== 1)
6908 /* The pattern is exact. */
6913 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6915 /* Divide the normalized pattern into blocks. */
6917 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6922 blk
->len
= p
- blk
->pattern
;
6926 blk
->len
= q
- blk
->pattern
;
6928 /* Setup a table for the Boyer-Moore string search. */
6929 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6932 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6933 blk
->pattern
[blk
->len
- 1] = '\0';
6935 for (skip
= 1; skip
< blk
->len
; skip
++)
6936 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6939 for (i
= 0; i
< 256; i
++)
6940 blk
->skip
[i
] = skip
;
6942 p
= blk
->pattern
+ (blk
->len
- skip
);
6944 blk
->skip
[*p
++] = skip
;
6946 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6953 xlfdpat_exact_p (pat
)
6954 struct xlfdpat
*pat
;
6956 return pat
->blocks
== NULL
;
6959 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6960 that the pattern in *BLK matches with its prefix. Return NULL
6961 there is no such strings. STRING must be lowered in advance. */
6964 xlfdpat_block_match_1 (blk
, string
, start_max
)
6965 struct xlfdpat_block
*blk
;
6966 const unsigned char *string
;
6969 int start
, infinity
;
6971 const unsigned char *s
;
6973 xassert (blk
->len
> 0);
6974 xassert (start_max
+ blk
->len
<= strlen (string
));
6975 xassert (blk
->last_char
!= '?');
6977 /* See the comments in the function `boyer_moore' (search.c) for the
6978 use of `infinity'. */
6979 infinity
= start_max
+ blk
->len
+ 1;
6980 blk
->skip
[blk
->last_char
] = infinity
;
6985 /* Check the last character of the pattern. */
6986 s
= string
+ blk
->len
- 1;
6989 start
+= blk
->skip
[*(s
+ start
)];
6991 while (start
<= start_max
);
6993 if (start
< infinity
)
6994 /* Couldn't find the last character. */
6997 /* No less than `infinity' means we could find the last
6998 character at `s[start - infinity]'. */
7001 /* Check the remaining characters. We prefer making no-'?'
7002 cases faster because the use of '?' is really rare. */
7007 while (*p
++ == *s
++)
7010 while (*(p
- 1) == '?');
7012 if (*(p
- 1) == '\0')
7014 return string
+ start
;
7017 start
+= blk
->last_char_skip
;
7019 while (start
<= start_max
);
7024 #define xlfdpat_block_match(b, s, m) \
7025 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7026 : xlfdpat_block_match_1 (b, s, m))
7028 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7029 matches with STRING. STRING must be lowered in advance. */
7032 xlfdpat_match (pat
, string
)
7033 struct xlfdpat
*pat
;
7034 const unsigned char *string
;
7036 int str_len
, nblocks
, i
, start_max
;
7037 struct xlfdpat_block
*blk
;
7038 const unsigned char *s
;
7040 xassert (pat
->nblocks
> 0);
7042 if (xlfdpat_exact_p (pat
))
7043 return strcmp (pat
->buf
, string
) == 0;
7045 /* The number of the characters in the string must not be smaller
7046 than that in the pattern. */
7047 str_len
= strlen (string
);
7048 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7051 /* Chop off the trailing '?'s. */
7052 str_len
-= pat
->trailing_anychars
;
7054 /* The last block. When it is non-empty, it must match at the end
7056 nblocks
= pat
->nblocks
;
7057 blk
= pat
->blocks
+ (nblocks
- 1);
7059 /* The last block is also the first one. */
7060 return (str_len
== blk
->len
7061 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7062 else if (blk
->len
!= 0)
7063 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7066 /* The first block. When it is non-empty, it must match at the
7067 beginning of the string. */
7071 s
= xlfdpat_block_match (blk
, string
, 0);
7074 string
= s
+ blk
->len
;
7077 /* The rest of the blocks. */
7078 start_max
= str_len
- pat
->nchars
;
7079 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7081 s
= xlfdpat_block_match (blk
, string
, start_max
);
7084 start_max
-= s
- string
;
7085 string
= s
+ blk
->len
;
7092 /***********************************************************************
7094 ***********************************************************************/
7096 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7099 x_get_font_info (f
, font_idx
)
7103 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7106 /* the global font name table */
7107 static char **font_name_table
= NULL
;
7108 static int font_name_table_size
= 0;
7109 static int font_name_count
= 0;
7111 /* Alist linking font family names to Font Manager font family
7112 references (which can also be used as QuickDraw font IDs). We use
7113 an alist because hash tables are not ready when the terminal frame
7114 for Mac OS Classic is created. */
7115 static Lisp_Object fm_font_family_alist
;
7117 /* Hash table linking font family names to ATSU font IDs. */
7118 static Lisp_Object atsu_font_id_hash
;
7119 /* Alist linking Font Manager style to face attributes. */
7120 static Lisp_Object fm_style_face_attributes_alist
;
7121 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7124 /* Alist linking character set strings to Mac text encoding and Emacs
7126 static Lisp_Object Vmac_charset_info_alist
;
7129 create_text_encoding_info_alist ()
7131 Lisp_Object result
= Qnil
, rest
;
7133 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7135 Lisp_Object charset_info
= XCAR (rest
);
7136 Lisp_Object charset
, coding_system
, text_encoding
;
7137 Lisp_Object existing_info
;
7139 if (!(CONSP (charset_info
)
7140 && STRINGP (charset
= XCAR (charset_info
))
7141 && CONSP (XCDR (charset_info
))
7142 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
7143 && CONSP (XCDR (XCDR (charset_info
)))
7144 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
7147 existing_info
= assq_no_quit (text_encoding
, result
);
7148 if (NILP (existing_info
))
7149 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7152 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7153 XSETCDR (XCDR (existing_info
),
7154 Fcons (charset
, XCDR (XCDR (existing_info
))));
7162 decode_mac_font_name (name
, size
, coding_system
)
7165 Lisp_Object coding_system
;
7167 struct coding_system coding
;
7170 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7172 for (p
= name
; *p
; p
++)
7173 if (!isascii (*p
) || iscntrl (*p
))
7178 setup_coding_system (coding_system
, &coding
);
7179 coding
.src_multibyte
= 0;
7180 coding
.dst_multibyte
= 1;
7181 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7182 coding
.composing
= COMPOSITION_DISABLED
;
7183 buf
= (char *) alloca (size
);
7185 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7186 bcopy (buf
, name
, coding
.produced
);
7187 name
[coding
.produced
] = '\0';
7191 /* If there's just one occurrence of '-' in the family name, it is
7192 replaced with '_'. (More than one occurrence of '-' means a
7193 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7194 p
= strchr (name
, '-');
7195 if (p
&& strchr (p
+ 1, '-') == NULL
)
7198 for (p
= name
; *p
; p
++)
7199 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7200 for some locales. */
7207 mac_to_x_fontname (name
, size
, style
, charset
)
7215 char xf
[256], *result
;
7218 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7222 strcpy(foundry
, "Apple");
7223 strcpy(family
, name
);
7226 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7227 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7228 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7230 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7231 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7232 for (p
= result
; *p
; p
++)
7233 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7234 for some locales. */
7241 /* Parse fully-specified and instantiated X11 font spec XF, and store
7242 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7243 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7244 caller must allocate at least 256 and 32 bytes respectively. For
7245 ordinary Mac fonts, the value stored to FAMILY should just be their
7246 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7247 intlfonts collection contain their charset designation in their
7248 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7249 types of font names are handled accordingly. */
7251 const int kDefaultFontSize
= 12;
7254 parse_x_font_name (xf
, family
, size
, style
, charset
)
7261 Str31 foundry
, weight
;
7262 int point_size
, avgwidth
;
7265 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7266 foundry
, family
, weight
, slant
, size
,
7267 &point_size
, &avgwidth
, charset
) != 8
7268 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7269 foundry
, family
, weight
, slant
, size
,
7270 &point_size
, &avgwidth
, charset
) != 8)
7276 *size
= point_size
/ 10;
7277 else if (avgwidth
> 0)
7278 *size
= avgwidth
/ 10;
7281 *size
= kDefaultFontSize
;
7284 if (strcmp (weight
, "bold") == 0)
7289 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7291 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7293 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7295 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7296 but take overlap into account. */
7297 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7298 memcpy (family
, foundry
, foundry_len
);
7299 family
[foundry_len
] = '-';
7300 family
[foundry_len
+ 1 + family_len
] = '-';
7301 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7307 for (p
= family
; *p
; p
++)
7308 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7309 for some locales. */
7318 add_font_name_table_entry (char *font_name
)
7320 if (font_name_table_size
== 0)
7322 font_name_table_size
= 256;
7323 font_name_table
= (char **)
7324 xmalloc (font_name_table_size
* sizeof (char *));
7326 else if (font_name_count
+ 1 >= font_name_table_size
)
7328 font_name_table_size
*= 2;
7329 font_name_table
= (char **)
7330 xrealloc (font_name_table
,
7331 font_name_table_size
* sizeof (char *));
7334 font_name_table
[font_name_count
++] = font_name
;
7338 add_mac_font_name (name
, size
, style
, charset
)
7342 const char *charset
;
7345 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7348 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7349 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7350 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7351 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7358 fm_get_style_from_font (font
)
7362 FMFontStyle style
= normal
;
7365 FMFontFamily font_family
;
7366 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
7368 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
7369 some font (e.g., Optima) even if it is `bold'. */
7370 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
7371 sizeof (mac_style
), &mac_style
, &len
);
7373 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
7374 style
= EndianU16_BtoN (mac_style
);
7376 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
7382 atsu_find_font_from_family_name (family
)
7385 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
7388 Lisp_Object rest
, best
;
7389 FMFontStyle min_style
, style
;
7391 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
7394 return kATSUInvalidFontID
;
7396 rest
= HASH_VALUE (h
, i
);
7397 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
7398 return cons_to_long (rest
);
7400 rest
= Fnreverse (rest
);
7404 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
7407 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
7408 if (style
< min_style
)
7411 if (style
== normal
)
7418 while (!NILP (rest
));
7420 HASH_VALUE (h
, i
) = best
;
7421 return cons_to_long (best
);
7425 fm_style_to_face_attributes (fm_style
)
7426 FMFontStyle fm_style
;
7430 fm_style
&= (bold
| italic
);
7431 tem
= assq_no_quit (make_number (fm_style
),
7432 fm_style_face_attributes_alist
);
7436 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
7437 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
7438 fm_style_face_attributes_alist
=
7439 Fcons (Fcons (make_number (fm_style
), tem
),
7440 fm_style_face_attributes_alist
);
7446 atsu_find_font_family_name (font_id
)
7451 Lisp_Object family
= Qnil
;
7453 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7454 kFontMacintoshPlatform
, kFontNoScript
,
7455 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
7458 family
= make_uninit_string (len
);
7459 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7460 kFontMacintoshPlatform
, kFontNoScript
,
7461 kFontNoLanguage
, len
, SDATA (family
),
7465 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
7471 mac_atsu_font_face_attributes (font_id
)
7474 Lisp_Object family
, style_attrs
;
7476 family
= atsu_find_font_family_name (font_id
);
7479 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
7480 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
7484 /* Sets up the table font_name_table to contain the list of all fonts
7485 in the system the first time the table is used so that the Resource
7486 Manager need not be accessed every time this information is
7490 init_font_name_table ()
7492 #if TARGET_API_MAC_CARBON
7493 FMFontFamilyIterator ffi
;
7494 FMFontFamilyInstanceIterator ffii
;
7496 Lisp_Object text_encoding_info_alist
;
7497 struct gcpro gcpro1
;
7499 text_encoding_info_alist
= create_text_encoding_info_alist ();
7502 #if USE_CG_TEXT_DRAWING
7503 init_cg_text_anti_aliasing_threshold ();
7505 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7506 text_encoding_info_alist
)))
7509 struct Lisp_Hash_Table
*h
;
7511 ItemCount nfonts
, i
;
7512 ATSUFontID
*font_ids
= NULL
;
7513 Lisp_Object prev_family
= Qnil
;
7517 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7518 make_float (DEFAULT_REHASH_SIZE
),
7519 make_float (DEFAULT_REHASH_THRESHOLD
),
7521 h
= XHASH_TABLE (atsu_font_id_hash
);
7523 err
= ATSUFontCount (&nfonts
);
7526 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7527 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7530 for (i
= 0; i
< nfonts
; i
++)
7534 family
= atsu_find_font_family_name (font_ids
[i
]);
7535 if (NILP (family
) || SREF (family
, 0) == '.')
7537 if (!NILP (Fequal (prev_family
, family
)))
7538 family
= prev_family
;
7540 j
= hash_lookup (h
, family
, &hash_code
);
7543 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
7544 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
7547 else if (EQ (prev_family
, family
))
7548 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
7550 prev_family
= family
;
7557 /* Create a dummy instance iterator here to avoid creating and
7558 destroying it in the loop. */
7559 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7561 /* Create an iterator to enumerate the font families. */
7562 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7565 FMDisposeFontFamilyInstanceIterator (&ffii
);
7569 GCPRO1 (text_encoding_info_alist
);
7571 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7577 TextEncoding encoding
;
7578 TextEncodingBase sc
;
7579 Lisp_Object text_encoding_info
, family
;
7581 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7587 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7589 sc
= GetTextEncodingBase (encoding
);
7590 text_encoding_info
= assq_no_quit (make_number (sc
),
7591 text_encoding_info_alist
);
7592 if (NILP (text_encoding_info
))
7593 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7594 text_encoding_info_alist
);
7595 decode_mac_font_name (name
, sizeof (name
),
7596 XCAR (XCDR (text_encoding_info
)));
7597 family
= build_string (name
);
7598 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7600 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7601 fm_font_family_alist
);
7603 /* Point the instance iterator at the current font family. */
7604 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7607 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7610 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7612 if (size
> 0 || style
== normal
)
7613 for (; !NILP (rest
); rest
= XCDR (rest
))
7614 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7620 /* Dispose of the iterators. */
7621 FMDisposeFontFamilyIterator (&ffi
);
7622 FMDisposeFontFamilyInstanceIterator (&ffii
);
7623 #else /* !TARGET_API_MAC_CARBON */
7625 SInt16 fontnum
, old_fontnum
;
7626 int num_mac_fonts
= CountResources('FOND');
7628 Handle font_handle
, font_handle_2
;
7629 short id
, scriptcode
;
7632 struct FontAssoc
*fat
;
7633 struct AsscEntry
*assc_entry
;
7634 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7635 struct gcpro gcpro1
;
7637 GetPort (&port
); /* save the current font number used */
7638 old_fontnum
= port
->txFont
;
7640 text_encoding_info_alist
= create_text_encoding_info_alist ();
7642 GCPRO1 (text_encoding_info_alist
);
7644 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7646 font_handle
= GetIndResource ('FOND', i
);
7650 GetResInfo (font_handle
, &id
, &type
, name
);
7651 GetFNum (name
, &fontnum
);
7653 if (fontnum
== 0 || *name
== '.')
7657 scriptcode
= FontToScript (fontnum
);
7658 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7659 text_encoding_info_alist
);
7660 if (NILP (text_encoding_info
))
7661 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7662 text_encoding_info_alist
);
7663 decode_mac_font_name (name
, sizeof (name
),
7664 XCAR (XCDR (text_encoding_info
)));
7665 family
= build_string (name
);
7666 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7668 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7669 fm_font_family_alist
);
7672 HLock (font_handle
);
7674 if (GetResourceSizeOnDisk (font_handle
)
7675 >= sizeof (struct FamRec
))
7677 fat
= (struct FontAssoc
*) (*font_handle
7678 + sizeof (struct FamRec
));
7680 = (struct AsscEntry
*) (*font_handle
7681 + sizeof (struct FamRec
)
7682 + sizeof (struct FontAssoc
));
7684 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7686 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7688 for (; !NILP (rest
); rest
= XCDR (rest
))
7689 add_mac_font_name (name
, assc_entry
->fontSize
,
7690 assc_entry
->fontStyle
,
7691 SDATA (XCAR (rest
)));
7695 HUnlock (font_handle
);
7696 font_handle_2
= GetNextFOND (font_handle
);
7697 ReleaseResource (font_handle
);
7698 font_handle
= font_handle_2
;
7700 while (ResError () == noErr
&& font_handle
);
7705 TextFont (old_fontnum
);
7706 #endif /* !TARGET_API_MAC_CARBON */
7711 mac_clear_font_name_table ()
7715 for (i
= 0; i
< font_name_count
; i
++)
7716 xfree (font_name_table
[i
]);
7717 xfree (font_name_table
);
7718 font_name_table
= NULL
;
7719 font_name_table_size
= font_name_count
= 0;
7720 fm_font_family_alist
= Qnil
;
7724 enum xlfd_scalable_field_index
7726 XLFD_SCL_PIXEL_SIZE
,
7727 XLFD_SCL_POINT_SIZE
,
7732 static const int xlfd_scalable_fields
[] =
7741 mac_do_list_fonts (pattern
, maxnames
)
7742 const char *pattern
;
7746 Lisp_Object font_list
= Qnil
;
7747 struct xlfdpat
*pat
;
7750 int scl_val
[XLFD_SCL_LAST
], *val
;
7754 if (font_name_table
== NULL
) /* Initialize when first used. */
7755 init_font_name_table ();
7757 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7760 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7761 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7762 fonts are scaled according to the specified size. */
7765 field
= xlfd_scalable_fields
;
7773 if ('0' <= *ptr
&& *ptr
<= '9')
7775 *val
= *ptr
++ - '0';
7776 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7777 *val
= *val
* 10 + *ptr
++ - '0';
7784 ptr
= strchr (ptr
, '-');
7787 while (ptr
&& i
< 14);
7789 if (i
== 14 && ptr
== NULL
)
7791 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7792 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7793 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7794 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7796 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7797 scl_val
[XLFD_SCL_POINT_SIZE
] =
7798 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7799 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7801 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7802 scl_val
[XLFD_SCL_AVGWIDTH
] =
7803 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7804 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7808 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7810 pat
= xlfdpat_create (pattern
);
7814 exact
= xlfdpat_exact_p (pat
);
7816 for (i
= 0; i
< font_name_count
; i
++)
7818 if (xlfdpat_match (pat
, font_name_table
[i
]))
7820 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7821 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7824 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7825 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7827 int former_len
= ptr
- font_name_table
[i
];
7829 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7830 memcpy (scaled
, font_name_table
[i
], former_len
);
7831 sprintf (scaled
+ former_len
,
7832 "-%d-%d-72-72-m-%d-%s",
7833 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7834 scl_val
[XLFD_SCL_POINT_SIZE
],
7835 scl_val
[XLFD_SCL_AVGWIDTH
],
7836 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7838 if (xlfdpat_match (pat
, scaled
))
7840 font_list
= Fcons (build_string (scaled
), font_list
);
7842 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7850 xlfdpat_destroy (pat
);
7855 /* Return a list of names of available fonts matching PATTERN on frame F.
7857 Frame F null means we have not yet created any frame on Mac, and
7858 consult the first display in x_display_list. MAXNAMES sets a limit
7859 on how many fonts to match. */
7862 x_list_fonts (f
, pattern
, size
, maxnames
)
7864 Lisp_Object pattern
;
7867 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7868 struct mac_display_info
*dpyinfo
7869 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7871 xassert (size
<= 0);
7873 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7874 if (NILP (patterns
))
7875 patterns
= Fcons (pattern
, Qnil
);
7877 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7879 pattern
= XCAR (patterns
);
7881 if (!STRINGP (pattern
))
7884 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7885 key
= Fcons (pattern
, make_number (maxnames
));
7887 list
= Fassoc (key
, tem
);
7890 list
= Fcdr_safe (list
);
7891 /* We have a cashed list. Don't have to get the list again. */
7896 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7899 /* MAC_TODO: add code for matching outline fonts here */
7901 /* Now store the result in the cache. */
7902 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7903 Fcons (Fcons (key
, list
),
7904 XCAR (XCDR (dpyinfo
->name_list_element
))));
7907 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7916 /* Check that FONT is valid on frame F. It is if it can be found in F's
7920 x_check_font (f
, font
)
7925 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7927 xassert (font
!= NULL
);
7929 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7930 if (dpyinfo
->font_table
[i
].name
7931 && font
== dpyinfo
->font_table
[i
].font
)
7934 xassert (i
< dpyinfo
->n_fonts
);
7937 #endif /* GLYPH_DEBUG != 0 */
7939 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7940 Note: There are (broken) X fonts out there with invalid XFontStruct
7941 min_bounds contents. For example, handa@etl.go.jp reports that
7942 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7943 have font->min_bounds.width == 0. */
7946 x_font_min_bounds (font
, w
, h
)
7947 MacFontStruct
*font
;
7950 *h
= FONT_HEIGHT (font
);
7951 *w
= font
->min_bounds
.width
;
7955 /* Compute the smallest character width and smallest font height over
7956 all fonts available on frame F. Set the members smallest_char_width
7957 and smallest_font_height in F's x_display_info structure to
7958 the values computed. Value is non-zero if smallest_font_height or
7959 smallest_char_width become smaller than they were before. */
7962 x_compute_min_glyph_bounds (f
)
7966 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7967 MacFontStruct
*font
;
7968 int old_width
= dpyinfo
->smallest_char_width
;
7969 int old_height
= dpyinfo
->smallest_font_height
;
7971 dpyinfo
->smallest_font_height
= 100000;
7972 dpyinfo
->smallest_char_width
= 100000;
7974 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7975 if (dpyinfo
->font_table
[i
].name
)
7977 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7980 font
= (MacFontStruct
*) fontp
->font
;
7981 xassert (font
!= (MacFontStruct
*) ~0);
7982 x_font_min_bounds (font
, &w
, &h
);
7984 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7985 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7988 xassert (dpyinfo
->smallest_char_width
> 0
7989 && dpyinfo
->smallest_font_height
> 0);
7991 return (dpyinfo
->n_fonts
== 1
7992 || dpyinfo
->smallest_char_width
< old_width
7993 || dpyinfo
->smallest_font_height
< old_height
);
7997 /* Determine whether given string is a fully-specified XLFD: all 14
7998 fields are present, none is '*'. */
8001 is_fully_specified_xlfd (p
)
8010 for (i
= 0; i
< 13; i
++)
8012 q
= strchr (p
+ 1, '-');
8015 if (q
- p
== 2 && *(p
+ 1) == '*')
8020 if (strchr (p
+ 1, '-') != NULL
)
8023 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8030 /* mac_load_query_font creates and returns an internal representation
8031 for a font in a MacFontStruct struct. There is really no concept
8032 corresponding to "loading" a font on the Mac. But we check its
8033 existence and find the font number and all other information for it
8034 and store them in the returned MacFontStruct. */
8036 static MacFontStruct
*
8037 mac_load_query_font (f
, fontname
)
8047 static ATSUFontID font_id
;
8048 ATSUStyle mac_style
= NULL
;
8051 #if TARGET_API_MAC_CARBON
8052 TextEncoding encoding
;
8057 MacFontStruct
*font
;
8058 XCharStruct
*space_bounds
= NULL
, *pcm
;
8060 if (is_fully_specified_xlfd (fontname
))
8064 Lisp_Object matched_fonts
;
8066 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8067 if (NILP (matched_fonts
))
8069 name
= SDATA (XCAR (matched_fonts
));
8072 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8076 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8079 static const ATSUAttributeTag tags
[] =
8080 {kATSUFontTag
, kATSUSizeTag
,
8081 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8082 static const ByteCount sizes
[] =
8083 {sizeof (ATSUFontID
), sizeof (Fixed
),
8084 sizeof (Boolean
), sizeof (Boolean
)};
8085 static Fixed size_fixed
;
8086 static Boolean bold_p
, italic_p
;
8087 static const ATSUAttributeValuePtr values
[] =
8088 {&font_id
, &size_fixed
,
8089 &bold_p
, &italic_p
};
8090 static const ATSUFontFeatureType types
[] =
8091 {kAllTypographicFeaturesType
, kDiacriticsType
};
8092 static const ATSUFontFeatureSelector selectors
[] =
8093 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8096 font_id
= atsu_find_font_from_family_name (family
);
8097 if (font_id
== kATSUInvalidFontID
)
8099 size_fixed
= Long2Fix (size
);
8100 bold_p
= (fontface
& bold
) != 0;
8101 italic_p
= (fontface
& italic
) != 0;
8102 err
= ATSUCreateStyle (&mac_style
);
8105 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8109 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8110 tags
, sizes
, values
);
8113 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8116 scriptcode
= kTextEncodingMacUnicode
;
8121 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8125 fontnum
= XINT (XCDR (tmp
));
8126 #if TARGET_API_MAC_CARBON
8127 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8129 scriptcode
= GetTextEncodingBase (encoding
);
8131 scriptcode
= FontToScript (fontnum
);
8135 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8137 font
->mac_fontnum
= fontnum
;
8138 font
->mac_fontsize
= size
;
8139 font
->mac_fontface
= fontface
;
8140 font
->mac_scriptcode
= scriptcode
;
8142 font
->mac_style
= mac_style
;
8143 #if USE_CG_TEXT_DRAWING
8144 font
->cg_font
= NULL
;
8145 font
->cg_glyphs
= NULL
;
8149 /* Apple Japanese (SJIS) font is listed as both
8150 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8151 (Roman script) in init_font_name_table (). The latter should be
8152 treated as a one-byte font. */
8153 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8154 font
->mac_scriptcode
= smRoman
;
8156 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8159 if (font
->mac_style
)
8164 font
->min_byte1
= 0;
8165 font
->max_byte1
= 0xff;
8166 font
->min_char_or_byte2
= 0;
8167 font
->max_char_or_byte2
= 0xff;
8169 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8170 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8171 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8172 pcm_init (font
->bounds
.rows
[0], 0x100);
8174 #if USE_CG_TEXT_DRAWING
8178 ATSFontRef ats_font
;
8180 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8182 /* Use CG text drawing if italic/bold is not synthesized. */
8183 if (err
== noErr
&& style
== fontface
)
8185 ats_font
= FMGetATSFontRefFromFont (font_id
);
8186 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8192 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8193 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8196 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8197 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8198 &font
->ascent
, &font
->descent
,
8200 #if USE_CG_TEXT_DRAWING
8201 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8208 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8210 mac_unload_font (&one_mac_display_info
, font
);
8214 pcm
= font
->bounds
.rows
[0];
8215 for (c
= 0x21; c
<= 0xff; c
++)
8218 /* Soft hyphen is not supported in ATSUI. */
8222 #if USE_CG_TEXT_DRAWING
8223 if (font
->cg_glyphs
)
8233 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8234 pcm
? pcm
+ c
: NULL
,
8235 #if USE_CG_TEXT_DRAWING
8236 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8243 #if USE_CG_TEXT_DRAWING
8244 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8246 /* Don't use CG text drawing if font substitution occurs in
8247 ASCII or Latin-1 characters. */
8248 CGFontRelease (font
->cg_font
);
8249 font
->cg_font
= NULL
;
8250 xfree (font
->cg_glyphs
);
8251 font
->cg_glyphs
= NULL
;
8262 FontInfo the_fontinfo
;
8263 int is_two_byte_font
;
8266 mac_prepare_for_quickdraw (f
);
8268 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8272 TextFace (fontface
);
8274 GetFontInfo (&the_fontinfo
);
8276 font
->ascent
= the_fontinfo
.ascent
;
8277 font
->descent
= the_fontinfo
.descent
;
8279 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8280 || font
->mac_scriptcode
== smTradChinese
8281 || font
->mac_scriptcode
== smSimpChinese
8282 || font
->mac_scriptcode
== smKorean
);
8284 if (is_two_byte_font
)
8288 font
->min_byte1
= 0xa1;
8289 font
->max_byte1
= 0xfe;
8290 font
->min_char_or_byte2
= 0xa1;
8291 font
->max_char_or_byte2
= 0xfe;
8293 /* Use the width of an "ideographic space" of that font
8294 because the_fontinfo.widMax returns the wrong width for
8296 switch (font
->mac_scriptcode
)
8299 font
->min_byte1
= 0x81;
8300 font
->max_byte1
= 0xfc;
8301 font
->min_char_or_byte2
= 0x40;
8302 font
->max_char_or_byte2
= 0xfc;
8303 char_width
= StringWidth("\p\x81\x40");
8306 font
->min_char_or_byte2
= 0x40;
8307 char_width
= StringWidth("\p\xa1\x40");
8310 char_width
= StringWidth("\p\xa1\xa1");
8313 char_width
= StringWidth("\p\xa1\xa1");
8317 font
->bounds
.per_char
= NULL
;
8319 if (fontface
& italic
)
8320 font
->max_bounds
.rbearing
= char_width
+ 1;
8322 font
->max_bounds
.rbearing
= char_width
;
8323 font
->max_bounds
.lbearing
= 0;
8324 font
->max_bounds
.width
= char_width
;
8325 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8326 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8328 font
->min_bounds
= font
->max_bounds
;
8334 font
->min_byte1
= font
->max_byte1
= 0;
8335 font
->min_char_or_byte2
= 0x20;
8336 font
->max_char_or_byte2
= 0xff;
8338 font
->bounds
.per_char
=
8339 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8340 bzero (font
->bounds
.per_char
,
8341 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8343 space_bounds
= font
->bounds
.per_char
;
8344 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
8345 &font
->descent
, space_bounds
, NULL
);
8346 if (err
!= noErr
|| space_bounds
->width
<= 0)
8348 mac_unload_font (&one_mac_display_info
, font
);
8352 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8353 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8361 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8362 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8365 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8367 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8369 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8371 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8373 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
8376 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8378 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8380 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8382 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8384 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
8389 font
->mac_style
== NULL
&&
8391 font
->max_bounds
.width
== font
->min_bounds
.width
8392 && font
->min_bounds
.lbearing
>= 0
8393 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8395 /* Fixed width and no overhangs. */
8396 xfree (font
->bounds
.per_char
);
8397 font
->bounds
.per_char
= NULL
;
8401 #if !defined (MAC_OS8) || USE_ATSUI
8402 /* AppKit and WebKit do some adjustment to the heights of Courier,
8403 Helvetica, and Times. This only works on the environments where
8404 srcCopy text transfer mode is never used. */
8406 #ifdef MAC_OS8 /* implies USE_ATSUI */
8409 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8410 || strcmp (family
, "times") == 0))
8411 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8419 mac_unload_font (dpyinfo
, font
)
8420 struct mac_display_info
*dpyinfo
;
8423 xfree (font
->full_name
);
8425 if (font
->mac_style
)
8429 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8430 if (font
->bounds
.rows
[i
])
8431 xfree (font
->bounds
.rows
[i
]);
8432 xfree (font
->bounds
.rows
);
8433 ATSUDisposeStyle (font
->mac_style
);
8437 if (font
->bounds
.per_char
)
8438 xfree (font
->bounds
.per_char
);
8439 #if USE_CG_TEXT_DRAWING
8441 CGFontRelease (font
->cg_font
);
8442 if (font
->cg_glyphs
)
8443 xfree (font
->cg_glyphs
);
8449 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8450 pointer to the structure font_info while allocating it dynamically.
8451 If SIZE is 0, load any size of font.
8452 If loading is failed, return NULL. */
8455 x_load_font (f
, fontname
, size
)
8457 register char *fontname
;
8460 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8461 Lisp_Object font_names
;
8463 /* Get a list of all the fonts that match this name. Once we
8464 have a list of matching fonts, we compare them against the fonts
8465 we already have by comparing names. */
8466 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8468 if (!NILP (font_names
))
8473 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8474 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8475 if (dpyinfo
->font_table
[i
].name
8476 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8477 SDATA (XCAR (tail
)))
8478 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8479 SDATA (XCAR (tail
)))))
8480 return (dpyinfo
->font_table
+ i
);
8485 /* Load the font and add it to the table. */
8487 struct MacFontStruct
*font
;
8488 struct font_info
*fontp
;
8491 fontname
= (char *) SDATA (XCAR (font_names
));
8494 font
= mac_load_query_font (f
, fontname
);
8499 /* Find a free slot in the font table. */
8500 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8501 if (dpyinfo
->font_table
[i
].name
== NULL
)
8504 /* If no free slot found, maybe enlarge the font table. */
8505 if (i
== dpyinfo
->n_fonts
8506 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8509 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8510 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8512 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8515 fontp
= dpyinfo
->font_table
+ i
;
8516 if (i
== dpyinfo
->n_fonts
)
8519 /* Now fill in the slots of *FONTP. */
8521 bzero (fontp
, sizeof (*fontp
));
8523 fontp
->font_idx
= i
;
8524 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8525 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8527 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8529 /* Fixed width font. */
8530 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8537 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8538 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8540 fontp
->space_width
= pcm
->width
;
8542 fontp
->space_width
= FONT_WIDTH (font
);
8546 int width
= pcm
->width
;
8547 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8548 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8549 width
+= pcm
->width
;
8550 fontp
->average_width
= width
/ 95;
8553 fontp
->average_width
= FONT_WIDTH (font
);
8556 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8557 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8559 fontp
->size
= font
->max_bounds
.width
;
8560 fontp
->height
= FONT_HEIGHT (font
);
8562 /* For some font, ascent and descent in max_bounds field is
8563 larger than the above value. */
8564 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8565 if (max_height
> fontp
->height
)
8566 fontp
->height
= max_height
;
8569 /* The slot `encoding' specifies how to map a character
8570 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8571 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8572 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8573 2:0xA020..0xFF7F). For the moment, we don't know which charset
8574 uses this font. So, we set information in fontp->encoding[1]
8575 which is never used by any charset. If mapping can't be
8576 decided, set FONT_ENCODING_NOT_DECIDED. */
8577 if (font
->mac_scriptcode
== smJapanese
)
8578 fontp
->encoding
[1] = 4;
8582 = (font
->max_byte1
== 0
8584 ? (font
->min_char_or_byte2
< 0x80
8585 ? (font
->max_char_or_byte2
< 0x80
8586 ? 0 /* 0x20..0x7F */
8587 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8588 : 1) /* 0xA0..0xFF */
8590 : (font
->min_byte1
< 0x80
8591 ? (font
->max_byte1
< 0x80
8592 ? (font
->min_char_or_byte2
< 0x80
8593 ? (font
->max_char_or_byte2
< 0x80
8594 ? 0 /* 0x2020..0x7F7F */
8595 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8596 : 3) /* 0x20A0..0x7FFF */
8597 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8598 : (font
->min_char_or_byte2
< 0x80
8599 ? (font
->max_char_or_byte2
< 0x80
8600 ? 2 /* 0xA020..0xFF7F */
8601 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8602 : 1))); /* 0xA0A0..0xFFFF */
8605 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8606 fontp
->baseline_offset
8607 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8608 ? (long) value
: 0);
8609 fontp
->relative_compose
8610 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8611 ? (long) value
: 0);
8612 fontp
->default_ascent
8613 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8614 ? (long) value
: 0);
8616 fontp
->baseline_offset
= 0;
8617 fontp
->relative_compose
= 0;
8618 fontp
->default_ascent
= 0;
8621 /* Set global flag fonts_changed_p to non-zero if the font loaded
8622 has a character with a smaller width than any other character
8623 before, or if the font loaded has a smaller height than any
8624 other font loaded before. If this happens, it will make a
8625 glyph matrix reallocation necessary. */
8626 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8633 /* Return a pointer to struct font_info of a font named FONTNAME for
8634 frame F. If no such font is loaded, return NULL. */
8637 x_query_font (f
, fontname
)
8639 register char *fontname
;
8641 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8644 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8645 if (dpyinfo
->font_table
[i
].name
8646 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8647 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8648 return (dpyinfo
->font_table
+ i
);
8653 /* Find a CCL program for a font specified by FONTP, and set the member
8654 `encoder' of the structure. */
8657 x_find_ccl_program (fontp
)
8658 struct font_info
*fontp
;
8660 Lisp_Object list
, elt
;
8662 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8666 && STRINGP (XCAR (elt
))
8667 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8673 struct ccl_program
*ccl
8674 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8676 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8679 fontp
->font_encoder
= ccl
;
8683 #if USE_MAC_FONT_PANEL
8684 /* Whether Font Panel has been shown before. The first call to font
8685 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8686 slow. This variable is used for deferring such a call as much as
8688 static int font_panel_shown_p
= 0;
8691 mac_font_panel_visible_p ()
8693 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8697 mac_show_hide_font_panel ()
8699 font_panel_shown_p
= 1;
8701 return FPShowHideFontPanel ();
8705 mac_set_font_info_for_selection (f
, face_id
, c
)
8710 EventTargetRef target
= NULL
;
8711 XFontStruct
*font
= NULL
;
8713 if (!mac_font_panel_visible_p ())
8718 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8720 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8724 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8725 face
= FACE_FROM_ID (f
, face_id
);
8731 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8734 if (font
->mac_fontnum
!= -1)
8736 FontSelectionQDStyle qd_style
;
8738 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8739 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8740 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8741 qd_style
.size
= font
->mac_fontsize
;
8742 qd_style
.hasColor
= false;
8744 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8745 1, &qd_style
, target
);
8748 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8749 1, &font
->mac_style
, target
);
8757 /* The Mac Event loop code */
8759 #if !TARGET_API_MAC_CARBON
8761 #include <Quickdraw.h>
8762 #include <Balloons.h>
8763 #include <Devices.h>
8765 #include <Gestalt.h>
8767 #include <Processes.h>
8769 #include <ToolUtils.h>
8770 #include <TextUtils.h>
8771 #include <Dialogs.h>
8774 #include <Resources.h>
8779 #endif /* ! TARGET_API_MAC_CARBON */
8784 #define WINDOW_RESOURCE 128
8785 #define TERM_WINDOW_RESOURCE 129
8787 #define DEFAULT_NUM_COLS 80
8789 #define MIN_DOC_SIZE 64
8790 #define MAX_DOC_SIZE 32767
8792 #define EXTRA_STACK_ALLOC (256 * 1024)
8794 #define ARGV_STRING_LIST_ID 129
8795 #define ABOUT_ALERT_ID 128
8796 #define RAM_TOO_LARGE_ALERT_ID 129
8798 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8799 Lisp_Object Qreverse
;
8802 /* Modifier associated with the control key, or nil to ignore. */
8803 Lisp_Object Vmac_control_modifier
;
8805 /* Modifier associated with the option key, or nil to ignore. */
8806 Lisp_Object Vmac_option_modifier
;
8808 /* Modifier associated with the command key, or nil to ignore. */
8809 Lisp_Object Vmac_command_modifier
;
8811 /* Modifier associated with the function key, or nil to ignore. */
8812 Lisp_Object Vmac_function_modifier
;
8814 /* True if the option and command modifiers should be used to emulate
8815 a three button mouse */
8816 Lisp_Object Vmac_emulate_three_button_mouse
;
8818 #if USE_CARBON_EVENTS
8819 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8820 mouse-2, instead of mouse-3. */
8821 int mac_wheel_button_is_mouse_2
;
8823 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8824 for processing before Emacs sees it. */
8825 int mac_pass_command_to_system
;
8827 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8828 for processing before Emacs sees it. */
8829 int mac_pass_control_to_system
;
8832 /* Points to the variable `inev' in the function XTread_socket. It is
8833 used for passing an input event to the function back from
8834 Carbon/Apple event handlers. */
8835 static struct input_event
*read_socket_inev
= NULL
;
8837 Point saved_menu_event_location
;
8840 #if USE_CARBON_EVENTS
8841 static Lisp_Object Qhi_command
;
8843 extern Lisp_Object Qwindow
;
8844 static Lisp_Object Qtoolbar_switch_mode
;
8846 #if USE_MAC_FONT_PANEL
8847 extern Lisp_Object Qfont
;
8848 static Lisp_Object Qpanel_closed
, Qselection
;
8851 static TSMDocumentID tsm_document_id
;
8852 static Lisp_Object Qtext_input
;
8853 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8854 static Lisp_Object Vmac_ts_active_input_overlay
;
8855 extern Lisp_Object Qbefore_string
;
8856 static Lisp_Object Vmac_ts_script_language_on_focus
;
8857 static Lisp_Object saved_ts_script_language_on_focus
;
8858 static ScriptLanguageRecord saved_ts_language
;
8859 static Component saved_ts_component
;
8862 extern int mac_ready_for_apple_events
;
8863 extern Lisp_Object Qundefined
;
8864 extern void init_apple_event_handler
P_ ((void));
8865 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8866 Lisp_Object
*, Lisp_Object
*,
8868 extern OSErr init_coercion_handler
P_ ((void));
8871 extern OSErr install_drag_handler
P_ ((WindowRef
));
8872 extern void remove_drag_handler
P_ ((WindowRef
));
8874 /* Showing help echo string during menu tracking */
8875 extern OSStatus install_menu_target_item_handler
P_ ((WindowPtr
));
8877 #if USE_CARBON_EVENTS
8879 extern void init_service_handler ();
8880 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8883 /* Window Event Handler */
8884 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8887 OSStatus
install_window_handler (WindowPtr
);
8889 extern void init_emacs_passwd_dir ();
8890 extern int emacs_main (int, char **, char **);
8892 extern void initialize_applescript();
8893 extern void terminate_applescript();
8895 /* Table for translating Mac keycode to X keysym values. Contributed
8897 Mapping for special keys is now identical to that in Apple X11
8898 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8899 on the right of the Cmd key on laptops, and fn + `enter' (->
8901 static const unsigned char keycode_to_xkeysym_table
[] = {
8902 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8903 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8904 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8906 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8907 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8908 /*0x38*/ 0, 0, 0, 0,
8909 /*0x3C*/ 0, 0, 0, 0,
8911 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8912 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8913 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8914 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8916 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8917 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8918 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8919 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8921 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8922 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8923 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8924 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8926 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8927 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8928 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8929 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8933 /* Table for translating Mac keycode with the laptop `fn' key to that
8934 without it. Destination symbols in comments are keys on US
8935 keyboard, and they may not be the same on other types of keyboards.
8936 If the destination is identical to the source (f1 ... f12), it
8937 doesn't map `fn' key to a modifier. */
8938 static const unsigned char fn_keycode_to_keycode_table
[] = {
8939 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8940 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8941 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8943 /*0x30*/ 0, 0, 0, 0,
8944 /*0x34*/ 0, 0, 0, 0,
8945 /*0x38*/ 0, 0, 0, 0,
8946 /*0x3C*/ 0, 0, 0, 0,
8948 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8949 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8950 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8951 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8953 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8954 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8955 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8956 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8958 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8959 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8960 /*0x68*/ 0, 0, 0, 0,
8961 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8963 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
8964 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8965 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
8968 #endif /* MAC_OSX */
8971 #if USE_CARBON_EVENTS
8972 mac_to_emacs_modifiers (UInt32 mods
)
8974 mac_to_emacs_modifiers (EventModifiers mods
)
8977 unsigned int result
= 0;
8978 if (mods
& shiftKey
)
8979 result
|= shift_modifier
;
8981 /* Deactivated to simplify configuration:
8982 if Vmac_option_modifier is non-NIL, we fully process the Option
8983 key. Otherwise, we only process it if an additional Ctrl or Command
8984 is pressed. That way the system may convert the character to a
8986 if ((mods & optionKey) &&
8987 (( !NILP(Vmac_option_modifier) ||
8988 ((mods & cmdKey) || (mods & controlKey))))) */
8990 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8991 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8993 result
|= XUINT(val
);
8995 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8996 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8998 result
|= XUINT(val
);
9000 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9001 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9003 result
|= XUINT(val
);
9007 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9008 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9010 result
|= XUINT(val
);
9018 mac_get_emulated_btn ( UInt32 modifiers
)
9021 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9022 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9023 if (modifiers
& cmdKey
)
9024 result
= cmdIs3
? 2 : 1;
9025 else if (modifiers
& optionKey
)
9026 result
= cmdIs3
? 1 : 2;
9031 #if USE_CARBON_EVENTS
9032 /* Obtains the event modifiers from the event ref and then calls
9033 mac_to_emacs_modifiers. */
9035 mac_event_to_emacs_modifiers (EventRef eventRef
)
9038 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9039 sizeof (UInt32
), NULL
, &mods
);
9040 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9041 GetEventClass(eventRef
) == kEventClassMouse
)
9043 mods
&= ~(optionKey
| cmdKey
);
9045 return mac_to_emacs_modifiers (mods
);
9048 /* Given an event ref, return the code to use for the mouse button
9049 code in the emacs input_event. */
9051 mac_get_mouse_btn (EventRef ref
)
9053 EventMouseButton result
= kEventMouseButtonPrimary
;
9054 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9055 sizeof (EventMouseButton
), NULL
, &result
);
9058 case kEventMouseButtonPrimary
:
9059 if (NILP (Vmac_emulate_three_button_mouse
))
9063 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9064 sizeof (UInt32
), NULL
, &mods
);
9065 return mac_get_emulated_btn(mods
);
9067 case kEventMouseButtonSecondary
:
9068 return mac_wheel_button_is_mouse_2
? 2 : 1;
9069 case kEventMouseButtonTertiary
:
9070 case 4: /* 4 is the number for the mouse wheel button */
9071 return mac_wheel_button_is_mouse_2
? 1 : 2;
9077 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9078 events. However the click of the mouse wheel is not converted to a
9079 mouseDown or mouseUp event. Likewise for dead key down events.
9080 This calls ConvertEventRef, but then checks to see if it is a mouse
9081 up/down, or a dead key down carbon event that has not been
9082 converted, and if so, converts it by hand (to be picked up in the
9083 XTread_socket loop). */
9084 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9087 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9092 switch (GetEventClass (eventRef
))
9094 case kEventClassMouse
:
9095 switch (GetEventKind (eventRef
))
9097 case kEventMouseDown
:
9098 eventRec
->what
= mouseDown
;
9103 eventRec
->what
= mouseUp
;
9112 case kEventClassKeyboard
:
9113 switch (GetEventKind (eventRef
))
9115 case kEventRawKeyDown
:
9117 unsigned char char_codes
;
9120 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9121 typeChar
, NULL
, sizeof (char),
9124 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9125 typeUInt32
, NULL
, sizeof (UInt32
),
9129 eventRec
->what
= keyDown
;
9130 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9147 /* Need where and when. */
9150 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9151 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9152 /* Use two step process because new event modifiers are 32-bit
9153 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9154 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9155 NULL
, sizeof (UInt32
), NULL
, &mods
);
9156 eventRec
->modifiers
= mods
;
9158 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9170 Handle menubar_handle
;
9171 MenuHandle menu_handle
;
9173 menubar_handle
= GetNewMBar (128);
9174 if(menubar_handle
== NULL
)
9176 SetMenuBar (menubar_handle
);
9179 #if !TARGET_API_MAC_CARBON
9180 menu_handle
= GetMenuHandle (M_APPLE
);
9181 if(menu_handle
!= NULL
)
9182 AppendResMenu (menu_handle
,'DRVR');
9190 do_init_managers (void)
9192 #if !TARGET_API_MAC_CARBON
9193 InitGraf (&qd
.thePort
);
9195 FlushEvents (everyEvent
, 0);
9200 #endif /* !TARGET_API_MAC_CARBON */
9203 #if !TARGET_API_MAC_CARBON
9204 /* set up some extra stack space for use by emacs */
9205 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9207 /* MaxApplZone must be called for AppleScript to execute more
9208 complicated scripts */
9211 #endif /* !TARGET_API_MAC_CARBON */
9215 do_check_ram_size (void)
9217 SInt32 physical_ram_size
, logical_ram_size
;
9219 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
9220 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
9221 || physical_ram_size
> (1 << VALBITS
)
9222 || logical_ram_size
> (1 << VALBITS
))
9224 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
9228 #endif /* MAC_OS8 */
9231 do_window_update (WindowPtr win
)
9233 struct frame
*f
= mac_window_to_frame (win
);
9237 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
9239 if (win
!= tip_window
)
9241 if (f
->async_visible
== 0)
9243 /* Update events may occur when a frame gets iconified. */
9245 f
->async_visible
= 1;
9246 f
->async_iconified
= 0;
9247 SET_FRAME_GARBAGED (f
);
9253 #if TARGET_API_MAC_CARBON
9254 RgnHandle region
= NewRgn ();
9256 GetPortVisibleRegion (GetWindowPort (win
), region
);
9257 GetRegionBounds (region
, &r
);
9258 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9259 UpdateControls (win
, region
);
9260 DisposeRgn (region
);
9262 r
= (*win
->visRgn
)->rgnBBox
;
9263 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9264 UpdateControls (win
, win
->visRgn
);
9273 is_emacs_window (WindowPtr win
)
9275 Lisp_Object tail
, frame
;
9280 FOR_EACH_FRAME (tail
, frame
)
9281 if (FRAME_MAC_P (XFRAME (frame
)))
9282 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9293 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9295 err
= ActivateTSMDocument (tsm_document_id
);
9299 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9300 && EQ (saved_ts_script_language_on_focus
, Qt
))
9301 slptr
= &saved_ts_language
;
9302 else if (CONSP (Vmac_ts_script_language_on_focus
)
9303 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9304 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9305 && CONSP (saved_ts_script_language_on_focus
)
9306 && EQ (XCAR (saved_ts_script_language_on_focus
),
9307 XCAR (Vmac_ts_script_language_on_focus
))
9308 && EQ (XCDR (saved_ts_script_language_on_focus
),
9309 XCDR (Vmac_ts_script_language_on_focus
)))
9311 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9312 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9319 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9320 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
9321 kKeyboardInputMethodClass
);
9323 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
9326 err
= SetTextServiceLanguage (slptr
);
9328 /* Seems to be needed on Mac OS X 10.2. */
9330 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
9340 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9342 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
9344 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
9346 err
= GetTextServiceLanguage (&saved_ts_language
);
9348 slptr
= &saved_ts_language
;
9350 else if (CONSP (Vmac_ts_script_language_on_focus
)
9351 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9352 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
9354 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9355 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9361 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9362 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
9363 kKeyboardInputMethodClass
);
9365 GetDefaultInputMethod (&saved_ts_component
, slptr
);
9369 err
= DeactivateTSMDocument (tsm_document_id
);
9375 #if !TARGET_API_MAC_CARBON
9377 do_apple_menu (SInt16 menu_item
)
9380 SInt16 da_driver_refnum
;
9382 if (menu_item
== I_ABOUT
)
9383 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9386 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9387 da_driver_refnum
= OpenDeskAcc (item_name
);
9390 #endif /* !TARGET_API_MAC_CARBON */
9392 /* Handle drags in size box. Based on code contributed by Ben
9393 Mesander and IM - Window Manager A. */
9396 do_grow_window (w
, e
)
9398 const EventRecord
*e
;
9401 int rows
, columns
, width
, height
;
9402 struct frame
*f
= mac_window_to_frame (w
);
9403 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
9404 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
9405 #if TARGET_API_MAC_CARBON
9411 if (size_hints
->flags
& PMinSize
)
9413 min_width
= size_hints
->min_width
;
9414 min_height
= size_hints
->min_height
;
9416 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9418 #if TARGET_API_MAC_CARBON
9419 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
9421 height
= new_rect
.bottom
- new_rect
.top
;
9422 width
= new_rect
.right
- new_rect
.left
;
9424 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9425 /* see if it really changed size */
9428 height
= HiWord (grow_size
);
9429 width
= LoWord (grow_size
);
9432 if (width
!= FRAME_PIXEL_WIDTH (f
)
9433 || height
!= FRAME_PIXEL_HEIGHT (f
))
9435 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9436 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9438 x_set_window_size (f
, 0, columns
, rows
);
9443 #if TARGET_API_MAC_CARBON
9445 mac_get_ideal_size (f
)
9448 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9449 WindowPtr w
= FRAME_MAC_WINDOW (f
);
9452 int height
, width
, columns
, rows
;
9454 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9455 ideal_size
.v
= dpyinfo
->height
;
9456 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
9457 /* Adjust the standard size according to character boundaries. */
9458 width
= standard_rect
.right
- standard_rect
.left
;
9459 height
= standard_rect
.bottom
- standard_rect
.top
;
9460 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9461 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9462 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9463 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9469 /* Handle clicks in zoom box. Calculation of "standard state" based
9470 on code in IM - Window Manager A and code contributed by Ben
9471 Mesander. The standard state of an Emacs window is 80-characters
9472 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9475 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9477 Rect zoom_rect
, port_rect
;
9479 struct frame
*f
= mac_window_to_frame (w
);
9480 #if TARGET_API_MAC_CARBON
9481 Point ideal_size
= mac_get_ideal_size (f
);
9483 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9484 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
9485 && port_rect
.left
== zoom_rect
.left
9486 && port_rect
.top
== zoom_rect
.top
)
9487 zoom_in_or_out
= inZoomIn
;
9489 zoom_in_or_out
= inZoomOut
;
9492 mac_clear_window (f
);
9494 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
9495 #else /* not TARGET_API_MAC_CARBON */
9498 int w_title_height
, rows
;
9499 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9501 GetPort (&save_port
);
9503 SetPortWindowPort (w
);
9505 /* Clear window to avoid flicker. */
9506 EraseRect (&(w
->portRect
));
9507 if (zoom_in_or_out
== inZoomOut
)
9509 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9510 LocalToGlobal (&top_left
);
9512 /* calculate height of window's title bar */
9513 w_title_height
= top_left
.v
- 1
9514 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9516 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9517 zoom_rect
= qd
.screenBits
.bounds
;
9518 zoom_rect
.top
+= w_title_height
;
9519 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9521 zoom_rect
.right
= zoom_rect
.left
9522 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9524 /* Adjust the standard size according to character boundaries. */
9525 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9527 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9529 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9533 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9535 SetPort (save_port
);
9536 #endif /* not TARGET_API_MAC_CARBON */
9538 #if !USE_CARBON_EVENTS
9539 /* retrieve window size and update application values */
9540 #if TARGET_API_MAC_CARBON
9541 GetWindowPortBounds (w
, &port_rect
);
9543 port_rect
= w
->portRect
;
9545 height
= port_rect
.bottom
- port_rect
.top
;
9546 width
= port_rect
.right
- port_rect
.left
;
9548 mac_handle_size_change (f
, width
, height
);
9549 mac_handle_origin_change (f
);
9554 mac_store_apple_event (class, id
, desc
)
9555 Lisp_Object
class, id
;
9558 struct input_event buf
;
9562 buf
.kind
= MAC_APPLE_EVENT
;
9565 XSETFRAME (buf
.frame_or_window
,
9566 mac_focus_frame (&one_mac_display_info
));
9567 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9568 is safe to use them during read_socket_hook. */
9569 buf
.arg
= mac_aedesc_to_lisp (desc
);
9570 kbd_buffer_store_event (&buf
);
9573 #if TARGET_API_MAC_CARBON
9575 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9576 event
, num_params
, names
, types
)
9579 Lisp_Object class_key
, id_key
;
9582 const EventParamName
*names
;
9583 const EventParamType
*types
;
9585 OSStatus err
= eventNotHandledErr
;
9586 Lisp_Object binding
;
9588 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9589 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9591 if (INTEGERP (binding
))
9592 err
= XINT (binding
);
9595 AppleEvent apple_event
;
9596 err
= create_apple_event_from_event_ref (event
, num_params
,
9601 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9602 AEDisposeDesc (&apple_event
);
9603 mac_wakeup_from_rne ();
9612 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9618 struct input_event buf
;
9622 buf
.kind
= DRAG_N_DROP_EVENT
;
9623 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9624 buf
.timestamp
= TickCount () * (1000 / 60);
9625 XSETINT (buf
.x
, mouse_pos
.h
);
9626 XSETINT (buf
.y
, mouse_pos
.v
);
9627 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9628 buf
.arg
= mac_aedesc_to_lisp (desc
);
9629 kbd_buffer_store_event (&buf
);
9633 #if USE_CARBON_EVENTS
9634 static pascal OSStatus
9635 mac_handle_command_event (next_handler
, event
, data
)
9636 EventHandlerCallRef next_handler
;
9640 OSStatus result
, err
;
9642 static const EventParamName names
[] =
9643 {kEventParamDirectObject
, kEventParamKeyModifiers
};
9644 static const EventParamType types
[] =
9645 {typeHICommand
, typeUInt32
};
9646 int num_params
= sizeof (names
) / sizeof (names
[0]);
9648 result
= CallNextEventHandler (next_handler
, event
);
9649 if (result
!= eventNotHandledErr
)
9652 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9653 NULL
, sizeof (HICommand
), NULL
, &command
);
9655 if (err
!= noErr
|| command
.commandID
== 0)
9656 return eventNotHandledErr
;
9658 /* A HI command event is mapped to an Apple event whose event class
9659 symbol is `hi-command' and event ID is its command ID. */
9660 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9662 event
, num_params
, names
, types
);
9663 return err
== noErr
? noErr
: eventNotHandledErr
;
9667 init_command_handler ()
9669 static const EventTypeSpec specs
[] =
9670 {{kEventClassCommand
, kEventCommandProcess
}};
9671 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9673 if (handle_command_eventUPP
== NULL
)
9674 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9675 return InstallApplicationEventHandler (handle_command_eventUPP
,
9676 GetEventTypeCount (specs
), specs
,
9680 static pascal OSStatus
9681 mac_handle_window_event (next_handler
, event
, data
)
9682 EventHandlerCallRef next_handler
;
9687 OSStatus result
, err
;
9690 XSizeHints
*size_hints
;
9692 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9693 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9695 return eventNotHandledErr
;
9697 f
= mac_window_to_frame (wp
);
9698 switch (GetEventKind (event
))
9700 case kEventWindowUpdate
:
9701 result
= CallNextEventHandler (next_handler
, event
);
9702 if (result
!= eventNotHandledErr
)
9705 do_window_update (wp
);
9708 case kEventWindowGetIdealSize
:
9709 result
= CallNextEventHandler (next_handler
, event
);
9710 if (result
!= eventNotHandledErr
)
9714 Point ideal_size
= mac_get_ideal_size (f
);
9716 err
= SetEventParameter (event
, kEventParamDimensions
,
9717 typeQDPoint
, sizeof (Point
), &ideal_size
);
9723 case kEventWindowBoundsChanging
:
9724 result
= CallNextEventHandler (next_handler
, event
);
9725 if (result
!= eventNotHandledErr
)
9728 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9729 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9733 size_hints
= FRAME_SIZE_HINTS (f
);
9734 if ((attributes
& kWindowBoundsChangeUserResize
)
9735 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9736 == (PResizeInc
| PBaseSize
| PMinSize
)))
9741 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9742 typeQDRectangle
, NULL
, sizeof (Rect
),
9747 width
= bounds
.right
- bounds
.left
;
9748 height
= bounds
.bottom
- bounds
.top
;
9750 if (width
< size_hints
->min_width
)
9751 width
= size_hints
->min_width
;
9753 width
= size_hints
->base_width
9754 + (int) ((width
- size_hints
->base_width
)
9755 / (float) size_hints
->width_inc
+ .5)
9756 * size_hints
->width_inc
;
9758 if (height
< size_hints
->min_height
)
9759 height
= size_hints
->min_height
;
9761 height
= size_hints
->base_height
9762 + (int) ((height
- size_hints
->base_height
)
9763 / (float) size_hints
->height_inc
+ .5)
9764 * size_hints
->height_inc
;
9766 bounds
.right
= bounds
.left
+ width
;
9767 bounds
.bottom
= bounds
.top
+ height
;
9768 SetEventParameter (event
, kEventParamCurrentBounds
,
9769 typeQDRectangle
, sizeof (Rect
), &bounds
);
9774 case kEventWindowBoundsChanged
:
9775 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9776 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9780 if (attributes
& kWindowBoundsChangeSizeChanged
)
9784 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9785 typeQDRectangle
, NULL
, sizeof (Rect
),
9791 width
= bounds
.right
- bounds
.left
;
9792 height
= bounds
.bottom
- bounds
.top
;
9793 mac_handle_size_change (f
, width
, height
);
9797 if (attributes
& kWindowBoundsChangeOriginChanged
)
9798 mac_handle_origin_change (f
);
9802 case kEventWindowShown
:
9803 case kEventWindowHidden
:
9804 case kEventWindowExpanded
:
9805 case kEventWindowCollapsed
:
9806 result
= CallNextEventHandler (next_handler
, event
);
9808 mac_handle_visibility_change (f
);
9813 case kEventWindowClose
:
9814 result
= CallNextEventHandler (next_handler
, event
);
9816 struct input_event buf
;
9819 buf
.kind
= DELETE_WINDOW_EVENT
;
9820 XSETFRAME (buf
.frame_or_window
, f
);
9822 kbd_buffer_store_event (&buf
);
9827 case kEventWindowToolbarSwitchMode
:
9828 result
= CallNextEventHandler (next_handler
, event
);
9830 static const EventParamName names
[] = {kEventParamDirectObject
,
9831 kEventParamWindowMouseLocation
,
9832 kEventParamKeyModifiers
,
9833 kEventParamMouseButton
,
9834 kEventParamClickCount
,
9835 kEventParamMouseChord
};
9836 static const EventParamType types
[] = {typeWindowRef
,
9842 int num_params
= sizeof (names
) / sizeof (names
[0]);
9844 err
= mac_store_event_ref_as_apple_event (0, 0,
9846 Qtoolbar_switch_mode
,
9850 return err
== noErr
? noErr
: result
;
9854 case kEventWindowFocusAcquired
:
9855 result
= CallNextEventHandler (next_handler
, event
);
9856 err
= mac_tsm_resume ();
9857 return err
== noErr
? noErr
: result
;
9859 case kEventWindowFocusRelinquish
:
9860 result
= CallNextEventHandler (next_handler
, event
);
9861 err
= mac_tsm_suspend ();
9862 return err
== noErr
? noErr
: result
;
9866 return eventNotHandledErr
;
9869 static pascal OSStatus
9870 mac_handle_mouse_event (next_handler
, event
, data
)
9871 EventHandlerCallRef next_handler
;
9875 OSStatus result
, err
;
9877 switch (GetEventKind (event
))
9879 case kEventMouseWheelMoved
:
9883 EventMouseWheelAxis axis
;
9887 result
= CallNextEventHandler (next_handler
, event
);
9888 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9891 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9892 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9896 f
= mac_window_to_frame (wp
);
9897 if (f
!= mac_focus_frame (&one_mac_display_info
))
9900 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
9901 typeMouseWheelAxis
, NULL
,
9902 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9903 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
9906 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
9907 typeSInt32
, NULL
, sizeof (SInt32
),
9911 err
= GetEventParameter (event
, kEventParamMouseLocation
,
9912 typeQDPoint
, NULL
, sizeof (Point
),
9916 read_socket_inev
->kind
= WHEEL_EVENT
;
9917 read_socket_inev
->code
= 0;
9918 read_socket_inev
->modifiers
=
9919 (mac_event_to_emacs_modifiers (event
)
9920 | ((delta
< 0) ? down_modifier
: up_modifier
));
9921 SetPortWindowPort (wp
);
9922 GlobalToLocal (&point
);
9923 XSETINT (read_socket_inev
->x
, point
.h
);
9924 XSETINT (read_socket_inev
->y
, point
.v
);
9925 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9935 return eventNotHandledErr
;
9938 #if USE_MAC_FONT_PANEL
9939 static pascal OSStatus
9940 mac_handle_font_event (next_handler
, event
, data
)
9941 EventHandlerCallRef next_handler
;
9945 OSStatus result
, err
;
9948 const EventParamName
*names
;
9949 const EventParamType
*types
;
9950 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9951 kEventParamATSUFontSize
,
9952 kEventParamFMFontFamily
,
9953 kEventParamFMFontSize
,
9954 kEventParamFontColor
};
9955 static const EventParamType types_sel
[] = {typeATSUFontID
,
9961 result
= CallNextEventHandler (next_handler
, event
);
9962 if (result
!= eventNotHandledErr
)
9965 switch (GetEventKind (event
))
9967 case kEventFontPanelClosed
:
9968 id_key
= Qpanel_closed
;
9974 case kEventFontSelection
:
9975 id_key
= Qselection
;
9976 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9982 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9986 return err
== noErr
? noErr
: eventNotHandledErr
;
9991 static pascal OSStatus
9992 mac_handle_text_input_event (next_handler
, event
, data
)
9993 EventHandlerCallRef next_handler
;
9997 OSStatus result
, err
= noErr
;
9998 Lisp_Object id_key
= Qnil
;
10000 const EventParamName
*names
;
10001 const EventParamType
*types
;
10002 static UInt32 seqno_uaia
= 0;
10003 static const EventParamName names_uaia
[] =
10004 {kEventParamTextInputSendComponentInstance
,
10005 kEventParamTextInputSendRefCon
,
10006 kEventParamTextInputSendSLRec
,
10007 kEventParamTextInputSendFixLen
,
10008 kEventParamTextInputSendText
,
10009 kEventParamTextInputSendUpdateRng
,
10010 kEventParamTextInputSendHiliteRng
,
10011 kEventParamTextInputSendClauseRng
,
10012 kEventParamTextInputSendPinRng
,
10013 kEventParamTextInputSendTextServiceEncoding
,
10014 kEventParamTextInputSendTextServiceMacEncoding
,
10015 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
10016 static const EventParamType types_uaia
[] =
10017 {typeComponentInstance
,
10019 typeIntlWritingCode
,
10026 typeTextRangeArray
,
10027 typeTextRangeArray
,
10033 static const EventParamName names_ufke
[] =
10034 {kEventParamTextInputSendComponentInstance
,
10035 kEventParamTextInputSendRefCon
,
10036 kEventParamTextInputSendSLRec
,
10037 kEventParamTextInputSendText
};
10038 static const EventParamType types_ufke
[] =
10039 {typeComponentInstance
,
10041 typeIntlWritingCode
,
10044 result
= CallNextEventHandler (next_handler
, event
);
10046 switch (GetEventKind (event
))
10048 case kEventTextInputUpdateActiveInputArea
:
10049 id_key
= Qupdate_active_input_area
;
10050 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
10051 names
= names_uaia
;
10052 types
= types_uaia
;
10053 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
10054 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
10058 case kEventTextInputUnicodeForKeyEvent
:
10060 EventRef kbd_event
;
10061 UInt32 actual_size
, modifiers
, mapped_modifiers
;
10063 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
10064 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
10067 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
10069 sizeof (UInt32
), NULL
, &modifiers
);
10073 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
10074 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
10075 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
10077 mapped_modifiers
|=
10078 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
10080 if (modifiers
& mapped_modifiers
)
10081 /* There're mapped modifier keys. Process it in
10083 return eventNotHandledErr
;
10086 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10087 typeUnicodeText
, NULL
, 0, &actual_size
,
10089 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
10093 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10094 typeUnicodeText
, NULL
,
10095 sizeof (UniChar
), NULL
, &code
);
10096 if (err
== noErr
&& code
< 0x80)
10098 /* ASCII character. Process it in XTread_socket. */
10099 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
10103 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
10104 typeUInt32
, NULL
, sizeof (UInt32
),
10106 if (!(err
== noErr
&& key_code
<= 0x7f
10107 && keycode_to_xkeysym_table
[key_code
]))
10110 mac_focus_frame (&one_mac_display_info
);
10112 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
10113 read_socket_inev
->code
= code
;
10114 read_socket_inev
->modifiers
=
10115 mac_to_emacs_modifiers (modifiers
);
10116 read_socket_inev
->modifiers
|=
10117 (extra_keyboard_modifiers
10118 & (meta_modifier
| alt_modifier
10119 | hyper_modifier
| super_modifier
));
10120 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10123 return eventNotHandledErr
;
10127 /* Non-ASCII keystrokes without mapped modifiers are processed
10128 at the Lisp level. */
10129 id_key
= Qunicode_for_key_event
;
10130 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
10131 names
= names_ufke
;
10132 types
= types_ufke
;
10135 case kEventTextInputOffsetToPos
:
10141 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
10142 return eventNotHandledErr
;
10144 /* Strictly speaking, this is not always correct because
10145 previous events may change some states about display. */
10146 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
10148 /* Active input area is displayed in the echo area. */
10149 w
= XWINDOW (echo_area_window
);
10150 f
= WINDOW_XFRAME (w
);
10154 /* Active input area is displayed around the current point. */
10155 f
= SELECTED_FRAME ();
10156 w
= XWINDOW (f
->selected_window
);
10159 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
10160 + WINDOW_LEFT_FRINGE_WIDTH (w
));
10161 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
10162 + FONT_BASE (FRAME_FONT (f
)));
10163 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
10164 LocalToGlobal (&p
);
10165 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
10166 typeQDPoint
, sizeof (typeQDPoint
), &p
);
10174 if (!NILP (id_key
))
10175 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
10179 return err
== noErr
? noErr
: result
;
10185 mac_store_service_event (event
)
10189 Lisp_Object id_key
;
10191 const EventParamName
*names
;
10192 const EventParamType
*types
;
10193 static const EventParamName names_pfm
[] =
10194 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10195 static const EventParamType types_pfm
[] =
10196 {typeCFStringRef
, typeCFStringRef
};
10198 switch (GetEventKind (event
))
10200 case kEventServicePaste
:
10207 case kEventServicePerform
:
10209 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10218 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10224 #endif /* MAC_OSX */
10225 #endif /* USE_CARBON_EVENTS */
10229 install_window_handler (window
)
10232 OSStatus err
= noErr
;
10233 #if USE_CARBON_EVENTS
10234 static const EventTypeSpec specs_window
[] =
10235 {{kEventClassWindow
, kEventWindowUpdate
},
10236 {kEventClassWindow
, kEventWindowGetIdealSize
},
10237 {kEventClassWindow
, kEventWindowBoundsChanging
},
10238 {kEventClassWindow
, kEventWindowBoundsChanged
},
10239 {kEventClassWindow
, kEventWindowShown
},
10240 {kEventClassWindow
, kEventWindowHidden
},
10241 {kEventClassWindow
, kEventWindowExpanded
},
10242 {kEventClassWindow
, kEventWindowCollapsed
},
10243 {kEventClassWindow
, kEventWindowClose
},
10245 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
10248 {kEventClassWindow
, kEventWindowFocusAcquired
},
10249 {kEventClassWindow
, kEventWindowFocusRelinquish
},
10252 static const EventTypeSpec specs_mouse
[] =
10253 {{kEventClassMouse
, kEventMouseWheelMoved
}};
10254 static EventHandlerUPP handle_window_eventUPP
= NULL
;
10255 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
10256 #if USE_MAC_FONT_PANEL
10257 static const EventTypeSpec specs_font
[] =
10258 {{kEventClassFont
, kEventFontPanelClosed
},
10259 {kEventClassFont
, kEventFontSelection
}};
10260 static EventHandlerUPP handle_font_eventUPP
= NULL
;
10263 static const EventTypeSpec specs_text_input
[] =
10264 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
10265 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
10266 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
10267 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
10270 if (handle_window_eventUPP
== NULL
)
10271 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
10272 if (handle_mouse_eventUPP
== NULL
)
10273 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
10274 #if USE_MAC_FONT_PANEL
10275 if (handle_font_eventUPP
== NULL
)
10276 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
10279 if (handle_text_input_eventUPP
== NULL
)
10280 handle_text_input_eventUPP
=
10281 NewEventHandlerUPP (mac_handle_text_input_event
);
10283 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
10284 GetEventTypeCount (specs_window
),
10285 specs_window
, NULL
, NULL
);
10287 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
10288 GetEventTypeCount (specs_mouse
),
10289 specs_mouse
, NULL
, NULL
);
10290 #if USE_MAC_FONT_PANEL
10292 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
10293 GetEventTypeCount (specs_font
),
10294 specs_font
, NULL
, NULL
);
10298 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
10299 GetEventTypeCount (specs_text_input
),
10300 specs_text_input
, window
, NULL
);
10304 err
= install_drag_handler (window
);
10306 err
= install_menu_target_item_handler (window
);
10312 remove_window_handler (window
)
10315 remove_drag_handler (window
);
10321 profiler_exit_proc ()
10323 ProfilerDump ("\pEmacs.prof");
10328 /* These few functions implement Emacs as a normal Mac application
10329 (almost): set up the heap and the Toolbox, handle necessary system
10330 events plus a few simple menu events. They also set up Emacs's
10331 access to functions defined in the rest of this file. Emacs uses
10332 function hooks to perform all its terminal I/O. A complete list of
10333 these functions appear in termhooks.h. For what they do, read the
10334 comments there and see also w32term.c and xterm.c. What's
10335 noticeably missing here is the event loop, which is normally
10336 present in most Mac application. After performing the necessary
10337 Mac initializations, main passes off control to emacs_main
10338 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10339 (defined further below) to read input. This is where
10340 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10347 #if __profile__ /* is the profiler on? */
10348 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10353 /* set creator and type for files created by MSL */
10354 _fcreator
= MAC_EMACS_CREATOR_CODE
;
10358 do_init_managers ();
10362 #ifndef USE_LSB_TAG
10363 do_check_ram_size ();
10366 init_emacs_passwd_dir ();
10370 init_coercion_handler ();
10372 initialize_applescript ();
10374 init_apple_event_handler ();
10380 /* set up argv array from STR# resource */
10381 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10385 /* free up AppleScript resources on exit */
10386 atexit (terminate_applescript
);
10388 #if __profile__ /* is the profiler on? */
10389 atexit (profiler_exit_proc
);
10392 /* 3rd param "envp" never used in emacs_main */
10393 (void) emacs_main (argc
, argv
, 0);
10396 /* Never reached - real exit in Fkill_emacs */
10401 #if !USE_CARBON_EVENTS
10402 static RgnHandle mouse_region
= NULL
;
10405 mac_wait_next_event (er
, sleep_time
, dequeue
)
10410 static EventRecord er_buf
= {nullEvent
};
10411 UInt32 target_tick
, current_tick
;
10412 EventMask event_mask
;
10414 if (mouse_region
== NULL
)
10415 mouse_region
= NewRgn ();
10417 event_mask
= everyEvent
;
10418 if (!mac_ready_for_apple_events
)
10419 event_mask
-= highLevelEventMask
;
10421 current_tick
= TickCount ();
10422 target_tick
= current_tick
+ sleep_time
;
10424 if (er_buf
.what
== nullEvent
)
10425 while (!WaitNextEvent (event_mask
, &er_buf
,
10426 target_tick
- current_tick
, mouse_region
))
10428 current_tick
= TickCount ();
10429 if (target_tick
<= current_tick
)
10435 er_buf
.what
= nullEvent
;
10438 #endif /* not USE_CARBON_EVENTS */
10440 #if TARGET_API_MAC_CARBON
10442 mac_post_mouse_moved_event ()
10444 EventRef event
= NULL
;
10447 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
10448 kEventAttributeNone
, &event
);
10453 GetMouse (&mouse_pos
);
10454 LocalToGlobal (&mouse_pos
);
10455 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
10456 sizeof (Point
), &mouse_pos
);
10460 UInt32 modifiers
= GetCurrentKeyModifiers ();
10462 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10463 sizeof (UInt32
), &modifiers
);
10466 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10467 kEventPriorityStandard
);
10469 ReleaseEvent (event
);
10475 mac_set_unicode_keystroke_event (code
, buf
)
10477 struct input_event
*buf
;
10479 int charset_id
, c1
, c2
;
10483 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10486 else if (code
< 0x100)
10489 charset_id
= CHARSET_8_BIT_CONTROL
;
10491 charset_id
= charset_latin_iso8859_1
;
10492 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10493 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10498 charset_id
= charset_mule_unicode_0100_24ff
,
10500 else if (code
< 0x33FF)
10501 charset_id
= charset_mule_unicode_2500_33ff
,
10503 else if (code
>= 0xE000)
10504 charset_id
= charset_mule_unicode_e000_ffff
,
10506 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10507 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10508 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10513 /* Emacs calls this whenever it wants to read an input event from the
10516 XTread_socket (sd
, expected
, hold_quit
)
10518 struct input_event
*hold_quit
;
10520 struct input_event inev
;
10522 #if USE_CARBON_EVENTS
10524 EventTargetRef toolbox_dispatcher
;
10527 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10529 if (interrupt_input_blocked
)
10531 interrupt_input_pending
= 1;
10535 interrupt_input_pending
= 0;
10538 /* So people can tell when we have read the available input. */
10539 input_signal_count
++;
10543 #if USE_CARBON_EVENTS
10544 toolbox_dispatcher
= GetEventDispatcherTarget ();
10548 mac_prepare_for_quickdraw (NULL
),
10550 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10551 kEventRemoveFromQueue
, &eventRef
))
10552 #else /* !USE_CARBON_EVENTS */
10553 while (mac_wait_next_event (&er
, 0, true))
10554 #endif /* !USE_CARBON_EVENTS */
10558 unsigned long timestamp
;
10561 inev
.kind
= NO_EVENT
;
10564 #if USE_CARBON_EVENTS
10565 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10567 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10570 #if USE_CARBON_EVENTS
10571 /* Handle new events */
10572 if (!mac_convert_event_ref (eventRef
, &er
))
10574 /* There used to be a handler for the kEventMouseWheelMoved
10575 event here. But as of Mac OS X 10.4, this kind of event
10576 is not directly posted to the main event queue by
10577 two-finger scrolling on the trackpad. Instead, some
10578 private event is posted and it is converted to a wheel
10579 event by the default handler for the application target.
10580 The converted one can be received by a Carbon event
10581 handler installed on a window target. */
10582 read_socket_inev
= &inev
;
10583 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10584 read_socket_inev
= NULL
;
10587 #endif /* USE_CARBON_EVENTS */
10593 WindowPtr window_ptr
;
10594 ControlPartCode part_code
;
10595 int tool_bar_p
= 0;
10597 #if USE_CARBON_EVENTS
10598 /* This is needed to send mouse events like aqua window
10599 buttons to the correct handler. */
10600 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10601 != eventNotHandledErr
)
10604 last_mouse_glyph_frame
= 0;
10606 if (dpyinfo
->grabbed
&& last_mouse_frame
10607 && FRAME_LIVE_P (last_mouse_frame
))
10609 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10610 part_code
= inContent
;
10614 part_code
= FindWindow (er
.where
, &window_ptr
);
10615 if (tip_window
&& window_ptr
== tip_window
)
10617 HideWindow (tip_window
);
10618 part_code
= FindWindow (er
.where
, &window_ptr
);
10622 if (er
.what
!= mouseDown
&&
10623 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10629 f
= mac_focus_frame (dpyinfo
);
10630 saved_menu_event_location
= er
.where
;
10631 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10632 XSETFRAME (inev
.frame_or_window
, f
);
10637 #if TARGET_API_MAC_CARBON
10638 FrontNonFloatingWindow ()
10643 || (mac_window_to_frame (window_ptr
)
10644 != dpyinfo
->x_focus_frame
))
10645 SelectWindow (window_ptr
);
10648 ControlPartCode control_part_code
;
10650 Point mouse_loc
= er
.where
;
10652 ControlKind control_kind
;
10655 f
= mac_window_to_frame (window_ptr
);
10656 /* convert to local coordinates of new window */
10657 SetPortWindowPort (window_ptr
);
10659 GlobalToLocal (&mouse_loc
);
10660 #if TARGET_API_MAC_CARBON
10661 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10662 &control_part_code
);
10665 GetControlKind (ch
, &control_kind
);
10668 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10672 #if USE_CARBON_EVENTS
10673 inev
.code
= mac_get_mouse_btn (eventRef
);
10674 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10676 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10677 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10679 XSETINT (inev
.x
, mouse_loc
.h
);
10680 XSETINT (inev
.y
, mouse_loc
.v
);
10682 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10684 #ifndef USE_TOOLKIT_SCROLL_BARS
10685 /* control_part_code becomes kControlNoPart if
10686 a progress indicator is clicked. */
10687 && control_part_code
!= kControlNoPart
10688 #else /* USE_TOOLKIT_SCROLL_BARS */
10690 && control_kind
.kind
== kControlKindScrollBar
10691 #endif /* MAC_OSX */
10692 #endif /* USE_TOOLKIT_SCROLL_BARS */
10695 struct scroll_bar
*bar
;
10697 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10699 bar
= tracked_scroll_bar
;
10700 #ifndef USE_TOOLKIT_SCROLL_BARS
10701 control_part_code
= kControlIndicatorPart
;
10705 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10706 #ifdef USE_TOOLKIT_SCROLL_BARS
10707 /* Make the "Ctrl-Mouse-2 splits window" work
10708 for toolkit scroll bars. */
10709 if (er
.modifiers
& controlKey
)
10710 x_scroll_bar_handle_click (bar
, control_part_code
,
10712 else if (er
.what
== mouseDown
)
10713 x_scroll_bar_handle_press (bar
, control_part_code
,
10716 x_scroll_bar_handle_release (bar
, &inev
);
10717 #else /* not USE_TOOLKIT_SCROLL_BARS */
10718 x_scroll_bar_handle_click (bar
, control_part_code
,
10720 if (er
.what
== mouseDown
10721 && control_part_code
== kControlIndicatorPart
)
10722 tracked_scroll_bar
= bar
;
10724 tracked_scroll_bar
= NULL
;
10725 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10729 Lisp_Object window
;
10730 int x
= mouse_loc
.h
;
10731 int y
= mouse_loc
.v
;
10733 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10734 if (EQ (window
, f
->tool_bar_window
))
10736 if (er
.what
== mouseDown
)
10737 handle_tool_bar_click (f
, x
, y
, 1, 0);
10739 handle_tool_bar_click (f
, x
, y
, 0,
10745 XSETFRAME (inev
.frame_or_window
, f
);
10746 inev
.kind
= MOUSE_CLICK_EVENT
;
10750 if (er
.what
== mouseDown
)
10752 dpyinfo
->grabbed
|= (1 << inev
.code
);
10753 last_mouse_frame
= f
;
10756 last_tool_bar_item
= -1;
10760 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10761 /* If a button is released though it was not
10762 previously pressed, that would be because
10763 of multi-button emulation. */
10764 dpyinfo
->grabbed
= 0;
10766 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10769 /* Ignore any mouse motion that happened before
10770 this event; any subsequent mouse-movement Emacs
10771 events should reflect only motion after the
10774 f
->mouse_moved
= 0;
10776 #ifdef USE_TOOLKIT_SCROLL_BARS
10777 if (inev
.kind
== MOUSE_CLICK_EVENT
)
10782 inev
.modifiers
|= down_modifier
;
10785 inev
.modifiers
|= up_modifier
;
10792 #if TARGET_API_MAC_CARBON
10794 if (IsWindowPathSelectClick (window_ptr
, &er
))
10796 WindowPathSelect (window_ptr
, NULL
, NULL
);
10799 if (part_code
== inProxyIcon
10800 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
10801 != errUserWantsToDragWindow
))
10803 DragWindow (window_ptr
, er
.where
, NULL
);
10804 #else /* not TARGET_API_MAC_CARBON */
10805 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10806 #endif /* not TARGET_API_MAC_CARBON */
10807 /* Update the frame parameters. */
10808 #if !USE_CARBON_EVENTS
10810 struct frame
*f
= mac_window_to_frame (window_ptr
);
10812 if (f
&& !f
->async_iconified
)
10813 mac_handle_origin_change (f
);
10819 if (TrackGoAway (window_ptr
, er
.where
))
10821 inev
.kind
= DELETE_WINDOW_EVENT
;
10822 XSETFRAME (inev
.frame_or_window
,
10823 mac_window_to_frame (window_ptr
));
10827 /* window resize handling added --ben */
10829 do_grow_window (window_ptr
, &er
);
10832 /* window zoom handling added --ben */
10835 if (TrackBox (window_ptr
, er
.where
, part_code
))
10836 do_zoom_window (window_ptr
, part_code
);
10846 #if USE_CARBON_EVENTS
10847 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10848 != eventNotHandledErr
)
10851 do_window_update ((WindowPtr
) er
.message
);
10856 #if USE_CARBON_EVENTS
10857 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10858 != eventNotHandledErr
)
10861 switch ((er
.message
>> 24) & 0x000000FF)
10863 case suspendResumeMessage
:
10865 if (er
.message
& resumeFlag
)
10868 mac_tsm_suspend ();
10872 case mouseMovedMessage
:
10873 #if !USE_CARBON_EVENTS
10874 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
10875 er
.where
.h
+ 1, er
.where
.v
+ 1);
10877 previous_help_echo_string
= help_echo_string
;
10878 help_echo_string
= Qnil
;
10880 if (dpyinfo
->grabbed
&& last_mouse_frame
10881 && FRAME_LIVE_P (last_mouse_frame
))
10882 f
= last_mouse_frame
;
10884 f
= dpyinfo
->x_focus_frame
;
10886 if (dpyinfo
->mouse_face_hidden
)
10888 dpyinfo
->mouse_face_hidden
= 0;
10889 clear_mouse_face (dpyinfo
);
10894 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
10895 Point mouse_pos
= er
.where
;
10897 SetPortWindowPort (wp
);
10899 GlobalToLocal (&mouse_pos
);
10901 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10902 #ifdef USE_TOOLKIT_SCROLL_BARS
10903 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
10905 #else /* not USE_TOOLKIT_SCROLL_BARS */
10906 x_scroll_bar_note_movement (tracked_scroll_bar
,
10908 - XINT (tracked_scroll_bar
->top
),
10909 er
.when
* (1000 / 60));
10910 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10913 /* Generate SELECT_WINDOW_EVENTs when needed. */
10914 if (!NILP (Vmouse_autoselect_window
))
10916 Lisp_Object window
;
10918 window
= window_from_coordinates (f
,
10923 /* Window will be selected only when it is
10924 not selected now and last mouse movement
10925 event was not in it. Minibuffer window
10926 will be selected iff it is active. */
10927 if (WINDOWP (window
)
10928 && !EQ (window
, last_window
)
10929 && !EQ (window
, selected_window
))
10931 inev
.kind
= SELECT_WINDOW_EVENT
;
10932 inev
.frame_or_window
= window
;
10935 last_window
=window
;
10937 if (!note_mouse_movement (f
, &mouse_pos
))
10938 help_echo_string
= previous_help_echo_string
;
10942 /* If the contents of the global variable
10943 help_echo_string has changed, generate a
10945 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10953 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10955 #if USE_CARBON_EVENTS
10956 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10957 != eventNotHandledErr
)
10960 if (window_ptr
== tip_window
)
10962 HideWindow (tip_window
);
10966 if (!is_emacs_window (window_ptr
))
10969 if ((er
.modifiers
& activeFlag
) != 0)
10971 /* A window has been activated */
10972 Point mouse_loc
= er
.where
;
10974 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10976 SetPortWindowPort (window_ptr
);
10977 GlobalToLocal (&mouse_loc
);
10978 /* Window-activated event counts as mouse movement,
10979 so update things that depend on mouse position. */
10980 note_mouse_movement (mac_window_to_frame (window_ptr
),
10985 /* A window has been deactivated */
10986 #if USE_TOOLKIT_SCROLL_BARS
10987 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10989 struct input_event event
;
10991 EVENT_INIT (event
);
10992 event
.kind
= NO_EVENT
;
10993 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10994 if (event
.kind
!= NO_EVENT
)
10996 event
.timestamp
= timestamp
;
10997 kbd_buffer_store_event_hold (&event
, hold_quit
);
11002 dpyinfo
->grabbed
= 0;
11004 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11006 f
= mac_window_to_frame (window_ptr
);
11007 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11009 /* If we move outside the frame, then we're
11010 certainly no longer on any text in the
11012 clear_mouse_face (dpyinfo
);
11013 dpyinfo
->mouse_face_mouse_frame
= 0;
11016 /* Generate a nil HELP_EVENT to cancel a help-echo.
11017 Do it only if there's something to cancel.
11018 Otherwise, the startup message is cleared when the
11019 mouse leaves the frame. */
11020 if (any_help_event_p
)
11030 int keycode
= (er
.message
& keyCodeMask
) >> 8;
11031 static SInt16 last_key_script
= -1;
11032 SInt16 current_key_script
;
11033 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
11036 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
11037 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
11038 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
11040 #if USE_CARBON_EVENTS && defined (MAC_OSX)
11041 mapped_modifiers
|=
11042 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
11044 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
11046 sizeof (UInt32
), NULL
, &modifiers
);
11048 mapped_modifiers
&= modifiers
;
11050 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
11051 /* When using Carbon Events, we need to pass raw keyboard
11052 events to the TSM ourselves. If TSM handles it, it
11053 will pass back noErr, otherwise it will pass back
11054 "eventNotHandledErr" and we can process it
11056 if (!(mapped_modifiers
11057 & ~(mac_pass_command_to_system
? cmdKey
: 0)
11058 & ~(mac_pass_control_to_system
? controlKey
: 0)))
11062 read_socket_inev
= &inev
;
11063 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11064 read_socket_inev
= NULL
;
11065 if (err
!= eventNotHandledErr
)
11069 if (er
.what
== keyUp
)
11074 f
= mac_focus_frame (dpyinfo
);
11076 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
11077 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
11079 clear_mouse_face (dpyinfo
);
11080 dpyinfo
->mouse_face_hidden
= 1;
11083 current_key_script
= GetScriptManagerVariable (smKeyScript
);
11084 if (last_key_script
!= current_key_script
)
11086 struct input_event event
;
11088 EVENT_INIT (event
);
11089 event
.kind
= LANGUAGE_CHANGE_EVENT
;
11091 event
.code
= current_key_script
;
11092 event
.timestamp
= timestamp
;
11093 kbd_buffer_store_event (&event
);
11095 last_key_script
= current_key_script
;
11099 if (inev
.kind
!= NO_EVENT
)
11104 if (mapped_modifiers
& kEventKeyModifierFnMask
11106 && fn_keycode_to_keycode_table
[keycode
])
11107 keycode
= fn_keycode_to_keycode_table
[keycode
];
11109 if (keycode
<= 0x7f && keycode_to_xkeysym_table
[keycode
])
11111 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
11112 inev
.code
= 0xff00 | keycode_to_xkeysym_table
[keycode
];
11114 if (modifiers
& kEventKeyModifierFnMask
11116 && fn_keycode_to_keycode_table
[keycode
] == keycode
)
11117 modifiers
&= ~kEventKeyModifierFnMask
;
11120 else if (mapped_modifiers
)
11122 /* translate the keycode back to determine the
11125 static SInt16 last_key_layout_id
= 0;
11126 static Handle uchr_handle
= (Handle
)-1;
11127 SInt16 current_key_layout_id
=
11128 GetScriptVariable (current_key_script
, smScriptKeys
);
11130 if (uchr_handle
== (Handle
)-1
11131 || last_key_layout_id
!= current_key_layout_id
)
11133 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
11134 last_key_layout_id
= current_key_layout_id
;
11140 UInt16 key_action
= er
.what
- keyDown
;
11141 UInt32 modifier_key_state
=
11142 (modifiers
& ~mapped_modifiers
) >> 8;
11143 UInt32 keyboard_type
= LMGetKbdType ();
11144 SInt32 dead_key_state
= 0;
11146 UniCharCount actual_length
;
11148 status
= UCKeyTranslate ((UCKeyboardLayout
*)*uchr_handle
,
11149 keycode
, key_action
,
11150 modifier_key_state
,
11152 kUCKeyTranslateNoDeadKeysMask
,
11154 1, &actual_length
, &code
);
11155 if (status
== noErr
&& actual_length
== 1)
11156 mac_set_unicode_keystroke_event (code
, &inev
);
11158 #endif /* MAC_OSX */
11160 if (inev
.kind
== NO_EVENT
)
11162 /* This code comes from Keyboard Resource,
11163 Appendix C of IM - Text. This is necessary
11164 since shift is ignored in KCHR table
11165 translation when option or command is pressed.
11166 It also does not translate correctly
11167 control-shift chars like C-% so mask off shift
11169 /* Mask off modifier keys that are mapped to some
11170 Emacs modifiers. */
11171 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
11172 /* set high byte of keycode to modifier high byte*/
11173 int new_keycode
= keycode
| new_modifiers
;
11174 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
11175 unsigned long some_state
= 0;
11176 UInt32 new_char_code
;
11178 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
11180 if (new_char_code
== 0)
11181 /* Seems like a dead key. Append up-stroke. */
11182 new_char_code
= KeyTranslate (kchr_ptr
,
11183 new_keycode
| 0x80,
11187 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11188 inev
.code
= new_char_code
& 0xff;
11193 if (inev
.kind
== NO_EVENT
)
11195 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11196 inev
.code
= er
.message
& charCodeMask
;
11199 inev
.modifiers
= mac_to_emacs_modifiers (modifiers
);
11200 inev
.modifiers
|= (extra_keyboard_modifiers
11201 & (meta_modifier
| alt_modifier
11202 | hyper_modifier
| super_modifier
));
11203 XSETFRAME (inev
.frame_or_window
, f
);
11205 #if TARGET_API_MAC_CARBON
11206 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
11207 && inev
.code
>= 0x80 && inev
.modifiers
)
11210 TextEncoding encoding
= kTextEncodingMacRoman
;
11211 TextToUnicodeInfo ttu_info
;
11213 UpgradeScriptInfoToTextEncoding (current_key_script
,
11214 kTextLanguageDontCare
,
11215 kTextRegionDontCare
,
11217 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
11222 ByteCount unicode_len
;
11225 pstr
[1] = inev
.code
;
11226 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
11228 &unicode_len
, &code
);
11229 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
11230 mac_set_unicode_keystroke_event (code
, &inev
);
11231 DisposeTextToUnicodeInfo (&ttu_info
);
11238 case kHighLevelEvent
:
11239 AEProcessAppleEvent (&er
);
11245 #if USE_CARBON_EVENTS
11246 ReleaseEvent (eventRef
);
11249 if (inev
.kind
!= NO_EVENT
)
11251 inev
.timestamp
= timestamp
;
11252 kbd_buffer_store_event_hold (&inev
, hold_quit
);
11257 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
11262 XSETFRAME (frame
, f
);
11268 any_help_event_p
= 1;
11269 gen_help_event (help_echo_string
, frame
, help_echo_window
,
11270 help_echo_object
, help_echo_pos
);
11274 help_echo_string
= Qnil
;
11275 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
11282 /* If the focus was just given to an autoraising frame,
11284 /* ??? This ought to be able to handle more than one such frame. */
11285 if (pending_autoraise_frame
)
11287 x_raise_frame (pending_autoraise_frame
);
11288 pending_autoraise_frame
= 0;
11291 #if !USE_CARBON_EVENTS
11292 /* Check which frames are still visible. We do this here because
11293 there doesn't seem to be any direct notification from the Window
11294 Manager that the visibility of a window has changed (at least,
11295 not in all cases). */
11297 Lisp_Object tail
, frame
;
11299 FOR_EACH_FRAME (tail
, frame
)
11301 struct frame
*f
= XFRAME (frame
);
11303 /* The tooltip has been drawn already. Avoid the
11304 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11305 if (EQ (frame
, tip_frame
))
11308 if (FRAME_MAC_P (f
))
11309 mac_handle_visibility_change (f
);
11320 /* Need to override CodeWarrior's input function so no conversion is
11321 done on newlines Otherwise compiled functions in .elc files will be
11322 read incorrectly. Defined in ...:MSL C:MSL
11323 Common:Source:buffer_io.c. */
11326 __convert_to_newlines (unsigned char * p
, size_t * n
)
11328 #pragma unused(p,n)
11332 __convert_from_newlines (unsigned char * p
, size_t * n
)
11334 #pragma unused(p,n)
11340 make_mac_terminal_frame (struct frame
*f
)
11345 XSETFRAME (frame
, f
);
11347 f
->output_method
= output_mac
;
11348 f
->output_data
.mac
= (struct mac_output
*)
11349 xmalloc (sizeof (struct mac_output
));
11350 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
11352 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
11354 FRAME_COLS (f
) = 96;
11355 FRAME_LINES (f
) = 4;
11357 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
11358 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
11360 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
11362 f
->output_data
.mac
->cursor_pixel
= 0;
11363 f
->output_data
.mac
->border_pixel
= 0x00ff00;
11364 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
11365 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
11367 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
11368 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
11369 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
11370 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
11371 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
11372 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
11374 FRAME_FONTSET (f
) = -1;
11375 f
->output_data
.mac
->explicit_parent
= 0;
11378 f
->border_width
= 0;
11380 f
->internal_border_width
= 0;
11385 f
->new_text_cols
= 0;
11386 f
->new_text_lines
= 0;
11388 SetRect (&r
, f
->left_pos
, f
->top_pos
,
11389 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
11390 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
11394 if (!(FRAME_MAC_WINDOW (f
) =
11395 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
11396 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
11398 /* so that update events can find this mac_output struct */
11399 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
11405 /* Need to be initialized for unshow_buffer in window.c. */
11406 selected_window
= f
->selected_window
;
11408 Fmodify_frame_parameters (frame
,
11409 Fcons (Fcons (Qfont
,
11410 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
11411 Fmodify_frame_parameters (frame
,
11412 Fcons (Fcons (Qforeground_color
,
11413 build_string ("black")), Qnil
));
11414 Fmodify_frame_parameters (frame
,
11415 Fcons (Fcons (Qbackground_color
,
11416 build_string ("white")), Qnil
));
11421 /***********************************************************************
11423 ***********************************************************************/
11425 int mac_initialized
= 0;
11428 mac_initialize_display_info ()
11430 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11432 bzero (dpyinfo
, sizeof (*dpyinfo
));
11435 dpyinfo
->mac_id_name
11436 = (char *) xmalloc (SCHARS (Vinvocation_name
)
11437 + SCHARS (Vsystem_name
)
11439 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
11440 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11442 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
11443 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
11446 dpyinfo
->reference_count
= 0;
11447 dpyinfo
->resx
= 72.0;
11448 dpyinfo
->resy
= 72.0;
11450 /* HasDepth returns true if it is possible to have a 32 bit display,
11451 but this may not be what is actually used. Mac OSX can do better. */
11452 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11453 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11454 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11455 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11458 GDHandle main_device_handle
= LMGetMainDevice();
11460 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
11461 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11462 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
11463 gdDevType
, dpyinfo
->color_p
))
11465 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
11466 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
11469 dpyinfo
->grabbed
= 0;
11470 dpyinfo
->root_window
= NULL
;
11471 dpyinfo
->image_cache
= make_image_cache ();
11473 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11474 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11475 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11476 dpyinfo
->mouse_face_window
= Qnil
;
11477 dpyinfo
->mouse_face_overlay
= Qnil
;
11478 dpyinfo
->mouse_face_hidden
= 0;
11483 mac_make_rdb (xrm_option
)
11484 const char *xrm_option
;
11486 XrmDatabase database
;
11488 database
= xrm_get_preference_database (NULL
);
11490 xrm_merge_string_database (database
, xrm_option
);
11495 struct mac_display_info
*
11496 mac_term_init (display_name
, xrm_option
, resource_name
)
11497 Lisp_Object display_name
;
11499 char *resource_name
;
11501 struct mac_display_info
*dpyinfo
;
11505 if (!mac_initialized
)
11508 mac_initialized
= 1;
11511 if (x_display_list
)
11512 error ("Sorry, this version can only handle one display");
11514 mac_initialize_display_info ();
11516 dpyinfo
= &one_mac_display_info
;
11518 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11520 /* Put this display on the chain. */
11521 dpyinfo
->next
= x_display_list
;
11522 x_display_list
= dpyinfo
;
11524 /* Put it on x_display_name_list. */
11525 x_display_name_list
= Fcons (Fcons (display_name
,
11526 Fcons (Qnil
, dpyinfo
->xrdb
)),
11527 x_display_name_list
);
11528 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11534 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11537 x_delete_display (dpyinfo
)
11538 struct mac_display_info
*dpyinfo
;
11542 /* Discard this display from x_display_name_list and x_display_list.
11543 We can't use Fdelq because that can quit. */
11544 if (! NILP (x_display_name_list
)
11545 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11546 x_display_name_list
= XCDR (x_display_name_list
);
11551 tail
= x_display_name_list
;
11552 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11554 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11556 XSETCDR (tail
, XCDR (XCDR (tail
)));
11559 tail
= XCDR (tail
);
11563 if (x_display_list
== dpyinfo
)
11564 x_display_list
= dpyinfo
->next
;
11567 struct x_display_info
*tail
;
11569 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11570 if (tail
->next
== dpyinfo
)
11571 tail
->next
= tail
->next
->next
;
11574 /* Free the font names in the font table. */
11575 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11576 if (dpyinfo
->font_table
[i
].name
)
11578 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11579 xfree (dpyinfo
->font_table
[i
].full_name
);
11580 xfree (dpyinfo
->font_table
[i
].name
);
11583 if (dpyinfo
->font_table
)
11585 if (dpyinfo
->font_table
->font_encoder
)
11586 xfree (dpyinfo
->font_table
->font_encoder
);
11587 xfree (dpyinfo
->font_table
);
11589 if (dpyinfo
->mac_id_name
)
11590 xfree (dpyinfo
->mac_id_name
);
11592 if (x_display_list
== 0)
11594 mac_clear_font_name_table ();
11595 bzero (dpyinfo
, sizeof (*dpyinfo
));
11604 extern int inhibit_window_system
;
11605 extern int noninteractive
;
11606 CFBundleRef appsBundle
;
11608 /* No need to test if already -nw*/
11609 if (inhibit_window_system
|| noninteractive
)
11612 appsBundle
= CFBundleGetMainBundle();
11613 if (appsBundle
!= NULL
)
11615 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
11616 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
11617 /* We found the bundle identifier, now we know we are valid. */
11624 /* MAC_TODO: Have this start the bundled executable */
11626 /* For now, prevent the fatal error by bringing it up in the terminal */
11627 inhibit_window_system
= 1;
11631 MakeMeTheFrontProcess ()
11633 ProcessSerialNumber psn
;
11636 err
= GetCurrentProcess (&psn
);
11638 (void) SetFrontProcess (&psn
);
11641 /***** Code to handle C-g testing *****/
11643 /* Contains the Mac modifier formed from quit_char */
11644 int mac_quit_char_modifiers
= 0;
11645 int mac_quit_char_keycode
;
11646 extern int quit_char
;
11649 mac_determine_quit_char_modifiers()
11651 /* Todo: Determine modifiers from quit_char. */
11652 UInt32 qc_modifiers
= ctrl_modifier
;
11654 /* Map modifiers */
11655 mac_quit_char_modifiers
= 0;
11656 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
11657 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
11658 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
11662 init_quit_char_handler ()
11664 /* TODO: Let this support keys other the 'g' */
11665 mac_quit_char_keycode
= 5;
11666 /* Look at <architecture/adb_kb_map.h> for details */
11667 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
11669 mac_determine_quit_char_modifiers();
11671 #endif /* MAC_OSX */
11679 MenuItemIndex menu_index
;
11681 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11682 &menu
, &menu_index
);
11684 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11685 #if USE_CARBON_EVENTS
11686 EnableMenuCommand (NULL
, kHICommandPreferences
);
11687 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11688 &menu
, &menu_index
);
11691 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11692 InsertMenuItemTextWithCFString (menu
, NULL
,
11693 0, kMenuItemAttrSeparator
, 0);
11694 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11695 0, 0, kHICommandAbout
);
11697 #endif /* USE_CARBON_EVENTS */
11698 #else /* !MAC_OSX */
11699 #if USE_CARBON_EVENTS
11700 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11710 static InterfaceTypeList types
= {kUnicodeDocument
};
11712 static InterfaceTypeList types
= {kTextService
};
11715 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11716 &tsm_document_id
, 0);
11720 /* Set up use of X before we make the first connection. */
11722 extern frame_parm_handler mac_frame_parm_handlers
[];
11724 static struct redisplay_interface x_redisplay_interface
=
11726 mac_frame_parm_handlers
,
11730 x_clear_end_of_line
,
11732 x_after_update_window_line
,
11733 x_update_window_begin
,
11734 x_update_window_end
,
11737 0, /* flush_display_optional */
11738 x_clear_window_mouse_face
,
11739 x_get_glyph_overhangs
,
11740 x_fix_overlapping_area
,
11741 x_draw_fringe_bitmap
,
11743 mac_define_fringe_bitmap
,
11744 mac_destroy_fringe_bitmap
,
11746 0, /* define_fringe_bitmap */
11747 0, /* destroy_fringe_bitmap */
11749 mac_per_char_metric
,
11751 mac_compute_glyph_string_overhangs
,
11752 x_draw_glyph_string
,
11753 mac_define_frame_cursor
,
11754 mac_clear_frame_area
,
11755 mac_draw_window_cursor
,
11756 mac_draw_vertical_window_border
,
11757 mac_shift_glyphs_for_insert
11763 rif
= &x_redisplay_interface
;
11765 clear_frame_hook
= x_clear_frame
;
11766 ins_del_lines_hook
= x_ins_del_lines
;
11767 delete_glyphs_hook
= x_delete_glyphs
;
11768 ring_bell_hook
= XTring_bell
;
11769 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11770 set_terminal_modes_hook
= XTset_terminal_modes
;
11771 update_begin_hook
= x_update_begin
;
11772 update_end_hook
= x_update_end
;
11773 set_terminal_window_hook
= XTset_terminal_window
;
11774 read_socket_hook
= XTread_socket
;
11775 frame_up_to_date_hook
= XTframe_up_to_date
;
11776 mouse_position_hook
= XTmouse_position
;
11777 frame_rehighlight_hook
= XTframe_rehighlight
;
11778 frame_raise_lower_hook
= XTframe_raise_lower
;
11780 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11781 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11782 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11783 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11785 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
11786 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
11787 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
11788 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
11789 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
11794 last_tool_bar_item
= -1;
11795 any_help_event_p
= 0;
11797 /* Try to use interrupt input; if we can't, then start polling. */
11798 Fset_input_interrupt_mode (Qt
);
11802 #if TARGET_API_MAC_CARBON
11804 #if USE_CARBON_EVENTS
11806 init_service_handler ();
11808 init_quit_char_handler ();
11809 #endif /* MAC_OSX */
11811 init_command_handler ();
11818 #endif /* USE_CARBON_EVENTS */
11821 init_coercion_handler ();
11823 init_apple_event_handler ();
11825 if (!inhibit_window_system
)
11826 MakeMeTheFrontProcess ();
11833 mac_init_fringe ();
11844 staticpro (&x_error_message_string
);
11845 x_error_message_string
= Qnil
;
11848 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11849 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11850 Qalt
= intern ("alt"); staticpro (&Qalt
);
11851 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
11852 Qsuper
= intern ("super"); staticpro (&Qsuper
);
11853 Qmodifier_value
= intern ("modifier-value");
11854 staticpro (&Qmodifier_value
);
11856 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
11857 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11858 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11859 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11860 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11862 #if USE_CARBON_EVENTS
11863 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
11865 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
11866 staticpro (&Qtoolbar_switch_mode
);
11867 #if USE_MAC_FONT_PANEL
11868 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
11869 Qselection
= intern ("selection"); staticpro (&Qselection
);
11872 Qservice
= intern ("service"); staticpro (&Qservice
);
11873 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
11874 Qperform
= intern ("perform"); staticpro (&Qperform
);
11877 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
11878 Qupdate_active_input_area
= intern ("update-active-input-area");
11879 staticpro (&Qupdate_active_input_area
);
11880 Qunicode_for_key_event
= intern ("unicode-for-key-event");
11881 staticpro (&Qunicode_for_key_event
);
11886 Fprovide (intern ("mac-carbon"), Qnil
);
11889 staticpro (&Qreverse
);
11890 Qreverse
= intern ("reverse");
11892 staticpro (&x_display_name_list
);
11893 x_display_name_list
= Qnil
;
11895 staticpro (&last_mouse_scroll_bar
);
11896 last_mouse_scroll_bar
= Qnil
;
11898 staticpro (&fm_font_family_alist
);
11899 fm_font_family_alist
= Qnil
;
11902 staticpro (&atsu_font_id_hash
);
11903 atsu_font_id_hash
= Qnil
;
11905 staticpro (&fm_style_face_attributes_alist
);
11906 fm_style_face_attributes_alist
= Qnil
;
11910 staticpro (&saved_ts_script_language_on_focus
);
11911 saved_ts_script_language_on_focus
= Qnil
;
11914 /* We don't yet support this, but defining this here avoids whining
11915 from cus-start.el and other places, like "M-x set-variable". */
11916 DEFVAR_BOOL ("x-use-underline-position-properties",
11917 &x_use_underline_position_properties
,
11918 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11919 A value of nil means ignore them. If you encounter fonts with bogus
11920 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11921 to 4.1, set this to nil.
11923 NOTE: Not supported on Mac yet. */);
11924 x_use_underline_position_properties
= 0;
11926 DEFVAR_BOOL ("x-underline-at-descent-line",
11927 &x_underline_at_descent_line
,
11928 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
11929 A value of nil means to draw the underline according to the value of the
11930 variable `x-use-underline-position-properties', which is usually at the
11931 baseline level. The default value is nil. */);
11932 x_underline_at_descent_line
= 0;
11934 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
11935 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
11936 #ifdef USE_TOOLKIT_SCROLL_BARS
11937 Vx_toolkit_scroll_bars
= Qt
;
11939 Vx_toolkit_scroll_bars
= Qnil
;
11942 staticpro (&last_mouse_motion_frame
);
11943 last_mouse_motion_frame
= Qnil
;
11945 /* Variables to configure modifier key assignment. */
11947 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
11948 doc
: /* *Modifier key assumed when the Mac control key is pressed.
11949 The value can be `control', `meta', `alt', `hyper', or `super' for the
11950 respective modifier. The default is `control'. */);
11951 Vmac_control_modifier
= Qcontrol
;
11953 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
11954 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
11955 The value can be `control', `meta', `alt', `hyper', or `super' for the
11956 respective modifier. If the value is nil then the key will act as the
11957 normal Mac control modifier, and the option key can be used to compose
11958 characters depending on the chosen Mac keyboard setting. */);
11959 Vmac_option_modifier
= Qnil
;
11961 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
11962 doc
: /* *Modifier key assumed when the Mac command key is pressed.
11963 The value can be `control', `meta', `alt', `hyper', or `super' for the
11964 respective modifier. The default is `meta'. */);
11965 Vmac_command_modifier
= Qmeta
;
11967 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
11968 doc
: /* *Modifier key assumed when the Mac function key is pressed.
11969 The value can be `control', `meta', `alt', `hyper', or `super' for the
11970 respective modifier. Note that remapping the function key may lead to
11971 unexpected results for some keys on non-US/GB keyboards. */);
11972 Vmac_function_modifier
= Qnil
;
11974 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11975 &Vmac_emulate_three_button_mouse
,
11976 doc
: /* *Specify a way of three button mouse emulation.
11977 The value can be nil, t, or the symbol `reverse'.
11978 A value of nil means that no emulation should be done and the modifiers
11979 should be placed on the mouse-1 event.
11980 t means that when the option-key is held down while pressing the mouse
11981 button, the click will register as mouse-2 and while the command-key
11982 is held down, the click will register as mouse-3.
11983 The symbol `reverse' means that the option-key will register for
11984 mouse-3 and the command-key will register for mouse-2. */);
11985 Vmac_emulate_three_button_mouse
= Qnil
;
11987 #if USE_CARBON_EVENTS
11988 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
11989 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11990 Otherwise, the right click will be treated as mouse-2 and the wheel
11991 button will be mouse-3. */);
11992 mac_wheel_button_is_mouse_2
= 1;
11994 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
11995 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
11996 mac_pass_command_to_system
= 1;
11998 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
11999 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12000 mac_pass_control_to_system
= 1;
12004 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
12005 doc
: /* *If non-nil, allow anti-aliasing.
12006 The text will be rendered using Core Graphics text rendering which
12007 may anti-alias the text. */);
12009 mac_use_core_graphics
= 1;
12011 mac_use_core_graphics
= 0;
12014 /* Register an entry for `mac-roman' so that it can be used when
12015 creating the terminal frame on Mac OS 9 before loading
12016 term/mac-win.elc. */
12017 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
12018 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
12019 Each entry should be of the form:
12021 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12023 where CHARSET-NAME is a string used in font names to identify the
12024 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12025 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12026 Vmac_charset_info_alist
=
12027 Fcons (list3 (build_string ("mac-roman"),
12028 make_number (smRoman
), Qnil
), Qnil
);
12031 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
12032 doc
: /* Overlay used to display Mac TSM active input area. */);
12033 Vmac_ts_active_input_overlay
= Qnil
;
12035 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
12036 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
12037 If the value is t, the input script and language are restored to those
12038 used in the last focus frame. If the value is a pair of integers, the
12039 input script and language codes, which are defined in the Script
12040 Manager, are set to its car and cdr parts, respectively. Otherwise,
12041 Emacs doesn't set them and thus follows the system default behavior. */);
12042 Vmac_ts_script_language_on_focus
= Qnil
;
12046 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12047 (do not change this comment) */