1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* 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>
56 #if defined (__MRC__) || (__MSL__ >= 0x6000)
57 #include <ControlDefinitions.h>
63 #endif /* not TARGET_API_MAC_CARBON */
76 #include "dispextern.h"
78 #include "termhooks.h"
85 #include "intervals.h"
91 /* Non-nil means Emacs uses toolkit scroll bars. */
93 Lisp_Object Vx_toolkit_scroll_bars
;
95 /* If non-zero, the text will be rendered using Core Graphics text
96 rendering which may anti-alias the text. */
97 int mac_use_core_graphics
;
100 /* Non-zero means that a HELP_EVENT has been generated since Emacs
103 static int any_help_event_p
;
105 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
106 static Lisp_Object last_window
;
108 /* Non-zero means make use of UNDERLINE_POSITION font properties.
109 (Not yet supported.) */
110 int x_use_underline_position_properties
;
112 /* Non-zero means to draw the underline at the same place as the descent line. */
114 int x_underline_at_descent_line
;
116 /* This is a chain of structures for all the X displays currently in
119 struct x_display_info
*x_display_list
;
121 /* This is a list of cons cells, each of the form (NAME
122 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
123 x_display_list and in the same order. NAME is the name of the
124 frame. FONT-LIST-CACHE records previous values returned by
125 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
126 equivalent, which is implemented with a Lisp object, for the
129 Lisp_Object x_display_name_list
;
131 /* This is display since Mac does not support multiple ones. */
132 struct mac_display_info one_mac_display_info
;
134 /* Frame being updated by update_frame. This is declared in term.c.
135 This is set by update_begin and looked at by all the XT functions.
136 It is zero while not inside an update. In that case, the XT
137 functions assume that `selected_frame' is the frame to apply to. */
139 extern struct frame
*updating_frame
;
141 /* This is a frame waiting to be auto-raised, within XTread_socket. */
143 struct frame
*pending_autoraise_frame
;
147 Formerly, we used PointerMotionHintMask (in standard_event_mask)
148 so that we would have to call XQueryPointer after each MotionNotify
149 event to ask for another such event. However, this made mouse tracking
150 slow, and there was a bug that made it eventually stop.
152 Simply asking for MotionNotify all the time seems to work better.
154 In order to avoid asking for motion events and then throwing most
155 of them away or busy-polling the server for mouse positions, we ask
156 the server for pointer motion hints. This means that we get only
157 one event per group of mouse movements. "Groups" are delimited by
158 other kinds of events (focus changes and button clicks, for
159 example), or by XQueryPointer calls; when one of these happens, we
160 get another MotionNotify event the next time the mouse moves. This
161 is at least as efficient as getting motion events when mouse
162 tracking is on, and I suspect only negligibly worse when tracking
165 /* Where the mouse was last time we reported a mouse event. */
167 static Rect last_mouse_glyph
;
168 static FRAME_PTR last_mouse_glyph_frame
;
170 /* The scroll bar in which the last X motion event occurred.
172 If the last X motion event occurred in a scroll bar, we set this so
173 XTmouse_position can know whether to report a scroll bar motion or
176 If the last X motion event didn't occur in a scroll bar, we set
177 this to Qnil, to tell XTmouse_position to return an ordinary motion
180 static Lisp_Object last_mouse_scroll_bar
;
182 /* This is a hack. We would really prefer that XTmouse_position would
183 return the time associated with the position it returns, but there
184 doesn't seem to be any way to wrest the time-stamp from the server
185 along with the position query. So, we just keep track of the time
186 of the last movement we received, and return that in hopes that
187 it's somewhat accurate. */
189 static Time last_mouse_movement_time
;
191 struct scroll_bar
*tracked_scroll_bar
= NULL
;
193 /* Incremented by XTread_socket whenever it really tries to read
197 static int volatile input_signal_count
;
199 static int input_signal_count
;
202 extern Lisp_Object Vsystem_name
;
204 extern Lisp_Object Qeql
;
206 /* A mask of extra modifier bits to put into every keyboard char. */
208 extern EMACS_INT extra_keyboard_modifiers
;
210 /* The keysyms to use for the various modifiers. */
212 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
214 extern int inhibit_window_system
;
216 #if __MRC__ && !TARGET_API_MAC_CARBON
217 QDGlobals qd
; /* QuickDraw global information structure. */
220 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
222 struct mac_display_info
*mac_display_info_for_display (Display
*);
223 static void x_update_window_end
P_ ((struct window
*, int, int));
224 int x_catch_errors
P_ ((Display
*));
225 void x_uncatch_errors
P_ ((Display
*, int));
226 void x_lower_frame
P_ ((struct frame
*));
227 void x_scroll_bar_clear
P_ ((struct frame
*));
228 int x_had_errors_p
P_ ((Display
*));
229 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
230 void x_raise_frame
P_ ((struct frame
*));
231 void x_set_window_size
P_ ((struct frame
*, int, int, int));
232 void x_wm_set_window_state
P_ ((struct frame
*, int));
233 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
234 void mac_initialize
P_ ((void));
235 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
236 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
237 static void x_update_end
P_ ((struct frame
*));
238 static void XTframe_up_to_date
P_ ((struct frame
*));
239 static void XTset_terminal_modes
P_ ((void));
240 static void XTreset_terminal_modes
P_ ((void));
241 static void x_clear_frame
P_ ((void));
242 static void frame_highlight
P_ ((struct frame
*));
243 static void frame_unhighlight
P_ ((struct frame
*));
244 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
245 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
246 struct frame
*, struct input_event
*));
247 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
249 struct input_event
*));
250 static void XTframe_rehighlight
P_ ((struct frame
*));
251 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
252 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
253 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
254 enum text_cursor_kinds
));
256 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
257 static void x_flush
P_ ((struct frame
*f
));
258 static void x_update_begin
P_ ((struct frame
*));
259 static void x_update_window_begin
P_ ((struct window
*));
260 static void x_after_update_window_line
P_ ((struct glyph_row
*));
261 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
262 enum scroll_bar_part
*,
263 Lisp_Object
*, Lisp_Object
*,
266 static int is_emacs_window
P_ ((WindowPtr
));
267 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
268 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
270 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
271 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
272 #define GC_FONT(gc) ((gc)->xgcv.font)
273 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
275 #define CG_SET_FILL_COLOR(context, color) \
276 CGContextSetRGBFillColor (context, \
277 RED_FROM_ULONG (color) / 255.0f, \
278 GREEN_FROM_ULONG (color) / 255.0f, \
279 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
280 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
281 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
282 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
284 if (CGColorGetTypeID != NULL) \
285 CGContextSetFillColorWithColor (context, cg_color); \
287 CG_SET_FILL_COLOR (context, color); \
290 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
291 CGContextSetFillColorWithColor (context, cg_color)
294 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
295 CG_SET_FILL_COLOR (context, color)
297 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
298 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
300 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
301 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
305 #define CG_SET_STROKE_COLOR(context, color) \
306 CGContextSetRGBStrokeColor (context, \
307 RED_FROM_ULONG (color) / 255.0f, \
308 GREEN_FROM_ULONG (color) / 255.0f, \
309 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
310 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
311 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
312 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
314 if (CGColorGetTypeID != NULL) \
315 CGContextSetStrokeColorWithColor (context, cg_color); \
317 CG_SET_STROKE_COLOR (context, color); \
320 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
321 CGContextSetStrokeColorWithColor (context, cg_color)
324 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
325 CG_SET_STROKE_COLOR (context, color)
327 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
328 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
332 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
334 /* Fringe bitmaps. */
336 static int max_fringe_bmp
= 0;
337 static CGImageRef
*fringe_bmp
= 0;
339 static CGColorSpaceRef mac_cg_color_space_rgb
;
340 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
341 static CGColorRef mac_cg_color_black
;
347 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
348 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
349 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
350 /* Don't check the availability of CGColorCreate; this symbol is
351 defined even in Mac OS X 10.1. */
352 if (CGColorGetTypeID
!= NULL
)
355 float rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
357 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
363 mac_begin_cg_clip (f
, gc
)
367 CGContextRef context
= FRAME_CG_CONTEXT (f
);
371 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
372 FRAME_CG_CONTEXT (f
) = context
;
375 CGContextSaveGState (context
);
376 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
377 CGContextScaleCTM (context
, 1, -1);
378 if (gc
&& gc
->n_clip_rects
)
379 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
388 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
392 mac_prepare_for_quickdraw (f
)
397 Lisp_Object rest
, frame
;
398 FOR_EACH_FRAME (rest
, frame
)
399 if (FRAME_MAC_P (XFRAME (frame
)))
400 mac_prepare_for_quickdraw (XFRAME (frame
));
404 CGContextRef context
= FRAME_CG_CONTEXT (f
);
408 CGContextSynchronize (context
);
409 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
410 &FRAME_CG_CONTEXT (f
));
416 static RgnHandle saved_port_clip_region
= NULL
;
422 static RgnHandle new_region
= NULL
;
424 if (saved_port_clip_region
== NULL
)
425 saved_port_clip_region
= NewRgn ();
426 if (new_region
== NULL
)
427 new_region
= NewRgn ();
429 if (gc
->n_clip_rects
)
431 GetClip (saved_port_clip_region
);
432 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
433 SetClip (new_region
);
441 if (gc
->n_clip_rects
)
442 SetClip (saved_port_clip_region
);
446 /* X display function emulation */
449 XFreePixmap (display
, pixmap
)
450 Display
*display
; /* not used */
453 DisposeGWorld (pixmap
);
457 /* Mac version of XDrawLine. */
460 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
466 CGContextRef context
;
467 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
470 gx1
+= 0.5f
, gx2
+= 0.5f
;
472 gy1
+= 0.5f
, gy2
+= 0.5f
;
474 context
= mac_begin_cg_clip (f
, gc
);
475 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
476 CGContextBeginPath (context
);
477 CGContextMoveToPoint (context
, gx1
, gy1
);
478 CGContextAddLineToPoint (context
, gx2
, gy2
);
479 CGContextClosePath (context
);
480 CGContextStrokePath (context
);
498 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
500 RGBForeColor (GC_FORE_COLOR (gc
));
509 /* Mac version of XDrawLine (to Pixmap). */
512 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
536 GetGWorld (&old_port
, &old_gdh
);
539 RGBForeColor (GC_FORE_COLOR (gc
));
541 LockPixels (GetGWorldPixMap (p
));
544 UnlockPixels (GetGWorldPixMap (p
));
546 SetGWorld (old_port
, old_gdh
);
551 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
555 unsigned int width
, height
;
558 CGContextRef context
;
560 context
= mac_begin_cg_clip (f
, gc
);
561 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
562 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
567 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
569 RGBBackColor (GC_BACK_COLOR (gc
));
570 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
576 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
581 /* Mac version of XClearArea. */
584 mac_clear_area (f
, x
, y
, width
, height
)
587 unsigned int width
, height
;
589 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
592 /* Mac version of XClearWindow. */
599 CGContextRef context
;
600 GC gc
= FRAME_NORMAL_GC (f
);
602 context
= mac_begin_cg_clip (f
, NULL
);
603 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
604 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
605 FRAME_PIXEL_HEIGHT (f
)));
608 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
610 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
612 #if TARGET_API_MAC_CARBON
616 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
619 #else /* not TARGET_API_MAC_CARBON */
620 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
621 #endif /* not TARGET_API_MAC_CARBON */
626 /* Mac replacement for XCopyArea. */
630 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
631 dest_x
, dest_y
, overlay_p
)
636 unsigned int width
, height
;
637 int dest_x
, dest_y
, overlay_p
;
639 CGContextRef context
;
640 float port_height
= FRAME_PIXEL_HEIGHT (f
);
641 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
643 context
= mac_begin_cg_clip (f
, gc
);
646 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
647 CGContextFillRect (context
, dest_rect
);
649 CGContextClipToRect (context
, dest_rect
);
650 CGContextScaleCTM (context
, 1, -1);
651 CGContextTranslateCTM (context
, 0, -port_height
);
652 if (CGImageIsMask (image
))
653 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
654 CGContextDrawImage (context
,
655 CGRectMake (dest_x
- src_x
,
656 port_height
- (dest_y
- src_y
657 + CGImageGetHeight (image
)),
658 CGImageGetWidth (image
),
659 CGImageGetHeight (image
)),
664 #else /* !USE_CG_DRAWING */
667 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
670 int x
, y
, width
, height
;
671 unsigned short *bits
;
677 bitmap
.rowBytes
= sizeof(unsigned short);
678 bitmap
.baseAddr
= (char *)bits
;
679 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
681 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
683 RGBForeColor (GC_FORE_COLOR (gc
));
684 RGBBackColor (GC_BACK_COLOR (gc
));
685 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
688 #if TARGET_API_MAC_CARBON
694 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
695 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
696 UnlockPortBits (port
);
698 #else /* not TARGET_API_MAC_CARBON */
699 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
700 overlay_p
? srcOr
: srcCopy
, 0);
701 #endif /* not TARGET_API_MAC_CARBON */
704 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
706 #endif /* !USE_CG_DRAWING */
709 /* Mac replacement for XCreateBitmapFromBitmapData. */
712 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
717 static const unsigned char swap_nibble
[16]
718 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
719 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
720 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
721 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
725 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
726 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
727 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
728 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
729 for (i
= 0; i
< h
; i
++)
731 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
732 for (j
= 0; j
< w1
; j
++)
734 /* Bitswap XBM bytes to match how Mac does things. */
735 unsigned char c
= *bits
++;
736 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
737 | (swap_nibble
[(c
>>4) & 0xf]));
741 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
746 mac_free_bitmap (bitmap
)
749 xfree (bitmap
->baseAddr
);
754 XCreatePixmap (display
, w
, width
, height
, depth
)
755 Display
*display
; /* not used */
757 unsigned int width
, height
;
764 SetPortWindowPort (w
);
766 SetRect (&r
, 0, 0, width
, height
);
767 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
770 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
771 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
773 /* CreateCGImageFromPixMaps requires ARGB format. */
774 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
783 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
784 Display
*display
; /* not used */
787 unsigned int width
, height
;
788 unsigned long fg
, bg
;
795 static GC gc
= NULL
; /* not reentrant */
798 gc
= XCreateGC (display
, w
, 0, NULL
);
800 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
804 GetGWorld (&old_port
, &old_gdh
);
805 SetGWorld (pixmap
, NULL
);
806 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
807 XSetForeground (display
, gc
, fg
);
808 XSetBackground (display
, gc
, bg
);
809 RGBForeColor (GC_FORE_COLOR (gc
));
810 RGBBackColor (GC_BACK_COLOR (gc
));
811 LockPixels (GetGWorldPixMap (pixmap
));
812 #if TARGET_API_MAC_CARBON
813 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
814 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
815 #else /* not TARGET_API_MAC_CARBON */
816 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
817 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
818 #endif /* not TARGET_API_MAC_CARBON */
819 UnlockPixels (GetGWorldPixMap (pixmap
));
820 SetGWorld (old_port
, old_gdh
);
821 mac_free_bitmap (&bitmap
);
827 /* Mac replacement for XFillRectangle. */
830 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
834 unsigned int width
, height
;
837 CGContextRef context
;
839 context
= mac_begin_cg_clip (f
, gc
);
840 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
841 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
846 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
848 RGBForeColor (GC_FORE_COLOR (gc
));
849 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
852 PaintRect (&r
); /* using foreground color of gc */
858 /* Mac replacement for XDrawRectangle: dest is a window. */
861 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
865 unsigned int width
, height
;
868 CGContextRef context
;
870 context
= mac_begin_cg_clip (f
, gc
);
871 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
872 CGContextStrokeRect (context
,
873 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
878 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
880 RGBForeColor (GC_FORE_COLOR (gc
));
881 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
884 FrameRect (&r
); /* using foreground color of gc */
892 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
893 ConstUniCharArrayPtr text
;
894 UniCharCount text_length
;
896 ATSUTextLayout
*text_layout
;
899 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
901 if (saved_text_layout
== NULL
)
903 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
904 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
905 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
906 static ATSLineLayoutOptions line_layout
=
907 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
908 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
909 | kATSLineUseQDRendering
911 kATSLineIsDisplayOnly
| kATSLineFractDisable
914 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
916 err
= ATSUCreateTextLayoutWithTextPtr (text
,
917 kATSUFromTextBeginning
,
923 err
= ATSUSetLayoutControls (saved_text_layout
,
924 sizeof (tags
) / sizeof (tags
[0]),
925 tags
, sizes
, values
);
926 /* XXX: Should we do this? */
928 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
932 err
= ATSUSetRunStyle (saved_text_layout
, style
,
933 kATSUFromTextBeginning
, kATSUToTextEnd
);
935 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
936 kATSUFromTextBeginning
,
942 *text_layout
= saved_text_layout
;
949 mac_invert_rectangle (f
, x
, y
, width
, height
)
952 unsigned int width
, height
;
957 mac_prepare_for_quickdraw (f
);
959 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
961 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
968 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
969 overstrike_p
, bytes_per_char
)
974 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
976 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
979 if (GC_FONT (gc
)->mac_style
)
982 ATSUTextLayout text_layout
;
984 xassert (bytes_per_char
== 2);
986 #ifndef WORDS_BIG_ENDIAN
989 UniChar
*text
= (UniChar
*)buf
;
991 for (i
= 0; i
< nchars
; i
++)
992 text
[i
] = EndianU16_BtoN (text
[i
]);
995 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
997 GC_FONT (gc
)->mac_style
,
1002 if (!mac_use_core_graphics
)
1006 mac_prepare_for_quickdraw (f
);
1008 mac_begin_clip (gc
);
1009 RGBForeColor (GC_FORE_COLOR (gc
));
1014 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1015 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1016 RGBBackColor (GC_BACK_COLOR (gc
));
1018 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1021 ATSUDrawText (text_layout
,
1022 kATSUFromTextBeginning
, kATSUToTextEnd
,
1023 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1027 ATSUDrawText (text_layout
,
1028 kATSUFromTextBeginning
, kATSUToTextEnd
,
1029 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1037 static CGContextRef context
;
1038 float port_height
= FRAME_PIXEL_HEIGHT (f
);
1039 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1040 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1041 static const ATSUAttributeValuePtr values
[] = {&context
};
1044 context
= mac_begin_cg_clip (f
, gc
);
1047 QDBeginCGContext (port
, &context
);
1048 if (gc
->n_clip_rects
|| bg_width
)
1050 CGContextTranslateCTM (context
, 0, port_height
);
1051 CGContextScaleCTM (context
, 1, -1);
1052 if (gc
->n_clip_rects
)
1053 CGContextClipToRects (context
, gc
->clip_rects
,
1058 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1061 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
1062 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1064 CGContextScaleCTM (context
, 1, -1);
1065 CGContextTranslateCTM (context
, 0, -port_height
);
1069 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1070 err
= ATSUSetLayoutControls (text_layout
,
1071 sizeof (tags
) / sizeof (tags
[0]),
1072 tags
, sizes
, values
);
1075 ATSUDrawText (text_layout
,
1076 kATSUFromTextBeginning
, kATSUToTextEnd
,
1077 Long2Fix (x
), Long2Fix (port_height
- y
));
1079 ATSUDrawText (text_layout
,
1080 kATSUFromTextBeginning
, kATSUToTextEnd
,
1081 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1084 mac_end_cg_clip (f
);
1087 CGContextSynchronize (context
);
1088 QDEndCGContext (port
, &context
);
1091 /* This doesn't work on Mac OS X 10.1. */
1092 ATSUClearLayoutControls (text_layout
,
1093 sizeof (tags
) / sizeof (tags
[0]), tags
);
1095 ATSUSetLayoutControls (text_layout
,
1096 sizeof (tags
) / sizeof (tags
[0]),
1097 tags
, sizes
, values
);
1100 #endif /* MAC_OSX */
1103 #endif /* USE_ATSUI */
1105 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1108 if (mac_use_core_graphics
)
1109 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1112 mac_prepare_for_quickdraw (f
);
1114 mac_begin_clip (gc
);
1115 RGBForeColor (GC_FORE_COLOR (gc
));
1119 RGBBackColor (GC_BACK_COLOR (gc
));
1125 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1127 - Screen is double-buffered. (In srcCopy mode, a text is
1128 drawn into an offscreen graphics world first. So
1129 performance gain cannot be expected.)
1130 - It lowers rendering quality.
1131 - Some fonts leave garbage on cursor movement. */
1136 RGBBackColor (GC_BACK_COLOR (gc
));
1137 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1138 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1143 TextFont (GC_FONT (gc
)->mac_fontnum
);
1144 TextSize (GC_FONT (gc
)->mac_fontsize
);
1145 TextFace (GC_FONT (gc
)->mac_fontface
);
1147 DrawText (buf
, 0, nchars
* bytes_per_char
);
1152 DrawText (buf
, 0, nchars
* bytes_per_char
);
1155 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1158 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1159 if (mac_use_core_graphics
)
1160 SwapQDTextFlags(savedFlags
);
1166 /* Mac replacement for XDrawImageString. */
1169 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1174 int nchars
, bg_width
, overstrike_p
;
1176 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1181 /* Mac replacement for XDrawImageString16. */
1184 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1189 int nchars
, bg_width
, overstrike_p
;
1191 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1196 /* Mac replacement for XQueryTextExtents, but takes a character. If
1197 STYLE is NULL, measurement is done by QuickDraw Text routines for
1198 the font of the current graphics port. If CG_GLYPH is not NULL,
1199 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1202 mac_query_char_extents (style
, c
,
1203 font_ascent_return
, font_descent_return
,
1204 overall_return
, cg_glyph
)
1211 int *font_ascent_return
, *font_descent_return
;
1212 XCharStruct
*overall_return
;
1213 #if USE_CG_TEXT_DRAWING
1219 OSStatus err
= noErr
;
1226 ATSUTextLayout text_layout
;
1229 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1231 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1233 ATSTrapezoid glyph_bounds
;
1235 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1236 kATSUFromTextBeginning
, kATSUToTextEnd
,
1237 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1238 kATSUseFractionalOrigins
,
1240 kATSUseDeviceOrigins
,
1242 1, &glyph_bounds
, NULL
);
1245 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1246 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1248 width
= Fix2Long (glyph_bounds
.upperRight
.x
1249 - glyph_bounds
.upperLeft
.x
);
1250 if (font_ascent_return
)
1251 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1252 if (font_descent_return
)
1253 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1256 if (err
== noErr
&& overall_return
)
1258 err
= ATSUMeasureTextImage (text_layout
,
1259 kATSUFromTextBeginning
, kATSUToTextEnd
,
1260 0, 0, &char_bounds
);
1262 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1263 #if USE_CG_TEXT_DRAWING
1264 if (err
== noErr
&& cg_glyph
)
1267 ATSUGlyphInfoArray glyph_info_array
;
1268 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1270 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1271 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1273 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1274 kATSUToTextEnd
, &count
,
1277 /* Make sure that we don't have to make layout
1279 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1280 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1281 && glyph_info_array
.glyphs
[0].screenX
== 0)
1283 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1284 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1295 if (font_ascent_return
|| font_descent_return
)
1299 GetFontInfo (&font_info
);
1300 if (font_ascent_return
)
1301 *font_ascent_return
= font_info
.ascent
;
1302 if (font_descent_return
)
1303 *font_descent_return
= font_info
.descent
;
1309 width
= CharWidth (ch
);
1310 QDTextBounds (1, &ch
, &char_bounds
);
1311 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1319 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1322 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1323 XFontStruct
*font_struct
;
1326 XCharStruct
*overall_return
;
1329 short width
= 0, lbearing
= 0, rbearing
= 0;
1332 for (i
= 0; i
< nchars
; i
++)
1334 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1336 width
+= FONT_WIDTH (font_struct
);
1339 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1340 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1341 width
+= pcm
->width
;
1346 overall_return
->lbearing
= lbearing
;
1347 overall_return
->rbearing
= rbearing
;
1348 overall_return
->width
= width
;
1350 /* What's the meaning of the return value of XTextExtents16? */
1354 #if USE_CG_TEXT_DRAWING
1355 static int cg_text_anti_aliasing_threshold
= 8;
1358 init_cg_text_anti_aliasing_threshold ()
1364 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1365 kCFPreferencesCurrentApplication
,
1368 cg_text_anti_aliasing_threshold
= threshold
;
1372 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1377 int nchars
, bg_width
, overstrike_p
;
1380 float port_height
, gx
, gy
;
1382 CGContextRef context
;
1386 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1389 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1390 port_height
= FRAME_PIXEL_HEIGHT (f
);
1392 gy
= port_height
- y
;
1393 glyphs
= (CGGlyph
*)buf
;
1394 advances
= alloca (sizeof (CGSize
) * nchars
);
1395 if (advances
== NULL
)
1397 for (i
= 0; i
< nchars
; i
++)
1399 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1401 advances
[i
].width
= pcm
->width
;
1402 advances
[i
].height
= 0;
1403 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1408 context
= mac_begin_cg_clip (f
, gc
);
1410 QDBeginCGContext (port
, &context
);
1411 if (gc
->n_clip_rects
|| bg_width
)
1413 CGContextTranslateCTM (context
, 0, port_height
);
1414 CGContextScaleCTM (context
, 1, -1);
1415 if (gc
->n_clip_rects
)
1416 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1420 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1423 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1424 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1426 CGContextScaleCTM (context
, 1, -1);
1427 CGContextTranslateCTM (context
, 0, -port_height
);
1431 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1432 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1433 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1434 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1435 CGContextSetShouldAntialias (context
, false);
1436 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1437 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1438 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1441 CGContextSetTextPosition (context
, gx
, gy
);
1442 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1445 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1446 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1449 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1452 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1453 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1455 for (i
= 0; i
< nchars
; i
++)
1457 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1459 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1460 gx
+= advances
[i
].width
;
1465 mac_end_cg_clip (f
);
1467 CGContextSynchronize (context
);
1468 QDEndCGContext (port
, &context
);
1477 /* Mac replacement for XCopyArea: dest must be window. */
1480 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1485 unsigned int width
, height
;
1490 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1492 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1493 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1495 ForeColor (blackColor
);
1496 BackColor (whiteColor
);
1498 mac_begin_clip (gc
);
1499 LockPixels (GetGWorldPixMap (src
));
1500 #if TARGET_API_MAC_CARBON
1505 LockPortBits (port
);
1506 CopyBits (GetPortBitMapForCopyBits (src
),
1507 GetPortBitMapForCopyBits (port
),
1508 &src_r
, &dest_r
, srcCopy
, 0);
1509 UnlockPortBits (port
);
1511 #else /* not TARGET_API_MAC_CARBON */
1512 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1513 &src_r
, &dest_r
, srcCopy
, 0);
1514 #endif /* not TARGET_API_MAC_CARBON */
1515 UnlockPixels (GetGWorldPixMap (src
));
1518 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1523 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1524 width
, height
, dest_x
, dest_y
)
1529 unsigned int width
, height
;
1534 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1536 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1537 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1539 ForeColor (blackColor
);
1540 BackColor (whiteColor
);
1542 mac_begin_clip (gc
);
1543 LockPixels (GetGWorldPixMap (src
));
1544 LockPixels (GetGWorldPixMap (mask
));
1545 #if TARGET_API_MAC_CARBON
1550 LockPortBits (port
);
1551 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1552 GetPortBitMapForCopyBits (port
),
1553 &src_r
, &src_r
, &dest_r
);
1554 UnlockPortBits (port
);
1556 #else /* not TARGET_API_MAC_CARBON */
1557 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1558 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1559 #endif /* not TARGET_API_MAC_CARBON */
1560 UnlockPixels (GetGWorldPixMap (mask
));
1561 UnlockPixels (GetGWorldPixMap (src
));
1564 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1566 #endif /* !USE_CG_DRAWING */
1569 /* Mac replacement for XCopyArea: used only for scrolling. */
1572 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1576 unsigned int width
, height
;
1579 #if TARGET_API_MAC_CARBON
1581 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1583 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1585 mac_prepare_for_quickdraw (f
);
1587 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1588 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1589 kScrollWindowNoOptions
, dummy
);
1591 #else /* not TARGET_API_MAC_CARBON */
1593 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1597 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1598 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1600 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1601 color mapping in CopyBits. Otherwise, it will be slow. */
1602 ForeColor (blackColor
);
1603 BackColor (whiteColor
);
1604 mac_begin_clip (gc
);
1605 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1608 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1609 #endif /* not TARGET_API_MAC_CARBON */
1613 /* Mac replacement for XChangeGC. */
1616 XChangeGC (display
, gc
, mask
, xgcv
)
1622 if (mask
& GCForeground
)
1623 XSetForeground (display
, gc
, xgcv
->foreground
);
1624 if (mask
& GCBackground
)
1625 XSetBackground (display
, gc
, xgcv
->background
);
1627 XSetFont (display
, gc
, xgcv
->font
);
1631 /* Mac replacement for XCreateGC. */
1634 XCreateGC (display
, d
, mask
, xgcv
)
1640 GC gc
= xmalloc (sizeof (*gc
));
1642 bzero (gc
, sizeof (*gc
));
1643 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1644 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1645 if (CGColorGetTypeID
!= NULL
)
1648 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1649 CGColorRetain (gc
->cg_fore_color
);
1650 CGColorRetain (gc
->cg_back_color
);
1653 XChangeGC (display
, gc
, mask
, xgcv
);
1659 /* Used in xfaces.c. */
1662 XFreeGC (display
, gc
)
1666 if (gc
->clip_region
)
1667 DisposeRgn (gc
->clip_region
);
1668 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1669 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1670 if (CGColorGetTypeID
!= NULL
)
1673 CGColorRelease (gc
->cg_fore_color
);
1674 CGColorRelease (gc
->cg_back_color
);
1681 /* Mac replacement for XGetGCValues. */
1684 XGetGCValues (display
, gc
, mask
, xgcv
)
1690 if (mask
& GCForeground
)
1691 xgcv
->foreground
= gc
->xgcv
.foreground
;
1692 if (mask
& GCBackground
)
1693 xgcv
->background
= gc
->xgcv
.background
;
1695 xgcv
->font
= gc
->xgcv
.font
;
1699 /* Mac replacement for XSetForeground. */
1702 XSetForeground (display
, gc
, color
)
1705 unsigned long color
;
1707 if (gc
->xgcv
.foreground
!= color
)
1709 gc
->xgcv
.foreground
= color
;
1710 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1711 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1712 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1713 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1714 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1715 if (CGColorGetTypeID
!= NULL
)
1718 CGColorRelease (gc
->cg_fore_color
);
1721 gc
->cg_fore_color
= mac_cg_color_black
;
1722 CGColorRetain (gc
->cg_fore_color
);
1728 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1729 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1730 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1732 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1740 /* Mac replacement for XSetBackground. */
1743 XSetBackground (display
, gc
, color
)
1746 unsigned long color
;
1748 if (gc
->xgcv
.background
!= color
)
1750 gc
->xgcv
.background
= color
;
1751 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1752 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1753 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1754 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1755 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1756 if (CGColorGetTypeID
!= NULL
)
1759 CGColorRelease (gc
->cg_back_color
);
1762 gc
->cg_back_color
= mac_cg_color_black
;
1763 CGColorRetain (gc
->cg_back_color
);
1769 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1770 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1771 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1773 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1781 /* Mac replacement for XSetFont. */
1784 XSetFont (display
, gc
, font
)
1789 gc
->xgcv
.font
= font
;
1793 /* Mac replacement for XSetClipRectangles. */
1796 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1804 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1806 gc
->n_clip_rects
= n
;
1809 if (gc
->clip_region
== NULL
)
1810 gc
->clip_region
= NewRgn ();
1811 RectRgn (gc
->clip_region
, rectangles
);
1814 RgnHandle region
= NewRgn ();
1816 for (i
= 1; i
< n
; i
++)
1818 RectRgn (region
, rectangles
+ i
);
1819 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1821 DisposeRgn (region
);
1824 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1825 for (i
= 0; i
< n
; i
++)
1827 Rect
*rect
= rectangles
+ i
;
1829 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1830 rect
->right
- rect
->left
,
1831 rect
->bottom
- rect
->top
);
1837 /* Mac replacement for XSetClipMask. */
1840 mac_reset_clip_rectangles (display
, gc
)
1844 gc
->n_clip_rects
= 0;
1848 /* Mac replacement for XSetWindowBackground. */
1851 XSetWindowBackground (display
, w
, color
)
1854 unsigned long color
;
1856 #if !TARGET_API_MAC_CARBON
1857 AuxWinHandle aw_handle
;
1858 CTabHandle ctab_handle
;
1859 ColorSpecPtr ct_table
;
1864 bg_color
.red
= RED16_FROM_ULONG (color
);
1865 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1866 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1868 #if TARGET_API_MAC_CARBON
1869 SetWindowContentColor (w
, &bg_color
);
1871 if (GetAuxWin (w
, &aw_handle
))
1873 ctab_handle
= (*aw_handle
)->awCTable
;
1874 HandToHand ((Handle
*) &ctab_handle
);
1875 ct_table
= (*ctab_handle
)->ctTable
;
1876 ct_size
= (*ctab_handle
)->ctSize
;
1877 while (ct_size
> -1)
1879 if (ct_table
->value
== 0)
1881 ct_table
->rgb
= bg_color
;
1882 CTabChanged (ctab_handle
);
1883 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1891 /* Flush display of frame F, or of all frames if F is null. */
1897 #if TARGET_API_MAC_CARBON
1900 mac_prepare_for_quickdraw (f
);
1903 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1905 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1911 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1912 Calls to XFlush should be unnecessary because the X output buffer
1913 is flushed automatically as needed by calls to XPending,
1914 XNextEvent, or XWindowEvent according to the XFlush man page.
1915 XTread_socket calls XPending. Removing XFlush improves
1918 #define XFlush(DISPLAY) (void) 0
1922 mac_flush_display_optional (f
)
1926 mac_prepare_for_quickdraw (f
);
1931 /***********************************************************************
1932 Starting and ending an update
1933 ***********************************************************************/
1935 /* Start an update of frame F. This function is installed as a hook
1936 for update_begin, i.e. it is called when update_begin is called.
1937 This function is called prior to calls to x_update_window_begin for
1938 each window being updated. */
1944 #if TARGET_API_MAC_CARBON
1945 /* During update of a frame, availability of input events is
1946 periodically checked with ReceiveNextEvent if
1947 redisplay-dont-pause is nil. That normally flushes window buffer
1948 changes for every check, and thus screen update looks waving even
1949 if no input is available. So we disable screen updates during
1950 update of a frame. */
1952 DisableScreenUpdates ();
1958 /* Start update of window W. Set the global variable updated_window
1959 to the window being updated and set output_cursor to the cursor
1963 x_update_window_begin (w
)
1966 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1967 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1970 set_output_cursor (&w
->cursor
);
1974 if (f
== display_info
->mouse_face_mouse_frame
)
1976 /* Don't do highlighting for mouse motion during the update. */
1977 display_info
->mouse_face_defer
= 1;
1979 /* If F needs to be redrawn, simply forget about any prior mouse
1981 if (FRAME_GARBAGED_P (f
))
1982 display_info
->mouse_face_window
= Qnil
;
1984 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1985 their mouse_face_p flag set, which means that they are always
1986 unequal to rows in a desired matrix which never have that
1987 flag set. So, rows containing mouse-face glyphs are never
1988 scrolled, and we don't have to switch the mouse highlight off
1989 here to prevent it from being scrolled. */
1991 /* Can we tell that this update does not affect the window
1992 where the mouse highlight is? If so, no need to turn off.
1993 Likewise, don't do anything if the frame is garbaged;
1994 in that case, the frame's current matrix that we would use
1995 is all wrong, and we will redisplay that line anyway. */
1996 if (!NILP (display_info
->mouse_face_window
)
1997 && w
== XWINDOW (display_info
->mouse_face_window
))
2001 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2002 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2005 if (i
< w
->desired_matrix
->nrows
)
2006 clear_mouse_face (display_info
);
2015 /* Draw a vertical window border from (x,y0) to (x,y1) */
2018 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2022 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2025 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2027 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2030 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2033 /* End update of window W (which is equal to updated_window).
2035 Draw vertical borders between horizontally adjacent windows, and
2036 display W's cursor if CURSOR_ON_P is non-zero.
2038 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2039 glyphs in mouse-face were overwritten. In that case we have to
2040 make sure that the mouse-highlight is properly redrawn.
2042 W may be a menu bar pseudo-window in case we don't have X toolkit
2043 support. Such windows don't have a cursor, so don't display it
2047 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2049 int cursor_on_p
, mouse_face_overwritten_p
;
2051 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2053 if (!w
->pseudo_window_p
)
2058 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2060 output_cursor
.x
, output_cursor
.y
);
2062 if (draw_window_fringes (w
, 1))
2063 x_draw_vertical_border (w
);
2068 /* If a row with mouse-face was overwritten, arrange for
2069 XTframe_up_to_date to redisplay the mouse highlight. */
2070 if (mouse_face_overwritten_p
)
2072 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2073 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2074 dpyinfo
->mouse_face_window
= Qnil
;
2077 updated_window
= NULL
;
2081 /* End update of frame F. This function is installed as a hook in
2088 /* Mouse highlight may be displayed again. */
2089 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2092 #if TARGET_API_MAC_CARBON
2093 EnableScreenUpdates ();
2095 XFlush (FRAME_MAC_DISPLAY (f
));
2100 /* This function is called from various places in xdisp.c whenever a
2101 complete update has been performed. The global variable
2102 updated_window is not available here. */
2105 XTframe_up_to_date (f
)
2108 if (FRAME_MAC_P (f
))
2110 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2112 if (dpyinfo
->mouse_face_deferred_gc
2113 || f
== dpyinfo
->mouse_face_mouse_frame
)
2116 if (dpyinfo
->mouse_face_mouse_frame
)
2117 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2118 dpyinfo
->mouse_face_mouse_x
,
2119 dpyinfo
->mouse_face_mouse_y
);
2120 dpyinfo
->mouse_face_deferred_gc
= 0;
2127 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2128 arrow bitmaps, or clear the fringes if no bitmaps are required
2129 before DESIRED_ROW is made current. The window being updated is
2130 found in updated_window. This function is called from
2131 update_window_line only if it is known that there are differences
2132 between bitmaps to be drawn between current row and DESIRED_ROW. */
2135 x_after_update_window_line (desired_row
)
2136 struct glyph_row
*desired_row
;
2138 struct window
*w
= updated_window
;
2144 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2145 desired_row
->redraw_fringe_bitmaps_p
= 1;
2147 /* When a window has disappeared, make sure that no rest of
2148 full-width rows stays visible in the internal border. Could
2149 check here if updated_window is the leftmost/rightmost window,
2150 but I guess it's not worth doing since vertically split windows
2151 are almost never used, internal border is rarely set, and the
2152 overhead is very small. */
2153 if (windows_or_buffers_changed
2154 && desired_row
->full_width_p
2155 && (f
= XFRAME (w
->frame
),
2156 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2158 && (height
= desired_row
->visible_height
,
2161 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2163 /* Internal border is drawn below the tool bar. */
2164 if (WINDOWP (f
->tool_bar_window
)
2165 && w
== XWINDOW (f
->tool_bar_window
))
2169 mac_clear_area (f
, 0, y
, width
, height
);
2170 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2176 /* Draw the bitmap WHICH in one of the left or right fringes of
2177 window W. ROW is the glyph row for which to display the bitmap; it
2178 determines the vertical position at which the bitmap has to be
2182 x_draw_fringe_bitmap (w
, row
, p
)
2184 struct glyph_row
*row
;
2185 struct draw_fringe_bitmap_params
*p
;
2187 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2188 Display
*display
= FRAME_MAC_DISPLAY (f
);
2189 struct face
*face
= p
->face
;
2192 /* Must clip because of partially visible lines. */
2193 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2196 /* Adjust position of "bottom aligned" bitmap on partially
2197 visible last row. */
2199 int oldVH
= row
->visible_height
;
2200 row
->visible_height
= p
->h
;
2201 row
->y
-= rowY
- p
->y
;
2202 x_clip_to_row (w
, row
, -1, face
->gc
);
2204 row
->visible_height
= oldVH
;
2207 x_clip_to_row (w
, row
, -1, face
->gc
);
2209 if (p
->bx
>= 0 && !p
->overlay_p
)
2211 #if 0 /* MAC_TODO: stipple */
2212 /* In case the same realized face is used for fringes and
2213 for something displayed in the text (e.g. face `region' on
2214 mono-displays, the fill style may have been changed to
2215 FillSolid in x_draw_glyph_string_background. */
2217 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2219 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2222 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2224 #if 0 /* MAC_TODO: stipple */
2226 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2232 && p
->which
< max_fringe_bmp
2238 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2239 XSetForeground (display
, face
->gc
,
2241 ? (p
->overlay_p
? face
->background
2242 : f
->output_data
.mac
->cursor_pixel
)
2243 : face
->foreground
));
2245 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2246 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
2248 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2249 p
->wd
, p
->h
, p
->bits
+ p
->dh
, p
->overlay_p
);
2251 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2254 mac_reset_clip_rectangles (display
, face
->gc
);
2259 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2261 unsigned short *bits
;
2265 CGDataProviderRef provider
;
2267 if (which
>= max_fringe_bmp
)
2270 max_fringe_bmp
= which
+ 20;
2271 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2272 while (i
< max_fringe_bmp
)
2273 fringe_bmp
[i
++] = 0;
2276 for (i
= 0; i
< h
; i
++)
2281 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2282 sizeof (unsigned short) * h
, NULL
);
2285 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2286 sizeof (unsigned short),
2288 CGDataProviderRelease (provider
);
2295 mac_destroy_fringe_bitmap (which
)
2298 if (which
>= max_fringe_bmp
)
2301 if (fringe_bmp
[which
])
2304 CGImageRelease (fringe_bmp
[which
]);
2307 fringe_bmp
[which
] = 0;
2312 /* This is called when starting Emacs and when restarting after
2313 suspend. When starting Emacs, no window is mapped. And nothing
2314 must be done to Emacs's own window if it is suspended (though that
2318 XTset_terminal_modes ()
2322 /* This is called when exiting or suspending Emacs. Exiting will make
2323 the windows go away, and suspending requires no action. */
2326 XTreset_terminal_modes ()
2332 /***********************************************************************
2334 ***********************************************************************/
2336 /* Function prototypes of this page. */
2338 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2339 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2343 pcm_init (pcm
, count
)
2347 bzero (pcm
, sizeof (XCharStruct
) * count
);
2348 while (--count
>= 0)
2350 pcm
->descent
= PCM_INVALID
;
2355 static enum pcm_status
2356 pcm_get_status (pcm
)
2357 const XCharStruct
*pcm
;
2359 int height
= pcm
->ascent
+ pcm
->descent
;
2361 /* Negative height means some special status. */
2362 return height
>= 0 ? PCM_VALID
: height
;
2365 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2366 is not contained in the font. */
2368 static INLINE XCharStruct
*
2369 x_per_char_metric (font
, char2b
)
2373 /* The result metric information. */
2374 XCharStruct
*pcm
= NULL
;
2376 xassert (font
&& char2b
);
2379 if (font
->mac_style
)
2381 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2385 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2386 pcm_init (*row
, 0x100);
2388 pcm
= *row
+ char2b
->byte2
;
2389 if (pcm_get_status (pcm
) != PCM_VALID
)
2392 mac_query_char_extents (font
->mac_style
,
2393 (char2b
->byte1
<< 8) + char2b
->byte2
,
2394 NULL
, NULL
, pcm
, NULL
);
2401 if (font
->bounds
.per_char
!= NULL
)
2403 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2405 /* min_char_or_byte2 specifies the linear character index
2406 corresponding to the first element of the per_char array,
2407 max_char_or_byte2 is the index of the last character. A
2408 character with non-zero CHAR2B->byte1 is not in the font.
2409 A character with byte2 less than min_char_or_byte2 or
2410 greater max_char_or_byte2 is not in the font. */
2411 if (char2b
->byte1
== 0
2412 && char2b
->byte2
>= font
->min_char_or_byte2
2413 && char2b
->byte2
<= font
->max_char_or_byte2
)
2414 pcm
= font
->bounds
.per_char
2415 + (char2b
->byte2
- font
->min_char_or_byte2
);
2419 /* If either min_byte1 or max_byte1 are nonzero, both
2420 min_char_or_byte2 and max_char_or_byte2 are less than
2421 256, and the 2-byte character index values corresponding
2422 to the per_char array element N (counting from 0) are:
2424 byte1 = N/D + min_byte1
2425 byte2 = N\D + min_char_or_byte2
2429 D = max_char_or_byte2 - min_char_or_byte2 + 1
2430 / = integer division
2431 \ = integer modulus */
2432 if (char2b
->byte1
>= font
->min_byte1
2433 && char2b
->byte1
<= font
->max_byte1
2434 && char2b
->byte2
>= font
->min_char_or_byte2
2435 && char2b
->byte2
<= font
->max_char_or_byte2
)
2437 pcm
= (font
->bounds
.per_char
2438 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2439 * (char2b
->byte1
- font
->min_byte1
))
2440 + (char2b
->byte2
- font
->min_char_or_byte2
));
2446 /* If the per_char pointer is null, all glyphs between the first
2447 and last character indexes inclusive have the same
2448 information, as given by both min_bounds and max_bounds. */
2449 if (char2b
->byte2
>= font
->min_char_or_byte2
2450 && char2b
->byte2
<= font
->max_char_or_byte2
)
2451 pcm
= &font
->max_bounds
;
2457 return ((pcm
== NULL
2459 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2460 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2469 static XCharStruct
*
2470 mac_per_char_metric (font
, char2b
, font_type
)
2475 return x_per_char_metric (font
, char2b
);
2479 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2480 the two-byte form of C. Encoding is returned in *CHAR2B. */
2483 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2486 struct font_info
*font_info
;
2489 int charset
= CHAR_CHARSET (c
);
2490 XFontStruct
*font
= font_info
->font
;
2492 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2493 This may be either a program in a special encoder language or a
2495 if (font_info
->font_encoder
)
2497 /* It's a program. */
2498 struct ccl_program
*ccl
= font_info
->font_encoder
;
2500 check_ccl_update (ccl
);
2501 if (CHARSET_DIMENSION (charset
) == 1)
2503 ccl
->reg
[0] = charset
;
2504 ccl
->reg
[1] = char2b
->byte2
;
2509 ccl
->reg
[0] = charset
;
2510 ccl
->reg
[1] = char2b
->byte1
;
2511 ccl
->reg
[2] = char2b
->byte2
;
2514 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2516 /* We assume that MSBs are appropriately set/reset by CCL
2518 if (font
->max_byte1
== 0) /* 1-byte font */
2519 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2521 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2523 else if (font_info
->encoding
[charset
])
2525 /* Fixed encoding scheme. See fontset.h for the meaning of the
2526 encoding numbers. */
2527 int enc
= font_info
->encoding
[charset
];
2529 if ((enc
== 1 || enc
== 2)
2530 && CHARSET_DIMENSION (charset
) == 2)
2531 char2b
->byte1
|= 0x80;
2533 if (enc
== 1 || enc
== 3)
2534 char2b
->byte2
|= 0x80;
2540 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2541 char2b
->byte1
= sjis1
;
2542 char2b
->byte2
= sjis2
;
2547 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2549 return FONT_TYPE_UNKNOWN
;
2554 /***********************************************************************
2556 ***********************************************************************/
2560 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2561 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2562 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2564 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2565 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2566 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2567 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2568 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2569 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2570 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2571 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2572 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2573 unsigned long *, double, int));*/
2574 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2575 double, int, unsigned long));
2576 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2577 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2578 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2579 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2580 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2582 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2583 int, int, int, int, int, int,
2585 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2586 int, int, int, Rect
*));
2589 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2593 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2598 struct glyph_string
*s
;
2600 if (s
->font
== FRAME_FONT (s
->f
)
2601 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2602 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2604 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2607 /* Cursor on non-default face: must merge. */
2611 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2612 xgcv
.foreground
= s
->face
->background
;
2614 /* If the glyph would be invisible, try a different foreground. */
2615 if (xgcv
.foreground
== xgcv
.background
)
2616 xgcv
.foreground
= s
->face
->foreground
;
2617 if (xgcv
.foreground
== xgcv
.background
)
2618 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2619 if (xgcv
.foreground
== xgcv
.background
)
2620 xgcv
.foreground
= s
->face
->foreground
;
2622 /* Make sure the cursor is distinct from text in this face. */
2623 if (xgcv
.background
== s
->face
->background
2624 && xgcv
.foreground
== s
->face
->foreground
)
2626 xgcv
.background
= s
->face
->foreground
;
2627 xgcv
.foreground
= s
->face
->background
;
2630 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2631 xgcv
.font
= s
->font
;
2632 mask
= GCForeground
| GCBackground
| GCFont
;
2634 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2635 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2638 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2639 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2641 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2646 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2649 x_set_mouse_face_gc (s
)
2650 struct glyph_string
*s
;
2655 /* What face has to be used last for the mouse face? */
2656 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2657 face
= FACE_FROM_ID (s
->f
, face_id
);
2659 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2661 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2662 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2664 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2665 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2666 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2668 /* If font in this face is same as S->font, use it. */
2669 if (s
->font
== s
->face
->font
)
2670 s
->gc
= s
->face
->gc
;
2673 /* Otherwise construct scratch_cursor_gc with values from FACE
2678 xgcv
.background
= s
->face
->background
;
2679 xgcv
.foreground
= s
->face
->foreground
;
2680 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2681 xgcv
.font
= s
->font
;
2682 mask
= GCForeground
| GCBackground
| GCFont
;
2684 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2685 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2688 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2689 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2691 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2694 xassert (s
->gc
!= 0);
2698 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2699 Faces to use in the mode line have already been computed when the
2700 matrix was built, so there isn't much to do, here. */
2703 x_set_mode_line_face_gc (s
)
2704 struct glyph_string
*s
;
2706 s
->gc
= s
->face
->gc
;
2710 /* Set S->gc of glyph string S for drawing that glyph string. Set
2711 S->stippled_p to a non-zero value if the face of S has a stipple
2715 x_set_glyph_string_gc (s
)
2716 struct glyph_string
*s
;
2718 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2720 if (s
->hl
== DRAW_NORMAL_TEXT
)
2722 s
->gc
= s
->face
->gc
;
2723 s
->stippled_p
= s
->face
->stipple
!= 0;
2725 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2727 x_set_mode_line_face_gc (s
);
2728 s
->stippled_p
= s
->face
->stipple
!= 0;
2730 else if (s
->hl
== DRAW_CURSOR
)
2732 x_set_cursor_gc (s
);
2735 else if (s
->hl
== DRAW_MOUSE_FACE
)
2737 x_set_mouse_face_gc (s
);
2738 s
->stippled_p
= s
->face
->stipple
!= 0;
2740 else if (s
->hl
== DRAW_IMAGE_RAISED
2741 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2743 s
->gc
= s
->face
->gc
;
2744 s
->stippled_p
= s
->face
->stipple
!= 0;
2748 s
->gc
= s
->face
->gc
;
2749 s
->stippled_p
= s
->face
->stipple
!= 0;
2752 /* GC must have been set. */
2753 xassert (s
->gc
!= 0);
2757 /* Set clipping for output of glyph string S. S may be part of a mode
2758 line or menu if we don't have X toolkit support. */
2761 x_set_glyph_string_clipping (s
)
2762 struct glyph_string
*s
;
2764 Rect rects
[MAX_CLIP_RECTS
];
2767 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2768 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2773 Compute left and right overhang of glyph string S. If S is a glyph
2774 string for a composition, assume overhangs don't exist. */
2777 mac_compute_glyph_string_overhangs (s
)
2778 struct glyph_string
*s
;
2780 if (!(s
->cmp
== NULL
2781 && s
->first_glyph
->type
== CHAR_GLYPH
))
2786 || s
->font
->mac_style
2792 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2793 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2794 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2799 MacFontStruct
*font
= s
->font
;
2802 mac_prepare_for_quickdraw (s
->f
);
2804 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2806 TextFont (font
->mac_fontnum
);
2807 TextSize (font
->mac_fontsize
);
2808 TextFace (font
->mac_fontface
);
2810 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2812 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2813 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2818 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2821 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2822 struct glyph_string
*s
;
2825 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2829 /* Draw the background of glyph_string S. If S->background_filled_p
2830 is non-zero don't draw it. FORCE_P non-zero means draw the
2831 background even if it wouldn't be drawn normally. This is used
2832 when a string preceding S draws into the background of S, or S
2833 contains the first component of a composition. */
2836 x_draw_glyph_string_background (s
, force_p
)
2837 struct glyph_string
*s
;
2840 /* Nothing to do if background has already been drawn or if it
2841 shouldn't be drawn in the first place. */
2842 if (!s
->background_filled_p
)
2844 int box_line_width
= max (s
->face
->box_line_width
, 0);
2846 #if 0 /* MAC_TODO: stipple */
2849 /* Fill background with a stipple pattern. */
2850 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2851 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2852 s
->y
+ box_line_width
,
2853 s
->background_width
,
2854 s
->height
- 2 * box_line_width
);
2855 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2856 s
->background_filled_p
= 1;
2860 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2861 || s
->font_not_found_p
2862 || s
->extends_to_end_of_line_p
2865 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2866 s
->background_width
,
2867 s
->height
- 2 * box_line_width
);
2868 s
->background_filled_p
= 1;
2874 /* Draw the foreground of glyph string S. */
2877 x_draw_glyph_string_foreground (s
)
2878 struct glyph_string
*s
;
2882 /* If first glyph of S has a left box line, start drawing the text
2883 of S to the right of that box line. */
2884 if (s
->face
->box
!= FACE_NO_BOX
2885 && s
->first_glyph
->left_box_line_p
)
2886 x
= s
->x
+ abs (s
->face
->box_line_width
);
2890 /* Draw characters of S as rectangles if S's font could not be
2892 if (s
->font_not_found_p
)
2894 for (i
= 0; i
< s
->nchars
; ++i
)
2896 struct glyph
*g
= s
->first_glyph
+ i
;
2897 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2898 g
->pixel_width
- 1, s
->height
- 1);
2899 x
+= g
->pixel_width
;
2904 char *char1b
= (char *) s
->char2b
;
2905 int boff
= s
->font_info
->baseline_offset
;
2907 if (s
->font_info
->vertical_centering
)
2908 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2910 /* If we can use 8-bit functions, condense S->char2b. */
2913 && GC_FONT (s
->gc
)->mac_style
== NULL
2916 for (i
= 0; i
< s
->nchars
; ++i
)
2917 char1b
[i
] = s
->char2b
[i
].byte2
;
2919 /* Draw text with XDrawString if background has already been
2920 filled. Otherwise, use XDrawImageString. (Note that
2921 XDrawImageString is usually faster than XDrawString.) Always
2922 use XDrawImageString when drawing the cursor so that there is
2923 no chance that characters under a box cursor are invisible. */
2925 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2926 bg_width
= 0; /* Corresponds to XDrawString. */
2928 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2932 || GC_FONT (s
->gc
)->mac_style
2935 #if USE_CG_TEXT_DRAWING
2937 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2938 s
->char2b
, s
->nchars
, bg_width
,
2939 s
->face
->overstrike
))
2943 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2944 s
->char2b
, s
->nchars
, bg_width
,
2945 s
->face
->overstrike
);
2947 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2948 char1b
, s
->nchars
, bg_width
,
2949 s
->face
->overstrike
);
2953 /* Draw the foreground of composite glyph string S. */
2956 x_draw_composite_glyph_string_foreground (s
)
2957 struct glyph_string
*s
;
2961 /* If first glyph of S has a left box line, start drawing the text
2962 of S to the right of that box line. */
2963 if (s
->face
->box
!= FACE_NO_BOX
2964 && s
->first_glyph
->left_box_line_p
)
2965 x
= s
->x
+ abs (s
->face
->box_line_width
);
2969 /* S is a glyph string for a composition. S->gidx is the index of
2970 the first character drawn for glyphs of this composition.
2971 S->gidx == 0 means we are drawing the very first character of
2972 this composition. */
2974 /* Draw a rectangle for the composition if the font for the very
2975 first character of the composition could not be loaded. */
2976 if (s
->font_not_found_p
)
2979 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2980 s
->width
- 1, s
->height
- 1);
2984 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2985 if (mac_per_char_metric (GC_FONT (s
->gc
), s
->char2b
+ i
, 0) == NULL
)
2986 /* This is a nonexistent or zero-width glyph such as a
2987 combining diacritic. Draw a rectangle. */
2988 mac_draw_rectangle (s
->f
, s
->gc
,
2989 x
+ s
->cmp
->offsets
[s
->gidx
* 2], s
->y
,
2990 FONT_WIDTH (GC_FONT (s
->gc
)) - 1, s
->height
- 1);
2992 mac_draw_image_string_16 (s
->f
, s
->gc
,
2993 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2994 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2995 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3000 #ifdef USE_X_TOOLKIT
3002 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3005 /* Return the frame on which widget WIDGET is used.. Abort if frame
3006 cannot be determined. */
3008 static struct frame
*
3009 x_frame_of_widget (widget
)
3012 struct x_display_info
*dpyinfo
;
3016 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3018 /* Find the top-level shell of the widget. Note that this function
3019 can be called when the widget is not yet realized, so XtWindow
3020 (widget) == 0. That's the reason we can't simply use
3021 x_any_window_to_frame. */
3022 while (!XtIsTopLevelShell (widget
))
3023 widget
= XtParent (widget
);
3025 /* Look for a frame with that top-level widget. Allocate the color
3026 on that frame to get the right gamma correction value. */
3027 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3028 if (GC_FRAMEP (XCAR (tail
))
3029 && (f
= XFRAME (XCAR (tail
)),
3030 (f
->output_data
.nothing
!= 1
3031 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3032 && f
->output_data
.x
->widget
== widget
)
3039 /* Allocate the color COLOR->pixel on the screen and display of
3040 widget WIDGET in colormap CMAP. If an exact match cannot be
3041 allocated, try the nearest color available. Value is non-zero
3042 if successful. This is called from lwlib. */
3045 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3050 struct frame
*f
= x_frame_of_widget (widget
);
3051 return x_alloc_nearest_color (f
, cmap
, color
);
3055 #endif /* USE_X_TOOLKIT */
3057 #if 0 /* MAC_TODO */
3059 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3060 CMAP. If an exact match can't be allocated, try the nearest color
3061 available. Value is non-zero if successful. Set *COLOR to the
3065 x_alloc_nearest_color (f
, cmap
, color
)
3070 Display
*display
= FRAME_X_DISPLAY (f
);
3071 Screen
*screen
= FRAME_X_SCREEN (f
);
3074 gamma_correct (f
, color
);
3075 rc
= XAllocColor (display
, cmap
, color
);
3078 /* If we got to this point, the colormap is full, so we're going
3079 to try to get the next closest color. The algorithm used is
3080 a least-squares matching, which is what X uses for closest
3081 color matching with StaticColor visuals. */
3083 unsigned long nearest_delta
= ~0;
3084 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3085 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3087 for (i
= 0; i
< ncells
; ++i
)
3089 XQueryColors (display
, cmap
, cells
, ncells
);
3091 for (nearest
= i
= 0; i
< ncells
; ++i
)
3093 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3094 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3095 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3096 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3098 if (delta
< nearest_delta
)
3101 nearest_delta
= delta
;
3105 color
->red
= cells
[nearest
].red
;
3106 color
->green
= cells
[nearest
].green
;
3107 color
->blue
= cells
[nearest
].blue
;
3108 rc
= XAllocColor (display
, cmap
, color
);
3111 #ifdef DEBUG_X_COLORS
3113 register_color (color
->pixel
);
3114 #endif /* DEBUG_X_COLORS */
3120 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3121 It's necessary to do this instead of just using PIXEL directly to
3122 get color reference counts right. */
3125 x_copy_color (f
, pixel
)
3127 unsigned long pixel
;
3131 color
.pixel
= pixel
;
3133 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3134 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3136 #ifdef DEBUG_X_COLORS
3137 register_color (pixel
);
3143 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3144 It's necessary to do this instead of just using PIXEL directly to
3145 get color reference counts right. */
3148 x_copy_dpy_color (dpy
, cmap
, pixel
)
3151 unsigned long pixel
;
3155 color
.pixel
= pixel
;
3157 XQueryColor (dpy
, cmap
, &color
);
3158 XAllocColor (dpy
, cmap
, &color
);
3160 #ifdef DEBUG_X_COLORS
3161 register_color (pixel
);
3166 #endif /* MAC_TODO */
3169 /* Brightness beyond which a color won't have its highlight brightness
3172 Nominally, highlight colors for `3d' faces are calculated by
3173 brightening an object's color by a constant scale factor, but this
3174 doesn't yield good results for dark colors, so for colors who's
3175 brightness is less than this value (on a scale of 0-255) have to
3176 use an additional additive factor.
3178 The value here is set so that the default menu-bar/mode-line color
3179 (grey75) will not have its highlights changed at all. */
3180 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3183 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3184 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3185 If this produces the same color as COLOR, try a color where all RGB
3186 values have DELTA added. Return the allocated color in *COLOR.
3187 DISPLAY is the X display, CMAP is the colormap to operate on.
3188 Value is non-zero if successful. */
3191 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3193 unsigned long *color
;
3200 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3203 /* Change RGB values by specified FACTOR. Avoid overflow! */
3204 xassert (factor
>= 0);
3205 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3206 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3207 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3209 /* Calculate brightness of COLOR. */
3210 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3211 + BLUE_FROM_ULONG (*color
)) / 6;
3213 /* We only boost colors that are darker than
3214 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3215 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3216 /* Make an additive adjustment to NEW, because it's dark enough so
3217 that scaling by FACTOR alone isn't enough. */
3219 /* How far below the limit this color is (0 - 1, 1 being darker). */
3220 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3221 /* The additive adjustment. */
3222 int min_delta
= delta
* dimness
* factor
/ 2;
3225 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3226 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3227 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3229 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3230 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3231 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3235 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3236 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3237 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3239 /* MAC_TODO: Map to palette and retry with delta if same? */
3240 /* MAC_TODO: Free colors (if using palette)? */
3251 /* Set up the foreground color for drawing relief lines of glyph
3252 string S. RELIEF is a pointer to a struct relief containing the GC
3253 with which lines will be drawn. Use a color that is FACTOR or
3254 DELTA lighter or darker than the relief's background which is found
3255 in S->f->output_data.x->relief_background. If such a color cannot
3256 be allocated, use DEFAULT_PIXEL, instead. */
3259 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3261 struct relief
*relief
;
3264 unsigned long default_pixel
;
3267 struct mac_output
*di
= f
->output_data
.mac
;
3268 unsigned long mask
= GCForeground
;
3269 unsigned long pixel
;
3270 unsigned long background
= di
->relief_background
;
3271 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3273 /* MAC_TODO: Free colors (if using palette)? */
3275 /* Allocate new color. */
3276 xgcv
.foreground
= default_pixel
;
3278 if (dpyinfo
->n_planes
!= 1
3279 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3281 relief
->allocated_p
= 1;
3282 xgcv
.foreground
= relief
->pixel
= pixel
;
3285 if (relief
->gc
== 0)
3287 #if 0 /* MAC_TODO: stipple */
3288 xgcv
.stipple
= dpyinfo
->gray
;
3291 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3294 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3298 /* Set up colors for the relief lines around glyph string S. */
3301 x_setup_relief_colors (s
)
3302 struct glyph_string
*s
;
3304 struct mac_output
*di
= s
->f
->output_data
.mac
;
3305 unsigned long color
;
3307 if (s
->face
->use_box_color_for_shadows_p
)
3308 color
= s
->face
->box_color
;
3309 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3311 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3312 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3317 /* Get the background color of the face. */
3318 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3319 color
= xgcv
.background
;
3322 if (di
->white_relief
.gc
== 0
3323 || color
!= di
->relief_background
)
3325 di
->relief_background
= color
;
3326 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3327 WHITE_PIX_DEFAULT (s
->f
));
3328 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3329 BLACK_PIX_DEFAULT (s
->f
));
3334 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3335 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3336 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3337 relief. LEFT_P non-zero means draw a relief on the left side of
3338 the rectangle. RIGHT_P non-zero means draw a relief on the right
3339 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3343 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3344 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3346 int left_x
, top_y
, right_x
, bottom_y
, width
;
3347 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3350 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3355 gc
= f
->output_data
.mac
->white_relief
.gc
;
3357 gc
= f
->output_data
.mac
->black_relief
.gc
;
3358 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3362 for (i
= 0; i
< width
; ++i
)
3363 mac_draw_line (f
, gc
,
3364 left_x
+ i
* left_p
, top_y
+ i
,
3365 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3369 for (i
= 0; i
< width
; ++i
)
3370 mac_draw_line (f
, gc
,
3371 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3373 mac_reset_clip_rectangles (dpy
, gc
);
3375 gc
= f
->output_data
.mac
->black_relief
.gc
;
3377 gc
= f
->output_data
.mac
->white_relief
.gc
;
3378 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3382 for (i
= 0; i
< width
; ++i
)
3383 mac_draw_line (f
, gc
,
3384 left_x
+ i
* left_p
, bottom_y
- i
,
3385 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3389 for (i
= 0; i
< width
; ++i
)
3390 mac_draw_line (f
, gc
,
3391 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3393 mac_reset_clip_rectangles (dpy
, gc
);
3397 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3398 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3399 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3400 left side of the rectangle. RIGHT_P non-zero means draw a line
3401 on the right side of the rectangle. CLIP_RECT is the clipping
3402 rectangle to use when drawing. */
3405 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3406 left_p
, right_p
, clip_rect
)
3407 struct glyph_string
*s
;
3408 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3413 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3414 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3415 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3418 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3419 right_x
- left_x
+ 1, width
);
3423 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3424 width
, bottom_y
- top_y
+ 1);
3427 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3428 right_x
- left_x
+ 1, width
);
3432 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3433 top_y
, width
, bottom_y
- top_y
+ 1);
3435 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3436 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3440 /* Draw a box around glyph string S. */
3443 x_draw_glyph_string_box (s
)
3444 struct glyph_string
*s
;
3446 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3447 int left_p
, right_p
;
3448 struct glyph
*last_glyph
;
3451 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3452 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3453 : window_box_right (s
->w
, s
->area
));
3455 /* The glyph that may have a right box line. */
3456 last_glyph
= (s
->cmp
|| s
->img
3458 : s
->first_glyph
+ s
->nchars
- 1);
3460 width
= abs (s
->face
->box_line_width
);
3461 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3463 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3465 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3467 bottom_y
= top_y
+ s
->height
- 1;
3469 left_p
= (s
->first_glyph
->left_box_line_p
3470 || (s
->hl
== DRAW_MOUSE_FACE
3472 || s
->prev
->hl
!= s
->hl
)));
3473 right_p
= (last_glyph
->right_box_line_p
3474 || (s
->hl
== DRAW_MOUSE_FACE
3476 || s
->next
->hl
!= s
->hl
)));
3478 get_glyph_string_clip_rect (s
, &clip_rect
);
3480 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3481 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3482 left_p
, right_p
, &clip_rect
);
3485 x_setup_relief_colors (s
);
3486 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3487 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3492 /* Draw foreground of image glyph string S. */
3495 x_draw_image_foreground (s
)
3496 struct glyph_string
*s
;
3499 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3501 /* If first glyph of S has a left box line, start drawing it to the
3502 right of that line. */
3503 if (s
->face
->box
!= FACE_NO_BOX
3504 && s
->first_glyph
->left_box_line_p
3506 x
+= abs (s
->face
->box_line_width
);
3508 /* If there is a margin around the image, adjust x- and y-position
3510 if (s
->slice
.x
== 0)
3511 x
+= s
->img
->hmargin
;
3512 if (s
->slice
.y
== 0)
3513 y
+= s
->img
->vmargin
;
3517 x_set_glyph_string_clipping (s
);
3520 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3521 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3522 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3526 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3527 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3528 s
->slice
.width
, s
->slice
.height
, x
, y
);
3535 mac_copy_area (s
->img
->pixmap
,
3536 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3537 s
->slice
.width
, s
->slice
.height
, x
, y
);
3540 /* When the image has a mask, we can expect that at
3541 least part of a mouse highlight or a block cursor will
3542 be visible. If the image doesn't have a mask, make
3543 a block cursor visible by drawing a rectangle around
3544 the image. I believe it's looking better if we do
3545 nothing here for mouse-face. */
3546 if (s
->hl
== DRAW_CURSOR
)
3548 int r
= s
->img
->relief
;
3550 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3551 s
->slice
.width
+ r
*2 - 1,
3552 s
->slice
.height
+ r
*2 - 1);
3557 /* Draw a rectangle if image could not be loaded. */
3558 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3559 s
->slice
.width
- 1, s
->slice
.height
- 1);
3563 /* Draw a relief around the image glyph string S. */
3566 x_draw_image_relief (s
)
3567 struct glyph_string
*s
;
3569 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3572 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3574 /* If first glyph of S has a left box line, start drawing it to the
3575 right of that line. */
3576 if (s
->face
->box
!= FACE_NO_BOX
3577 && s
->first_glyph
->left_box_line_p
3579 x
+= abs (s
->face
->box_line_width
);
3581 /* If there is a margin around the image, adjust x- and y-position
3583 if (s
->slice
.x
== 0)
3584 x
+= s
->img
->hmargin
;
3585 if (s
->slice
.y
== 0)
3586 y
+= s
->img
->vmargin
;
3588 if (s
->hl
== DRAW_IMAGE_SUNKEN
3589 || s
->hl
== DRAW_IMAGE_RAISED
)
3591 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3592 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3596 thick
= abs (s
->img
->relief
);
3597 raised_p
= s
->img
->relief
> 0;
3602 x1
= x
+ s
->slice
.width
+ thick
- 1;
3603 y1
= y
+ s
->slice
.height
+ thick
- 1;
3605 x_setup_relief_colors (s
);
3606 get_glyph_string_clip_rect (s
, &r
);
3607 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3609 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3611 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3616 /* Draw part of the background of glyph string S. X, Y, W, and H
3617 give the rectangle to draw. */
3620 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3621 struct glyph_string
*s
;
3624 #if 0 /* MAC_TODO: stipple */
3627 /* Fill background with a stipple pattern. */
3628 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3629 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3630 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3633 #endif /* MAC_TODO */
3634 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3638 /* Draw image glyph string S.
3641 s->x +-------------------------
3644 | +-------------------------
3647 | | +-------------------
3653 x_draw_image_glyph_string (s
)
3654 struct glyph_string
*s
;
3657 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3658 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3661 height
= s
->height
- 2 * box_line_vwidth
;
3664 /* Fill background with face under the image. Do it only if row is
3665 taller than image or if image has a clip mask to reduce
3667 s
->stippled_p
= s
->face
->stipple
!= 0;
3668 if (height
> s
->slice
.height
3672 || s
->img
->pixmap
== 0
3673 || s
->width
!= s
->background_width
)
3676 if (s
->first_glyph
->left_box_line_p
3678 x
+= box_line_hwidth
;
3681 if (s
->slice
.y
== 0)
3682 y
+= box_line_vwidth
;
3684 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3686 s
->background_filled_p
= 1;
3689 /* Draw the foreground. */
3690 x_draw_image_foreground (s
);
3692 /* If we must draw a relief around the image, do it. */
3694 || s
->hl
== DRAW_IMAGE_RAISED
3695 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3696 x_draw_image_relief (s
);
3700 /* Draw stretch glyph string S. */
3703 x_draw_stretch_glyph_string (s
)
3704 struct glyph_string
*s
;
3706 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3708 if (s
->hl
== DRAW_CURSOR
3709 && !x_stretch_cursor_p
)
3711 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3712 as wide as the stretch glyph. */
3713 int width
, background_width
= s
->background_width
;
3714 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3718 background_width
-= left_x
- x
;
3721 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3724 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3726 /* Clear rest using the GC of the original non-cursor face. */
3727 if (width
< background_width
)
3730 int w
= background_width
- width
, h
= s
->height
;
3735 if (s
->row
->mouse_face_p
3736 && cursor_in_mouse_face_p (s
->w
))
3738 x_set_mouse_face_gc (s
);
3744 get_glyph_string_clip_rect (s
, &r
);
3745 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3747 #if 0 /* MAC_TODO: stipple */
3748 if (s
->face
->stipple
)
3750 /* Fill background with a stipple pattern. */
3751 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3752 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3753 XSetFillStyle (s
->display
, gc
, FillSolid
);
3756 #endif /* MAC_TODO */
3757 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3760 else if (!s
->background_filled_p
)
3762 int background_width
= s
->background_width
;
3763 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3765 /* Don't draw into left margin, fringe or scrollbar area
3766 except for header line and mode line. */
3767 if (x
< left_x
&& !s
->row
->mode_line_p
)
3769 background_width
-= left_x
- x
;
3772 if (background_width
> 0)
3773 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3776 s
->background_filled_p
= 1;
3780 /* Draw glyph string S. */
3783 x_draw_glyph_string (s
)
3784 struct glyph_string
*s
;
3786 int relief_drawn_p
= 0;
3788 /* If S draws into the background of its successor that does not
3789 draw a cursor, draw the background of the successor first so that
3790 S can draw into it. This makes S->next use XDrawString instead
3791 of XDrawImageString. */
3792 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3793 && s
->next
->hl
!= DRAW_CURSOR
)
3795 xassert (s
->next
->img
== NULL
);
3796 x_set_glyph_string_gc (s
->next
);
3797 x_set_glyph_string_clipping (s
->next
);
3798 x_draw_glyph_string_background (s
->next
, 1);
3801 /* Set up S->gc, set clipping and draw S. */
3802 x_set_glyph_string_gc (s
);
3804 /* Draw relief (if any) in advance for char/composition so that the
3805 glyph string can be drawn over it. */
3806 if (!s
->for_overlaps
3807 && s
->face
->box
!= FACE_NO_BOX
3808 && (s
->first_glyph
->type
== CHAR_GLYPH
3809 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3812 x_set_glyph_string_clipping (s
);
3813 x_draw_glyph_string_background (s
, 1);
3814 x_draw_glyph_string_box (s
);
3815 x_set_glyph_string_clipping (s
);
3819 x_set_glyph_string_clipping (s
);
3821 switch (s
->first_glyph
->type
)
3824 x_draw_image_glyph_string (s
);
3828 x_draw_stretch_glyph_string (s
);
3832 if (s
->for_overlaps
)
3833 s
->background_filled_p
= 1;
3835 x_draw_glyph_string_background (s
, 0);
3836 x_draw_glyph_string_foreground (s
);
3839 case COMPOSITE_GLYPH
:
3840 if (s
->for_overlaps
|| s
->gidx
> 0)
3841 s
->background_filled_p
= 1;
3843 x_draw_glyph_string_background (s
, 1);
3844 x_draw_composite_glyph_string_foreground (s
);
3851 if (!s
->for_overlaps
)
3853 /* Draw underline. */
3854 if (s
->face
->underline_p
)
3856 unsigned long tem
, h
;
3860 /* Get the underline thickness. Default is 1 pixel. */
3861 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3865 y
= s
->y
+ s
->height
- h
;
3866 if (!x_underline_at_descent_line
)
3868 /* Get the underline position. This is the recommended
3869 vertical offset in pixels from the baseline to the top of
3870 the underline. This is a signed value according to the
3871 specs, and its default is
3873 ROUND ((maximum descent) / 2), with
3874 ROUND(x) = floor (x + 0.5) */
3877 if (x_use_underline_position_properties
3878 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3879 y
= s
->ybase
+ (long) tem
;
3883 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3886 if (s
->face
->underline_defaulted_p
)
3887 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3888 s
->background_width
, h
);
3892 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3893 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3894 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3895 s
->background_width
, h
);
3896 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3900 /* Draw overline. */
3901 if (s
->face
->overline_p
)
3903 unsigned long dy
= 0, h
= 1;
3905 if (s
->face
->overline_color_defaulted_p
)
3906 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3907 s
->background_width
, h
);
3911 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3912 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3913 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3914 s
->background_width
, h
);
3915 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3919 /* Draw strike-through. */
3920 if (s
->face
->strike_through_p
)
3922 unsigned long h
= 1;
3923 unsigned long dy
= (s
->height
- h
) / 2;
3925 if (s
->face
->strike_through_color_defaulted_p
)
3926 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3931 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3932 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3933 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3935 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3939 /* Draw relief if not yet drawn. */
3940 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3941 x_draw_glyph_string_box (s
);
3944 /* Reset clipping. */
3945 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3948 /* Shift display to make room for inserted glyphs. */
3951 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3953 int x
, y
, width
, height
, shift_by
;
3955 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3956 x
, y
, width
, height
,
3960 /* Delete N glyphs at the nominal cursor position. Not implemented
3971 /* Clear entire frame. If updating_frame is non-null, clear that
3972 frame. Otherwise clear the selected frame. */
3982 f
= SELECTED_FRAME ();
3984 /* Clearing the frame will erase any cursor, so mark them all as no
3986 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3987 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3988 output_cursor
.x
= -1;
3990 /* We don't set the output cursor here because there will always
3991 follow an explicit cursor_to. */
3993 mac_clear_window (f
);
3995 /* We have to clear the scroll bars, too. If we have changed
3996 colors or something like that, then they should be notified. */
3997 x_scroll_bar_clear (f
);
3999 XFlush (FRAME_MAC_DISPLAY (f
));
4005 /* Invert the middle quarter of the frame for .15 sec. */
4007 /* We use the select system call to do the waiting, so we have to make
4008 sure it's available. If it isn't, we just won't do visual bells. */
4010 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4013 /* Subtract the `struct timeval' values X and Y, storing the result in
4014 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4017 timeval_subtract (result
, x
, y
)
4018 struct timeval
*result
, x
, y
;
4020 /* Perform the carry for the later subtraction by updating y. This
4021 is safer because on some systems the tv_sec member is unsigned. */
4022 if (x
.tv_usec
< y
.tv_usec
)
4024 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4025 y
.tv_usec
-= 1000000 * nsec
;
4029 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4031 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4032 y
.tv_usec
+= 1000000 * nsec
;
4036 /* Compute the time remaining to wait. tv_usec is certainly
4038 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4039 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4041 /* Return indication of whether the result should be considered
4043 return x
.tv_sec
< y
.tv_sec
;
4050 /* Get the height not including a menu bar widget. */
4051 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4052 /* Height of each line to flash. */
4053 int flash_height
= FRAME_LINE_HEIGHT (f
);
4054 /* These will be the left and right margins of the rectangles. */
4055 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4056 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4060 /* Don't flash the area between a scroll bar and the frame
4061 edge it is next to. */
4062 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4064 case vertical_scroll_bar_left
:
4065 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4068 case vertical_scroll_bar_right
:
4069 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4076 width
= flash_right
- flash_left
;
4080 /* If window is tall, flash top and bottom line. */
4081 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4083 mac_invert_rectangle (f
, flash_left
,
4084 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4085 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4086 width
, flash_height
);
4087 mac_invert_rectangle (f
, flash_left
,
4088 (height
- flash_height
4089 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4090 width
, flash_height
);
4093 /* If it is short, flash it all. */
4094 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4095 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4100 struct timeval wakeup
;
4102 EMACS_GET_TIME (wakeup
);
4104 /* Compute time to wait until, propagating carry from usecs. */
4105 wakeup
.tv_usec
+= 150000;
4106 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4107 wakeup
.tv_usec
%= 1000000;
4109 /* Keep waiting until past the time wakeup or any input gets
4111 while (! detect_input_pending ())
4113 struct timeval current
;
4114 struct timeval timeout
;
4116 EMACS_GET_TIME (current
);
4118 /* Break if result would be negative. */
4119 if (timeval_subtract (¤t
, wakeup
, current
))
4122 /* How long `select' should wait. */
4124 timeout
.tv_usec
= 10000;
4126 /* Try to wait that long--but we might wake up sooner. */
4127 select (0, NULL
, NULL
, NULL
, &timeout
);
4131 /* If window is tall, flash top and bottom line. */
4132 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4134 mac_invert_rectangle (f
, flash_left
,
4135 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4136 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4137 width
, flash_height
);
4138 mac_invert_rectangle (f
, flash_left
,
4139 (height
- flash_height
4140 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4141 width
, flash_height
);
4144 /* If it is short, flash it all. */
4145 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4146 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4153 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4156 /* Make audible bell. */
4161 struct frame
*f
= SELECTED_FRAME ();
4163 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4171 XFlush (FRAME_MAC_DISPLAY (f
));
4177 /* Specify how many text lines, from the top of the window,
4178 should be affected by insert-lines and delete-lines operations.
4179 This, and those operations, are used only within an update
4180 that is bounded by calls to x_update_begin and x_update_end. */
4183 XTset_terminal_window (n
)
4186 /* This function intentionally left blank. */
4191 /***********************************************************************
4193 ***********************************************************************/
4195 /* Perform an insert-lines or delete-lines operation, inserting N
4196 lines or deleting -N lines at vertical position VPOS. */
4199 x_ins_del_lines (vpos
, n
)
4206 /* Scroll part of the display as described by RUN. */
4209 x_scroll_run (w
, run
)
4213 struct frame
*f
= XFRAME (w
->frame
);
4214 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4216 /* Get frame-relative bounding box of the text display area of W,
4217 without mode lines. Include in this box the left and right
4219 window_box (w
, -1, &x
, &y
, &width
, &height
);
4221 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4222 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4223 bottom_y
= y
+ height
;
4227 /* Scrolling up. Make sure we don't copy part of the mode
4228 line at the bottom. */
4229 if (from_y
+ run
->height
> bottom_y
)
4230 height
= bottom_y
- from_y
;
4232 height
= run
->height
;
4236 /* Scolling down. Make sure we don't copy over the mode line.
4238 if (to_y
+ run
->height
> bottom_y
)
4239 height
= bottom_y
- to_y
;
4241 height
= run
->height
;
4246 /* Cursor off. Will be switched on again in x_update_window_end. */
4250 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4260 /***********************************************************************
4262 ***********************************************************************/
4270 ControlRef root_control
;
4273 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4275 ActivateControl (root_control
);
4277 x_update_cursor (f
, 1);
4281 frame_unhighlight (f
)
4285 ControlRef root_control
;
4288 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4290 DeactivateControl (root_control
);
4292 x_update_cursor (f
, 1);
4295 /* The focus has changed. Update the frames as necessary to reflect
4296 the new situation. Note that we can't change the selected frame
4297 here, because the Lisp code we are interrupting might become confused.
4298 Each event gets marked with the frame in which it occurred, so the
4299 Lisp code can tell when the switch took place by examining the events. */
4302 x_new_focus_frame (dpyinfo
, frame
)
4303 struct x_display_info
*dpyinfo
;
4304 struct frame
*frame
;
4306 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4308 if (frame
!= dpyinfo
->x_focus_frame
)
4310 /* Set this before calling other routines, so that they see
4311 the correct value of x_focus_frame. */
4312 dpyinfo
->x_focus_frame
= frame
;
4314 if (old_focus
&& old_focus
->auto_lower
)
4315 x_lower_frame (old_focus
);
4318 selected_frame
= frame
;
4319 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4321 Fselect_window (selected_frame
->selected_window
, Qnil
);
4322 choose_minibuf_frame ();
4325 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4326 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4328 pending_autoraise_frame
= 0;
4330 #if USE_MAC_FONT_PANEL
4332 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4336 x_frame_rehighlight (dpyinfo
);
4339 /* Handle FocusIn and FocusOut state changes for FRAME.
4340 If FRAME has focus and there exists more than one frame, puts
4341 a FOCUS_IN_EVENT into *BUFP. */
4344 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4346 struct mac_display_info
*dpyinfo
;
4347 struct frame
*frame
;
4348 struct input_event
*bufp
;
4350 if (type
== activeFlag
)
4352 if (dpyinfo
->x_focus_event_frame
!= frame
)
4354 x_new_focus_frame (dpyinfo
, frame
);
4355 dpyinfo
->x_focus_event_frame
= frame
;
4357 /* Don't stop displaying the initial startup message
4358 for a switch-frame event we don't need. */
4359 if (GC_NILP (Vterminal_frame
)
4360 && GC_CONSP (Vframe_list
)
4361 && !GC_NILP (XCDR (Vframe_list
)))
4363 bufp
->kind
= FOCUS_IN_EVENT
;
4364 XSETFRAME (bufp
->frame_or_window
, frame
);
4370 if (dpyinfo
->x_focus_event_frame
== frame
)
4372 dpyinfo
->x_focus_event_frame
= 0;
4373 x_new_focus_frame (dpyinfo
, 0);
4378 /* The focus may have changed. Figure out if it is a real focus change,
4379 by checking both FocusIn/Out and Enter/LeaveNotify events.
4381 Returns FOCUS_IN_EVENT event in *BUFP. */
4384 x_detect_focus_change (dpyinfo
, event
, bufp
)
4385 struct mac_display_info
*dpyinfo
;
4386 const EventRecord
*event
;
4387 struct input_event
*bufp
;
4389 struct frame
*frame
;
4391 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4395 /* On Mac, this is only called from focus events, so no switch needed. */
4396 mac_focus_changed ((event
->modifiers
& activeFlag
),
4397 dpyinfo
, frame
, bufp
);
4401 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4404 x_mouse_leave (dpyinfo
)
4405 struct x_display_info
*dpyinfo
;
4407 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4410 /* The focus has changed, or we have redirected a frame's focus to
4411 another frame (this happens when a frame uses a surrogate
4412 mini-buffer frame). Shift the highlight as appropriate.
4414 The FRAME argument doesn't necessarily have anything to do with which
4415 frame is being highlighted or un-highlighted; we only use it to find
4416 the appropriate X display info. */
4419 XTframe_rehighlight (frame
)
4420 struct frame
*frame
;
4422 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4426 x_frame_rehighlight (dpyinfo
)
4427 struct x_display_info
*dpyinfo
;
4429 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4431 if (dpyinfo
->x_focus_frame
)
4433 dpyinfo
->x_highlight_frame
4434 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4435 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4436 : dpyinfo
->x_focus_frame
);
4437 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4439 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4440 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4444 dpyinfo
->x_highlight_frame
= 0;
4446 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4449 frame_unhighlight (old_highlight
);
4450 if (dpyinfo
->x_highlight_frame
)
4451 frame_highlight (dpyinfo
->x_highlight_frame
);
4457 /* Convert a keysym to its name. */
4460 x_get_keysym_name (keysym
)
4467 value
= XKeysymToString (keysym
);
4478 /* Function to report a mouse movement to the mainstream Emacs code.
4479 The input handler calls this.
4481 We have received a mouse movement event, which is given in *event.
4482 If the mouse is over a different glyph than it was last time, tell
4483 the mainstream emacs code by setting mouse_moved. If not, ask for
4484 another motion event, so we can check again the next time it moves. */
4486 static Point last_mouse_motion_position
;
4487 static Lisp_Object last_mouse_motion_frame
;
4490 note_mouse_movement (frame
, pos
)
4494 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4495 #if TARGET_API_MAC_CARBON
4499 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4500 last_mouse_motion_position
= *pos
;
4501 XSETFRAME (last_mouse_motion_frame
, frame
);
4503 if (frame
== dpyinfo
->mouse_face_mouse_frame
4504 #if TARGET_API_MAC_CARBON
4505 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4507 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4511 /* This case corresponds to LeaveNotify in X11. If we move
4512 outside the frame, then we're certainly no longer on any text
4514 clear_mouse_face (dpyinfo
);
4515 dpyinfo
->mouse_face_mouse_frame
= 0;
4516 if (!dpyinfo
->grabbed
)
4517 rif
->define_frame_cursor (frame
,
4518 frame
->output_data
.mac
->nontext_cursor
);
4521 /* Has the mouse moved off the glyph it was on at the last sighting? */
4522 if (frame
!= last_mouse_glyph_frame
4523 || !PtInRect (*pos
, &last_mouse_glyph
))
4525 frame
->mouse_moved
= 1;
4526 last_mouse_scroll_bar
= Qnil
;
4527 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4528 /* Remember which glyph we're now on. */
4529 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4530 last_mouse_glyph_frame
= frame
;
4538 /************************************************************************
4540 ************************************************************************/
4542 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4545 redo_mouse_highlight ()
4547 if (!NILP (last_mouse_motion_frame
)
4548 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4549 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4550 last_mouse_motion_position
.h
,
4551 last_mouse_motion_position
.v
);
4555 static struct frame
*
4556 mac_focus_frame (dpyinfo
)
4557 struct mac_display_info
*dpyinfo
;
4559 if (dpyinfo
->x_focus_frame
)
4560 return dpyinfo
->x_focus_frame
;
4562 /* Mac version may get events, such as a menu bar click, even when
4563 all the frames are invisible. In this case, we regard the
4564 event came to the selected frame. */
4565 return SELECTED_FRAME ();
4569 /* Return the current position of the mouse.
4570 *FP should be a frame which indicates which display to ask about.
4572 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4573 and *PART to the frame, window, and scroll bar part that the mouse
4574 is over. Set *X and *Y to the portion and whole of the mouse's
4575 position on the scroll bar.
4577 If the mouse movement started elsewhere, set *FP to the frame the
4578 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4581 Set *TIME to the server time-stamp for the time at which the mouse
4582 was at this position.
4584 Don't store anything if we don't have a valid set of values to report.
4586 This clears the mouse_moved flag, so we can wait for the next mouse
4590 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4593 Lisp_Object
*bar_window
;
4594 enum scroll_bar_part
*part
;
4596 unsigned long *time
;
4602 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4603 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4606 Lisp_Object frame
, tail
;
4608 /* Clear the mouse-moved flag for every frame on this display. */
4609 FOR_EACH_FRAME (tail
, frame
)
4610 XFRAME (frame
)->mouse_moved
= 0;
4612 last_mouse_scroll_bar
= Qnil
;
4614 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4615 && FRAME_LIVE_P (last_mouse_frame
))
4616 f1
= last_mouse_frame
;
4618 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4622 /* Ok, we found a frame. Store all the values.
4623 last_mouse_glyph is a rectangle used to reduce the
4624 generation of mouse events. To not miss any motion
4625 events, we must divide the frame into rectangles of the
4626 size of the smallest character that could be displayed
4627 on it, i.e. into the same rectangles that matrices on
4628 the frame are divided into. */
4631 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4632 GetMouse (&mouse_pos
);
4633 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4635 last_mouse_glyph_frame
= f1
;
4640 XSETINT (*x
, mouse_pos
.h
);
4641 XSETINT (*y
, mouse_pos
.v
);
4642 *time
= last_mouse_movement_time
;
4650 /************************************************************************
4652 ************************************************************************/
4654 #ifdef USE_TOOLKIT_SCROLL_BARS
4656 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4657 static OSStatus install_scroll_bar_timer
P_ ((void));
4658 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4659 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4660 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4661 struct input_event
*));
4662 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4664 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4665 ControlPartCode
, Point
,
4666 struct input_event
*));
4667 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4668 struct input_event
*));
4669 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4670 Point
, struct input_event
*));
4671 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4674 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4676 static int last_scroll_bar_part
;
4678 static EventLoopTimerRef scroll_bar_timer
;
4680 static int scroll_bar_timer_event_posted_p
;
4682 #define SCROLL_BAR_FIRST_DELAY 0.5
4683 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4686 scroll_bar_timer_callback (timer
, data
)
4687 EventLoopTimerRef timer
;
4692 err
= mac_post_mouse_moved_event ();
4694 scroll_bar_timer_event_posted_p
= 1;
4698 install_scroll_bar_timer ()
4700 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4702 if (scroll_bar_timer_callbackUPP
== NULL
)
4703 scroll_bar_timer_callbackUPP
=
4704 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4706 if (scroll_bar_timer
== NULL
)
4707 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4708 kEventDurationForever as delays. */
4710 InstallEventLoopTimer (GetCurrentEventLoop (),
4711 kEventDurationForever
, kEventDurationForever
,
4712 scroll_bar_timer_callbackUPP
, NULL
,
4717 set_scroll_bar_timer (delay
)
4718 EventTimerInterval delay
;
4720 if (scroll_bar_timer
== NULL
)
4721 install_scroll_bar_timer ();
4723 scroll_bar_timer_event_posted_p
= 0;
4725 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4729 control_part_code_to_scroll_bar_part (part_code
)
4730 ControlPartCode part_code
;
4734 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4735 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4736 case kControlPageUpPart
: return scroll_bar_above_handle
;
4737 case kControlPageDownPart
: return scroll_bar_below_handle
;
4738 case kControlIndicatorPart
: return scroll_bar_handle
;
4745 construct_scroll_bar_click (bar
, part
, bufp
)
4746 struct scroll_bar
*bar
;
4748 struct input_event
*bufp
;
4750 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4751 bufp
->frame_or_window
= bar
->window
;
4755 XSETINT (bufp
->x
, 0);
4756 XSETINT (bufp
->y
, 0);
4757 bufp
->modifiers
= 0;
4761 get_control_part_bounds (ch
, part_code
, rect
)
4763 ControlPartCode part_code
;
4766 RgnHandle region
= NewRgn ();
4769 err
= GetControlRegion (ch
, part_code
, region
);
4771 GetRegionBounds (region
, rect
);
4772 DisposeRgn (region
);
4778 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4779 struct scroll_bar
*bar
;
4780 ControlPartCode part_code
;
4782 struct input_event
*bufp
;
4784 int part
= control_part_code_to_scroll_bar_part (part_code
);
4789 if (part
!= scroll_bar_handle
)
4791 construct_scroll_bar_click (bar
, part
, bufp
);
4792 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4793 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4794 bar
->dragging
= Qnil
;
4800 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4801 kControlIndicatorPart
, &r
);
4802 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4805 last_scroll_bar_part
= part
;
4806 tracked_scroll_bar
= bar
;
4810 x_scroll_bar_handle_release (bar
, bufp
)
4811 struct scroll_bar
*bar
;
4812 struct input_event
*bufp
;
4814 if (last_scroll_bar_part
!= scroll_bar_handle
4815 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4816 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4818 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4819 set_scroll_bar_timer (kEventDurationForever
);
4821 last_scroll_bar_part
= -1;
4822 bar
->dragging
= Qnil
;
4823 tracked_scroll_bar
= NULL
;
4827 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4829 struct scroll_bar
*bar
;
4831 struct input_event
*bufp
;
4833 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4835 if (last_scroll_bar_part
== scroll_bar_handle
)
4840 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4841 kControlIndicatorPart
, &r
);
4843 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4844 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4846 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4847 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4851 if (top
> top_range
)
4854 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4855 XSETINT (bufp
->x
, top
);
4856 XSETINT (bufp
->y
, top_range
);
4860 ControlPartCode part_code
;
4861 int unhilite_p
= 0, part
;
4863 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4867 part
= control_part_code_to_scroll_bar_part (part_code
);
4869 switch (last_scroll_bar_part
)
4871 case scroll_bar_above_handle
:
4872 case scroll_bar_below_handle
:
4873 if (part
!= scroll_bar_above_handle
4874 && part
!= scroll_bar_below_handle
)
4878 case scroll_bar_up_arrow
:
4879 case scroll_bar_down_arrow
:
4880 if (part
!= scroll_bar_up_arrow
4881 && part
!= scroll_bar_down_arrow
)
4888 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4889 else if (part
!= last_scroll_bar_part
4890 || scroll_bar_timer_event_posted_p
)
4892 construct_scroll_bar_click (bar
, part
, bufp
);
4893 last_scroll_bar_part
= part
;
4894 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4895 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4900 /* Set the thumb size and position of scroll bar BAR. We are currently
4901 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4904 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4905 struct scroll_bar
*bar
;
4906 int portion
, position
, whole
;
4908 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4909 int value
, viewsize
, maximum
;
4911 if (XINT (bar
->track_height
) == 0)
4914 if (whole
<= portion
)
4915 value
= 0, viewsize
= 1, maximum
= 0;
4920 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4921 scale
= (float) maximum
/ (whole
- portion
);
4922 value
= position
* scale
+ 0.5f
;
4923 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
4928 if (GetControlViewSize (ch
) != viewsize
4929 || GetControl32BitValue (ch
) != value
4930 || GetControl32BitMaximum (ch
) != maximum
)
4932 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4933 SetControlVisibility (ch
, false, false);
4935 SetControl32BitMaximum (ch
, maximum
);
4936 SetControl32BitValue (ch
, value
);
4937 SetControlViewSize (ch
, viewsize
);
4939 SetControlVisibility (ch
, true, true);
4945 #endif /* USE_TOOLKIT_SCROLL_BARS */
4949 /************************************************************************
4950 Scroll bars, general
4951 ************************************************************************/
4953 /* Create a scroll bar and return the scroll bar vector for it. W is
4954 the Emacs window on which to create the scroll bar. TOP, LEFT,
4955 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4958 static struct scroll_bar
*
4959 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4961 int top
, left
, width
, height
, disp_top
, disp_height
;
4963 struct frame
*f
= XFRAME (w
->frame
);
4964 struct scroll_bar
*bar
4965 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4973 r
.right
= left
+ width
;
4974 r
.bottom
= disp_top
+ disp_height
;
4977 mac_prepare_for_quickdraw (f
);
4979 #if TARGET_API_MAC_CARBON
4980 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4981 #ifdef USE_TOOLKIT_SCROLL_BARS
4984 width
< disp_height
,
4986 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4988 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4989 0, 0, 0, scrollBarProc
, (long) bar
);
4991 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4993 XSETWINDOW (bar
->window
, w
);
4994 XSETINT (bar
->top
, top
);
4995 XSETINT (bar
->left
, left
);
4996 XSETINT (bar
->width
, width
);
4997 XSETINT (bar
->height
, height
);
4998 XSETINT (bar
->start
, 0);
4999 XSETINT (bar
->end
, 0);
5000 bar
->dragging
= Qnil
;
5001 bar
->redraw_needed_p
= Qnil
;
5002 #ifdef USE_TOOLKIT_SCROLL_BARS
5003 bar
->track_top
= Qnil
;
5004 bar
->track_height
= Qnil
;
5005 bar
->min_handle
= Qnil
;
5008 /* Add bar to its frame's list of scroll bars. */
5009 bar
->next
= FRAME_SCROLL_BARS (f
);
5011 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5012 if (!NILP (bar
->next
))
5013 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5020 /* Draw BAR's handle in the proper position.
5022 If the handle is already drawn from START to END, don't bother
5023 redrawing it, unless REBUILD is non-zero; in that case, always
5024 redraw it. (REBUILD is handy for drawing the handle after expose
5027 Normally, we want to constrain the start and end of the handle to
5028 fit inside its rectangle, but if the user is dragging the scroll
5029 bar handle, we want to let them drag it down all the way, so that
5030 the bar's top is as far down as it goes; otherwise, there's no way
5031 to move to the very end of the buffer. */
5033 #ifndef USE_TOOLKIT_SCROLL_BARS
5036 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5037 struct scroll_bar
*bar
;
5041 int dragging
= ! NILP (bar
->dragging
);
5042 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5043 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5044 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5045 int length
= end
- start
;
5047 /* If the display is already accurate, do nothing. */
5049 && start
== XINT (bar
->start
)
5050 && end
== XINT (bar
->end
))
5055 /* Make sure the values are reasonable, and try to preserve the
5056 distance between start and end. */
5059 else if (start
> top_range
)
5061 end
= start
+ length
;
5065 else if (end
> top_range
&& ! dragging
)
5068 /* Store the adjusted setting in the scroll bar. */
5069 XSETINT (bar
->start
, start
);
5070 XSETINT (bar
->end
, end
);
5072 /* Clip the end position, just for display. */
5073 if (end
> top_range
)
5076 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5077 top positions, to make sure the handle is always at least that
5078 many pixels tall. */
5079 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5081 SetControlMinimum (ch
, 0);
5082 /* Don't inadvertently activate deactivated scroll bars */
5083 if (GetControlMaximum (ch
) != -1)
5084 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5086 SetControlValue (ch
, start
);
5087 #if TARGET_API_MAC_CARBON
5088 SetControlViewSize (ch
, end
- start
);
5094 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5096 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5100 x_scroll_bar_remove (bar
)
5101 struct scroll_bar
*bar
;
5103 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5108 mac_prepare_for_quickdraw (f
);
5110 /* Destroy the Mac scroll bar control */
5111 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
5113 /* Disassociate this scroll bar from its window. */
5114 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5120 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5121 that we are displaying PORTION characters out of a total of WHOLE
5122 characters, starting at POSITION. If WINDOW has no scroll bar,
5126 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5128 int portion
, whole
, position
;
5130 struct frame
*f
= XFRAME (w
->frame
);
5131 struct scroll_bar
*bar
;
5132 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5133 int window_y
, window_height
;
5135 /* Get window dimensions. */
5136 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5138 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5139 height
= window_height
;
5141 /* Compute the left edge of the scroll bar area. */
5142 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5144 /* Compute the width of the scroll bar which might be less than
5145 the width of the area reserved for the scroll bar. */
5146 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5147 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5151 /* Compute the left edge of the scroll bar. */
5152 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5155 sb_left
= left
+ width
- sb_width
;
5157 /* Adjustments according to Inside Macintosh to make it look nice */
5159 disp_height
= height
;
5166 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5172 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5176 /* Does the scroll bar exist yet? */
5177 if (NILP (w
->vertical_scroll_bar
))
5180 mac_clear_area (f
, left
, top
, width
, height
);
5182 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5184 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5188 /* It may just need to be moved and resized. */
5191 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5192 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5196 /* If already correctly positioned, do nothing. */
5197 if (XINT (bar
->left
) == sb_left
5198 && XINT (bar
->top
) == top
5199 && XINT (bar
->width
) == sb_width
5200 && XINT (bar
->height
) == height
)
5202 if (!NILP (bar
->redraw_needed_p
))
5205 mac_prepare_for_quickdraw (f
);
5207 Draw1Control (SCROLL_BAR_CONTROL_HANDLE (bar
));
5212 /* Since toolkit scroll bars are smaller than the space reserved
5213 for them on the frame, we have to clear "under" them. */
5214 mac_clear_area (f
, left
, top
, width
, height
);
5217 mac_prepare_for_quickdraw (f
);
5220 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5221 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5223 #ifndef USE_TOOLKIT_SCROLL_BARS
5224 if (sb_width
< disp_height
)
5228 /* Remember new settings. */
5229 XSETINT (bar
->left
, sb_left
);
5230 XSETINT (bar
->top
, top
);
5231 XSETINT (bar
->width
, sb_width
);
5232 XSETINT (bar
->height
, height
);
5233 #ifdef USE_TOOLKIT_SCROLL_BARS
5234 bar
->track_top
= Qnil
;
5235 bar
->track_height
= Qnil
;
5236 bar
->min_handle
= Qnil
;
5243 bar
->redraw_needed_p
= Qnil
;
5245 #ifdef USE_TOOLKIT_SCROLL_BARS
5246 if (NILP (bar
->track_top
))
5248 if (sb_width
>= disp_height
5250 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5254 XSETINT (bar
->track_top
, 0);
5255 XSETINT (bar
->track_height
, 0);
5256 XSETINT (bar
->min_handle
, 0);
5260 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5265 SetControl32BitMinimum (ch
, 0);
5266 SetControl32BitMaximum (ch
, 1 << 30);
5267 SetControlViewSize (ch
, 1);
5269 /* Move the scroll bar thumb to the top. */
5270 SetControl32BitValue (ch
, 0);
5271 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5273 /* Move the scroll bar thumb to the bottom. */
5274 SetControl32BitValue (ch
, 1 << 30);
5275 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5277 UnionRect (&r0
, &r1
, &r0
);
5278 XSETINT (bar
->track_top
, r0
.top
);
5279 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5280 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5282 /* Don't show the scroll bar if its height is not enough to
5283 display the scroll bar thumb. */
5284 if (r0
.bottom
- r0
.top
> 0)
5291 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5292 #else /* not USE_TOOLKIT_SCROLL_BARS */
5293 /* Set the scroll bar's current state, unless we're currently being
5295 if (NILP (bar
->dragging
))
5297 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5300 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5303 int start
= ((double) position
* top_range
) / whole
;
5304 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5305 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5308 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5312 /* The following three hooks are used when we're doing a thorough
5313 redisplay of the frame. We don't explicitly know which scroll bars
5314 are going to be deleted, because keeping track of when windows go
5315 away is a real pain - "Can you say set-window-configuration, boys
5316 and girls?" Instead, we just assert at the beginning of redisplay
5317 that *all* scroll bars are to be removed, and then save a scroll bar
5318 from the fiery pit when we actually redisplay its window. */
5320 /* Arrange for all scroll bars on FRAME to be removed at the next call
5321 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5322 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5325 XTcondemn_scroll_bars (frame
)
5328 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5329 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5332 bar
= FRAME_SCROLL_BARS (frame
);
5333 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5334 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5335 XSCROLL_BAR (bar
)->prev
= Qnil
;
5336 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5337 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5338 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5343 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5344 Note that WINDOW isn't necessarily condemned at all. */
5347 XTredeem_scroll_bar (window
)
5348 struct window
*window
;
5350 struct scroll_bar
*bar
;
5353 /* We can't redeem this window's scroll bar if it doesn't have one. */
5354 if (NILP (window
->vertical_scroll_bar
))
5357 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5359 /* Unlink it from the condemned list. */
5360 f
= XFRAME (WINDOW_FRAME (window
));
5361 if (NILP (bar
->prev
))
5363 /* If the prev pointer is nil, it must be the first in one of
5365 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5366 /* It's not condemned. Everything's fine. */
5368 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5369 window
->vertical_scroll_bar
))
5370 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5372 /* If its prev pointer is nil, it must be at the front of
5373 one or the other! */
5377 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5379 if (! NILP (bar
->next
))
5380 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5382 bar
->next
= FRAME_SCROLL_BARS (f
);
5384 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5385 if (! NILP (bar
->next
))
5386 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5389 /* Remove all scroll bars on FRAME that haven't been saved since the
5390 last call to `*condemn_scroll_bars_hook'. */
5393 XTjudge_scroll_bars (f
)
5396 Lisp_Object bar
, next
;
5398 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5400 /* Clear out the condemned list now so we won't try to process any
5401 more events on the hapless scroll bars. */
5402 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5404 for (; ! NILP (bar
); bar
= next
)
5406 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5408 x_scroll_bar_remove (b
);
5411 b
->next
= b
->prev
= Qnil
;
5414 /* Now there should be no references to the condemned scroll bars,
5415 and they should get garbage-collected. */
5419 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5420 is set to something other than NO_EVENT, it is enqueued.
5422 This may be called from a signal handler, so we have to ignore GC
5426 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5427 struct scroll_bar
*bar
;
5428 ControlPartCode part_code
;
5429 const EventRecord
*er
;
5430 struct input_event
*bufp
;
5432 int win_y
, top_range
;
5434 if (! GC_WINDOWP (bar
->window
))
5437 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5438 bufp
->frame_or_window
= bar
->window
;
5441 bar
->dragging
= Qnil
;
5445 case kControlUpButtonPart
:
5446 bufp
->part
= scroll_bar_up_arrow
;
5448 case kControlDownButtonPart
:
5449 bufp
->part
= scroll_bar_down_arrow
;
5451 case kControlPageUpPart
:
5452 bufp
->part
= scroll_bar_above_handle
;
5454 case kControlPageDownPart
:
5455 bufp
->part
= scroll_bar_below_handle
;
5457 #if TARGET_API_MAC_CARBON
5460 case kControlIndicatorPart
:
5462 if (er
->what
== mouseDown
)
5463 bar
->dragging
= make_number (0);
5464 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5465 bufp
->part
= scroll_bar_handle
;
5469 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5470 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5472 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5476 if (! NILP (bar
->dragging
))
5477 win_y
-= XINT (bar
->dragging
);
5481 if (win_y
> top_range
)
5484 XSETINT (bufp
->x
, win_y
);
5485 XSETINT (bufp
->y
, top_range
);
5488 #ifndef USE_TOOLKIT_SCROLL_BARS
5490 /* Handle some mouse motion while someone is dragging the scroll bar.
5492 This may be called from a signal handler, so we have to ignore GC
5496 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5497 struct scroll_bar
*bar
;
5501 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5503 last_mouse_movement_time
= t
;
5506 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5508 /* If we're dragging the bar, display it. */
5509 if (! GC_NILP (bar
->dragging
))
5511 /* Where should the handle be now? */
5512 int new_start
= y_pos
- 24;
5514 if (new_start
!= XINT (bar
->start
))
5516 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5518 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5523 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5525 /* Return information to the user about the current position of the mouse
5526 on the scroll bar. */
5529 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5531 Lisp_Object
*bar_window
;
5532 enum scroll_bar_part
*part
;
5534 unsigned long *time
;
5536 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5537 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5538 #if TARGET_API_MAC_CARBON
5539 WindowPtr wp
= GetControlOwner (ch
);
5541 WindowPtr wp
= (*ch
)->contrlOwner
;
5544 struct frame
*f
= mac_window_to_frame (wp
);
5545 int win_y
, top_range
;
5547 SetPortWindowPort (wp
);
5549 GetMouse (&mouse_pos
);
5551 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5552 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5554 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5558 if (! NILP (bar
->dragging
))
5559 win_y
-= XINT (bar
->dragging
);
5563 if (win_y
> top_range
)
5567 *bar_window
= bar
->window
;
5569 if (! NILP (bar
->dragging
))
5570 *part
= scroll_bar_handle
;
5571 else if (win_y
< XINT (bar
->start
))
5572 *part
= scroll_bar_above_handle
;
5573 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5574 *part
= scroll_bar_handle
;
5576 *part
= scroll_bar_below_handle
;
5578 XSETINT (*x
, win_y
);
5579 XSETINT (*y
, top_range
);
5582 last_mouse_scroll_bar
= Qnil
;
5584 *time
= last_mouse_movement_time
;
5588 /* The screen has been cleared so we may have changed foreground or
5589 background colors, and the scroll bars may need to be redrawn.
5590 Clear out the scroll bars, and ask for expose events, so we can
5594 x_scroll_bar_clear (f
)
5599 /* We can have scroll bars even if this is 0,
5600 if we just turned off scroll bar mode.
5601 But in that case we should not clear them. */
5602 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5603 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5604 bar
= XSCROLL_BAR (bar
)->next
)
5605 XSCROLL_BAR (bar
)->redraw_needed_p
= Qt
;
5609 /***********************************************************************
5611 ***********************************************************************/
5613 /* Set clipping for output in glyph row ROW. W is the window in which
5614 we operate. GC is the graphics context to set clipping in.
5616 ROW may be a text row or, e.g., a mode line. Text rows must be
5617 clipped to the interior of the window dedicated to text display,
5618 mode lines must be clipped to the whole window. */
5621 x_clip_to_row (w
, row
, area
, gc
)
5623 struct glyph_row
*row
;
5627 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5629 int window_x
, window_y
, window_width
;
5631 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5633 clip_rect
.left
= window_x
;
5634 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5635 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5636 clip_rect
.right
= clip_rect
.left
+ window_width
;
5637 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5639 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5643 /* Draw a hollow box cursor on window W in glyph row ROW. */
5646 x_draw_hollow_cursor (w
, row
)
5648 struct glyph_row
*row
;
5650 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5651 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5652 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5655 struct glyph
*cursor_glyph
;
5658 /* Get the glyph the cursor is on. If we can't tell because
5659 the current matrix is invalid or such, give up. */
5660 cursor_glyph
= get_phys_cursor_glyph (w
);
5661 if (cursor_glyph
== NULL
)
5664 /* Compute frame-relative coordinates for phys cursor. */
5665 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5666 wd
= w
->phys_cursor_width
;
5668 /* The foreground of cursor_gc is typically the same as the normal
5669 background color, which can cause the cursor box to be invisible. */
5670 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5671 if (dpyinfo
->scratch_cursor_gc
)
5672 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5674 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5675 GCForeground
, &xgcv
);
5676 gc
= dpyinfo
->scratch_cursor_gc
;
5678 /* Set clipping, draw the rectangle, and reset clipping again. */
5679 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5680 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5681 mac_reset_clip_rectangles (dpy
, gc
);
5685 /* Draw a bar cursor on window W in glyph row ROW.
5687 Implementation note: One would like to draw a bar cursor with an
5688 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5689 Unfortunately, I didn't find a font yet that has this property set.
5693 x_draw_bar_cursor (w
, row
, width
, kind
)
5695 struct glyph_row
*row
;
5697 enum text_cursor_kinds kind
;
5699 struct frame
*f
= XFRAME (w
->frame
);
5700 struct glyph
*cursor_glyph
;
5702 /* If cursor is out of bounds, don't draw garbage. This can happen
5703 in mini-buffer windows when switching between echo area glyphs
5705 cursor_glyph
= get_phys_cursor_glyph (w
);
5706 if (cursor_glyph
== NULL
)
5709 /* If on an image, draw like a normal cursor. That's usually better
5710 visible than drawing a bar, esp. if the image is large so that
5711 the bar might not be in the window. */
5712 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5714 struct glyph_row
*row
;
5715 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5716 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5720 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5721 Window window
= FRAME_MAC_WINDOW (f
);
5722 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5723 unsigned long mask
= GCForeground
| GCBackground
;
5724 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5727 /* If the glyph's background equals the color we normally draw
5728 the bar cursor in, the bar cursor in its normal color is
5729 invisible. Use the glyph's foreground color instead in this
5730 case, on the assumption that the glyph's colors are chosen so
5731 that the glyph is legible. */
5732 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5733 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5735 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5738 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5741 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5742 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5746 width
= FRAME_CURSOR_WIDTH (f
);
5747 width
= min (cursor_glyph
->pixel_width
, width
);
5749 w
->phys_cursor_width
= width
;
5750 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5752 if (kind
== BAR_CURSOR
)
5753 mac_fill_rectangle (f
, gc
,
5754 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5755 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5756 width
, row
->height
);
5758 mac_fill_rectangle (f
, gc
,
5759 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5760 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5761 row
->height
- width
),
5762 cursor_glyph
->pixel_width
,
5765 mac_reset_clip_rectangles (dpy
, gc
);
5770 /* RIF: Define cursor CURSOR on frame F. */
5773 mac_define_frame_cursor (f
, cursor
)
5777 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5779 if (dpyinfo
->x_focus_frame
== f
)
5780 SetThemeCursor (cursor
);
5784 /* RIF: Clear area on frame F. */
5787 mac_clear_frame_area (f
, x
, y
, width
, height
)
5789 int x
, y
, width
, height
;
5791 mac_clear_area (f
, x
, y
, width
, height
);
5795 /* RIF: Draw cursor on window W. */
5798 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5800 struct glyph_row
*glyph_row
;
5802 int cursor_type
, cursor_width
;
5807 w
->phys_cursor_type
= cursor_type
;
5808 w
->phys_cursor_on_p
= 1;
5810 if (glyph_row
->exact_window_width_line_p
5811 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5813 glyph_row
->cursor_in_fringe_p
= 1;
5814 draw_fringe_bitmap (w
, glyph_row
, 0);
5817 switch (cursor_type
)
5819 case HOLLOW_BOX_CURSOR
:
5820 x_draw_hollow_cursor (w
, glyph_row
);
5823 case FILLED_BOX_CURSOR
:
5824 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5828 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5832 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5836 w
->phys_cursor_width
= 0;
5848 #if 0 /* MAC_TODO: no icon support yet. */
5850 x_bitmap_icon (f
, icon
)
5856 if (FRAME_W32_WINDOW (f
) == 0)
5860 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5861 else if (STRINGP (icon
))
5862 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5863 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5864 else if (SYMBOLP (icon
))
5868 if (EQ (icon
, intern ("application")))
5869 name
= (LPCTSTR
) IDI_APPLICATION
;
5870 else if (EQ (icon
, intern ("hand")))
5871 name
= (LPCTSTR
) IDI_HAND
;
5872 else if (EQ (icon
, intern ("question")))
5873 name
= (LPCTSTR
) IDI_QUESTION
;
5874 else if (EQ (icon
, intern ("exclamation")))
5875 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5876 else if (EQ (icon
, intern ("asterisk")))
5877 name
= (LPCTSTR
) IDI_ASTERISK
;
5878 else if (EQ (icon
, intern ("winlogo")))
5879 name
= (LPCTSTR
) IDI_WINLOGO
;
5883 hicon
= LoadIcon (NULL
, name
);
5891 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5896 #endif /* MAC_TODO */
5898 /************************************************************************
5900 ************************************************************************/
5902 /* Display Error Handling functions not used on W32. Listing them here
5903 helps diff stay in step when comparing w32term.c with xterm.c.
5905 x_error_catcher (display, error)
5906 x_catch_errors (dpy)
5907 x_catch_errors_unwind (old_val)
5908 x_check_errors (dpy, format)
5909 x_had_errors_p (dpy)
5910 x_clear_errors (dpy)
5911 x_uncatch_errors (dpy, count)
5913 x_connection_signal (signalnum)
5914 x_connection_closed (dpy, error_message)
5915 x_error_quitter (display, error)
5916 x_error_handler (display, error)
5917 x_io_error_quitter (display)
5922 /* Changing the font of the frame. */
5924 /* Give frame F the font named FONTNAME as its default font, and
5925 return the full name of that font. FONTNAME may be a wildcard
5926 pattern; in that case, we choose some font that fits the pattern.
5927 The return value shows which font we chose. */
5930 x_new_font (f
, fontname
)
5932 register char *fontname
;
5934 struct font_info
*fontp
5935 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5940 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5941 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5942 FRAME_FONTSET (f
) = -1;
5944 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5945 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5946 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5948 compute_fringe_widths (f
, 1);
5950 /* Compute the scroll bar width in character columns. */
5951 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5953 int wid
= FRAME_COLUMN_WIDTH (f
);
5954 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5955 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5959 int wid
= FRAME_COLUMN_WIDTH (f
);
5960 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5963 /* Now make the frame display the given font. */
5964 if (FRAME_MAC_WINDOW (f
) != 0)
5966 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5968 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5970 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5973 /* Don't change the size of a tip frame; there's no point in
5974 doing it because it's done in Fx_show_tip, and it leads to
5975 problems because the tip frame has no widget. */
5976 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5977 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5980 return build_string (fontp
->full_name
);
5983 /* Give frame F the fontset named FONTSETNAME as its default font, and
5984 return the full name of that fontset. FONTSETNAME may be a wildcard
5985 pattern; in that case, we choose some fontset that fits the pattern.
5986 The return value shows which fontset we chose. */
5989 x_new_fontset (f
, fontsetname
)
5993 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5999 if (FRAME_FONTSET (f
) == fontset
)
6000 /* This fontset is already set in frame F. There's nothing more
6002 return fontset_name (fontset
);
6004 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6006 if (!STRINGP (result
))
6007 /* Can't load ASCII font. */
6010 /* Since x_new_font doesn't update any fontset information, do it now. */
6011 FRAME_FONTSET (f
) = fontset
;
6013 return build_string (fontsetname
);
6017 /***********************************************************************
6018 TODO: W32 Input Methods
6019 ***********************************************************************/
6020 /* Listing missing functions from xterm.c helps diff stay in step.
6022 xim_destroy_callback (xim, client_data, call_data)
6023 xim_open_dpy (dpyinfo, resource_name)
6025 xim_instantiate_callback (display, client_data, call_data)
6026 xim_initialize (dpyinfo, resource_name)
6027 xim_close_dpy (dpyinfo)
6033 mac_get_window_bounds (f
, inner
, outer
)
6035 Rect
*inner
, *outer
;
6037 #if TARGET_API_MAC_CARBON
6038 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6039 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6040 #else /* not TARGET_API_MAC_CARBON */
6041 RgnHandle region
= NewRgn ();
6043 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6044 *inner
= (*region
)->rgnBBox
;
6045 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6046 *outer
= (*region
)->rgnBBox
;
6047 DisposeRgn (region
);
6048 #endif /* not TARGET_API_MAC_CARBON */
6052 mac_handle_origin_change (f
)
6055 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6059 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6061 int pixelwidth
, pixelheight
;
6065 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6066 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6068 if (cols
!= FRAME_COLS (f
)
6069 || rows
!= FRAME_LINES (f
)
6070 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6071 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6073 /* We pass 1 for DELAY since we can't run Lisp code inside of
6075 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6076 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6077 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6078 SET_FRAME_GARBAGED (f
);
6080 /* If cursor was outside the new size, mark it as off. */
6081 mark_window_cursors_off (XWINDOW (f
->root_window
));
6083 /* Clear out any recollection of where the mouse highlighting
6084 was, since it might be in a place that's outside the new
6085 frame size. Actually checking whether it is outside is a
6086 pain in the neck, so don't try--just let the highlighting be
6087 done afresh with new size. */
6088 cancel_mouse_face (f
);
6090 #if TARGET_API_MAC_CARBON
6091 if (f
->output_data
.mac
->hourglass_control
)
6094 mac_prepare_for_quickdraw (f
);
6096 MoveControl (f
->output_data
.mac
->hourglass_control
,
6097 pixelwidth
- HOURGLASS_WIDTH
, 0);
6104 /* Calculate the absolute position in frame F
6105 from its current recorded position values and gravity. */
6108 x_calc_absolute_position (f
)
6111 int width_diff
= 0, height_diff
= 0;
6112 int flags
= f
->size_hint_flags
;
6115 /* We have nothing to do if the current position
6116 is already for the top-left corner. */
6117 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6120 /* Find the offsets of the outside upper-left corner of
6121 the inner window, with respect to the outer window. */
6123 mac_get_window_bounds (f
, &inner
, &outer
);
6126 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6127 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6129 /* Treat negative positions as relative to the leftmost bottommost
6130 position that fits on the screen. */
6131 if (flags
& XNegative
)
6132 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6134 - FRAME_PIXEL_WIDTH (f
)
6137 if (flags
& YNegative
)
6138 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6140 - FRAME_PIXEL_HEIGHT (f
)
6143 /* The left_pos and top_pos
6144 are now relative to the top and left screen edges,
6145 so the flags should correspond. */
6146 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6149 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6150 to really change the position, and 0 when calling from
6151 x_make_frame_visible (in that case, XOFF and YOFF are the current
6152 position values). It is -1 when calling from x_set_frame_parameters,
6153 which means, do adjust for borders but don't change the gravity. */
6156 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6158 register int xoff
, yoff
;
6161 if (change_gravity
> 0)
6165 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6167 f
->size_hint_flags
|= XNegative
;
6169 f
->size_hint_flags
|= YNegative
;
6170 f
->win_gravity
= NorthWestGravity
;
6172 x_calc_absolute_position (f
);
6175 x_wm_set_size_hint (f
, (long) 0, 0);
6177 #if TARGET_API_MAC_CARBON
6178 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6179 /* If the title bar is completely outside the screen, adjust the
6181 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6182 kWindowConstrainMoveRegardlessOfFit
6183 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6184 #if USE_CARBON_EVENTS
6185 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6187 mac_handle_origin_change (f
);
6190 Rect inner
, outer
, screen_rect
, dummy
;
6191 RgnHandle region
= NewRgn ();
6193 mac_get_window_bounds (f
, &inner
, &outer
);
6194 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6195 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6196 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6197 f
->top_pos
+ f
->y_pixels_diff
, false);
6199 /* If the title bar is completely outside the screen, adjust the
6200 position. The variable `outer' holds the title bar rectangle.
6201 The variable `inner' holds slightly smaller one than `outer',
6202 so that the calculation of overlapping may not become too
6204 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6205 outer
= (*region
)->rgnBBox
;
6206 DisposeRgn (region
);
6208 InsetRect (&inner
, 8, 8);
6209 screen_rect
= qd
.screenBits
.bounds
;
6210 screen_rect
.top
+= GetMBarHeight ();
6212 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6214 if (inner
.right
<= screen_rect
.left
)
6215 f
->left_pos
= screen_rect
.left
;
6216 else if (inner
.left
>= screen_rect
.right
)
6217 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6219 if (inner
.bottom
<= screen_rect
.top
)
6220 f
->top_pos
= screen_rect
.top
;
6221 else if (inner
.top
>= screen_rect
.bottom
)
6222 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6224 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6225 f
->top_pos
+ f
->y_pixels_diff
, false);
6233 /* Call this to change the size of frame F's x-window.
6234 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6235 for this size change and subsequent size changes.
6236 Otherwise we leave the window gravity unchanged. */
6239 x_set_window_size (f
, change_gravity
, cols
, rows
)
6244 int pixelwidth
, pixelheight
;
6248 check_frame_size (f
, &rows
, &cols
);
6249 f
->scroll_bar_actual_width
6250 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6252 compute_fringe_widths (f
, 0);
6254 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6255 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6257 f
->win_gravity
= NorthWestGravity
;
6258 x_wm_set_size_hint (f
, (long) 0, 0);
6260 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6262 #if USE_CARBON_EVENTS
6263 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6265 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6267 if (f
->output_data
.mac
->internal_border_width
6268 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6270 mac_clear_window (f
);
6271 f
->output_data
.mac
->internal_border_width
6272 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6275 SET_FRAME_GARBAGED (f
);
6280 /* Mouse warping. */
6282 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6285 x_set_mouse_position (f
, x
, y
)
6291 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6292 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6294 if (pix_x
< 0) pix_x
= 0;
6295 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6297 if (pix_y
< 0) pix_y
= 0;
6298 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6300 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6304 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6313 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
6319 CGWarpMouseCursorPosition (point
);
6322 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6325 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6326 0, 0, 0, 0, pix_x
, pix_y
);
6332 /* focus shifting, raising and lowering. */
6335 x_focus_on_frame (f
)
6338 #if 0 /* This proves to be unpleasant. */
6342 /* I don't think that the ICCCM allows programs to do things like this
6343 without the interaction of the window manager. Whatever you end up
6344 doing with this code, do it to x_unfocus_frame too. */
6345 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6346 RevertToPointerRoot
, CurrentTime
);
6356 /* Raise frame F. */
6362 if (f
->async_visible
)
6365 BringToFront (FRAME_MAC_WINDOW (f
));
6370 /* Lower frame F. */
6376 if (f
->async_visible
)
6379 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6385 XTframe_raise_lower (f
, raise_flag
)
6395 /* Change of visibility. */
6398 mac_handle_visibility_change (f
)
6401 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6402 int visible
= 0, iconified
= 0;
6403 struct input_event buf
;
6405 if (IsWindowVisible (wp
))
6407 if (IsWindowCollapsed (wp
))
6413 if (!f
->async_visible
&& visible
)
6417 /* wait_reading_process_output will notice this and update
6418 the frame's display structures. If we were made
6419 invisible, we should not set garbaged, because that stops
6420 redrawing on Update events. */
6421 SET_FRAME_GARBAGED (f
);
6424 buf
.kind
= DEICONIFY_EVENT
;
6425 XSETFRAME (buf
.frame_or_window
, f
);
6427 kbd_buffer_store_event (&buf
);
6429 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6430 /* Force a redisplay sooner or later to update the
6431 frame titles in case this is the second frame. */
6432 record_asynch_buffer_change ();
6434 else if (f
->async_visible
&& !visible
)
6438 buf
.kind
= ICONIFY_EVENT
;
6439 XSETFRAME (buf
.frame_or_window
, f
);
6441 kbd_buffer_store_event (&buf
);
6444 f
->async_visible
= visible
;
6445 f
->async_iconified
= iconified
;
6448 /* This tries to wait until the frame is really visible.
6449 However, if the window manager asks the user where to position
6450 the frame, this will return before the user finishes doing that.
6451 The frame will not actually be visible at that time,
6452 but it will become visible later when the window manager
6453 finishes with it. */
6456 x_make_frame_visible (f
)
6461 if (! FRAME_VISIBLE_P (f
))
6463 /* We test FRAME_GARBAGED_P here to make sure we don't
6464 call x_set_offset a second time
6465 if we get to x_make_frame_visible a second time
6466 before the window gets really visible. */
6467 if (! FRAME_ICONIFIED_P (f
)
6468 && ! f
->output_data
.mac
->asked_for_visible
)
6470 #if TARGET_API_MAC_CARBON
6471 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6473 struct frame
*sf
= SELECTED_FRAME ();
6474 if (!FRAME_MAC_P (sf
))
6475 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6476 kWindowCenterOnMainScreen
);
6478 RepositionWindow (FRAME_MAC_WINDOW (f
),
6479 FRAME_MAC_WINDOW (sf
),
6480 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6481 kWindowCascadeStartAtParentWindowScreen
6483 kWindowCascadeOnParentWindowScreen
6486 #if USE_CARBON_EVENTS
6487 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6489 mac_handle_origin_change (f
);
6493 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6496 f
->output_data
.mac
->asked_for_visible
= 1;
6498 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6499 ShowWindow (FRAME_MAC_WINDOW (f
));
6502 XFlush (FRAME_MAC_DISPLAY (f
));
6504 /* Synchronize to ensure Emacs knows the frame is visible
6505 before we do anything else. We do this loop with input not blocked
6506 so that incoming events are handled. */
6511 /* This must come after we set COUNT. */
6514 XSETFRAME (frame
, f
);
6516 /* Wait until the frame is visible. Process X events until a
6517 MapNotify event has been seen, or until we think we won't get a
6518 MapNotify at all.. */
6519 for (count
= input_signal_count
+ 10;
6520 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6522 /* Force processing of queued events. */
6525 /* Machines that do polling rather than SIGIO have been
6526 observed to go into a busy-wait here. So we'll fake an
6527 alarm signal to let the handler know that there's something
6528 to be read. We used to raise a real alarm, but it seems
6529 that the handler isn't always enabled here. This is
6531 if (input_polling_used ())
6533 /* It could be confusing if a real alarm arrives while
6534 processing the fake one. Turn it off and let the
6535 handler reset it. */
6536 extern void poll_for_input_1
P_ ((void));
6537 int old_poll_suppress_count
= poll_suppress_count
;
6538 poll_suppress_count
= 1;
6539 poll_for_input_1 ();
6540 poll_suppress_count
= old_poll_suppress_count
;
6543 /* See if a MapNotify event has been processed. */
6544 FRAME_SAMPLE_VISIBILITY (f
);
6549 /* Change from mapped state to withdrawn state. */
6551 /* Make the frame visible (mapped and not iconified). */
6554 x_make_frame_invisible (f
)
6557 /* A deactivate event does not occur when the last visible frame is
6558 made invisible. So if we clear the highlight here, it will not
6559 be rehighlighted when it is made visible. */
6561 /* Don't keep the highlight on an invisible frame. */
6562 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6563 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6568 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6569 that the current position of the window is user-specified, rather than
6570 program-specified, so that when the window is mapped again, it will be
6571 placed at the same location, without forcing the user to position it
6572 by hand again (they have already done that once for this window.) */
6573 x_wm_set_size_hint (f
, (long) 0, 1);
6575 HideWindow (FRAME_MAC_WINDOW (f
));
6579 #if !USE_CARBON_EVENTS
6580 mac_handle_visibility_change (f
);
6584 /* Change window state from mapped to iconified. */
6592 /* A deactivate event does not occur when the last visible frame is
6593 iconified. So if we clear the highlight here, it will not be
6594 rehighlighted when it is deiconified. */
6596 /* Don't keep the highlight on an invisible frame. */
6597 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6598 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6601 if (f
->async_iconified
)
6606 FRAME_SAMPLE_VISIBILITY (f
);
6608 if (! FRAME_VISIBLE_P (f
))
6609 ShowWindow (FRAME_MAC_WINDOW (f
));
6611 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6616 error ("Can't notify window manager of iconification");
6618 #if !USE_CARBON_EVENTS
6619 mac_handle_visibility_change (f
);
6624 /* Free X resources of frame F. */
6627 x_free_frame_resources (f
)
6630 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6631 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6635 if (wp
!= tip_window
)
6636 remove_window_handler (wp
);
6639 mac_prepare_for_quickdraw (f
);
6642 if (wp
== tip_window
)
6643 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6644 closed' event. So we reset tip_window here. */
6647 free_frame_menubar (f
);
6649 if (FRAME_FACE_CACHE (f
))
6650 free_frame_faces (f
);
6654 if (FRAME_SIZE_HINTS (f
))
6655 xfree (FRAME_SIZE_HINTS (f
));
6657 xfree (f
->output_data
.mac
);
6658 f
->output_data
.mac
= NULL
;
6660 if (f
== dpyinfo
->x_focus_frame
)
6662 dpyinfo
->x_focus_frame
= 0;
6663 #if USE_MAC_FONT_PANEL
6664 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6667 if (f
== dpyinfo
->x_focus_event_frame
)
6668 dpyinfo
->x_focus_event_frame
= 0;
6669 if (f
== dpyinfo
->x_highlight_frame
)
6670 dpyinfo
->x_highlight_frame
= 0;
6672 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6674 dpyinfo
->mouse_face_beg_row
6675 = dpyinfo
->mouse_face_beg_col
= -1;
6676 dpyinfo
->mouse_face_end_row
6677 = dpyinfo
->mouse_face_end_col
= -1;
6678 dpyinfo
->mouse_face_window
= Qnil
;
6679 dpyinfo
->mouse_face_deferred_gc
= 0;
6680 dpyinfo
->mouse_face_mouse_frame
= 0;
6687 /* Destroy the X window of frame F. */
6690 x_destroy_window (f
)
6693 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6695 x_free_frame_resources (f
);
6697 dpyinfo
->reference_count
--;
6701 /* Setting window manager hints. */
6703 /* Set the normal size hints for the window manager, for frame F.
6704 FLAGS is the flags word to use--or 0 meaning preserve the flags
6705 that the window now has.
6706 If USER_POSITION is nonzero, we set the USPosition
6707 flag (this is useful when FLAGS is 0). */
6709 x_wm_set_size_hint (f
, flags
, user_position
)
6714 int base_width
, base_height
, width_inc
, height_inc
;
6715 int min_rows
= 0, min_cols
= 0;
6716 XSizeHints
*size_hints
;
6718 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6719 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6720 width_inc
= FRAME_COLUMN_WIDTH (f
);
6721 height_inc
= FRAME_LINE_HEIGHT (f
);
6723 check_frame_size (f
, &min_rows
, &min_cols
);
6725 size_hints
= FRAME_SIZE_HINTS (f
);
6726 if (size_hints
== NULL
)
6728 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6729 bzero (size_hints
, sizeof (XSizeHints
));
6732 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6733 size_hints
->width_inc
= width_inc
;
6734 size_hints
->height_inc
= height_inc
;
6735 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6736 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6737 size_hints
->base_width
= base_width
;
6738 size_hints
->base_height
= base_height
;
6741 size_hints
->flags
= flags
;
6742 else if (user_position
)
6744 size_hints
->flags
&= ~ PPosition
;
6745 size_hints
->flags
|= USPosition
;
6749 #if 0 /* MAC_TODO: hide application instead of iconify? */
6750 /* Used for IconicState or NormalState */
6753 x_wm_set_window_state (f
, state
)
6757 #ifdef USE_X_TOOLKIT
6760 XtSetArg (al
[0], XtNinitialState
, state
);
6761 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6762 #else /* not USE_X_TOOLKIT */
6763 Window window
= FRAME_X_WINDOW (f
);
6765 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6766 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6768 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6769 #endif /* not USE_X_TOOLKIT */
6773 x_wm_set_icon_pixmap (f
, pixmap_id
)
6779 #ifndef USE_X_TOOLKIT
6780 Window window
= FRAME_X_WINDOW (f
);
6785 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6786 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6790 /* It seems there is no way to turn off use of an icon pixmap.
6791 The following line does it, only if no icon has yet been created,
6792 for some window managers. But with mwm it crashes.
6793 Some people say it should clear the IconPixmapHint bit in this case,
6794 but that doesn't work, and the X consortium said it isn't the
6795 right thing at all. Since there is no way to win,
6796 best to explicitly give up. */
6798 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6804 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6808 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6809 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6812 #else /* not USE_X_TOOLKIT */
6814 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6815 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6817 #endif /* not USE_X_TOOLKIT */
6820 #endif /* MAC_TODO */
6823 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6827 #if 0 /* MAC_TODO: no icons on Mac */
6828 #ifdef USE_X_TOOLKIT
6829 Window window
= XtWindow (f
->output_data
.x
->widget
);
6831 Window window
= FRAME_X_WINDOW (f
);
6834 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6835 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6836 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6838 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6839 #endif /* MAC_TODO */
6843 /***********************************************************************
6845 ***********************************************************************/
6847 /* An XLFD pattern is divided into blocks delimited by '*'. This
6848 structure holds information for each block. */
6849 struct xlfdpat_block
6851 /* Length of the pattern string in this block. Non-zero except for
6852 the first and the last blocks. */
6855 /* Pattern string except the last character in this block. The last
6856 character is replaced with NUL in order to use it as a
6858 unsigned char *pattern
;
6860 /* Last character of the pattern string. Must not be '?'. */
6861 unsigned char last_char
;
6863 /* One of the tables for the Boyer-Moore string search. It
6864 specifies the number of positions to proceed for each character
6865 with which the match fails. */
6868 /* The skip value for the last character in the above `skip' is
6869 assigned to `infinity' in order to simplify a loop condition.
6870 The original value is saved here. */
6876 /* Normalized pattern string. "Normalized" means that capital
6877 letters are lowered, blocks are not empty except the first and
6878 the last ones, and trailing '?'s in a block that is not the last
6879 one are moved to the next one. The last character in each block
6880 is replaced with NUL. */
6883 /* Number of characters except '*'s and trailing '?'s in the
6884 normalized pattern string. */
6887 /* Number of trailing '?'s in the normalized pattern string. */
6888 int trailing_anychars
;
6890 /* Number of blocks and information for each block. The latter is
6891 NULL if the pattern is exact (no '*' or '?' in it). */
6893 struct xlfdpat_block
*blocks
;
6897 xlfdpat_destroy (pat
)
6898 struct xlfdpat
*pat
;
6905 xfree (pat
->blocks
);
6912 static struct xlfdpat
*
6913 xlfdpat_create (pattern
)
6914 const char *pattern
;
6916 struct xlfdpat
*pat
;
6917 int nblocks
, i
, skip
;
6918 unsigned char last_char
, *p
, *q
, *anychar_head
;
6919 const unsigned char *ptr
;
6920 struct xlfdpat_block
*blk
;
6922 pat
= xmalloc (sizeof (struct xlfdpat
));
6923 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6925 /* Normalize the pattern string and store it to `pat->buf'. */
6927 anychar_head
= NULL
;
6930 for (ptr
= pattern
; *ptr
; ptr
++)
6932 unsigned char c
= *ptr
;
6935 if (last_char
== '*')
6936 /* ...a** -> ...a* */
6940 if (last_char
== '?')
6942 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6943 /* ...*??* -> ...*?? */
6946 /* ...a??* -> ...a*?? */
6948 *anychar_head
++ = '*';
6956 if (last_char
!= '?')
6960 /* On Mac OS X 10.3, tolower also converts non-ASCII
6961 characters for some locales. */
6965 *q
++ = last_char
= c
;
6969 pat
->nblocks
= nblocks
;
6970 if (last_char
!= '?')
6971 pat
->trailing_anychars
= 0;
6974 pat
->trailing_anychars
= q
- anychar_head
;
6977 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6979 if (anychar_head
== NULL
&& nblocks
== 1)
6981 /* The pattern is exact. */
6986 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6988 /* Divide the normalized pattern into blocks. */
6990 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6995 blk
->len
= p
- blk
->pattern
;
6999 blk
->len
= q
- blk
->pattern
;
7001 /* Setup a table for the Boyer-Moore string search. */
7002 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7005 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7006 blk
->pattern
[blk
->len
- 1] = '\0';
7008 for (skip
= 1; skip
< blk
->len
; skip
++)
7009 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7012 for (i
= 0; i
< 256; i
++)
7013 blk
->skip
[i
] = skip
;
7015 p
= blk
->pattern
+ (blk
->len
- skip
);
7017 blk
->skip
[*p
++] = skip
;
7019 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7026 xlfdpat_exact_p (pat
)
7027 struct xlfdpat
*pat
;
7029 return pat
->blocks
== NULL
;
7032 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7033 that the pattern in *BLK matches with its prefix. Return NULL
7034 there is no such strings. STRING must be lowered in advance. */
7037 xlfdpat_block_match_1 (blk
, string
, start_max
)
7038 struct xlfdpat_block
*blk
;
7039 const unsigned char *string
;
7042 int start
, infinity
;
7044 const unsigned char *s
;
7046 xassert (blk
->len
> 0);
7047 xassert (start_max
+ blk
->len
<= strlen (string
));
7048 xassert (blk
->last_char
!= '?');
7050 /* See the comments in the function `boyer_moore' (search.c) for the
7051 use of `infinity'. */
7052 infinity
= start_max
+ blk
->len
+ 1;
7053 blk
->skip
[blk
->last_char
] = infinity
;
7058 /* Check the last character of the pattern. */
7059 s
= string
+ blk
->len
- 1;
7062 start
+= blk
->skip
[*(s
+ start
)];
7064 while (start
<= start_max
);
7066 if (start
< infinity
)
7067 /* Couldn't find the last character. */
7070 /* No less than `infinity' means we could find the last
7071 character at `s[start - infinity]'. */
7074 /* Check the remaining characters. We prefer making no-'?'
7075 cases faster because the use of '?' is really rare. */
7080 while (*p
++ == *s
++)
7083 while (*(p
- 1) == '?');
7085 if (*(p
- 1) == '\0')
7087 return string
+ start
;
7090 start
+= blk
->last_char_skip
;
7092 while (start
<= start_max
);
7097 #define xlfdpat_block_match(b, s, m) \
7098 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7099 : xlfdpat_block_match_1 (b, s, m))
7101 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7102 matches with STRING. STRING must be lowered in advance. */
7105 xlfdpat_match (pat
, string
)
7106 struct xlfdpat
*pat
;
7107 const unsigned char *string
;
7109 int str_len
, nblocks
, i
, start_max
;
7110 struct xlfdpat_block
*blk
;
7111 const unsigned char *s
;
7113 xassert (pat
->nblocks
> 0);
7115 if (xlfdpat_exact_p (pat
))
7116 return strcmp (pat
->buf
, string
) == 0;
7118 /* The number of the characters in the string must not be smaller
7119 than that in the pattern. */
7120 str_len
= strlen (string
);
7121 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7124 /* Chop off the trailing '?'s. */
7125 str_len
-= pat
->trailing_anychars
;
7127 /* The last block. When it is non-empty, it must match at the end
7129 nblocks
= pat
->nblocks
;
7130 blk
= pat
->blocks
+ (nblocks
- 1);
7132 /* The last block is also the first one. */
7133 return (str_len
== blk
->len
7134 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7135 else if (blk
->len
!= 0)
7136 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7139 /* The first block. When it is non-empty, it must match at the
7140 beginning of the string. */
7144 s
= xlfdpat_block_match (blk
, string
, 0);
7147 string
= s
+ blk
->len
;
7150 /* The rest of the blocks. */
7151 start_max
= str_len
- pat
->nchars
;
7152 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7154 s
= xlfdpat_block_match (blk
, string
, start_max
);
7157 start_max
-= s
- string
;
7158 string
= s
+ blk
->len
;
7165 /***********************************************************************
7167 ***********************************************************************/
7169 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7172 x_get_font_info (f
, font_idx
)
7176 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7179 /* the global font name table */
7180 static char **font_name_table
= NULL
;
7181 static int font_name_table_size
= 0;
7182 static int font_name_count
= 0;
7184 /* Alist linking font family names to Font Manager font family
7185 references (which can also be used as QuickDraw font IDs). We use
7186 an alist because hash tables are not ready when the terminal frame
7187 for Mac OS Classic is created. */
7188 static Lisp_Object fm_font_family_alist
;
7190 /* Hash table linking font family names to ATSU font IDs. */
7191 static Lisp_Object atsu_font_id_hash
;
7192 /* Alist linking Font Manager style to face attributes. */
7193 static Lisp_Object fm_style_face_attributes_alist
;
7194 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7197 /* Alist linking character set strings to Mac text encoding and Emacs
7199 static Lisp_Object Vmac_charset_info_alist
;
7202 create_text_encoding_info_alist ()
7204 Lisp_Object result
= Qnil
, rest
;
7206 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7208 Lisp_Object charset_info
= XCAR (rest
);
7209 Lisp_Object charset
, coding_system
, text_encoding
;
7210 Lisp_Object existing_info
;
7212 if (!(CONSP (charset_info
)
7213 && (charset
= XCAR (charset_info
),
7215 && CONSP (XCDR (charset_info
))
7216 && (text_encoding
= XCAR (XCDR (charset_info
)),
7217 INTEGERP (text_encoding
))
7218 && CONSP (XCDR (XCDR (charset_info
)))
7219 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7220 SYMBOLP (coding_system
))))
7223 existing_info
= assq_no_quit (text_encoding
, result
);
7224 if (NILP (existing_info
))
7225 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7228 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7229 XSETCDR (XCDR (existing_info
),
7230 Fcons (charset
, XCDR (XCDR (existing_info
))));
7238 decode_mac_font_name (name
, size
, coding_system
)
7241 Lisp_Object coding_system
;
7243 struct coding_system coding
;
7246 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7248 for (p
= name
; *p
; p
++)
7249 if (!isascii (*p
) || iscntrl (*p
))
7254 setup_coding_system (coding_system
, &coding
);
7255 coding
.src_multibyte
= 0;
7256 coding
.dst_multibyte
= 1;
7257 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7258 coding
.composing
= COMPOSITION_DISABLED
;
7259 buf
= (char *) alloca (size
);
7261 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7262 bcopy (buf
, name
, coding
.produced
);
7263 name
[coding
.produced
] = '\0';
7267 /* If there's just one occurrence of '-' in the family name, it is
7268 replaced with '_'. (More than one occurrence of '-' means a
7269 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7270 p
= strchr (name
, '-');
7271 if (p
&& strchr (p
+ 1, '-') == NULL
)
7274 for (p
= name
; *p
; p
++)
7275 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7276 for some locales. */
7283 mac_to_x_fontname (name
, size
, style
, charset
)
7291 char xf
[256], *result
;
7294 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7298 strcpy(foundry
, "Apple");
7299 strcpy(family
, name
);
7302 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7303 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7304 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7306 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7307 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7308 for (p
= result
; *p
; p
++)
7309 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7310 for some locales. */
7317 /* Parse fully-specified and instantiated X11 font spec XF, and store
7318 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7319 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7320 caller must allocate at least 256 and 32 bytes respectively. For
7321 ordinary Mac fonts, the value stored to FAMILY should just be their
7322 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7323 intlfonts collection contain their charset designation in their
7324 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7325 types of font names are handled accordingly. */
7327 const int kDefaultFontSize
= 12;
7330 parse_x_font_name (xf
, family
, size
, style
, charset
)
7337 Str31 foundry
, weight
;
7338 int point_size
, avgwidth
;
7341 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7342 foundry
, family
, weight
, slant
, size
,
7343 &point_size
, &avgwidth
, charset
) != 8
7344 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7345 foundry
, family
, weight
, slant
, size
,
7346 &point_size
, &avgwidth
, charset
) != 8)
7352 *size
= point_size
/ 10;
7353 else if (avgwidth
> 0)
7354 *size
= avgwidth
/ 10;
7357 *size
= kDefaultFontSize
;
7360 if (strcmp (weight
, "bold") == 0)
7365 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7367 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7369 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7371 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7372 but take overlap into account. */
7373 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7374 memcpy (family
, foundry
, foundry_len
);
7375 family
[foundry_len
] = '-';
7376 family
[foundry_len
+ 1 + family_len
] = '-';
7377 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7383 for (p
= family
; *p
; p
++)
7384 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7385 for some locales. */
7394 add_font_name_table_entry (char *font_name
)
7396 if (font_name_table_size
== 0)
7398 font_name_table_size
= 256;
7399 font_name_table
= (char **)
7400 xmalloc (font_name_table_size
* sizeof (char *));
7402 else if (font_name_count
+ 1 >= font_name_table_size
)
7404 font_name_table_size
*= 2;
7405 font_name_table
= (char **)
7406 xrealloc (font_name_table
,
7407 font_name_table_size
* sizeof (char *));
7410 font_name_table
[font_name_count
++] = font_name
;
7414 add_mac_font_name (name
, size
, style
, charset
)
7418 const char *charset
;
7421 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7424 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7425 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7426 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7427 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7434 fm_get_style_from_font (font
)
7438 FMFontStyle style
= normal
;
7441 FMFontFamily font_family
;
7442 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
7444 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
7445 some font (e.g., Optima) even if it is `bold'. */
7446 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
7447 sizeof (mac_style
), &mac_style
, &len
);
7449 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
7450 style
= EndianU16_BtoN (mac_style
);
7452 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
7458 atsu_find_font_from_family_name (family
)
7461 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
7464 Lisp_Object rest
, best
;
7465 FMFontStyle min_style
, style
;
7467 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
7470 return kATSUInvalidFontID
;
7472 rest
= HASH_VALUE (h
, i
);
7473 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
7474 return cons_to_long (rest
);
7476 rest
= Fnreverse (rest
);
7480 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
7483 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
7484 if (style
< min_style
)
7487 if (style
== normal
)
7494 while (!NILP (rest
));
7496 HASH_VALUE (h
, i
) = best
;
7497 return cons_to_long (best
);
7501 fm_style_to_face_attributes (fm_style
)
7502 FMFontStyle fm_style
;
7506 fm_style
&= (bold
| italic
);
7507 tem
= assq_no_quit (make_number (fm_style
),
7508 fm_style_face_attributes_alist
);
7512 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
7513 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
7514 fm_style_face_attributes_alist
=
7515 Fcons (Fcons (make_number (fm_style
), tem
),
7516 fm_style_face_attributes_alist
);
7522 atsu_find_font_family_name (font_id
)
7527 Lisp_Object family
= Qnil
;
7529 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7530 kFontMacintoshPlatform
, kFontNoScript
,
7531 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
7534 family
= make_uninit_string (len
);
7535 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7536 kFontMacintoshPlatform
, kFontNoScript
,
7537 kFontNoLanguage
, len
, SDATA (family
),
7541 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
7547 mac_atsu_font_face_attributes (font_id
)
7550 Lisp_Object family
, style_attrs
;
7552 family
= atsu_find_font_family_name (font_id
);
7555 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
7556 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
7560 /* Sets up the table font_name_table to contain the list of all fonts
7561 in the system the first time the table is used so that the Resource
7562 Manager need not be accessed every time this information is
7566 init_font_name_table ()
7568 #if TARGET_API_MAC_CARBON
7569 FMFontFamilyIterator ffi
;
7570 FMFontFamilyInstanceIterator ffii
;
7572 Lisp_Object text_encoding_info_alist
;
7573 struct gcpro gcpro1
;
7575 text_encoding_info_alist
= create_text_encoding_info_alist ();
7578 #if USE_CG_TEXT_DRAWING
7579 init_cg_text_anti_aliasing_threshold ();
7581 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7582 text_encoding_info_alist
)))
7585 struct Lisp_Hash_Table
*h
;
7587 ItemCount nfonts
, i
;
7588 ATSUFontID
*font_ids
= NULL
;
7589 Lisp_Object prev_family
= Qnil
;
7593 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7594 make_float (DEFAULT_REHASH_SIZE
),
7595 make_float (DEFAULT_REHASH_THRESHOLD
),
7597 h
= XHASH_TABLE (atsu_font_id_hash
);
7599 err
= ATSUFontCount (&nfonts
);
7602 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7603 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7606 for (i
= 0; i
< nfonts
; i
++)
7610 family
= atsu_find_font_family_name (font_ids
[i
]);
7611 if (NILP (family
) || SREF (family
, 0) == '.')
7613 if (!NILP (Fequal (prev_family
, family
)))
7614 family
= prev_family
;
7616 j
= hash_lookup (h
, family
, &hash_code
);
7619 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
7620 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
7623 else if (EQ (prev_family
, family
))
7624 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
7626 prev_family
= family
;
7633 /* Create a dummy instance iterator here to avoid creating and
7634 destroying it in the loop. */
7635 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7637 /* Create an iterator to enumerate the font families. */
7638 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7641 FMDisposeFontFamilyInstanceIterator (&ffii
);
7645 GCPRO1 (text_encoding_info_alist
);
7647 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7653 TextEncoding encoding
;
7654 TextEncodingBase sc
;
7655 Lisp_Object text_encoding_info
, family
;
7657 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7663 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7665 sc
= GetTextEncodingBase (encoding
);
7666 text_encoding_info
= assq_no_quit (make_number (sc
),
7667 text_encoding_info_alist
);
7668 if (NILP (text_encoding_info
))
7669 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7670 text_encoding_info_alist
);
7671 decode_mac_font_name (name
, sizeof (name
),
7672 XCAR (XCDR (text_encoding_info
)));
7673 family
= build_string (name
);
7674 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7676 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7677 fm_font_family_alist
);
7679 /* Point the instance iterator at the current font family. */
7680 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7683 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7686 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7688 if (size
> 0 || style
== normal
)
7689 for (; !NILP (rest
); rest
= XCDR (rest
))
7690 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7696 /* Dispose of the iterators. */
7697 FMDisposeFontFamilyIterator (&ffi
);
7698 FMDisposeFontFamilyInstanceIterator (&ffii
);
7699 #else /* !TARGET_API_MAC_CARBON */
7701 SInt16 fontnum
, old_fontnum
;
7702 int num_mac_fonts
= CountResources('FOND');
7704 Handle font_handle
, font_handle_2
;
7705 short id
, scriptcode
;
7708 struct FontAssoc
*fat
;
7709 struct AsscEntry
*assc_entry
;
7710 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7711 struct gcpro gcpro1
;
7713 GetPort (&port
); /* save the current font number used */
7714 old_fontnum
= port
->txFont
;
7716 text_encoding_info_alist
= create_text_encoding_info_alist ();
7718 GCPRO1 (text_encoding_info_alist
);
7720 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7722 font_handle
= GetIndResource ('FOND', i
);
7726 GetResInfo (font_handle
, &id
, &type
, name
);
7727 GetFNum (name
, &fontnum
);
7729 if (fontnum
== 0 || *name
== '.')
7733 scriptcode
= FontToScript (fontnum
);
7734 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7735 text_encoding_info_alist
);
7736 if (NILP (text_encoding_info
))
7737 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7738 text_encoding_info_alist
);
7739 decode_mac_font_name (name
, sizeof (name
),
7740 XCAR (XCDR (text_encoding_info
)));
7741 family
= build_string (name
);
7742 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7744 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7745 fm_font_family_alist
);
7748 HLock (font_handle
);
7750 if (GetResourceSizeOnDisk (font_handle
)
7751 >= sizeof (struct FamRec
))
7753 fat
= (struct FontAssoc
*) (*font_handle
7754 + sizeof (struct FamRec
));
7756 = (struct AsscEntry
*) (*font_handle
7757 + sizeof (struct FamRec
)
7758 + sizeof (struct FontAssoc
));
7760 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7762 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7764 for (; !NILP (rest
); rest
= XCDR (rest
))
7765 add_mac_font_name (name
, assc_entry
->fontSize
,
7766 assc_entry
->fontStyle
,
7767 SDATA (XCAR (rest
)));
7771 HUnlock (font_handle
);
7772 font_handle_2
= GetNextFOND (font_handle
);
7773 ReleaseResource (font_handle
);
7774 font_handle
= font_handle_2
;
7776 while (ResError () == noErr
&& font_handle
);
7781 TextFont (old_fontnum
);
7782 #endif /* !TARGET_API_MAC_CARBON */
7787 mac_clear_font_name_table ()
7791 for (i
= 0; i
< font_name_count
; i
++)
7792 xfree (font_name_table
[i
]);
7793 xfree (font_name_table
);
7794 font_name_table
= NULL
;
7795 font_name_table_size
= font_name_count
= 0;
7796 fm_font_family_alist
= Qnil
;
7800 enum xlfd_scalable_field_index
7802 XLFD_SCL_PIXEL_SIZE
,
7803 XLFD_SCL_POINT_SIZE
,
7808 static const int xlfd_scalable_fields
[] =
7817 mac_do_list_fonts (pattern
, maxnames
)
7818 const char *pattern
;
7822 Lisp_Object font_list
= Qnil
;
7823 struct xlfdpat
*pat
;
7826 int scl_val
[XLFD_SCL_LAST
], *val
;
7830 if (font_name_table
== NULL
) /* Initialize when first used. */
7831 init_font_name_table ();
7833 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7836 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7837 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7838 fonts are scaled according to the specified size. */
7841 field
= xlfd_scalable_fields
;
7849 if ('0' <= *ptr
&& *ptr
<= '9')
7851 *val
= *ptr
++ - '0';
7852 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7853 *val
= *val
* 10 + *ptr
++ - '0';
7860 ptr
= strchr (ptr
, '-');
7863 while (ptr
&& i
< 14);
7865 if (i
== 14 && ptr
== NULL
)
7867 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7868 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7869 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7870 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7872 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7873 scl_val
[XLFD_SCL_POINT_SIZE
] =
7874 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7875 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7877 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7878 scl_val
[XLFD_SCL_AVGWIDTH
] =
7879 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7880 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7884 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7886 pat
= xlfdpat_create (pattern
);
7890 exact
= xlfdpat_exact_p (pat
);
7892 for (i
= 0; i
< font_name_count
; i
++)
7894 if (xlfdpat_match (pat
, font_name_table
[i
]))
7896 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7897 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7900 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7901 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7903 int former_len
= ptr
- font_name_table
[i
];
7905 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7906 memcpy (scaled
, font_name_table
[i
], former_len
);
7907 sprintf (scaled
+ former_len
,
7908 "-%d-%d-72-72-m-%d-%s",
7909 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7910 scl_val
[XLFD_SCL_POINT_SIZE
],
7911 scl_val
[XLFD_SCL_AVGWIDTH
],
7912 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7914 if (xlfdpat_match (pat
, scaled
))
7916 font_list
= Fcons (build_string (scaled
), font_list
);
7918 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7926 xlfdpat_destroy (pat
);
7931 /* Return a list of names of available fonts matching PATTERN on frame F.
7933 Frame F null means we have not yet created any frame on Mac, and
7934 consult the first display in x_display_list. MAXNAMES sets a limit
7935 on how many fonts to match. */
7938 x_list_fonts (f
, pattern
, size
, maxnames
)
7940 Lisp_Object pattern
;
7943 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7944 struct mac_display_info
*dpyinfo
7945 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7947 xassert (size
<= 0);
7949 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7950 if (NILP (patterns
))
7951 patterns
= Fcons (pattern
, Qnil
);
7953 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7955 pattern
= XCAR (patterns
);
7957 if (!STRINGP (pattern
))
7960 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7961 key
= Fcons (pattern
, make_number (maxnames
));
7963 list
= Fassoc (key
, tem
);
7966 list
= Fcdr_safe (list
);
7967 /* We have a cashed list. Don't have to get the list again. */
7972 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7975 /* MAC_TODO: add code for matching outline fonts here */
7977 /* Now store the result in the cache. */
7978 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7979 Fcons (Fcons (key
, list
),
7980 XCAR (XCDR (dpyinfo
->name_list_element
))));
7983 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7992 /* Check that FONT is valid on frame F. It is if it can be found in F's
7996 x_check_font (f
, font
)
8001 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8003 xassert (font
!= NULL
);
8005 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8006 if (dpyinfo
->font_table
[i
].name
8007 && font
== dpyinfo
->font_table
[i
].font
)
8010 xassert (i
< dpyinfo
->n_fonts
);
8013 #endif /* GLYPH_DEBUG != 0 */
8015 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8016 Note: There are (broken) X fonts out there with invalid XFontStruct
8017 min_bounds contents. For example, handa@etl.go.jp reports that
8018 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8019 have font->min_bounds.width == 0. */
8022 x_font_min_bounds (font
, w
, h
)
8023 MacFontStruct
*font
;
8026 *h
= FONT_HEIGHT (font
);
8027 *w
= font
->min_bounds
.width
;
8031 /* Compute the smallest character width and smallest font height over
8032 all fonts available on frame F. Set the members smallest_char_width
8033 and smallest_font_height in F's x_display_info structure to
8034 the values computed. Value is non-zero if smallest_font_height or
8035 smallest_char_width become smaller than they were before. */
8038 x_compute_min_glyph_bounds (f
)
8042 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8043 MacFontStruct
*font
;
8044 int old_width
= dpyinfo
->smallest_char_width
;
8045 int old_height
= dpyinfo
->smallest_font_height
;
8047 dpyinfo
->smallest_font_height
= 100000;
8048 dpyinfo
->smallest_char_width
= 100000;
8050 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8051 if (dpyinfo
->font_table
[i
].name
)
8053 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8056 font
= (MacFontStruct
*) fontp
->font
;
8057 xassert (font
!= (MacFontStruct
*) ~0);
8058 x_font_min_bounds (font
, &w
, &h
);
8060 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8061 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8064 xassert (dpyinfo
->smallest_char_width
> 0
8065 && dpyinfo
->smallest_font_height
> 0);
8067 return (dpyinfo
->n_fonts
== 1
8068 || dpyinfo
->smallest_char_width
< old_width
8069 || dpyinfo
->smallest_font_height
< old_height
);
8073 /* Determine whether given string is a fully-specified XLFD: all 14
8074 fields are present, none is '*'. */
8077 is_fully_specified_xlfd (p
)
8086 for (i
= 0; i
< 13; i
++)
8088 q
= strchr (p
+ 1, '-');
8091 if (q
- p
== 2 && *(p
+ 1) == '*')
8096 if (strchr (p
+ 1, '-') != NULL
)
8099 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8106 /* mac_load_query_font creates and returns an internal representation
8107 for a font in a MacFontStruct struct. There is really no concept
8108 corresponding to "loading" a font on the Mac. But we check its
8109 existence and find the font number and all other information for it
8110 and store them in the returned MacFontStruct. */
8112 static MacFontStruct
*
8113 mac_load_query_font (f
, fontname
)
8123 static ATSUFontID font_id
;
8124 ATSUStyle mac_style
= NULL
;
8127 #if TARGET_API_MAC_CARBON
8128 TextEncoding encoding
;
8133 MacFontStruct
*font
;
8134 XCharStruct
*space_bounds
= NULL
, *pcm
;
8136 if (is_fully_specified_xlfd (fontname
))
8140 Lisp_Object matched_fonts
;
8142 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8143 if (NILP (matched_fonts
))
8145 name
= SDATA (XCAR (matched_fonts
));
8148 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8152 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8155 static const ATSUAttributeTag tags
[] =
8156 {kATSUFontTag
, kATSUSizeTag
,
8157 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8158 static const ByteCount sizes
[] =
8159 {sizeof (ATSUFontID
), sizeof (Fixed
),
8160 sizeof (Boolean
), sizeof (Boolean
)};
8161 static Fixed size_fixed
;
8162 static Boolean bold_p
, italic_p
;
8163 static const ATSUAttributeValuePtr values
[] =
8164 {&font_id
, &size_fixed
,
8165 &bold_p
, &italic_p
};
8166 static const ATSUFontFeatureType types
[] =
8167 {kAllTypographicFeaturesType
, kDiacriticsType
};
8168 static const ATSUFontFeatureSelector selectors
[] =
8169 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8172 font_id
= atsu_find_font_from_family_name (family
);
8173 if (font_id
== kATSUInvalidFontID
)
8175 size_fixed
= Long2Fix (size
);
8176 bold_p
= (fontface
& bold
) != 0;
8177 italic_p
= (fontface
& italic
) != 0;
8178 err
= ATSUCreateStyle (&mac_style
);
8181 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8185 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8186 tags
, sizes
, values
);
8189 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8192 scriptcode
= kTextEncodingMacUnicode
;
8197 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8201 fontnum
= XINT (XCDR (tmp
));
8202 #if TARGET_API_MAC_CARBON
8203 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8205 scriptcode
= GetTextEncodingBase (encoding
);
8207 scriptcode
= FontToScript (fontnum
);
8211 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8213 font
->mac_fontnum
= fontnum
;
8214 font
->mac_fontsize
= size
;
8215 font
->mac_fontface
= fontface
;
8216 font
->mac_scriptcode
= scriptcode
;
8218 font
->mac_style
= mac_style
;
8219 #if USE_CG_TEXT_DRAWING
8220 font
->cg_font
= NULL
;
8221 font
->cg_glyphs
= NULL
;
8225 /* Apple Japanese (SJIS) font is listed as both
8226 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8227 (Roman script) in init_font_name_table (). The latter should be
8228 treated as a one-byte font. */
8229 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8230 font
->mac_scriptcode
= smRoman
;
8232 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8235 if (font
->mac_style
)
8240 font
->min_byte1
= 0;
8241 font
->max_byte1
= 0xff;
8242 font
->min_char_or_byte2
= 0;
8243 font
->max_char_or_byte2
= 0xff;
8245 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8246 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8247 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8248 pcm_init (font
->bounds
.rows
[0], 0x100);
8250 #if USE_CG_TEXT_DRAWING
8254 ATSFontRef ats_font
;
8256 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8258 /* Use CG text drawing if italic/bold is not synthesized. */
8259 if (err
== noErr
&& style
== fontface
)
8261 ats_font
= FMGetATSFontRefFromFont (font_id
);
8262 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8268 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8269 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8272 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8273 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8274 &font
->ascent
, &font
->descent
,
8276 #if USE_CG_TEXT_DRAWING
8277 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8284 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8286 mac_unload_font (&one_mac_display_info
, font
);
8290 pcm
= font
->bounds
.rows
[0];
8291 for (c
= 0x21; c
<= 0xff; c
++)
8294 /* Soft hyphen is not supported in ATSUI. */
8298 #if USE_CG_TEXT_DRAWING
8299 if (font
->cg_glyphs
)
8309 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8310 pcm
? pcm
+ c
: NULL
,
8311 #if USE_CG_TEXT_DRAWING
8312 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8319 #if USE_CG_TEXT_DRAWING
8320 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8322 /* Don't use CG text drawing if font substitution occurs in
8323 ASCII or Latin-1 characters. */
8324 CGFontRelease (font
->cg_font
);
8325 font
->cg_font
= NULL
;
8326 xfree (font
->cg_glyphs
);
8327 font
->cg_glyphs
= NULL
;
8338 FontInfo the_fontinfo
;
8339 int is_two_byte_font
;
8342 mac_prepare_for_quickdraw (f
);
8344 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8348 TextFace (fontface
);
8350 GetFontInfo (&the_fontinfo
);
8352 font
->ascent
= the_fontinfo
.ascent
;
8353 font
->descent
= the_fontinfo
.descent
;
8355 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8356 || font
->mac_scriptcode
== smTradChinese
8357 || font
->mac_scriptcode
== smSimpChinese
8358 || font
->mac_scriptcode
== smKorean
);
8360 if (is_two_byte_font
)
8364 font
->min_byte1
= 0xa1;
8365 font
->max_byte1
= 0xfe;
8366 font
->min_char_or_byte2
= 0xa1;
8367 font
->max_char_or_byte2
= 0xfe;
8369 /* Use the width of an "ideographic space" of that font
8370 because the_fontinfo.widMax returns the wrong width for
8372 switch (font
->mac_scriptcode
)
8375 font
->min_byte1
= 0x81;
8376 font
->max_byte1
= 0xfc;
8377 font
->min_char_or_byte2
= 0x40;
8378 font
->max_char_or_byte2
= 0xfc;
8379 char_width
= StringWidth("\p\x81\x40");
8382 font
->min_char_or_byte2
= 0x40;
8383 char_width
= StringWidth("\p\xa1\x40");
8386 char_width
= StringWidth("\p\xa1\xa1");
8389 char_width
= StringWidth("\p\xa1\xa1");
8393 font
->bounds
.per_char
= NULL
;
8395 if (fontface
& italic
)
8396 font
->max_bounds
.rbearing
= char_width
+ 1;
8398 font
->max_bounds
.rbearing
= char_width
;
8399 font
->max_bounds
.lbearing
= 0;
8400 font
->max_bounds
.width
= char_width
;
8401 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8402 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8404 font
->min_bounds
= font
->max_bounds
;
8410 font
->min_byte1
= font
->max_byte1
= 0;
8411 font
->min_char_or_byte2
= 0x20;
8412 font
->max_char_or_byte2
= 0xff;
8414 font
->bounds
.per_char
=
8415 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8416 bzero (font
->bounds
.per_char
,
8417 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8419 space_bounds
= font
->bounds
.per_char
;
8420 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
8421 &font
->descent
, space_bounds
, NULL
);
8422 if (err
!= noErr
|| space_bounds
->width
<= 0)
8424 mac_unload_font (&one_mac_display_info
, font
);
8428 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8429 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8437 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8438 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8441 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8443 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8445 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8447 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8449 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
8452 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8454 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8456 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8458 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8460 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
8465 font
->mac_style
== NULL
&&
8467 font
->max_bounds
.width
== font
->min_bounds
.width
8468 && font
->min_bounds
.lbearing
>= 0
8469 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8471 /* Fixed width and no overhangs. */
8472 xfree (font
->bounds
.per_char
);
8473 font
->bounds
.per_char
= NULL
;
8477 #if !defined (MAC_OS8) || USE_ATSUI
8478 /* AppKit and WebKit do some adjustment to the heights of Courier,
8479 Helvetica, and Times. This only works on the environments where
8480 srcCopy text transfer mode is never used. */
8482 #ifdef MAC_OS8 /* implies USE_ATSUI */
8485 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8486 || strcmp (family
, "times") == 0))
8487 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8495 mac_unload_font (dpyinfo
, font
)
8496 struct mac_display_info
*dpyinfo
;
8499 xfree (font
->full_name
);
8501 if (font
->mac_style
)
8505 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8506 if (font
->bounds
.rows
[i
])
8507 xfree (font
->bounds
.rows
[i
]);
8508 xfree (font
->bounds
.rows
);
8509 ATSUDisposeStyle (font
->mac_style
);
8513 if (font
->bounds
.per_char
)
8514 xfree (font
->bounds
.per_char
);
8515 #if USE_CG_TEXT_DRAWING
8517 CGFontRelease (font
->cg_font
);
8518 if (font
->cg_glyphs
)
8519 xfree (font
->cg_glyphs
);
8525 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8526 pointer to the structure font_info while allocating it dynamically.
8527 If SIZE is 0, load any size of font.
8528 If loading is failed, return NULL. */
8531 x_load_font (f
, fontname
, size
)
8533 register char *fontname
;
8536 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8537 Lisp_Object font_names
;
8539 /* Get a list of all the fonts that match this name. Once we
8540 have a list of matching fonts, we compare them against the fonts
8541 we already have by comparing names. */
8542 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8544 if (!NILP (font_names
))
8549 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8550 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8551 if (dpyinfo
->font_table
[i
].name
8552 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8553 SDATA (XCAR (tail
)))
8554 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8555 SDATA (XCAR (tail
)))))
8556 return (dpyinfo
->font_table
+ i
);
8561 /* Load the font and add it to the table. */
8563 struct MacFontStruct
*font
;
8564 struct font_info
*fontp
;
8567 fontname
= (char *) SDATA (XCAR (font_names
));
8570 font
= mac_load_query_font (f
, fontname
);
8575 /* Find a free slot in the font table. */
8576 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8577 if (dpyinfo
->font_table
[i
].name
== NULL
)
8580 /* If no free slot found, maybe enlarge the font table. */
8581 if (i
== dpyinfo
->n_fonts
8582 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8585 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8586 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8588 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8591 fontp
= dpyinfo
->font_table
+ i
;
8592 if (i
== dpyinfo
->n_fonts
)
8595 /* Now fill in the slots of *FONTP. */
8597 bzero (fontp
, sizeof (*fontp
));
8599 fontp
->font_idx
= i
;
8600 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8601 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8603 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8605 /* Fixed width font. */
8606 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8613 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8614 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8616 fontp
->space_width
= pcm
->width
;
8618 fontp
->space_width
= FONT_WIDTH (font
);
8622 int width
= pcm
->width
;
8623 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8624 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8625 width
+= pcm
->width
;
8626 fontp
->average_width
= width
/ 95;
8629 fontp
->average_width
= FONT_WIDTH (font
);
8632 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8633 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8635 fontp
->size
= font
->max_bounds
.width
;
8636 fontp
->height
= FONT_HEIGHT (font
);
8638 /* For some font, ascent and descent in max_bounds field is
8639 larger than the above value. */
8640 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8641 if (max_height
> fontp
->height
)
8642 fontp
->height
= max_height
;
8645 /* The slot `encoding' specifies how to map a character
8646 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8647 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8648 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8649 2:0xA020..0xFF7F). For the moment, we don't know which charset
8650 uses this font. So, we set information in fontp->encoding[1]
8651 which is never used by any charset. If mapping can't be
8652 decided, set FONT_ENCODING_NOT_DECIDED. */
8653 if (font
->mac_scriptcode
== smJapanese
)
8654 fontp
->encoding
[1] = 4;
8658 = (font
->max_byte1
== 0
8660 ? (font
->min_char_or_byte2
< 0x80
8661 ? (font
->max_char_or_byte2
< 0x80
8662 ? 0 /* 0x20..0x7F */
8663 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8664 : 1) /* 0xA0..0xFF */
8666 : (font
->min_byte1
< 0x80
8667 ? (font
->max_byte1
< 0x80
8668 ? (font
->min_char_or_byte2
< 0x80
8669 ? (font
->max_char_or_byte2
< 0x80
8670 ? 0 /* 0x2020..0x7F7F */
8671 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8672 : 3) /* 0x20A0..0x7FFF */
8673 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8674 : (font
->min_char_or_byte2
< 0x80
8675 ? (font
->max_char_or_byte2
< 0x80
8676 ? 2 /* 0xA020..0xFF7F */
8677 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8678 : 1))); /* 0xA0A0..0xFFFF */
8681 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8682 fontp
->baseline_offset
8683 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8684 ? (long) value
: 0);
8685 fontp
->relative_compose
8686 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8687 ? (long) value
: 0);
8688 fontp
->default_ascent
8689 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8690 ? (long) value
: 0);
8692 fontp
->baseline_offset
= 0;
8693 fontp
->relative_compose
= 0;
8694 fontp
->default_ascent
= 0;
8697 /* Set global flag fonts_changed_p to non-zero if the font loaded
8698 has a character with a smaller width than any other character
8699 before, or if the font loaded has a smaller height than any
8700 other font loaded before. If this happens, it will make a
8701 glyph matrix reallocation necessary. */
8702 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8709 /* Return a pointer to struct font_info of a font named FONTNAME for
8710 frame F. If no such font is loaded, return NULL. */
8713 x_query_font (f
, fontname
)
8715 register char *fontname
;
8717 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8720 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8721 if (dpyinfo
->font_table
[i
].name
8722 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8723 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8724 return (dpyinfo
->font_table
+ i
);
8729 /* Find a CCL program for a font specified by FONTP, and set the member
8730 `encoder' of the structure. */
8733 x_find_ccl_program (fontp
)
8734 struct font_info
*fontp
;
8736 Lisp_Object list
, elt
;
8738 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8742 && STRINGP (XCAR (elt
))
8743 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8749 struct ccl_program
*ccl
8750 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8752 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8755 fontp
->font_encoder
= ccl
;
8759 #if USE_MAC_FONT_PANEL
8760 /* Whether Font Panel has been shown before. The first call to font
8761 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8762 slow. This variable is used for deferring such a call as much as
8764 static int font_panel_shown_p
= 0;
8767 mac_font_panel_visible_p ()
8769 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8773 mac_show_hide_font_panel ()
8775 font_panel_shown_p
= 1;
8777 return FPShowHideFontPanel ();
8781 mac_set_font_info_for_selection (f
, face_id
, c
)
8786 EventTargetRef target
= NULL
;
8787 XFontStruct
*font
= NULL
;
8789 if (!mac_font_panel_visible_p ())
8794 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8796 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8800 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8801 face
= FACE_FROM_ID (f
, face_id
);
8807 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8810 if (font
->mac_fontnum
!= -1)
8812 FontSelectionQDStyle qd_style
;
8814 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8815 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8816 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8817 qd_style
.size
= font
->mac_fontsize
;
8818 qd_style
.hasColor
= false;
8820 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8821 1, &qd_style
, target
);
8824 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8825 1, &font
->mac_style
, target
);
8833 /* The Mac Event loop code */
8835 #if !TARGET_API_MAC_CARBON
8837 #include <Quickdraw.h>
8838 #include <Balloons.h>
8839 #include <Devices.h>
8841 #include <Gestalt.h>
8843 #include <Processes.h>
8845 #include <ToolUtils.h>
8846 #include <TextUtils.h>
8847 #include <Dialogs.h>
8850 #include <Resources.h>
8855 #endif /* ! TARGET_API_MAC_CARBON */
8860 #define DEFAULT_NUM_COLS 80
8862 #define MIN_DOC_SIZE 64
8863 #define MAX_DOC_SIZE 32767
8865 #define EXTRA_STACK_ALLOC (256 * 1024)
8867 #define ARGV_STRING_LIST_ID 129
8868 #define ABOUT_ALERT_ID 128
8869 #define RAM_TOO_LARGE_ALERT_ID 129
8871 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8872 Lisp_Object Qreverse
;
8875 /* Modifier associated with the control key, or nil to ignore. */
8876 Lisp_Object Vmac_control_modifier
;
8878 /* Modifier associated with the option key, or nil to ignore. */
8879 Lisp_Object Vmac_option_modifier
;
8881 /* Modifier associated with the command key, or nil to ignore. */
8882 Lisp_Object Vmac_command_modifier
;
8884 /* Modifier associated with the function key, or nil to ignore. */
8885 Lisp_Object Vmac_function_modifier
;
8887 /* True if the option and command modifiers should be used to emulate
8888 a three button mouse */
8889 Lisp_Object Vmac_emulate_three_button_mouse
;
8891 #if USE_CARBON_EVENTS
8892 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8893 mouse-2, instead of mouse-3. */
8894 int mac_wheel_button_is_mouse_2
;
8896 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8897 for processing before Emacs sees it. */
8898 int mac_pass_command_to_system
;
8900 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8901 for processing before Emacs sees it. */
8902 int mac_pass_control_to_system
;
8905 /* Points to the variable `inev' in the function XTread_socket. It is
8906 used for passing an input event to the function back from
8907 Carbon/Apple event handlers. */
8908 static struct input_event
*read_socket_inev
= NULL
;
8910 /* Whether or not the screen configuration has changed. */
8911 static int mac_screen_config_changed
= 0;
8913 Point saved_menu_event_location
;
8916 #if USE_CARBON_EVENTS
8917 static Lisp_Object Qhi_command
;
8919 extern Lisp_Object Qwindow
;
8920 static Lisp_Object Qtoolbar_switch_mode
;
8922 #if USE_MAC_FONT_PANEL
8923 extern Lisp_Object Qfont
;
8924 static Lisp_Object Qpanel_closed
, Qselection
;
8927 static TSMDocumentID tsm_document_id
;
8928 static Lisp_Object Qtext_input
;
8929 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8930 static Lisp_Object Vmac_ts_active_input_overlay
;
8931 extern Lisp_Object Qbefore_string
;
8932 static Lisp_Object Vmac_ts_script_language_on_focus
;
8933 static Lisp_Object saved_ts_script_language_on_focus
;
8934 static ScriptLanguageRecord saved_ts_language
;
8935 static Component saved_ts_component
;
8938 extern int mac_ready_for_apple_events
;
8939 extern Lisp_Object Qundefined
;
8940 extern void init_apple_event_handler
P_ ((void));
8941 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8942 Lisp_Object
*, Lisp_Object
*,
8944 extern OSErr init_coercion_handler
P_ ((void));
8947 extern OSErr install_drag_handler
P_ ((WindowRef
));
8948 extern void remove_drag_handler
P_ ((WindowRef
));
8950 /* Showing help echo string during menu tracking */
8951 extern OSStatus install_menu_target_item_handler
P_ ((WindowPtr
));
8953 #if USE_CARBON_EVENTS
8955 extern void init_service_handler ();
8956 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8959 /* Window Event Handler */
8960 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8963 OSStatus
install_window_handler (WindowPtr
);
8965 extern void init_emacs_passwd_dir ();
8966 extern int emacs_main (int, char **, char **);
8968 extern void initialize_applescript();
8969 extern void terminate_applescript();
8971 /* Table for translating Mac keycode to X keysym values. Contributed
8973 Mapping for special keys is now identical to that in Apple X11
8974 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8975 on the right of the Cmd key on laptops, and fn + `enter' (->
8977 static const unsigned char keycode_to_xkeysym_table
[] = {
8978 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8979 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8980 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8982 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8983 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8984 /*0x38*/ 0, 0, 0, 0,
8985 /*0x3C*/ 0, 0, 0, 0,
8987 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8988 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8989 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8990 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8992 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8993 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8994 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8995 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8997 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8998 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8999 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9000 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9002 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9003 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9004 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9005 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9009 /* Table for translating Mac keycode with the laptop `fn' key to that
9010 without it. Destination symbols in comments are keys on US
9011 keyboard, and they may not be the same on other types of keyboards.
9012 If the destination is identical to the source, it doesn't map `fn'
9013 key to a modifier. */
9014 static const unsigned char fn_keycode_to_keycode_table
[] = {
9015 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9016 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9017 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9019 /*0x30*/ 0, 0, 0, 0,
9020 /*0x34*/ 0, 0, 0, 0,
9021 /*0x38*/ 0, 0, 0, 0,
9022 /*0x3C*/ 0, 0, 0, 0,
9024 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9025 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9026 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9027 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9029 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9030 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9031 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9032 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9034 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9035 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9036 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
9037 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9039 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
9040 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9041 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
9042 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
9044 #endif /* MAC_OSX */
9047 #if USE_CARBON_EVENTS
9048 mac_to_emacs_modifiers (UInt32 mods
)
9050 mac_to_emacs_modifiers (EventModifiers mods
)
9053 unsigned int result
= 0;
9054 if (mods
& shiftKey
)
9055 result
|= shift_modifier
;
9057 /* Deactivated to simplify configuration:
9058 if Vmac_option_modifier is non-NIL, we fully process the Option
9059 key. Otherwise, we only process it if an additional Ctrl or Command
9060 is pressed. That way the system may convert the character to a
9062 if ((mods & optionKey) &&
9063 (( !NILP(Vmac_option_modifier) ||
9064 ((mods & cmdKey) || (mods & controlKey))))) */
9066 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9067 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9069 result
|= XUINT(val
);
9071 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9072 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9074 result
|= XUINT(val
);
9076 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9077 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9079 result
|= XUINT(val
);
9083 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9084 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9086 result
|= XUINT(val
);
9094 mac_mapped_modifiers (modifiers
, key_code
)
9095 UInt32 modifiers
, key_code
;
9097 UInt32 mapped_modifiers_all
=
9098 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9099 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9100 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9103 mapped_modifiers_all
|=
9104 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9106 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
9107 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
9108 no longer means laptop's `fn' key is down for the following keys:
9109 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
9110 Down, the arrow keys, and Clear. We ignore the corresponding bit
9111 if that key can be entered without the `fn' key on laptops. */
9112 if (modifiers
& kEventKeyModifierFnMask
9114 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
9115 modifiers
&= ~kEventKeyModifierFnMask
;
9118 return mapped_modifiers_all
& modifiers
;
9122 mac_get_emulated_btn ( UInt32 modifiers
)
9125 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9126 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9127 if (modifiers
& cmdKey
)
9128 result
= cmdIs3
? 2 : 1;
9129 else if (modifiers
& optionKey
)
9130 result
= cmdIs3
? 1 : 2;
9135 #if TARGET_API_MAC_CARBON
9136 /***** Code to handle C-g testing *****/
9137 extern int quit_char
;
9138 extern int make_ctrl_char
P_ ((int));
9141 mac_quit_char_key_p (modifiers
, key_code
)
9142 UInt32 modifiers
, key_code
;
9144 UInt32 char_code
, mapped_modifiers
;
9145 unsigned long some_state
= 0;
9146 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9147 int c
, emacs_modifiers
;
9149 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9150 mapped_modifiers
= mac_mapped_modifiers (modifiers
, key_code
);
9151 key_code
|= (modifiers
& ~mapped_modifiers
);
9152 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9153 if (char_code
& ~0xff)
9156 emacs_modifiers
= mac_to_emacs_modifiers (mapped_modifiers
);
9157 if (emacs_modifiers
& ctrl_modifier
)
9158 c
= make_ctrl_char (char_code
);
9160 c
|= (emacs_modifiers
9161 & (meta_modifier
| alt_modifier
9162 | hyper_modifier
| super_modifier
));
9164 return c
== quit_char
;
9168 #if USE_CARBON_EVENTS
9169 /* Obtains the event modifiers from the event ref and then calls
9170 mac_to_emacs_modifiers. */
9172 mac_event_to_emacs_modifiers (EventRef eventRef
)
9175 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9176 sizeof (UInt32
), NULL
, &mods
);
9177 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9178 GetEventClass(eventRef
) == kEventClassMouse
)
9180 mods
&= ~(optionKey
| cmdKey
);
9182 return mac_to_emacs_modifiers (mods
);
9185 /* Given an event ref, return the code to use for the mouse button
9186 code in the emacs input_event. */
9188 mac_get_mouse_btn (EventRef ref
)
9190 EventMouseButton result
= kEventMouseButtonPrimary
;
9191 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9192 sizeof (EventMouseButton
), NULL
, &result
);
9195 case kEventMouseButtonPrimary
:
9196 if (NILP (Vmac_emulate_three_button_mouse
))
9200 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9201 sizeof (UInt32
), NULL
, &mods
);
9202 return mac_get_emulated_btn(mods
);
9204 case kEventMouseButtonSecondary
:
9205 return mac_wheel_button_is_mouse_2
? 2 : 1;
9206 case kEventMouseButtonTertiary
:
9207 case 4: /* 4 is the number for the mouse wheel button */
9208 return mac_wheel_button_is_mouse_2
? 1 : 2;
9214 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9215 events. However the click of the mouse wheel is not converted to a
9216 mouseDown or mouseUp event. Likewise for dead key events. This
9217 calls ConvertEventRefToEventRecord, but then checks to see if it is
9218 a mouse up/down, or a dead key Carbon event that has not been
9219 converted, and if so, converts it by hand (to be picked up in the
9220 XTread_socket loop). */
9221 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9224 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9230 switch (GetEventClass (eventRef
))
9232 case kEventClassMouse
:
9233 switch (GetEventKind (eventRef
))
9235 case kEventMouseDown
:
9236 eventRec
->what
= mouseDown
;
9241 eventRec
->what
= mouseUp
;
9250 case kEventClassKeyboard
:
9251 switch (GetEventKind (eventRef
))
9253 case kEventRawKeyDown
:
9255 goto keystroke_common
;
9256 case kEventRawKeyRepeat
:
9258 goto keystroke_common
;
9259 case kEventRawKeyUp
:
9263 unsigned char char_codes
;
9266 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9267 typeChar
, NULL
, sizeof (char),
9270 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9271 typeUInt32
, NULL
, sizeof (UInt32
),
9275 eventRec
->what
= action
;
9276 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9293 /* Need where and when. */
9296 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9297 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9298 /* Use two step process because new event modifiers are 32-bit
9299 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9300 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9301 NULL
, sizeof (UInt32
), NULL
, &mods
);
9302 eventRec
->modifiers
= mods
;
9304 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9316 Handle menubar_handle
;
9317 MenuHandle menu_handle
;
9319 menubar_handle
= GetNewMBar (128);
9320 if(menubar_handle
== NULL
)
9322 SetMenuBar (menubar_handle
);
9325 #if !TARGET_API_MAC_CARBON
9326 menu_handle
= GetMenuHandle (M_APPLE
);
9327 if(menu_handle
!= NULL
)
9328 AppendResMenu (menu_handle
,'DRVR');
9336 do_init_managers (void)
9338 #if !TARGET_API_MAC_CARBON
9339 InitGraf (&qd
.thePort
);
9341 FlushEvents (everyEvent
, 0);
9346 #endif /* !TARGET_API_MAC_CARBON */
9349 #if !TARGET_API_MAC_CARBON
9350 /* set up some extra stack space for use by emacs */
9351 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9353 /* MaxApplZone must be called for AppleScript to execute more
9354 complicated scripts */
9357 #endif /* !TARGET_API_MAC_CARBON */
9361 do_check_ram_size (void)
9363 SInt32 physical_ram_size
, logical_ram_size
;
9365 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
9366 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
9367 || physical_ram_size
> (1 << VALBITS
)
9368 || logical_ram_size
> (1 << VALBITS
))
9370 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
9374 #endif /* MAC_OS8 */
9377 do_window_update (WindowPtr win
)
9379 struct frame
*f
= mac_window_to_frame (win
);
9383 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
9385 if (win
!= tip_window
)
9387 if (f
->async_visible
== 0)
9389 /* Update events may occur when a frame gets iconified. */
9391 f
->async_visible
= 1;
9392 f
->async_iconified
= 0;
9393 SET_FRAME_GARBAGED (f
);
9399 #if TARGET_API_MAC_CARBON
9400 RgnHandle region
= NewRgn ();
9402 GetPortVisibleRegion (GetWindowPort (win
), region
);
9403 GetRegionBounds (region
, &r
);
9404 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9406 mac_prepare_for_quickdraw (f
);
9408 UpdateControls (win
, region
);
9409 DisposeRgn (region
);
9411 r
= (*win
->visRgn
)->rgnBBox
;
9412 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9413 UpdateControls (win
, win
->visRgn
);
9422 is_emacs_window (WindowPtr win
)
9424 Lisp_Object tail
, frame
;
9429 FOR_EACH_FRAME (tail
, frame
)
9430 if (FRAME_MAC_P (XFRAME (frame
)))
9431 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9442 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9444 err
= ActivateTSMDocument (tsm_document_id
);
9448 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9449 && EQ (saved_ts_script_language_on_focus
, Qt
))
9450 slptr
= &saved_ts_language
;
9451 else if (CONSP (Vmac_ts_script_language_on_focus
)
9452 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9453 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9454 && CONSP (saved_ts_script_language_on_focus
)
9455 && EQ (XCAR (saved_ts_script_language_on_focus
),
9456 XCAR (Vmac_ts_script_language_on_focus
))
9457 && EQ (XCDR (saved_ts_script_language_on_focus
),
9458 XCDR (Vmac_ts_script_language_on_focus
)))
9460 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9461 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9468 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9469 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
9470 kKeyboardInputMethodClass
);
9472 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
9475 err
= SetTextServiceLanguage (slptr
);
9477 /* Seems to be needed on Mac OS X 10.2. */
9479 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
9489 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9491 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
9493 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
9495 err
= GetTextServiceLanguage (&saved_ts_language
);
9497 slptr
= &saved_ts_language
;
9499 else if (CONSP (Vmac_ts_script_language_on_focus
)
9500 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9501 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
9503 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9504 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9510 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9511 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
9512 kKeyboardInputMethodClass
);
9514 GetDefaultInputMethod (&saved_ts_component
, slptr
);
9518 err
= DeactivateTSMDocument (tsm_document_id
);
9524 #if !TARGET_API_MAC_CARBON
9526 do_apple_menu (SInt16 menu_item
)
9529 SInt16 da_driver_refnum
;
9531 if (menu_item
== I_ABOUT
)
9532 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9535 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9536 da_driver_refnum
= OpenDeskAcc (item_name
);
9539 #endif /* !TARGET_API_MAC_CARBON */
9541 /* Handle drags in size box. Based on code contributed by Ben
9542 Mesander and IM - Window Manager A. */
9545 do_grow_window (w
, e
)
9547 const EventRecord
*e
;
9550 int rows
, columns
, width
, height
;
9551 struct frame
*f
= mac_window_to_frame (w
);
9552 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
9553 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
9554 #if TARGET_API_MAC_CARBON
9560 if (size_hints
->flags
& PMinSize
)
9562 min_width
= size_hints
->min_width
;
9563 min_height
= size_hints
->min_height
;
9565 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9567 #if TARGET_API_MAC_CARBON
9568 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
9570 height
= new_rect
.bottom
- new_rect
.top
;
9571 width
= new_rect
.right
- new_rect
.left
;
9573 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9574 /* see if it really changed size */
9577 height
= HiWord (grow_size
);
9578 width
= LoWord (grow_size
);
9581 if (width
!= FRAME_PIXEL_WIDTH (f
)
9582 || height
!= FRAME_PIXEL_HEIGHT (f
))
9584 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9585 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9587 x_set_window_size (f
, 0, columns
, rows
);
9592 #if TARGET_API_MAC_CARBON
9594 mac_get_ideal_size (f
)
9597 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9598 WindowPtr w
= FRAME_MAC_WINDOW (f
);
9601 int height
, width
, columns
, rows
;
9603 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9604 ideal_size
.v
= dpyinfo
->height
;
9605 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
9606 /* Adjust the standard size according to character boundaries. */
9607 width
= standard_rect
.right
- standard_rect
.left
;
9608 height
= standard_rect
.bottom
- standard_rect
.top
;
9609 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9610 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9611 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9612 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9618 /* Handle clicks in zoom box. Calculation of "standard state" based
9619 on code in IM - Window Manager A and code contributed by Ben
9620 Mesander. The standard state of an Emacs window is 80-characters
9621 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9624 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9626 Rect zoom_rect
, port_rect
;
9628 struct frame
*f
= mac_window_to_frame (w
);
9629 #if TARGET_API_MAC_CARBON
9630 Point ideal_size
= mac_get_ideal_size (f
);
9632 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9633 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
9634 && port_rect
.left
== zoom_rect
.left
9635 && port_rect
.top
== zoom_rect
.top
)
9636 zoom_in_or_out
= inZoomIn
;
9638 zoom_in_or_out
= inZoomOut
;
9641 mac_clear_window (f
);
9643 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
9644 #else /* not TARGET_API_MAC_CARBON */
9647 int w_title_height
, rows
;
9648 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9650 GetPort (&save_port
);
9652 SetPortWindowPort (w
);
9654 /* Clear window to avoid flicker. */
9655 EraseRect (&(w
->portRect
));
9656 if (zoom_in_or_out
== inZoomOut
)
9658 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9659 LocalToGlobal (&top_left
);
9661 /* calculate height of window's title bar */
9662 w_title_height
= top_left
.v
- 1
9663 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9665 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9666 zoom_rect
= qd
.screenBits
.bounds
;
9667 zoom_rect
.top
+= w_title_height
;
9668 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9670 zoom_rect
.right
= zoom_rect
.left
9671 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9673 /* Adjust the standard size according to character boundaries. */
9674 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9676 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9678 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9682 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9684 SetPort (save_port
);
9685 #endif /* not TARGET_API_MAC_CARBON */
9687 #if !USE_CARBON_EVENTS
9688 /* retrieve window size and update application values */
9689 #if TARGET_API_MAC_CARBON
9690 GetWindowPortBounds (w
, &port_rect
);
9692 port_rect
= w
->portRect
;
9694 height
= port_rect
.bottom
- port_rect
.top
;
9695 width
= port_rect
.right
- port_rect
.left
;
9697 mac_handle_size_change (f
, width
, height
);
9698 mac_handle_origin_change (f
);
9703 mac_store_apple_event (class, id
, desc
)
9704 Lisp_Object
class, id
;
9707 struct input_event buf
;
9711 buf
.kind
= MAC_APPLE_EVENT
;
9714 XSETFRAME (buf
.frame_or_window
,
9715 mac_focus_frame (&one_mac_display_info
));
9716 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9717 is safe to use them during read_socket_hook. */
9718 buf
.arg
= mac_aedesc_to_lisp (desc
);
9719 kbd_buffer_store_event (&buf
);
9722 #if TARGET_API_MAC_CARBON
9724 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9725 event
, num_params
, names
, types
)
9728 Lisp_Object class_key
, id_key
;
9731 const EventParamName
*names
;
9732 const EventParamType
*types
;
9734 OSStatus err
= eventNotHandledErr
;
9735 Lisp_Object binding
;
9737 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9738 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9740 if (INTEGERP (binding
))
9741 err
= XINT (binding
);
9744 AppleEvent apple_event
;
9745 err
= create_apple_event_from_event_ref (event
, num_params
,
9750 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9751 AEDisposeDesc (&apple_event
);
9752 mac_wakeup_from_rne ();
9761 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9767 struct input_event buf
;
9771 buf
.kind
= DRAG_N_DROP_EVENT
;
9772 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9773 buf
.timestamp
= TickCount () * (1000 / 60);
9774 XSETINT (buf
.x
, mouse_pos
.h
);
9775 XSETINT (buf
.y
, mouse_pos
.v
);
9776 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9777 buf
.arg
= mac_aedesc_to_lisp (desc
);
9778 kbd_buffer_store_event (&buf
);
9782 #if USE_CARBON_EVENTS
9783 static pascal OSStatus
9784 mac_handle_command_event (next_handler
, event
, data
)
9785 EventHandlerCallRef next_handler
;
9789 OSStatus result
, err
;
9791 static const EventParamName names
[] =
9792 {kEventParamDirectObject
, kEventParamKeyModifiers
};
9793 static const EventParamType types
[] =
9794 {typeHICommand
, typeUInt32
};
9795 int num_params
= sizeof (names
) / sizeof (names
[0]);
9797 result
= CallNextEventHandler (next_handler
, event
);
9798 if (result
!= eventNotHandledErr
)
9801 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9802 NULL
, sizeof (HICommand
), NULL
, &command
);
9804 if (err
!= noErr
|| command
.commandID
== 0)
9805 return eventNotHandledErr
;
9807 /* A HI command event is mapped to an Apple event whose event class
9808 symbol is `hi-command' and event ID is its command ID. */
9809 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9811 event
, num_params
, names
, types
);
9812 return err
== noErr
? noErr
: eventNotHandledErr
;
9816 init_command_handler ()
9818 static const EventTypeSpec specs
[] =
9819 {{kEventClassCommand
, kEventCommandProcess
}};
9820 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9822 if (handle_command_eventUPP
== NULL
)
9823 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9824 return InstallApplicationEventHandler (handle_command_eventUPP
,
9825 GetEventTypeCount (specs
), specs
,
9829 static pascal OSStatus
9830 mac_handle_window_event (next_handler
, event
, data
)
9831 EventHandlerCallRef next_handler
;
9836 OSStatus result
, err
;
9839 XSizeHints
*size_hints
;
9841 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9842 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9844 return eventNotHandledErr
;
9846 f
= mac_window_to_frame (wp
);
9847 switch (GetEventKind (event
))
9849 case kEventWindowUpdate
:
9850 result
= CallNextEventHandler (next_handler
, event
);
9851 if (result
!= eventNotHandledErr
)
9854 do_window_update (wp
);
9857 case kEventWindowGetIdealSize
:
9858 result
= CallNextEventHandler (next_handler
, event
);
9859 if (result
!= eventNotHandledErr
)
9863 Point ideal_size
= mac_get_ideal_size (f
);
9865 err
= SetEventParameter (event
, kEventParamDimensions
,
9866 typeQDPoint
, sizeof (Point
), &ideal_size
);
9872 case kEventWindowBoundsChanging
:
9873 result
= CallNextEventHandler (next_handler
, event
);
9874 if (result
!= eventNotHandledErr
)
9877 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9878 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9882 size_hints
= FRAME_SIZE_HINTS (f
);
9883 if ((attributes
& kWindowBoundsChangeUserResize
)
9884 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9885 == (PResizeInc
| PBaseSize
| PMinSize
)))
9890 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9891 typeQDRectangle
, NULL
, sizeof (Rect
),
9896 width
= bounds
.right
- bounds
.left
;
9897 height
= bounds
.bottom
- bounds
.top
;
9899 if (width
< size_hints
->min_width
)
9900 width
= size_hints
->min_width
;
9902 width
= size_hints
->base_width
9903 + (int) ((width
- size_hints
->base_width
)
9904 / (float) size_hints
->width_inc
+ .5)
9905 * size_hints
->width_inc
;
9907 if (height
< size_hints
->min_height
)
9908 height
= size_hints
->min_height
;
9910 height
= size_hints
->base_height
9911 + (int) ((height
- size_hints
->base_height
)
9912 / (float) size_hints
->height_inc
+ .5)
9913 * size_hints
->height_inc
;
9915 bounds
.right
= bounds
.left
+ width
;
9916 bounds
.bottom
= bounds
.top
+ height
;
9917 SetEventParameter (event
, kEventParamCurrentBounds
,
9918 typeQDRectangle
, sizeof (Rect
), &bounds
);
9923 case kEventWindowBoundsChanged
:
9924 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9925 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9929 if (attributes
& kWindowBoundsChangeSizeChanged
)
9933 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9934 typeQDRectangle
, NULL
, sizeof (Rect
),
9940 width
= bounds
.right
- bounds
.left
;
9941 height
= bounds
.bottom
- bounds
.top
;
9942 mac_handle_size_change (f
, width
, height
);
9943 mac_wakeup_from_rne ();
9947 if (attributes
& kWindowBoundsChangeOriginChanged
)
9948 mac_handle_origin_change (f
);
9952 case kEventWindowShown
:
9953 case kEventWindowHidden
:
9954 case kEventWindowExpanded
:
9955 case kEventWindowCollapsed
:
9956 result
= CallNextEventHandler (next_handler
, event
);
9958 mac_handle_visibility_change (f
);
9963 case kEventWindowClose
:
9964 result
= CallNextEventHandler (next_handler
, event
);
9966 struct input_event buf
;
9969 buf
.kind
= DELETE_WINDOW_EVENT
;
9970 XSETFRAME (buf
.frame_or_window
, f
);
9972 kbd_buffer_store_event (&buf
);
9977 case kEventWindowToolbarSwitchMode
:
9978 result
= CallNextEventHandler (next_handler
, event
);
9980 static const EventParamName names
[] = {kEventParamDirectObject
,
9981 kEventParamWindowMouseLocation
,
9982 kEventParamKeyModifiers
,
9983 kEventParamMouseButton
,
9984 kEventParamClickCount
,
9985 kEventParamMouseChord
};
9986 static const EventParamType types
[] = {typeWindowRef
,
9992 int num_params
= sizeof (names
) / sizeof (names
[0]);
9994 err
= mac_store_event_ref_as_apple_event (0, 0,
9996 Qtoolbar_switch_mode
,
10000 return err
== noErr
? noErr
: result
;
10004 case kEventWindowFocusAcquired
:
10005 result
= CallNextEventHandler (next_handler
, event
);
10006 err
= mac_tsm_resume ();
10007 return err
== noErr
? noErr
: result
;
10009 case kEventWindowFocusRelinquish
:
10010 result
= CallNextEventHandler (next_handler
, event
);
10011 err
= mac_tsm_suspend ();
10012 return err
== noErr
? noErr
: result
;
10016 return eventNotHandledErr
;
10019 static pascal OSStatus
10020 mac_handle_mouse_event (next_handler
, event
, data
)
10021 EventHandlerCallRef next_handler
;
10025 OSStatus result
, err
;
10027 switch (GetEventKind (event
))
10029 case kEventMouseWheelMoved
:
10033 EventMouseWheelAxis axis
;
10037 result
= CallNextEventHandler (next_handler
, event
);
10038 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
10041 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
10042 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10046 f
= mac_window_to_frame (wp
);
10047 if (f
!= mac_focus_frame (&one_mac_display_info
))
10050 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
10051 typeMouseWheelAxis
, NULL
,
10052 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
10053 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
10056 err
= GetEventParameter (event
, kEventParamMouseLocation
,
10057 typeQDPoint
, NULL
, sizeof (Point
),
10062 SetPortWindowPort (wp
);
10063 GlobalToLocal (&point
);
10064 if (point
.h
< 0 || point
.v
< 0
10065 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
10066 f
->tool_bar_window
))
10069 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
10070 typeSInt32
, NULL
, sizeof (SInt32
),
10075 read_socket_inev
->kind
= WHEEL_EVENT
;
10076 read_socket_inev
->code
= 0;
10077 read_socket_inev
->modifiers
=
10078 (mac_event_to_emacs_modifiers (event
)
10079 | ((delta
< 0) ? down_modifier
: up_modifier
));
10080 XSETINT (read_socket_inev
->x
, point
.h
);
10081 XSETINT (read_socket_inev
->y
, point
.v
);
10082 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10092 return eventNotHandledErr
;
10095 #if USE_MAC_FONT_PANEL
10096 static pascal OSStatus
10097 mac_handle_font_event (next_handler
, event
, data
)
10098 EventHandlerCallRef next_handler
;
10102 OSStatus result
, err
;
10103 Lisp_Object id_key
;
10105 const EventParamName
*names
;
10106 const EventParamType
*types
;
10107 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
10108 kEventParamATSUFontSize
,
10109 kEventParamFMFontFamily
,
10110 kEventParamFMFontSize
,
10111 kEventParamFontColor
};
10112 static const EventParamType types_sel
[] = {typeATSUFontID
,
10118 result
= CallNextEventHandler (next_handler
, event
);
10119 if (result
!= eventNotHandledErr
)
10122 switch (GetEventKind (event
))
10124 case kEventFontPanelClosed
:
10125 id_key
= Qpanel_closed
;
10131 case kEventFontSelection
:
10132 id_key
= Qselection
;
10133 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
10139 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
10143 return err
== noErr
? noErr
: eventNotHandledErr
;
10148 static pascal OSStatus
10149 mac_handle_text_input_event (next_handler
, event
, data
)
10150 EventHandlerCallRef next_handler
;
10154 OSStatus result
, err
= noErr
;
10155 Lisp_Object id_key
= Qnil
;
10157 const EventParamName
*names
;
10158 const EventParamType
*types
;
10159 static UInt32 seqno_uaia
= 0;
10160 static const EventParamName names_uaia
[] =
10161 {kEventParamTextInputSendComponentInstance
,
10162 kEventParamTextInputSendRefCon
,
10163 kEventParamTextInputSendSLRec
,
10164 kEventParamTextInputSendFixLen
,
10165 kEventParamTextInputSendText
,
10166 kEventParamTextInputSendUpdateRng
,
10167 kEventParamTextInputSendHiliteRng
,
10168 kEventParamTextInputSendClauseRng
,
10169 kEventParamTextInputSendPinRng
,
10170 kEventParamTextInputSendTextServiceEncoding
,
10171 kEventParamTextInputSendTextServiceMacEncoding
,
10172 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
10173 static const EventParamType types_uaia
[] =
10174 {typeComponentInstance
,
10176 typeIntlWritingCode
,
10183 typeTextRangeArray
,
10184 typeTextRangeArray
,
10190 static const EventParamName names_ufke
[] =
10191 {kEventParamTextInputSendComponentInstance
,
10192 kEventParamTextInputSendRefCon
,
10193 kEventParamTextInputSendSLRec
,
10194 kEventParamTextInputSendText
};
10195 static const EventParamType types_ufke
[] =
10196 {typeComponentInstance
,
10198 typeIntlWritingCode
,
10201 result
= CallNextEventHandler (next_handler
, event
);
10203 switch (GetEventKind (event
))
10205 case kEventTextInputUpdateActiveInputArea
:
10206 id_key
= Qupdate_active_input_area
;
10207 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
10208 names
= names_uaia
;
10209 types
= types_uaia
;
10210 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
10211 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
10215 case kEventTextInputUnicodeForKeyEvent
:
10217 EventRef kbd_event
;
10218 UInt32 actual_size
, modifiers
, key_code
;
10220 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
10221 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
10224 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
10226 sizeof (UInt32
), NULL
, &modifiers
);
10228 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
10229 typeUInt32
, NULL
, sizeof (UInt32
),
10231 if (err
== noErr
&& mac_mapped_modifiers (modifiers
, key_code
))
10232 /* There're mapped modifier keys. Process it in
10234 return eventNotHandledErr
;
10236 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10237 typeUnicodeText
, NULL
, 0, &actual_size
,
10239 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
10243 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10244 typeUnicodeText
, NULL
,
10245 sizeof (UniChar
), NULL
, &code
);
10246 if (err
== noErr
&& code
< 0x80)
10248 /* ASCII character. Process it in XTread_socket. */
10249 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e
10250 && !(key_code
<= 0x7f
10251 && keycode_to_xkeysym_table
[key_code
]))
10253 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
10255 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
10256 read_socket_inev
->code
= code
;
10257 read_socket_inev
->modifiers
=
10258 mac_to_emacs_modifiers (modifiers
);
10259 read_socket_inev
->modifiers
|=
10260 (extra_keyboard_modifiers
10261 & (meta_modifier
| alt_modifier
10262 | hyper_modifier
| super_modifier
));
10263 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10265 return eventNotHandledErr
;
10269 /* Non-ASCII keystrokes without mapped modifiers are processed
10270 at the Lisp level. */
10271 id_key
= Qunicode_for_key_event
;
10272 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
10273 names
= names_ufke
;
10274 types
= types_ufke
;
10277 case kEventTextInputOffsetToPos
:
10283 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
10284 return eventNotHandledErr
;
10286 /* Strictly speaking, this is not always correct because
10287 previous events may change some states about display. */
10288 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
10290 if (!WINDOWP (echo_area_window
))
10291 return eventNotHandledErr
;
10293 /* Active input area is displayed in the echo area. */
10294 w
= XWINDOW (echo_area_window
);
10295 f
= WINDOW_XFRAME (w
);
10299 /* Active input area is displayed around the current point. */
10300 f
= SELECTED_FRAME ();
10301 w
= XWINDOW (f
->selected_window
);
10304 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
10305 + WINDOW_LEFT_FRINGE_WIDTH (w
));
10306 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
10307 + FONT_BASE (FRAME_FONT (f
)));
10308 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
10309 LocalToGlobal (&p
);
10310 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
10311 typeQDPoint
, sizeof (typeQDPoint
), &p
);
10319 if (!NILP (id_key
))
10320 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
10324 return err
== noErr
? noErr
: result
;
10330 mac_store_service_event (event
)
10334 Lisp_Object id_key
;
10336 const EventParamName
*names
;
10337 const EventParamType
*types
;
10338 static const EventParamName names_pfm
[] =
10339 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10340 static const EventParamType types_pfm
[] =
10341 {typeCFStringRef
, typeCFStringRef
};
10343 switch (GetEventKind (event
))
10345 case kEventServicePaste
:
10352 case kEventServicePerform
:
10354 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10363 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10369 #endif /* MAC_OSX */
10370 #endif /* USE_CARBON_EVENTS */
10374 install_window_handler (window
)
10377 OSStatus err
= noErr
;
10378 #if USE_CARBON_EVENTS
10379 static const EventTypeSpec specs_window
[] =
10380 {{kEventClassWindow
, kEventWindowUpdate
},
10381 {kEventClassWindow
, kEventWindowGetIdealSize
},
10382 {kEventClassWindow
, kEventWindowBoundsChanging
},
10383 {kEventClassWindow
, kEventWindowBoundsChanged
},
10384 {kEventClassWindow
, kEventWindowShown
},
10385 {kEventClassWindow
, kEventWindowHidden
},
10386 {kEventClassWindow
, kEventWindowExpanded
},
10387 {kEventClassWindow
, kEventWindowCollapsed
},
10388 {kEventClassWindow
, kEventWindowClose
},
10390 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
10393 {kEventClassWindow
, kEventWindowFocusAcquired
},
10394 {kEventClassWindow
, kEventWindowFocusRelinquish
},
10397 static const EventTypeSpec specs_mouse
[] =
10398 {{kEventClassMouse
, kEventMouseWheelMoved
}};
10399 static EventHandlerUPP handle_window_eventUPP
= NULL
;
10400 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
10401 #if USE_MAC_FONT_PANEL
10402 static const EventTypeSpec specs_font
[] =
10403 {{kEventClassFont
, kEventFontPanelClosed
},
10404 {kEventClassFont
, kEventFontSelection
}};
10405 static EventHandlerUPP handle_font_eventUPP
= NULL
;
10408 static const EventTypeSpec specs_text_input
[] =
10409 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
10410 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
10411 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
10412 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
10415 if (handle_window_eventUPP
== NULL
)
10416 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
10417 if (handle_mouse_eventUPP
== NULL
)
10418 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
10419 #if USE_MAC_FONT_PANEL
10420 if (handle_font_eventUPP
== NULL
)
10421 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
10424 if (handle_text_input_eventUPP
== NULL
)
10425 handle_text_input_eventUPP
=
10426 NewEventHandlerUPP (mac_handle_text_input_event
);
10428 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
10429 GetEventTypeCount (specs_window
),
10430 specs_window
, NULL
, NULL
);
10432 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
10433 GetEventTypeCount (specs_mouse
),
10434 specs_mouse
, NULL
, NULL
);
10435 #if USE_MAC_FONT_PANEL
10437 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
10438 GetEventTypeCount (specs_font
),
10439 specs_font
, NULL
, NULL
);
10443 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
10444 GetEventTypeCount (specs_text_input
),
10445 specs_text_input
, window
, NULL
);
10449 err
= install_drag_handler (window
);
10451 err
= install_menu_target_item_handler (window
);
10457 remove_window_handler (window
)
10460 remove_drag_handler (window
);
10465 mac_handle_dm_notification (event
)
10468 mac_screen_config_changed
= 1;
10472 init_dm_notification_handler ()
10475 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
10476 ProcessSerialNumber psn
;
10478 if (handle_dm_notificationUPP
== NULL
)
10479 handle_dm_notificationUPP
=
10480 NewDMNotificationUPP (mac_handle_dm_notification
);
10482 err
= GetCurrentProcess (&psn
);
10484 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
10490 mac_get_screen_info (dpyinfo
)
10491 struct mac_display_info
*dpyinfo
;
10494 /* HasDepth returns true if it is possible to have a 32 bit display,
10495 but this may not be what is actually used. Mac OSX can do better. */
10496 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
10497 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
10500 CGDisplayCount ndisps
;
10501 CGDirectDisplayID
*displays
;
10503 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
10506 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
10507 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
10511 CGRect bounds
= CGRectZero
;
10513 while (ndisps
-- > 0)
10514 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
10515 dpyinfo
->height
= CGRectGetHeight (bounds
);
10516 dpyinfo
->width
= CGRectGetWidth (bounds
);
10520 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
10521 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
10524 #else /* !MAC_OSX */
10526 GDHandle gdh
= GetMainDevice ();
10527 Rect rect
= (**gdh
).gdRect
;
10529 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
10530 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10531 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
10534 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
10535 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
10536 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
10538 dpyinfo
->height
= rect
.bottom
- rect
.top
;
10539 dpyinfo
->width
= rect
.right
- rect
.left
;
10541 #endif /* !MAC_OSX */
10547 profiler_exit_proc ()
10549 ProfilerDump ("\pEmacs.prof");
10554 /* These few functions implement Emacs as a normal Mac application
10555 (almost): set up the heap and the Toolbox, handle necessary system
10556 events plus a few simple menu events. They also set up Emacs's
10557 access to functions defined in the rest of this file. Emacs uses
10558 function hooks to perform all its terminal I/O. A complete list of
10559 these functions appear in termhooks.h. For what they do, read the
10560 comments there and see also w32term.c and xterm.c. What's
10561 noticeably missing here is the event loop, which is normally
10562 present in most Mac application. After performing the necessary
10563 Mac initializations, main passes off control to emacs_main
10564 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10565 (defined further below) to read input. This is where
10566 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10573 #if __profile__ /* is the profiler on? */
10574 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10579 /* set creator and type for files created by MSL */
10580 _fcreator
= MAC_EMACS_CREATOR_CODE
;
10584 do_init_managers ();
10588 #ifndef USE_LSB_TAG
10589 do_check_ram_size ();
10592 init_emacs_passwd_dir ();
10596 init_coercion_handler ();
10598 initialize_applescript ();
10600 init_apple_event_handler ();
10602 init_dm_notification_handler ();
10608 /* set up argv array from STR# resource */
10609 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10613 /* free up AppleScript resources on exit */
10614 atexit (terminate_applescript
);
10616 #if __profile__ /* is the profiler on? */
10617 atexit (profiler_exit_proc
);
10620 /* 3rd param "envp" never used in emacs_main */
10621 (void) emacs_main (argc
, argv
, 0);
10624 /* Never reached - real exit in Fkill_emacs */
10629 #if !USE_CARBON_EVENTS
10630 static RgnHandle mouse_region
= NULL
;
10633 mac_wait_next_event (er
, sleep_time
, dequeue
)
10638 static EventRecord er_buf
= {nullEvent
};
10639 UInt32 target_tick
, current_tick
;
10640 EventMask event_mask
;
10642 if (mouse_region
== NULL
)
10643 mouse_region
= NewRgn ();
10645 event_mask
= everyEvent
;
10646 if (!mac_ready_for_apple_events
)
10647 event_mask
-= highLevelEventMask
;
10649 current_tick
= TickCount ();
10650 target_tick
= current_tick
+ sleep_time
;
10652 if (er_buf
.what
== nullEvent
)
10653 while (!WaitNextEvent (event_mask
, &er_buf
,
10654 target_tick
- current_tick
, mouse_region
))
10656 current_tick
= TickCount ();
10657 if (target_tick
<= current_tick
)
10663 er_buf
.what
= nullEvent
;
10666 #endif /* not USE_CARBON_EVENTS */
10668 #if TARGET_API_MAC_CARBON
10670 mac_post_mouse_moved_event ()
10672 EventRef event
= NULL
;
10675 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
10676 kEventAttributeNone
, &event
);
10681 GetGlobalMouse (&mouse_pos
);
10682 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
10683 sizeof (Point
), &mouse_pos
);
10687 UInt32 modifiers
= GetCurrentKeyModifiers ();
10689 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10690 sizeof (UInt32
), &modifiers
);
10693 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10694 kEventPriorityStandard
);
10696 ReleaseEvent (event
);
10702 mac_set_unicode_keystroke_event (code
, buf
)
10704 struct input_event
*buf
;
10706 int charset_id
, c1
, c2
;
10710 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10713 else if (code
< 0x100)
10716 charset_id
= CHARSET_8_BIT_CONTROL
;
10718 charset_id
= charset_latin_iso8859_1
;
10719 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10720 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10725 charset_id
= charset_mule_unicode_0100_24ff
,
10727 else if (code
< 0x33FF)
10728 charset_id
= charset_mule_unicode_2500_33ff
,
10730 else if (code
>= 0xE000)
10731 charset_id
= charset_mule_unicode_e000_ffff
,
10733 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10734 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10735 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10740 /* Emacs calls this whenever it wants to read an input event from the
10743 XTread_socket (sd
, expected
, hold_quit
)
10745 struct input_event
*hold_quit
;
10747 struct input_event inev
;
10749 #if USE_CARBON_EVENTS
10751 EventTargetRef toolbox_dispatcher
;
10754 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10756 if (interrupt_input_blocked
)
10758 interrupt_input_pending
= 1;
10762 interrupt_input_pending
= 0;
10765 /* So people can tell when we have read the available input. */
10766 input_signal_count
++;
10770 #if USE_CARBON_EVENTS
10771 toolbox_dispatcher
= GetEventDispatcherTarget ();
10775 mac_prepare_for_quickdraw (NULL
),
10777 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10778 kEventRemoveFromQueue
, &eventRef
))
10779 #else /* !USE_CARBON_EVENTS */
10780 while (mac_wait_next_event (&er
, 0, true))
10781 #endif /* !USE_CARBON_EVENTS */
10785 unsigned long timestamp
;
10788 inev
.kind
= NO_EVENT
;
10791 #if USE_CARBON_EVENTS
10792 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10794 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10797 #if USE_CARBON_EVENTS
10798 /* Handle new events */
10799 if (!mac_convert_event_ref (eventRef
, &er
))
10801 /* There used to be a handler for the kEventMouseWheelMoved
10802 event here. But as of Mac OS X 10.4, this kind of event
10803 is not directly posted to the main event queue by
10804 two-finger scrolling on the trackpad. Instead, some
10805 private event is posted and it is converted to a wheel
10806 event by the default handler for the application target.
10807 The converted one can be received by a Carbon event
10808 handler installed on a window target. */
10809 read_socket_inev
= &inev
;
10810 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10811 read_socket_inev
= NULL
;
10814 #endif /* USE_CARBON_EVENTS */
10820 WindowPtr window_ptr
;
10821 ControlPartCode part_code
;
10822 int tool_bar_p
= 0;
10824 #if USE_CARBON_EVENTS
10825 /* This is needed to send mouse events like aqua window
10826 buttons to the correct handler. */
10827 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10828 != eventNotHandledErr
)
10831 last_mouse_glyph_frame
= 0;
10833 if (dpyinfo
->grabbed
&& last_mouse_frame
10834 && FRAME_LIVE_P (last_mouse_frame
))
10836 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10837 part_code
= inContent
;
10841 part_code
= FindWindow (er
.where
, &window_ptr
);
10842 if (tip_window
&& window_ptr
== tip_window
)
10844 HideWindow (tip_window
);
10845 part_code
= FindWindow (er
.where
, &window_ptr
);
10849 if (er
.what
!= mouseDown
&&
10850 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10856 f
= mac_focus_frame (dpyinfo
);
10857 saved_menu_event_location
= er
.where
;
10858 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10859 XSETFRAME (inev
.frame_or_window
, f
);
10864 #if TARGET_API_MAC_CARBON
10865 FrontNonFloatingWindow ()
10870 || (mac_window_to_frame (window_ptr
)
10871 != dpyinfo
->x_focus_frame
))
10872 SelectWindow (window_ptr
);
10875 ControlPartCode control_part_code
;
10877 Point mouse_loc
= er
.where
;
10879 ControlKind control_kind
;
10882 f
= mac_window_to_frame (window_ptr
);
10883 /* convert to local coordinates of new window */
10884 SetPortWindowPort (window_ptr
);
10886 GlobalToLocal (&mouse_loc
);
10887 #if TARGET_API_MAC_CARBON
10888 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10889 &control_part_code
);
10892 GetControlKind (ch
, &control_kind
);
10895 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10899 #if USE_CARBON_EVENTS
10900 inev
.code
= mac_get_mouse_btn (eventRef
);
10901 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10903 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10904 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10906 XSETINT (inev
.x
, mouse_loc
.h
);
10907 XSETINT (inev
.y
, mouse_loc
.v
);
10909 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10911 #ifndef USE_TOOLKIT_SCROLL_BARS
10912 /* control_part_code becomes kControlNoPart if
10913 a progress indicator is clicked. */
10914 && control_part_code
!= kControlNoPart
10915 #else /* USE_TOOLKIT_SCROLL_BARS */
10917 && control_kind
.kind
== kControlKindScrollBar
10918 #endif /* MAC_OSX */
10919 #endif /* USE_TOOLKIT_SCROLL_BARS */
10922 struct scroll_bar
*bar
;
10924 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10926 bar
= tracked_scroll_bar
;
10927 #ifndef USE_TOOLKIT_SCROLL_BARS
10928 control_part_code
= kControlIndicatorPart
;
10932 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10933 #ifdef USE_TOOLKIT_SCROLL_BARS
10934 /* Make the "Ctrl-Mouse-2 splits window" work
10935 for toolkit scroll bars. */
10936 if (inev
.modifiers
& ctrl_modifier
)
10937 x_scroll_bar_handle_click (bar
, control_part_code
,
10939 else if (er
.what
== mouseDown
)
10940 x_scroll_bar_handle_press (bar
, control_part_code
,
10943 x_scroll_bar_handle_release (bar
, &inev
);
10944 #else /* not USE_TOOLKIT_SCROLL_BARS */
10945 x_scroll_bar_handle_click (bar
, control_part_code
,
10947 if (er
.what
== mouseDown
10948 && control_part_code
== kControlIndicatorPart
)
10949 tracked_scroll_bar
= bar
;
10951 tracked_scroll_bar
= NULL
;
10952 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10956 Lisp_Object window
;
10957 int x
= mouse_loc
.h
;
10958 int y
= mouse_loc
.v
;
10960 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10961 if (EQ (window
, f
->tool_bar_window
))
10963 if (er
.what
== mouseDown
)
10964 handle_tool_bar_click (f
, x
, y
, 1, 0);
10966 handle_tool_bar_click (f
, x
, y
, 0,
10972 XSETFRAME (inev
.frame_or_window
, f
);
10973 inev
.kind
= MOUSE_CLICK_EVENT
;
10977 if (er
.what
== mouseDown
)
10979 dpyinfo
->grabbed
|= (1 << inev
.code
);
10980 last_mouse_frame
= f
;
10983 last_tool_bar_item
= -1;
10987 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10988 /* If a button is released though it was not
10989 previously pressed, that would be because
10990 of multi-button emulation. */
10991 dpyinfo
->grabbed
= 0;
10993 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10996 /* Ignore any mouse motion that happened before
10997 this event; any subsequent mouse-movement Emacs
10998 events should reflect only motion after the
11001 f
->mouse_moved
= 0;
11003 #ifdef USE_TOOLKIT_SCROLL_BARS
11004 if (inev
.kind
== MOUSE_CLICK_EVENT
11005 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
11006 && (inev
.modifiers
& ctrl_modifier
)))
11011 inev
.modifiers
|= down_modifier
;
11014 inev
.modifiers
|= up_modifier
;
11021 #if TARGET_API_MAC_CARBON
11023 if (IsWindowPathSelectClick (window_ptr
, &er
))
11025 WindowPathSelect (window_ptr
, NULL
, NULL
);
11028 if (part_code
== inProxyIcon
11029 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
11030 != errUserWantsToDragWindow
))
11032 DragWindow (window_ptr
, er
.where
, NULL
);
11033 #else /* not TARGET_API_MAC_CARBON */
11034 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
11035 #endif /* not TARGET_API_MAC_CARBON */
11036 /* Update the frame parameters. */
11037 #if !USE_CARBON_EVENTS
11039 struct frame
*f
= mac_window_to_frame (window_ptr
);
11041 if (f
&& !f
->async_iconified
)
11042 mac_handle_origin_change (f
);
11048 if (TrackGoAway (window_ptr
, er
.where
))
11050 inev
.kind
= DELETE_WINDOW_EVENT
;
11051 XSETFRAME (inev
.frame_or_window
,
11052 mac_window_to_frame (window_ptr
));
11056 /* window resize handling added --ben */
11058 do_grow_window (window_ptr
, &er
);
11061 /* window zoom handling added --ben */
11064 if (TrackBox (window_ptr
, er
.where
, part_code
))
11065 do_zoom_window (window_ptr
, part_code
);
11075 #if USE_CARBON_EVENTS
11076 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11077 != eventNotHandledErr
)
11080 do_window_update ((WindowPtr
) er
.message
);
11085 #if USE_CARBON_EVENTS
11086 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11087 != eventNotHandledErr
)
11090 switch ((er
.message
>> 24) & 0x000000FF)
11092 case suspendResumeMessage
:
11094 if (er
.message
& resumeFlag
)
11097 mac_tsm_suspend ();
11101 case mouseMovedMessage
:
11102 #if !USE_CARBON_EVENTS
11103 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
11104 er
.where
.h
+ 1, er
.where
.v
+ 1);
11106 previous_help_echo_string
= help_echo_string
;
11107 help_echo_string
= Qnil
;
11109 if (dpyinfo
->grabbed
&& last_mouse_frame
11110 && FRAME_LIVE_P (last_mouse_frame
))
11111 f
= last_mouse_frame
;
11113 f
= dpyinfo
->x_focus_frame
;
11115 if (dpyinfo
->mouse_face_hidden
)
11117 dpyinfo
->mouse_face_hidden
= 0;
11118 clear_mouse_face (dpyinfo
);
11123 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
11124 Point mouse_pos
= er
.where
;
11126 SetPortWindowPort (wp
);
11128 GlobalToLocal (&mouse_pos
);
11130 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11131 #ifdef USE_TOOLKIT_SCROLL_BARS
11132 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
11134 #else /* not USE_TOOLKIT_SCROLL_BARS */
11135 x_scroll_bar_note_movement (tracked_scroll_bar
,
11137 - XINT (tracked_scroll_bar
->top
),
11138 er
.when
* (1000 / 60));
11139 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11142 /* Generate SELECT_WINDOW_EVENTs when needed. */
11143 if (!NILP (Vmouse_autoselect_window
))
11145 Lisp_Object window
;
11147 window
= window_from_coordinates (f
,
11152 /* Window will be selected only when it is
11153 not selected now and last mouse movement
11154 event was not in it. Minibuffer window
11155 will be selected only when it is active. */
11156 if (WINDOWP (window
)
11157 && !EQ (window
, last_window
)
11158 && !EQ (window
, selected_window
)
11159 /* For click-to-focus window managers
11160 create event iff we don't leave the
11162 && (focus_follows_mouse
11163 || (EQ (XWINDOW (window
)->frame
,
11164 XWINDOW (selected_window
)->frame
))))
11166 inev
.kind
= SELECT_WINDOW_EVENT
;
11167 inev
.frame_or_window
= window
;
11170 last_window
=window
;
11172 if (!note_mouse_movement (f
, &mouse_pos
))
11173 help_echo_string
= previous_help_echo_string
;
11177 /* If the contents of the global variable
11178 help_echo_string has changed, generate a
11180 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
11188 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
11190 #if USE_CARBON_EVENTS
11191 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11192 != eventNotHandledErr
)
11195 if (window_ptr
== tip_window
)
11197 HideWindow (tip_window
);
11201 if (!is_emacs_window (window_ptr
))
11204 if ((er
.modifiers
& activeFlag
) != 0)
11206 /* A window has been activated */
11207 Point mouse_loc
= er
.where
;
11209 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11211 SetPortWindowPort (window_ptr
);
11212 GlobalToLocal (&mouse_loc
);
11213 /* Window-activated event counts as mouse movement,
11214 so update things that depend on mouse position. */
11215 note_mouse_movement (mac_window_to_frame (window_ptr
),
11220 /* A window has been deactivated */
11221 #ifdef USE_TOOLKIT_SCROLL_BARS
11222 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11224 struct input_event event
;
11226 EVENT_INIT (event
);
11227 event
.kind
= NO_EVENT
;
11228 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
11229 if (event
.kind
!= NO_EVENT
)
11231 event
.timestamp
= timestamp
;
11232 kbd_buffer_store_event_hold (&event
, hold_quit
);
11237 dpyinfo
->grabbed
= 0;
11239 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11241 f
= mac_window_to_frame (window_ptr
);
11242 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11244 /* If we move outside the frame, then we're
11245 certainly no longer on any text in the
11247 clear_mouse_face (dpyinfo
);
11248 dpyinfo
->mouse_face_mouse_frame
= 0;
11251 /* Generate a nil HELP_EVENT to cancel a help-echo.
11252 Do it only if there's something to cancel.
11253 Otherwise, the startup message is cleared when the
11254 mouse leaves the frame. */
11255 if (any_help_event_p
)
11265 int keycode
= (er
.message
& keyCodeMask
) >> 8;
11266 static SInt16 last_key_script
= -1;
11267 SInt16 current_key_script
;
11268 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
11270 #if USE_CARBON_EVENTS && defined (MAC_OSX)
11271 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
11273 sizeof (UInt32
), NULL
, &modifiers
);
11275 mapped_modifiers
= mac_mapped_modifiers (modifiers
, keycode
);
11277 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
11278 /* When using Carbon Events, we need to pass raw keyboard
11279 events to the TSM ourselves. If TSM handles it, it
11280 will pass back noErr, otherwise it will pass back
11281 "eventNotHandledErr" and we can process it
11283 if (!(mapped_modifiers
11284 & ~(mac_pass_command_to_system
? cmdKey
: 0)
11285 & ~(mac_pass_control_to_system
? controlKey
: 0)))
11289 read_socket_inev
= &inev
;
11290 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11291 read_socket_inev
= NULL
;
11292 if (err
!= eventNotHandledErr
)
11296 if (er
.what
== keyUp
)
11301 f
= mac_focus_frame (dpyinfo
);
11303 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
11304 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
11306 clear_mouse_face (dpyinfo
);
11307 dpyinfo
->mouse_face_hidden
= 1;
11310 current_key_script
= GetScriptManagerVariable (smKeyScript
);
11311 if (last_key_script
!= current_key_script
)
11313 struct input_event event
;
11315 EVENT_INIT (event
);
11316 event
.kind
= LANGUAGE_CHANGE_EVENT
;
11318 event
.code
= current_key_script
;
11319 event
.timestamp
= timestamp
;
11320 kbd_buffer_store_event (&event
);
11322 last_key_script
= current_key_script
;
11326 if (inev
.kind
!= NO_EVENT
)
11331 if (mapped_modifiers
& kEventKeyModifierFnMask
11333 && fn_keycode_to_keycode_table
[keycode
])
11334 keycode
= fn_keycode_to_keycode_table
[keycode
];
11336 if (keycode
<= 0x7f && keycode_to_xkeysym_table
[keycode
])
11338 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
11339 inev
.code
= 0xff00 | keycode_to_xkeysym_table
[keycode
];
11341 else if (mapped_modifiers
)
11343 /* translate the keycode back to determine the
11346 UCKeyboardLayout
*uchr_ptr
= NULL
;
11347 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11349 KeyboardLayoutRef layout
;
11351 err
= KLGetCurrentKeyboardLayout (&layout
);
11353 KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
11354 (const void **) &uchr_ptr
);
11356 static SInt16 last_key_layout_id
= 0;
11357 static Handle uchr_handle
= (Handle
)-1;
11358 SInt16 current_key_layout_id
=
11359 GetScriptVariable (current_key_script
, smScriptKeys
);
11361 if (uchr_handle
== (Handle
)-1
11362 || last_key_layout_id
!= current_key_layout_id
)
11364 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
11365 last_key_layout_id
= current_key_layout_id
;
11368 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
11374 UInt16 key_action
= er
.what
- keyDown
;
11375 UInt32 modifier_key_state
=
11376 (modifiers
& ~mapped_modifiers
) >> 8;
11377 UInt32 keyboard_type
= LMGetKbdType ();
11378 SInt32 dead_key_state
= 0;
11380 UniCharCount actual_length
;
11382 status
= UCKeyTranslate (uchr_ptr
,
11383 keycode
, key_action
,
11384 modifier_key_state
,
11386 kUCKeyTranslateNoDeadKeysMask
,
11388 1, &actual_length
, &code
);
11389 if (status
== noErr
&& actual_length
== 1)
11390 mac_set_unicode_keystroke_event (code
, &inev
);
11392 #endif /* MAC_OSX */
11394 if (inev
.kind
== NO_EVENT
)
11396 /* This code comes from Keyboard Resource,
11397 Appendix C of IM - Text. This is necessary
11398 since shift is ignored in KCHR table
11399 translation when option or command is pressed.
11400 It also does not translate correctly
11401 control-shift chars like C-% so mask off shift
11403 /* Mask off modifier keys that are mapped to some
11404 Emacs modifiers. */
11405 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
11406 /* set high byte of keycode to modifier high byte*/
11407 int new_keycode
= keycode
| new_modifiers
;
11408 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
11409 unsigned long some_state
= 0;
11410 UInt32 new_char_code
;
11412 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
11414 if (new_char_code
== 0)
11415 /* Seems like a dead key. Append up-stroke. */
11416 new_char_code
= KeyTranslate (kchr_ptr
,
11417 new_keycode
| 0x80,
11421 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11422 inev
.code
= new_char_code
& 0xff;
11427 if (inev
.kind
== NO_EVENT
)
11429 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11430 inev
.code
= er
.message
& charCodeMask
;
11433 inev
.modifiers
= mac_to_emacs_modifiers (mapped_modifiers
);
11434 inev
.modifiers
|= (extra_keyboard_modifiers
11435 & (meta_modifier
| alt_modifier
11436 | hyper_modifier
| super_modifier
));
11437 XSETFRAME (inev
.frame_or_window
, f
);
11439 #if TARGET_API_MAC_CARBON
11440 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
11441 && inev
.code
>= 0x80 && inev
.modifiers
)
11444 TextEncoding encoding
= kTextEncodingMacRoman
;
11445 TextToUnicodeInfo ttu_info
;
11447 UpgradeScriptInfoToTextEncoding (current_key_script
,
11448 kTextLanguageDontCare
,
11449 kTextRegionDontCare
,
11451 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
11456 ByteCount unicode_len
;
11459 pstr
[1] = inev
.code
;
11460 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
11462 &unicode_len
, &code
);
11463 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
11464 mac_set_unicode_keystroke_event (code
, &inev
);
11465 DisposeTextToUnicodeInfo (&ttu_info
);
11472 case kHighLevelEvent
:
11473 AEProcessAppleEvent (&er
);
11479 #if USE_CARBON_EVENTS
11480 ReleaseEvent (eventRef
);
11483 if (inev
.kind
!= NO_EVENT
)
11485 inev
.timestamp
= timestamp
;
11486 kbd_buffer_store_event_hold (&inev
, hold_quit
);
11491 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
11496 XSETFRAME (frame
, f
);
11502 any_help_event_p
= 1;
11503 gen_help_event (help_echo_string
, frame
, help_echo_window
,
11504 help_echo_object
, help_echo_pos
);
11508 help_echo_string
= Qnil
;
11509 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
11516 /* If the focus was just given to an autoraising frame,
11518 /* ??? This ought to be able to handle more than one such frame. */
11519 if (pending_autoraise_frame
)
11521 x_raise_frame (pending_autoraise_frame
);
11522 pending_autoraise_frame
= 0;
11525 if (mac_screen_config_changed
)
11527 mac_get_screen_info (dpyinfo
);
11528 mac_screen_config_changed
= 0;
11531 #if !USE_CARBON_EVENTS
11532 /* Check which frames are still visible. We do this here because
11533 there doesn't seem to be any direct notification from the Window
11534 Manager that the visibility of a window has changed (at least,
11535 not in all cases). */
11537 Lisp_Object tail
, frame
;
11539 FOR_EACH_FRAME (tail
, frame
)
11541 struct frame
*f
= XFRAME (frame
);
11543 /* The tooltip has been drawn already. Avoid the
11544 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11545 if (EQ (frame
, tip_frame
))
11548 if (FRAME_MAC_P (f
))
11549 mac_handle_visibility_change (f
);
11560 /* Need to override CodeWarrior's input function so no conversion is
11561 done on newlines Otherwise compiled functions in .elc files will be
11562 read incorrectly. Defined in ...:MSL C:MSL
11563 Common:Source:buffer_io.c. */
11566 __convert_to_newlines (unsigned char * p
, size_t * n
)
11568 #pragma unused(p,n)
11572 __convert_from_newlines (unsigned char * p
, size_t * n
)
11574 #pragma unused(p,n)
11580 make_mac_terminal_frame (struct frame
*f
)
11585 XSETFRAME (frame
, f
);
11587 f
->output_method
= output_mac
;
11588 f
->output_data
.mac
= (struct mac_output
*)
11589 xmalloc (sizeof (struct mac_output
));
11590 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
11592 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
11594 FRAME_COLS (f
) = 96;
11595 FRAME_LINES (f
) = 4;
11597 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
11598 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
11600 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
11602 f
->output_data
.mac
->cursor_pixel
= 0;
11603 f
->output_data
.mac
->border_pixel
= 0x00ff00;
11604 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
11605 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
11607 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
11608 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
11609 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
11610 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
11611 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
11612 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
11614 FRAME_FONTSET (f
) = -1;
11615 f
->output_data
.mac
->explicit_parent
= 0;
11618 f
->border_width
= 0;
11620 f
->internal_border_width
= 0;
11625 f
->new_text_cols
= 0;
11626 f
->new_text_lines
= 0;
11628 SetRect (&r
, f
->left_pos
, f
->top_pos
,
11629 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
11630 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
11634 if (!(FRAME_MAC_WINDOW (f
) =
11635 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
11636 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
11638 /* so that update events can find this mac_output struct */
11639 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
11645 /* Need to be initialized for unshow_buffer in window.c. */
11646 selected_window
= f
->selected_window
;
11648 Fmodify_frame_parameters (frame
,
11649 Fcons (Fcons (Qfont
,
11650 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
11651 Fmodify_frame_parameters (frame
,
11652 Fcons (Fcons (Qforeground_color
,
11653 build_string ("black")), Qnil
));
11654 Fmodify_frame_parameters (frame
,
11655 Fcons (Fcons (Qbackground_color
,
11656 build_string ("white")), Qnil
));
11661 /***********************************************************************
11663 ***********************************************************************/
11665 static int mac_initialized
= 0;
11668 mac_make_rdb (xrm_option
)
11669 const char *xrm_option
;
11671 XrmDatabase database
;
11673 database
= xrm_get_preference_database (NULL
);
11675 xrm_merge_string_database (database
, xrm_option
);
11680 struct mac_display_info
*
11681 mac_term_init (display_name
, xrm_option
, resource_name
)
11682 Lisp_Object display_name
;
11684 char *resource_name
;
11686 struct mac_display_info
*dpyinfo
;
11690 if (!mac_initialized
)
11693 mac_initialized
= 1;
11696 if (x_display_list
)
11697 error ("Sorry, this version can only handle one display");
11699 dpyinfo
= &one_mac_display_info
;
11700 bzero (dpyinfo
, sizeof (*dpyinfo
));
11703 dpyinfo
->mac_id_name
11704 = (char *) xmalloc (SCHARS (Vinvocation_name
)
11705 + SCHARS (Vsystem_name
)
11707 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
11708 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11710 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
11711 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
11714 dpyinfo
->reference_count
= 0;
11715 dpyinfo
->resx
= 72.0;
11716 dpyinfo
->resy
= 72.0;
11718 mac_get_screen_info (dpyinfo
);
11720 dpyinfo
->grabbed
= 0;
11721 dpyinfo
->root_window
= NULL
;
11722 dpyinfo
->image_cache
= make_image_cache ();
11724 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11725 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11726 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11727 dpyinfo
->mouse_face_window
= Qnil
;
11728 dpyinfo
->mouse_face_overlay
= Qnil
;
11729 dpyinfo
->mouse_face_hidden
= 0;
11731 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11733 /* Put this display on the chain. */
11734 dpyinfo
->next
= x_display_list
;
11735 x_display_list
= dpyinfo
;
11737 /* Put it on x_display_name_list. */
11738 x_display_name_list
= Fcons (Fcons (display_name
,
11739 Fcons (Qnil
, dpyinfo
->xrdb
)),
11740 x_display_name_list
);
11741 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11748 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11751 x_delete_display (dpyinfo
)
11752 struct mac_display_info
*dpyinfo
;
11756 /* Discard this display from x_display_name_list and x_display_list.
11757 We can't use Fdelq because that can quit. */
11758 if (! NILP (x_display_name_list
)
11759 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11760 x_display_name_list
= XCDR (x_display_name_list
);
11765 tail
= x_display_name_list
;
11766 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11768 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11770 XSETCDR (tail
, XCDR (XCDR (tail
)));
11773 tail
= XCDR (tail
);
11777 if (x_display_list
== dpyinfo
)
11778 x_display_list
= dpyinfo
->next
;
11781 struct x_display_info
*tail
;
11783 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11784 if (tail
->next
== dpyinfo
)
11785 tail
->next
= tail
->next
->next
;
11788 /* Free the font names in the font table. */
11789 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11790 if (dpyinfo
->font_table
[i
].name
)
11792 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11793 xfree (dpyinfo
->font_table
[i
].full_name
);
11794 xfree (dpyinfo
->font_table
[i
].name
);
11797 if (dpyinfo
->font_table
)
11799 if (dpyinfo
->font_table
->font_encoder
)
11800 xfree (dpyinfo
->font_table
->font_encoder
);
11801 xfree (dpyinfo
->font_table
);
11803 if (dpyinfo
->mac_id_name
)
11804 xfree (dpyinfo
->mac_id_name
);
11806 if (x_display_list
== 0)
11808 mac_clear_font_name_table ();
11809 bzero (dpyinfo
, sizeof (*dpyinfo
));
11820 MenuItemIndex menu_index
;
11822 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11823 &menu
, &menu_index
);
11825 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11826 #if USE_CARBON_EVENTS
11827 EnableMenuCommand (NULL
, kHICommandPreferences
);
11828 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11829 &menu
, &menu_index
);
11832 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11833 InsertMenuItemTextWithCFString (menu
, NULL
,
11834 0, kMenuItemAttrSeparator
, 0);
11835 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11836 0, 0, kHICommandAbout
);
11838 #endif /* USE_CARBON_EVENTS */
11839 #else /* !MAC_OSX */
11840 #if USE_CARBON_EVENTS
11841 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11851 static InterfaceTypeList types
= {kUnicodeDocument
};
11853 static InterfaceTypeList types
= {kTextService
};
11856 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11857 &tsm_document_id
, 0);
11861 /* Set up use of X before we make the first connection. */
11863 extern frame_parm_handler mac_frame_parm_handlers
[];
11865 static struct redisplay_interface x_redisplay_interface
=
11867 mac_frame_parm_handlers
,
11871 x_clear_end_of_line
,
11873 x_after_update_window_line
,
11874 x_update_window_begin
,
11875 x_update_window_end
,
11879 mac_flush_display_optional
,
11881 0, /* flush_display_optional */
11883 x_clear_window_mouse_face
,
11884 x_get_glyph_overhangs
,
11885 x_fix_overlapping_area
,
11886 x_draw_fringe_bitmap
,
11888 mac_define_fringe_bitmap
,
11889 mac_destroy_fringe_bitmap
,
11891 0, /* define_fringe_bitmap */
11892 0, /* destroy_fringe_bitmap */
11894 mac_per_char_metric
,
11896 mac_compute_glyph_string_overhangs
,
11897 x_draw_glyph_string
,
11898 mac_define_frame_cursor
,
11899 mac_clear_frame_area
,
11900 mac_draw_window_cursor
,
11901 mac_draw_vertical_window_border
,
11902 mac_shift_glyphs_for_insert
11908 rif
= &x_redisplay_interface
;
11910 clear_frame_hook
= x_clear_frame
;
11911 ins_del_lines_hook
= x_ins_del_lines
;
11912 delete_glyphs_hook
= x_delete_glyphs
;
11913 ring_bell_hook
= XTring_bell
;
11914 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11915 set_terminal_modes_hook
= XTset_terminal_modes
;
11916 update_begin_hook
= x_update_begin
;
11917 update_end_hook
= x_update_end
;
11918 set_terminal_window_hook
= XTset_terminal_window
;
11919 read_socket_hook
= XTread_socket
;
11920 frame_up_to_date_hook
= XTframe_up_to_date
;
11921 mouse_position_hook
= XTmouse_position
;
11922 frame_rehighlight_hook
= XTframe_rehighlight
;
11923 frame_raise_lower_hook
= XTframe_raise_lower
;
11925 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11926 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11927 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11928 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11930 scroll_region_ok
= 1; /* we'll scroll partial frames */
11931 char_ins_del_ok
= 1;
11932 line_ins_del_ok
= 1; /* we'll just blt 'em */
11933 fast_clear_end_of_line
= 1; /* X does this well */
11934 memory_below_frame
= 0; /* we don't remember what scrolls
11938 last_tool_bar_item
= -1;
11939 any_help_event_p
= 0;
11941 /* Try to use interrupt input; if we can't, then start polling. */
11942 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11946 #if TARGET_API_MAC_CARBON
11948 #if USE_CARBON_EVENTS
11950 init_service_handler ();
11951 #endif /* MAC_OSX */
11953 init_command_handler ();
11960 #endif /* USE_CARBON_EVENTS */
11963 init_coercion_handler ();
11965 init_apple_event_handler ();
11967 init_dm_notification_handler ();
11969 if (!inhibit_window_system
)
11971 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
11973 SetFrontProcess (&psn
);
11981 mac_init_fringe ();
11992 staticpro (&x_error_message_string
);
11993 x_error_message_string
= Qnil
;
11996 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11997 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11998 Qalt
= intern ("alt"); staticpro (&Qalt
);
11999 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
12000 Qsuper
= intern ("super"); staticpro (&Qsuper
);
12001 Qmodifier_value
= intern ("modifier-value");
12002 staticpro (&Qmodifier_value
);
12004 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
12005 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12006 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12007 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12008 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12010 #if USE_CARBON_EVENTS
12011 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
12013 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
12014 staticpro (&Qtoolbar_switch_mode
);
12015 #if USE_MAC_FONT_PANEL
12016 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12017 Qselection
= intern ("selection"); staticpro (&Qselection
);
12020 Qservice
= intern ("service"); staticpro (&Qservice
);
12021 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12022 Qperform
= intern ("perform"); staticpro (&Qperform
);
12025 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12026 Qupdate_active_input_area
= intern ("update-active-input-area");
12027 staticpro (&Qupdate_active_input_area
);
12028 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12029 staticpro (&Qunicode_for_key_event
);
12034 Fprovide (intern ("mac-carbon"), Qnil
);
12037 staticpro (&Qreverse
);
12038 Qreverse
= intern ("reverse");
12040 staticpro (&x_display_name_list
);
12041 x_display_name_list
= Qnil
;
12043 staticpro (&last_mouse_scroll_bar
);
12044 last_mouse_scroll_bar
= Qnil
;
12046 staticpro (&fm_font_family_alist
);
12047 fm_font_family_alist
= Qnil
;
12050 staticpro (&atsu_font_id_hash
);
12051 atsu_font_id_hash
= Qnil
;
12053 staticpro (&fm_style_face_attributes_alist
);
12054 fm_style_face_attributes_alist
= Qnil
;
12058 staticpro (&saved_ts_script_language_on_focus
);
12059 saved_ts_script_language_on_focus
= Qnil
;
12062 /* We don't yet support this, but defining this here avoids whining
12063 from cus-start.el and other places, like "M-x set-variable". */
12064 DEFVAR_BOOL ("x-use-underline-position-properties",
12065 &x_use_underline_position_properties
,
12066 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12067 A value of nil means ignore them. If you encounter fonts with bogus
12068 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12069 to 4.1, set this to nil.
12071 NOTE: Not supported on Mac yet. */);
12072 x_use_underline_position_properties
= 0;
12074 DEFVAR_BOOL ("x-underline-at-descent-line",
12075 &x_underline_at_descent_line
,
12076 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12077 A value of nil means to draw the underline according to the value of the
12078 variable `x-use-underline-position-properties', which is usually at the
12079 baseline level. The default value is nil. */);
12080 x_underline_at_descent_line
= 0;
12082 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12083 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12084 #ifdef USE_TOOLKIT_SCROLL_BARS
12085 Vx_toolkit_scroll_bars
= Qt
;
12087 Vx_toolkit_scroll_bars
= Qnil
;
12090 staticpro (&last_mouse_motion_frame
);
12091 last_mouse_motion_frame
= Qnil
;
12093 /* Variables to configure modifier key assignment. */
12095 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12096 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12097 The value can be `control', `meta', `alt', `hyper', or `super' for the
12098 respective modifier. The default is `control'. */);
12099 Vmac_control_modifier
= Qcontrol
;
12101 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12102 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12103 The value can be `control', `meta', `alt', `hyper', or `super' for the
12104 respective modifier. If the value is nil then the key will act as the
12105 normal Mac control modifier, and the option key can be used to compose
12106 characters depending on the chosen Mac keyboard setting. */);
12107 Vmac_option_modifier
= Qnil
;
12109 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12110 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12111 The value can be `control', `meta', `alt', `hyper', or `super' for the
12112 respective modifier. The default is `meta'. */);
12113 Vmac_command_modifier
= Qmeta
;
12115 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12116 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12117 The value can be `control', `meta', `alt', `hyper', or `super' for the
12118 respective modifier. Note that remapping the function key may lead to
12119 unexpected results for some keys on non-US/GB keyboards. */);
12120 Vmac_function_modifier
= Qnil
;
12122 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12123 &Vmac_emulate_three_button_mouse
,
12124 doc
: /* *Specify a way of three button mouse emulation.
12125 The value can be nil, t, or the symbol `reverse'.
12126 A value of nil means that no emulation should be done and the modifiers
12127 should be placed on the mouse-1 event.
12128 t means that when the option-key is held down while pressing the mouse
12129 button, the click will register as mouse-2 and while the command-key
12130 is held down, the click will register as mouse-3.
12131 The symbol `reverse' means that the option-key will register for
12132 mouse-3 and the command-key will register for mouse-2. */);
12133 Vmac_emulate_three_button_mouse
= Qnil
;
12135 #if USE_CARBON_EVENTS
12136 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12137 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12138 Otherwise, the right click will be treated as mouse-2 and the wheel
12139 button will be mouse-3. */);
12140 mac_wheel_button_is_mouse_2
= 1;
12142 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12143 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12144 mac_pass_command_to_system
= 1;
12146 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12147 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12148 mac_pass_control_to_system
= 1;
12152 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
12153 doc
: /* *If non-nil, allow anti-aliasing.
12154 The text will be rendered using Core Graphics text rendering which
12155 may anti-alias the text. */);
12157 mac_use_core_graphics
= 1;
12159 mac_use_core_graphics
= 0;
12162 /* Register an entry for `mac-roman' so that it can be used when
12163 creating the terminal frame on Mac OS 9 before loading
12164 term/mac-win.elc. */
12165 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
12166 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
12167 Each entry should be of the form:
12169 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12171 where CHARSET-NAME is a string used in font names to identify the
12172 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12173 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12174 Vmac_charset_info_alist
=
12175 Fcons (list3 (build_string ("mac-roman"),
12176 make_number (smRoman
), Qnil
), Qnil
);
12179 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
12180 doc
: /* Overlay used to display Mac TSM active input area. */);
12181 Vmac_ts_active_input_overlay
= Qnil
;
12183 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
12184 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
12185 If the value is t, the input script and language are restored to those
12186 used in the last focus frame. If the value is a pair of integers, the
12187 input script and language codes, which are defined in the Script
12188 Manager, are set to its car and cdr parts, respectively. Otherwise,
12189 Emacs doesn't set them and thus follows the system default behavior. */);
12190 Vmac_ts_script_language_on_focus
= Qnil
;
12194 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12195 (do not change this comment) */