1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* 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
++)
2278 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2279 sizeof (unsigned short) * h
, NULL
);
2282 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2283 sizeof (unsigned short),
2285 CGDataProviderRelease (provider
);
2290 mac_destroy_fringe_bitmap (which
)
2293 if (which
>= max_fringe_bmp
)
2296 if (fringe_bmp
[which
])
2297 CGImageRelease (fringe_bmp
[which
]);
2298 fringe_bmp
[which
] = 0;
2303 /* This is called when starting Emacs and when restarting after
2304 suspend. When starting Emacs, no window is mapped. And nothing
2305 must be done to Emacs's own window if it is suspended (though that
2309 XTset_terminal_modes ()
2313 /* This is called when exiting or suspending Emacs. Exiting will make
2314 the windows go away, and suspending requires no action. */
2317 XTreset_terminal_modes ()
2323 /***********************************************************************
2325 ***********************************************************************/
2327 /* Function prototypes of this page. */
2329 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2330 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2334 pcm_init (pcm
, count
)
2338 bzero (pcm
, sizeof (XCharStruct
) * count
);
2339 while (--count
>= 0)
2341 pcm
->descent
= PCM_INVALID
;
2346 static enum pcm_status
2347 pcm_get_status (pcm
)
2348 const XCharStruct
*pcm
;
2350 int height
= pcm
->ascent
+ pcm
->descent
;
2352 /* Negative height means some special status. */
2353 return height
>= 0 ? PCM_VALID
: height
;
2356 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2357 is not contained in the font. */
2359 static INLINE XCharStruct
*
2360 x_per_char_metric (font
, char2b
)
2364 /* The result metric information. */
2365 XCharStruct
*pcm
= NULL
;
2367 xassert (font
&& char2b
);
2370 if (font
->mac_style
)
2372 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2376 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2377 pcm_init (*row
, 0x100);
2379 pcm
= *row
+ char2b
->byte2
;
2380 if (pcm_get_status (pcm
) != PCM_VALID
)
2383 mac_query_char_extents (font
->mac_style
,
2384 (char2b
->byte1
<< 8) + char2b
->byte2
,
2385 NULL
, NULL
, pcm
, NULL
);
2392 if (font
->bounds
.per_char
!= NULL
)
2394 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2396 /* min_char_or_byte2 specifies the linear character index
2397 corresponding to the first element of the per_char array,
2398 max_char_or_byte2 is the index of the last character. A
2399 character with non-zero CHAR2B->byte1 is not in the font.
2400 A character with byte2 less than min_char_or_byte2 or
2401 greater max_char_or_byte2 is not in the font. */
2402 if (char2b
->byte1
== 0
2403 && char2b
->byte2
>= font
->min_char_or_byte2
2404 && char2b
->byte2
<= font
->max_char_or_byte2
)
2405 pcm
= font
->bounds
.per_char
2406 + (char2b
->byte2
- font
->min_char_or_byte2
);
2410 /* If either min_byte1 or max_byte1 are nonzero, both
2411 min_char_or_byte2 and max_char_or_byte2 are less than
2412 256, and the 2-byte character index values corresponding
2413 to the per_char array element N (counting from 0) are:
2415 byte1 = N/D + min_byte1
2416 byte2 = N\D + min_char_or_byte2
2420 D = max_char_or_byte2 - min_char_or_byte2 + 1
2421 / = integer division
2422 \ = integer modulus */
2423 if (char2b
->byte1
>= font
->min_byte1
2424 && char2b
->byte1
<= font
->max_byte1
2425 && char2b
->byte2
>= font
->min_char_or_byte2
2426 && char2b
->byte2
<= font
->max_char_or_byte2
)
2428 pcm
= (font
->bounds
.per_char
2429 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2430 * (char2b
->byte1
- font
->min_byte1
))
2431 + (char2b
->byte2
- font
->min_char_or_byte2
));
2437 /* If the per_char pointer is null, all glyphs between the first
2438 and last character indexes inclusive have the same
2439 information, as given by both min_bounds and max_bounds. */
2440 if (char2b
->byte2
>= font
->min_char_or_byte2
2441 && char2b
->byte2
<= font
->max_char_or_byte2
)
2442 pcm
= &font
->max_bounds
;
2448 return ((pcm
== NULL
2450 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2451 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2460 static XCharStruct
*
2461 mac_per_char_metric (font
, char2b
, font_type
)
2466 return x_per_char_metric (font
, char2b
);
2470 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2471 the two-byte form of C. Encoding is returned in *CHAR2B. */
2474 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2477 struct font_info
*font_info
;
2480 int charset
= CHAR_CHARSET (c
);
2481 XFontStruct
*font
= font_info
->font
;
2483 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2484 This may be either a program in a special encoder language or a
2486 if (font_info
->font_encoder
)
2488 /* It's a program. */
2489 struct ccl_program
*ccl
= font_info
->font_encoder
;
2491 check_ccl_update (ccl
);
2492 if (CHARSET_DIMENSION (charset
) == 1)
2494 ccl
->reg
[0] = charset
;
2495 ccl
->reg
[1] = char2b
->byte2
;
2500 ccl
->reg
[0] = charset
;
2501 ccl
->reg
[1] = char2b
->byte1
;
2502 ccl
->reg
[2] = char2b
->byte2
;
2505 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2507 /* We assume that MSBs are appropriately set/reset by CCL
2509 if (font
->max_byte1
== 0) /* 1-byte font */
2510 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2512 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2514 else if (font_info
->encoding
[charset
])
2516 /* Fixed encoding scheme. See fontset.h for the meaning of the
2517 encoding numbers. */
2518 int enc
= font_info
->encoding
[charset
];
2520 if ((enc
== 1 || enc
== 2)
2521 && CHARSET_DIMENSION (charset
) == 2)
2522 char2b
->byte1
|= 0x80;
2524 if (enc
== 1 || enc
== 3)
2525 char2b
->byte2
|= 0x80;
2531 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2532 char2b
->byte1
= sjis1
;
2533 char2b
->byte2
= sjis2
;
2538 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2540 return FONT_TYPE_UNKNOWN
;
2545 /***********************************************************************
2547 ***********************************************************************/
2551 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2552 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2553 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2555 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2556 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2557 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2558 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2559 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2560 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2561 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2562 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2563 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2564 unsigned long *, double, int));*/
2565 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2566 double, int, unsigned long));
2567 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2568 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2569 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2570 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2571 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2573 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2574 int, int, int, int, int, int,
2576 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2577 int, int, int, Rect
*));
2580 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2584 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2589 struct glyph_string
*s
;
2591 if (s
->font
== FRAME_FONT (s
->f
)
2592 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2593 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2595 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2598 /* Cursor on non-default face: must merge. */
2602 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2603 xgcv
.foreground
= s
->face
->background
;
2605 /* If the glyph would be invisible, try a different foreground. */
2606 if (xgcv
.foreground
== xgcv
.background
)
2607 xgcv
.foreground
= s
->face
->foreground
;
2608 if (xgcv
.foreground
== xgcv
.background
)
2609 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2610 if (xgcv
.foreground
== xgcv
.background
)
2611 xgcv
.foreground
= s
->face
->foreground
;
2613 /* Make sure the cursor is distinct from text in this face. */
2614 if (xgcv
.background
== s
->face
->background
2615 && xgcv
.foreground
== s
->face
->foreground
)
2617 xgcv
.background
= s
->face
->foreground
;
2618 xgcv
.foreground
= s
->face
->background
;
2621 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2622 xgcv
.font
= s
->font
;
2623 mask
= GCForeground
| GCBackground
| GCFont
;
2625 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2626 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2629 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2630 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2632 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2637 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2640 x_set_mouse_face_gc (s
)
2641 struct glyph_string
*s
;
2646 /* What face has to be used last for the mouse face? */
2647 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2648 face
= FACE_FROM_ID (s
->f
, face_id
);
2650 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2652 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2653 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2655 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2656 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2657 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2659 /* If font in this face is same as S->font, use it. */
2660 if (s
->font
== s
->face
->font
)
2661 s
->gc
= s
->face
->gc
;
2664 /* Otherwise construct scratch_cursor_gc with values from FACE
2669 xgcv
.background
= s
->face
->background
;
2670 xgcv
.foreground
= s
->face
->foreground
;
2671 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2672 xgcv
.font
= s
->font
;
2673 mask
= GCForeground
| GCBackground
| GCFont
;
2675 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2676 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2679 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2680 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2682 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2685 xassert (s
->gc
!= 0);
2689 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2690 Faces to use in the mode line have already been computed when the
2691 matrix was built, so there isn't much to do, here. */
2694 x_set_mode_line_face_gc (s
)
2695 struct glyph_string
*s
;
2697 s
->gc
= s
->face
->gc
;
2701 /* Set S->gc of glyph string S for drawing that glyph string. Set
2702 S->stippled_p to a non-zero value if the face of S has a stipple
2706 x_set_glyph_string_gc (s
)
2707 struct glyph_string
*s
;
2709 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2711 if (s
->hl
== DRAW_NORMAL_TEXT
)
2713 s
->gc
= s
->face
->gc
;
2714 s
->stippled_p
= s
->face
->stipple
!= 0;
2716 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2718 x_set_mode_line_face_gc (s
);
2719 s
->stippled_p
= s
->face
->stipple
!= 0;
2721 else if (s
->hl
== DRAW_CURSOR
)
2723 x_set_cursor_gc (s
);
2726 else if (s
->hl
== DRAW_MOUSE_FACE
)
2728 x_set_mouse_face_gc (s
);
2729 s
->stippled_p
= s
->face
->stipple
!= 0;
2731 else if (s
->hl
== DRAW_IMAGE_RAISED
2732 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2734 s
->gc
= s
->face
->gc
;
2735 s
->stippled_p
= s
->face
->stipple
!= 0;
2739 s
->gc
= s
->face
->gc
;
2740 s
->stippled_p
= s
->face
->stipple
!= 0;
2743 /* GC must have been set. */
2744 xassert (s
->gc
!= 0);
2748 /* Set clipping for output of glyph string S. S may be part of a mode
2749 line or menu if we don't have X toolkit support. */
2752 x_set_glyph_string_clipping (s
)
2753 struct glyph_string
*s
;
2755 Rect rects
[MAX_CLIP_RECTS
];
2758 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2759 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2764 Compute left and right overhang of glyph string S. If S is a glyph
2765 string for a composition, assume overhangs don't exist. */
2768 mac_compute_glyph_string_overhangs (s
)
2769 struct glyph_string
*s
;
2771 if (!(s
->cmp
== NULL
2772 && s
->first_glyph
->type
== CHAR_GLYPH
))
2777 || s
->font
->mac_style
2783 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2784 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2785 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2790 MacFontStruct
*font
= s
->font
;
2793 mac_prepare_for_quickdraw (s
->f
);
2795 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2797 TextFont (font
->mac_fontnum
);
2798 TextSize (font
->mac_fontsize
);
2799 TextFace (font
->mac_fontface
);
2801 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2803 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2804 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2809 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2812 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2813 struct glyph_string
*s
;
2816 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2820 /* Draw the background of glyph_string S. If S->background_filled_p
2821 is non-zero don't draw it. FORCE_P non-zero means draw the
2822 background even if it wouldn't be drawn normally. This is used
2823 when a string preceding S draws into the background of S, or S
2824 contains the first component of a composition. */
2827 x_draw_glyph_string_background (s
, force_p
)
2828 struct glyph_string
*s
;
2831 /* Nothing to do if background has already been drawn or if it
2832 shouldn't be drawn in the first place. */
2833 if (!s
->background_filled_p
)
2835 int box_line_width
= max (s
->face
->box_line_width
, 0);
2837 #if 0 /* MAC_TODO: stipple */
2840 /* Fill background with a stipple pattern. */
2841 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2842 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2843 s
->y
+ box_line_width
,
2844 s
->background_width
,
2845 s
->height
- 2 * box_line_width
);
2846 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2847 s
->background_filled_p
= 1;
2851 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2852 || s
->font_not_found_p
2853 || s
->extends_to_end_of_line_p
2856 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2857 s
->background_width
,
2858 s
->height
- 2 * box_line_width
);
2859 s
->background_filled_p
= 1;
2865 /* Draw the foreground of glyph string S. */
2868 x_draw_glyph_string_foreground (s
)
2869 struct glyph_string
*s
;
2873 /* If first glyph of S has a left box line, start drawing the text
2874 of S to the right of that box line. */
2875 if (s
->face
->box
!= FACE_NO_BOX
2876 && s
->first_glyph
->left_box_line_p
)
2877 x
= s
->x
+ abs (s
->face
->box_line_width
);
2881 /* Draw characters of S as rectangles if S's font could not be
2883 if (s
->font_not_found_p
)
2885 for (i
= 0; i
< s
->nchars
; ++i
)
2887 struct glyph
*g
= s
->first_glyph
+ i
;
2888 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2889 g
->pixel_width
- 1, s
->height
- 1);
2890 x
+= g
->pixel_width
;
2895 char *char1b
= (char *) s
->char2b
;
2896 int boff
= s
->font_info
->baseline_offset
;
2898 if (s
->font_info
->vertical_centering
)
2899 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2901 /* If we can use 8-bit functions, condense S->char2b. */
2904 && GC_FONT (s
->gc
)->mac_style
== NULL
2907 for (i
= 0; i
< s
->nchars
; ++i
)
2908 char1b
[i
] = s
->char2b
[i
].byte2
;
2910 /* Draw text with XDrawString if background has already been
2911 filled. Otherwise, use XDrawImageString. (Note that
2912 XDrawImageString is usually faster than XDrawString.) Always
2913 use XDrawImageString when drawing the cursor so that there is
2914 no chance that characters under a box cursor are invisible. */
2916 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2917 bg_width
= 0; /* Corresponds to XDrawString. */
2919 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2923 || GC_FONT (s
->gc
)->mac_style
2926 #if USE_CG_TEXT_DRAWING
2928 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2929 s
->char2b
, s
->nchars
, bg_width
,
2930 s
->face
->overstrike
))
2934 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2935 s
->char2b
, s
->nchars
, bg_width
,
2936 s
->face
->overstrike
);
2938 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2939 char1b
, s
->nchars
, bg_width
,
2940 s
->face
->overstrike
);
2944 /* Draw the foreground of composite glyph string S. */
2947 x_draw_composite_glyph_string_foreground (s
)
2948 struct glyph_string
*s
;
2952 /* If first glyph of S has a left box line, start drawing the text
2953 of S to the right of that box line. */
2954 if (s
->face
->box
!= FACE_NO_BOX
2955 && s
->first_glyph
->left_box_line_p
)
2956 x
= s
->x
+ abs (s
->face
->box_line_width
);
2960 /* S is a glyph string for a composition. S->gidx is the index of
2961 the first character drawn for glyphs of this composition.
2962 S->gidx == 0 means we are drawing the very first character of
2963 this composition. */
2965 /* Draw a rectangle for the composition if the font for the very
2966 first character of the composition could not be loaded. */
2967 if (s
->font_not_found_p
)
2970 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2971 s
->width
- 1, s
->height
- 1);
2975 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2976 mac_draw_image_string_16 (s
->f
, s
->gc
,
2977 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2978 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2979 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
2984 #ifdef USE_X_TOOLKIT
2986 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2989 /* Return the frame on which widget WIDGET is used.. Abort if frame
2990 cannot be determined. */
2992 static struct frame
*
2993 x_frame_of_widget (widget
)
2996 struct x_display_info
*dpyinfo
;
3000 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3002 /* Find the top-level shell of the widget. Note that this function
3003 can be called when the widget is not yet realized, so XtWindow
3004 (widget) == 0. That's the reason we can't simply use
3005 x_any_window_to_frame. */
3006 while (!XtIsTopLevelShell (widget
))
3007 widget
= XtParent (widget
);
3009 /* Look for a frame with that top-level widget. Allocate the color
3010 on that frame to get the right gamma correction value. */
3011 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3012 if (GC_FRAMEP (XCAR (tail
))
3013 && (f
= XFRAME (XCAR (tail
)),
3014 (f
->output_data
.nothing
!= 1
3015 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3016 && f
->output_data
.x
->widget
== widget
)
3023 /* Allocate the color COLOR->pixel on the screen and display of
3024 widget WIDGET in colormap CMAP. If an exact match cannot be
3025 allocated, try the nearest color available. Value is non-zero
3026 if successful. This is called from lwlib. */
3029 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3034 struct frame
*f
= x_frame_of_widget (widget
);
3035 return x_alloc_nearest_color (f
, cmap
, color
);
3039 #endif /* USE_X_TOOLKIT */
3041 #if 0 /* MAC_TODO */
3043 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3044 CMAP. If an exact match can't be allocated, try the nearest color
3045 available. Value is non-zero if successful. Set *COLOR to the
3049 x_alloc_nearest_color (f
, cmap
, color
)
3054 Display
*display
= FRAME_X_DISPLAY (f
);
3055 Screen
*screen
= FRAME_X_SCREEN (f
);
3058 gamma_correct (f
, color
);
3059 rc
= XAllocColor (display
, cmap
, color
);
3062 /* If we got to this point, the colormap is full, so we're going
3063 to try to get the next closest color. The algorithm used is
3064 a least-squares matching, which is what X uses for closest
3065 color matching with StaticColor visuals. */
3067 unsigned long nearest_delta
= ~0;
3068 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3069 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3071 for (i
= 0; i
< ncells
; ++i
)
3073 XQueryColors (display
, cmap
, cells
, ncells
);
3075 for (nearest
= i
= 0; i
< ncells
; ++i
)
3077 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3078 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3079 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3080 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3082 if (delta
< nearest_delta
)
3085 nearest_delta
= delta
;
3089 color
->red
= cells
[nearest
].red
;
3090 color
->green
= cells
[nearest
].green
;
3091 color
->blue
= cells
[nearest
].blue
;
3092 rc
= XAllocColor (display
, cmap
, color
);
3095 #ifdef DEBUG_X_COLORS
3097 register_color (color
->pixel
);
3098 #endif /* DEBUG_X_COLORS */
3104 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3105 It's necessary to do this instead of just using PIXEL directly to
3106 get color reference counts right. */
3109 x_copy_color (f
, pixel
)
3111 unsigned long pixel
;
3115 color
.pixel
= pixel
;
3117 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3118 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3120 #ifdef DEBUG_X_COLORS
3121 register_color (pixel
);
3127 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3128 It's necessary to do this instead of just using PIXEL directly to
3129 get color reference counts right. */
3132 x_copy_dpy_color (dpy
, cmap
, pixel
)
3135 unsigned long pixel
;
3139 color
.pixel
= pixel
;
3141 XQueryColor (dpy
, cmap
, &color
);
3142 XAllocColor (dpy
, cmap
, &color
);
3144 #ifdef DEBUG_X_COLORS
3145 register_color (pixel
);
3150 #endif /* MAC_TODO */
3153 /* Brightness beyond which a color won't have its highlight brightness
3156 Nominally, highlight colors for `3d' faces are calculated by
3157 brightening an object's color by a constant scale factor, but this
3158 doesn't yield good results for dark colors, so for colors who's
3159 brightness is less than this value (on a scale of 0-255) have to
3160 use an additional additive factor.
3162 The value here is set so that the default menu-bar/mode-line color
3163 (grey75) will not have its highlights changed at all. */
3164 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3167 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3168 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3169 If this produces the same color as COLOR, try a color where all RGB
3170 values have DELTA added. Return the allocated color in *COLOR.
3171 DISPLAY is the X display, CMAP is the colormap to operate on.
3172 Value is non-zero if successful. */
3175 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3177 unsigned long *color
;
3184 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3187 /* Change RGB values by specified FACTOR. Avoid overflow! */
3188 xassert (factor
>= 0);
3189 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3190 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3191 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3193 /* Calculate brightness of COLOR. */
3194 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3195 + BLUE_FROM_ULONG (*color
)) / 6;
3197 /* We only boost colors that are darker than
3198 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3199 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3200 /* Make an additive adjustment to NEW, because it's dark enough so
3201 that scaling by FACTOR alone isn't enough. */
3203 /* How far below the limit this color is (0 - 1, 1 being darker). */
3204 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3205 /* The additive adjustment. */
3206 int min_delta
= delta
* dimness
* factor
/ 2;
3209 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3210 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3211 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3213 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3214 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3215 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3219 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3220 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3221 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3223 /* MAC_TODO: Map to palette and retry with delta if same? */
3224 /* MAC_TODO: Free colors (if using palette)? */
3235 /* Set up the foreground color for drawing relief lines of glyph
3236 string S. RELIEF is a pointer to a struct relief containing the GC
3237 with which lines will be drawn. Use a color that is FACTOR or
3238 DELTA lighter or darker than the relief's background which is found
3239 in S->f->output_data.x->relief_background. If such a color cannot
3240 be allocated, use DEFAULT_PIXEL, instead. */
3243 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3245 struct relief
*relief
;
3248 unsigned long default_pixel
;
3251 struct mac_output
*di
= f
->output_data
.mac
;
3252 unsigned long mask
= GCForeground
;
3253 unsigned long pixel
;
3254 unsigned long background
= di
->relief_background
;
3255 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3257 /* MAC_TODO: Free colors (if using palette)? */
3259 /* Allocate new color. */
3260 xgcv
.foreground
= default_pixel
;
3262 if (dpyinfo
->n_planes
!= 1
3263 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3265 relief
->allocated_p
= 1;
3266 xgcv
.foreground
= relief
->pixel
= pixel
;
3269 if (relief
->gc
== 0)
3271 #if 0 /* MAC_TODO: stipple */
3272 xgcv
.stipple
= dpyinfo
->gray
;
3275 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3278 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3282 /* Set up colors for the relief lines around glyph string S. */
3285 x_setup_relief_colors (s
)
3286 struct glyph_string
*s
;
3288 struct mac_output
*di
= s
->f
->output_data
.mac
;
3289 unsigned long color
;
3291 if (s
->face
->use_box_color_for_shadows_p
)
3292 color
= s
->face
->box_color
;
3293 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3295 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3296 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3301 /* Get the background color of the face. */
3302 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3303 color
= xgcv
.background
;
3306 if (di
->white_relief
.gc
== 0
3307 || color
!= di
->relief_background
)
3309 di
->relief_background
= color
;
3310 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3311 WHITE_PIX_DEFAULT (s
->f
));
3312 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3313 BLACK_PIX_DEFAULT (s
->f
));
3318 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3319 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3320 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3321 relief. LEFT_P non-zero means draw a relief on the left side of
3322 the rectangle. RIGHT_P non-zero means draw a relief on the right
3323 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3327 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3328 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3330 int left_x
, top_y
, right_x
, bottom_y
, width
;
3331 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3334 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3339 gc
= f
->output_data
.mac
->white_relief
.gc
;
3341 gc
= f
->output_data
.mac
->black_relief
.gc
;
3342 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3346 for (i
= 0; i
< width
; ++i
)
3347 mac_draw_line (f
, gc
,
3348 left_x
+ i
* left_p
, top_y
+ i
,
3349 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3353 for (i
= 0; i
< width
; ++i
)
3354 mac_draw_line (f
, gc
,
3355 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3357 mac_reset_clip_rectangles (dpy
, gc
);
3359 gc
= f
->output_data
.mac
->black_relief
.gc
;
3361 gc
= f
->output_data
.mac
->white_relief
.gc
;
3362 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3366 for (i
= 0; i
< width
; ++i
)
3367 mac_draw_line (f
, gc
,
3368 left_x
+ i
* left_p
, bottom_y
- i
,
3369 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3373 for (i
= 0; i
< width
; ++i
)
3374 mac_draw_line (f
, gc
,
3375 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3377 mac_reset_clip_rectangles (dpy
, gc
);
3381 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3382 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3383 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3384 left side of the rectangle. RIGHT_P non-zero means draw a line
3385 on the right side of the rectangle. CLIP_RECT is the clipping
3386 rectangle to use when drawing. */
3389 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3390 left_p
, right_p
, clip_rect
)
3391 struct glyph_string
*s
;
3392 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3397 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3398 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3399 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3402 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3403 right_x
- left_x
+ 1, width
);
3407 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3408 width
, bottom_y
- top_y
+ 1);
3411 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3412 right_x
- left_x
+ 1, width
);
3416 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3417 top_y
, width
, bottom_y
- top_y
+ 1);
3419 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3420 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3424 /* Draw a box around glyph string S. */
3427 x_draw_glyph_string_box (s
)
3428 struct glyph_string
*s
;
3430 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3431 int left_p
, right_p
;
3432 struct glyph
*last_glyph
;
3435 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3436 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3437 : window_box_right (s
->w
, s
->area
));
3439 /* The glyph that may have a right box line. */
3440 last_glyph
= (s
->cmp
|| s
->img
3442 : s
->first_glyph
+ s
->nchars
- 1);
3444 width
= abs (s
->face
->box_line_width
);
3445 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3447 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3449 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3451 bottom_y
= top_y
+ s
->height
- 1;
3453 left_p
= (s
->first_glyph
->left_box_line_p
3454 || (s
->hl
== DRAW_MOUSE_FACE
3456 || s
->prev
->hl
!= s
->hl
)));
3457 right_p
= (last_glyph
->right_box_line_p
3458 || (s
->hl
== DRAW_MOUSE_FACE
3460 || s
->next
->hl
!= s
->hl
)));
3462 get_glyph_string_clip_rect (s
, &clip_rect
);
3464 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3465 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3466 left_p
, right_p
, &clip_rect
);
3469 x_setup_relief_colors (s
);
3470 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3471 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3476 /* Draw foreground of image glyph string S. */
3479 x_draw_image_foreground (s
)
3480 struct glyph_string
*s
;
3483 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3485 /* If first glyph of S has a left box line, start drawing it to the
3486 right of that line. */
3487 if (s
->face
->box
!= FACE_NO_BOX
3488 && s
->first_glyph
->left_box_line_p
3490 x
+= abs (s
->face
->box_line_width
);
3492 /* If there is a margin around the image, adjust x- and y-position
3494 if (s
->slice
.x
== 0)
3495 x
+= s
->img
->hmargin
;
3496 if (s
->slice
.y
== 0)
3497 y
+= s
->img
->vmargin
;
3501 x_set_glyph_string_clipping (s
);
3504 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3505 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3506 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3510 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3511 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3512 s
->slice
.width
, s
->slice
.height
, x
, y
);
3519 mac_copy_area (s
->img
->pixmap
,
3520 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3521 s
->slice
.width
, s
->slice
.height
, x
, y
);
3524 /* When the image has a mask, we can expect that at
3525 least part of a mouse highlight or a block cursor will
3526 be visible. If the image doesn't have a mask, make
3527 a block cursor visible by drawing a rectangle around
3528 the image. I believe it's looking better if we do
3529 nothing here for mouse-face. */
3530 if (s
->hl
== DRAW_CURSOR
)
3532 int r
= s
->img
->relief
;
3534 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3535 s
->slice
.width
+ r
*2 - 1,
3536 s
->slice
.height
+ r
*2 - 1);
3541 /* Draw a rectangle if image could not be loaded. */
3542 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3543 s
->slice
.width
- 1, s
->slice
.height
- 1);
3547 /* Draw a relief around the image glyph string S. */
3550 x_draw_image_relief (s
)
3551 struct glyph_string
*s
;
3553 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3556 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3558 /* If first glyph of S has a left box line, start drawing it to the
3559 right of that line. */
3560 if (s
->face
->box
!= FACE_NO_BOX
3561 && s
->first_glyph
->left_box_line_p
3563 x
+= abs (s
->face
->box_line_width
);
3565 /* If there is a margin around the image, adjust x- and y-position
3567 if (s
->slice
.x
== 0)
3568 x
+= s
->img
->hmargin
;
3569 if (s
->slice
.y
== 0)
3570 y
+= s
->img
->vmargin
;
3572 if (s
->hl
== DRAW_IMAGE_SUNKEN
3573 || s
->hl
== DRAW_IMAGE_RAISED
)
3575 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3576 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3580 thick
= abs (s
->img
->relief
);
3581 raised_p
= s
->img
->relief
> 0;
3586 x1
= x
+ s
->slice
.width
+ thick
- 1;
3587 y1
= y
+ s
->slice
.height
+ thick
- 1;
3589 x_setup_relief_colors (s
);
3590 get_glyph_string_clip_rect (s
, &r
);
3591 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3593 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3595 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3600 /* Draw part of the background of glyph string S. X, Y, W, and H
3601 give the rectangle to draw. */
3604 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3605 struct glyph_string
*s
;
3608 #if 0 /* MAC_TODO: stipple */
3611 /* Fill background with a stipple pattern. */
3612 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3613 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3614 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3617 #endif /* MAC_TODO */
3618 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3622 /* Draw image glyph string S.
3625 s->x +-------------------------
3628 | +-------------------------
3631 | | +-------------------
3637 x_draw_image_glyph_string (s
)
3638 struct glyph_string
*s
;
3641 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3642 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3645 height
= s
->height
- 2 * box_line_vwidth
;
3648 /* Fill background with face under the image. Do it only if row is
3649 taller than image or if image has a clip mask to reduce
3651 s
->stippled_p
= s
->face
->stipple
!= 0;
3652 if (height
> s
->slice
.height
3656 || s
->img
->pixmap
== 0
3657 || s
->width
!= s
->background_width
)
3660 if (s
->first_glyph
->left_box_line_p
3662 x
+= box_line_hwidth
;
3665 if (s
->slice
.y
== 0)
3666 y
+= box_line_vwidth
;
3668 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3670 s
->background_filled_p
= 1;
3673 /* Draw the foreground. */
3674 x_draw_image_foreground (s
);
3676 /* If we must draw a relief around the image, do it. */
3678 || s
->hl
== DRAW_IMAGE_RAISED
3679 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3680 x_draw_image_relief (s
);
3684 /* Draw stretch glyph string S. */
3687 x_draw_stretch_glyph_string (s
)
3688 struct glyph_string
*s
;
3690 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3691 s
->stippled_p
= s
->face
->stipple
!= 0;
3693 if (s
->hl
== DRAW_CURSOR
3694 && !x_stretch_cursor_p
)
3696 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3697 as wide as the stretch glyph. */
3698 int width
, background_width
= s
->background_width
;
3699 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3703 background_width
-= left_x
- x
;
3706 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3709 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3711 /* Clear rest using the GC of the original non-cursor face. */
3712 if (width
< background_width
)
3715 int w
= background_width
- width
, h
= s
->height
;
3720 if (s
->row
->mouse_face_p
3721 && cursor_in_mouse_face_p (s
->w
))
3723 x_set_mouse_face_gc (s
);
3729 get_glyph_string_clip_rect (s
, &r
);
3730 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3732 #if 0 /* MAC_TODO: stipple */
3733 if (s
->face
->stipple
)
3735 /* Fill background with a stipple pattern. */
3736 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3737 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3738 XSetFillStyle (s
->display
, gc
, FillSolid
);
3741 #endif /* MAC_TODO */
3742 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3745 else if (!s
->background_filled_p
)
3747 int background_width
= s
->background_width
;
3748 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3750 /* Don't draw into left margin, fringe or scrollbar area
3751 except for header line and mode line. */
3752 if (x
< left_x
&& !s
->row
->mode_line_p
)
3754 background_width
-= left_x
- x
;
3757 if (background_width
> 0)
3758 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3761 s
->background_filled_p
= 1;
3765 /* Draw glyph string S. */
3768 x_draw_glyph_string (s
)
3769 struct glyph_string
*s
;
3771 int relief_drawn_p
= 0;
3773 /* If S draws into the background of its successor that does not
3774 draw a cursor, draw the background of the successor first so that
3775 S can draw into it. This makes S->next use XDrawString instead
3776 of XDrawImageString. */
3777 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3778 && s
->next
->hl
!= DRAW_CURSOR
)
3780 xassert (s
->next
->img
== NULL
);
3781 x_set_glyph_string_gc (s
->next
);
3782 x_set_glyph_string_clipping (s
->next
);
3783 x_draw_glyph_string_background (s
->next
, 1);
3786 /* Set up S->gc, set clipping and draw S. */
3787 x_set_glyph_string_gc (s
);
3789 /* Draw relief (if any) in advance for char/composition so that the
3790 glyph string can be drawn over it. */
3791 if (!s
->for_overlaps
3792 && s
->face
->box
!= FACE_NO_BOX
3793 && (s
->first_glyph
->type
== CHAR_GLYPH
3794 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3797 x_set_glyph_string_clipping (s
);
3798 x_draw_glyph_string_background (s
, 1);
3799 x_draw_glyph_string_box (s
);
3800 x_set_glyph_string_clipping (s
);
3804 x_set_glyph_string_clipping (s
);
3806 switch (s
->first_glyph
->type
)
3809 x_draw_image_glyph_string (s
);
3813 x_draw_stretch_glyph_string (s
);
3817 if (s
->for_overlaps
)
3818 s
->background_filled_p
= 1;
3820 x_draw_glyph_string_background (s
, 0);
3821 x_draw_glyph_string_foreground (s
);
3824 case COMPOSITE_GLYPH
:
3825 if (s
->for_overlaps
|| s
->gidx
> 0)
3826 s
->background_filled_p
= 1;
3828 x_draw_glyph_string_background (s
, 1);
3829 x_draw_composite_glyph_string_foreground (s
);
3836 if (!s
->for_overlaps
)
3838 /* Draw underline. */
3839 if (s
->face
->underline_p
)
3841 unsigned long tem
, h
;
3845 /* Get the underline thickness. Default is 1 pixel. */
3846 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3850 y
= s
->y
+ s
->height
- h
;
3851 if (!x_underline_at_descent_line
)
3853 /* Get the underline position. This is the recommended
3854 vertical offset in pixels from the baseline to the top of
3855 the underline. This is a signed value according to the
3856 specs, and its default is
3858 ROUND ((maximum descent) / 2), with
3859 ROUND(x) = floor (x + 0.5) */
3862 if (x_use_underline_position_properties
3863 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3864 y
= s
->ybase
+ (long) tem
;
3868 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3871 if (s
->face
->underline_defaulted_p
)
3872 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3873 s
->background_width
, h
);
3877 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3878 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3879 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3880 s
->background_width
, h
);
3881 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3885 /* Draw overline. */
3886 if (s
->face
->overline_p
)
3888 unsigned long dy
= 0, h
= 1;
3890 if (s
->face
->overline_color_defaulted_p
)
3891 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3892 s
->background_width
, h
);
3896 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3897 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3898 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3899 s
->background_width
, h
);
3900 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3904 /* Draw strike-through. */
3905 if (s
->face
->strike_through_p
)
3907 unsigned long h
= 1;
3908 unsigned long dy
= (s
->height
- h
) / 2;
3910 if (s
->face
->strike_through_color_defaulted_p
)
3911 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3916 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3917 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3918 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3920 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3924 /* Draw relief if not yet drawn. */
3925 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3926 x_draw_glyph_string_box (s
);
3929 /* Reset clipping. */
3930 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3933 /* Shift display to make room for inserted glyphs. */
3936 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3938 int x
, y
, width
, height
, shift_by
;
3940 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3941 x
, y
, width
, height
,
3945 /* Delete N glyphs at the nominal cursor position. Not implemented
3956 /* Clear entire frame. If updating_frame is non-null, clear that
3957 frame. Otherwise clear the selected frame. */
3967 f
= SELECTED_FRAME ();
3969 /* Clearing the frame will erase any cursor, so mark them all as no
3971 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3972 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3973 output_cursor
.x
= -1;
3975 /* We don't set the output cursor here because there will always
3976 follow an explicit cursor_to. */
3978 mac_clear_window (f
);
3980 /* We have to clear the scroll bars, too. If we have changed
3981 colors or something like that, then they should be notified. */
3982 x_scroll_bar_clear (f
);
3984 XFlush (FRAME_MAC_DISPLAY (f
));
3990 /* Invert the middle quarter of the frame for .15 sec. */
3992 /* We use the select system call to do the waiting, so we have to make
3993 sure it's available. If it isn't, we just won't do visual bells. */
3995 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3998 /* Subtract the `struct timeval' values X and Y, storing the result in
3999 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4002 timeval_subtract (result
, x
, y
)
4003 struct timeval
*result
, x
, y
;
4005 /* Perform the carry for the later subtraction by updating y. This
4006 is safer because on some systems the tv_sec member is unsigned. */
4007 if (x
.tv_usec
< y
.tv_usec
)
4009 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4010 y
.tv_usec
-= 1000000 * nsec
;
4014 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4016 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4017 y
.tv_usec
+= 1000000 * nsec
;
4021 /* Compute the time remaining to wait. tv_usec is certainly
4023 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4024 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4026 /* Return indication of whether the result should be considered
4028 return x
.tv_sec
< y
.tv_sec
;
4035 /* Get the height not including a menu bar widget. */
4036 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4037 /* Height of each line to flash. */
4038 int flash_height
= FRAME_LINE_HEIGHT (f
);
4039 /* These will be the left and right margins of the rectangles. */
4040 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4041 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4045 /* Don't flash the area between a scroll bar and the frame
4046 edge it is next to. */
4047 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4049 case vertical_scroll_bar_left
:
4050 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4053 case vertical_scroll_bar_right
:
4054 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4061 width
= flash_right
- flash_left
;
4065 /* If window is tall, flash top and bottom line. */
4066 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4068 mac_invert_rectangle (f
, flash_left
,
4069 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4070 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4071 width
, flash_height
);
4072 mac_invert_rectangle (f
, flash_left
,
4073 (height
- flash_height
4074 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4075 width
, flash_height
);
4078 /* If it is short, flash it all. */
4079 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4080 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4085 struct timeval wakeup
;
4087 EMACS_GET_TIME (wakeup
);
4089 /* Compute time to wait until, propagating carry from usecs. */
4090 wakeup
.tv_usec
+= 150000;
4091 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4092 wakeup
.tv_usec
%= 1000000;
4094 /* Keep waiting until past the time wakeup or any input gets
4096 while (! detect_input_pending ())
4098 struct timeval current
;
4099 struct timeval timeout
;
4101 EMACS_GET_TIME (current
);
4103 /* Break if result would be negative. */
4104 if (timeval_subtract (¤t
, wakeup
, current
))
4107 /* How long `select' should wait. */
4109 timeout
.tv_usec
= 10000;
4111 /* Try to wait that long--but we might wake up sooner. */
4112 select (0, NULL
, NULL
, NULL
, &timeout
);
4116 /* If window is tall, flash top and bottom line. */
4117 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4119 mac_invert_rectangle (f
, flash_left
,
4120 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4121 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4122 width
, flash_height
);
4123 mac_invert_rectangle (f
, flash_left
,
4124 (height
- flash_height
4125 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4126 width
, flash_height
);
4129 /* If it is short, flash it all. */
4130 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4131 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4138 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4141 /* Make audible bell. */
4146 struct frame
*f
= SELECTED_FRAME ();
4148 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4156 XFlush (FRAME_MAC_DISPLAY (f
));
4162 /* Specify how many text lines, from the top of the window,
4163 should be affected by insert-lines and delete-lines operations.
4164 This, and those operations, are used only within an update
4165 that is bounded by calls to x_update_begin and x_update_end. */
4168 XTset_terminal_window (n
)
4171 /* This function intentionally left blank. */
4176 /***********************************************************************
4178 ***********************************************************************/
4180 /* Perform an insert-lines or delete-lines operation, inserting N
4181 lines or deleting -N lines at vertical position VPOS. */
4184 x_ins_del_lines (vpos
, n
)
4191 /* Scroll part of the display as described by RUN. */
4194 x_scroll_run (w
, run
)
4198 struct frame
*f
= XFRAME (w
->frame
);
4199 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4201 /* Get frame-relative bounding box of the text display area of W,
4202 without mode lines. Include in this box the left and right
4204 window_box (w
, -1, &x
, &y
, &width
, &height
);
4206 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4207 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4208 bottom_y
= y
+ height
;
4212 /* Scrolling up. Make sure we don't copy part of the mode
4213 line at the bottom. */
4214 if (from_y
+ run
->height
> bottom_y
)
4215 height
= bottom_y
- from_y
;
4217 height
= run
->height
;
4221 /* Scolling down. Make sure we don't copy over the mode line.
4223 if (to_y
+ run
->height
> bottom_y
)
4224 height
= bottom_y
- to_y
;
4226 height
= run
->height
;
4231 /* Cursor off. Will be switched on again in x_update_window_end. */
4235 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4245 /***********************************************************************
4247 ***********************************************************************/
4255 ControlRef root_control
;
4258 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4260 ActivateControl (root_control
);
4262 x_update_cursor (f
, 1);
4266 frame_unhighlight (f
)
4270 ControlRef root_control
;
4273 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4275 DeactivateControl (root_control
);
4277 x_update_cursor (f
, 1);
4280 /* The focus has changed. Update the frames as necessary to reflect
4281 the new situation. Note that we can't change the selected frame
4282 here, because the Lisp code we are interrupting might become confused.
4283 Each event gets marked with the frame in which it occurred, so the
4284 Lisp code can tell when the switch took place by examining the events. */
4287 x_new_focus_frame (dpyinfo
, frame
)
4288 struct x_display_info
*dpyinfo
;
4289 struct frame
*frame
;
4291 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4293 if (frame
!= dpyinfo
->x_focus_frame
)
4295 /* Set this before calling other routines, so that they see
4296 the correct value of x_focus_frame. */
4297 dpyinfo
->x_focus_frame
= frame
;
4299 if (old_focus
&& old_focus
->auto_lower
)
4300 x_lower_frame (old_focus
);
4303 selected_frame
= frame
;
4304 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4306 Fselect_window (selected_frame
->selected_window
, Qnil
);
4307 choose_minibuf_frame ();
4310 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4311 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4313 pending_autoraise_frame
= 0;
4315 #if USE_MAC_FONT_PANEL
4317 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4321 x_frame_rehighlight (dpyinfo
);
4324 /* Handle FocusIn and FocusOut state changes for FRAME.
4325 If FRAME has focus and there exists more than one frame, puts
4326 a FOCUS_IN_EVENT into *BUFP. */
4329 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4331 struct mac_display_info
*dpyinfo
;
4332 struct frame
*frame
;
4333 struct input_event
*bufp
;
4335 if (type
== activeFlag
)
4337 if (dpyinfo
->x_focus_event_frame
!= frame
)
4339 x_new_focus_frame (dpyinfo
, frame
);
4340 dpyinfo
->x_focus_event_frame
= frame
;
4342 /* Don't stop displaying the initial startup message
4343 for a switch-frame event we don't need. */
4344 if (GC_NILP (Vterminal_frame
)
4345 && GC_CONSP (Vframe_list
)
4346 && !GC_NILP (XCDR (Vframe_list
)))
4348 bufp
->kind
= FOCUS_IN_EVENT
;
4349 XSETFRAME (bufp
->frame_or_window
, frame
);
4355 if (dpyinfo
->x_focus_event_frame
== frame
)
4357 dpyinfo
->x_focus_event_frame
= 0;
4358 x_new_focus_frame (dpyinfo
, 0);
4363 /* The focus may have changed. Figure out if it is a real focus change,
4364 by checking both FocusIn/Out and Enter/LeaveNotify events.
4366 Returns FOCUS_IN_EVENT event in *BUFP. */
4369 x_detect_focus_change (dpyinfo
, event
, bufp
)
4370 struct mac_display_info
*dpyinfo
;
4371 const EventRecord
*event
;
4372 struct input_event
*bufp
;
4374 struct frame
*frame
;
4376 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4380 /* On Mac, this is only called from focus events, so no switch needed. */
4381 mac_focus_changed ((event
->modifiers
& activeFlag
),
4382 dpyinfo
, frame
, bufp
);
4386 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4389 x_mouse_leave (dpyinfo
)
4390 struct x_display_info
*dpyinfo
;
4392 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4395 /* The focus has changed, or we have redirected a frame's focus to
4396 another frame (this happens when a frame uses a surrogate
4397 mini-buffer frame). Shift the highlight as appropriate.
4399 The FRAME argument doesn't necessarily have anything to do with which
4400 frame is being highlighted or un-highlighted; we only use it to find
4401 the appropriate X display info. */
4404 XTframe_rehighlight (frame
)
4405 struct frame
*frame
;
4407 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4411 x_frame_rehighlight (dpyinfo
)
4412 struct x_display_info
*dpyinfo
;
4414 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4416 if (dpyinfo
->x_focus_frame
)
4418 dpyinfo
->x_highlight_frame
4419 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4420 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4421 : dpyinfo
->x_focus_frame
);
4422 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4424 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4425 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4429 dpyinfo
->x_highlight_frame
= 0;
4431 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4434 frame_unhighlight (old_highlight
);
4435 if (dpyinfo
->x_highlight_frame
)
4436 frame_highlight (dpyinfo
->x_highlight_frame
);
4442 /* Convert a keysym to its name. */
4445 x_get_keysym_name (keysym
)
4452 value
= XKeysymToString (keysym
);
4463 /* Function to report a mouse movement to the mainstream Emacs code.
4464 The input handler calls this.
4466 We have received a mouse movement event, which is given in *event.
4467 If the mouse is over a different glyph than it was last time, tell
4468 the mainstream emacs code by setting mouse_moved. If not, ask for
4469 another motion event, so we can check again the next time it moves. */
4471 static Point last_mouse_motion_position
;
4472 static Lisp_Object last_mouse_motion_frame
;
4475 note_mouse_movement (frame
, pos
)
4479 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4480 #if TARGET_API_MAC_CARBON
4484 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4485 last_mouse_motion_position
= *pos
;
4486 XSETFRAME (last_mouse_motion_frame
, frame
);
4488 if (frame
== dpyinfo
->mouse_face_mouse_frame
4489 #if TARGET_API_MAC_CARBON
4490 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4492 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4496 /* This case corresponds to LeaveNotify in X11. If we move
4497 outside the frame, then we're certainly no longer on any text
4499 clear_mouse_face (dpyinfo
);
4500 dpyinfo
->mouse_face_mouse_frame
= 0;
4501 if (!dpyinfo
->grabbed
)
4502 rif
->define_frame_cursor (frame
,
4503 frame
->output_data
.mac
->nontext_cursor
);
4506 /* Has the mouse moved off the glyph it was on at the last sighting? */
4507 if (frame
!= last_mouse_glyph_frame
4508 || !PtInRect (*pos
, &last_mouse_glyph
))
4510 frame
->mouse_moved
= 1;
4511 last_mouse_scroll_bar
= Qnil
;
4512 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4513 /* Remember which glyph we're now on. */
4514 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4515 last_mouse_glyph_frame
= frame
;
4523 /************************************************************************
4525 ************************************************************************/
4527 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4530 redo_mouse_highlight ()
4532 if (!NILP (last_mouse_motion_frame
)
4533 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4534 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4535 last_mouse_motion_position
.h
,
4536 last_mouse_motion_position
.v
);
4540 static struct frame
*
4541 mac_focus_frame (dpyinfo
)
4542 struct mac_display_info
*dpyinfo
;
4544 if (dpyinfo
->x_focus_frame
)
4545 return dpyinfo
->x_focus_frame
;
4547 /* Mac version may get events, such as a menu bar click, even when
4548 all the frames are invisible. In this case, we regard the
4549 event came to the selected frame. */
4550 return SELECTED_FRAME ();
4554 /* Return the current position of the mouse.
4555 *FP should be a frame which indicates which display to ask about.
4557 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4558 and *PART to the frame, window, and scroll bar part that the mouse
4559 is over. Set *X and *Y to the portion and whole of the mouse's
4560 position on the scroll bar.
4562 If the mouse movement started elsewhere, set *FP to the frame the
4563 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4566 Set *TIME to the server time-stamp for the time at which the mouse
4567 was at this position.
4569 Don't store anything if we don't have a valid set of values to report.
4571 This clears the mouse_moved flag, so we can wait for the next mouse
4575 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4578 Lisp_Object
*bar_window
;
4579 enum scroll_bar_part
*part
;
4581 unsigned long *time
;
4587 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4588 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4591 Lisp_Object frame
, tail
;
4593 /* Clear the mouse-moved flag for every frame on this display. */
4594 FOR_EACH_FRAME (tail
, frame
)
4595 XFRAME (frame
)->mouse_moved
= 0;
4597 last_mouse_scroll_bar
= Qnil
;
4599 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4600 && FRAME_LIVE_P (last_mouse_frame
))
4601 f1
= last_mouse_frame
;
4603 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4607 /* Ok, we found a frame. Store all the values.
4608 last_mouse_glyph is a rectangle used to reduce the
4609 generation of mouse events. To not miss any motion
4610 events, we must divide the frame into rectangles of the
4611 size of the smallest character that could be displayed
4612 on it, i.e. into the same rectangles that matrices on
4613 the frame are divided into. */
4616 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4617 GetMouse (&mouse_pos
);
4618 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4620 last_mouse_glyph_frame
= f1
;
4625 XSETINT (*x
, mouse_pos
.h
);
4626 XSETINT (*y
, mouse_pos
.v
);
4627 *time
= last_mouse_movement_time
;
4635 /************************************************************************
4637 ************************************************************************/
4639 #ifdef USE_TOOLKIT_SCROLL_BARS
4641 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4642 static OSStatus install_scroll_bar_timer
P_ ((void));
4643 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4644 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4645 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4646 struct input_event
*));
4647 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4649 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4650 ControlPartCode
, Point
,
4651 struct input_event
*));
4652 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4653 struct input_event
*));
4654 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4655 Point
, struct input_event
*));
4656 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4659 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4661 static int last_scroll_bar_part
;
4663 static EventLoopTimerRef scroll_bar_timer
;
4665 static int scroll_bar_timer_event_posted_p
;
4667 #define SCROLL_BAR_FIRST_DELAY 0.5
4668 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4671 scroll_bar_timer_callback (timer
, data
)
4672 EventLoopTimerRef timer
;
4677 err
= mac_post_mouse_moved_event ();
4679 scroll_bar_timer_event_posted_p
= 1;
4683 install_scroll_bar_timer ()
4685 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4687 if (scroll_bar_timer_callbackUPP
== NULL
)
4688 scroll_bar_timer_callbackUPP
=
4689 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4691 if (scroll_bar_timer
== NULL
)
4692 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4693 kEventDurationForever as delays. */
4695 InstallEventLoopTimer (GetCurrentEventLoop (),
4696 kEventDurationForever
, kEventDurationForever
,
4697 scroll_bar_timer_callbackUPP
, NULL
,
4702 set_scroll_bar_timer (delay
)
4703 EventTimerInterval delay
;
4705 if (scroll_bar_timer
== NULL
)
4706 install_scroll_bar_timer ();
4708 scroll_bar_timer_event_posted_p
= 0;
4710 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4714 control_part_code_to_scroll_bar_part (part_code
)
4715 ControlPartCode part_code
;
4719 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4720 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4721 case kControlPageUpPart
: return scroll_bar_above_handle
;
4722 case kControlPageDownPart
: return scroll_bar_below_handle
;
4723 case kControlIndicatorPart
: return scroll_bar_handle
;
4730 construct_scroll_bar_click (bar
, part
, bufp
)
4731 struct scroll_bar
*bar
;
4733 struct input_event
*bufp
;
4735 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4736 bufp
->frame_or_window
= bar
->window
;
4740 XSETINT (bufp
->x
, 0);
4741 XSETINT (bufp
->y
, 0);
4742 bufp
->modifiers
= 0;
4746 get_control_part_bounds (ch
, part_code
, rect
)
4748 ControlPartCode part_code
;
4751 RgnHandle region
= NewRgn ();
4754 err
= GetControlRegion (ch
, part_code
, region
);
4756 GetRegionBounds (region
, rect
);
4757 DisposeRgn (region
);
4763 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4764 struct scroll_bar
*bar
;
4765 ControlPartCode part_code
;
4767 struct input_event
*bufp
;
4769 int part
= control_part_code_to_scroll_bar_part (part_code
);
4774 if (part
!= scroll_bar_handle
)
4776 construct_scroll_bar_click (bar
, part
, bufp
);
4777 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4778 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4779 bar
->dragging
= Qnil
;
4785 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4786 kControlIndicatorPart
, &r
);
4787 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4790 last_scroll_bar_part
= part
;
4791 tracked_scroll_bar
= bar
;
4795 x_scroll_bar_handle_release (bar
, bufp
)
4796 struct scroll_bar
*bar
;
4797 struct input_event
*bufp
;
4799 if (last_scroll_bar_part
!= scroll_bar_handle
4800 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4801 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4803 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4804 set_scroll_bar_timer (kEventDurationForever
);
4806 last_scroll_bar_part
= -1;
4807 bar
->dragging
= Qnil
;
4808 tracked_scroll_bar
= NULL
;
4812 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4814 struct scroll_bar
*bar
;
4816 struct input_event
*bufp
;
4818 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4820 if (last_scroll_bar_part
== scroll_bar_handle
)
4825 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4826 kControlIndicatorPart
, &r
);
4828 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4829 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4831 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4832 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4836 if (top
> top_range
)
4839 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4840 XSETINT (bufp
->x
, top
);
4841 XSETINT (bufp
->y
, top_range
);
4845 ControlPartCode part_code
;
4846 int unhilite_p
= 0, part
;
4848 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4852 part
= control_part_code_to_scroll_bar_part (part_code
);
4854 switch (last_scroll_bar_part
)
4856 case scroll_bar_above_handle
:
4857 case scroll_bar_below_handle
:
4858 if (part
!= scroll_bar_above_handle
4859 && part
!= scroll_bar_below_handle
)
4863 case scroll_bar_up_arrow
:
4864 case scroll_bar_down_arrow
:
4865 if (part
!= scroll_bar_up_arrow
4866 && part
!= scroll_bar_down_arrow
)
4873 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4874 else if (part
!= last_scroll_bar_part
4875 || scroll_bar_timer_event_posted_p
)
4877 construct_scroll_bar_click (bar
, part
, bufp
);
4878 last_scroll_bar_part
= part
;
4879 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4880 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4885 /* Set the thumb size and position of scroll bar BAR. We are currently
4886 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4889 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4890 struct scroll_bar
*bar
;
4891 int portion
, position
, whole
;
4893 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4894 int value
, viewsize
, maximum
;
4896 if (XINT (bar
->track_height
) == 0)
4899 if (whole
<= portion
)
4900 value
= 0, viewsize
= 1, maximum
= 0;
4905 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4906 scale
= (float) maximum
/ (whole
- portion
);
4907 value
= position
* scale
+ 0.5f
;
4908 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
4913 if (GetControlViewSize (ch
) != viewsize
4914 || GetControl32BitValue (ch
) != value
4915 || GetControl32BitMaximum (ch
) != maximum
)
4917 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4918 SetControlVisibility (ch
, false, false);
4920 SetControl32BitMaximum (ch
, maximum
);
4921 SetControl32BitValue (ch
, value
);
4922 SetControlViewSize (ch
, viewsize
);
4924 SetControlVisibility (ch
, true, true);
4930 #endif /* USE_TOOLKIT_SCROLL_BARS */
4934 /************************************************************************
4935 Scroll bars, general
4936 ************************************************************************/
4938 /* Create a scroll bar and return the scroll bar vector for it. W is
4939 the Emacs window on which to create the scroll bar. TOP, LEFT,
4940 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4943 static struct scroll_bar
*
4944 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4946 int top
, left
, width
, height
, disp_top
, disp_height
;
4948 struct frame
*f
= XFRAME (w
->frame
);
4949 struct scroll_bar
*bar
4950 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4958 r
.right
= left
+ width
;
4959 r
.bottom
= disp_top
+ disp_height
;
4962 mac_prepare_for_quickdraw (f
);
4964 #if TARGET_API_MAC_CARBON
4965 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4966 #ifdef USE_TOOLKIT_SCROLL_BARS
4969 width
< disp_height
,
4971 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4973 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4974 0, 0, 0, scrollBarProc
, (long) bar
);
4976 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4978 XSETWINDOW (bar
->window
, w
);
4979 XSETINT (bar
->top
, top
);
4980 XSETINT (bar
->left
, left
);
4981 XSETINT (bar
->width
, width
);
4982 XSETINT (bar
->height
, height
);
4983 XSETINT (bar
->start
, 0);
4984 XSETINT (bar
->end
, 0);
4985 bar
->dragging
= Qnil
;
4986 #ifdef USE_TOOLKIT_SCROLL_BARS
4987 bar
->track_top
= Qnil
;
4988 bar
->track_height
= Qnil
;
4989 bar
->min_handle
= Qnil
;
4992 /* Add bar to its frame's list of scroll bars. */
4993 bar
->next
= FRAME_SCROLL_BARS (f
);
4995 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4996 if (!NILP (bar
->next
))
4997 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5004 /* Draw BAR's handle in the proper position.
5006 If the handle is already drawn from START to END, don't bother
5007 redrawing it, unless REBUILD is non-zero; in that case, always
5008 redraw it. (REBUILD is handy for drawing the handle after expose
5011 Normally, we want to constrain the start and end of the handle to
5012 fit inside its rectangle, but if the user is dragging the scroll
5013 bar handle, we want to let them drag it down all the way, so that
5014 the bar's top is as far down as it goes; otherwise, there's no way
5015 to move to the very end of the buffer. */
5017 #ifndef USE_TOOLKIT_SCROLL_BARS
5020 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5021 struct scroll_bar
*bar
;
5025 int dragging
= ! NILP (bar
->dragging
);
5026 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5027 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5028 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5029 int length
= end
- start
;
5031 /* If the display is already accurate, do nothing. */
5033 && start
== XINT (bar
->start
)
5034 && end
== XINT (bar
->end
))
5039 /* Make sure the values are reasonable, and try to preserve the
5040 distance between start and end. */
5043 else if (start
> top_range
)
5045 end
= start
+ length
;
5049 else if (end
> top_range
&& ! dragging
)
5052 /* Store the adjusted setting in the scroll bar. */
5053 XSETINT (bar
->start
, start
);
5054 XSETINT (bar
->end
, end
);
5056 /* Clip the end position, just for display. */
5057 if (end
> top_range
)
5060 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5061 top positions, to make sure the handle is always at least that
5062 many pixels tall. */
5063 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5065 SetControlMinimum (ch
, 0);
5066 /* Don't inadvertently activate deactivated scroll bars */
5067 if (GetControlMaximum (ch
) != -1)
5068 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5070 SetControlValue (ch
, start
);
5071 #if TARGET_API_MAC_CARBON
5072 SetControlViewSize (ch
, end
- start
);
5078 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5080 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5084 x_scroll_bar_remove (bar
)
5085 struct scroll_bar
*bar
;
5087 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5092 mac_prepare_for_quickdraw (f
);
5094 /* Destroy the Mac scroll bar control */
5095 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
5097 /* Disassociate this scroll bar from its window. */
5098 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5104 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5105 that we are displaying PORTION characters out of a total of WHOLE
5106 characters, starting at POSITION. If WINDOW has no scroll bar,
5110 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5112 int portion
, whole
, position
;
5114 struct frame
*f
= XFRAME (w
->frame
);
5115 struct scroll_bar
*bar
;
5116 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5117 int window_y
, window_height
;
5119 /* Get window dimensions. */
5120 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5122 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5123 height
= window_height
;
5125 /* Compute the left edge of the scroll bar area. */
5126 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5128 /* Compute the width of the scroll bar which might be less than
5129 the width of the area reserved for the scroll bar. */
5130 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5131 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5135 /* Compute the left edge of the scroll bar. */
5136 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5139 sb_left
= left
+ width
- sb_width
;
5141 /* Adjustments according to Inside Macintosh to make it look nice */
5143 disp_height
= height
;
5150 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5156 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5160 /* Does the scroll bar exist yet? */
5161 if (NILP (w
->vertical_scroll_bar
))
5164 mac_clear_area (f
, left
, top
, width
, height
);
5166 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5168 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5172 /* It may just need to be moved and resized. */
5175 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5176 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5180 /* If already correctly positioned, do nothing. */
5181 if (!(XINT (bar
->left
) == sb_left
5182 && XINT (bar
->top
) == top
5183 && XINT (bar
->width
) == sb_width
5184 && XINT (bar
->height
) == height
))
5186 /* Since toolkit scroll bars are smaller than the space reserved
5187 for them on the frame, we have to clear "under" them. */
5188 mac_clear_area (f
, left
, top
, width
, height
);
5191 mac_prepare_for_quickdraw (f
);
5194 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5195 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5197 #ifndef USE_TOOLKIT_SCROLL_BARS
5198 if (sb_width
< disp_height
)
5202 /* Remember new settings. */
5203 XSETINT (bar
->left
, sb_left
);
5204 XSETINT (bar
->top
, top
);
5205 XSETINT (bar
->width
, sb_width
);
5206 XSETINT (bar
->height
, height
);
5207 #ifdef USE_TOOLKIT_SCROLL_BARS
5208 bar
->track_top
= Qnil
;
5209 bar
->track_height
= Qnil
;
5210 bar
->min_handle
= Qnil
;
5217 #ifdef USE_TOOLKIT_SCROLL_BARS
5218 if (NILP (bar
->track_top
))
5220 if (sb_width
>= disp_height
5222 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5226 XSETINT (bar
->track_top
, 0);
5227 XSETINT (bar
->track_height
, 0);
5228 XSETINT (bar
->min_handle
, 0);
5232 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5237 SetControl32BitMinimum (ch
, 0);
5238 SetControl32BitMaximum (ch
, 1 << 30);
5239 SetControlViewSize (ch
, 1);
5241 /* Move the scroll bar thumb to the top. */
5242 SetControl32BitValue (ch
, 0);
5243 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5245 /* Move the scroll bar thumb to the bottom. */
5246 SetControl32BitValue (ch
, 1 << 30);
5247 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5249 UnionRect (&r0
, &r1
, &r0
);
5250 XSETINT (bar
->track_top
, r0
.top
);
5251 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5252 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5254 /* Don't show the scroll bar if its height is not enough to
5255 display the scroll bar thumb. */
5256 if (r0
.bottom
- r0
.top
> 0)
5263 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5264 #else /* not USE_TOOLKIT_SCROLL_BARS */
5265 /* Set the scroll bar's current state, unless we're currently being
5267 if (NILP (bar
->dragging
))
5269 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5272 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5275 int start
= ((double) position
* top_range
) / whole
;
5276 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5277 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5280 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5284 /* The following three hooks are used when we're doing a thorough
5285 redisplay of the frame. We don't explicitly know which scroll bars
5286 are going to be deleted, because keeping track of when windows go
5287 away is a real pain - "Can you say set-window-configuration, boys
5288 and girls?" Instead, we just assert at the beginning of redisplay
5289 that *all* scroll bars are to be removed, and then save a scroll bar
5290 from the fiery pit when we actually redisplay its window. */
5292 /* Arrange for all scroll bars on FRAME to be removed at the next call
5293 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5294 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5297 XTcondemn_scroll_bars (frame
)
5300 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5301 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5304 bar
= FRAME_SCROLL_BARS (frame
);
5305 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5306 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5307 XSCROLL_BAR (bar
)->prev
= Qnil
;
5308 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5309 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5310 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5315 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5316 Note that WINDOW isn't necessarily condemned at all. */
5319 XTredeem_scroll_bar (window
)
5320 struct window
*window
;
5322 struct scroll_bar
*bar
;
5325 /* We can't redeem this window's scroll bar if it doesn't have one. */
5326 if (NILP (window
->vertical_scroll_bar
))
5329 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5331 /* Unlink it from the condemned list. */
5332 f
= XFRAME (WINDOW_FRAME (window
));
5333 if (NILP (bar
->prev
))
5335 /* If the prev pointer is nil, it must be the first in one of
5337 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5338 /* It's not condemned. Everything's fine. */
5340 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5341 window
->vertical_scroll_bar
))
5342 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5344 /* If its prev pointer is nil, it must be at the front of
5345 one or the other! */
5349 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5351 if (! NILP (bar
->next
))
5352 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5354 bar
->next
= FRAME_SCROLL_BARS (f
);
5356 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5357 if (! NILP (bar
->next
))
5358 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5361 /* Remove all scroll bars on FRAME that haven't been saved since the
5362 last call to `*condemn_scroll_bars_hook'. */
5365 XTjudge_scroll_bars (f
)
5368 Lisp_Object bar
, next
;
5370 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5372 /* Clear out the condemned list now so we won't try to process any
5373 more events on the hapless scroll bars. */
5374 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5376 for (; ! NILP (bar
); bar
= next
)
5378 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5380 x_scroll_bar_remove (b
);
5383 b
->next
= b
->prev
= Qnil
;
5386 /* Now there should be no references to the condemned scroll bars,
5387 and they should get garbage-collected. */
5391 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5392 is set to something other than NO_EVENT, it is enqueued.
5394 This may be called from a signal handler, so we have to ignore GC
5398 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5399 struct scroll_bar
*bar
;
5400 ControlPartCode part_code
;
5401 const EventRecord
*er
;
5402 struct input_event
*bufp
;
5404 int win_y
, top_range
;
5406 if (! GC_WINDOWP (bar
->window
))
5409 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5410 bufp
->frame_or_window
= bar
->window
;
5413 bar
->dragging
= Qnil
;
5417 case kControlUpButtonPart
:
5418 bufp
->part
= scroll_bar_up_arrow
;
5420 case kControlDownButtonPart
:
5421 bufp
->part
= scroll_bar_down_arrow
;
5423 case kControlPageUpPart
:
5424 bufp
->part
= scroll_bar_above_handle
;
5426 case kControlPageDownPart
:
5427 bufp
->part
= scroll_bar_below_handle
;
5429 #if TARGET_API_MAC_CARBON
5432 case kControlIndicatorPart
:
5434 if (er
->what
== mouseDown
)
5435 bar
->dragging
= make_number (0);
5436 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5437 bufp
->part
= scroll_bar_handle
;
5441 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5442 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5444 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5448 if (! NILP (bar
->dragging
))
5449 win_y
-= XINT (bar
->dragging
);
5453 if (win_y
> top_range
)
5456 XSETINT (bufp
->x
, win_y
);
5457 XSETINT (bufp
->y
, top_range
);
5460 #ifndef USE_TOOLKIT_SCROLL_BARS
5462 /* Handle some mouse motion while someone is dragging the scroll bar.
5464 This may be called from a signal handler, so we have to ignore GC
5468 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5469 struct scroll_bar
*bar
;
5473 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5475 last_mouse_movement_time
= t
;
5478 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5480 /* If we're dragging the bar, display it. */
5481 if (! GC_NILP (bar
->dragging
))
5483 /* Where should the handle be now? */
5484 int new_start
= y_pos
- 24;
5486 if (new_start
!= XINT (bar
->start
))
5488 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5490 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5495 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5497 /* Return information to the user about the current position of the mouse
5498 on the scroll bar. */
5501 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5503 Lisp_Object
*bar_window
;
5504 enum scroll_bar_part
*part
;
5506 unsigned long *time
;
5508 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5509 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5510 #if TARGET_API_MAC_CARBON
5511 WindowPtr wp
= GetControlOwner (ch
);
5513 WindowPtr wp
= (*ch
)->contrlOwner
;
5516 struct frame
*f
= mac_window_to_frame (wp
);
5517 int win_y
, top_range
;
5519 SetPortWindowPort (wp
);
5521 GetMouse (&mouse_pos
);
5523 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5524 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5526 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5530 if (! NILP (bar
->dragging
))
5531 win_y
-= XINT (bar
->dragging
);
5535 if (win_y
> top_range
)
5539 *bar_window
= bar
->window
;
5541 if (! NILP (bar
->dragging
))
5542 *part
= scroll_bar_handle
;
5543 else if (win_y
< XINT (bar
->start
))
5544 *part
= scroll_bar_above_handle
;
5545 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5546 *part
= scroll_bar_handle
;
5548 *part
= scroll_bar_below_handle
;
5550 XSETINT (*x
, win_y
);
5551 XSETINT (*y
, top_range
);
5554 last_mouse_scroll_bar
= Qnil
;
5556 *time
= last_mouse_movement_time
;
5560 /* The screen has been cleared so we may have changed foreground or
5561 background colors, and the scroll bars may need to be redrawn.
5562 Clear out the scroll bars, and ask for expose events, so we can
5566 x_scroll_bar_clear (f
)
5569 XTcondemn_scroll_bars (f
);
5570 XTjudge_scroll_bars (f
);
5574 /***********************************************************************
5576 ***********************************************************************/
5578 /* Set clipping for output in glyph row ROW. W is the window in which
5579 we operate. GC is the graphics context to set clipping in.
5581 ROW may be a text row or, e.g., a mode line. Text rows must be
5582 clipped to the interior of the window dedicated to text display,
5583 mode lines must be clipped to the whole window. */
5586 x_clip_to_row (w
, row
, area
, gc
)
5588 struct glyph_row
*row
;
5592 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5594 int window_x
, window_y
, window_width
;
5596 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5598 clip_rect
.left
= window_x
;
5599 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5600 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5601 clip_rect
.right
= clip_rect
.left
+ window_width
;
5602 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5604 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5608 /* Draw a hollow box cursor on window W in glyph row ROW. */
5611 x_draw_hollow_cursor (w
, row
)
5613 struct glyph_row
*row
;
5615 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5616 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5617 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5620 struct glyph
*cursor_glyph
;
5623 /* Get the glyph the cursor is on. If we can't tell because
5624 the current matrix is invalid or such, give up. */
5625 cursor_glyph
= get_phys_cursor_glyph (w
);
5626 if (cursor_glyph
== NULL
)
5629 /* Compute frame-relative coordinates for phys cursor. */
5630 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5631 wd
= w
->phys_cursor_width
;
5633 /* The foreground of cursor_gc is typically the same as the normal
5634 background color, which can cause the cursor box to be invisible. */
5635 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5636 if (dpyinfo
->scratch_cursor_gc
)
5637 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5639 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5640 GCForeground
, &xgcv
);
5641 gc
= dpyinfo
->scratch_cursor_gc
;
5643 /* Set clipping, draw the rectangle, and reset clipping again. */
5644 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5645 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5646 mac_reset_clip_rectangles (dpy
, gc
);
5650 /* Draw a bar cursor on window W in glyph row ROW.
5652 Implementation note: One would like to draw a bar cursor with an
5653 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5654 Unfortunately, I didn't find a font yet that has this property set.
5658 x_draw_bar_cursor (w
, row
, width
, kind
)
5660 struct glyph_row
*row
;
5662 enum text_cursor_kinds kind
;
5664 struct frame
*f
= XFRAME (w
->frame
);
5665 struct glyph
*cursor_glyph
;
5667 /* If cursor is out of bounds, don't draw garbage. This can happen
5668 in mini-buffer windows when switching between echo area glyphs
5670 cursor_glyph
= get_phys_cursor_glyph (w
);
5671 if (cursor_glyph
== NULL
)
5674 /* If on an image, draw like a normal cursor. That's usually better
5675 visible than drawing a bar, esp. if the image is large so that
5676 the bar might not be in the window. */
5677 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5679 struct glyph_row
*row
;
5680 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5681 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5685 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5686 Window window
= FRAME_MAC_WINDOW (f
);
5687 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5688 unsigned long mask
= GCForeground
| GCBackground
;
5689 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5692 /* If the glyph's background equals the color we normally draw
5693 the bar cursor in, the bar cursor in its normal color is
5694 invisible. Use the glyph's foreground color instead in this
5695 case, on the assumption that the glyph's colors are chosen so
5696 that the glyph is legible. */
5697 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5698 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5700 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5703 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5706 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5707 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5711 width
= FRAME_CURSOR_WIDTH (f
);
5712 width
= min (cursor_glyph
->pixel_width
, width
);
5714 w
->phys_cursor_width
= width
;
5715 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5717 if (kind
== BAR_CURSOR
)
5718 mac_fill_rectangle (f
, gc
,
5719 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5720 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5721 width
, row
->height
);
5723 mac_fill_rectangle (f
, gc
,
5724 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5725 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5726 row
->height
- width
),
5727 cursor_glyph
->pixel_width
,
5730 mac_reset_clip_rectangles (dpy
, gc
);
5735 /* RIF: Define cursor CURSOR on frame F. */
5738 mac_define_frame_cursor (f
, cursor
)
5742 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5744 if (dpyinfo
->x_focus_frame
== f
)
5745 SetThemeCursor (cursor
);
5749 /* RIF: Clear area on frame F. */
5752 mac_clear_frame_area (f
, x
, y
, width
, height
)
5754 int x
, y
, width
, height
;
5756 mac_clear_area (f
, x
, y
, width
, height
);
5760 /* RIF: Draw cursor on window W. */
5763 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5765 struct glyph_row
*glyph_row
;
5767 int cursor_type
, cursor_width
;
5772 w
->phys_cursor_type
= cursor_type
;
5773 w
->phys_cursor_on_p
= 1;
5775 if (glyph_row
->exact_window_width_line_p
5776 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5778 glyph_row
->cursor_in_fringe_p
= 1;
5779 draw_fringe_bitmap (w
, glyph_row
, 0);
5782 switch (cursor_type
)
5784 case HOLLOW_BOX_CURSOR
:
5785 x_draw_hollow_cursor (w
, glyph_row
);
5788 case FILLED_BOX_CURSOR
:
5789 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5793 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5797 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5801 w
->phys_cursor_width
= 0;
5813 #if 0 /* MAC_TODO: no icon support yet. */
5815 x_bitmap_icon (f
, icon
)
5821 if (FRAME_W32_WINDOW (f
) == 0)
5825 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5826 else if (STRINGP (icon
))
5827 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5828 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5829 else if (SYMBOLP (icon
))
5833 if (EQ (icon
, intern ("application")))
5834 name
= (LPCTSTR
) IDI_APPLICATION
;
5835 else if (EQ (icon
, intern ("hand")))
5836 name
= (LPCTSTR
) IDI_HAND
;
5837 else if (EQ (icon
, intern ("question")))
5838 name
= (LPCTSTR
) IDI_QUESTION
;
5839 else if (EQ (icon
, intern ("exclamation")))
5840 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5841 else if (EQ (icon
, intern ("asterisk")))
5842 name
= (LPCTSTR
) IDI_ASTERISK
;
5843 else if (EQ (icon
, intern ("winlogo")))
5844 name
= (LPCTSTR
) IDI_WINLOGO
;
5848 hicon
= LoadIcon (NULL
, name
);
5856 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5861 #endif /* MAC_TODO */
5863 /************************************************************************
5865 ************************************************************************/
5867 /* Display Error Handling functions not used on W32. Listing them here
5868 helps diff stay in step when comparing w32term.c with xterm.c.
5870 x_error_catcher (display, error)
5871 x_catch_errors (dpy)
5872 x_catch_errors_unwind (old_val)
5873 x_check_errors (dpy, format)
5874 x_had_errors_p (dpy)
5875 x_clear_errors (dpy)
5876 x_uncatch_errors (dpy, count)
5878 x_connection_signal (signalnum)
5879 x_connection_closed (dpy, error_message)
5880 x_error_quitter (display, error)
5881 x_error_handler (display, error)
5882 x_io_error_quitter (display)
5887 /* Changing the font of the frame. */
5889 /* Give frame F the font named FONTNAME as its default font, and
5890 return the full name of that font. FONTNAME may be a wildcard
5891 pattern; in that case, we choose some font that fits the pattern.
5892 The return value shows which font we chose. */
5895 x_new_font (f
, fontname
)
5897 register char *fontname
;
5899 struct font_info
*fontp
5900 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5905 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5906 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5907 FRAME_FONTSET (f
) = -1;
5909 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5910 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5911 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5913 compute_fringe_widths (f
, 1);
5915 /* Compute the scroll bar width in character columns. */
5916 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5918 int wid
= FRAME_COLUMN_WIDTH (f
);
5919 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5920 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5924 int wid
= FRAME_COLUMN_WIDTH (f
);
5925 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5928 /* Now make the frame display the given font. */
5929 if (FRAME_MAC_WINDOW (f
) != 0)
5931 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5933 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5935 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5938 /* Don't change the size of a tip frame; there's no point in
5939 doing it because it's done in Fx_show_tip, and it leads to
5940 problems because the tip frame has no widget. */
5941 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5942 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5945 return build_string (fontp
->full_name
);
5948 /* Give frame F the fontset named FONTSETNAME as its default font, and
5949 return the full name of that fontset. FONTSETNAME may be a wildcard
5950 pattern; in that case, we choose some fontset that fits the pattern.
5951 The return value shows which fontset we chose. */
5954 x_new_fontset (f
, fontsetname
)
5958 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5964 if (FRAME_FONTSET (f
) == fontset
)
5965 /* This fontset is already set in frame F. There's nothing more
5967 return fontset_name (fontset
);
5969 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5971 if (!STRINGP (result
))
5972 /* Can't load ASCII font. */
5975 /* Since x_new_font doesn't update any fontset information, do it now. */
5976 FRAME_FONTSET (f
) = fontset
;
5978 return build_string (fontsetname
);
5982 /***********************************************************************
5983 TODO: W32 Input Methods
5984 ***********************************************************************/
5985 /* Listing missing functions from xterm.c helps diff stay in step.
5987 xim_destroy_callback (xim, client_data, call_data)
5988 xim_open_dpy (dpyinfo, resource_name)
5990 xim_instantiate_callback (display, client_data, call_data)
5991 xim_initialize (dpyinfo, resource_name)
5992 xim_close_dpy (dpyinfo)
5998 mac_get_window_bounds (f
, inner
, outer
)
6000 Rect
*inner
, *outer
;
6002 #if TARGET_API_MAC_CARBON
6003 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6004 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6005 #else /* not TARGET_API_MAC_CARBON */
6006 RgnHandle region
= NewRgn ();
6008 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6009 *inner
= (*region
)->rgnBBox
;
6010 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6011 *outer
= (*region
)->rgnBBox
;
6012 DisposeRgn (region
);
6013 #endif /* not TARGET_API_MAC_CARBON */
6017 mac_handle_origin_change (f
)
6020 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6024 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6026 int pixelwidth
, pixelheight
;
6030 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6031 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6033 if (cols
!= FRAME_COLS (f
)
6034 || rows
!= FRAME_LINES (f
)
6035 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6036 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6038 /* We pass 1 for DELAY since we can't run Lisp code inside of
6040 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6041 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6042 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6043 SET_FRAME_GARBAGED (f
);
6045 /* If cursor was outside the new size, mark it as off. */
6046 mark_window_cursors_off (XWINDOW (f
->root_window
));
6048 /* Clear out any recollection of where the mouse highlighting
6049 was, since it might be in a place that's outside the new
6050 frame size. Actually checking whether it is outside is a
6051 pain in the neck, so don't try--just let the highlighting be
6052 done afresh with new size. */
6053 cancel_mouse_face (f
);
6055 #if TARGET_API_MAC_CARBON
6056 if (f
->output_data
.mac
->hourglass_control
)
6059 mac_prepare_for_quickdraw (f
);
6061 MoveControl (f
->output_data
.mac
->hourglass_control
,
6062 pixelwidth
- HOURGLASS_WIDTH
, 0);
6069 /* Calculate the absolute position in frame F
6070 from its current recorded position values and gravity. */
6073 x_calc_absolute_position (f
)
6076 int width_diff
= 0, height_diff
= 0;
6077 int flags
= f
->size_hint_flags
;
6080 /* We have nothing to do if the current position
6081 is already for the top-left corner. */
6082 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6085 /* Find the offsets of the outside upper-left corner of
6086 the inner window, with respect to the outer window. */
6088 mac_get_window_bounds (f
, &inner
, &outer
);
6091 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6092 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6094 /* Treat negative positions as relative to the leftmost bottommost
6095 position that fits on the screen. */
6096 if (flags
& XNegative
)
6097 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6099 - FRAME_PIXEL_WIDTH (f
)
6102 if (flags
& YNegative
)
6103 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6105 - FRAME_PIXEL_HEIGHT (f
)
6108 /* The left_pos and top_pos
6109 are now relative to the top and left screen edges,
6110 so the flags should correspond. */
6111 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6114 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6115 to really change the position, and 0 when calling from
6116 x_make_frame_visible (in that case, XOFF and YOFF are the current
6117 position values). It is -1 when calling from x_set_frame_parameters,
6118 which means, do adjust for borders but don't change the gravity. */
6121 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6123 register int xoff
, yoff
;
6126 if (change_gravity
> 0)
6130 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6132 f
->size_hint_flags
|= XNegative
;
6134 f
->size_hint_flags
|= YNegative
;
6135 f
->win_gravity
= NorthWestGravity
;
6137 x_calc_absolute_position (f
);
6140 x_wm_set_size_hint (f
, (long) 0, 0);
6142 #if TARGET_API_MAC_CARBON
6143 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6144 /* If the title bar is completely outside the screen, adjust the
6146 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6147 kWindowConstrainMoveRegardlessOfFit
6148 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6149 #if USE_CARBON_EVENTS
6150 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6152 mac_handle_origin_change (f
);
6155 Rect inner
, outer
, screen_rect
, dummy
;
6156 RgnHandle region
= NewRgn ();
6158 mac_get_window_bounds (f
, &inner
, &outer
);
6159 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6160 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6161 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6162 f
->top_pos
+ f
->y_pixels_diff
, false);
6164 /* If the title bar is completely outside the screen, adjust the
6165 position. The variable `outer' holds the title bar rectangle.
6166 The variable `inner' holds slightly smaller one than `outer',
6167 so that the calculation of overlapping may not become too
6169 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6170 outer
= (*region
)->rgnBBox
;
6171 DisposeRgn (region
);
6173 InsetRect (&inner
, 8, 8);
6174 screen_rect
= qd
.screenBits
.bounds
;
6175 screen_rect
.top
+= GetMBarHeight ();
6177 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6179 if (inner
.right
<= screen_rect
.left
)
6180 f
->left_pos
= screen_rect
.left
;
6181 else if (inner
.left
>= screen_rect
.right
)
6182 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6184 if (inner
.bottom
<= screen_rect
.top
)
6185 f
->top_pos
= screen_rect
.top
;
6186 else if (inner
.top
>= screen_rect
.bottom
)
6187 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6189 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6190 f
->top_pos
+ f
->y_pixels_diff
, false);
6198 /* Call this to change the size of frame F's x-window.
6199 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6200 for this size change and subsequent size changes.
6201 Otherwise we leave the window gravity unchanged. */
6204 x_set_window_size (f
, change_gravity
, cols
, rows
)
6209 int pixelwidth
, pixelheight
;
6213 check_frame_size (f
, &rows
, &cols
);
6214 f
->scroll_bar_actual_width
6215 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6217 compute_fringe_widths (f
, 0);
6219 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6220 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6222 f
->win_gravity
= NorthWestGravity
;
6223 x_wm_set_size_hint (f
, (long) 0, 0);
6225 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6227 #if USE_CARBON_EVENTS
6228 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6230 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6232 if (f
->output_data
.mac
->internal_border_width
6233 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6235 mac_clear_window (f
);
6236 f
->output_data
.mac
->internal_border_width
6237 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6240 SET_FRAME_GARBAGED (f
);
6245 /* Mouse warping. */
6247 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6250 x_set_mouse_position (f
, x
, y
)
6256 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6257 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6259 if (pix_x
< 0) pix_x
= 0;
6260 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6262 if (pix_y
< 0) pix_y
= 0;
6263 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6265 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6269 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6278 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
6284 CGWarpMouseCursorPosition (point
);
6287 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6290 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6291 0, 0, 0, 0, pix_x
, pix_y
);
6297 /* focus shifting, raising and lowering. */
6300 x_focus_on_frame (f
)
6303 #if 0 /* This proves to be unpleasant. */
6307 /* I don't think that the ICCCM allows programs to do things like this
6308 without the interaction of the window manager. Whatever you end up
6309 doing with this code, do it to x_unfocus_frame too. */
6310 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6311 RevertToPointerRoot
, CurrentTime
);
6321 /* Raise frame F. */
6327 if (f
->async_visible
)
6330 BringToFront (FRAME_MAC_WINDOW (f
));
6335 /* Lower frame F. */
6341 if (f
->async_visible
)
6344 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6350 XTframe_raise_lower (f
, raise_flag
)
6360 /* Change of visibility. */
6363 mac_handle_visibility_change (f
)
6366 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6367 int visible
= 0, iconified
= 0;
6368 struct input_event buf
;
6370 if (IsWindowVisible (wp
))
6372 if (IsWindowCollapsed (wp
))
6378 if (!f
->async_visible
&& visible
)
6382 /* wait_reading_process_output will notice this and update
6383 the frame's display structures. If we were made
6384 invisible, we should not set garbaged, because that stops
6385 redrawing on Update events. */
6386 SET_FRAME_GARBAGED (f
);
6389 buf
.kind
= DEICONIFY_EVENT
;
6390 XSETFRAME (buf
.frame_or_window
, f
);
6392 kbd_buffer_store_event (&buf
);
6394 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6395 /* Force a redisplay sooner or later to update the
6396 frame titles in case this is the second frame. */
6397 record_asynch_buffer_change ();
6399 else if (f
->async_visible
&& !visible
)
6403 buf
.kind
= ICONIFY_EVENT
;
6404 XSETFRAME (buf
.frame_or_window
, f
);
6406 kbd_buffer_store_event (&buf
);
6409 f
->async_visible
= visible
;
6410 f
->async_iconified
= iconified
;
6413 /* This tries to wait until the frame is really visible.
6414 However, if the window manager asks the user where to position
6415 the frame, this will return before the user finishes doing that.
6416 The frame will not actually be visible at that time,
6417 but it will become visible later when the window manager
6418 finishes with it. */
6421 x_make_frame_visible (f
)
6426 if (! FRAME_VISIBLE_P (f
))
6428 /* We test FRAME_GARBAGED_P here to make sure we don't
6429 call x_set_offset a second time
6430 if we get to x_make_frame_visible a second time
6431 before the window gets really visible. */
6432 if (! FRAME_ICONIFIED_P (f
)
6433 && ! f
->output_data
.mac
->asked_for_visible
)
6435 #if TARGET_API_MAC_CARBON
6436 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6438 struct frame
*sf
= SELECTED_FRAME ();
6439 if (!FRAME_MAC_P (sf
))
6440 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6441 kWindowCenterOnMainScreen
);
6443 RepositionWindow (FRAME_MAC_WINDOW (f
),
6444 FRAME_MAC_WINDOW (sf
),
6445 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6446 kWindowCascadeStartAtParentWindowScreen
6448 kWindowCascadeOnParentWindowScreen
6451 #if USE_CARBON_EVENTS
6452 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6454 mac_handle_origin_change (f
);
6458 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6461 f
->output_data
.mac
->asked_for_visible
= 1;
6463 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6464 ShowWindow (FRAME_MAC_WINDOW (f
));
6467 XFlush (FRAME_MAC_DISPLAY (f
));
6469 /* Synchronize to ensure Emacs knows the frame is visible
6470 before we do anything else. We do this loop with input not blocked
6471 so that incoming events are handled. */
6476 /* This must come after we set COUNT. */
6479 XSETFRAME (frame
, f
);
6481 /* Wait until the frame is visible. Process X events until a
6482 MapNotify event has been seen, or until we think we won't get a
6483 MapNotify at all.. */
6484 for (count
= input_signal_count
+ 10;
6485 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6487 /* Force processing of queued events. */
6490 /* Machines that do polling rather than SIGIO have been
6491 observed to go into a busy-wait here. So we'll fake an
6492 alarm signal to let the handler know that there's something
6493 to be read. We used to raise a real alarm, but it seems
6494 that the handler isn't always enabled here. This is
6496 if (input_polling_used ())
6498 /* It could be confusing if a real alarm arrives while
6499 processing the fake one. Turn it off and let the
6500 handler reset it. */
6501 extern void poll_for_input_1
P_ ((void));
6502 int old_poll_suppress_count
= poll_suppress_count
;
6503 poll_suppress_count
= 1;
6504 poll_for_input_1 ();
6505 poll_suppress_count
= old_poll_suppress_count
;
6508 /* See if a MapNotify event has been processed. */
6509 FRAME_SAMPLE_VISIBILITY (f
);
6514 /* Change from mapped state to withdrawn state. */
6516 /* Make the frame visible (mapped and not iconified). */
6519 x_make_frame_invisible (f
)
6522 /* A deactivate event does not occur when the last visible frame is
6523 made invisible. So if we clear the highlight here, it will not
6524 be rehighlighted when it is made visible. */
6526 /* Don't keep the highlight on an invisible frame. */
6527 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6528 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6533 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6534 that the current position of the window is user-specified, rather than
6535 program-specified, so that when the window is mapped again, it will be
6536 placed at the same location, without forcing the user to position it
6537 by hand again (they have already done that once for this window.) */
6538 x_wm_set_size_hint (f
, (long) 0, 1);
6540 HideWindow (FRAME_MAC_WINDOW (f
));
6544 #if !USE_CARBON_EVENTS
6545 mac_handle_visibility_change (f
);
6549 /* Change window state from mapped to iconified. */
6557 /* A deactivate event does not occur when the last visible frame is
6558 iconified. So if we clear the highlight here, it will not be
6559 rehighlighted when it is deiconified. */
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;
6566 if (f
->async_iconified
)
6571 FRAME_SAMPLE_VISIBILITY (f
);
6573 if (! FRAME_VISIBLE_P (f
))
6574 ShowWindow (FRAME_MAC_WINDOW (f
));
6576 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6581 error ("Can't notify window manager of iconification");
6583 #if !USE_CARBON_EVENTS
6584 mac_handle_visibility_change (f
);
6589 /* Free X resources of frame F. */
6592 x_free_frame_resources (f
)
6595 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6596 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6600 if (wp
!= tip_window
)
6601 remove_window_handler (wp
);
6604 mac_prepare_for_quickdraw (f
);
6607 if (wp
== tip_window
)
6608 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6609 closed' event. So we reset tip_window here. */
6612 free_frame_menubar (f
);
6614 if (FRAME_FACE_CACHE (f
))
6615 free_frame_faces (f
);
6619 if (FRAME_SIZE_HINTS (f
))
6620 xfree (FRAME_SIZE_HINTS (f
));
6622 xfree (f
->output_data
.mac
);
6623 f
->output_data
.mac
= NULL
;
6625 if (f
== dpyinfo
->x_focus_frame
)
6627 dpyinfo
->x_focus_frame
= 0;
6628 #if USE_MAC_FONT_PANEL
6629 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6632 if (f
== dpyinfo
->x_focus_event_frame
)
6633 dpyinfo
->x_focus_event_frame
= 0;
6634 if (f
== dpyinfo
->x_highlight_frame
)
6635 dpyinfo
->x_highlight_frame
= 0;
6637 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6639 dpyinfo
->mouse_face_beg_row
6640 = dpyinfo
->mouse_face_beg_col
= -1;
6641 dpyinfo
->mouse_face_end_row
6642 = dpyinfo
->mouse_face_end_col
= -1;
6643 dpyinfo
->mouse_face_window
= Qnil
;
6644 dpyinfo
->mouse_face_deferred_gc
= 0;
6645 dpyinfo
->mouse_face_mouse_frame
= 0;
6652 /* Destroy the X window of frame F. */
6655 x_destroy_window (f
)
6658 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6660 x_free_frame_resources (f
);
6662 dpyinfo
->reference_count
--;
6666 /* Setting window manager hints. */
6668 /* Set the normal size hints for the window manager, for frame F.
6669 FLAGS is the flags word to use--or 0 meaning preserve the flags
6670 that the window now has.
6671 If USER_POSITION is nonzero, we set the USPosition
6672 flag (this is useful when FLAGS is 0). */
6674 x_wm_set_size_hint (f
, flags
, user_position
)
6679 int base_width
, base_height
, width_inc
, height_inc
;
6680 int min_rows
= 0, min_cols
= 0;
6681 XSizeHints
*size_hints
;
6683 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6684 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6685 width_inc
= FRAME_COLUMN_WIDTH (f
);
6686 height_inc
= FRAME_LINE_HEIGHT (f
);
6688 check_frame_size (f
, &min_rows
, &min_cols
);
6690 size_hints
= FRAME_SIZE_HINTS (f
);
6691 if (size_hints
== NULL
)
6693 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6694 bzero (size_hints
, sizeof (XSizeHints
));
6697 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6698 size_hints
->width_inc
= width_inc
;
6699 size_hints
->height_inc
= height_inc
;
6700 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6701 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6702 size_hints
->base_width
= base_width
;
6703 size_hints
->base_height
= base_height
;
6706 size_hints
->flags
= flags
;
6707 else if (user_position
)
6709 size_hints
->flags
&= ~ PPosition
;
6710 size_hints
->flags
|= USPosition
;
6714 #if 0 /* MAC_TODO: hide application instead of iconify? */
6715 /* Used for IconicState or NormalState */
6718 x_wm_set_window_state (f
, state
)
6722 #ifdef USE_X_TOOLKIT
6725 XtSetArg (al
[0], XtNinitialState
, state
);
6726 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6727 #else /* not USE_X_TOOLKIT */
6728 Window window
= FRAME_X_WINDOW (f
);
6730 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6731 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6733 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6734 #endif /* not USE_X_TOOLKIT */
6738 x_wm_set_icon_pixmap (f
, pixmap_id
)
6744 #ifndef USE_X_TOOLKIT
6745 Window window
= FRAME_X_WINDOW (f
);
6750 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6751 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6755 /* It seems there is no way to turn off use of an icon pixmap.
6756 The following line does it, only if no icon has yet been created,
6757 for some window managers. But with mwm it crashes.
6758 Some people say it should clear the IconPixmapHint bit in this case,
6759 but that doesn't work, and the X consortium said it isn't the
6760 right thing at all. Since there is no way to win,
6761 best to explicitly give up. */
6763 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6769 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6773 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6774 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6777 #else /* not USE_X_TOOLKIT */
6779 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6780 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6782 #endif /* not USE_X_TOOLKIT */
6785 #endif /* MAC_TODO */
6788 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6792 #if 0 /* MAC_TODO: no icons on Mac */
6793 #ifdef USE_X_TOOLKIT
6794 Window window
= XtWindow (f
->output_data
.x
->widget
);
6796 Window window
= FRAME_X_WINDOW (f
);
6799 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6800 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6801 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6803 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6804 #endif /* MAC_TODO */
6808 /***********************************************************************
6810 ***********************************************************************/
6812 /* An XLFD pattern is divided into blocks delimited by '*'. This
6813 structure holds information for each block. */
6814 struct xlfdpat_block
6816 /* Length of the pattern string in this block. Non-zero except for
6817 the first and the last blocks. */
6820 /* Pattern string except the last character in this block. The last
6821 character is replaced with NUL in order to use it as a
6823 unsigned char *pattern
;
6825 /* Last character of the pattern string. Must not be '?'. */
6826 unsigned char last_char
;
6828 /* One of the tables for the Boyer-Moore string search. It
6829 specifies the number of positions to proceed for each character
6830 with which the match fails. */
6833 /* The skip value for the last character in the above `skip' is
6834 assigned to `infinity' in order to simplify a loop condition.
6835 The original value is saved here. */
6841 /* Normalized pattern string. "Normalized" means that capital
6842 letters are lowered, blocks are not empty except the first and
6843 the last ones, and trailing '?'s in a block that is not the last
6844 one are moved to the next one. The last character in each block
6845 is replaced with NUL. */
6848 /* Number of characters except '*'s and trailing '?'s in the
6849 normalized pattern string. */
6852 /* Number of trailing '?'s in the normalized pattern string. */
6853 int trailing_anychars
;
6855 /* Number of blocks and information for each block. The latter is
6856 NULL if the pattern is exact (no '*' or '?' in it). */
6858 struct xlfdpat_block
*blocks
;
6862 xlfdpat_destroy (pat
)
6863 struct xlfdpat
*pat
;
6870 xfree (pat
->blocks
);
6877 static struct xlfdpat
*
6878 xlfdpat_create (pattern
)
6879 const char *pattern
;
6881 struct xlfdpat
*pat
;
6882 int nblocks
, i
, skip
;
6883 unsigned char last_char
, *p
, *q
, *anychar_head
;
6884 const unsigned char *ptr
;
6885 struct xlfdpat_block
*blk
;
6887 pat
= xmalloc (sizeof (struct xlfdpat
));
6888 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6890 /* Normalize the pattern string and store it to `pat->buf'. */
6892 anychar_head
= NULL
;
6895 for (ptr
= pattern
; *ptr
; ptr
++)
6897 unsigned char c
= *ptr
;
6900 if (last_char
== '*')
6901 /* ...a** -> ...a* */
6905 if (last_char
== '?')
6907 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6908 /* ...*??* -> ...*?? */
6911 /* ...a??* -> ...a*?? */
6913 *anychar_head
++ = '*';
6921 if (last_char
!= '?')
6925 /* On Mac OS X 10.3, tolower also converts non-ASCII
6926 characters for some locales. */
6930 *q
++ = last_char
= c
;
6934 pat
->nblocks
= nblocks
;
6935 if (last_char
!= '?')
6936 pat
->trailing_anychars
= 0;
6939 pat
->trailing_anychars
= q
- anychar_head
;
6942 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6944 if (anychar_head
== NULL
&& nblocks
== 1)
6946 /* The pattern is exact. */
6951 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6953 /* Divide the normalized pattern into blocks. */
6955 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6960 blk
->len
= p
- blk
->pattern
;
6964 blk
->len
= q
- blk
->pattern
;
6966 /* Setup a table for the Boyer-Moore string search. */
6967 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6970 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6971 blk
->pattern
[blk
->len
- 1] = '\0';
6973 for (skip
= 1; skip
< blk
->len
; skip
++)
6974 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6977 for (i
= 0; i
< 256; i
++)
6978 blk
->skip
[i
] = skip
;
6980 p
= blk
->pattern
+ (blk
->len
- skip
);
6982 blk
->skip
[*p
++] = skip
;
6984 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6991 xlfdpat_exact_p (pat
)
6992 struct xlfdpat
*pat
;
6994 return pat
->blocks
== NULL
;
6997 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6998 that the pattern in *BLK matches with its prefix. Return NULL
6999 there is no such strings. STRING must be lowered in advance. */
7002 xlfdpat_block_match_1 (blk
, string
, start_max
)
7003 struct xlfdpat_block
*blk
;
7004 const unsigned char *string
;
7007 int start
, infinity
;
7009 const unsigned char *s
;
7011 xassert (blk
->len
> 0);
7012 xassert (start_max
+ blk
->len
<= strlen (string
));
7013 xassert (blk
->last_char
!= '?');
7015 /* See the comments in the function `boyer_moore' (search.c) for the
7016 use of `infinity'. */
7017 infinity
= start_max
+ blk
->len
+ 1;
7018 blk
->skip
[blk
->last_char
] = infinity
;
7023 /* Check the last character of the pattern. */
7024 s
= string
+ blk
->len
- 1;
7027 start
+= blk
->skip
[*(s
+ start
)];
7029 while (start
<= start_max
);
7031 if (start
< infinity
)
7032 /* Couldn't find the last character. */
7035 /* No less than `infinity' means we could find the last
7036 character at `s[start - infinity]'. */
7039 /* Check the remaining characters. We prefer making no-'?'
7040 cases faster because the use of '?' is really rare. */
7045 while (*p
++ == *s
++)
7048 while (*(p
- 1) == '?');
7050 if (*(p
- 1) == '\0')
7052 return string
+ start
;
7055 start
+= blk
->last_char_skip
;
7057 while (start
<= start_max
);
7062 #define xlfdpat_block_match(b, s, m) \
7063 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7064 : xlfdpat_block_match_1 (b, s, m))
7066 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7067 matches with STRING. STRING must be lowered in advance. */
7070 xlfdpat_match (pat
, string
)
7071 struct xlfdpat
*pat
;
7072 const unsigned char *string
;
7074 int str_len
, nblocks
, i
, start_max
;
7075 struct xlfdpat_block
*blk
;
7076 const unsigned char *s
;
7078 xassert (pat
->nblocks
> 0);
7080 if (xlfdpat_exact_p (pat
))
7081 return strcmp (pat
->buf
, string
) == 0;
7083 /* The number of the characters in the string must not be smaller
7084 than that in the pattern. */
7085 str_len
= strlen (string
);
7086 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7089 /* Chop off the trailing '?'s. */
7090 str_len
-= pat
->trailing_anychars
;
7092 /* The last block. When it is non-empty, it must match at the end
7094 nblocks
= pat
->nblocks
;
7095 blk
= pat
->blocks
+ (nblocks
- 1);
7097 /* The last block is also the first one. */
7098 return (str_len
== blk
->len
7099 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7100 else if (blk
->len
!= 0)
7101 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7104 /* The first block. When it is non-empty, it must match at the
7105 beginning of the string. */
7109 s
= xlfdpat_block_match (blk
, string
, 0);
7112 string
= s
+ blk
->len
;
7115 /* The rest of the blocks. */
7116 start_max
= str_len
- pat
->nchars
;
7117 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7119 s
= xlfdpat_block_match (blk
, string
, start_max
);
7122 start_max
-= s
- string
;
7123 string
= s
+ blk
->len
;
7130 /***********************************************************************
7132 ***********************************************************************/
7134 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7137 x_get_font_info (f
, font_idx
)
7141 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7144 /* the global font name table */
7145 static char **font_name_table
= NULL
;
7146 static int font_name_table_size
= 0;
7147 static int font_name_count
= 0;
7149 /* Alist linking font family names to Font Manager font family
7150 references (which can also be used as QuickDraw font IDs). We use
7151 an alist because hash tables are not ready when the terminal frame
7152 for Mac OS Classic is created. */
7153 static Lisp_Object fm_font_family_alist
;
7155 /* Hash table linking font family names to ATSU font IDs. */
7156 static Lisp_Object atsu_font_id_hash
;
7157 /* Alist linking Font Manager style to face attributes. */
7158 static Lisp_Object fm_style_face_attributes_alist
;
7159 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7162 /* Alist linking character set strings to Mac text encoding and Emacs
7164 static Lisp_Object Vmac_charset_info_alist
;
7167 create_text_encoding_info_alist ()
7169 Lisp_Object result
= Qnil
, rest
;
7171 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7173 Lisp_Object charset_info
= XCAR (rest
);
7174 Lisp_Object charset
, coding_system
, text_encoding
;
7175 Lisp_Object existing_info
;
7177 if (!(CONSP (charset_info
)
7178 && (charset
= XCAR (charset_info
),
7180 && CONSP (XCDR (charset_info
))
7181 && (text_encoding
= XCAR (XCDR (charset_info
)),
7182 INTEGERP (text_encoding
))
7183 && CONSP (XCDR (XCDR (charset_info
)))
7184 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7185 SYMBOLP (coding_system
))))
7188 existing_info
= assq_no_quit (text_encoding
, result
);
7189 if (NILP (existing_info
))
7190 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7193 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7194 XSETCDR (XCDR (existing_info
),
7195 Fcons (charset
, XCDR (XCDR (existing_info
))));
7203 decode_mac_font_name (name
, size
, coding_system
)
7206 Lisp_Object coding_system
;
7208 struct coding_system coding
;
7211 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7213 for (p
= name
; *p
; p
++)
7214 if (!isascii (*p
) || iscntrl (*p
))
7219 setup_coding_system (coding_system
, &coding
);
7220 coding
.src_multibyte
= 0;
7221 coding
.dst_multibyte
= 1;
7222 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7223 coding
.composing
= COMPOSITION_DISABLED
;
7224 buf
= (char *) alloca (size
);
7226 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7227 bcopy (buf
, name
, coding
.produced
);
7228 name
[coding
.produced
] = '\0';
7232 /* If there's just one occurrence of '-' in the family name, it is
7233 replaced with '_'. (More than one occurrence of '-' means a
7234 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7235 p
= strchr (name
, '-');
7236 if (p
&& strchr (p
+ 1, '-') == NULL
)
7239 for (p
= name
; *p
; p
++)
7240 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7241 for some locales. */
7248 mac_to_x_fontname (name
, size
, style
, charset
)
7256 char xf
[256], *result
;
7259 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7263 strcpy(foundry
, "Apple");
7264 strcpy(family
, name
);
7267 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7268 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7269 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7271 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7272 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7273 for (p
= result
; *p
; p
++)
7274 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7275 for some locales. */
7282 /* Parse fully-specified and instantiated X11 font spec XF, and store
7283 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7284 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7285 caller must allocate at least 256 and 32 bytes respectively. For
7286 ordinary Mac fonts, the value stored to FAMILY should just be their
7287 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7288 intlfonts collection contain their charset designation in their
7289 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7290 types of font names are handled accordingly. */
7292 const int kDefaultFontSize
= 12;
7295 parse_x_font_name (xf
, family
, size
, style
, charset
)
7302 Str31 foundry
, weight
;
7303 int point_size
, avgwidth
;
7306 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7307 foundry
, family
, weight
, slant
, size
,
7308 &point_size
, &avgwidth
, charset
) != 8
7309 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7310 foundry
, family
, weight
, slant
, size
,
7311 &point_size
, &avgwidth
, charset
) != 8)
7317 *size
= point_size
/ 10;
7318 else if (avgwidth
> 0)
7319 *size
= avgwidth
/ 10;
7322 *size
= kDefaultFontSize
;
7325 if (strcmp (weight
, "bold") == 0)
7330 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7332 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7334 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7336 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7337 but take overlap into account. */
7338 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7339 memcpy (family
, foundry
, foundry_len
);
7340 family
[foundry_len
] = '-';
7341 family
[foundry_len
+ 1 + family_len
] = '-';
7342 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7348 for (p
= family
; *p
; p
++)
7349 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7350 for some locales. */
7359 add_font_name_table_entry (char *font_name
)
7361 if (font_name_table_size
== 0)
7363 font_name_table_size
= 256;
7364 font_name_table
= (char **)
7365 xmalloc (font_name_table_size
* sizeof (char *));
7367 else if (font_name_count
+ 1 >= font_name_table_size
)
7369 font_name_table_size
*= 2;
7370 font_name_table
= (char **)
7371 xrealloc (font_name_table
,
7372 font_name_table_size
* sizeof (char *));
7375 font_name_table
[font_name_count
++] = font_name
;
7379 add_mac_font_name (name
, size
, style
, charset
)
7383 const char *charset
;
7386 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7389 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7390 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7391 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7392 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7399 fm_get_style_from_font (font
)
7403 FMFontStyle style
= normal
;
7406 FMFontFamily font_family
;
7407 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
7409 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
7410 some font (e.g., Optima) even if it is `bold'. */
7411 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
7412 sizeof (mac_style
), &mac_style
, &len
);
7414 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
7415 style
= EndianU16_BtoN (mac_style
);
7417 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
7423 atsu_find_font_from_family_name (family
)
7426 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
7429 Lisp_Object rest
, best
;
7430 FMFontStyle min_style
, style
;
7432 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
7435 return kATSUInvalidFontID
;
7437 rest
= HASH_VALUE (h
, i
);
7438 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
7439 return cons_to_long (rest
);
7441 rest
= Fnreverse (rest
);
7445 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
7448 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
7449 if (style
< min_style
)
7452 if (style
== normal
)
7459 while (!NILP (rest
));
7461 HASH_VALUE (h
, i
) = best
;
7462 return cons_to_long (best
);
7466 fm_style_to_face_attributes (fm_style
)
7467 FMFontStyle fm_style
;
7471 fm_style
&= (bold
| italic
);
7472 tem
= assq_no_quit (make_number (fm_style
),
7473 fm_style_face_attributes_alist
);
7477 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
7478 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
7479 fm_style_face_attributes_alist
=
7480 Fcons (Fcons (make_number (fm_style
), tem
),
7481 fm_style_face_attributes_alist
);
7487 atsu_find_font_family_name (font_id
)
7492 Lisp_Object family
= Qnil
;
7494 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7495 kFontMacintoshPlatform
, kFontNoScript
,
7496 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
7499 family
= make_uninit_string (len
);
7500 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7501 kFontMacintoshPlatform
, kFontNoScript
,
7502 kFontNoLanguage
, len
, SDATA (family
),
7506 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
7512 mac_atsu_font_face_attributes (font_id
)
7515 Lisp_Object family
, style_attrs
;
7517 family
= atsu_find_font_family_name (font_id
);
7520 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
7521 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
7525 /* Sets up the table font_name_table to contain the list of all fonts
7526 in the system the first time the table is used so that the Resource
7527 Manager need not be accessed every time this information is
7531 init_font_name_table ()
7533 #if TARGET_API_MAC_CARBON
7534 FMFontFamilyIterator ffi
;
7535 FMFontFamilyInstanceIterator ffii
;
7537 Lisp_Object text_encoding_info_alist
;
7538 struct gcpro gcpro1
;
7540 text_encoding_info_alist
= create_text_encoding_info_alist ();
7543 #if USE_CG_TEXT_DRAWING
7544 init_cg_text_anti_aliasing_threshold ();
7546 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7547 text_encoding_info_alist
)))
7550 struct Lisp_Hash_Table
*h
;
7552 ItemCount nfonts
, i
;
7553 ATSUFontID
*font_ids
= NULL
;
7554 Lisp_Object prev_family
= Qnil
;
7558 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7559 make_float (DEFAULT_REHASH_SIZE
),
7560 make_float (DEFAULT_REHASH_THRESHOLD
),
7562 h
= XHASH_TABLE (atsu_font_id_hash
);
7564 err
= ATSUFontCount (&nfonts
);
7567 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7568 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7571 for (i
= 0; i
< nfonts
; i
++)
7575 family
= atsu_find_font_family_name (font_ids
[i
]);
7576 if (NILP (family
) || SREF (family
, 0) == '.')
7578 if (!NILP (Fequal (prev_family
, family
)))
7579 family
= prev_family
;
7581 j
= hash_lookup (h
, family
, &hash_code
);
7584 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
7585 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
7588 else if (EQ (prev_family
, family
))
7589 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
7591 prev_family
= family
;
7598 /* Create a dummy instance iterator here to avoid creating and
7599 destroying it in the loop. */
7600 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7602 /* Create an iterator to enumerate the font families. */
7603 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7606 FMDisposeFontFamilyInstanceIterator (&ffii
);
7610 GCPRO1 (text_encoding_info_alist
);
7612 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7618 TextEncoding encoding
;
7619 TextEncodingBase sc
;
7620 Lisp_Object text_encoding_info
, family
;
7622 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7628 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7630 sc
= GetTextEncodingBase (encoding
);
7631 text_encoding_info
= assq_no_quit (make_number (sc
),
7632 text_encoding_info_alist
);
7633 if (NILP (text_encoding_info
))
7634 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7635 text_encoding_info_alist
);
7636 decode_mac_font_name (name
, sizeof (name
),
7637 XCAR (XCDR (text_encoding_info
)));
7638 family
= build_string (name
);
7639 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7641 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7642 fm_font_family_alist
);
7644 /* Point the instance iterator at the current font family. */
7645 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7648 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7651 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7653 if (size
> 0 || style
== normal
)
7654 for (; !NILP (rest
); rest
= XCDR (rest
))
7655 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7661 /* Dispose of the iterators. */
7662 FMDisposeFontFamilyIterator (&ffi
);
7663 FMDisposeFontFamilyInstanceIterator (&ffii
);
7664 #else /* !TARGET_API_MAC_CARBON */
7666 SInt16 fontnum
, old_fontnum
;
7667 int num_mac_fonts
= CountResources('FOND');
7669 Handle font_handle
, font_handle_2
;
7670 short id
, scriptcode
;
7673 struct FontAssoc
*fat
;
7674 struct AsscEntry
*assc_entry
;
7675 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7676 struct gcpro gcpro1
;
7678 GetPort (&port
); /* save the current font number used */
7679 old_fontnum
= port
->txFont
;
7681 text_encoding_info_alist
= create_text_encoding_info_alist ();
7683 GCPRO1 (text_encoding_info_alist
);
7685 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7687 font_handle
= GetIndResource ('FOND', i
);
7691 GetResInfo (font_handle
, &id
, &type
, name
);
7692 GetFNum (name
, &fontnum
);
7694 if (fontnum
== 0 || *name
== '.')
7698 scriptcode
= FontToScript (fontnum
);
7699 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7700 text_encoding_info_alist
);
7701 if (NILP (text_encoding_info
))
7702 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7703 text_encoding_info_alist
);
7704 decode_mac_font_name (name
, sizeof (name
),
7705 XCAR (XCDR (text_encoding_info
)));
7706 family
= build_string (name
);
7707 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7709 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7710 fm_font_family_alist
);
7713 HLock (font_handle
);
7715 if (GetResourceSizeOnDisk (font_handle
)
7716 >= sizeof (struct FamRec
))
7718 fat
= (struct FontAssoc
*) (*font_handle
7719 + sizeof (struct FamRec
));
7721 = (struct AsscEntry
*) (*font_handle
7722 + sizeof (struct FamRec
)
7723 + sizeof (struct FontAssoc
));
7725 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7727 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7729 for (; !NILP (rest
); rest
= XCDR (rest
))
7730 add_mac_font_name (name
, assc_entry
->fontSize
,
7731 assc_entry
->fontStyle
,
7732 SDATA (XCAR (rest
)));
7736 HUnlock (font_handle
);
7737 font_handle_2
= GetNextFOND (font_handle
);
7738 ReleaseResource (font_handle
);
7739 font_handle
= font_handle_2
;
7741 while (ResError () == noErr
&& font_handle
);
7746 TextFont (old_fontnum
);
7747 #endif /* !TARGET_API_MAC_CARBON */
7752 mac_clear_font_name_table ()
7756 for (i
= 0; i
< font_name_count
; i
++)
7757 xfree (font_name_table
[i
]);
7758 xfree (font_name_table
);
7759 font_name_table
= NULL
;
7760 font_name_table_size
= font_name_count
= 0;
7761 fm_font_family_alist
= Qnil
;
7765 enum xlfd_scalable_field_index
7767 XLFD_SCL_PIXEL_SIZE
,
7768 XLFD_SCL_POINT_SIZE
,
7773 static const int xlfd_scalable_fields
[] =
7782 mac_do_list_fonts (pattern
, maxnames
)
7783 const char *pattern
;
7787 Lisp_Object font_list
= Qnil
;
7788 struct xlfdpat
*pat
;
7791 int scl_val
[XLFD_SCL_LAST
], *val
;
7795 if (font_name_table
== NULL
) /* Initialize when first used. */
7796 init_font_name_table ();
7798 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7801 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7802 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7803 fonts are scaled according to the specified size. */
7806 field
= xlfd_scalable_fields
;
7814 if ('0' <= *ptr
&& *ptr
<= '9')
7816 *val
= *ptr
++ - '0';
7817 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7818 *val
= *val
* 10 + *ptr
++ - '0';
7825 ptr
= strchr (ptr
, '-');
7828 while (ptr
&& i
< 14);
7830 if (i
== 14 && ptr
== NULL
)
7832 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7833 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7834 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7835 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7837 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7838 scl_val
[XLFD_SCL_POINT_SIZE
] =
7839 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7840 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7842 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7843 scl_val
[XLFD_SCL_AVGWIDTH
] =
7844 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7845 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7849 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7851 pat
= xlfdpat_create (pattern
);
7855 exact
= xlfdpat_exact_p (pat
);
7857 for (i
= 0; i
< font_name_count
; i
++)
7859 if (xlfdpat_match (pat
, font_name_table
[i
]))
7861 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7862 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7865 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7866 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7868 int former_len
= ptr
- font_name_table
[i
];
7870 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7871 memcpy (scaled
, font_name_table
[i
], former_len
);
7872 sprintf (scaled
+ former_len
,
7873 "-%d-%d-72-72-m-%d-%s",
7874 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7875 scl_val
[XLFD_SCL_POINT_SIZE
],
7876 scl_val
[XLFD_SCL_AVGWIDTH
],
7877 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7879 if (xlfdpat_match (pat
, scaled
))
7881 font_list
= Fcons (build_string (scaled
), font_list
);
7883 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7891 xlfdpat_destroy (pat
);
7896 /* Return a list of names of available fonts matching PATTERN on frame F.
7898 Frame F null means we have not yet created any frame on Mac, and
7899 consult the first display in x_display_list. MAXNAMES sets a limit
7900 on how many fonts to match. */
7903 x_list_fonts (f
, pattern
, size
, maxnames
)
7905 Lisp_Object pattern
;
7908 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7909 struct mac_display_info
*dpyinfo
7910 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7912 xassert (size
<= 0);
7914 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7915 if (NILP (patterns
))
7916 patterns
= Fcons (pattern
, Qnil
);
7918 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7920 pattern
= XCAR (patterns
);
7922 if (!STRINGP (pattern
))
7925 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7926 key
= Fcons (pattern
, make_number (maxnames
));
7928 list
= Fassoc (key
, tem
);
7931 list
= Fcdr_safe (list
);
7932 /* We have a cashed list. Don't have to get the list again. */
7937 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7940 /* MAC_TODO: add code for matching outline fonts here */
7942 /* Now store the result in the cache. */
7943 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7944 Fcons (Fcons (key
, list
),
7945 XCAR (XCDR (dpyinfo
->name_list_element
))));
7948 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7957 /* Check that FONT is valid on frame F. It is if it can be found in F's
7961 x_check_font (f
, font
)
7966 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7968 xassert (font
!= NULL
);
7970 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7971 if (dpyinfo
->font_table
[i
].name
7972 && font
== dpyinfo
->font_table
[i
].font
)
7975 xassert (i
< dpyinfo
->n_fonts
);
7978 #endif /* GLYPH_DEBUG != 0 */
7980 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7981 Note: There are (broken) X fonts out there with invalid XFontStruct
7982 min_bounds contents. For example, handa@etl.go.jp reports that
7983 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7984 have font->min_bounds.width == 0. */
7987 x_font_min_bounds (font
, w
, h
)
7988 MacFontStruct
*font
;
7991 *h
= FONT_HEIGHT (font
);
7992 *w
= font
->min_bounds
.width
;
7996 /* Compute the smallest character width and smallest font height over
7997 all fonts available on frame F. Set the members smallest_char_width
7998 and smallest_font_height in F's x_display_info structure to
7999 the values computed. Value is non-zero if smallest_font_height or
8000 smallest_char_width become smaller than they were before. */
8003 x_compute_min_glyph_bounds (f
)
8007 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8008 MacFontStruct
*font
;
8009 int old_width
= dpyinfo
->smallest_char_width
;
8010 int old_height
= dpyinfo
->smallest_font_height
;
8012 dpyinfo
->smallest_font_height
= 100000;
8013 dpyinfo
->smallest_char_width
= 100000;
8015 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8016 if (dpyinfo
->font_table
[i
].name
)
8018 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8021 font
= (MacFontStruct
*) fontp
->font
;
8022 xassert (font
!= (MacFontStruct
*) ~0);
8023 x_font_min_bounds (font
, &w
, &h
);
8025 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8026 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8029 xassert (dpyinfo
->smallest_char_width
> 0
8030 && dpyinfo
->smallest_font_height
> 0);
8032 return (dpyinfo
->n_fonts
== 1
8033 || dpyinfo
->smallest_char_width
< old_width
8034 || dpyinfo
->smallest_font_height
< old_height
);
8038 /* Determine whether given string is a fully-specified XLFD: all 14
8039 fields are present, none is '*'. */
8042 is_fully_specified_xlfd (p
)
8051 for (i
= 0; i
< 13; i
++)
8053 q
= strchr (p
+ 1, '-');
8056 if (q
- p
== 2 && *(p
+ 1) == '*')
8061 if (strchr (p
+ 1, '-') != NULL
)
8064 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8071 /* mac_load_query_font creates and returns an internal representation
8072 for a font in a MacFontStruct struct. There is really no concept
8073 corresponding to "loading" a font on the Mac. But we check its
8074 existence and find the font number and all other information for it
8075 and store them in the returned MacFontStruct. */
8077 static MacFontStruct
*
8078 mac_load_query_font (f
, fontname
)
8088 static ATSUFontID font_id
;
8089 ATSUStyle mac_style
= NULL
;
8092 #if TARGET_API_MAC_CARBON
8093 TextEncoding encoding
;
8098 MacFontStruct
*font
;
8099 XCharStruct
*space_bounds
= NULL
, *pcm
;
8101 if (is_fully_specified_xlfd (fontname
))
8105 Lisp_Object matched_fonts
;
8107 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8108 if (NILP (matched_fonts
))
8110 name
= SDATA (XCAR (matched_fonts
));
8113 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8117 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8120 static const ATSUAttributeTag tags
[] =
8121 {kATSUFontTag
, kATSUSizeTag
,
8122 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8123 static const ByteCount sizes
[] =
8124 {sizeof (ATSUFontID
), sizeof (Fixed
),
8125 sizeof (Boolean
), sizeof (Boolean
)};
8126 static Fixed size_fixed
;
8127 static Boolean bold_p
, italic_p
;
8128 static const ATSUAttributeValuePtr values
[] =
8129 {&font_id
, &size_fixed
,
8130 &bold_p
, &italic_p
};
8131 static const ATSUFontFeatureType types
[] =
8132 {kAllTypographicFeaturesType
, kDiacriticsType
};
8133 static const ATSUFontFeatureSelector selectors
[] =
8134 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8137 font_id
= atsu_find_font_from_family_name (family
);
8138 if (font_id
== kATSUInvalidFontID
)
8140 size_fixed
= Long2Fix (size
);
8141 bold_p
= (fontface
& bold
) != 0;
8142 italic_p
= (fontface
& italic
) != 0;
8143 err
= ATSUCreateStyle (&mac_style
);
8146 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8150 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8151 tags
, sizes
, values
);
8154 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8157 scriptcode
= kTextEncodingMacUnicode
;
8162 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8166 fontnum
= XINT (XCDR (tmp
));
8167 #if TARGET_API_MAC_CARBON
8168 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8170 scriptcode
= GetTextEncodingBase (encoding
);
8172 scriptcode
= FontToScript (fontnum
);
8176 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8178 font
->mac_fontnum
= fontnum
;
8179 font
->mac_fontsize
= size
;
8180 font
->mac_fontface
= fontface
;
8181 font
->mac_scriptcode
= scriptcode
;
8183 font
->mac_style
= mac_style
;
8184 #if USE_CG_TEXT_DRAWING
8185 font
->cg_font
= NULL
;
8186 font
->cg_glyphs
= NULL
;
8190 /* Apple Japanese (SJIS) font is listed as both
8191 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8192 (Roman script) in init_font_name_table (). The latter should be
8193 treated as a one-byte font. */
8194 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8195 font
->mac_scriptcode
= smRoman
;
8197 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8200 if (font
->mac_style
)
8205 font
->min_byte1
= 0;
8206 font
->max_byte1
= 0xff;
8207 font
->min_char_or_byte2
= 0;
8208 font
->max_char_or_byte2
= 0xff;
8210 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8211 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8212 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8213 pcm_init (font
->bounds
.rows
[0], 0x100);
8215 #if USE_CG_TEXT_DRAWING
8219 ATSFontRef ats_font
;
8221 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8223 /* Use CG text drawing if italic/bold is not synthesized. */
8224 if (err
== noErr
&& style
== fontface
)
8226 ats_font
= FMGetATSFontRefFromFont (font_id
);
8227 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8233 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8234 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8237 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8238 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8239 &font
->ascent
, &font
->descent
,
8241 #if USE_CG_TEXT_DRAWING
8242 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8249 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8251 mac_unload_font (&one_mac_display_info
, font
);
8255 pcm
= font
->bounds
.rows
[0];
8256 for (c
= 0x21; c
<= 0xff; c
++)
8259 /* Soft hyphen is not supported in ATSUI. */
8263 #if USE_CG_TEXT_DRAWING
8264 if (font
->cg_glyphs
)
8274 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8275 pcm
? pcm
+ c
: NULL
,
8276 #if USE_CG_TEXT_DRAWING
8277 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8284 #if USE_CG_TEXT_DRAWING
8285 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8287 /* Don't use CG text drawing if font substitution occurs in
8288 ASCII or Latin-1 characters. */
8289 CGFontRelease (font
->cg_font
);
8290 font
->cg_font
= NULL
;
8291 xfree (font
->cg_glyphs
);
8292 font
->cg_glyphs
= NULL
;
8303 FontInfo the_fontinfo
;
8304 int is_two_byte_font
;
8307 mac_prepare_for_quickdraw (f
);
8309 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8313 TextFace (fontface
);
8315 GetFontInfo (&the_fontinfo
);
8317 font
->ascent
= the_fontinfo
.ascent
;
8318 font
->descent
= the_fontinfo
.descent
;
8320 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8321 || font
->mac_scriptcode
== smTradChinese
8322 || font
->mac_scriptcode
== smSimpChinese
8323 || font
->mac_scriptcode
== smKorean
);
8325 if (is_two_byte_font
)
8329 font
->min_byte1
= 0xa1;
8330 font
->max_byte1
= 0xfe;
8331 font
->min_char_or_byte2
= 0xa1;
8332 font
->max_char_or_byte2
= 0xfe;
8334 /* Use the width of an "ideographic space" of that font
8335 because the_fontinfo.widMax returns the wrong width for
8337 switch (font
->mac_scriptcode
)
8340 font
->min_byte1
= 0x81;
8341 font
->max_byte1
= 0xfc;
8342 font
->min_char_or_byte2
= 0x40;
8343 font
->max_char_or_byte2
= 0xfc;
8344 char_width
= StringWidth("\p\x81\x40");
8347 font
->min_char_or_byte2
= 0x40;
8348 char_width
= StringWidth("\p\xa1\x40");
8351 char_width
= StringWidth("\p\xa1\xa1");
8354 char_width
= StringWidth("\p\xa1\xa1");
8358 font
->bounds
.per_char
= NULL
;
8360 if (fontface
& italic
)
8361 font
->max_bounds
.rbearing
= char_width
+ 1;
8363 font
->max_bounds
.rbearing
= char_width
;
8364 font
->max_bounds
.lbearing
= 0;
8365 font
->max_bounds
.width
= char_width
;
8366 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8367 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8369 font
->min_bounds
= font
->max_bounds
;
8375 font
->min_byte1
= font
->max_byte1
= 0;
8376 font
->min_char_or_byte2
= 0x20;
8377 font
->max_char_or_byte2
= 0xff;
8379 font
->bounds
.per_char
=
8380 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8381 bzero (font
->bounds
.per_char
,
8382 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8384 space_bounds
= font
->bounds
.per_char
;
8385 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
8386 &font
->descent
, space_bounds
, NULL
);
8387 if (err
!= noErr
|| space_bounds
->width
<= 0)
8389 mac_unload_font (&one_mac_display_info
, font
);
8393 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8394 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8402 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8403 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8406 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8408 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8410 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8412 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8414 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
8417 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8419 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8421 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8423 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8425 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
8430 font
->mac_style
== NULL
&&
8432 font
->max_bounds
.width
== font
->min_bounds
.width
8433 && font
->min_bounds
.lbearing
>= 0
8434 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8436 /* Fixed width and no overhangs. */
8437 xfree (font
->bounds
.per_char
);
8438 font
->bounds
.per_char
= NULL
;
8442 #if !defined (MAC_OS8) || USE_ATSUI
8443 /* AppKit and WebKit do some adjustment to the heights of Courier,
8444 Helvetica, and Times. This only works on the environments where
8445 srcCopy text transfer mode is never used. */
8447 #ifdef MAC_OS8 /* implies USE_ATSUI */
8450 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8451 || strcmp (family
, "times") == 0))
8452 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8460 mac_unload_font (dpyinfo
, font
)
8461 struct mac_display_info
*dpyinfo
;
8464 xfree (font
->full_name
);
8466 if (font
->mac_style
)
8470 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8471 if (font
->bounds
.rows
[i
])
8472 xfree (font
->bounds
.rows
[i
]);
8473 xfree (font
->bounds
.rows
);
8474 ATSUDisposeStyle (font
->mac_style
);
8478 if (font
->bounds
.per_char
)
8479 xfree (font
->bounds
.per_char
);
8480 #if USE_CG_TEXT_DRAWING
8482 CGFontRelease (font
->cg_font
);
8483 if (font
->cg_glyphs
)
8484 xfree (font
->cg_glyphs
);
8490 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8491 pointer to the structure font_info while allocating it dynamically.
8492 If SIZE is 0, load any size of font.
8493 If loading is failed, return NULL. */
8496 x_load_font (f
, fontname
, size
)
8498 register char *fontname
;
8501 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8502 Lisp_Object font_names
;
8504 /* Get a list of all the fonts that match this name. Once we
8505 have a list of matching fonts, we compare them against the fonts
8506 we already have by comparing names. */
8507 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8509 if (!NILP (font_names
))
8514 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8515 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8516 if (dpyinfo
->font_table
[i
].name
8517 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8518 SDATA (XCAR (tail
)))
8519 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8520 SDATA (XCAR (tail
)))))
8521 return (dpyinfo
->font_table
+ i
);
8526 /* Load the font and add it to the table. */
8528 struct MacFontStruct
*font
;
8529 struct font_info
*fontp
;
8532 fontname
= (char *) SDATA (XCAR (font_names
));
8535 font
= mac_load_query_font (f
, fontname
);
8540 /* Find a free slot in the font table. */
8541 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8542 if (dpyinfo
->font_table
[i
].name
== NULL
)
8545 /* If no free slot found, maybe enlarge the font table. */
8546 if (i
== dpyinfo
->n_fonts
8547 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8550 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8551 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8553 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8556 fontp
= dpyinfo
->font_table
+ i
;
8557 if (i
== dpyinfo
->n_fonts
)
8560 /* Now fill in the slots of *FONTP. */
8562 bzero (fontp
, sizeof (*fontp
));
8564 fontp
->font_idx
= i
;
8565 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8566 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8568 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8570 /* Fixed width font. */
8571 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8578 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8579 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8581 fontp
->space_width
= pcm
->width
;
8583 fontp
->space_width
= FONT_WIDTH (font
);
8587 int width
= pcm
->width
;
8588 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8589 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8590 width
+= pcm
->width
;
8591 fontp
->average_width
= width
/ 95;
8594 fontp
->average_width
= FONT_WIDTH (font
);
8597 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8598 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8600 fontp
->size
= font
->max_bounds
.width
;
8601 fontp
->height
= FONT_HEIGHT (font
);
8603 /* For some font, ascent and descent in max_bounds field is
8604 larger than the above value. */
8605 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8606 if (max_height
> fontp
->height
)
8607 fontp
->height
= max_height
;
8610 /* The slot `encoding' specifies how to map a character
8611 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8612 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8613 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8614 2:0xA020..0xFF7F). For the moment, we don't know which charset
8615 uses this font. So, we set information in fontp->encoding[1]
8616 which is never used by any charset. If mapping can't be
8617 decided, set FONT_ENCODING_NOT_DECIDED. */
8618 if (font
->mac_scriptcode
== smJapanese
)
8619 fontp
->encoding
[1] = 4;
8623 = (font
->max_byte1
== 0
8625 ? (font
->min_char_or_byte2
< 0x80
8626 ? (font
->max_char_or_byte2
< 0x80
8627 ? 0 /* 0x20..0x7F */
8628 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8629 : 1) /* 0xA0..0xFF */
8631 : (font
->min_byte1
< 0x80
8632 ? (font
->max_byte1
< 0x80
8633 ? (font
->min_char_or_byte2
< 0x80
8634 ? (font
->max_char_or_byte2
< 0x80
8635 ? 0 /* 0x2020..0x7F7F */
8636 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8637 : 3) /* 0x20A0..0x7FFF */
8638 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8639 : (font
->min_char_or_byte2
< 0x80
8640 ? (font
->max_char_or_byte2
< 0x80
8641 ? 2 /* 0xA020..0xFF7F */
8642 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8643 : 1))); /* 0xA0A0..0xFFFF */
8646 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8647 fontp
->baseline_offset
8648 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8649 ? (long) value
: 0);
8650 fontp
->relative_compose
8651 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8652 ? (long) value
: 0);
8653 fontp
->default_ascent
8654 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8655 ? (long) value
: 0);
8657 fontp
->baseline_offset
= 0;
8658 fontp
->relative_compose
= 0;
8659 fontp
->default_ascent
= 0;
8662 /* Set global flag fonts_changed_p to non-zero if the font loaded
8663 has a character with a smaller width than any other character
8664 before, or if the font loaded has a smaller height than any
8665 other font loaded before. If this happens, it will make a
8666 glyph matrix reallocation necessary. */
8667 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8674 /* Return a pointer to struct font_info of a font named FONTNAME for
8675 frame F. If no such font is loaded, return NULL. */
8678 x_query_font (f
, fontname
)
8680 register char *fontname
;
8682 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8685 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8686 if (dpyinfo
->font_table
[i
].name
8687 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8688 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8689 return (dpyinfo
->font_table
+ i
);
8694 /* Find a CCL program for a font specified by FONTP, and set the member
8695 `encoder' of the structure. */
8698 x_find_ccl_program (fontp
)
8699 struct font_info
*fontp
;
8701 Lisp_Object list
, elt
;
8703 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8707 && STRINGP (XCAR (elt
))
8708 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8714 struct ccl_program
*ccl
8715 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8717 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8720 fontp
->font_encoder
= ccl
;
8724 #if USE_MAC_FONT_PANEL
8725 /* Whether Font Panel has been shown before. The first call to font
8726 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8727 slow. This variable is used for deferring such a call as much as
8729 static int font_panel_shown_p
= 0;
8732 mac_font_panel_visible_p ()
8734 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8738 mac_show_hide_font_panel ()
8740 font_panel_shown_p
= 1;
8742 return FPShowHideFontPanel ();
8746 mac_set_font_info_for_selection (f
, face_id
, c
)
8751 EventTargetRef target
= NULL
;
8752 XFontStruct
*font
= NULL
;
8754 if (!mac_font_panel_visible_p ())
8759 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8761 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8765 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8766 face
= FACE_FROM_ID (f
, face_id
);
8772 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8775 if (font
->mac_fontnum
!= -1)
8777 FontSelectionQDStyle qd_style
;
8779 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8780 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8781 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8782 qd_style
.size
= font
->mac_fontsize
;
8783 qd_style
.hasColor
= false;
8785 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8786 1, &qd_style
, target
);
8789 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8790 1, &font
->mac_style
, target
);
8798 /* The Mac Event loop code */
8800 #if !TARGET_API_MAC_CARBON
8802 #include <Quickdraw.h>
8803 #include <Balloons.h>
8804 #include <Devices.h>
8806 #include <Gestalt.h>
8808 #include <Processes.h>
8810 #include <ToolUtils.h>
8811 #include <TextUtils.h>
8812 #include <Dialogs.h>
8815 #include <Resources.h>
8820 #endif /* ! TARGET_API_MAC_CARBON */
8825 #define DEFAULT_NUM_COLS 80
8827 #define MIN_DOC_SIZE 64
8828 #define MAX_DOC_SIZE 32767
8830 #define EXTRA_STACK_ALLOC (256 * 1024)
8832 #define ARGV_STRING_LIST_ID 129
8833 #define ABOUT_ALERT_ID 128
8834 #define RAM_TOO_LARGE_ALERT_ID 129
8836 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8837 Lisp_Object Qreverse
;
8840 /* Modifier associated with the control key, or nil to ignore. */
8841 Lisp_Object Vmac_control_modifier
;
8843 /* Modifier associated with the option key, or nil to ignore. */
8844 Lisp_Object Vmac_option_modifier
;
8846 /* Modifier associated with the command key, or nil to ignore. */
8847 Lisp_Object Vmac_command_modifier
;
8849 /* Modifier associated with the function key, or nil to ignore. */
8850 Lisp_Object Vmac_function_modifier
;
8852 /* True if the option and command modifiers should be used to emulate
8853 a three button mouse */
8854 Lisp_Object Vmac_emulate_three_button_mouse
;
8856 #if USE_CARBON_EVENTS
8857 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8858 mouse-2, instead of mouse-3. */
8859 int mac_wheel_button_is_mouse_2
;
8861 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8862 for processing before Emacs sees it. */
8863 int mac_pass_command_to_system
;
8865 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8866 for processing before Emacs sees it. */
8867 int mac_pass_control_to_system
;
8870 /* Points to the variable `inev' in the function XTread_socket. It is
8871 used for passing an input event to the function back from
8872 Carbon/Apple event handlers. */
8873 static struct input_event
*read_socket_inev
= NULL
;
8875 /* Whether or not the screen configuration has changed. */
8876 static int mac_screen_config_changed
= 0;
8878 Point saved_menu_event_location
;
8881 #if USE_CARBON_EVENTS
8882 static Lisp_Object Qhi_command
;
8884 extern Lisp_Object Qwindow
;
8885 static Lisp_Object Qtoolbar_switch_mode
;
8887 #if USE_MAC_FONT_PANEL
8888 extern Lisp_Object Qfont
;
8889 static Lisp_Object Qpanel_closed
, Qselection
;
8892 static TSMDocumentID tsm_document_id
;
8893 static Lisp_Object Qtext_input
;
8894 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8895 static Lisp_Object Vmac_ts_active_input_overlay
;
8896 extern Lisp_Object Qbefore_string
;
8897 static Lisp_Object Vmac_ts_script_language_on_focus
;
8898 static Lisp_Object saved_ts_script_language_on_focus
;
8899 static ScriptLanguageRecord saved_ts_language
;
8900 static Component saved_ts_component
;
8903 extern int mac_ready_for_apple_events
;
8904 extern Lisp_Object Qundefined
;
8905 extern void init_apple_event_handler
P_ ((void));
8906 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8907 Lisp_Object
*, Lisp_Object
*,
8909 extern OSErr init_coercion_handler
P_ ((void));
8912 extern OSErr install_drag_handler
P_ ((WindowRef
));
8913 extern void remove_drag_handler
P_ ((WindowRef
));
8915 /* Showing help echo string during menu tracking */
8916 extern OSStatus install_menu_target_item_handler
P_ ((WindowPtr
));
8918 #if USE_CARBON_EVENTS
8920 extern void init_service_handler ();
8921 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8924 /* Window Event Handler */
8925 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8928 OSStatus
install_window_handler (WindowPtr
);
8930 extern void init_emacs_passwd_dir ();
8931 extern int emacs_main (int, char **, char **);
8933 extern void initialize_applescript();
8934 extern void terminate_applescript();
8936 /* Table for translating Mac keycode to X keysym values. Contributed
8938 Mapping for special keys is now identical to that in Apple X11
8939 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8940 on the right of the Cmd key on laptops, and fn + `enter' (->
8942 static const unsigned char keycode_to_xkeysym_table
[] = {
8943 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8944 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8945 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8947 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8948 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8949 /*0x38*/ 0, 0, 0, 0,
8950 /*0x3C*/ 0, 0, 0, 0,
8952 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8953 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8954 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8955 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8957 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8958 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8959 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8960 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8962 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8963 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8964 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8965 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8967 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8968 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8969 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8970 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8974 /* Table for translating Mac keycode with the laptop `fn' key to that
8975 without it. Destination symbols in comments are keys on US
8976 keyboard, and they may not be the same on other types of keyboards.
8977 If the destination is identical to the source (f1 ... f12), it
8978 doesn't map `fn' key to a modifier. */
8979 static const unsigned char fn_keycode_to_keycode_table
[] = {
8980 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8981 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8982 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8984 /*0x30*/ 0, 0, 0, 0,
8985 /*0x34*/ 0, 0, 0, 0,
8986 /*0x38*/ 0, 0, 0, 0,
8987 /*0x3C*/ 0, 0, 0, 0,
8989 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8990 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8991 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8992 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8994 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8995 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8996 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8997 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8999 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9000 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9001 /*0x68*/ 0, 0, 0, 0,
9002 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9004 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9005 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9006 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9009 #endif /* MAC_OSX */
9012 #if USE_CARBON_EVENTS
9013 mac_to_emacs_modifiers (UInt32 mods
)
9015 mac_to_emacs_modifiers (EventModifiers mods
)
9018 unsigned int result
= 0;
9019 if (mods
& shiftKey
)
9020 result
|= shift_modifier
;
9022 /* Deactivated to simplify configuration:
9023 if Vmac_option_modifier is non-NIL, we fully process the Option
9024 key. Otherwise, we only process it if an additional Ctrl or Command
9025 is pressed. That way the system may convert the character to a
9027 if ((mods & optionKey) &&
9028 (( !NILP(Vmac_option_modifier) ||
9029 ((mods & cmdKey) || (mods & controlKey))))) */
9031 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9032 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9034 result
|= XUINT(val
);
9036 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9037 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9039 result
|= XUINT(val
);
9041 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9042 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9044 result
|= XUINT(val
);
9048 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9049 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9051 result
|= XUINT(val
);
9059 mac_mapped_modifiers (modifiers
)
9062 UInt32 mapped_modifiers_all
=
9063 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9064 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9065 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9068 mapped_modifiers_all
|=
9069 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9072 return mapped_modifiers_all
& modifiers
;
9076 mac_get_emulated_btn ( UInt32 modifiers
)
9079 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9080 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9081 if (modifiers
& cmdKey
)
9082 result
= cmdIs3
? 2 : 1;
9083 else if (modifiers
& optionKey
)
9084 result
= cmdIs3
? 1 : 2;
9089 #if TARGET_API_MAC_CARBON
9090 /***** Code to handle C-g testing *****/
9091 extern int quit_char
;
9092 extern int make_ctrl_char
P_ ((int));
9095 mac_quit_char_key_p (modifiers
, key_code
)
9096 UInt32 modifiers
, key_code
;
9099 unsigned long some_state
= 0;
9100 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9101 int c
, emacs_modifiers
;
9103 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9104 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9105 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9106 if (char_code
& ~0xff)
9109 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9110 if (emacs_modifiers
& ctrl_modifier
)
9111 c
= make_ctrl_char (char_code
);
9113 c
|= (emacs_modifiers
9114 & (meta_modifier
| alt_modifier
9115 | hyper_modifier
| super_modifier
));
9117 return c
== quit_char
;
9121 #if USE_CARBON_EVENTS
9122 /* Obtains the event modifiers from the event ref and then calls
9123 mac_to_emacs_modifiers. */
9125 mac_event_to_emacs_modifiers (EventRef eventRef
)
9128 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9129 sizeof (UInt32
), NULL
, &mods
);
9130 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9131 GetEventClass(eventRef
) == kEventClassMouse
)
9133 mods
&= ~(optionKey
| cmdKey
);
9135 return mac_to_emacs_modifiers (mods
);
9138 /* Given an event ref, return the code to use for the mouse button
9139 code in the emacs input_event. */
9141 mac_get_mouse_btn (EventRef ref
)
9143 EventMouseButton result
= kEventMouseButtonPrimary
;
9144 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9145 sizeof (EventMouseButton
), NULL
, &result
);
9148 case kEventMouseButtonPrimary
:
9149 if (NILP (Vmac_emulate_three_button_mouse
))
9153 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9154 sizeof (UInt32
), NULL
, &mods
);
9155 return mac_get_emulated_btn(mods
);
9157 case kEventMouseButtonSecondary
:
9158 return mac_wheel_button_is_mouse_2
? 2 : 1;
9159 case kEventMouseButtonTertiary
:
9160 case 4: /* 4 is the number for the mouse wheel button */
9161 return mac_wheel_button_is_mouse_2
? 1 : 2;
9167 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9168 events. However the click of the mouse wheel is not converted to a
9169 mouseDown or mouseUp event. Likewise for dead key events. This
9170 calls ConvertEventRefToEventRecord, but then checks to see if it is
9171 a mouse up/down, or a dead key Carbon event that has not been
9172 converted, and if so, converts it by hand (to be picked up in the
9173 XTread_socket loop). */
9174 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9177 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9183 switch (GetEventClass (eventRef
))
9185 case kEventClassMouse
:
9186 switch (GetEventKind (eventRef
))
9188 case kEventMouseDown
:
9189 eventRec
->what
= mouseDown
;
9194 eventRec
->what
= mouseUp
;
9203 case kEventClassKeyboard
:
9204 switch (GetEventKind (eventRef
))
9206 case kEventRawKeyDown
:
9208 goto keystroke_common
;
9209 case kEventRawKeyRepeat
:
9211 goto keystroke_common
;
9212 case kEventRawKeyUp
:
9216 unsigned char char_codes
;
9219 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9220 typeChar
, NULL
, sizeof (char),
9223 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9224 typeUInt32
, NULL
, sizeof (UInt32
),
9228 eventRec
->what
= action
;
9229 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9246 /* Need where and when. */
9249 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9250 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9251 /* Use two step process because new event modifiers are 32-bit
9252 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9253 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9254 NULL
, sizeof (UInt32
), NULL
, &mods
);
9255 eventRec
->modifiers
= mods
;
9257 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9269 Handle menubar_handle
;
9270 MenuHandle menu_handle
;
9272 menubar_handle
= GetNewMBar (128);
9273 if(menubar_handle
== NULL
)
9275 SetMenuBar (menubar_handle
);
9278 #if !TARGET_API_MAC_CARBON
9279 menu_handle
= GetMenuHandle (M_APPLE
);
9280 if(menu_handle
!= NULL
)
9281 AppendResMenu (menu_handle
,'DRVR');
9289 do_init_managers (void)
9291 #if !TARGET_API_MAC_CARBON
9292 InitGraf (&qd
.thePort
);
9294 FlushEvents (everyEvent
, 0);
9299 #endif /* !TARGET_API_MAC_CARBON */
9302 #if !TARGET_API_MAC_CARBON
9303 /* set up some extra stack space for use by emacs */
9304 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9306 /* MaxApplZone must be called for AppleScript to execute more
9307 complicated scripts */
9310 #endif /* !TARGET_API_MAC_CARBON */
9314 do_check_ram_size (void)
9316 SInt32 physical_ram_size
, logical_ram_size
;
9318 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
9319 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
9320 || physical_ram_size
> (1 << VALBITS
)
9321 || logical_ram_size
> (1 << VALBITS
))
9323 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
9327 #endif /* MAC_OS8 */
9330 do_window_update (WindowPtr win
)
9332 struct frame
*f
= mac_window_to_frame (win
);
9336 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
9338 if (win
!= tip_window
)
9340 if (f
->async_visible
== 0)
9342 /* Update events may occur when a frame gets iconified. */
9344 f
->async_visible
= 1;
9345 f
->async_iconified
= 0;
9346 SET_FRAME_GARBAGED (f
);
9352 #if TARGET_API_MAC_CARBON
9353 RgnHandle region
= NewRgn ();
9355 GetPortVisibleRegion (GetWindowPort (win
), region
);
9356 GetRegionBounds (region
, &r
);
9357 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9359 mac_prepare_for_quickdraw (f
);
9361 UpdateControls (win
, region
);
9362 DisposeRgn (region
);
9364 r
= (*win
->visRgn
)->rgnBBox
;
9365 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9366 UpdateControls (win
, win
->visRgn
);
9375 is_emacs_window (WindowPtr win
)
9377 Lisp_Object tail
, frame
;
9382 FOR_EACH_FRAME (tail
, frame
)
9383 if (FRAME_MAC_P (XFRAME (frame
)))
9384 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9395 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9397 err
= ActivateTSMDocument (tsm_document_id
);
9401 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9402 && EQ (saved_ts_script_language_on_focus
, Qt
))
9403 slptr
= &saved_ts_language
;
9404 else if (CONSP (Vmac_ts_script_language_on_focus
)
9405 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9406 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9407 && CONSP (saved_ts_script_language_on_focus
)
9408 && EQ (XCAR (saved_ts_script_language_on_focus
),
9409 XCAR (Vmac_ts_script_language_on_focus
))
9410 && EQ (XCDR (saved_ts_script_language_on_focus
),
9411 XCDR (Vmac_ts_script_language_on_focus
)))
9413 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9414 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9421 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9422 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
9423 kKeyboardInputMethodClass
);
9425 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
9428 err
= SetTextServiceLanguage (slptr
);
9430 /* Seems to be needed on Mac OS X 10.2. */
9432 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
9442 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9444 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
9446 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
9448 err
= GetTextServiceLanguage (&saved_ts_language
);
9450 slptr
= &saved_ts_language
;
9452 else if (CONSP (Vmac_ts_script_language_on_focus
)
9453 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9454 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
9456 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9457 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9463 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9464 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
9465 kKeyboardInputMethodClass
);
9467 GetDefaultInputMethod (&saved_ts_component
, slptr
);
9471 err
= DeactivateTSMDocument (tsm_document_id
);
9477 #if !TARGET_API_MAC_CARBON
9479 do_apple_menu (SInt16 menu_item
)
9482 SInt16 da_driver_refnum
;
9484 if (menu_item
== I_ABOUT
)
9485 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9488 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9489 da_driver_refnum
= OpenDeskAcc (item_name
);
9492 #endif /* !TARGET_API_MAC_CARBON */
9494 /* Handle drags in size box. Based on code contributed by Ben
9495 Mesander and IM - Window Manager A. */
9498 do_grow_window (w
, e
)
9500 const EventRecord
*e
;
9503 int rows
, columns
, width
, height
;
9504 struct frame
*f
= mac_window_to_frame (w
);
9505 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
9506 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
9507 #if TARGET_API_MAC_CARBON
9513 if (size_hints
->flags
& PMinSize
)
9515 min_width
= size_hints
->min_width
;
9516 min_height
= size_hints
->min_height
;
9518 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9520 #if TARGET_API_MAC_CARBON
9521 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
9523 height
= new_rect
.bottom
- new_rect
.top
;
9524 width
= new_rect
.right
- new_rect
.left
;
9526 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9527 /* see if it really changed size */
9530 height
= HiWord (grow_size
);
9531 width
= LoWord (grow_size
);
9534 if (width
!= FRAME_PIXEL_WIDTH (f
)
9535 || height
!= FRAME_PIXEL_HEIGHT (f
))
9537 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9538 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9540 x_set_window_size (f
, 0, columns
, rows
);
9545 #if TARGET_API_MAC_CARBON
9547 mac_get_ideal_size (f
)
9550 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9551 WindowPtr w
= FRAME_MAC_WINDOW (f
);
9554 int height
, width
, columns
, rows
;
9556 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9557 ideal_size
.v
= dpyinfo
->height
;
9558 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
9559 /* Adjust the standard size according to character boundaries. */
9560 width
= standard_rect
.right
- standard_rect
.left
;
9561 height
= standard_rect
.bottom
- standard_rect
.top
;
9562 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9563 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9564 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9565 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9571 /* Handle clicks in zoom box. Calculation of "standard state" based
9572 on code in IM - Window Manager A and code contributed by Ben
9573 Mesander. The standard state of an Emacs window is 80-characters
9574 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9577 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9579 Rect zoom_rect
, port_rect
;
9581 struct frame
*f
= mac_window_to_frame (w
);
9582 #if TARGET_API_MAC_CARBON
9583 Point ideal_size
= mac_get_ideal_size (f
);
9585 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9586 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
9587 && port_rect
.left
== zoom_rect
.left
9588 && port_rect
.top
== zoom_rect
.top
)
9589 zoom_in_or_out
= inZoomIn
;
9591 zoom_in_or_out
= inZoomOut
;
9594 mac_clear_window (f
);
9596 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
9597 #else /* not TARGET_API_MAC_CARBON */
9600 int w_title_height
, rows
;
9601 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9603 GetPort (&save_port
);
9605 SetPortWindowPort (w
);
9607 /* Clear window to avoid flicker. */
9608 EraseRect (&(w
->portRect
));
9609 if (zoom_in_or_out
== inZoomOut
)
9611 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9612 LocalToGlobal (&top_left
);
9614 /* calculate height of window's title bar */
9615 w_title_height
= top_left
.v
- 1
9616 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9618 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9619 zoom_rect
= qd
.screenBits
.bounds
;
9620 zoom_rect
.top
+= w_title_height
;
9621 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9623 zoom_rect
.right
= zoom_rect
.left
9624 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9626 /* Adjust the standard size according to character boundaries. */
9627 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9629 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9631 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9635 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9637 SetPort (save_port
);
9638 #endif /* not TARGET_API_MAC_CARBON */
9640 #if !USE_CARBON_EVENTS
9641 /* retrieve window size and update application values */
9642 #if TARGET_API_MAC_CARBON
9643 GetWindowPortBounds (w
, &port_rect
);
9645 port_rect
= w
->portRect
;
9647 height
= port_rect
.bottom
- port_rect
.top
;
9648 width
= port_rect
.right
- port_rect
.left
;
9650 mac_handle_size_change (f
, width
, height
);
9651 mac_handle_origin_change (f
);
9656 mac_store_apple_event (class, id
, desc
)
9657 Lisp_Object
class, id
;
9660 struct input_event buf
;
9664 buf
.kind
= MAC_APPLE_EVENT
;
9667 XSETFRAME (buf
.frame_or_window
,
9668 mac_focus_frame (&one_mac_display_info
));
9669 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9670 is safe to use them during read_socket_hook. */
9671 buf
.arg
= mac_aedesc_to_lisp (desc
);
9672 kbd_buffer_store_event (&buf
);
9675 #if TARGET_API_MAC_CARBON
9677 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9678 event
, num_params
, names
, types
)
9681 Lisp_Object class_key
, id_key
;
9684 const EventParamName
*names
;
9685 const EventParamType
*types
;
9687 OSStatus err
= eventNotHandledErr
;
9688 Lisp_Object binding
;
9690 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9691 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9693 if (INTEGERP (binding
))
9694 err
= XINT (binding
);
9697 AppleEvent apple_event
;
9698 err
= create_apple_event_from_event_ref (event
, num_params
,
9703 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9704 AEDisposeDesc (&apple_event
);
9705 mac_wakeup_from_rne ();
9714 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9720 struct input_event buf
;
9724 buf
.kind
= DRAG_N_DROP_EVENT
;
9725 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9726 buf
.timestamp
= TickCount () * (1000 / 60);
9727 XSETINT (buf
.x
, mouse_pos
.h
);
9728 XSETINT (buf
.y
, mouse_pos
.v
);
9729 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9730 buf
.arg
= mac_aedesc_to_lisp (desc
);
9731 kbd_buffer_store_event (&buf
);
9735 #if USE_CARBON_EVENTS
9736 static pascal OSStatus
9737 mac_handle_command_event (next_handler
, event
, data
)
9738 EventHandlerCallRef next_handler
;
9742 OSStatus result
, err
;
9744 static const EventParamName names
[] =
9745 {kEventParamDirectObject
, kEventParamKeyModifiers
};
9746 static const EventParamType types
[] =
9747 {typeHICommand
, typeUInt32
};
9748 int num_params
= sizeof (names
) / sizeof (names
[0]);
9750 result
= CallNextEventHandler (next_handler
, event
);
9751 if (result
!= eventNotHandledErr
)
9754 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9755 NULL
, sizeof (HICommand
), NULL
, &command
);
9757 if (err
!= noErr
|| command
.commandID
== 0)
9758 return eventNotHandledErr
;
9760 /* A HI command event is mapped to an Apple event whose event class
9761 symbol is `hi-command' and event ID is its command ID. */
9762 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9764 event
, num_params
, names
, types
);
9765 return err
== noErr
? noErr
: eventNotHandledErr
;
9769 init_command_handler ()
9771 static const EventTypeSpec specs
[] =
9772 {{kEventClassCommand
, kEventCommandProcess
}};
9773 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9775 if (handle_command_eventUPP
== NULL
)
9776 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9777 return InstallApplicationEventHandler (handle_command_eventUPP
,
9778 GetEventTypeCount (specs
), specs
,
9782 static pascal OSStatus
9783 mac_handle_window_event (next_handler
, event
, data
)
9784 EventHandlerCallRef next_handler
;
9789 OSStatus result
, err
;
9792 XSizeHints
*size_hints
;
9794 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9795 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9797 return eventNotHandledErr
;
9799 f
= mac_window_to_frame (wp
);
9800 switch (GetEventKind (event
))
9802 case kEventWindowUpdate
:
9803 result
= CallNextEventHandler (next_handler
, event
);
9804 if (result
!= eventNotHandledErr
)
9807 do_window_update (wp
);
9810 case kEventWindowGetIdealSize
:
9811 result
= CallNextEventHandler (next_handler
, event
);
9812 if (result
!= eventNotHandledErr
)
9816 Point ideal_size
= mac_get_ideal_size (f
);
9818 err
= SetEventParameter (event
, kEventParamDimensions
,
9819 typeQDPoint
, sizeof (Point
), &ideal_size
);
9825 case kEventWindowBoundsChanging
:
9826 result
= CallNextEventHandler (next_handler
, event
);
9827 if (result
!= eventNotHandledErr
)
9830 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9831 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9835 size_hints
= FRAME_SIZE_HINTS (f
);
9836 if ((attributes
& kWindowBoundsChangeUserResize
)
9837 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9838 == (PResizeInc
| PBaseSize
| PMinSize
)))
9843 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9844 typeQDRectangle
, NULL
, sizeof (Rect
),
9849 width
= bounds
.right
- bounds
.left
;
9850 height
= bounds
.bottom
- bounds
.top
;
9852 if (width
< size_hints
->min_width
)
9853 width
= size_hints
->min_width
;
9855 width
= size_hints
->base_width
9856 + (int) ((width
- size_hints
->base_width
)
9857 / (float) size_hints
->width_inc
+ .5)
9858 * size_hints
->width_inc
;
9860 if (height
< size_hints
->min_height
)
9861 height
= size_hints
->min_height
;
9863 height
= size_hints
->base_height
9864 + (int) ((height
- size_hints
->base_height
)
9865 / (float) size_hints
->height_inc
+ .5)
9866 * size_hints
->height_inc
;
9868 bounds
.right
= bounds
.left
+ width
;
9869 bounds
.bottom
= bounds
.top
+ height
;
9870 SetEventParameter (event
, kEventParamCurrentBounds
,
9871 typeQDRectangle
, sizeof (Rect
), &bounds
);
9876 case kEventWindowBoundsChanged
:
9877 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9878 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9882 if (attributes
& kWindowBoundsChangeSizeChanged
)
9886 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9887 typeQDRectangle
, NULL
, sizeof (Rect
),
9893 width
= bounds
.right
- bounds
.left
;
9894 height
= bounds
.bottom
- bounds
.top
;
9895 mac_handle_size_change (f
, width
, height
);
9896 mac_wakeup_from_rne ();
9900 if (attributes
& kWindowBoundsChangeOriginChanged
)
9901 mac_handle_origin_change (f
);
9905 case kEventWindowShown
:
9906 case kEventWindowHidden
:
9907 case kEventWindowExpanded
:
9908 case kEventWindowCollapsed
:
9909 result
= CallNextEventHandler (next_handler
, event
);
9911 mac_handle_visibility_change (f
);
9916 case kEventWindowClose
:
9917 result
= CallNextEventHandler (next_handler
, event
);
9919 struct input_event buf
;
9922 buf
.kind
= DELETE_WINDOW_EVENT
;
9923 XSETFRAME (buf
.frame_or_window
, f
);
9925 kbd_buffer_store_event (&buf
);
9930 case kEventWindowToolbarSwitchMode
:
9931 result
= CallNextEventHandler (next_handler
, event
);
9933 static const EventParamName names
[] = {kEventParamDirectObject
,
9934 kEventParamWindowMouseLocation
,
9935 kEventParamKeyModifiers
,
9936 kEventParamMouseButton
,
9937 kEventParamClickCount
,
9938 kEventParamMouseChord
};
9939 static const EventParamType types
[] = {typeWindowRef
,
9945 int num_params
= sizeof (names
) / sizeof (names
[0]);
9947 err
= mac_store_event_ref_as_apple_event (0, 0,
9949 Qtoolbar_switch_mode
,
9953 return err
== noErr
? noErr
: result
;
9957 case kEventWindowFocusAcquired
:
9958 result
= CallNextEventHandler (next_handler
, event
);
9959 err
= mac_tsm_resume ();
9960 return err
== noErr
? noErr
: result
;
9962 case kEventWindowFocusRelinquish
:
9963 result
= CallNextEventHandler (next_handler
, event
);
9964 err
= mac_tsm_suspend ();
9965 return err
== noErr
? noErr
: result
;
9969 return eventNotHandledErr
;
9972 static pascal OSStatus
9973 mac_handle_mouse_event (next_handler
, event
, data
)
9974 EventHandlerCallRef next_handler
;
9978 OSStatus result
, err
;
9980 switch (GetEventKind (event
))
9982 case kEventMouseWheelMoved
:
9986 EventMouseWheelAxis axis
;
9990 result
= CallNextEventHandler (next_handler
, event
);
9991 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9994 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9995 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9999 f
= mac_window_to_frame (wp
);
10000 if (f
!= mac_focus_frame (&one_mac_display_info
))
10003 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
10004 typeMouseWheelAxis
, NULL
,
10005 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
10006 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
10009 err
= GetEventParameter (event
, kEventParamMouseLocation
,
10010 typeQDPoint
, NULL
, sizeof (Point
),
10015 SetPortWindowPort (wp
);
10016 GlobalToLocal (&point
);
10017 if (point
.h
< 0 || point
.v
< 0
10018 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
10019 f
->tool_bar_window
))
10022 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
10023 typeSInt32
, NULL
, sizeof (SInt32
),
10028 read_socket_inev
->kind
= WHEEL_EVENT
;
10029 read_socket_inev
->code
= 0;
10030 read_socket_inev
->modifiers
=
10031 (mac_event_to_emacs_modifiers (event
)
10032 | ((delta
< 0) ? down_modifier
: up_modifier
));
10033 XSETINT (read_socket_inev
->x
, point
.h
);
10034 XSETINT (read_socket_inev
->y
, point
.v
);
10035 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10045 return eventNotHandledErr
;
10048 #if USE_MAC_FONT_PANEL
10049 static pascal OSStatus
10050 mac_handle_font_event (next_handler
, event
, data
)
10051 EventHandlerCallRef next_handler
;
10055 OSStatus result
, err
;
10056 Lisp_Object id_key
;
10058 const EventParamName
*names
;
10059 const EventParamType
*types
;
10060 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
10061 kEventParamATSUFontSize
,
10062 kEventParamFMFontFamily
,
10063 kEventParamFMFontSize
,
10064 kEventParamFontColor
};
10065 static const EventParamType types_sel
[] = {typeATSUFontID
,
10071 result
= CallNextEventHandler (next_handler
, event
);
10072 if (result
!= eventNotHandledErr
)
10075 switch (GetEventKind (event
))
10077 case kEventFontPanelClosed
:
10078 id_key
= Qpanel_closed
;
10084 case kEventFontSelection
:
10085 id_key
= Qselection
;
10086 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
10092 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
10096 return err
== noErr
? noErr
: eventNotHandledErr
;
10101 static pascal OSStatus
10102 mac_handle_text_input_event (next_handler
, event
, data
)
10103 EventHandlerCallRef next_handler
;
10107 OSStatus result
, err
= noErr
;
10108 Lisp_Object id_key
= Qnil
;
10110 const EventParamName
*names
;
10111 const EventParamType
*types
;
10112 static UInt32 seqno_uaia
= 0;
10113 static const EventParamName names_uaia
[] =
10114 {kEventParamTextInputSendComponentInstance
,
10115 kEventParamTextInputSendRefCon
,
10116 kEventParamTextInputSendSLRec
,
10117 kEventParamTextInputSendFixLen
,
10118 kEventParamTextInputSendText
,
10119 kEventParamTextInputSendUpdateRng
,
10120 kEventParamTextInputSendHiliteRng
,
10121 kEventParamTextInputSendClauseRng
,
10122 kEventParamTextInputSendPinRng
,
10123 kEventParamTextInputSendTextServiceEncoding
,
10124 kEventParamTextInputSendTextServiceMacEncoding
,
10125 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
10126 static const EventParamType types_uaia
[] =
10127 {typeComponentInstance
,
10129 typeIntlWritingCode
,
10136 typeTextRangeArray
,
10137 typeTextRangeArray
,
10143 static const EventParamName names_ufke
[] =
10144 {kEventParamTextInputSendComponentInstance
,
10145 kEventParamTextInputSendRefCon
,
10146 kEventParamTextInputSendSLRec
,
10147 kEventParamTextInputSendText
};
10148 static const EventParamType types_ufke
[] =
10149 {typeComponentInstance
,
10151 typeIntlWritingCode
,
10154 result
= CallNextEventHandler (next_handler
, event
);
10156 switch (GetEventKind (event
))
10158 case kEventTextInputUpdateActiveInputArea
:
10159 id_key
= Qupdate_active_input_area
;
10160 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
10161 names
= names_uaia
;
10162 types
= types_uaia
;
10163 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
10164 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
10168 case kEventTextInputUnicodeForKeyEvent
:
10170 EventRef kbd_event
;
10171 UInt32 actual_size
, modifiers
;
10173 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
10174 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
10177 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
10179 sizeof (UInt32
), NULL
, &modifiers
);
10180 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
10181 /* There're mapped modifier keys. Process it in
10183 return eventNotHandledErr
;
10185 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10186 typeUnicodeText
, NULL
, 0, &actual_size
,
10188 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
10192 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10193 typeUnicodeText
, NULL
,
10194 sizeof (UniChar
), NULL
, &code
);
10195 if (err
== noErr
&& code
< 0x80)
10197 /* ASCII character. Process it in XTread_socket. */
10198 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
10202 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
10203 typeUInt32
, NULL
, sizeof (UInt32
),
10205 if (!(err
== noErr
&& key_code
<= 0x7f
10206 && keycode_to_xkeysym_table
[key_code
]))
10209 mac_focus_frame (&one_mac_display_info
);
10211 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
10212 read_socket_inev
->code
= code
;
10213 read_socket_inev
->modifiers
=
10214 mac_to_emacs_modifiers (modifiers
);
10215 read_socket_inev
->modifiers
|=
10216 (extra_keyboard_modifiers
10217 & (meta_modifier
| alt_modifier
10218 | hyper_modifier
| super_modifier
));
10219 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10222 return eventNotHandledErr
;
10226 /* Non-ASCII keystrokes without mapped modifiers are processed
10227 at the Lisp level. */
10228 id_key
= Qunicode_for_key_event
;
10229 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
10230 names
= names_ufke
;
10231 types
= types_ufke
;
10234 case kEventTextInputOffsetToPos
:
10240 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
10241 return eventNotHandledErr
;
10243 /* Strictly speaking, this is not always correct because
10244 previous events may change some states about display. */
10245 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
10247 /* Active input area is displayed in the echo area. */
10248 w
= XWINDOW (echo_area_window
);
10249 f
= WINDOW_XFRAME (w
);
10253 /* Active input area is displayed around the current point. */
10254 f
= SELECTED_FRAME ();
10255 w
= XWINDOW (f
->selected_window
);
10258 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
10259 + WINDOW_LEFT_FRINGE_WIDTH (w
));
10260 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
10261 + FONT_BASE (FRAME_FONT (f
)));
10262 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
10263 LocalToGlobal (&p
);
10264 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
10265 typeQDPoint
, sizeof (typeQDPoint
), &p
);
10273 if (!NILP (id_key
))
10274 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
10278 return err
== noErr
? noErr
: result
;
10284 mac_store_service_event (event
)
10288 Lisp_Object id_key
;
10290 const EventParamName
*names
;
10291 const EventParamType
*types
;
10292 static const EventParamName names_pfm
[] =
10293 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10294 static const EventParamType types_pfm
[] =
10295 {typeCFStringRef
, typeCFStringRef
};
10297 switch (GetEventKind (event
))
10299 case kEventServicePaste
:
10306 case kEventServicePerform
:
10308 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10317 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10323 #endif /* MAC_OSX */
10324 #endif /* USE_CARBON_EVENTS */
10328 install_window_handler (window
)
10331 OSStatus err
= noErr
;
10332 #if USE_CARBON_EVENTS
10333 static const EventTypeSpec specs_window
[] =
10334 {{kEventClassWindow
, kEventWindowUpdate
},
10335 {kEventClassWindow
, kEventWindowGetIdealSize
},
10336 {kEventClassWindow
, kEventWindowBoundsChanging
},
10337 {kEventClassWindow
, kEventWindowBoundsChanged
},
10338 {kEventClassWindow
, kEventWindowShown
},
10339 {kEventClassWindow
, kEventWindowHidden
},
10340 {kEventClassWindow
, kEventWindowExpanded
},
10341 {kEventClassWindow
, kEventWindowCollapsed
},
10342 {kEventClassWindow
, kEventWindowClose
},
10344 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
10347 {kEventClassWindow
, kEventWindowFocusAcquired
},
10348 {kEventClassWindow
, kEventWindowFocusRelinquish
},
10351 static const EventTypeSpec specs_mouse
[] =
10352 {{kEventClassMouse
, kEventMouseWheelMoved
}};
10353 static EventHandlerUPP handle_window_eventUPP
= NULL
;
10354 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
10355 #if USE_MAC_FONT_PANEL
10356 static const EventTypeSpec specs_font
[] =
10357 {{kEventClassFont
, kEventFontPanelClosed
},
10358 {kEventClassFont
, kEventFontSelection
}};
10359 static EventHandlerUPP handle_font_eventUPP
= NULL
;
10362 static const EventTypeSpec specs_text_input
[] =
10363 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
10364 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
10365 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
10366 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
10369 if (handle_window_eventUPP
== NULL
)
10370 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
10371 if (handle_mouse_eventUPP
== NULL
)
10372 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
10373 #if USE_MAC_FONT_PANEL
10374 if (handle_font_eventUPP
== NULL
)
10375 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
10378 if (handle_text_input_eventUPP
== NULL
)
10379 handle_text_input_eventUPP
=
10380 NewEventHandlerUPP (mac_handle_text_input_event
);
10382 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
10383 GetEventTypeCount (specs_window
),
10384 specs_window
, NULL
, NULL
);
10386 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
10387 GetEventTypeCount (specs_mouse
),
10388 specs_mouse
, NULL
, NULL
);
10389 #if USE_MAC_FONT_PANEL
10391 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
10392 GetEventTypeCount (specs_font
),
10393 specs_font
, NULL
, NULL
);
10397 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
10398 GetEventTypeCount (specs_text_input
),
10399 specs_text_input
, window
, NULL
);
10403 err
= install_drag_handler (window
);
10405 err
= install_menu_target_item_handler (window
);
10411 remove_window_handler (window
)
10414 remove_drag_handler (window
);
10419 mac_handle_dm_notification (event
)
10422 mac_screen_config_changed
= 1;
10426 init_dm_notification_handler ()
10429 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
10430 ProcessSerialNumber psn
;
10432 if (handle_dm_notificationUPP
== NULL
)
10433 handle_dm_notificationUPP
=
10434 NewDMNotificationUPP (mac_handle_dm_notification
);
10436 err
= GetCurrentProcess (&psn
);
10438 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
10444 mac_get_screen_info (dpyinfo
)
10445 struct mac_display_info
*dpyinfo
;
10448 /* HasDepth returns true if it is possible to have a 32 bit display,
10449 but this may not be what is actually used. Mac OSX can do better. */
10450 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
10451 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
10454 CGDisplayCount ndisps
;
10455 CGDirectDisplayID
*displays
;
10457 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
10460 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
10461 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
10465 CGRect bounds
= CGRectZero
;
10467 while (ndisps
-- > 0)
10468 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
10469 dpyinfo
->height
= CGRectGetHeight (bounds
);
10470 dpyinfo
->width
= CGRectGetWidth (bounds
);
10474 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
10475 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
10478 #else /* !MAC_OSX */
10480 GDHandle gdh
= GetMainDevice ();
10481 Rect rect
= (**gdh
).gdRect
;
10483 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
10484 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10485 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
10488 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
10489 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
10490 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
10492 dpyinfo
->height
= rect
.bottom
- rect
.top
;
10493 dpyinfo
->width
= rect
.right
- rect
.left
;
10495 #endif /* !MAC_OSX */
10501 profiler_exit_proc ()
10503 ProfilerDump ("\pEmacs.prof");
10508 /* These few functions implement Emacs as a normal Mac application
10509 (almost): set up the heap and the Toolbox, handle necessary system
10510 events plus a few simple menu events. They also set up Emacs's
10511 access to functions defined in the rest of this file. Emacs uses
10512 function hooks to perform all its terminal I/O. A complete list of
10513 these functions appear in termhooks.h. For what they do, read the
10514 comments there and see also w32term.c and xterm.c. What's
10515 noticeably missing here is the event loop, which is normally
10516 present in most Mac application. After performing the necessary
10517 Mac initializations, main passes off control to emacs_main
10518 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10519 (defined further below) to read input. This is where
10520 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10527 #if __profile__ /* is the profiler on? */
10528 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10533 /* set creator and type for files created by MSL */
10534 _fcreator
= MAC_EMACS_CREATOR_CODE
;
10538 do_init_managers ();
10542 #ifndef USE_LSB_TAG
10543 do_check_ram_size ();
10546 init_emacs_passwd_dir ();
10550 init_coercion_handler ();
10552 initialize_applescript ();
10554 init_apple_event_handler ();
10556 init_dm_notification_handler ();
10562 /* set up argv array from STR# resource */
10563 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10567 /* free up AppleScript resources on exit */
10568 atexit (terminate_applescript
);
10570 #if __profile__ /* is the profiler on? */
10571 atexit (profiler_exit_proc
);
10574 /* 3rd param "envp" never used in emacs_main */
10575 (void) emacs_main (argc
, argv
, 0);
10578 /* Never reached - real exit in Fkill_emacs */
10583 #if !USE_CARBON_EVENTS
10584 static RgnHandle mouse_region
= NULL
;
10587 mac_wait_next_event (er
, sleep_time
, dequeue
)
10592 static EventRecord er_buf
= {nullEvent
};
10593 UInt32 target_tick
, current_tick
;
10594 EventMask event_mask
;
10596 if (mouse_region
== NULL
)
10597 mouse_region
= NewRgn ();
10599 event_mask
= everyEvent
;
10600 if (!mac_ready_for_apple_events
)
10601 event_mask
-= highLevelEventMask
;
10603 current_tick
= TickCount ();
10604 target_tick
= current_tick
+ sleep_time
;
10606 if (er_buf
.what
== nullEvent
)
10607 while (!WaitNextEvent (event_mask
, &er_buf
,
10608 target_tick
- current_tick
, mouse_region
))
10610 current_tick
= TickCount ();
10611 if (target_tick
<= current_tick
)
10617 er_buf
.what
= nullEvent
;
10620 #endif /* not USE_CARBON_EVENTS */
10622 #if TARGET_API_MAC_CARBON
10624 mac_post_mouse_moved_event ()
10626 EventRef event
= NULL
;
10629 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
10630 kEventAttributeNone
, &event
);
10635 GetGlobalMouse (&mouse_pos
);
10636 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
10637 sizeof (Point
), &mouse_pos
);
10641 UInt32 modifiers
= GetCurrentKeyModifiers ();
10643 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10644 sizeof (UInt32
), &modifiers
);
10647 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10648 kEventPriorityStandard
);
10650 ReleaseEvent (event
);
10656 mac_set_unicode_keystroke_event (code
, buf
)
10658 struct input_event
*buf
;
10660 int charset_id
, c1
, c2
;
10664 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10667 else if (code
< 0x100)
10670 charset_id
= CHARSET_8_BIT_CONTROL
;
10672 charset_id
= charset_latin_iso8859_1
;
10673 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10674 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10679 charset_id
= charset_mule_unicode_0100_24ff
,
10681 else if (code
< 0x33FF)
10682 charset_id
= charset_mule_unicode_2500_33ff
,
10684 else if (code
>= 0xE000)
10685 charset_id
= charset_mule_unicode_e000_ffff
,
10687 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10688 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10689 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10694 /* Emacs calls this whenever it wants to read an input event from the
10697 XTread_socket (sd
, expected
, hold_quit
)
10699 struct input_event
*hold_quit
;
10701 struct input_event inev
;
10703 #if USE_CARBON_EVENTS
10705 EventTargetRef toolbox_dispatcher
;
10708 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10710 if (interrupt_input_blocked
)
10712 interrupt_input_pending
= 1;
10716 interrupt_input_pending
= 0;
10719 /* So people can tell when we have read the available input. */
10720 input_signal_count
++;
10724 #if USE_CARBON_EVENTS
10725 toolbox_dispatcher
= GetEventDispatcherTarget ();
10729 mac_prepare_for_quickdraw (NULL
),
10731 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10732 kEventRemoveFromQueue
, &eventRef
))
10733 #else /* !USE_CARBON_EVENTS */
10734 while (mac_wait_next_event (&er
, 0, true))
10735 #endif /* !USE_CARBON_EVENTS */
10739 unsigned long timestamp
;
10742 inev
.kind
= NO_EVENT
;
10745 #if USE_CARBON_EVENTS
10746 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10748 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10751 #if USE_CARBON_EVENTS
10752 /* Handle new events */
10753 if (!mac_convert_event_ref (eventRef
, &er
))
10755 /* There used to be a handler for the kEventMouseWheelMoved
10756 event here. But as of Mac OS X 10.4, this kind of event
10757 is not directly posted to the main event queue by
10758 two-finger scrolling on the trackpad. Instead, some
10759 private event is posted and it is converted to a wheel
10760 event by the default handler for the application target.
10761 The converted one can be received by a Carbon event
10762 handler installed on a window target. */
10763 read_socket_inev
= &inev
;
10764 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10765 read_socket_inev
= NULL
;
10768 #endif /* USE_CARBON_EVENTS */
10774 WindowPtr window_ptr
;
10775 ControlPartCode part_code
;
10776 int tool_bar_p
= 0;
10778 #if USE_CARBON_EVENTS
10779 /* This is needed to send mouse events like aqua window
10780 buttons to the correct handler. */
10781 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10782 != eventNotHandledErr
)
10785 last_mouse_glyph_frame
= 0;
10787 if (dpyinfo
->grabbed
&& last_mouse_frame
10788 && FRAME_LIVE_P (last_mouse_frame
))
10790 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10791 part_code
= inContent
;
10795 part_code
= FindWindow (er
.where
, &window_ptr
);
10796 if (tip_window
&& window_ptr
== tip_window
)
10798 HideWindow (tip_window
);
10799 part_code
= FindWindow (er
.where
, &window_ptr
);
10803 if (er
.what
!= mouseDown
&&
10804 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10810 f
= mac_focus_frame (dpyinfo
);
10811 saved_menu_event_location
= er
.where
;
10812 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10813 XSETFRAME (inev
.frame_or_window
, f
);
10818 #if TARGET_API_MAC_CARBON
10819 FrontNonFloatingWindow ()
10824 || (mac_window_to_frame (window_ptr
)
10825 != dpyinfo
->x_focus_frame
))
10826 SelectWindow (window_ptr
);
10829 ControlPartCode control_part_code
;
10831 Point mouse_loc
= er
.where
;
10833 ControlKind control_kind
;
10836 f
= mac_window_to_frame (window_ptr
);
10837 /* convert to local coordinates of new window */
10838 SetPortWindowPort (window_ptr
);
10840 GlobalToLocal (&mouse_loc
);
10841 #if TARGET_API_MAC_CARBON
10842 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10843 &control_part_code
);
10846 GetControlKind (ch
, &control_kind
);
10849 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10853 #if USE_CARBON_EVENTS
10854 inev
.code
= mac_get_mouse_btn (eventRef
);
10855 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10857 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10858 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10860 XSETINT (inev
.x
, mouse_loc
.h
);
10861 XSETINT (inev
.y
, mouse_loc
.v
);
10863 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10865 #ifndef USE_TOOLKIT_SCROLL_BARS
10866 /* control_part_code becomes kControlNoPart if
10867 a progress indicator is clicked. */
10868 && control_part_code
!= kControlNoPart
10869 #else /* USE_TOOLKIT_SCROLL_BARS */
10871 && control_kind
.kind
== kControlKindScrollBar
10872 #endif /* MAC_OSX */
10873 #endif /* USE_TOOLKIT_SCROLL_BARS */
10876 struct scroll_bar
*bar
;
10878 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10880 bar
= tracked_scroll_bar
;
10881 #ifndef USE_TOOLKIT_SCROLL_BARS
10882 control_part_code
= kControlIndicatorPart
;
10886 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10887 #ifdef USE_TOOLKIT_SCROLL_BARS
10888 /* Make the "Ctrl-Mouse-2 splits window" work
10889 for toolkit scroll bars. */
10890 if (inev
.modifiers
& ctrl_modifier
)
10891 x_scroll_bar_handle_click (bar
, control_part_code
,
10893 else if (er
.what
== mouseDown
)
10894 x_scroll_bar_handle_press (bar
, control_part_code
,
10897 x_scroll_bar_handle_release (bar
, &inev
);
10898 #else /* not USE_TOOLKIT_SCROLL_BARS */
10899 x_scroll_bar_handle_click (bar
, control_part_code
,
10901 if (er
.what
== mouseDown
10902 && control_part_code
== kControlIndicatorPart
)
10903 tracked_scroll_bar
= bar
;
10905 tracked_scroll_bar
= NULL
;
10906 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10910 Lisp_Object window
;
10911 int x
= mouse_loc
.h
;
10912 int y
= mouse_loc
.v
;
10914 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10915 if (EQ (window
, f
->tool_bar_window
))
10917 if (er
.what
== mouseDown
)
10918 handle_tool_bar_click (f
, x
, y
, 1, 0);
10920 handle_tool_bar_click (f
, x
, y
, 0,
10926 XSETFRAME (inev
.frame_or_window
, f
);
10927 inev
.kind
= MOUSE_CLICK_EVENT
;
10931 if (er
.what
== mouseDown
)
10933 dpyinfo
->grabbed
|= (1 << inev
.code
);
10934 last_mouse_frame
= f
;
10937 last_tool_bar_item
= -1;
10941 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10942 /* If a button is released though it was not
10943 previously pressed, that would be because
10944 of multi-button emulation. */
10945 dpyinfo
->grabbed
= 0;
10947 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10950 /* Ignore any mouse motion that happened before
10951 this event; any subsequent mouse-movement Emacs
10952 events should reflect only motion after the
10955 f
->mouse_moved
= 0;
10957 #ifdef USE_TOOLKIT_SCROLL_BARS
10958 if (inev
.kind
== MOUSE_CLICK_EVENT
10959 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
10960 && (inev
.modifiers
& ctrl_modifier
)))
10965 inev
.modifiers
|= down_modifier
;
10968 inev
.modifiers
|= up_modifier
;
10975 #if TARGET_API_MAC_CARBON
10977 if (IsWindowPathSelectClick (window_ptr
, &er
))
10979 WindowPathSelect (window_ptr
, NULL
, NULL
);
10982 if (part_code
== inProxyIcon
10983 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
10984 != errUserWantsToDragWindow
))
10986 DragWindow (window_ptr
, er
.where
, NULL
);
10987 #else /* not TARGET_API_MAC_CARBON */
10988 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10989 #endif /* not TARGET_API_MAC_CARBON */
10990 /* Update the frame parameters. */
10991 #if !USE_CARBON_EVENTS
10993 struct frame
*f
= mac_window_to_frame (window_ptr
);
10995 if (f
&& !f
->async_iconified
)
10996 mac_handle_origin_change (f
);
11002 if (TrackGoAway (window_ptr
, er
.where
))
11004 inev
.kind
= DELETE_WINDOW_EVENT
;
11005 XSETFRAME (inev
.frame_or_window
,
11006 mac_window_to_frame (window_ptr
));
11010 /* window resize handling added --ben */
11012 do_grow_window (window_ptr
, &er
);
11015 /* window zoom handling added --ben */
11018 if (TrackBox (window_ptr
, er
.where
, part_code
))
11019 do_zoom_window (window_ptr
, part_code
);
11029 #if USE_CARBON_EVENTS
11030 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11031 != eventNotHandledErr
)
11034 do_window_update ((WindowPtr
) er
.message
);
11039 #if USE_CARBON_EVENTS
11040 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11041 != eventNotHandledErr
)
11044 switch ((er
.message
>> 24) & 0x000000FF)
11046 case suspendResumeMessage
:
11048 if (er
.message
& resumeFlag
)
11051 mac_tsm_suspend ();
11055 case mouseMovedMessage
:
11056 #if !USE_CARBON_EVENTS
11057 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
11058 er
.where
.h
+ 1, er
.where
.v
+ 1);
11060 previous_help_echo_string
= help_echo_string
;
11061 help_echo_string
= Qnil
;
11063 if (dpyinfo
->grabbed
&& last_mouse_frame
11064 && FRAME_LIVE_P (last_mouse_frame
))
11065 f
= last_mouse_frame
;
11067 f
= dpyinfo
->x_focus_frame
;
11069 if (dpyinfo
->mouse_face_hidden
)
11071 dpyinfo
->mouse_face_hidden
= 0;
11072 clear_mouse_face (dpyinfo
);
11077 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
11078 Point mouse_pos
= er
.where
;
11080 SetPortWindowPort (wp
);
11082 GlobalToLocal (&mouse_pos
);
11084 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11085 #ifdef USE_TOOLKIT_SCROLL_BARS
11086 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
11088 #else /* not USE_TOOLKIT_SCROLL_BARS */
11089 x_scroll_bar_note_movement (tracked_scroll_bar
,
11091 - XINT (tracked_scroll_bar
->top
),
11092 er
.when
* (1000 / 60));
11093 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11096 /* Generate SELECT_WINDOW_EVENTs when needed. */
11097 if (!NILP (Vmouse_autoselect_window
))
11099 Lisp_Object window
;
11101 window
= window_from_coordinates (f
,
11106 /* Window will be selected only when it is
11107 not selected now and last mouse movement
11108 event was not in it. Minibuffer window
11109 will be selected iff it is active. */
11110 if (WINDOWP (window
)
11111 && !EQ (window
, last_window
)
11112 && !EQ (window
, selected_window
))
11114 inev
.kind
= SELECT_WINDOW_EVENT
;
11115 inev
.frame_or_window
= window
;
11118 last_window
=window
;
11120 if (!note_mouse_movement (f
, &mouse_pos
))
11121 help_echo_string
= previous_help_echo_string
;
11125 /* If the contents of the global variable
11126 help_echo_string has changed, generate a
11128 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
11136 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
11138 #if USE_CARBON_EVENTS
11139 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11140 != eventNotHandledErr
)
11143 if (window_ptr
== tip_window
)
11145 HideWindow (tip_window
);
11149 if (!is_emacs_window (window_ptr
))
11152 if ((er
.modifiers
& activeFlag
) != 0)
11154 /* A window has been activated */
11155 Point mouse_loc
= er
.where
;
11157 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11159 SetPortWindowPort (window_ptr
);
11160 GlobalToLocal (&mouse_loc
);
11161 /* Window-activated event counts as mouse movement,
11162 so update things that depend on mouse position. */
11163 note_mouse_movement (mac_window_to_frame (window_ptr
),
11168 /* A window has been deactivated */
11169 #ifdef USE_TOOLKIT_SCROLL_BARS
11170 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11172 struct input_event event
;
11174 EVENT_INIT (event
);
11175 event
.kind
= NO_EVENT
;
11176 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
11177 if (event
.kind
!= NO_EVENT
)
11179 event
.timestamp
= timestamp
;
11180 kbd_buffer_store_event_hold (&event
, hold_quit
);
11185 dpyinfo
->grabbed
= 0;
11187 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11189 f
= mac_window_to_frame (window_ptr
);
11190 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11192 /* If we move outside the frame, then we're
11193 certainly no longer on any text in the
11195 clear_mouse_face (dpyinfo
);
11196 dpyinfo
->mouse_face_mouse_frame
= 0;
11199 /* Generate a nil HELP_EVENT to cancel a help-echo.
11200 Do it only if there's something to cancel.
11201 Otherwise, the startup message is cleared when the
11202 mouse leaves the frame. */
11203 if (any_help_event_p
)
11213 int keycode
= (er
.message
& keyCodeMask
) >> 8;
11214 static SInt16 last_key_script
= -1;
11215 SInt16 current_key_script
;
11216 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
11218 #if USE_CARBON_EVENTS && defined (MAC_OSX)
11219 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
11221 sizeof (UInt32
), NULL
, &modifiers
);
11223 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
11225 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
11226 /* When using Carbon Events, we need to pass raw keyboard
11227 events to the TSM ourselves. If TSM handles it, it
11228 will pass back noErr, otherwise it will pass back
11229 "eventNotHandledErr" and we can process it
11231 if (!(mapped_modifiers
11232 & ~(mac_pass_command_to_system
? cmdKey
: 0)
11233 & ~(mac_pass_control_to_system
? controlKey
: 0)))
11237 read_socket_inev
= &inev
;
11238 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11239 read_socket_inev
= NULL
;
11240 if (err
!= eventNotHandledErr
)
11244 if (er
.what
== keyUp
)
11249 f
= mac_focus_frame (dpyinfo
);
11251 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
11252 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
11254 clear_mouse_face (dpyinfo
);
11255 dpyinfo
->mouse_face_hidden
= 1;
11258 current_key_script
= GetScriptManagerVariable (smKeyScript
);
11259 if (last_key_script
!= current_key_script
)
11261 struct input_event event
;
11263 EVENT_INIT (event
);
11264 event
.kind
= LANGUAGE_CHANGE_EVENT
;
11266 event
.code
= current_key_script
;
11267 event
.timestamp
= timestamp
;
11268 kbd_buffer_store_event (&event
);
11270 last_key_script
= current_key_script
;
11274 if (inev
.kind
!= NO_EVENT
)
11279 if (mapped_modifiers
& kEventKeyModifierFnMask
11281 && fn_keycode_to_keycode_table
[keycode
])
11282 keycode
= fn_keycode_to_keycode_table
[keycode
];
11284 if (keycode
<= 0x7f && keycode_to_xkeysym_table
[keycode
])
11286 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
11287 inev
.code
= 0xff00 | keycode_to_xkeysym_table
[keycode
];
11289 if (modifiers
& kEventKeyModifierFnMask
11291 && fn_keycode_to_keycode_table
[keycode
] == keycode
)
11292 modifiers
&= ~kEventKeyModifierFnMask
;
11295 else if (mapped_modifiers
)
11297 /* translate the keycode back to determine the
11300 UCKeyboardLayout
*uchr_ptr
= NULL
;
11301 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11303 KeyboardLayoutRef layout
;
11305 err
= KLGetCurrentKeyboardLayout (&layout
);
11307 KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
11308 (const void **) &uchr_ptr
);
11310 static SInt16 last_key_layout_id
= 0;
11311 static Handle uchr_handle
= (Handle
)-1;
11312 SInt16 current_key_layout_id
=
11313 GetScriptVariable (current_key_script
, smScriptKeys
);
11315 if (uchr_handle
== (Handle
)-1
11316 || last_key_layout_id
!= current_key_layout_id
)
11318 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
11319 last_key_layout_id
= current_key_layout_id
;
11322 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
11328 UInt16 key_action
= er
.what
- keyDown
;
11329 UInt32 modifier_key_state
=
11330 (modifiers
& ~mapped_modifiers
) >> 8;
11331 UInt32 keyboard_type
= LMGetKbdType ();
11332 SInt32 dead_key_state
= 0;
11334 UniCharCount actual_length
;
11336 status
= UCKeyTranslate (uchr_ptr
,
11337 keycode
, key_action
,
11338 modifier_key_state
,
11340 kUCKeyTranslateNoDeadKeysMask
,
11342 1, &actual_length
, &code
);
11343 if (status
== noErr
&& actual_length
== 1)
11344 mac_set_unicode_keystroke_event (code
, &inev
);
11346 #endif /* MAC_OSX */
11348 if (inev
.kind
== NO_EVENT
)
11350 /* This code comes from Keyboard Resource,
11351 Appendix C of IM - Text. This is necessary
11352 since shift is ignored in KCHR table
11353 translation when option or command is pressed.
11354 It also does not translate correctly
11355 control-shift chars like C-% so mask off shift
11357 /* Mask off modifier keys that are mapped to some
11358 Emacs modifiers. */
11359 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
11360 /* set high byte of keycode to modifier high byte*/
11361 int new_keycode
= keycode
| new_modifiers
;
11362 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
11363 unsigned long some_state
= 0;
11364 UInt32 new_char_code
;
11366 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
11368 if (new_char_code
== 0)
11369 /* Seems like a dead key. Append up-stroke. */
11370 new_char_code
= KeyTranslate (kchr_ptr
,
11371 new_keycode
| 0x80,
11375 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11376 inev
.code
= new_char_code
& 0xff;
11381 if (inev
.kind
== NO_EVENT
)
11383 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11384 inev
.code
= er
.message
& charCodeMask
;
11387 inev
.modifiers
= mac_to_emacs_modifiers (modifiers
);
11388 inev
.modifiers
|= (extra_keyboard_modifiers
11389 & (meta_modifier
| alt_modifier
11390 | hyper_modifier
| super_modifier
));
11391 XSETFRAME (inev
.frame_or_window
, f
);
11393 #if TARGET_API_MAC_CARBON
11394 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
11395 && inev
.code
>= 0x80 && inev
.modifiers
)
11398 TextEncoding encoding
= kTextEncodingMacRoman
;
11399 TextToUnicodeInfo ttu_info
;
11401 UpgradeScriptInfoToTextEncoding (current_key_script
,
11402 kTextLanguageDontCare
,
11403 kTextRegionDontCare
,
11405 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
11410 ByteCount unicode_len
;
11413 pstr
[1] = inev
.code
;
11414 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
11416 &unicode_len
, &code
);
11417 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
11418 mac_set_unicode_keystroke_event (code
, &inev
);
11419 DisposeTextToUnicodeInfo (&ttu_info
);
11426 case kHighLevelEvent
:
11427 AEProcessAppleEvent (&er
);
11433 #if USE_CARBON_EVENTS
11434 ReleaseEvent (eventRef
);
11437 if (inev
.kind
!= NO_EVENT
)
11439 inev
.timestamp
= timestamp
;
11440 kbd_buffer_store_event_hold (&inev
, hold_quit
);
11445 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
11450 XSETFRAME (frame
, f
);
11456 any_help_event_p
= 1;
11457 gen_help_event (help_echo_string
, frame
, help_echo_window
,
11458 help_echo_object
, help_echo_pos
);
11462 help_echo_string
= Qnil
;
11463 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
11470 /* If the focus was just given to an autoraising frame,
11472 /* ??? This ought to be able to handle more than one such frame. */
11473 if (pending_autoraise_frame
)
11475 x_raise_frame (pending_autoraise_frame
);
11476 pending_autoraise_frame
= 0;
11479 if (mac_screen_config_changed
)
11481 mac_get_screen_info (dpyinfo
);
11482 mac_screen_config_changed
= 0;
11485 #if !USE_CARBON_EVENTS
11486 /* Check which frames are still visible. We do this here because
11487 there doesn't seem to be any direct notification from the Window
11488 Manager that the visibility of a window has changed (at least,
11489 not in all cases). */
11491 Lisp_Object tail
, frame
;
11493 FOR_EACH_FRAME (tail
, frame
)
11495 struct frame
*f
= XFRAME (frame
);
11497 /* The tooltip has been drawn already. Avoid the
11498 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11499 if (EQ (frame
, tip_frame
))
11502 if (FRAME_MAC_P (f
))
11503 mac_handle_visibility_change (f
);
11514 /* Need to override CodeWarrior's input function so no conversion is
11515 done on newlines Otherwise compiled functions in .elc files will be
11516 read incorrectly. Defined in ...:MSL C:MSL
11517 Common:Source:buffer_io.c. */
11520 __convert_to_newlines (unsigned char * p
, size_t * n
)
11522 #pragma unused(p,n)
11526 __convert_from_newlines (unsigned char * p
, size_t * n
)
11528 #pragma unused(p,n)
11534 make_mac_terminal_frame (struct frame
*f
)
11539 XSETFRAME (frame
, f
);
11541 f
->output_method
= output_mac
;
11542 f
->output_data
.mac
= (struct mac_output
*)
11543 xmalloc (sizeof (struct mac_output
));
11544 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
11546 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
11548 FRAME_COLS (f
) = 96;
11549 FRAME_LINES (f
) = 4;
11551 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
11552 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
11554 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
11556 f
->output_data
.mac
->cursor_pixel
= 0;
11557 f
->output_data
.mac
->border_pixel
= 0x00ff00;
11558 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
11559 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
11561 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
11562 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
11563 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
11564 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
11565 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
11566 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
11568 FRAME_FONTSET (f
) = -1;
11569 f
->output_data
.mac
->explicit_parent
= 0;
11572 f
->border_width
= 0;
11574 f
->internal_border_width
= 0;
11579 f
->new_text_cols
= 0;
11580 f
->new_text_lines
= 0;
11582 SetRect (&r
, f
->left_pos
, f
->top_pos
,
11583 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
11584 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
11588 if (!(FRAME_MAC_WINDOW (f
) =
11589 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
11590 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
11592 /* so that update events can find this mac_output struct */
11593 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
11599 /* Need to be initialized for unshow_buffer in window.c. */
11600 selected_window
= f
->selected_window
;
11602 Fmodify_frame_parameters (frame
,
11603 Fcons (Fcons (Qfont
,
11604 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
11605 Fmodify_frame_parameters (frame
,
11606 Fcons (Fcons (Qforeground_color
,
11607 build_string ("black")), Qnil
));
11608 Fmodify_frame_parameters (frame
,
11609 Fcons (Fcons (Qbackground_color
,
11610 build_string ("white")), Qnil
));
11615 /***********************************************************************
11617 ***********************************************************************/
11619 static int mac_initialized
= 0;
11622 mac_make_rdb (xrm_option
)
11623 const char *xrm_option
;
11625 XrmDatabase database
;
11627 database
= xrm_get_preference_database (NULL
);
11629 xrm_merge_string_database (database
, xrm_option
);
11634 struct mac_display_info
*
11635 mac_term_init (display_name
, xrm_option
, resource_name
)
11636 Lisp_Object display_name
;
11638 char *resource_name
;
11640 struct mac_display_info
*dpyinfo
;
11644 if (!mac_initialized
)
11647 mac_initialized
= 1;
11650 if (x_display_list
)
11651 error ("Sorry, this version can only handle one display");
11653 dpyinfo
= &one_mac_display_info
;
11654 bzero (dpyinfo
, sizeof (*dpyinfo
));
11657 dpyinfo
->mac_id_name
11658 = (char *) xmalloc (SCHARS (Vinvocation_name
)
11659 + SCHARS (Vsystem_name
)
11661 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
11662 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11664 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
11665 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
11668 dpyinfo
->reference_count
= 0;
11669 dpyinfo
->resx
= 72.0;
11670 dpyinfo
->resy
= 72.0;
11672 mac_get_screen_info (dpyinfo
);
11674 dpyinfo
->grabbed
= 0;
11675 dpyinfo
->root_window
= NULL
;
11676 dpyinfo
->image_cache
= make_image_cache ();
11678 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11679 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11680 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11681 dpyinfo
->mouse_face_window
= Qnil
;
11682 dpyinfo
->mouse_face_overlay
= Qnil
;
11683 dpyinfo
->mouse_face_hidden
= 0;
11685 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11687 /* Put this display on the chain. */
11688 dpyinfo
->next
= x_display_list
;
11689 x_display_list
= dpyinfo
;
11691 /* Put it on x_display_name_list. */
11692 x_display_name_list
= Fcons (Fcons (display_name
,
11693 Fcons (Qnil
, dpyinfo
->xrdb
)),
11694 x_display_name_list
);
11695 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11702 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11705 x_delete_display (dpyinfo
)
11706 struct mac_display_info
*dpyinfo
;
11710 /* Discard this display from x_display_name_list and x_display_list.
11711 We can't use Fdelq because that can quit. */
11712 if (! NILP (x_display_name_list
)
11713 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11714 x_display_name_list
= XCDR (x_display_name_list
);
11719 tail
= x_display_name_list
;
11720 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11722 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11724 XSETCDR (tail
, XCDR (XCDR (tail
)));
11727 tail
= XCDR (tail
);
11731 if (x_display_list
== dpyinfo
)
11732 x_display_list
= dpyinfo
->next
;
11735 struct x_display_info
*tail
;
11737 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11738 if (tail
->next
== dpyinfo
)
11739 tail
->next
= tail
->next
->next
;
11742 /* Free the font names in the font table. */
11743 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11744 if (dpyinfo
->font_table
[i
].name
)
11746 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11747 xfree (dpyinfo
->font_table
[i
].full_name
);
11748 xfree (dpyinfo
->font_table
[i
].name
);
11751 if (dpyinfo
->font_table
)
11753 if (dpyinfo
->font_table
->font_encoder
)
11754 xfree (dpyinfo
->font_table
->font_encoder
);
11755 xfree (dpyinfo
->font_table
);
11757 if (dpyinfo
->mac_id_name
)
11758 xfree (dpyinfo
->mac_id_name
);
11760 if (x_display_list
== 0)
11762 mac_clear_font_name_table ();
11763 bzero (dpyinfo
, sizeof (*dpyinfo
));
11774 MenuItemIndex menu_index
;
11776 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11777 &menu
, &menu_index
);
11779 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11780 #if USE_CARBON_EVENTS
11781 EnableMenuCommand (NULL
, kHICommandPreferences
);
11782 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11783 &menu
, &menu_index
);
11786 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11787 InsertMenuItemTextWithCFString (menu
, NULL
,
11788 0, kMenuItemAttrSeparator
, 0);
11789 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11790 0, 0, kHICommandAbout
);
11792 #endif /* USE_CARBON_EVENTS */
11793 #else /* !MAC_OSX */
11794 #if USE_CARBON_EVENTS
11795 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11805 static InterfaceTypeList types
= {kUnicodeDocument
};
11807 static InterfaceTypeList types
= {kTextService
};
11810 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11811 &tsm_document_id
, 0);
11815 /* Set up use of X before we make the first connection. */
11817 extern frame_parm_handler mac_frame_parm_handlers
[];
11819 static struct redisplay_interface x_redisplay_interface
=
11821 mac_frame_parm_handlers
,
11825 x_clear_end_of_line
,
11827 x_after_update_window_line
,
11828 x_update_window_begin
,
11829 x_update_window_end
,
11833 mac_flush_display_optional
,
11835 0, /* flush_display_optional */
11837 x_clear_window_mouse_face
,
11838 x_get_glyph_overhangs
,
11839 x_fix_overlapping_area
,
11840 x_draw_fringe_bitmap
,
11842 mac_define_fringe_bitmap
,
11843 mac_destroy_fringe_bitmap
,
11845 0, /* define_fringe_bitmap */
11846 0, /* destroy_fringe_bitmap */
11848 mac_per_char_metric
,
11850 mac_compute_glyph_string_overhangs
,
11851 x_draw_glyph_string
,
11852 mac_define_frame_cursor
,
11853 mac_clear_frame_area
,
11854 mac_draw_window_cursor
,
11855 mac_draw_vertical_window_border
,
11856 mac_shift_glyphs_for_insert
11862 rif
= &x_redisplay_interface
;
11864 clear_frame_hook
= x_clear_frame
;
11865 ins_del_lines_hook
= x_ins_del_lines
;
11866 delete_glyphs_hook
= x_delete_glyphs
;
11867 ring_bell_hook
= XTring_bell
;
11868 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11869 set_terminal_modes_hook
= XTset_terminal_modes
;
11870 update_begin_hook
= x_update_begin
;
11871 update_end_hook
= x_update_end
;
11872 set_terminal_window_hook
= XTset_terminal_window
;
11873 read_socket_hook
= XTread_socket
;
11874 frame_up_to_date_hook
= XTframe_up_to_date
;
11875 mouse_position_hook
= XTmouse_position
;
11876 frame_rehighlight_hook
= XTframe_rehighlight
;
11877 frame_raise_lower_hook
= XTframe_raise_lower
;
11879 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11880 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11881 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11882 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11884 scroll_region_ok
= 1; /* we'll scroll partial frames */
11885 char_ins_del_ok
= 1;
11886 line_ins_del_ok
= 1; /* we'll just blt 'em */
11887 fast_clear_end_of_line
= 1; /* X does this well */
11888 memory_below_frame
= 0; /* we don't remember what scrolls
11892 last_tool_bar_item
= -1;
11893 any_help_event_p
= 0;
11895 /* Try to use interrupt input; if we can't, then start polling. */
11896 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11900 #if TARGET_API_MAC_CARBON
11902 #if USE_CARBON_EVENTS
11904 init_service_handler ();
11905 #endif /* MAC_OSX */
11907 init_command_handler ();
11914 #endif /* USE_CARBON_EVENTS */
11917 init_coercion_handler ();
11919 init_apple_event_handler ();
11921 init_dm_notification_handler ();
11923 if (!inhibit_window_system
)
11925 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
11927 SetFrontProcess (&psn
);
11935 mac_init_fringe ();
11946 staticpro (&x_error_message_string
);
11947 x_error_message_string
= Qnil
;
11950 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11951 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11952 Qalt
= intern ("alt"); staticpro (&Qalt
);
11953 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
11954 Qsuper
= intern ("super"); staticpro (&Qsuper
);
11955 Qmodifier_value
= intern ("modifier-value");
11956 staticpro (&Qmodifier_value
);
11958 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
11959 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11960 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11961 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11962 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11964 #if USE_CARBON_EVENTS
11965 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
11967 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
11968 staticpro (&Qtoolbar_switch_mode
);
11969 #if USE_MAC_FONT_PANEL
11970 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
11971 Qselection
= intern ("selection"); staticpro (&Qselection
);
11974 Qservice
= intern ("service"); staticpro (&Qservice
);
11975 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
11976 Qperform
= intern ("perform"); staticpro (&Qperform
);
11979 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
11980 Qupdate_active_input_area
= intern ("update-active-input-area");
11981 staticpro (&Qupdate_active_input_area
);
11982 Qunicode_for_key_event
= intern ("unicode-for-key-event");
11983 staticpro (&Qunicode_for_key_event
);
11988 Fprovide (intern ("mac-carbon"), Qnil
);
11991 staticpro (&Qreverse
);
11992 Qreverse
= intern ("reverse");
11994 staticpro (&x_display_name_list
);
11995 x_display_name_list
= Qnil
;
11997 staticpro (&last_mouse_scroll_bar
);
11998 last_mouse_scroll_bar
= Qnil
;
12000 staticpro (&fm_font_family_alist
);
12001 fm_font_family_alist
= Qnil
;
12004 staticpro (&atsu_font_id_hash
);
12005 atsu_font_id_hash
= Qnil
;
12007 staticpro (&fm_style_face_attributes_alist
);
12008 fm_style_face_attributes_alist
= Qnil
;
12012 staticpro (&saved_ts_script_language_on_focus
);
12013 saved_ts_script_language_on_focus
= Qnil
;
12016 /* We don't yet support this, but defining this here avoids whining
12017 from cus-start.el and other places, like "M-x set-variable". */
12018 DEFVAR_BOOL ("x-use-underline-position-properties",
12019 &x_use_underline_position_properties
,
12020 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12021 A value of nil means ignore them. If you encounter fonts with bogus
12022 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12023 to 4.1, set this to nil.
12025 NOTE: Not supported on Mac yet. */);
12026 x_use_underline_position_properties
= 0;
12028 DEFVAR_BOOL ("x-underline-at-descent-line",
12029 &x_underline_at_descent_line
,
12030 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12031 A value of nil means to draw the underline according to the value of the
12032 variable `x-use-underline-position-properties', which is usually at the
12033 baseline level. The default value is nil. */);
12034 x_underline_at_descent_line
= 0;
12036 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12037 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12038 #ifdef USE_TOOLKIT_SCROLL_BARS
12039 Vx_toolkit_scroll_bars
= Qt
;
12041 Vx_toolkit_scroll_bars
= Qnil
;
12044 staticpro (&last_mouse_motion_frame
);
12045 last_mouse_motion_frame
= Qnil
;
12047 /* Variables to configure modifier key assignment. */
12049 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12050 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12051 The value can be `control', `meta', `alt', `hyper', or `super' for the
12052 respective modifier. The default is `control'. */);
12053 Vmac_control_modifier
= Qcontrol
;
12055 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12056 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12057 The value can be `control', `meta', `alt', `hyper', or `super' for the
12058 respective modifier. If the value is nil then the key will act as the
12059 normal Mac control modifier, and the option key can be used to compose
12060 characters depending on the chosen Mac keyboard setting. */);
12061 Vmac_option_modifier
= Qnil
;
12063 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12064 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12065 The value can be `control', `meta', `alt', `hyper', or `super' for the
12066 respective modifier. The default is `meta'. */);
12067 Vmac_command_modifier
= Qmeta
;
12069 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12070 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12071 The value can be `control', `meta', `alt', `hyper', or `super' for the
12072 respective modifier. Note that remapping the function key may lead to
12073 unexpected results for some keys on non-US/GB keyboards. */);
12074 Vmac_function_modifier
= Qnil
;
12076 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12077 &Vmac_emulate_three_button_mouse
,
12078 doc
: /* *Specify a way of three button mouse emulation.
12079 The value can be nil, t, or the symbol `reverse'.
12080 A value of nil means that no emulation should be done and the modifiers
12081 should be placed on the mouse-1 event.
12082 t means that when the option-key is held down while pressing the mouse
12083 button, the click will register as mouse-2 and while the command-key
12084 is held down, the click will register as mouse-3.
12085 The symbol `reverse' means that the option-key will register for
12086 mouse-3 and the command-key will register for mouse-2. */);
12087 Vmac_emulate_three_button_mouse
= Qnil
;
12089 #if USE_CARBON_EVENTS
12090 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12091 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12092 Otherwise, the right click will be treated as mouse-2 and the wheel
12093 button will be mouse-3. */);
12094 mac_wheel_button_is_mouse_2
= 1;
12096 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12097 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12098 mac_pass_command_to_system
= 1;
12100 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12101 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12102 mac_pass_control_to_system
= 1;
12106 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
12107 doc
: /* *If non-nil, allow anti-aliasing.
12108 The text will be rendered using Core Graphics text rendering which
12109 may anti-alias the text. */);
12111 mac_use_core_graphics
= 1;
12113 mac_use_core_graphics
= 0;
12116 /* Register an entry for `mac-roman' so that it can be used when
12117 creating the terminal frame on Mac OS 9 before loading
12118 term/mac-win.elc. */
12119 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
12120 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
12121 Each entry should be of the form:
12123 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12125 where CHARSET-NAME is a string used in font names to identify the
12126 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12127 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12128 Vmac_charset_info_alist
=
12129 Fcons (list3 (build_string ("mac-roman"),
12130 make_number (smRoman
), Qnil
), Qnil
);
12133 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
12134 doc
: /* Overlay used to display Mac TSM active input area. */);
12135 Vmac_ts_active_input_overlay
= Qnil
;
12137 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
12138 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
12139 If the value is t, the input script and language are restored to those
12140 used in the last focus frame. If the value is a pair of integers, the
12141 input script and language codes, which are defined in the Script
12142 Manager, are set to its car and cdr parts, respectively. Otherwise,
12143 Emacs doesn't set them and thus follows the system default behavior. */);
12144 Vmac_ts_script_language_on_focus
= Qnil
;
12148 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12149 (do not change this comment) */