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"
88 #include "character.h"
93 /* Non-nil means Emacs uses toolkit scroll bars. */
95 Lisp_Object Vx_toolkit_scroll_bars
;
97 /* If non-zero, the text will be rendered using Core Graphics text
98 rendering which may anti-alias the text. */
99 int mac_use_core_graphics
;
102 /* Non-zero means that a HELP_EVENT has been generated since Emacs
105 static int any_help_event_p
;
107 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
108 static Lisp_Object last_window
;
110 /* Non-zero means make use of UNDERLINE_POSITION font properties.
111 (Not yet supported.) */
112 int x_use_underline_position_properties
;
114 /* Non-zero means to draw the underline at the same place as the descent line. */
116 int x_underline_at_descent_line
;
118 /* This is a chain of structures for all the X displays currently in
121 struct x_display_info
*x_display_list
;
123 /* This is a list of cons cells, each of the form (NAME
124 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
125 x_display_list and in the same order. NAME is the name of the
126 frame. FONT-LIST-CACHE records previous values returned by
127 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
128 equivalent, which is implemented with a Lisp object, for the
131 Lisp_Object x_display_name_list
;
133 /* This is display since Mac does not support multiple ones. */
134 struct mac_display_info one_mac_display_info
;
136 /* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the XT functions.
138 It is zero while not inside an update. In that case, the XT
139 functions assume that `selected_frame' is the frame to apply to. */
141 extern struct frame
*updating_frame
;
143 /* This is a frame waiting to be auto-raised, within XTread_socket. */
145 struct frame
*pending_autoraise_frame
;
149 Formerly, we used PointerMotionHintMask (in standard_event_mask)
150 so that we would have to call XQueryPointer after each MotionNotify
151 event to ask for another such event. However, this made mouse tracking
152 slow, and there was a bug that made it eventually stop.
154 Simply asking for MotionNotify all the time seems to work better.
156 In order to avoid asking for motion events and then throwing most
157 of them away or busy-polling the server for mouse positions, we ask
158 the server for pointer motion hints. This means that we get only
159 one event per group of mouse movements. "Groups" are delimited by
160 other kinds of events (focus changes and button clicks, for
161 example), or by XQueryPointer calls; when one of these happens, we
162 get another MotionNotify event the next time the mouse moves. This
163 is at least as efficient as getting motion events when mouse
164 tracking is on, and I suspect only negligibly worse when tracking
167 /* Where the mouse was last time we reported a mouse event. */
169 static Rect last_mouse_glyph
;
170 static FRAME_PTR last_mouse_glyph_frame
;
172 /* The scroll bar in which the last X motion event occurred.
174 If the last X motion event occurred in a scroll bar, we set this so
175 XTmouse_position can know whether to report a scroll bar motion or
178 If the last X motion event didn't occur in a scroll bar, we set
179 this to Qnil, to tell XTmouse_position to return an ordinary motion
182 static Lisp_Object last_mouse_scroll_bar
;
184 /* This is a hack. We would really prefer that XTmouse_position would
185 return the time associated with the position it returns, but there
186 doesn't seem to be any way to wrest the time-stamp from the server
187 along with the position query. So, we just keep track of the time
188 of the last movement we received, and return that in hopes that
189 it's somewhat accurate. */
191 static Time last_mouse_movement_time
;
193 struct scroll_bar
*tracked_scroll_bar
= NULL
;
195 /* Incremented by XTread_socket whenever it really tries to read
199 static int volatile input_signal_count
;
201 static int input_signal_count
;
204 extern Lisp_Object Vsystem_name
;
206 extern Lisp_Object Qeql
;
208 /* A mask of extra modifier bits to put into every keyboard char. */
210 extern EMACS_INT extra_keyboard_modifiers
;
212 /* The keysyms to use for the various modifiers. */
214 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
216 extern int inhibit_window_system
;
218 #if __MRC__ && !TARGET_API_MAC_CARBON
219 QDGlobals qd
; /* QuickDraw global information structure. */
222 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
224 struct mac_display_info
*mac_display_info_for_display (Display
*);
225 static void x_update_window_end
P_ ((struct window
*, int, int));
226 int x_catch_errors
P_ ((Display
*));
227 void x_uncatch_errors
P_ ((Display
*, int));
228 void x_lower_frame
P_ ((struct frame
*));
229 void x_scroll_bar_clear
P_ ((struct frame
*));
230 int x_had_errors_p
P_ ((Display
*));
231 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
232 void x_raise_frame
P_ ((struct frame
*));
233 void x_set_window_size
P_ ((struct frame
*, int, int, int));
234 void x_wm_set_window_state
P_ ((struct frame
*, int));
235 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
236 void mac_initialize
P_ ((void));
237 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
238 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
239 static void x_update_end
P_ ((struct frame
*));
240 static void XTframe_up_to_date
P_ ((struct frame
*));
241 static void XTset_terminal_modes
P_ ((void));
242 static void XTreset_terminal_modes
P_ ((void));
243 static void x_clear_frame
P_ ((void));
244 static void frame_highlight
P_ ((struct frame
*));
245 static void frame_unhighlight
P_ ((struct frame
*));
246 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
247 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
248 struct frame
*, struct input_event
*));
249 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
251 struct input_event
*));
252 static void XTframe_rehighlight
P_ ((struct frame
*));
253 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
254 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
255 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
256 enum text_cursor_kinds
));
258 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
259 static void x_flush
P_ ((struct frame
*f
));
260 static void x_update_begin
P_ ((struct frame
*));
261 static void x_update_window_begin
P_ ((struct window
*));
262 static void x_after_update_window_line
P_ ((struct glyph_row
*));
263 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
264 enum scroll_bar_part
*,
265 Lisp_Object
*, Lisp_Object
*,
268 static int is_emacs_window
P_ ((WindowPtr
));
269 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
270 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
272 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
273 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
274 #define GC_FONT(gc) ((gc)->xgcv.font)
275 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
277 #define CG_SET_FILL_COLOR(context, color) \
278 CGContextSetRGBFillColor (context, \
279 RED_FROM_ULONG (color) / 255.0f, \
280 GREEN_FROM_ULONG (color) / 255.0f, \
281 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
282 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
283 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
284 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
286 if (CGColorGetTypeID != NULL) \
287 CGContextSetFillColorWithColor (context, cg_color); \
289 CG_SET_FILL_COLOR (context, color); \
292 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
293 CGContextSetFillColorWithColor (context, cg_color)
296 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
297 CG_SET_FILL_COLOR (context, color)
299 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
300 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
302 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
303 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
307 #define CG_SET_STROKE_COLOR(context, color) \
308 CGContextSetRGBStrokeColor (context, \
309 RED_FROM_ULONG (color) / 255.0f, \
310 GREEN_FROM_ULONG (color) / 255.0f, \
311 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
312 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
313 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
314 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
316 if (CGColorGetTypeID != NULL) \
317 CGContextSetStrokeColorWithColor (context, cg_color); \
319 CG_SET_STROKE_COLOR (context, color); \
322 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
323 CGContextSetStrokeColorWithColor (context, cg_color)
326 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
327 CG_SET_STROKE_COLOR (context, color)
329 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
330 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
334 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
336 /* Fringe bitmaps. */
338 static int max_fringe_bmp
= 0;
339 static CGImageRef
*fringe_bmp
= 0;
341 static CGColorSpaceRef mac_cg_color_space_rgb
;
342 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
343 static CGColorRef mac_cg_color_black
;
349 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
350 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
351 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
352 /* Don't check the availability of CGColorCreate; this symbol is
353 defined even in Mac OS X 10.1. */
354 if (CGColorGetTypeID
!= NULL
)
357 float rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
359 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
365 mac_begin_cg_clip (f
, gc
)
369 CGContextRef context
= FRAME_CG_CONTEXT (f
);
373 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
374 FRAME_CG_CONTEXT (f
) = context
;
377 CGContextSaveGState (context
);
378 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
379 CGContextScaleCTM (context
, 1, -1);
380 if (gc
&& gc
->n_clip_rects
)
381 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
390 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
394 mac_prepare_for_quickdraw (f
)
399 Lisp_Object rest
, frame
;
400 FOR_EACH_FRAME (rest
, frame
)
401 if (FRAME_MAC_P (XFRAME (frame
)))
402 mac_prepare_for_quickdraw (XFRAME (frame
));
406 CGContextRef context
= FRAME_CG_CONTEXT (f
);
410 CGContextSynchronize (context
);
411 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
412 &FRAME_CG_CONTEXT (f
));
418 static RgnHandle saved_port_clip_region
= NULL
;
424 static RgnHandle new_region
= NULL
;
426 if (saved_port_clip_region
== NULL
)
427 saved_port_clip_region
= NewRgn ();
428 if (new_region
== NULL
)
429 new_region
= NewRgn ();
431 if (gc
->n_clip_rects
)
433 GetClip (saved_port_clip_region
);
434 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
435 SetClip (new_region
);
443 if (gc
->n_clip_rects
)
444 SetClip (saved_port_clip_region
);
448 /* X display function emulation */
451 XFreePixmap (display
, pixmap
)
452 Display
*display
; /* not used */
455 DisposeGWorld (pixmap
);
459 /* Mac version of XDrawLine. */
462 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
468 CGContextRef context
;
469 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
472 gx1
+= 0.5f
, gx2
+= 0.5f
;
474 gy1
+= 0.5f
, gy2
+= 0.5f
;
476 context
= mac_begin_cg_clip (f
, gc
);
477 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
478 CGContextBeginPath (context
);
479 CGContextMoveToPoint (context
, gx1
, gy1
);
480 CGContextAddLineToPoint (context
, gx2
, gy2
);
481 CGContextClosePath (context
);
482 CGContextStrokePath (context
);
500 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
502 RGBForeColor (GC_FORE_COLOR (gc
));
511 /* Mac version of XDrawLine (to Pixmap). */
514 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
538 GetGWorld (&old_port
, &old_gdh
);
541 RGBForeColor (GC_FORE_COLOR (gc
));
543 LockPixels (GetGWorldPixMap (p
));
546 UnlockPixels (GetGWorldPixMap (p
));
548 SetGWorld (old_port
, old_gdh
);
553 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
557 unsigned int width
, height
;
560 CGContextRef context
;
562 context
= mac_begin_cg_clip (f
, gc
);
563 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
564 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
569 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
571 RGBBackColor (GC_BACK_COLOR (gc
));
572 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
578 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
583 /* Mac version of XClearArea. */
586 mac_clear_area (f
, x
, y
, width
, height
)
589 unsigned int width
, height
;
591 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
594 /* Mac version of XClearWindow. */
601 CGContextRef context
;
602 GC gc
= FRAME_NORMAL_GC (f
);
604 context
= mac_begin_cg_clip (f
, NULL
);
605 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
606 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
607 FRAME_PIXEL_HEIGHT (f
)));
610 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
612 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
614 #if TARGET_API_MAC_CARBON
618 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
621 #else /* not TARGET_API_MAC_CARBON */
622 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
623 #endif /* not TARGET_API_MAC_CARBON */
628 /* Mac replacement for XCopyArea. */
632 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
633 dest_x
, dest_y
, overlay_p
)
638 unsigned int width
, height
;
639 int dest_x
, dest_y
, overlay_p
;
641 CGContextRef context
;
642 float port_height
= FRAME_PIXEL_HEIGHT (f
);
643 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
645 context
= mac_begin_cg_clip (f
, gc
);
648 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
649 CGContextFillRect (context
, dest_rect
);
651 CGContextClipToRect (context
, dest_rect
);
652 CGContextScaleCTM (context
, 1, -1);
653 CGContextTranslateCTM (context
, 0, -port_height
);
654 if (CGImageIsMask (image
))
655 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
656 CGContextDrawImage (context
,
657 CGRectMake (dest_x
- src_x
,
658 port_height
- (dest_y
- src_y
659 + CGImageGetHeight (image
)),
660 CGImageGetWidth (image
),
661 CGImageGetHeight (image
)),
666 #else /* !USE_CG_DRAWING */
669 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
672 int x
, y
, width
, height
;
673 unsigned short *bits
;
679 bitmap
.rowBytes
= sizeof(unsigned short);
680 bitmap
.baseAddr
= (char *)bits
;
681 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
683 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
685 RGBForeColor (GC_FORE_COLOR (gc
));
686 RGBBackColor (GC_BACK_COLOR (gc
));
687 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
690 #if TARGET_API_MAC_CARBON
696 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
697 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
698 UnlockPortBits (port
);
700 #else /* not TARGET_API_MAC_CARBON */
701 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
702 overlay_p
? srcOr
: srcCopy
, 0);
703 #endif /* not TARGET_API_MAC_CARBON */
706 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
708 #endif /* !USE_CG_DRAWING */
711 /* Mac replacement for XCreateBitmapFromBitmapData. */
714 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
719 static const unsigned char swap_nibble
[16]
720 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
721 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
722 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
723 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
727 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
728 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
729 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
730 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
731 for (i
= 0; i
< h
; i
++)
733 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
734 for (j
= 0; j
< w1
; j
++)
736 /* Bitswap XBM bytes to match how Mac does things. */
737 unsigned char c
= *bits
++;
738 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
739 | (swap_nibble
[(c
>>4) & 0xf]));
743 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
748 mac_free_bitmap (bitmap
)
751 xfree (bitmap
->baseAddr
);
756 XCreatePixmap (display
, w
, width
, height
, depth
)
757 Display
*display
; /* not used */
759 unsigned int width
, height
;
766 SetPortWindowPort (w
);
768 SetRect (&r
, 0, 0, width
, height
);
769 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
772 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
773 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
775 /* CreateCGImageFromPixMaps requires ARGB format. */
776 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
785 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
786 Display
*display
; /* not used */
789 unsigned int width
, height
;
790 unsigned long fg
, bg
;
797 static GC gc
= NULL
; /* not reentrant */
800 gc
= XCreateGC (display
, w
, 0, NULL
);
802 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
806 GetGWorld (&old_port
, &old_gdh
);
807 SetGWorld (pixmap
, NULL
);
808 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
809 XSetForeground (display
, gc
, fg
);
810 XSetBackground (display
, gc
, bg
);
811 RGBForeColor (GC_FORE_COLOR (gc
));
812 RGBBackColor (GC_BACK_COLOR (gc
));
813 LockPixels (GetGWorldPixMap (pixmap
));
814 #if TARGET_API_MAC_CARBON
815 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
816 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
817 #else /* not TARGET_API_MAC_CARBON */
818 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
819 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
820 #endif /* not TARGET_API_MAC_CARBON */
821 UnlockPixels (GetGWorldPixMap (pixmap
));
822 SetGWorld (old_port
, old_gdh
);
823 mac_free_bitmap (&bitmap
);
829 /* Mac replacement for XFillRectangle. */
832 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
836 unsigned int width
, height
;
839 CGContextRef context
;
841 context
= mac_begin_cg_clip (f
, gc
);
842 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
843 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
848 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
850 RGBForeColor (GC_FORE_COLOR (gc
));
851 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
854 PaintRect (&r
); /* using foreground color of gc */
860 /* Mac replacement for XDrawRectangle: dest is a window. */
863 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
867 unsigned int width
, height
;
870 CGContextRef context
;
872 context
= mac_begin_cg_clip (f
, gc
);
873 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
874 CGContextStrokeRect (context
,
875 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
880 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
882 RGBForeColor (GC_FORE_COLOR (gc
));
883 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
886 FrameRect (&r
); /* using foreground color of gc */
894 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
895 ConstUniCharArrayPtr text
;
896 UniCharCount text_length
;
898 ATSUTextLayout
*text_layout
;
901 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
903 if (saved_text_layout
== NULL
)
905 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
906 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
907 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
908 static ATSLineLayoutOptions line_layout
=
909 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
910 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
911 | kATSLineUseQDRendering
913 kATSLineIsDisplayOnly
| kATSLineFractDisable
916 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
918 err
= ATSUCreateTextLayoutWithTextPtr (text
,
919 kATSUFromTextBeginning
,
925 err
= ATSUSetLayoutControls (saved_text_layout
,
926 sizeof (tags
) / sizeof (tags
[0]),
927 tags
, sizes
, values
);
928 /* XXX: Should we do this? */
930 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
934 err
= ATSUSetRunStyle (saved_text_layout
, style
,
935 kATSUFromTextBeginning
, kATSUToTextEnd
);
937 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
938 kATSUFromTextBeginning
,
944 *text_layout
= saved_text_layout
;
951 mac_invert_rectangle (f
, x
, y
, width
, height
)
954 unsigned int width
, height
;
959 mac_prepare_for_quickdraw (f
);
961 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
963 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
970 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
971 overstrike_p
, bytes_per_char
)
976 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
978 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
981 if (GC_FONT (gc
)->mac_style
)
984 ATSUTextLayout text_layout
;
986 xassert (bytes_per_char
== 2);
988 #ifndef WORDS_BIG_ENDIAN
991 UniChar
*text
= (UniChar
*)buf
;
993 for (i
= 0; i
< nchars
; i
++)
994 text
[i
] = EndianU16_BtoN (text
[i
]);
997 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
999 GC_FONT (gc
)->mac_style
,
1004 if (!mac_use_core_graphics
)
1008 mac_prepare_for_quickdraw (f
);
1010 mac_begin_clip (gc
);
1011 RGBForeColor (GC_FORE_COLOR (gc
));
1016 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1017 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1018 RGBBackColor (GC_BACK_COLOR (gc
));
1020 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1023 ATSUDrawText (text_layout
,
1024 kATSUFromTextBeginning
, kATSUToTextEnd
,
1025 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1029 ATSUDrawText (text_layout
,
1030 kATSUFromTextBeginning
, kATSUToTextEnd
,
1031 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1039 static CGContextRef context
;
1040 float port_height
= FRAME_PIXEL_HEIGHT (f
);
1041 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1042 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1043 static const ATSUAttributeValuePtr values
[] = {&context
};
1046 context
= mac_begin_cg_clip (f
, gc
);
1049 QDBeginCGContext (port
, &context
);
1050 if (gc
->n_clip_rects
|| bg_width
)
1052 CGContextTranslateCTM (context
, 0, port_height
);
1053 CGContextScaleCTM (context
, 1, -1);
1054 if (gc
->n_clip_rects
)
1055 CGContextClipToRects (context
, gc
->clip_rects
,
1060 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1063 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
1064 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1066 CGContextScaleCTM (context
, 1, -1);
1067 CGContextTranslateCTM (context
, 0, -port_height
);
1071 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1072 err
= ATSUSetLayoutControls (text_layout
,
1073 sizeof (tags
) / sizeof (tags
[0]),
1074 tags
, sizes
, values
);
1077 ATSUDrawText (text_layout
,
1078 kATSUFromTextBeginning
, kATSUToTextEnd
,
1079 Long2Fix (x
), Long2Fix (port_height
- y
));
1081 ATSUDrawText (text_layout
,
1082 kATSUFromTextBeginning
, kATSUToTextEnd
,
1083 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1086 mac_end_cg_clip (f
);
1089 CGContextSynchronize (context
);
1090 QDEndCGContext (port
, &context
);
1093 /* This doesn't work on Mac OS X 10.1. */
1094 ATSUClearLayoutControls (text_layout
,
1095 sizeof (tags
) / sizeof (tags
[0]), tags
);
1097 ATSUSetLayoutControls (text_layout
,
1098 sizeof (tags
) / sizeof (tags
[0]),
1099 tags
, sizes
, values
);
1102 #endif /* MAC_OSX */
1105 #endif /* USE_ATSUI */
1107 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1110 if (mac_use_core_graphics
)
1111 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1114 mac_prepare_for_quickdraw (f
);
1116 mac_begin_clip (gc
);
1117 RGBForeColor (GC_FORE_COLOR (gc
));
1121 RGBBackColor (GC_BACK_COLOR (gc
));
1127 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1129 - Screen is double-buffered. (In srcCopy mode, a text is
1130 drawn into an offscreen graphics world first. So
1131 performance gain cannot be expected.)
1132 - It lowers rendering quality.
1133 - Some fonts leave garbage on cursor movement. */
1138 RGBBackColor (GC_BACK_COLOR (gc
));
1139 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1140 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1145 TextFont (GC_FONT (gc
)->mac_fontnum
);
1146 TextSize (GC_FONT (gc
)->mac_fontsize
);
1147 TextFace (GC_FONT (gc
)->mac_fontface
);
1149 DrawText (buf
, 0, nchars
* bytes_per_char
);
1154 DrawText (buf
, 0, nchars
* bytes_per_char
);
1157 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1160 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1161 if (mac_use_core_graphics
)
1162 SwapQDTextFlags(savedFlags
);
1168 /* Mac replacement for XDrawImageString. */
1171 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1176 int nchars
, bg_width
, overstrike_p
;
1178 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1183 /* Mac replacement for XDrawImageString16. */
1186 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1191 int nchars
, bg_width
, overstrike_p
;
1193 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1198 /* Mac replacement for XQueryTextExtents, but takes a character. If
1199 STYLE is NULL, measurement is done by QuickDraw Text routines for
1200 the font of the current graphics port. If CG_GLYPH is not NULL,
1201 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1204 mac_query_char_extents (style
, c
,
1205 font_ascent_return
, font_descent_return
,
1206 overall_return
, cg_glyph
)
1213 int *font_ascent_return
, *font_descent_return
;
1214 XCharStruct
*overall_return
;
1215 #if USE_CG_TEXT_DRAWING
1221 OSStatus err
= noErr
;
1228 ATSUTextLayout text_layout
;
1231 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1233 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1235 ATSTrapezoid glyph_bounds
;
1237 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1238 kATSUFromTextBeginning
, kATSUToTextEnd
,
1239 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1240 kATSUseFractionalOrigins
,
1242 kATSUseDeviceOrigins
,
1244 1, &glyph_bounds
, NULL
);
1247 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1248 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1250 width
= Fix2Long (glyph_bounds
.upperRight
.x
1251 - glyph_bounds
.upperLeft
.x
);
1252 if (font_ascent_return
)
1253 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1254 if (font_descent_return
)
1255 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1258 if (err
== noErr
&& overall_return
)
1260 err
= ATSUMeasureTextImage (text_layout
,
1261 kATSUFromTextBeginning
, kATSUToTextEnd
,
1262 0, 0, &char_bounds
);
1264 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1265 #if USE_CG_TEXT_DRAWING
1266 if (err
== noErr
&& cg_glyph
)
1269 ATSUGlyphInfoArray glyph_info_array
;
1270 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1272 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1273 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1275 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1276 kATSUToTextEnd
, &count
,
1279 /* Make sure that we don't have to make layout
1281 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1282 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1283 && glyph_info_array
.glyphs
[0].screenX
== 0)
1285 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1286 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1297 if (font_ascent_return
|| font_descent_return
)
1301 GetFontInfo (&font_info
);
1302 if (font_ascent_return
)
1303 *font_ascent_return
= font_info
.ascent
;
1304 if (font_descent_return
)
1305 *font_descent_return
= font_info
.descent
;
1311 width
= CharWidth (ch
);
1312 QDTextBounds (1, &ch
, &char_bounds
);
1313 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1321 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1324 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1325 XFontStruct
*font_struct
;
1328 XCharStruct
*overall_return
;
1331 short width
= 0, lbearing
= 0, rbearing
= 0;
1334 for (i
= 0; i
< nchars
; i
++)
1336 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1338 width
+= FONT_WIDTH (font_struct
);
1341 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1342 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1343 width
+= pcm
->width
;
1348 overall_return
->lbearing
= lbearing
;
1349 overall_return
->rbearing
= rbearing
;
1350 overall_return
->width
= width
;
1352 /* What's the meaning of the return value of XTextExtents16? */
1356 #if USE_CG_TEXT_DRAWING
1357 static int cg_text_anti_aliasing_threshold
= 8;
1360 init_cg_text_anti_aliasing_threshold ()
1366 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1367 kCFPreferencesCurrentApplication
,
1370 cg_text_anti_aliasing_threshold
= threshold
;
1374 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1379 int nchars
, bg_width
, overstrike_p
;
1382 float port_height
, gx
, gy
;
1384 CGContextRef context
;
1388 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1391 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1392 port_height
= FRAME_PIXEL_HEIGHT (f
);
1394 gy
= port_height
- y
;
1395 glyphs
= (CGGlyph
*)buf
;
1396 advances
= alloca (sizeof (CGSize
) * nchars
);
1397 if (advances
== NULL
)
1399 for (i
= 0; i
< nchars
; i
++)
1401 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1403 advances
[i
].width
= pcm
->width
;
1404 advances
[i
].height
= 0;
1405 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1410 context
= mac_begin_cg_clip (f
, gc
);
1412 QDBeginCGContext (port
, &context
);
1413 if (gc
->n_clip_rects
|| bg_width
)
1415 CGContextTranslateCTM (context
, 0, port_height
);
1416 CGContextScaleCTM (context
, 1, -1);
1417 if (gc
->n_clip_rects
)
1418 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1422 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1425 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1426 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1428 CGContextScaleCTM (context
, 1, -1);
1429 CGContextTranslateCTM (context
, 0, -port_height
);
1433 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1434 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1435 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1436 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1437 CGContextSetShouldAntialias (context
, false);
1438 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1439 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1440 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1443 CGContextSetTextPosition (context
, gx
, gy
);
1444 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1447 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1448 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1451 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1454 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1455 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1457 for (i
= 0; i
< nchars
; i
++)
1459 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1461 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1462 gx
+= advances
[i
].width
;
1467 mac_end_cg_clip (f
);
1469 CGContextSynchronize (context
);
1470 QDEndCGContext (port
, &context
);
1479 /* Mac replacement for XCopyArea: dest must be window. */
1482 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1487 unsigned int width
, height
;
1492 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1494 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1495 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1497 ForeColor (blackColor
);
1498 BackColor (whiteColor
);
1500 mac_begin_clip (gc
);
1501 LockPixels (GetGWorldPixMap (src
));
1502 #if TARGET_API_MAC_CARBON
1507 LockPortBits (port
);
1508 CopyBits (GetPortBitMapForCopyBits (src
),
1509 GetPortBitMapForCopyBits (port
),
1510 &src_r
, &dest_r
, srcCopy
, 0);
1511 UnlockPortBits (port
);
1513 #else /* not TARGET_API_MAC_CARBON */
1514 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1515 &src_r
, &dest_r
, srcCopy
, 0);
1516 #endif /* not TARGET_API_MAC_CARBON */
1517 UnlockPixels (GetGWorldPixMap (src
));
1520 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1525 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1526 width
, height
, dest_x
, dest_y
)
1531 unsigned int width
, height
;
1536 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1538 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1539 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1541 ForeColor (blackColor
);
1542 BackColor (whiteColor
);
1544 mac_begin_clip (gc
);
1545 LockPixels (GetGWorldPixMap (src
));
1546 LockPixels (GetGWorldPixMap (mask
));
1547 #if TARGET_API_MAC_CARBON
1552 LockPortBits (port
);
1553 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1554 GetPortBitMapForCopyBits (port
),
1555 &src_r
, &src_r
, &dest_r
);
1556 UnlockPortBits (port
);
1558 #else /* not TARGET_API_MAC_CARBON */
1559 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1560 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1561 #endif /* not TARGET_API_MAC_CARBON */
1562 UnlockPixels (GetGWorldPixMap (mask
));
1563 UnlockPixels (GetGWorldPixMap (src
));
1566 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1568 #endif /* !USE_CG_DRAWING */
1571 /* Mac replacement for XCopyArea: used only for scrolling. */
1574 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1578 unsigned int width
, height
;
1581 #if TARGET_API_MAC_CARBON
1583 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1585 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1587 mac_prepare_for_quickdraw (f
);
1589 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1590 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1591 kScrollWindowNoOptions
, dummy
);
1593 #else /* not TARGET_API_MAC_CARBON */
1595 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1599 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1600 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1602 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1603 color mapping in CopyBits. Otherwise, it will be slow. */
1604 ForeColor (blackColor
);
1605 BackColor (whiteColor
);
1606 mac_begin_clip (gc
);
1607 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1610 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1611 #endif /* not TARGET_API_MAC_CARBON */
1615 /* Mac replacement for XChangeGC. */
1618 XChangeGC (display
, gc
, mask
, xgcv
)
1624 if (mask
& GCForeground
)
1625 XSetForeground (display
, gc
, xgcv
->foreground
);
1626 if (mask
& GCBackground
)
1627 XSetBackground (display
, gc
, xgcv
->background
);
1629 XSetFont (display
, gc
, xgcv
->font
);
1633 /* Mac replacement for XCreateGC. */
1636 XCreateGC (display
, d
, mask
, xgcv
)
1642 GC gc
= xmalloc (sizeof (*gc
));
1644 bzero (gc
, sizeof (*gc
));
1645 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1646 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1647 if (CGColorGetTypeID
!= NULL
)
1650 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1651 CGColorRetain (gc
->cg_fore_color
);
1652 CGColorRetain (gc
->cg_back_color
);
1655 XChangeGC (display
, gc
, mask
, xgcv
);
1661 /* Used in xfaces.c. */
1664 XFreeGC (display
, gc
)
1668 if (gc
->clip_region
)
1669 DisposeRgn (gc
->clip_region
);
1670 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1671 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1672 if (CGColorGetTypeID
!= NULL
)
1675 CGColorRelease (gc
->cg_fore_color
);
1676 CGColorRelease (gc
->cg_back_color
);
1683 /* Mac replacement for XGetGCValues. */
1686 XGetGCValues (display
, gc
, mask
, xgcv
)
1692 if (mask
& GCForeground
)
1693 xgcv
->foreground
= gc
->xgcv
.foreground
;
1694 if (mask
& GCBackground
)
1695 xgcv
->background
= gc
->xgcv
.background
;
1697 xgcv
->font
= gc
->xgcv
.font
;
1701 /* Mac replacement for XSetForeground. */
1704 XSetForeground (display
, gc
, color
)
1707 unsigned long color
;
1709 if (gc
->xgcv
.foreground
!= color
)
1711 gc
->xgcv
.foreground
= color
;
1712 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1713 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1714 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1715 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1716 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1717 if (CGColorGetTypeID
!= NULL
)
1720 CGColorRelease (gc
->cg_fore_color
);
1723 gc
->cg_fore_color
= mac_cg_color_black
;
1724 CGColorRetain (gc
->cg_fore_color
);
1730 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1731 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1732 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1734 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1742 /* Mac replacement for XSetBackground. */
1745 XSetBackground (display
, gc
, color
)
1748 unsigned long color
;
1750 if (gc
->xgcv
.background
!= color
)
1752 gc
->xgcv
.background
= color
;
1753 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1754 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1755 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1756 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1757 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1758 if (CGColorGetTypeID
!= NULL
)
1761 CGColorRelease (gc
->cg_back_color
);
1764 gc
->cg_back_color
= mac_cg_color_black
;
1765 CGColorRetain (gc
->cg_back_color
);
1771 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1772 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1773 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1775 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1783 /* Mac replacement for XSetFont. */
1786 XSetFont (display
, gc
, font
)
1791 gc
->xgcv
.font
= font
;
1795 /* Mac replacement for XSetClipRectangles. */
1798 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1806 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1808 gc
->n_clip_rects
= n
;
1811 if (gc
->clip_region
== NULL
)
1812 gc
->clip_region
= NewRgn ();
1813 RectRgn (gc
->clip_region
, rectangles
);
1816 RgnHandle region
= NewRgn ();
1818 for (i
= 1; i
< n
; i
++)
1820 RectRgn (region
, rectangles
+ i
);
1821 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1823 DisposeRgn (region
);
1826 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1827 for (i
= 0; i
< n
; i
++)
1829 Rect
*rect
= rectangles
+ i
;
1831 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1832 rect
->right
- rect
->left
,
1833 rect
->bottom
- rect
->top
);
1839 /* Mac replacement for XSetClipMask. */
1842 mac_reset_clip_rectangles (display
, gc
)
1846 gc
->n_clip_rects
= 0;
1850 /* Mac replacement for XSetWindowBackground. */
1853 XSetWindowBackground (display
, w
, color
)
1856 unsigned long color
;
1858 #if !TARGET_API_MAC_CARBON
1859 AuxWinHandle aw_handle
;
1860 CTabHandle ctab_handle
;
1861 ColorSpecPtr ct_table
;
1866 bg_color
.red
= RED16_FROM_ULONG (color
);
1867 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1868 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1870 #if TARGET_API_MAC_CARBON
1871 SetWindowContentColor (w
, &bg_color
);
1873 if (GetAuxWin (w
, &aw_handle
))
1875 ctab_handle
= (*aw_handle
)->awCTable
;
1876 HandToHand ((Handle
*) &ctab_handle
);
1877 ct_table
= (*ctab_handle
)->ctTable
;
1878 ct_size
= (*ctab_handle
)->ctSize
;
1879 while (ct_size
> -1)
1881 if (ct_table
->value
== 0)
1883 ct_table
->rgb
= bg_color
;
1884 CTabChanged (ctab_handle
);
1885 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1893 /* Flush display of frame F, or of all frames if F is null. */
1899 #if TARGET_API_MAC_CARBON
1902 mac_prepare_for_quickdraw (f
);
1905 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1907 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1913 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1914 Calls to XFlush should be unnecessary because the X output buffer
1915 is flushed automatically as needed by calls to XPending,
1916 XNextEvent, or XWindowEvent according to the XFlush man page.
1917 XTread_socket calls XPending. Removing XFlush improves
1920 #define XFlush(DISPLAY) (void) 0
1924 mac_flush_display_optional (f
)
1928 mac_prepare_for_quickdraw (f
);
1933 /***********************************************************************
1934 Starting and ending an update
1935 ***********************************************************************/
1937 /* Start an update of frame F. This function is installed as a hook
1938 for update_begin, i.e. it is called when update_begin is called.
1939 This function is called prior to calls to x_update_window_begin for
1940 each window being updated. */
1946 #if TARGET_API_MAC_CARBON
1947 /* During update of a frame, availability of input events is
1948 periodically checked with ReceiveNextEvent if
1949 redisplay-dont-pause is nil. That normally flushes window buffer
1950 changes for every check, and thus screen update looks waving even
1951 if no input is available. So we disable screen updates during
1952 update of a frame. */
1954 DisableScreenUpdates ();
1960 /* Start update of window W. Set the global variable updated_window
1961 to the window being updated and set output_cursor to the cursor
1965 x_update_window_begin (w
)
1968 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1969 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1972 set_output_cursor (&w
->cursor
);
1976 if (f
== display_info
->mouse_face_mouse_frame
)
1978 /* Don't do highlighting for mouse motion during the update. */
1979 display_info
->mouse_face_defer
= 1;
1981 /* If F needs to be redrawn, simply forget about any prior mouse
1983 if (FRAME_GARBAGED_P (f
))
1984 display_info
->mouse_face_window
= Qnil
;
1986 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1987 their mouse_face_p flag set, which means that they are always
1988 unequal to rows in a desired matrix which never have that
1989 flag set. So, rows containing mouse-face glyphs are never
1990 scrolled, and we don't have to switch the mouse highlight off
1991 here to prevent it from being scrolled. */
1993 /* Can we tell that this update does not affect the window
1994 where the mouse highlight is? If so, no need to turn off.
1995 Likewise, don't do anything if the frame is garbaged;
1996 in that case, the frame's current matrix that we would use
1997 is all wrong, and we will redisplay that line anyway. */
1998 if (!NILP (display_info
->mouse_face_window
)
1999 && w
== XWINDOW (display_info
->mouse_face_window
))
2003 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2004 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2007 if (i
< w
->desired_matrix
->nrows
)
2008 clear_mouse_face (display_info
);
2017 /* Draw a vertical window border from (x,y0) to (x,y1) */
2020 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2024 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2027 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2029 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2032 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2035 /* End update of window W (which is equal to updated_window).
2037 Draw vertical borders between horizontally adjacent windows, and
2038 display W's cursor if CURSOR_ON_P is non-zero.
2040 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2041 glyphs in mouse-face were overwritten. In that case we have to
2042 make sure that the mouse-highlight is properly redrawn.
2044 W may be a menu bar pseudo-window in case we don't have X toolkit
2045 support. Such windows don't have a cursor, so don't display it
2049 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2051 int cursor_on_p
, mouse_face_overwritten_p
;
2053 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2055 if (!w
->pseudo_window_p
)
2060 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2062 output_cursor
.x
, output_cursor
.y
);
2064 if (draw_window_fringes (w
, 1))
2065 x_draw_vertical_border (w
);
2070 /* If a row with mouse-face was overwritten, arrange for
2071 XTframe_up_to_date to redisplay the mouse highlight. */
2072 if (mouse_face_overwritten_p
)
2074 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2075 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2076 dpyinfo
->mouse_face_window
= Qnil
;
2079 updated_window
= NULL
;
2083 /* End update of frame F. This function is installed as a hook in
2090 /* Mouse highlight may be displayed again. */
2091 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2094 #if TARGET_API_MAC_CARBON
2095 EnableScreenUpdates ();
2097 XFlush (FRAME_MAC_DISPLAY (f
));
2102 /* This function is called from various places in xdisp.c whenever a
2103 complete update has been performed. The global variable
2104 updated_window is not available here. */
2107 XTframe_up_to_date (f
)
2110 if (FRAME_MAC_P (f
))
2112 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2114 if (dpyinfo
->mouse_face_deferred_gc
2115 || f
== dpyinfo
->mouse_face_mouse_frame
)
2118 if (dpyinfo
->mouse_face_mouse_frame
)
2119 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2120 dpyinfo
->mouse_face_mouse_x
,
2121 dpyinfo
->mouse_face_mouse_y
);
2122 dpyinfo
->mouse_face_deferred_gc
= 0;
2129 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2130 arrow bitmaps, or clear the fringes if no bitmaps are required
2131 before DESIRED_ROW is made current. The window being updated is
2132 found in updated_window. This function is called from
2133 update_window_line only if it is known that there are differences
2134 between bitmaps to be drawn between current row and DESIRED_ROW. */
2137 x_after_update_window_line (desired_row
)
2138 struct glyph_row
*desired_row
;
2140 struct window
*w
= updated_window
;
2146 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2147 desired_row
->redraw_fringe_bitmaps_p
= 1;
2149 /* When a window has disappeared, make sure that no rest of
2150 full-width rows stays visible in the internal border. Could
2151 check here if updated_window is the leftmost/rightmost window,
2152 but I guess it's not worth doing since vertically split windows
2153 are almost never used, internal border is rarely set, and the
2154 overhead is very small. */
2155 if (windows_or_buffers_changed
2156 && desired_row
->full_width_p
2157 && (f
= XFRAME (w
->frame
),
2158 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2160 && (height
= desired_row
->visible_height
,
2163 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2165 /* Internal border is drawn below the tool bar. */
2166 if (WINDOWP (f
->tool_bar_window
)
2167 && w
== XWINDOW (f
->tool_bar_window
))
2171 mac_clear_area (f
, 0, y
, width
, height
);
2172 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2178 /* Draw the bitmap WHICH in one of the left or right fringes of
2179 window W. ROW is the glyph row for which to display the bitmap; it
2180 determines the vertical position at which the bitmap has to be
2184 x_draw_fringe_bitmap (w
, row
, p
)
2186 struct glyph_row
*row
;
2187 struct draw_fringe_bitmap_params
*p
;
2189 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2190 Display
*display
= FRAME_MAC_DISPLAY (f
);
2191 struct face
*face
= p
->face
;
2194 /* Must clip because of partially visible lines. */
2195 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2198 /* Adjust position of "bottom aligned" bitmap on partially
2199 visible last row. */
2201 int oldVH
= row
->visible_height
;
2202 row
->visible_height
= p
->h
;
2203 row
->y
-= rowY
- p
->y
;
2204 x_clip_to_row (w
, row
, -1, face
->gc
);
2206 row
->visible_height
= oldVH
;
2209 x_clip_to_row (w
, row
, -1, face
->gc
);
2211 if (p
->bx
>= 0 && !p
->overlay_p
)
2213 #if 0 /* MAC_TODO: stipple */
2214 /* In case the same realized face is used for fringes and
2215 for something displayed in the text (e.g. face `region' on
2216 mono-displays, the fill style may have been changed to
2217 FillSolid in x_draw_glyph_string_background. */
2219 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2221 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2224 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2226 #if 0 /* MAC_TODO: stipple */
2228 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2234 && p
->which
< max_fringe_bmp
2240 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2241 XSetForeground (display
, face
->gc
,
2243 ? (p
->overlay_p
? face
->background
2244 : f
->output_data
.mac
->cursor_pixel
)
2245 : face
->foreground
));
2247 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2248 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
2250 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2251 p
->wd
, p
->h
, p
->bits
+ p
->dh
, p
->overlay_p
);
2253 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2256 mac_reset_clip_rectangles (display
, face
->gc
);
2261 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2263 unsigned short *bits
;
2267 CGDataProviderRef provider
;
2269 if (which
>= max_fringe_bmp
)
2272 max_fringe_bmp
= which
+ 20;
2273 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2274 while (i
< max_fringe_bmp
)
2275 fringe_bmp
[i
++] = 0;
2278 for (i
= 0; i
< h
; i
++)
2280 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2281 sizeof (unsigned short) * h
, NULL
);
2284 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2285 sizeof (unsigned short),
2287 CGDataProviderRelease (provider
);
2292 mac_destroy_fringe_bitmap (which
)
2295 if (which
>= max_fringe_bmp
)
2298 if (fringe_bmp
[which
])
2299 CGImageRelease (fringe_bmp
[which
]);
2300 fringe_bmp
[which
] = 0;
2305 /* This is called when starting Emacs and when restarting after
2306 suspend. When starting Emacs, no window is mapped. And nothing
2307 must be done to Emacs's own window if it is suspended (though that
2311 XTset_terminal_modes ()
2315 /* This is called when exiting or suspending Emacs. Exiting will make
2316 the windows go away, and suspending requires no action. */
2319 XTreset_terminal_modes ()
2325 /***********************************************************************
2327 ***********************************************************************/
2329 /* Function prototypes of this page. */
2331 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2332 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
2333 struct charset
*, int *));
2337 pcm_init (pcm
, count
)
2341 bzero (pcm
, sizeof (XCharStruct
) * count
);
2342 while (--count
>= 0)
2344 pcm
->descent
= PCM_INVALID
;
2349 static enum pcm_status
2350 pcm_get_status (pcm
)
2351 const XCharStruct
*pcm
;
2353 int height
= pcm
->ascent
+ pcm
->descent
;
2355 /* Negative height means some special status. */
2356 return height
>= 0 ? PCM_VALID
: height
;
2359 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2360 is not contained in the font. */
2362 static INLINE XCharStruct
*
2363 x_per_char_metric (font
, char2b
)
2367 /* The result metric information. */
2368 XCharStruct
*pcm
= NULL
;
2370 xassert (font
&& char2b
);
2373 if (font
->mac_style
)
2375 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2379 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2380 pcm_init (*row
, 0x100);
2382 pcm
= *row
+ char2b
->byte2
;
2383 if (pcm_get_status (pcm
) != PCM_VALID
)
2386 mac_query_char_extents (font
->mac_style
,
2387 (char2b
->byte1
<< 8) + char2b
->byte2
,
2388 NULL
, NULL
, pcm
, NULL
);
2395 if (font
->bounds
.per_char
!= NULL
)
2397 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2399 /* min_char_or_byte2 specifies the linear character index
2400 corresponding to the first element of the per_char array,
2401 max_char_or_byte2 is the index of the last character. A
2402 character with non-zero CHAR2B->byte1 is not in the font.
2403 A character with byte2 less than min_char_or_byte2 or
2404 greater max_char_or_byte2 is not in the font. */
2405 if (char2b
->byte1
== 0
2406 && char2b
->byte2
>= font
->min_char_or_byte2
2407 && char2b
->byte2
<= font
->max_char_or_byte2
)
2408 pcm
= font
->bounds
.per_char
2409 + (char2b
->byte2
- font
->min_char_or_byte2
);
2413 /* If either min_byte1 or max_byte1 are nonzero, both
2414 min_char_or_byte2 and max_char_or_byte2 are less than
2415 256, and the 2-byte character index values corresponding
2416 to the per_char array element N (counting from 0) are:
2418 byte1 = N/D + min_byte1
2419 byte2 = N\D + min_char_or_byte2
2423 D = max_char_or_byte2 - min_char_or_byte2 + 1
2424 / = integer division
2425 \ = integer modulus */
2426 if (char2b
->byte1
>= font
->min_byte1
2427 && char2b
->byte1
<= font
->max_byte1
2428 && char2b
->byte2
>= font
->min_char_or_byte2
2429 && char2b
->byte2
<= font
->max_char_or_byte2
)
2431 pcm
= (font
->bounds
.per_char
2432 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2433 * (char2b
->byte1
- font
->min_byte1
))
2434 + (char2b
->byte2
- font
->min_char_or_byte2
));
2440 /* If the per_char pointer is null, all glyphs between the first
2441 and last character indexes inclusive have the same
2442 information, as given by both min_bounds and max_bounds. */
2443 if (char2b
->byte2
>= font
->min_char_or_byte2
2444 && char2b
->byte2
<= font
->max_char_or_byte2
)
2445 pcm
= &font
->max_bounds
;
2451 return ((pcm
== NULL
2453 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2454 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2463 static XCharStruct
*
2464 mac_per_char_metric (font
, char2b
, font_type
)
2469 return x_per_char_metric (font
, char2b
);
2473 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2474 the two-byte form of C. Encoding is returned in *CHAR2B. */
2477 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
2480 struct font_info
*font_info
;
2481 struct charset
*charset
;
2484 XFontStruct
*font
= font_info
->font
;
2486 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2487 This may be either a program in a special encoder language or a
2489 if (font_info
->font_encoder
)
2491 /* It's a program. */
2492 struct ccl_program
*ccl
= font_info
->font_encoder
;
2494 check_ccl_update (ccl
);
2495 if (CHARSET_DIMENSION (charset
) == 1)
2497 ccl
->reg
[0] = CHARSET_ID (charset
);
2498 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
2503 ccl
->reg
[0] = CHARSET_ID (charset
);
2504 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
2505 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
2508 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
2510 /* We assume that MSBs are appropriately set/reset by CCL
2512 if (font
->max_byte1
== 0) /* 1-byte font */
2513 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
2515 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
2517 else if (font_info
->encoding_type
)
2519 /* Fixed encoding scheme. See fontset.h for the meaning of the
2520 encoding numbers. */
2521 unsigned char enc
= font_info
->encoding_type
;
2523 if ((enc
== 1 || enc
== 2)
2524 && CHARSET_DIMENSION (charset
) == 2)
2525 char2b
->byte1
|= 0x80;
2527 if (enc
== 1 || enc
== 3)
2528 char2b
->byte2
|= 0x80;
2532 int code
= (char2b
->byte1
<< 8) | char2b
->byte2
;
2535 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
2540 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2542 return FONT_TYPE_UNKNOWN
;
2547 /***********************************************************************
2549 ***********************************************************************/
2553 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2554 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2555 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2557 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2558 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2559 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2560 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2561 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2562 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2563 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2564 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2565 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2566 unsigned long *, double, int));*/
2567 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2568 double, int, unsigned long));
2569 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2570 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2571 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2572 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2573 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2575 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2576 int, int, int, int, int, int,
2578 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2579 int, int, int, Rect
*));
2582 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2586 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2591 struct glyph_string
*s
;
2593 if (s
->font
== FRAME_FONT (s
->f
)
2594 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2595 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2597 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2600 /* Cursor on non-default face: must merge. */
2604 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2605 xgcv
.foreground
= s
->face
->background
;
2607 /* If the glyph would be invisible, try a different foreground. */
2608 if (xgcv
.foreground
== xgcv
.background
)
2609 xgcv
.foreground
= s
->face
->foreground
;
2610 if (xgcv
.foreground
== xgcv
.background
)
2611 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2612 if (xgcv
.foreground
== xgcv
.background
)
2613 xgcv
.foreground
= s
->face
->foreground
;
2615 /* Make sure the cursor is distinct from text in this face. */
2616 if (xgcv
.background
== s
->face
->background
2617 && xgcv
.foreground
== s
->face
->foreground
)
2619 xgcv
.background
= s
->face
->foreground
;
2620 xgcv
.foreground
= s
->face
->background
;
2623 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2624 xgcv
.font
= s
->font
;
2625 mask
= GCForeground
| GCBackground
| GCFont
;
2627 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2628 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2631 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2632 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2634 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2639 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2642 x_set_mouse_face_gc (s
)
2643 struct glyph_string
*s
;
2648 /* What face has to be used last for the mouse face? */
2649 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2650 face
= FACE_FROM_ID (s
->f
, face_id
);
2652 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2654 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2655 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
2657 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
2658 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2659 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2661 /* If font in this face is same as S->font, use it. */
2662 if (s
->font
== s
->face
->font
)
2663 s
->gc
= s
->face
->gc
;
2666 /* Otherwise construct scratch_cursor_gc with values from FACE
2671 xgcv
.background
= s
->face
->background
;
2672 xgcv
.foreground
= s
->face
->foreground
;
2673 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2674 xgcv
.font
= s
->font
;
2675 mask
= GCForeground
| GCBackground
| GCFont
;
2677 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2678 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2681 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2682 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2684 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2687 xassert (s
->gc
!= 0);
2691 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2692 Faces to use in the mode line have already been computed when the
2693 matrix was built, so there isn't much to do, here. */
2696 x_set_mode_line_face_gc (s
)
2697 struct glyph_string
*s
;
2699 s
->gc
= s
->face
->gc
;
2703 /* Set S->gc of glyph string S for drawing that glyph string. Set
2704 S->stippled_p to a non-zero value if the face of S has a stipple
2708 x_set_glyph_string_gc (s
)
2709 struct glyph_string
*s
;
2711 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2713 if (s
->hl
== DRAW_NORMAL_TEXT
)
2715 s
->gc
= s
->face
->gc
;
2716 s
->stippled_p
= s
->face
->stipple
!= 0;
2718 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2720 x_set_mode_line_face_gc (s
);
2721 s
->stippled_p
= s
->face
->stipple
!= 0;
2723 else if (s
->hl
== DRAW_CURSOR
)
2725 x_set_cursor_gc (s
);
2728 else if (s
->hl
== DRAW_MOUSE_FACE
)
2730 x_set_mouse_face_gc (s
);
2731 s
->stippled_p
= s
->face
->stipple
!= 0;
2733 else if (s
->hl
== DRAW_IMAGE_RAISED
2734 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2736 s
->gc
= s
->face
->gc
;
2737 s
->stippled_p
= s
->face
->stipple
!= 0;
2741 s
->gc
= s
->face
->gc
;
2742 s
->stippled_p
= s
->face
->stipple
!= 0;
2745 /* GC must have been set. */
2746 xassert (s
->gc
!= 0);
2750 /* Set clipping for output of glyph string S. S may be part of a mode
2751 line or menu if we don't have X toolkit support. */
2754 x_set_glyph_string_clipping (s
)
2755 struct glyph_string
*s
;
2757 Rect rects
[MAX_CLIP_RECTS
];
2760 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2761 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2766 Compute left and right overhang of glyph string S. If S is a glyph
2767 string for a composition, assume overhangs don't exist. */
2770 mac_compute_glyph_string_overhangs (s
)
2771 struct glyph_string
*s
;
2773 if (!(s
->cmp
== NULL
2774 && s
->first_glyph
->type
== CHAR_GLYPH
))
2779 || s
->font
->mac_style
2785 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2786 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2787 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2792 MacFontStruct
*font
= s
->font
;
2795 mac_prepare_for_quickdraw (s
->f
);
2797 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2799 TextFont (font
->mac_fontnum
);
2800 TextSize (font
->mac_fontsize
);
2801 TextFace (font
->mac_fontface
);
2803 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2805 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2806 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2811 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2814 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2815 struct glyph_string
*s
;
2818 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2822 /* Draw the background of glyph_string S. If S->background_filled_p
2823 is non-zero don't draw it. FORCE_P non-zero means draw the
2824 background even if it wouldn't be drawn normally. This is used
2825 when a string preceding S draws into the background of S, or S
2826 contains the first component of a composition. */
2829 x_draw_glyph_string_background (s
, force_p
)
2830 struct glyph_string
*s
;
2833 /* Nothing to do if background has already been drawn or if it
2834 shouldn't be drawn in the first place. */
2835 if (!s
->background_filled_p
)
2837 int box_line_width
= max (s
->face
->box_line_width
, 0);
2839 #if 0 /* MAC_TODO: stipple */
2842 /* Fill background with a stipple pattern. */
2843 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2844 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2845 s
->y
+ box_line_width
,
2846 s
->background_width
,
2847 s
->height
- 2 * box_line_width
);
2848 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2849 s
->background_filled_p
= 1;
2853 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2854 || s
->font_not_found_p
2855 || s
->extends_to_end_of_line_p
2858 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2859 s
->background_width
,
2860 s
->height
- 2 * box_line_width
);
2861 s
->background_filled_p
= 1;
2867 /* Draw the foreground of glyph string S. */
2870 x_draw_glyph_string_foreground (s
)
2871 struct glyph_string
*s
;
2875 /* If first glyph of S has a left box line, start drawing the text
2876 of S to the right of that box line. */
2877 if (s
->face
->box
!= FACE_NO_BOX
2878 && s
->first_glyph
->left_box_line_p
)
2879 x
= s
->x
+ abs (s
->face
->box_line_width
);
2883 /* Draw characters of S as rectangles if S's font could not be
2885 if (s
->font_not_found_p
)
2887 for (i
= 0; i
< s
->nchars
; ++i
)
2889 struct glyph
*g
= s
->first_glyph
+ i
;
2890 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2891 g
->pixel_width
- 1, s
->height
- 1);
2892 x
+= g
->pixel_width
;
2897 char *char1b
= (char *) s
->char2b
;
2898 int boff
= s
->font_info
->baseline_offset
;
2900 if (s
->font_info
->vertical_centering
)
2901 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2903 /* If we can use 8-bit functions, condense S->char2b. */
2906 && GC_FONT (s
->gc
)->mac_style
== NULL
2909 for (i
= 0; i
< s
->nchars
; ++i
)
2910 char1b
[i
] = s
->char2b
[i
].byte2
;
2912 /* Draw text with XDrawString if background has already been
2913 filled. Otherwise, use XDrawImageString. (Note that
2914 XDrawImageString is usually faster than XDrawString.) Always
2915 use XDrawImageString when drawing the cursor so that there is
2916 no chance that characters under a box cursor are invisible. */
2918 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2919 bg_width
= 0; /* Corresponds to XDrawString. */
2921 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2925 || GC_FONT (s
->gc
)->mac_style
2928 #if USE_CG_TEXT_DRAWING
2930 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2931 s
->char2b
, s
->nchars
, bg_width
,
2932 s
->face
->overstrike
))
2936 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2937 s
->char2b
, s
->nchars
, bg_width
,
2938 s
->face
->overstrike
);
2940 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2941 char1b
, s
->nchars
, bg_width
,
2942 s
->face
->overstrike
);
2946 /* Draw the foreground of composite glyph string S. */
2949 x_draw_composite_glyph_string_foreground (s
)
2950 struct glyph_string
*s
;
2954 /* If first glyph of S has a left box line, start drawing the text
2955 of S to the right of that box line. */
2956 if (s
->face
->box
!= FACE_NO_BOX
2957 && s
->first_glyph
->left_box_line_p
)
2958 x
= s
->x
+ abs (s
->face
->box_line_width
);
2962 /* S is a glyph string for a composition. S->gidx is the index of
2963 the first character drawn for glyphs of this composition.
2964 S->gidx == 0 means we are drawing the very first character of
2965 this composition. */
2967 /* Draw a rectangle for the composition if the font for the very
2968 first character of the composition could not be loaded. */
2969 if (s
->font_not_found_p
)
2972 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2973 s
->width
- 1, s
->height
- 1);
2977 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2978 mac_draw_image_string_16 (s
->f
, s
->gc
,
2979 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2980 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2981 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
2986 #ifdef USE_X_TOOLKIT
2988 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2991 /* Return the frame on which widget WIDGET is used.. Abort if frame
2992 cannot be determined. */
2994 static struct frame
*
2995 x_frame_of_widget (widget
)
2998 struct x_display_info
*dpyinfo
;
3002 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3004 /* Find the top-level shell of the widget. Note that this function
3005 can be called when the widget is not yet realized, so XtWindow
3006 (widget) == 0. That's the reason we can't simply use
3007 x_any_window_to_frame. */
3008 while (!XtIsTopLevelShell (widget
))
3009 widget
= XtParent (widget
);
3011 /* Look for a frame with that top-level widget. Allocate the color
3012 on that frame to get the right gamma correction value. */
3013 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3014 if (GC_FRAMEP (XCAR (tail
))
3015 && (f
= XFRAME (XCAR (tail
)),
3016 (f
->output_data
.nothing
!= 1
3017 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3018 && f
->output_data
.x
->widget
== widget
)
3025 /* Allocate the color COLOR->pixel on the screen and display of
3026 widget WIDGET in colormap CMAP. If an exact match cannot be
3027 allocated, try the nearest color available. Value is non-zero
3028 if successful. This is called from lwlib. */
3031 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3036 struct frame
*f
= x_frame_of_widget (widget
);
3037 return x_alloc_nearest_color (f
, cmap
, color
);
3041 #endif /* USE_X_TOOLKIT */
3043 #if 0 /* MAC_TODO */
3045 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3046 CMAP. If an exact match can't be allocated, try the nearest color
3047 available. Value is non-zero if successful. Set *COLOR to the
3051 x_alloc_nearest_color (f
, cmap
, color
)
3056 Display
*display
= FRAME_X_DISPLAY (f
);
3057 Screen
*screen
= FRAME_X_SCREEN (f
);
3060 gamma_correct (f
, color
);
3061 rc
= XAllocColor (display
, cmap
, color
);
3064 /* If we got to this point, the colormap is full, so we're going
3065 to try to get the next closest color. The algorithm used is
3066 a least-squares matching, which is what X uses for closest
3067 color matching with StaticColor visuals. */
3069 unsigned long nearest_delta
= ~0;
3070 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3071 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3073 for (i
= 0; i
< ncells
; ++i
)
3075 XQueryColors (display
, cmap
, cells
, ncells
);
3077 for (nearest
= i
= 0; i
< ncells
; ++i
)
3079 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3080 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3081 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3082 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3084 if (delta
< nearest_delta
)
3087 nearest_delta
= delta
;
3091 color
->red
= cells
[nearest
].red
;
3092 color
->green
= cells
[nearest
].green
;
3093 color
->blue
= cells
[nearest
].blue
;
3094 rc
= XAllocColor (display
, cmap
, color
);
3097 #ifdef DEBUG_X_COLORS
3099 register_color (color
->pixel
);
3100 #endif /* DEBUG_X_COLORS */
3106 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3107 It's necessary to do this instead of just using PIXEL directly to
3108 get color reference counts right. */
3111 x_copy_color (f
, pixel
)
3113 unsigned long pixel
;
3117 color
.pixel
= pixel
;
3119 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3120 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3122 #ifdef DEBUG_X_COLORS
3123 register_color (pixel
);
3129 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3130 It's necessary to do this instead of just using PIXEL directly to
3131 get color reference counts right. */
3134 x_copy_dpy_color (dpy
, cmap
, pixel
)
3137 unsigned long pixel
;
3141 color
.pixel
= pixel
;
3143 XQueryColor (dpy
, cmap
, &color
);
3144 XAllocColor (dpy
, cmap
, &color
);
3146 #ifdef DEBUG_X_COLORS
3147 register_color (pixel
);
3152 #endif /* MAC_TODO */
3155 /* Brightness beyond which a color won't have its highlight brightness
3158 Nominally, highlight colors for `3d' faces are calculated by
3159 brightening an object's color by a constant scale factor, but this
3160 doesn't yield good results for dark colors, so for colors who's
3161 brightness is less than this value (on a scale of 0-255) have to
3162 use an additional additive factor.
3164 The value here is set so that the default menu-bar/mode-line color
3165 (grey75) will not have its highlights changed at all. */
3166 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3169 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3170 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3171 If this produces the same color as COLOR, try a color where all RGB
3172 values have DELTA added. Return the allocated color in *COLOR.
3173 DISPLAY is the X display, CMAP is the colormap to operate on.
3174 Value is non-zero if successful. */
3177 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3179 unsigned long *color
;
3186 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3189 /* Change RGB values by specified FACTOR. Avoid overflow! */
3190 xassert (factor
>= 0);
3191 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3192 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3193 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3195 /* Calculate brightness of COLOR. */
3196 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3197 + BLUE_FROM_ULONG (*color
)) / 6;
3199 /* We only boost colors that are darker than
3200 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3201 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3202 /* Make an additive adjustment to NEW, because it's dark enough so
3203 that scaling by FACTOR alone isn't enough. */
3205 /* How far below the limit this color is (0 - 1, 1 being darker). */
3206 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3207 /* The additive adjustment. */
3208 int min_delta
= delta
* dimness
* factor
/ 2;
3211 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3212 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3213 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3215 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3216 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3217 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3221 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3222 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3223 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3225 /* MAC_TODO: Map to palette and retry with delta if same? */
3226 /* MAC_TODO: Free colors (if using palette)? */
3237 /* Set up the foreground color for drawing relief lines of glyph
3238 string S. RELIEF is a pointer to a struct relief containing the GC
3239 with which lines will be drawn. Use a color that is FACTOR or
3240 DELTA lighter or darker than the relief's background which is found
3241 in S->f->output_data.x->relief_background. If such a color cannot
3242 be allocated, use DEFAULT_PIXEL, instead. */
3245 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3247 struct relief
*relief
;
3250 unsigned long default_pixel
;
3253 struct mac_output
*di
= f
->output_data
.mac
;
3254 unsigned long mask
= GCForeground
;
3255 unsigned long pixel
;
3256 unsigned long background
= di
->relief_background
;
3257 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3259 /* MAC_TODO: Free colors (if using palette)? */
3261 /* Allocate new color. */
3262 xgcv
.foreground
= default_pixel
;
3264 if (dpyinfo
->n_planes
!= 1
3265 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3267 relief
->allocated_p
= 1;
3268 xgcv
.foreground
= relief
->pixel
= pixel
;
3271 if (relief
->gc
== 0)
3273 #if 0 /* MAC_TODO: stipple */
3274 xgcv
.stipple
= dpyinfo
->gray
;
3277 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3280 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3284 /* Set up colors for the relief lines around glyph string S. */
3287 x_setup_relief_colors (s
)
3288 struct glyph_string
*s
;
3290 struct mac_output
*di
= s
->f
->output_data
.mac
;
3291 unsigned long color
;
3293 if (s
->face
->use_box_color_for_shadows_p
)
3294 color
= s
->face
->box_color
;
3295 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3297 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3298 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3303 /* Get the background color of the face. */
3304 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3305 color
= xgcv
.background
;
3308 if (di
->white_relief
.gc
== 0
3309 || color
!= di
->relief_background
)
3311 di
->relief_background
= color
;
3312 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3313 WHITE_PIX_DEFAULT (s
->f
));
3314 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3315 BLACK_PIX_DEFAULT (s
->f
));
3320 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3321 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3322 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3323 relief. LEFT_P non-zero means draw a relief on the left side of
3324 the rectangle. RIGHT_P non-zero means draw a relief on the right
3325 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3329 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3330 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3332 int left_x
, top_y
, right_x
, bottom_y
, width
;
3333 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3336 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3341 gc
= f
->output_data
.mac
->white_relief
.gc
;
3343 gc
= f
->output_data
.mac
->black_relief
.gc
;
3344 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3348 for (i
= 0; i
< width
; ++i
)
3349 mac_draw_line (f
, gc
,
3350 left_x
+ i
* left_p
, top_y
+ i
,
3351 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3355 for (i
= 0; i
< width
; ++i
)
3356 mac_draw_line (f
, gc
,
3357 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3359 mac_reset_clip_rectangles (dpy
, gc
);
3361 gc
= f
->output_data
.mac
->black_relief
.gc
;
3363 gc
= f
->output_data
.mac
->white_relief
.gc
;
3364 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3368 for (i
= 0; i
< width
; ++i
)
3369 mac_draw_line (f
, gc
,
3370 left_x
+ i
* left_p
, bottom_y
- i
,
3371 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3375 for (i
= 0; i
< width
; ++i
)
3376 mac_draw_line (f
, gc
,
3377 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3379 mac_reset_clip_rectangles (dpy
, gc
);
3383 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3384 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3385 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3386 left side of the rectangle. RIGHT_P non-zero means draw a line
3387 on the right side of the rectangle. CLIP_RECT is the clipping
3388 rectangle to use when drawing. */
3391 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3392 left_p
, right_p
, clip_rect
)
3393 struct glyph_string
*s
;
3394 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3399 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3400 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3401 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3404 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3405 right_x
- left_x
+ 1, width
);
3409 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3410 width
, bottom_y
- top_y
+ 1);
3413 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3414 right_x
- left_x
+ 1, width
);
3418 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3419 top_y
, width
, bottom_y
- top_y
+ 1);
3421 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3422 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3426 /* Draw a box around glyph string S. */
3429 x_draw_glyph_string_box (s
)
3430 struct glyph_string
*s
;
3432 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3433 int left_p
, right_p
;
3434 struct glyph
*last_glyph
;
3437 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3438 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3439 : window_box_right (s
->w
, s
->area
));
3441 /* The glyph that may have a right box line. */
3442 last_glyph
= (s
->cmp
|| s
->img
3444 : s
->first_glyph
+ s
->nchars
- 1);
3446 width
= abs (s
->face
->box_line_width
);
3447 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3449 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3451 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3453 bottom_y
= top_y
+ s
->height
- 1;
3455 left_p
= (s
->first_glyph
->left_box_line_p
3456 || (s
->hl
== DRAW_MOUSE_FACE
3458 || s
->prev
->hl
!= s
->hl
)));
3459 right_p
= (last_glyph
->right_box_line_p
3460 || (s
->hl
== DRAW_MOUSE_FACE
3462 || s
->next
->hl
!= s
->hl
)));
3464 get_glyph_string_clip_rect (s
, &clip_rect
);
3466 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3467 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3468 left_p
, right_p
, &clip_rect
);
3471 x_setup_relief_colors (s
);
3472 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3473 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3478 /* Draw foreground of image glyph string S. */
3481 x_draw_image_foreground (s
)
3482 struct glyph_string
*s
;
3485 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3487 /* If first glyph of S has a left box line, start drawing it to the
3488 right of that line. */
3489 if (s
->face
->box
!= FACE_NO_BOX
3490 && s
->first_glyph
->left_box_line_p
3492 x
+= abs (s
->face
->box_line_width
);
3494 /* If there is a margin around the image, adjust x- and y-position
3496 if (s
->slice
.x
== 0)
3497 x
+= s
->img
->hmargin
;
3498 if (s
->slice
.y
== 0)
3499 y
+= s
->img
->vmargin
;
3503 x_set_glyph_string_clipping (s
);
3506 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3507 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3508 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3512 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3513 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3514 s
->slice
.width
, s
->slice
.height
, x
, y
);
3521 mac_copy_area (s
->img
->pixmap
,
3522 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3523 s
->slice
.width
, s
->slice
.height
, x
, y
);
3526 /* When the image has a mask, we can expect that at
3527 least part of a mouse highlight or a block cursor will
3528 be visible. If the image doesn't have a mask, make
3529 a block cursor visible by drawing a rectangle around
3530 the image. I believe it's looking better if we do
3531 nothing here for mouse-face. */
3532 if (s
->hl
== DRAW_CURSOR
)
3534 int r
= s
->img
->relief
;
3536 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3537 s
->slice
.width
+ r
*2 - 1,
3538 s
->slice
.height
+ r
*2 - 1);
3543 /* Draw a rectangle if image could not be loaded. */
3544 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3545 s
->slice
.width
- 1, s
->slice
.height
- 1);
3549 /* Draw a relief around the image glyph string S. */
3552 x_draw_image_relief (s
)
3553 struct glyph_string
*s
;
3555 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3558 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3560 /* If first glyph of S has a left box line, start drawing it to the
3561 right of that line. */
3562 if (s
->face
->box
!= FACE_NO_BOX
3563 && s
->first_glyph
->left_box_line_p
3565 x
+= abs (s
->face
->box_line_width
);
3567 /* If there is a margin around the image, adjust x- and y-position
3569 if (s
->slice
.x
== 0)
3570 x
+= s
->img
->hmargin
;
3571 if (s
->slice
.y
== 0)
3572 y
+= s
->img
->vmargin
;
3574 if (s
->hl
== DRAW_IMAGE_SUNKEN
3575 || s
->hl
== DRAW_IMAGE_RAISED
)
3577 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3578 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3582 thick
= abs (s
->img
->relief
);
3583 raised_p
= s
->img
->relief
> 0;
3588 x1
= x
+ s
->slice
.width
+ thick
- 1;
3589 y1
= y
+ s
->slice
.height
+ thick
- 1;
3591 x_setup_relief_colors (s
);
3592 get_glyph_string_clip_rect (s
, &r
);
3593 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3595 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3597 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3602 /* Draw part of the background of glyph string S. X, Y, W, and H
3603 give the rectangle to draw. */
3606 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3607 struct glyph_string
*s
;
3610 #if 0 /* MAC_TODO: stipple */
3613 /* Fill background with a stipple pattern. */
3614 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3615 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3616 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3619 #endif /* MAC_TODO */
3620 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3624 /* Draw image glyph string S.
3627 s->x +-------------------------
3630 | +-------------------------
3633 | | +-------------------
3639 x_draw_image_glyph_string (s
)
3640 struct glyph_string
*s
;
3643 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3644 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3647 height
= s
->height
- 2 * box_line_vwidth
;
3650 /* Fill background with face under the image. Do it only if row is
3651 taller than image or if image has a clip mask to reduce
3653 s
->stippled_p
= s
->face
->stipple
!= 0;
3654 if (height
> s
->slice
.height
3658 || s
->img
->pixmap
== 0
3659 || s
->width
!= s
->background_width
)
3662 if (s
->first_glyph
->left_box_line_p
3664 x
+= box_line_hwidth
;
3667 if (s
->slice
.y
== 0)
3668 y
+= box_line_vwidth
;
3670 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3672 s
->background_filled_p
= 1;
3675 /* Draw the foreground. */
3676 x_draw_image_foreground (s
);
3678 /* If we must draw a relief around the image, do it. */
3680 || s
->hl
== DRAW_IMAGE_RAISED
3681 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3682 x_draw_image_relief (s
);
3686 /* Draw stretch glyph string S. */
3689 x_draw_stretch_glyph_string (s
)
3690 struct glyph_string
*s
;
3692 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3693 s
->stippled_p
= s
->face
->stipple
!= 0;
3695 if (s
->hl
== DRAW_CURSOR
3696 && !x_stretch_cursor_p
)
3698 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3699 as wide as the stretch glyph. */
3700 int width
, background_width
= s
->background_width
;
3701 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3705 background_width
-= left_x
- x
;
3708 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3711 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3713 /* Clear rest using the GC of the original non-cursor face. */
3714 if (width
< background_width
)
3717 int w
= background_width
- width
, h
= s
->height
;
3722 if (s
->row
->mouse_face_p
3723 && cursor_in_mouse_face_p (s
->w
))
3725 x_set_mouse_face_gc (s
);
3731 get_glyph_string_clip_rect (s
, &r
);
3732 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3734 #if 0 /* MAC_TODO: stipple */
3735 if (s
->face
->stipple
)
3737 /* Fill background with a stipple pattern. */
3738 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3739 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3740 XSetFillStyle (s
->display
, gc
, FillSolid
);
3743 #endif /* MAC_TODO */
3744 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3747 else if (!s
->background_filled_p
)
3749 int background_width
= s
->background_width
;
3750 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3752 /* Don't draw into left margin, fringe or scrollbar area
3753 except for header line and mode line. */
3754 if (x
< left_x
&& !s
->row
->mode_line_p
)
3756 background_width
-= left_x
- x
;
3759 if (background_width
> 0)
3760 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3763 s
->background_filled_p
= 1;
3767 /* Draw glyph string S. */
3770 x_draw_glyph_string (s
)
3771 struct glyph_string
*s
;
3773 int relief_drawn_p
= 0;
3775 /* If S draws into the background of its successor that does not
3776 draw a cursor, draw the background of the successor first so that
3777 S can draw into it. This makes S->next use XDrawString instead
3778 of XDrawImageString. */
3779 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3780 && s
->next
->hl
!= DRAW_CURSOR
)
3782 xassert (s
->next
->img
== NULL
);
3783 x_set_glyph_string_gc (s
->next
);
3784 x_set_glyph_string_clipping (s
->next
);
3785 x_draw_glyph_string_background (s
->next
, 1);
3788 /* Set up S->gc, set clipping and draw S. */
3789 x_set_glyph_string_gc (s
);
3791 /* Draw relief (if any) in advance for char/composition so that the
3792 glyph string can be drawn over it. */
3793 if (!s
->for_overlaps
3794 && s
->face
->box
!= FACE_NO_BOX
3795 && (s
->first_glyph
->type
== CHAR_GLYPH
3796 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3799 x_set_glyph_string_clipping (s
);
3800 x_draw_glyph_string_background (s
, 1);
3801 x_draw_glyph_string_box (s
);
3802 x_set_glyph_string_clipping (s
);
3806 x_set_glyph_string_clipping (s
);
3808 switch (s
->first_glyph
->type
)
3811 x_draw_image_glyph_string (s
);
3815 x_draw_stretch_glyph_string (s
);
3819 if (s
->for_overlaps
)
3820 s
->background_filled_p
= 1;
3822 x_draw_glyph_string_background (s
, 0);
3823 x_draw_glyph_string_foreground (s
);
3826 case COMPOSITE_GLYPH
:
3827 if (s
->for_overlaps
|| s
->gidx
> 0)
3828 s
->background_filled_p
= 1;
3830 x_draw_glyph_string_background (s
, 1);
3831 x_draw_composite_glyph_string_foreground (s
);
3838 if (!s
->for_overlaps
)
3840 /* Draw underline. */
3841 if (s
->face
->underline_p
)
3843 unsigned long tem
, h
;
3847 /* Get the underline thickness. Default is 1 pixel. */
3848 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3852 y
= s
->y
+ s
->height
- h
;
3853 if (!x_underline_at_descent_line
)
3855 /* Get the underline position. This is the recommended
3856 vertical offset in pixels from the baseline to the top of
3857 the underline. This is a signed value according to the
3858 specs, and its default is
3860 ROUND ((maximum descent) / 2), with
3861 ROUND(x) = floor (x + 0.5) */
3864 if (x_use_underline_position_properties
3865 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3866 y
= s
->ybase
+ (long) tem
;
3870 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3873 if (s
->face
->underline_defaulted_p
)
3874 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3875 s
->background_width
, h
);
3879 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3880 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3881 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3882 s
->background_width
, h
);
3883 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3887 /* Draw overline. */
3888 if (s
->face
->overline_p
)
3890 unsigned long dy
= 0, h
= 1;
3892 if (s
->face
->overline_color_defaulted_p
)
3893 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3894 s
->background_width
, h
);
3898 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3899 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3900 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3901 s
->background_width
, h
);
3902 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3906 /* Draw strike-through. */
3907 if (s
->face
->strike_through_p
)
3909 unsigned long h
= 1;
3910 unsigned long dy
= (s
->height
- h
) / 2;
3912 if (s
->face
->strike_through_color_defaulted_p
)
3913 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3918 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3919 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3920 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3922 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3926 /* Draw relief if not yet drawn. */
3927 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3928 x_draw_glyph_string_box (s
);
3931 /* Reset clipping. */
3932 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3935 /* Shift display to make room for inserted glyphs. */
3938 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3940 int x
, y
, width
, height
, shift_by
;
3942 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3943 x
, y
, width
, height
,
3947 /* Delete N glyphs at the nominal cursor position. Not implemented
3958 /* Clear entire frame. If updating_frame is non-null, clear that
3959 frame. Otherwise clear the selected frame. */
3969 f
= SELECTED_FRAME ();
3971 /* Clearing the frame will erase any cursor, so mark them all as no
3973 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3974 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3975 output_cursor
.x
= -1;
3977 /* We don't set the output cursor here because there will always
3978 follow an explicit cursor_to. */
3980 mac_clear_window (f
);
3982 /* We have to clear the scroll bars, too. If we have changed
3983 colors or something like that, then they should be notified. */
3984 x_scroll_bar_clear (f
);
3986 XFlush (FRAME_MAC_DISPLAY (f
));
3992 /* Invert the middle quarter of the frame for .15 sec. */
3994 /* We use the select system call to do the waiting, so we have to make
3995 sure it's available. If it isn't, we just won't do visual bells. */
3997 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4000 /* Subtract the `struct timeval' values X and Y, storing the result in
4001 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4004 timeval_subtract (result
, x
, y
)
4005 struct timeval
*result
, x
, y
;
4007 /* Perform the carry for the later subtraction by updating y. This
4008 is safer because on some systems the tv_sec member is unsigned. */
4009 if (x
.tv_usec
< y
.tv_usec
)
4011 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4012 y
.tv_usec
-= 1000000 * nsec
;
4016 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4018 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4019 y
.tv_usec
+= 1000000 * nsec
;
4023 /* Compute the time remaining to wait. tv_usec is certainly
4025 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4026 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4028 /* Return indication of whether the result should be considered
4030 return x
.tv_sec
< y
.tv_sec
;
4037 /* Get the height not including a menu bar widget. */
4038 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4039 /* Height of each line to flash. */
4040 int flash_height
= FRAME_LINE_HEIGHT (f
);
4041 /* These will be the left and right margins of the rectangles. */
4042 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4043 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4047 /* Don't flash the area between a scroll bar and the frame
4048 edge it is next to. */
4049 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4051 case vertical_scroll_bar_left
:
4052 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4055 case vertical_scroll_bar_right
:
4056 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4063 width
= flash_right
- flash_left
;
4067 /* If window is tall, flash top and bottom line. */
4068 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4070 mac_invert_rectangle (f
, flash_left
,
4071 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4072 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4073 width
, flash_height
);
4074 mac_invert_rectangle (f
, flash_left
,
4075 (height
- flash_height
4076 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4077 width
, flash_height
);
4080 /* If it is short, flash it all. */
4081 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4082 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4087 struct timeval wakeup
;
4089 EMACS_GET_TIME (wakeup
);
4091 /* Compute time to wait until, propagating carry from usecs. */
4092 wakeup
.tv_usec
+= 150000;
4093 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4094 wakeup
.tv_usec
%= 1000000;
4096 /* Keep waiting until past the time wakeup or any input gets
4098 while (! detect_input_pending ())
4100 struct timeval current
;
4101 struct timeval timeout
;
4103 EMACS_GET_TIME (current
);
4105 /* Break if result would be negative. */
4106 if (timeval_subtract (¤t
, wakeup
, current
))
4109 /* How long `select' should wait. */
4111 timeout
.tv_usec
= 10000;
4113 /* Try to wait that long--but we might wake up sooner. */
4114 select (0, NULL
, NULL
, NULL
, &timeout
);
4118 /* If window is tall, flash top and bottom line. */
4119 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4121 mac_invert_rectangle (f
, flash_left
,
4122 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4123 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4124 width
, flash_height
);
4125 mac_invert_rectangle (f
, flash_left
,
4126 (height
- flash_height
4127 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4128 width
, flash_height
);
4131 /* If it is short, flash it all. */
4132 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4133 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4140 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4143 /* Make audible bell. */
4148 struct frame
*f
= SELECTED_FRAME ();
4150 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4158 XFlush (FRAME_MAC_DISPLAY (f
));
4164 /* Specify how many text lines, from the top of the window,
4165 should be affected by insert-lines and delete-lines operations.
4166 This, and those operations, are used only within an update
4167 that is bounded by calls to x_update_begin and x_update_end. */
4170 XTset_terminal_window (n
)
4173 /* This function intentionally left blank. */
4178 /***********************************************************************
4180 ***********************************************************************/
4182 /* Perform an insert-lines or delete-lines operation, inserting N
4183 lines or deleting -N lines at vertical position VPOS. */
4186 x_ins_del_lines (vpos
, n
)
4193 /* Scroll part of the display as described by RUN. */
4196 x_scroll_run (w
, run
)
4200 struct frame
*f
= XFRAME (w
->frame
);
4201 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4203 /* Get frame-relative bounding box of the text display area of W,
4204 without mode lines. Include in this box the left and right
4206 window_box (w
, -1, &x
, &y
, &width
, &height
);
4208 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4209 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4210 bottom_y
= y
+ height
;
4214 /* Scrolling up. Make sure we don't copy part of the mode
4215 line at the bottom. */
4216 if (from_y
+ run
->height
> bottom_y
)
4217 height
= bottom_y
- from_y
;
4219 height
= run
->height
;
4223 /* Scolling down. Make sure we don't copy over the mode line.
4225 if (to_y
+ run
->height
> bottom_y
)
4226 height
= bottom_y
- to_y
;
4228 height
= run
->height
;
4233 /* Cursor off. Will be switched on again in x_update_window_end. */
4237 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4247 /***********************************************************************
4249 ***********************************************************************/
4257 ControlRef root_control
;
4260 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4262 ActivateControl (root_control
);
4264 x_update_cursor (f
, 1);
4268 frame_unhighlight (f
)
4272 ControlRef root_control
;
4275 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4277 DeactivateControl (root_control
);
4279 x_update_cursor (f
, 1);
4282 /* The focus has changed. Update the frames as necessary to reflect
4283 the new situation. Note that we can't change the selected frame
4284 here, because the Lisp code we are interrupting might become confused.
4285 Each event gets marked with the frame in which it occurred, so the
4286 Lisp code can tell when the switch took place by examining the events. */
4289 x_new_focus_frame (dpyinfo
, frame
)
4290 struct x_display_info
*dpyinfo
;
4291 struct frame
*frame
;
4293 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4295 if (frame
!= dpyinfo
->x_focus_frame
)
4297 /* Set this before calling other routines, so that they see
4298 the correct value of x_focus_frame. */
4299 dpyinfo
->x_focus_frame
= frame
;
4301 if (old_focus
&& old_focus
->auto_lower
)
4302 x_lower_frame (old_focus
);
4305 selected_frame
= frame
;
4306 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4308 Fselect_window (selected_frame
->selected_window
, Qnil
);
4309 choose_minibuf_frame ();
4312 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4313 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4315 pending_autoraise_frame
= 0;
4317 #if USE_MAC_FONT_PANEL
4319 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4323 x_frame_rehighlight (dpyinfo
);
4326 /* Handle FocusIn and FocusOut state changes for FRAME.
4327 If FRAME has focus and there exists more than one frame, puts
4328 a FOCUS_IN_EVENT into *BUFP. */
4331 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4333 struct mac_display_info
*dpyinfo
;
4334 struct frame
*frame
;
4335 struct input_event
*bufp
;
4337 if (type
== activeFlag
)
4339 if (dpyinfo
->x_focus_event_frame
!= frame
)
4341 x_new_focus_frame (dpyinfo
, frame
);
4342 dpyinfo
->x_focus_event_frame
= frame
;
4344 /* Don't stop displaying the initial startup message
4345 for a switch-frame event we don't need. */
4346 if (GC_NILP (Vterminal_frame
)
4347 && GC_CONSP (Vframe_list
)
4348 && !GC_NILP (XCDR (Vframe_list
)))
4350 bufp
->kind
= FOCUS_IN_EVENT
;
4351 XSETFRAME (bufp
->frame_or_window
, frame
);
4357 if (dpyinfo
->x_focus_event_frame
== frame
)
4359 dpyinfo
->x_focus_event_frame
= 0;
4360 x_new_focus_frame (dpyinfo
, 0);
4365 /* The focus may have changed. Figure out if it is a real focus change,
4366 by checking both FocusIn/Out and Enter/LeaveNotify events.
4368 Returns FOCUS_IN_EVENT event in *BUFP. */
4371 x_detect_focus_change (dpyinfo
, event
, bufp
)
4372 struct mac_display_info
*dpyinfo
;
4373 const EventRecord
*event
;
4374 struct input_event
*bufp
;
4376 struct frame
*frame
;
4378 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4382 /* On Mac, this is only called from focus events, so no switch needed. */
4383 mac_focus_changed ((event
->modifiers
& activeFlag
),
4384 dpyinfo
, frame
, bufp
);
4388 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4391 x_mouse_leave (dpyinfo
)
4392 struct x_display_info
*dpyinfo
;
4394 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4397 /* The focus has changed, or we have redirected a frame's focus to
4398 another frame (this happens when a frame uses a surrogate
4399 mini-buffer frame). Shift the highlight as appropriate.
4401 The FRAME argument doesn't necessarily have anything to do with which
4402 frame is being highlighted or un-highlighted; we only use it to find
4403 the appropriate X display info. */
4406 XTframe_rehighlight (frame
)
4407 struct frame
*frame
;
4409 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4413 x_frame_rehighlight (dpyinfo
)
4414 struct x_display_info
*dpyinfo
;
4416 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4418 if (dpyinfo
->x_focus_frame
)
4420 dpyinfo
->x_highlight_frame
4421 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4422 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4423 : dpyinfo
->x_focus_frame
);
4424 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4426 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4427 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4431 dpyinfo
->x_highlight_frame
= 0;
4433 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4436 frame_unhighlight (old_highlight
);
4437 if (dpyinfo
->x_highlight_frame
)
4438 frame_highlight (dpyinfo
->x_highlight_frame
);
4444 /* Convert a keysym to its name. */
4447 x_get_keysym_name (keysym
)
4454 value
= XKeysymToString (keysym
);
4465 /* Function to report a mouse movement to the mainstream Emacs code.
4466 The input handler calls this.
4468 We have received a mouse movement event, which is given in *event.
4469 If the mouse is over a different glyph than it was last time, tell
4470 the mainstream emacs code by setting mouse_moved. If not, ask for
4471 another motion event, so we can check again the next time it moves. */
4473 static Point last_mouse_motion_position
;
4474 static Lisp_Object last_mouse_motion_frame
;
4477 note_mouse_movement (frame
, pos
)
4481 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4482 #if TARGET_API_MAC_CARBON
4486 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4487 last_mouse_motion_position
= *pos
;
4488 XSETFRAME (last_mouse_motion_frame
, frame
);
4490 if (frame
== dpyinfo
->mouse_face_mouse_frame
4491 #if TARGET_API_MAC_CARBON
4492 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4494 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4498 /* This case corresponds to LeaveNotify in X11. If we move
4499 outside the frame, then we're certainly no longer on any text
4501 clear_mouse_face (dpyinfo
);
4502 dpyinfo
->mouse_face_mouse_frame
= 0;
4503 if (!dpyinfo
->grabbed
)
4504 rif
->define_frame_cursor (frame
,
4505 frame
->output_data
.mac
->nontext_cursor
);
4508 /* Has the mouse moved off the glyph it was on at the last sighting? */
4509 if (frame
!= last_mouse_glyph_frame
4510 || !PtInRect (*pos
, &last_mouse_glyph
))
4512 frame
->mouse_moved
= 1;
4513 last_mouse_scroll_bar
= Qnil
;
4514 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4515 /* Remember which glyph we're now on. */
4516 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4517 last_mouse_glyph_frame
= frame
;
4525 /************************************************************************
4527 ************************************************************************/
4529 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4532 redo_mouse_highlight ()
4534 if (!NILP (last_mouse_motion_frame
)
4535 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4536 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4537 last_mouse_motion_position
.h
,
4538 last_mouse_motion_position
.v
);
4542 static struct frame
*
4543 mac_focus_frame (dpyinfo
)
4544 struct mac_display_info
*dpyinfo
;
4546 if (dpyinfo
->x_focus_frame
)
4547 return dpyinfo
->x_focus_frame
;
4549 /* Mac version may get events, such as a menu bar click, even when
4550 all the frames are invisible. In this case, we regard the
4551 event came to the selected frame. */
4552 return SELECTED_FRAME ();
4556 /* Return the current position of the mouse.
4557 *FP should be a frame which indicates which display to ask about.
4559 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4560 and *PART to the frame, window, and scroll bar part that the mouse
4561 is over. Set *X and *Y to the portion and whole of the mouse's
4562 position on the scroll bar.
4564 If the mouse movement started elsewhere, set *FP to the frame the
4565 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4568 Set *TIME to the server time-stamp for the time at which the mouse
4569 was at this position.
4571 Don't store anything if we don't have a valid set of values to report.
4573 This clears the mouse_moved flag, so we can wait for the next mouse
4577 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4580 Lisp_Object
*bar_window
;
4581 enum scroll_bar_part
*part
;
4583 unsigned long *time
;
4589 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4590 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4593 Lisp_Object frame
, tail
;
4595 /* Clear the mouse-moved flag for every frame on this display. */
4596 FOR_EACH_FRAME (tail
, frame
)
4597 XFRAME (frame
)->mouse_moved
= 0;
4599 last_mouse_scroll_bar
= Qnil
;
4601 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4602 && FRAME_LIVE_P (last_mouse_frame
))
4603 f1
= last_mouse_frame
;
4605 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4609 /* Ok, we found a frame. Store all the values.
4610 last_mouse_glyph is a rectangle used to reduce the
4611 generation of mouse events. To not miss any motion
4612 events, we must divide the frame into rectangles of the
4613 size of the smallest character that could be displayed
4614 on it, i.e. into the same rectangles that matrices on
4615 the frame are divided into. */
4618 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4619 GetMouse (&mouse_pos
);
4620 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4622 last_mouse_glyph_frame
= f1
;
4627 XSETINT (*x
, mouse_pos
.h
);
4628 XSETINT (*y
, mouse_pos
.v
);
4629 *time
= last_mouse_movement_time
;
4637 /************************************************************************
4639 ************************************************************************/
4641 #ifdef USE_TOOLKIT_SCROLL_BARS
4643 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4644 static OSStatus install_scroll_bar_timer
P_ ((void));
4645 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4646 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4647 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4648 struct input_event
*));
4649 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4651 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4652 ControlPartCode
, Point
,
4653 struct input_event
*));
4654 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4655 struct input_event
*));
4656 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4657 Point
, struct input_event
*));
4658 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4661 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4663 static int last_scroll_bar_part
;
4665 static EventLoopTimerRef scroll_bar_timer
;
4667 static int scroll_bar_timer_event_posted_p
;
4669 #define SCROLL_BAR_FIRST_DELAY 0.5
4670 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4673 scroll_bar_timer_callback (timer
, data
)
4674 EventLoopTimerRef timer
;
4679 err
= mac_post_mouse_moved_event ();
4681 scroll_bar_timer_event_posted_p
= 1;
4685 install_scroll_bar_timer ()
4687 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4689 if (scroll_bar_timer_callbackUPP
== NULL
)
4690 scroll_bar_timer_callbackUPP
=
4691 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4693 if (scroll_bar_timer
== NULL
)
4694 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4695 kEventDurationForever as delays. */
4697 InstallEventLoopTimer (GetCurrentEventLoop (),
4698 kEventDurationForever
, kEventDurationForever
,
4699 scroll_bar_timer_callbackUPP
, NULL
,
4704 set_scroll_bar_timer (delay
)
4705 EventTimerInterval delay
;
4707 if (scroll_bar_timer
== NULL
)
4708 install_scroll_bar_timer ();
4710 scroll_bar_timer_event_posted_p
= 0;
4712 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4716 control_part_code_to_scroll_bar_part (part_code
)
4717 ControlPartCode part_code
;
4721 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4722 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4723 case kControlPageUpPart
: return scroll_bar_above_handle
;
4724 case kControlPageDownPart
: return scroll_bar_below_handle
;
4725 case kControlIndicatorPart
: return scroll_bar_handle
;
4732 construct_scroll_bar_click (bar
, part
, bufp
)
4733 struct scroll_bar
*bar
;
4735 struct input_event
*bufp
;
4737 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4738 bufp
->frame_or_window
= bar
->window
;
4742 XSETINT (bufp
->x
, 0);
4743 XSETINT (bufp
->y
, 0);
4744 bufp
->modifiers
= 0;
4748 get_control_part_bounds (ch
, part_code
, rect
)
4750 ControlPartCode part_code
;
4753 RgnHandle region
= NewRgn ();
4756 err
= GetControlRegion (ch
, part_code
, region
);
4758 GetRegionBounds (region
, rect
);
4759 DisposeRgn (region
);
4765 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4766 struct scroll_bar
*bar
;
4767 ControlPartCode part_code
;
4769 struct input_event
*bufp
;
4771 int part
= control_part_code_to_scroll_bar_part (part_code
);
4776 if (part
!= scroll_bar_handle
)
4778 construct_scroll_bar_click (bar
, part
, bufp
);
4779 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4780 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4781 bar
->dragging
= Qnil
;
4787 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4788 kControlIndicatorPart
, &r
);
4789 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4792 last_scroll_bar_part
= part
;
4793 tracked_scroll_bar
= bar
;
4797 x_scroll_bar_handle_release (bar
, bufp
)
4798 struct scroll_bar
*bar
;
4799 struct input_event
*bufp
;
4801 if (last_scroll_bar_part
!= scroll_bar_handle
4802 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4803 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4805 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4806 set_scroll_bar_timer (kEventDurationForever
);
4808 last_scroll_bar_part
= -1;
4809 bar
->dragging
= Qnil
;
4810 tracked_scroll_bar
= NULL
;
4814 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4816 struct scroll_bar
*bar
;
4818 struct input_event
*bufp
;
4820 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4822 if (last_scroll_bar_part
== scroll_bar_handle
)
4827 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4828 kControlIndicatorPart
, &r
);
4830 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4831 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4833 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4834 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4838 if (top
> top_range
)
4841 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4842 XSETINT (bufp
->x
, top
);
4843 XSETINT (bufp
->y
, top_range
);
4847 ControlPartCode part_code
;
4848 int unhilite_p
= 0, part
;
4850 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4854 part
= control_part_code_to_scroll_bar_part (part_code
);
4856 switch (last_scroll_bar_part
)
4858 case scroll_bar_above_handle
:
4859 case scroll_bar_below_handle
:
4860 if (part
!= scroll_bar_above_handle
4861 && part
!= scroll_bar_below_handle
)
4865 case scroll_bar_up_arrow
:
4866 case scroll_bar_down_arrow
:
4867 if (part
!= scroll_bar_up_arrow
4868 && part
!= scroll_bar_down_arrow
)
4875 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4876 else if (part
!= last_scroll_bar_part
4877 || scroll_bar_timer_event_posted_p
)
4879 construct_scroll_bar_click (bar
, part
, bufp
);
4880 last_scroll_bar_part
= part
;
4881 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4882 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4887 /* Set the thumb size and position of scroll bar BAR. We are currently
4888 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4891 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4892 struct scroll_bar
*bar
;
4893 int portion
, position
, whole
;
4895 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4896 int value
, viewsize
, maximum
;
4898 if (XINT (bar
->track_height
) == 0)
4901 if (whole
<= portion
)
4902 value
= 0, viewsize
= 1, maximum
= 0;
4907 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4908 scale
= (float) maximum
/ (whole
- portion
);
4909 value
= position
* scale
+ 0.5f
;
4910 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
4915 if (GetControlViewSize (ch
) != viewsize
4916 || GetControl32BitValue (ch
) != value
4917 || GetControl32BitMaximum (ch
) != maximum
)
4919 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4920 SetControlVisibility (ch
, false, false);
4922 SetControl32BitMaximum (ch
, maximum
);
4923 SetControl32BitValue (ch
, value
);
4924 SetControlViewSize (ch
, viewsize
);
4926 SetControlVisibility (ch
, true, true);
4932 #endif /* USE_TOOLKIT_SCROLL_BARS */
4936 /************************************************************************
4937 Scroll bars, general
4938 ************************************************************************/
4940 /* Create a scroll bar and return the scroll bar vector for it. W is
4941 the Emacs window on which to create the scroll bar. TOP, LEFT,
4942 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4945 static struct scroll_bar
*
4946 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4948 int top
, left
, width
, height
, disp_top
, disp_height
;
4950 struct frame
*f
= XFRAME (w
->frame
);
4951 struct scroll_bar
*bar
4952 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4960 r
.right
= left
+ width
;
4961 r
.bottom
= disp_top
+ disp_height
;
4964 mac_prepare_for_quickdraw (f
);
4966 #if TARGET_API_MAC_CARBON
4967 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4968 #ifdef USE_TOOLKIT_SCROLL_BARS
4971 width
< disp_height
,
4973 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4975 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4976 0, 0, 0, scrollBarProc
, (long) bar
);
4978 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4980 XSETWINDOW (bar
->window
, w
);
4981 XSETINT (bar
->top
, top
);
4982 XSETINT (bar
->left
, left
);
4983 XSETINT (bar
->width
, width
);
4984 XSETINT (bar
->height
, height
);
4985 XSETINT (bar
->start
, 0);
4986 XSETINT (bar
->end
, 0);
4987 bar
->dragging
= Qnil
;
4988 #ifdef USE_TOOLKIT_SCROLL_BARS
4989 bar
->track_top
= Qnil
;
4990 bar
->track_height
= Qnil
;
4991 bar
->min_handle
= Qnil
;
4994 /* Add bar to its frame's list of scroll bars. */
4995 bar
->next
= FRAME_SCROLL_BARS (f
);
4997 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4998 if (!NILP (bar
->next
))
4999 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5006 /* Draw BAR's handle in the proper position.
5008 If the handle is already drawn from START to END, don't bother
5009 redrawing it, unless REBUILD is non-zero; in that case, always
5010 redraw it. (REBUILD is handy for drawing the handle after expose
5013 Normally, we want to constrain the start and end of the handle to
5014 fit inside its rectangle, but if the user is dragging the scroll
5015 bar handle, we want to let them drag it down all the way, so that
5016 the bar's top is as far down as it goes; otherwise, there's no way
5017 to move to the very end of the buffer. */
5019 #ifndef USE_TOOLKIT_SCROLL_BARS
5022 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5023 struct scroll_bar
*bar
;
5027 int dragging
= ! NILP (bar
->dragging
);
5028 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5029 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5030 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5031 int length
= end
- start
;
5033 /* If the display is already accurate, do nothing. */
5035 && start
== XINT (bar
->start
)
5036 && end
== XINT (bar
->end
))
5041 /* Make sure the values are reasonable, and try to preserve the
5042 distance between start and end. */
5045 else if (start
> top_range
)
5047 end
= start
+ length
;
5051 else if (end
> top_range
&& ! dragging
)
5054 /* Store the adjusted setting in the scroll bar. */
5055 XSETINT (bar
->start
, start
);
5056 XSETINT (bar
->end
, end
);
5058 /* Clip the end position, just for display. */
5059 if (end
> top_range
)
5062 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5063 top positions, to make sure the handle is always at least that
5064 many pixels tall. */
5065 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5067 SetControlMinimum (ch
, 0);
5068 /* Don't inadvertently activate deactivated scroll bars */
5069 if (GetControlMaximum (ch
) != -1)
5070 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5072 SetControlValue (ch
, start
);
5073 #if TARGET_API_MAC_CARBON
5074 SetControlViewSize (ch
, end
- start
);
5080 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5082 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5086 x_scroll_bar_remove (bar
)
5087 struct scroll_bar
*bar
;
5089 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5094 mac_prepare_for_quickdraw (f
);
5096 /* Destroy the Mac scroll bar control */
5097 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
5099 /* Disassociate this scroll bar from its window. */
5100 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5106 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5107 that we are displaying PORTION characters out of a total of WHOLE
5108 characters, starting at POSITION. If WINDOW has no scroll bar,
5112 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5114 int portion
, whole
, position
;
5116 struct frame
*f
= XFRAME (w
->frame
);
5117 struct scroll_bar
*bar
;
5118 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5119 int window_y
, window_height
;
5121 /* Get window dimensions. */
5122 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5124 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5125 height
= window_height
;
5127 /* Compute the left edge of the scroll bar area. */
5128 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5130 /* Compute the width of the scroll bar which might be less than
5131 the width of the area reserved for the scroll bar. */
5132 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5133 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5137 /* Compute the left edge of the scroll bar. */
5138 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5141 sb_left
= left
+ width
- sb_width
;
5143 /* Adjustments according to Inside Macintosh to make it look nice */
5145 disp_height
= height
;
5152 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5158 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5162 /* Does the scroll bar exist yet? */
5163 if (NILP (w
->vertical_scroll_bar
))
5166 mac_clear_area (f
, left
, top
, width
, height
);
5168 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5170 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5174 /* It may just need to be moved and resized. */
5177 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5178 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5182 /* If already correctly positioned, do nothing. */
5183 if (!(XINT (bar
->left
) == sb_left
5184 && XINT (bar
->top
) == top
5185 && XINT (bar
->width
) == sb_width
5186 && XINT (bar
->height
) == height
))
5188 /* Since toolkit scroll bars are smaller than the space reserved
5189 for them on the frame, we have to clear "under" them. */
5190 mac_clear_area (f
, left
, top
, width
, height
);
5193 mac_prepare_for_quickdraw (f
);
5196 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5197 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5199 #ifndef USE_TOOLKIT_SCROLL_BARS
5200 if (sb_width
< disp_height
)
5204 /* Remember new settings. */
5205 XSETINT (bar
->left
, sb_left
);
5206 XSETINT (bar
->top
, top
);
5207 XSETINT (bar
->width
, sb_width
);
5208 XSETINT (bar
->height
, height
);
5209 #ifdef USE_TOOLKIT_SCROLL_BARS
5210 bar
->track_top
= Qnil
;
5211 bar
->track_height
= Qnil
;
5212 bar
->min_handle
= Qnil
;
5219 #ifdef USE_TOOLKIT_SCROLL_BARS
5220 if (NILP (bar
->track_top
))
5222 if (sb_width
>= disp_height
5224 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5228 XSETINT (bar
->track_top
, 0);
5229 XSETINT (bar
->track_height
, 0);
5230 XSETINT (bar
->min_handle
, 0);
5234 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5239 SetControl32BitMinimum (ch
, 0);
5240 SetControl32BitMaximum (ch
, 1 << 30);
5241 SetControlViewSize (ch
, 1);
5243 /* Move the scroll bar thumb to the top. */
5244 SetControl32BitValue (ch
, 0);
5245 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5247 /* Move the scroll bar thumb to the bottom. */
5248 SetControl32BitValue (ch
, 1 << 30);
5249 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5251 UnionRect (&r0
, &r1
, &r0
);
5252 XSETINT (bar
->track_top
, r0
.top
);
5253 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5254 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5256 /* Don't show the scroll bar if its height is not enough to
5257 display the scroll bar thumb. */
5258 if (r0
.bottom
- r0
.top
> 0)
5265 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5266 #else /* not USE_TOOLKIT_SCROLL_BARS */
5267 /* Set the scroll bar's current state, unless we're currently being
5269 if (NILP (bar
->dragging
))
5271 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5274 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5277 int start
= ((double) position
* top_range
) / whole
;
5278 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5279 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5282 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5286 /* The following three hooks are used when we're doing a thorough
5287 redisplay of the frame. We don't explicitly know which scroll bars
5288 are going to be deleted, because keeping track of when windows go
5289 away is a real pain - "Can you say set-window-configuration, boys
5290 and girls?" Instead, we just assert at the beginning of redisplay
5291 that *all* scroll bars are to be removed, and then save a scroll bar
5292 from the fiery pit when we actually redisplay its window. */
5294 /* Arrange for all scroll bars on FRAME to be removed at the next call
5295 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5296 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5299 XTcondemn_scroll_bars (frame
)
5302 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5303 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5306 bar
= FRAME_SCROLL_BARS (frame
);
5307 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5308 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5309 XSCROLL_BAR (bar
)->prev
= Qnil
;
5310 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5311 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5312 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5317 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5318 Note that WINDOW isn't necessarily condemned at all. */
5321 XTredeem_scroll_bar (window
)
5322 struct window
*window
;
5324 struct scroll_bar
*bar
;
5327 /* We can't redeem this window's scroll bar if it doesn't have one. */
5328 if (NILP (window
->vertical_scroll_bar
))
5331 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5333 /* Unlink it from the condemned list. */
5334 f
= XFRAME (WINDOW_FRAME (window
));
5335 if (NILP (bar
->prev
))
5337 /* If the prev pointer is nil, it must be the first in one of
5339 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5340 /* It's not condemned. Everything's fine. */
5342 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5343 window
->vertical_scroll_bar
))
5344 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5346 /* If its prev pointer is nil, it must be at the front of
5347 one or the other! */
5351 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5353 if (! NILP (bar
->next
))
5354 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5356 bar
->next
= FRAME_SCROLL_BARS (f
);
5358 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5359 if (! NILP (bar
->next
))
5360 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5363 /* Remove all scroll bars on FRAME that haven't been saved since the
5364 last call to `*condemn_scroll_bars_hook'. */
5367 XTjudge_scroll_bars (f
)
5370 Lisp_Object bar
, next
;
5372 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5374 /* Clear out the condemned list now so we won't try to process any
5375 more events on the hapless scroll bars. */
5376 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5378 for (; ! NILP (bar
); bar
= next
)
5380 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5382 x_scroll_bar_remove (b
);
5385 b
->next
= b
->prev
= Qnil
;
5388 /* Now there should be no references to the condemned scroll bars,
5389 and they should get garbage-collected. */
5393 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5394 is set to something other than NO_EVENT, it is enqueued.
5396 This may be called from a signal handler, so we have to ignore GC
5400 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5401 struct scroll_bar
*bar
;
5402 ControlPartCode part_code
;
5403 const EventRecord
*er
;
5404 struct input_event
*bufp
;
5406 int win_y
, top_range
;
5408 if (! GC_WINDOWP (bar
->window
))
5411 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5412 bufp
->frame_or_window
= bar
->window
;
5415 bar
->dragging
= Qnil
;
5419 case kControlUpButtonPart
:
5420 bufp
->part
= scroll_bar_up_arrow
;
5422 case kControlDownButtonPart
:
5423 bufp
->part
= scroll_bar_down_arrow
;
5425 case kControlPageUpPart
:
5426 bufp
->part
= scroll_bar_above_handle
;
5428 case kControlPageDownPart
:
5429 bufp
->part
= scroll_bar_below_handle
;
5431 #if TARGET_API_MAC_CARBON
5434 case kControlIndicatorPart
:
5436 if (er
->what
== mouseDown
)
5437 bar
->dragging
= make_number (0);
5438 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5439 bufp
->part
= scroll_bar_handle
;
5443 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5444 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5446 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5450 if (! NILP (bar
->dragging
))
5451 win_y
-= XINT (bar
->dragging
);
5455 if (win_y
> top_range
)
5458 XSETINT (bufp
->x
, win_y
);
5459 XSETINT (bufp
->y
, top_range
);
5462 #ifndef USE_TOOLKIT_SCROLL_BARS
5464 /* Handle some mouse motion while someone is dragging the scroll bar.
5466 This may be called from a signal handler, so we have to ignore GC
5470 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5471 struct scroll_bar
*bar
;
5475 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5477 last_mouse_movement_time
= t
;
5480 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5482 /* If we're dragging the bar, display it. */
5483 if (! GC_NILP (bar
->dragging
))
5485 /* Where should the handle be now? */
5486 int new_start
= y_pos
- 24;
5488 if (new_start
!= XINT (bar
->start
))
5490 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5492 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5497 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5499 /* Return information to the user about the current position of the mouse
5500 on the scroll bar. */
5503 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5505 Lisp_Object
*bar_window
;
5506 enum scroll_bar_part
*part
;
5508 unsigned long *time
;
5510 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5511 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5512 #if TARGET_API_MAC_CARBON
5513 WindowPtr wp
= GetControlOwner (ch
);
5515 WindowPtr wp
= (*ch
)->contrlOwner
;
5518 struct frame
*f
= mac_window_to_frame (wp
);
5519 int win_y
, top_range
;
5521 SetPortWindowPort (wp
);
5523 GetMouse (&mouse_pos
);
5525 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5526 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5528 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5532 if (! NILP (bar
->dragging
))
5533 win_y
-= XINT (bar
->dragging
);
5537 if (win_y
> top_range
)
5541 *bar_window
= bar
->window
;
5543 if (! NILP (bar
->dragging
))
5544 *part
= scroll_bar_handle
;
5545 else if (win_y
< XINT (bar
->start
))
5546 *part
= scroll_bar_above_handle
;
5547 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5548 *part
= scroll_bar_handle
;
5550 *part
= scroll_bar_below_handle
;
5552 XSETINT (*x
, win_y
);
5553 XSETINT (*y
, top_range
);
5556 last_mouse_scroll_bar
= Qnil
;
5558 *time
= last_mouse_movement_time
;
5562 /* The screen has been cleared so we may have changed foreground or
5563 background colors, and the scroll bars may need to be redrawn.
5564 Clear out the scroll bars, and ask for expose events, so we can
5568 x_scroll_bar_clear (f
)
5571 XTcondemn_scroll_bars (f
);
5572 XTjudge_scroll_bars (f
);
5576 /***********************************************************************
5578 ***********************************************************************/
5580 /* Set clipping for output in glyph row ROW. W is the window in which
5581 we operate. GC is the graphics context to set clipping in.
5583 ROW may be a text row or, e.g., a mode line. Text rows must be
5584 clipped to the interior of the window dedicated to text display,
5585 mode lines must be clipped to the whole window. */
5588 x_clip_to_row (w
, row
, area
, gc
)
5590 struct glyph_row
*row
;
5594 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5596 int window_x
, window_y
, window_width
;
5598 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5600 clip_rect
.left
= window_x
;
5601 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5602 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5603 clip_rect
.right
= clip_rect
.left
+ window_width
;
5604 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5606 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5610 /* Draw a hollow box cursor on window W in glyph row ROW. */
5613 x_draw_hollow_cursor (w
, row
)
5615 struct glyph_row
*row
;
5617 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5618 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5619 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5622 struct glyph
*cursor_glyph
;
5625 /* Get the glyph the cursor is on. If we can't tell because
5626 the current matrix is invalid or such, give up. */
5627 cursor_glyph
= get_phys_cursor_glyph (w
);
5628 if (cursor_glyph
== NULL
)
5631 /* Compute frame-relative coordinates for phys cursor. */
5632 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5633 wd
= w
->phys_cursor_width
;
5635 /* The foreground of cursor_gc is typically the same as the normal
5636 background color, which can cause the cursor box to be invisible. */
5637 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5638 if (dpyinfo
->scratch_cursor_gc
)
5639 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5641 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5642 GCForeground
, &xgcv
);
5643 gc
= dpyinfo
->scratch_cursor_gc
;
5645 /* Set clipping, draw the rectangle, and reset clipping again. */
5646 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5647 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5648 mac_reset_clip_rectangles (dpy
, gc
);
5652 /* Draw a bar cursor on window W in glyph row ROW.
5654 Implementation note: One would like to draw a bar cursor with an
5655 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5656 Unfortunately, I didn't find a font yet that has this property set.
5660 x_draw_bar_cursor (w
, row
, width
, kind
)
5662 struct glyph_row
*row
;
5664 enum text_cursor_kinds kind
;
5666 struct frame
*f
= XFRAME (w
->frame
);
5667 struct glyph
*cursor_glyph
;
5669 /* If cursor is out of bounds, don't draw garbage. This can happen
5670 in mini-buffer windows when switching between echo area glyphs
5672 cursor_glyph
= get_phys_cursor_glyph (w
);
5673 if (cursor_glyph
== NULL
)
5676 /* If on an image, draw like a normal cursor. That's usually better
5677 visible than drawing a bar, esp. if the image is large so that
5678 the bar might not be in the window. */
5679 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5681 struct glyph_row
*row
;
5682 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5683 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5687 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5688 Window window
= FRAME_MAC_WINDOW (f
);
5689 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5690 unsigned long mask
= GCForeground
| GCBackground
;
5691 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5694 /* If the glyph's background equals the color we normally draw
5695 the bar cursor in, the bar cursor in its normal color is
5696 invisible. Use the glyph's foreground color instead in this
5697 case, on the assumption that the glyph's colors are chosen so
5698 that the glyph is legible. */
5699 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5700 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5702 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5705 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5708 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5709 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5713 width
= FRAME_CURSOR_WIDTH (f
);
5714 width
= min (cursor_glyph
->pixel_width
, width
);
5716 w
->phys_cursor_width
= width
;
5717 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5719 if (kind
== BAR_CURSOR
)
5720 mac_fill_rectangle (f
, gc
,
5721 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5722 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5723 width
, row
->height
);
5725 mac_fill_rectangle (f
, gc
,
5726 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5727 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5728 row
->height
- width
),
5729 cursor_glyph
->pixel_width
,
5732 mac_reset_clip_rectangles (dpy
, gc
);
5737 /* RIF: Define cursor CURSOR on frame F. */
5740 mac_define_frame_cursor (f
, cursor
)
5744 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5746 if (dpyinfo
->x_focus_frame
== f
)
5747 SetThemeCursor (cursor
);
5751 /* RIF: Clear area on frame F. */
5754 mac_clear_frame_area (f
, x
, y
, width
, height
)
5756 int x
, y
, width
, height
;
5758 mac_clear_area (f
, x
, y
, width
, height
);
5762 /* RIF: Draw cursor on window W. */
5765 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5767 struct glyph_row
*glyph_row
;
5769 int cursor_type
, cursor_width
;
5774 w
->phys_cursor_type
= cursor_type
;
5775 w
->phys_cursor_on_p
= 1;
5777 if (glyph_row
->exact_window_width_line_p
5778 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5780 glyph_row
->cursor_in_fringe_p
= 1;
5781 draw_fringe_bitmap (w
, glyph_row
, 0);
5784 switch (cursor_type
)
5786 case HOLLOW_BOX_CURSOR
:
5787 x_draw_hollow_cursor (w
, glyph_row
);
5790 case FILLED_BOX_CURSOR
:
5791 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5795 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5799 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5803 w
->phys_cursor_width
= 0;
5815 #if 0 /* MAC_TODO: no icon support yet. */
5817 x_bitmap_icon (f
, icon
)
5823 if (FRAME_W32_WINDOW (f
) == 0)
5827 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5828 else if (STRINGP (icon
))
5829 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5830 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5831 else if (SYMBOLP (icon
))
5835 if (EQ (icon
, intern ("application")))
5836 name
= (LPCTSTR
) IDI_APPLICATION
;
5837 else if (EQ (icon
, intern ("hand")))
5838 name
= (LPCTSTR
) IDI_HAND
;
5839 else if (EQ (icon
, intern ("question")))
5840 name
= (LPCTSTR
) IDI_QUESTION
;
5841 else if (EQ (icon
, intern ("exclamation")))
5842 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5843 else if (EQ (icon
, intern ("asterisk")))
5844 name
= (LPCTSTR
) IDI_ASTERISK
;
5845 else if (EQ (icon
, intern ("winlogo")))
5846 name
= (LPCTSTR
) IDI_WINLOGO
;
5850 hicon
= LoadIcon (NULL
, name
);
5858 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5863 #endif /* MAC_TODO */
5865 /************************************************************************
5867 ************************************************************************/
5869 /* Display Error Handling functions not used on W32. Listing them here
5870 helps diff stay in step when comparing w32term.c with xterm.c.
5872 x_error_catcher (display, error)
5873 x_catch_errors (dpy)
5874 x_catch_errors_unwind (old_val)
5875 x_check_errors (dpy, format)
5876 x_had_errors_p (dpy)
5877 x_clear_errors (dpy)
5878 x_uncatch_errors (dpy, count)
5880 x_connection_signal (signalnum)
5881 x_connection_closed (dpy, error_message)
5882 x_error_quitter (display, error)
5883 x_error_handler (display, error)
5884 x_io_error_quitter (display)
5889 /* Changing the font of the frame. */
5891 /* Give frame F the font named FONTNAME as its default font, and
5892 return the full name of that font. FONTNAME may be a wildcard
5893 pattern; in that case, we choose some font that fits the pattern.
5894 The return value shows which font we chose. */
5897 x_new_font (f
, fontname
)
5899 register char *fontname
;
5901 struct font_info
*fontp
5902 = FS_LOAD_FONT (f
, fontname
);
5907 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
5908 /* This font is already set in frame F. There's nothing more to
5910 return build_string (fontp
->full_name
);
5912 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5913 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5914 FRAME_FONTSET (f
) = -1;
5916 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5917 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5918 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5920 compute_fringe_widths (f
, 1);
5922 /* Compute the scroll bar width in character columns. */
5923 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5925 int wid
= FRAME_COLUMN_WIDTH (f
);
5926 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5927 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5931 int wid
= FRAME_COLUMN_WIDTH (f
);
5932 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5935 /* Now make the frame display the given font. */
5936 if (FRAME_MAC_WINDOW (f
) != 0)
5938 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5940 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5942 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5945 /* Don't change the size of a tip frame; there's no point in
5946 doing it because it's done in Fx_show_tip, and it leads to
5947 problems because the tip frame has no widget. */
5948 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5949 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5952 return build_string (fontp
->full_name
);
5955 /* Give frame F the fontset named FONTSETNAME as its default fontset,
5956 and return the full name of that fontset. FONTSETNAME may be a
5957 wildcard pattern; in that case, we choose some fontset that fits
5958 the pattern. FONTSETNAME may be a font name for ASCII characters;
5959 in that case, we create a fontset from that font name.
5961 The return value shows which fontset we chose.
5962 If FONTSETNAME specifies the default fontset, return Qt.
5963 If an ASCII font in the specified fontset can't be loaded, return
5967 x_new_fontset (f
, fontsetname
)
5969 Lisp_Object fontsetname
;
5971 int fontset
= fs_query_fontset (fontsetname
, 0);
5974 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
5975 /* This fontset is already set in frame F. There's nothing more
5977 return fontset_name (fontset
);
5978 else if (fontset
== 0)
5979 /* The default fontset can't be the default font. */
5983 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5985 result
= x_new_font (f
, SDATA (fontsetname
));
5987 if (!STRINGP (result
))
5988 /* Can't load ASCII font. */
5992 fontset
= new_fontset_from_font_name (result
);
5994 /* Since x_new_font doesn't update any fontset information, do it now. */
5995 FRAME_FONTSET (f
) = fontset
;
5997 return fontset_name (fontset
);
6001 /***********************************************************************
6002 TODO: W32 Input Methods
6003 ***********************************************************************/
6004 /* Listing missing functions from xterm.c helps diff stay in step.
6006 xim_destroy_callback (xim, client_data, call_data)
6007 xim_open_dpy (dpyinfo, resource_name)
6009 xim_instantiate_callback (display, client_data, call_data)
6010 xim_initialize (dpyinfo, resource_name)
6011 xim_close_dpy (dpyinfo)
6017 mac_get_window_bounds (f
, inner
, outer
)
6019 Rect
*inner
, *outer
;
6021 #if TARGET_API_MAC_CARBON
6022 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6023 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6024 #else /* not TARGET_API_MAC_CARBON */
6025 RgnHandle region
= NewRgn ();
6027 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6028 *inner
= (*region
)->rgnBBox
;
6029 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6030 *outer
= (*region
)->rgnBBox
;
6031 DisposeRgn (region
);
6032 #endif /* not TARGET_API_MAC_CARBON */
6036 mac_handle_origin_change (f
)
6039 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6043 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6045 int pixelwidth
, pixelheight
;
6049 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6050 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6052 if (cols
!= FRAME_COLS (f
)
6053 || rows
!= FRAME_LINES (f
)
6054 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6055 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6057 /* We pass 1 for DELAY since we can't run Lisp code inside of
6059 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6060 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6061 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6062 SET_FRAME_GARBAGED (f
);
6064 /* If cursor was outside the new size, mark it as off. */
6065 mark_window_cursors_off (XWINDOW (f
->root_window
));
6067 /* Clear out any recollection of where the mouse highlighting
6068 was, since it might be in a place that's outside the new
6069 frame size. Actually checking whether it is outside is a
6070 pain in the neck, so don't try--just let the highlighting be
6071 done afresh with new size. */
6072 cancel_mouse_face (f
);
6074 #if TARGET_API_MAC_CARBON
6075 if (f
->output_data
.mac
->hourglass_control
)
6078 mac_prepare_for_quickdraw (f
);
6080 MoveControl (f
->output_data
.mac
->hourglass_control
,
6081 pixelwidth
- HOURGLASS_WIDTH
, 0);
6088 /* Calculate the absolute position in frame F
6089 from its current recorded position values and gravity. */
6092 x_calc_absolute_position (f
)
6095 int width_diff
= 0, height_diff
= 0;
6096 int flags
= f
->size_hint_flags
;
6099 /* We have nothing to do if the current position
6100 is already for the top-left corner. */
6101 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6104 /* Find the offsets of the outside upper-left corner of
6105 the inner window, with respect to the outer window. */
6107 mac_get_window_bounds (f
, &inner
, &outer
);
6110 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6111 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6113 /* Treat negative positions as relative to the leftmost bottommost
6114 position that fits on the screen. */
6115 if (flags
& XNegative
)
6116 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6118 - FRAME_PIXEL_WIDTH (f
)
6121 if (flags
& YNegative
)
6122 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6124 - FRAME_PIXEL_HEIGHT (f
)
6127 /* The left_pos and top_pos
6128 are now relative to the top and left screen edges,
6129 so the flags should correspond. */
6130 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6133 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6134 to really change the position, and 0 when calling from
6135 x_make_frame_visible (in that case, XOFF and YOFF are the current
6136 position values). It is -1 when calling from x_set_frame_parameters,
6137 which means, do adjust for borders but don't change the gravity. */
6140 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6142 register int xoff
, yoff
;
6145 if (change_gravity
> 0)
6149 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6151 f
->size_hint_flags
|= XNegative
;
6153 f
->size_hint_flags
|= YNegative
;
6154 f
->win_gravity
= NorthWestGravity
;
6156 x_calc_absolute_position (f
);
6159 x_wm_set_size_hint (f
, (long) 0, 0);
6161 #if TARGET_API_MAC_CARBON
6162 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6163 /* If the title bar is completely outside the screen, adjust the
6165 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6166 kWindowConstrainMoveRegardlessOfFit
6167 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6168 #if USE_CARBON_EVENTS
6169 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6171 mac_handle_origin_change (f
);
6174 Rect inner
, outer
, screen_rect
, dummy
;
6175 RgnHandle region
= NewRgn ();
6177 mac_get_window_bounds (f
, &inner
, &outer
);
6178 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6179 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6180 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6181 f
->top_pos
+ f
->y_pixels_diff
, false);
6183 /* If the title bar is completely outside the screen, adjust the
6184 position. The variable `outer' holds the title bar rectangle.
6185 The variable `inner' holds slightly smaller one than `outer',
6186 so that the calculation of overlapping may not become too
6188 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6189 outer
= (*region
)->rgnBBox
;
6190 DisposeRgn (region
);
6192 InsetRect (&inner
, 8, 8);
6193 screen_rect
= qd
.screenBits
.bounds
;
6194 screen_rect
.top
+= GetMBarHeight ();
6196 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6198 if (inner
.right
<= screen_rect
.left
)
6199 f
->left_pos
= screen_rect
.left
;
6200 else if (inner
.left
>= screen_rect
.right
)
6201 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6203 if (inner
.bottom
<= screen_rect
.top
)
6204 f
->top_pos
= screen_rect
.top
;
6205 else if (inner
.top
>= screen_rect
.bottom
)
6206 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6208 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6209 f
->top_pos
+ f
->y_pixels_diff
, false);
6217 /* Call this to change the size of frame F's x-window.
6218 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6219 for this size change and subsequent size changes.
6220 Otherwise we leave the window gravity unchanged. */
6223 x_set_window_size (f
, change_gravity
, cols
, rows
)
6228 int pixelwidth
, pixelheight
;
6232 check_frame_size (f
, &rows
, &cols
);
6233 f
->scroll_bar_actual_width
6234 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6236 compute_fringe_widths (f
, 0);
6238 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6239 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6241 f
->win_gravity
= NorthWestGravity
;
6242 x_wm_set_size_hint (f
, (long) 0, 0);
6244 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6246 #if USE_CARBON_EVENTS
6247 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6249 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6251 if (f
->output_data
.mac
->internal_border_width
6252 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6254 mac_clear_window (f
);
6255 f
->output_data
.mac
->internal_border_width
6256 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6259 SET_FRAME_GARBAGED (f
);
6264 /* Mouse warping. */
6266 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6269 x_set_mouse_position (f
, x
, y
)
6275 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6276 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6278 if (pix_x
< 0) pix_x
= 0;
6279 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6281 if (pix_y
< 0) pix_y
= 0;
6282 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6284 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6288 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6297 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
6303 CGWarpMouseCursorPosition (point
);
6306 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6309 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6310 0, 0, 0, 0, pix_x
, pix_y
);
6316 /* focus shifting, raising and lowering. */
6319 x_focus_on_frame (f
)
6322 #if 0 /* This proves to be unpleasant. */
6326 /* I don't think that the ICCCM allows programs to do things like this
6327 without the interaction of the window manager. Whatever you end up
6328 doing with this code, do it to x_unfocus_frame too. */
6329 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6330 RevertToPointerRoot
, CurrentTime
);
6340 /* Raise frame F. */
6346 if (f
->async_visible
)
6349 BringToFront (FRAME_MAC_WINDOW (f
));
6354 /* Lower frame F. */
6360 if (f
->async_visible
)
6363 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6369 XTframe_raise_lower (f
, raise_flag
)
6379 /* Change of visibility. */
6382 mac_handle_visibility_change (f
)
6385 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6386 int visible
= 0, iconified
= 0;
6387 struct input_event buf
;
6389 if (IsWindowVisible (wp
))
6391 if (IsWindowCollapsed (wp
))
6397 if (!f
->async_visible
&& visible
)
6401 /* wait_reading_process_output will notice this and update
6402 the frame's display structures. If we were made
6403 invisible, we should not set garbaged, because that stops
6404 redrawing on Update events. */
6405 SET_FRAME_GARBAGED (f
);
6408 buf
.kind
= DEICONIFY_EVENT
;
6409 XSETFRAME (buf
.frame_or_window
, f
);
6411 kbd_buffer_store_event (&buf
);
6413 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6414 /* Force a redisplay sooner or later to update the
6415 frame titles in case this is the second frame. */
6416 record_asynch_buffer_change ();
6418 else if (f
->async_visible
&& !visible
)
6422 buf
.kind
= ICONIFY_EVENT
;
6423 XSETFRAME (buf
.frame_or_window
, f
);
6425 kbd_buffer_store_event (&buf
);
6428 f
->async_visible
= visible
;
6429 f
->async_iconified
= iconified
;
6432 /* This tries to wait until the frame is really visible.
6433 However, if the window manager asks the user where to position
6434 the frame, this will return before the user finishes doing that.
6435 The frame will not actually be visible at that time,
6436 but it will become visible later when the window manager
6437 finishes with it. */
6440 x_make_frame_visible (f
)
6445 if (! FRAME_VISIBLE_P (f
))
6447 /* We test FRAME_GARBAGED_P here to make sure we don't
6448 call x_set_offset a second time
6449 if we get to x_make_frame_visible a second time
6450 before the window gets really visible. */
6451 if (! FRAME_ICONIFIED_P (f
)
6452 && ! f
->output_data
.mac
->asked_for_visible
)
6454 #if TARGET_API_MAC_CARBON
6455 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6457 struct frame
*sf
= SELECTED_FRAME ();
6458 if (!FRAME_MAC_P (sf
))
6459 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6460 kWindowCenterOnMainScreen
);
6462 RepositionWindow (FRAME_MAC_WINDOW (f
),
6463 FRAME_MAC_WINDOW (sf
),
6464 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6465 kWindowCascadeStartAtParentWindowScreen
6467 kWindowCascadeOnParentWindowScreen
6470 #if USE_CARBON_EVENTS
6471 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6473 mac_handle_origin_change (f
);
6477 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6480 f
->output_data
.mac
->asked_for_visible
= 1;
6482 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6483 ShowWindow (FRAME_MAC_WINDOW (f
));
6486 XFlush (FRAME_MAC_DISPLAY (f
));
6488 /* Synchronize to ensure Emacs knows the frame is visible
6489 before we do anything else. We do this loop with input not blocked
6490 so that incoming events are handled. */
6495 /* This must come after we set COUNT. */
6498 XSETFRAME (frame
, f
);
6500 /* Wait until the frame is visible. Process X events until a
6501 MapNotify event has been seen, or until we think we won't get a
6502 MapNotify at all.. */
6503 for (count
= input_signal_count
+ 10;
6504 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6506 /* Force processing of queued events. */
6509 /* Machines that do polling rather than SIGIO have been
6510 observed to go into a busy-wait here. So we'll fake an
6511 alarm signal to let the handler know that there's something
6512 to be read. We used to raise a real alarm, but it seems
6513 that the handler isn't always enabled here. This is
6515 if (input_polling_used ())
6517 /* It could be confusing if a real alarm arrives while
6518 processing the fake one. Turn it off and let the
6519 handler reset it. */
6520 extern void poll_for_input_1
P_ ((void));
6521 int old_poll_suppress_count
= poll_suppress_count
;
6522 poll_suppress_count
= 1;
6523 poll_for_input_1 ();
6524 poll_suppress_count
= old_poll_suppress_count
;
6527 /* See if a MapNotify event has been processed. */
6528 FRAME_SAMPLE_VISIBILITY (f
);
6533 /* Change from mapped state to withdrawn state. */
6535 /* Make the frame visible (mapped and not iconified). */
6538 x_make_frame_invisible (f
)
6541 /* A deactivate event does not occur when the last visible frame is
6542 made invisible. So if we clear the highlight here, it will not
6543 be rehighlighted when it is made visible. */
6545 /* Don't keep the highlight on an invisible frame. */
6546 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6547 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6552 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6553 that the current position of the window is user-specified, rather than
6554 program-specified, so that when the window is mapped again, it will be
6555 placed at the same location, without forcing the user to position it
6556 by hand again (they have already done that once for this window.) */
6557 x_wm_set_size_hint (f
, (long) 0, 1);
6559 HideWindow (FRAME_MAC_WINDOW (f
));
6563 #if !USE_CARBON_EVENTS
6564 mac_handle_visibility_change (f
);
6568 /* Change window state from mapped to iconified. */
6576 /* A deactivate event does not occur when the last visible frame is
6577 iconified. So if we clear the highlight here, it will not be
6578 rehighlighted when it is deiconified. */
6580 /* Don't keep the highlight on an invisible frame. */
6581 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6582 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6585 if (f
->async_iconified
)
6590 FRAME_SAMPLE_VISIBILITY (f
);
6592 if (! FRAME_VISIBLE_P (f
))
6593 ShowWindow (FRAME_MAC_WINDOW (f
));
6595 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6600 error ("Can't notify window manager of iconification");
6602 #if !USE_CARBON_EVENTS
6603 mac_handle_visibility_change (f
);
6608 /* Free X resources of frame F. */
6611 x_free_frame_resources (f
)
6614 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6615 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6619 if (wp
!= tip_window
)
6620 remove_window_handler (wp
);
6623 mac_prepare_for_quickdraw (f
);
6626 if (wp
== tip_window
)
6627 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6628 closed' event. So we reset tip_window here. */
6631 free_frame_menubar (f
);
6633 if (FRAME_FACE_CACHE (f
))
6634 free_frame_faces (f
);
6638 if (FRAME_SIZE_HINTS (f
))
6639 xfree (FRAME_SIZE_HINTS (f
));
6641 xfree (f
->output_data
.mac
);
6642 f
->output_data
.mac
= NULL
;
6644 if (f
== dpyinfo
->x_focus_frame
)
6646 dpyinfo
->x_focus_frame
= 0;
6647 #if USE_MAC_FONT_PANEL
6648 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6651 if (f
== dpyinfo
->x_focus_event_frame
)
6652 dpyinfo
->x_focus_event_frame
= 0;
6653 if (f
== dpyinfo
->x_highlight_frame
)
6654 dpyinfo
->x_highlight_frame
= 0;
6656 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6658 dpyinfo
->mouse_face_beg_row
6659 = dpyinfo
->mouse_face_beg_col
= -1;
6660 dpyinfo
->mouse_face_end_row
6661 = dpyinfo
->mouse_face_end_col
= -1;
6662 dpyinfo
->mouse_face_window
= Qnil
;
6663 dpyinfo
->mouse_face_deferred_gc
= 0;
6664 dpyinfo
->mouse_face_mouse_frame
= 0;
6671 /* Destroy the X window of frame F. */
6674 x_destroy_window (f
)
6677 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6679 x_free_frame_resources (f
);
6681 dpyinfo
->reference_count
--;
6685 /* Setting window manager hints. */
6687 /* Set the normal size hints for the window manager, for frame F.
6688 FLAGS is the flags word to use--or 0 meaning preserve the flags
6689 that the window now has.
6690 If USER_POSITION is nonzero, we set the USPosition
6691 flag (this is useful when FLAGS is 0). */
6693 x_wm_set_size_hint (f
, flags
, user_position
)
6698 int base_width
, base_height
, width_inc
, height_inc
;
6699 int min_rows
= 0, min_cols
= 0;
6700 XSizeHints
*size_hints
;
6702 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6703 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6704 width_inc
= FRAME_COLUMN_WIDTH (f
);
6705 height_inc
= FRAME_LINE_HEIGHT (f
);
6707 check_frame_size (f
, &min_rows
, &min_cols
);
6709 size_hints
= FRAME_SIZE_HINTS (f
);
6710 if (size_hints
== NULL
)
6712 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6713 bzero (size_hints
, sizeof (XSizeHints
));
6716 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6717 size_hints
->width_inc
= width_inc
;
6718 size_hints
->height_inc
= height_inc
;
6719 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6720 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6721 size_hints
->base_width
= base_width
;
6722 size_hints
->base_height
= base_height
;
6725 size_hints
->flags
= flags
;
6726 else if (user_position
)
6728 size_hints
->flags
&= ~ PPosition
;
6729 size_hints
->flags
|= USPosition
;
6733 #if 0 /* MAC_TODO: hide application instead of iconify? */
6734 /* Used for IconicState or NormalState */
6737 x_wm_set_window_state (f
, state
)
6741 #ifdef USE_X_TOOLKIT
6744 XtSetArg (al
[0], XtNinitialState
, state
);
6745 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6746 #else /* not USE_X_TOOLKIT */
6747 Window window
= FRAME_X_WINDOW (f
);
6749 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6750 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6752 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6753 #endif /* not USE_X_TOOLKIT */
6757 x_wm_set_icon_pixmap (f
, pixmap_id
)
6763 #ifndef USE_X_TOOLKIT
6764 Window window
= FRAME_X_WINDOW (f
);
6769 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6770 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6774 /* It seems there is no way to turn off use of an icon pixmap.
6775 The following line does it, only if no icon has yet been created,
6776 for some window managers. But with mwm it crashes.
6777 Some people say it should clear the IconPixmapHint bit in this case,
6778 but that doesn't work, and the X consortium said it isn't the
6779 right thing at all. Since there is no way to win,
6780 best to explicitly give up. */
6782 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6788 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6792 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6793 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6796 #else /* not USE_X_TOOLKIT */
6798 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6799 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6801 #endif /* not USE_X_TOOLKIT */
6804 #endif /* MAC_TODO */
6807 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6811 #if 0 /* MAC_TODO: no icons on Mac */
6812 #ifdef USE_X_TOOLKIT
6813 Window window
= XtWindow (f
->output_data
.x
->widget
);
6815 Window window
= FRAME_X_WINDOW (f
);
6818 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6819 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6820 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6822 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6823 #endif /* MAC_TODO */
6827 /***********************************************************************
6829 ***********************************************************************/
6831 /* An XLFD pattern is divided into blocks delimited by '*'. This
6832 structure holds information for each block. */
6833 struct xlfdpat_block
6835 /* Length of the pattern string in this block. Non-zero except for
6836 the first and the last blocks. */
6839 /* Pattern string except the last character in this block. The last
6840 character is replaced with NUL in order to use it as a
6842 unsigned char *pattern
;
6844 /* Last character of the pattern string. Must not be '?'. */
6845 unsigned char last_char
;
6847 /* One of the tables for the Boyer-Moore string search. It
6848 specifies the number of positions to proceed for each character
6849 with which the match fails. */
6852 /* The skip value for the last character in the above `skip' is
6853 assigned to `infinity' in order to simplify a loop condition.
6854 The original value is saved here. */
6860 /* Normalized pattern string. "Normalized" means that capital
6861 letters are lowered, blocks are not empty except the first and
6862 the last ones, and trailing '?'s in a block that is not the last
6863 one are moved to the next one. The last character in each block
6864 is replaced with NUL. */
6867 /* Number of characters except '*'s and trailing '?'s in the
6868 normalized pattern string. */
6871 /* Number of trailing '?'s in the normalized pattern string. */
6872 int trailing_anychars
;
6874 /* Number of blocks and information for each block. The latter is
6875 NULL if the pattern is exact (no '*' or '?' in it). */
6877 struct xlfdpat_block
*blocks
;
6881 xlfdpat_destroy (pat
)
6882 struct xlfdpat
*pat
;
6889 xfree (pat
->blocks
);
6896 static struct xlfdpat
*
6897 xlfdpat_create (pattern
)
6898 const char *pattern
;
6900 struct xlfdpat
*pat
;
6901 int nblocks
, i
, skip
;
6902 unsigned char last_char
, *p
, *q
, *anychar_head
;
6903 const unsigned char *ptr
;
6904 struct xlfdpat_block
*blk
;
6906 pat
= xmalloc (sizeof (struct xlfdpat
));
6907 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6909 /* Normalize the pattern string and store it to `pat->buf'. */
6911 anychar_head
= NULL
;
6914 for (ptr
= pattern
; *ptr
; ptr
++)
6916 unsigned char c
= *ptr
;
6919 if (last_char
== '*')
6920 /* ...a** -> ...a* */
6924 if (last_char
== '?')
6926 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6927 /* ...*??* -> ...*?? */
6930 /* ...a??* -> ...a*?? */
6932 *anychar_head
++ = '*';
6940 if (last_char
!= '?')
6944 /* On Mac OS X 10.3, tolower also converts non-ASCII
6945 characters for some locales. */
6949 *q
++ = last_char
= c
;
6953 pat
->nblocks
= nblocks
;
6954 if (last_char
!= '?')
6955 pat
->trailing_anychars
= 0;
6958 pat
->trailing_anychars
= q
- anychar_head
;
6961 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6963 if (anychar_head
== NULL
&& nblocks
== 1)
6965 /* The pattern is exact. */
6970 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6972 /* Divide the normalized pattern into blocks. */
6974 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6979 blk
->len
= p
- blk
->pattern
;
6983 blk
->len
= q
- blk
->pattern
;
6985 /* Setup a table for the Boyer-Moore string search. */
6986 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6989 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6990 blk
->pattern
[blk
->len
- 1] = '\0';
6992 for (skip
= 1; skip
< blk
->len
; skip
++)
6993 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6996 for (i
= 0; i
< 256; i
++)
6997 blk
->skip
[i
] = skip
;
6999 p
= blk
->pattern
+ (blk
->len
- skip
);
7001 blk
->skip
[*p
++] = skip
;
7003 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7010 xlfdpat_exact_p (pat
)
7011 struct xlfdpat
*pat
;
7013 return pat
->blocks
== NULL
;
7016 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7017 that the pattern in *BLK matches with its prefix. Return NULL
7018 there is no such strings. STRING must be lowered in advance. */
7021 xlfdpat_block_match_1 (blk
, string
, start_max
)
7022 struct xlfdpat_block
*blk
;
7023 const unsigned char *string
;
7026 int start
, infinity
;
7028 const unsigned char *s
;
7030 xassert (blk
->len
> 0);
7031 xassert (start_max
+ blk
->len
<= strlen (string
));
7032 xassert (blk
->last_char
!= '?');
7034 /* See the comments in the function `boyer_moore' (search.c) for the
7035 use of `infinity'. */
7036 infinity
= start_max
+ blk
->len
+ 1;
7037 blk
->skip
[blk
->last_char
] = infinity
;
7042 /* Check the last character of the pattern. */
7043 s
= string
+ blk
->len
- 1;
7046 start
+= blk
->skip
[*(s
+ start
)];
7048 while (start
<= start_max
);
7050 if (start
< infinity
)
7051 /* Couldn't find the last character. */
7054 /* No less than `infinity' means we could find the last
7055 character at `s[start - infinity]'. */
7058 /* Check the remaining characters. We prefer making no-'?'
7059 cases faster because the use of '?' is really rare. */
7064 while (*p
++ == *s
++)
7067 while (*(p
- 1) == '?');
7069 if (*(p
- 1) == '\0')
7071 return string
+ start
;
7074 start
+= blk
->last_char_skip
;
7076 while (start
<= start_max
);
7081 #define xlfdpat_block_match(b, s, m) \
7082 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7083 : xlfdpat_block_match_1 (b, s, m))
7085 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7086 matches with STRING. STRING must be lowered in advance. */
7089 xlfdpat_match (pat
, string
)
7090 struct xlfdpat
*pat
;
7091 const unsigned char *string
;
7093 int str_len
, nblocks
, i
, start_max
;
7094 struct xlfdpat_block
*blk
;
7095 const unsigned char *s
;
7097 xassert (pat
->nblocks
> 0);
7099 if (xlfdpat_exact_p (pat
))
7100 return strcmp (pat
->buf
, string
) == 0;
7102 /* The number of the characters in the string must not be smaller
7103 than that in the pattern. */
7104 str_len
= strlen (string
);
7105 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7108 /* Chop off the trailing '?'s. */
7109 str_len
-= pat
->trailing_anychars
;
7111 /* The last block. When it is non-empty, it must match at the end
7113 nblocks
= pat
->nblocks
;
7114 blk
= pat
->blocks
+ (nblocks
- 1);
7116 /* The last block is also the first one. */
7117 return (str_len
== blk
->len
7118 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7119 else if (blk
->len
!= 0)
7120 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7123 /* The first block. When it is non-empty, it must match at the
7124 beginning of the string. */
7128 s
= xlfdpat_block_match (blk
, string
, 0);
7131 string
= s
+ blk
->len
;
7134 /* The rest of the blocks. */
7135 start_max
= str_len
- pat
->nchars
;
7136 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7138 s
= xlfdpat_block_match (blk
, string
, start_max
);
7141 start_max
-= s
- string
;
7142 string
= s
+ blk
->len
;
7149 /***********************************************************************
7151 ***********************************************************************/
7153 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7156 x_get_font_info (f
, font_idx
)
7160 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7163 /* the global font name table */
7164 static char **font_name_table
= NULL
;
7165 static int font_name_table_size
= 0;
7166 static int font_name_count
= 0;
7168 /* Alist linking font family names to Font Manager font family
7169 references (which can also be used as QuickDraw font IDs). We use
7170 an alist because hash tables are not ready when the terminal frame
7171 for Mac OS Classic is created. */
7172 static Lisp_Object fm_font_family_alist
;
7174 /* Hash table linking font family names to ATSU font IDs. */
7175 static Lisp_Object atsu_font_id_hash
;
7176 /* Alist linking Font Manager style to face attributes. */
7177 static Lisp_Object fm_style_face_attributes_alist
;
7178 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7181 /* Alist linking character set strings to Mac text encoding and Emacs
7183 static Lisp_Object Vmac_charset_info_alist
;
7186 create_text_encoding_info_alist ()
7188 Lisp_Object result
= Qnil
, rest
;
7190 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7192 Lisp_Object charset_info
= XCAR (rest
);
7193 Lisp_Object charset
, coding_system
, text_encoding
;
7194 Lisp_Object existing_info
;
7196 if (!(CONSP (charset_info
)
7197 && (charset
= XCAR (charset_info
),
7199 && CONSP (XCDR (charset_info
))
7200 && (text_encoding
= XCAR (XCDR (charset_info
)),
7201 INTEGERP (text_encoding
))
7202 && CONSP (XCDR (XCDR (charset_info
)))
7203 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7204 SYMBOLP (coding_system
))))
7207 existing_info
= assq_no_quit (text_encoding
, result
);
7208 if (NILP (existing_info
))
7209 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7212 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7213 XSETCDR (XCDR (existing_info
),
7214 Fcons (charset
, XCDR (XCDR (existing_info
))));
7222 decode_mac_font_name (name
, size
, coding_system
)
7225 Lisp_Object coding_system
;
7227 struct coding_system coding
;
7230 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7232 for (p
= name
; *p
; p
++)
7233 if (!isascii (*p
) || iscntrl (*p
))
7238 setup_coding_system (coding_system
, &coding
);
7239 coding
.src_multibyte
= 0;
7240 coding
.dst_multibyte
= 1;
7241 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7242 coding
.dst_bytes
= size
;
7243 coding
.destination
= (unsigned char *) alloca (coding
.dst_bytes
);
7245 decode_coding_c_string (&coding
, name
, strlen (name
), Qnil
);
7246 bcopy (coding
.destination
, name
, min (coding
.produced
, size
));
7247 name
[min (coding
.produced
, size
)] = '\0';
7251 /* If there's just one occurrence of '-' in the family name, it is
7252 replaced with '_'. (More than one occurrence of '-' means a
7253 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7254 p
= strchr (name
, '-');
7255 if (p
&& strchr (p
+ 1, '-') == NULL
)
7258 for (p
= name
; *p
; p
++)
7259 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7260 for some locales. */
7267 mac_to_x_fontname (name
, size
, style
, charset
)
7275 char xf
[256], *result
;
7278 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7282 strcpy(foundry
, "Apple");
7283 strcpy(family
, name
);
7286 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7287 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7288 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7290 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7291 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7292 for (p
= result
; *p
; p
++)
7293 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7294 for some locales. */
7301 /* Parse fully-specified and instantiated X11 font spec XF, and store
7302 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7303 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7304 caller must allocate at least 256 and 32 bytes respectively. For
7305 ordinary Mac fonts, the value stored to FAMILY should just be their
7306 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7307 intlfonts collection contain their charset designation in their
7308 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7309 types of font names are handled accordingly. */
7311 const int kDefaultFontSize
= 12;
7314 parse_x_font_name (xf
, family
, size
, style
, charset
)
7321 Str31 foundry
, weight
;
7322 int point_size
, avgwidth
;
7325 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7326 foundry
, family
, weight
, slant
, size
,
7327 &point_size
, &avgwidth
, charset
) != 8
7328 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7329 foundry
, family
, weight
, slant
, size
,
7330 &point_size
, &avgwidth
, charset
) != 8)
7336 *size
= point_size
/ 10;
7337 else if (avgwidth
> 0)
7338 *size
= avgwidth
/ 10;
7341 *size
= kDefaultFontSize
;
7344 if (strcmp (weight
, "bold") == 0)
7349 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7351 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7353 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7355 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7356 but take overlap into account. */
7357 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7358 memcpy (family
, foundry
, foundry_len
);
7359 family
[foundry_len
] = '-';
7360 family
[foundry_len
+ 1 + family_len
] = '-';
7361 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7367 for (p
= family
; *p
; p
++)
7368 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7369 for some locales. */
7378 add_font_name_table_entry (char *font_name
)
7380 if (font_name_table_size
== 0)
7382 font_name_table_size
= 256;
7383 font_name_table
= (char **)
7384 xmalloc (font_name_table_size
* sizeof (char *));
7386 else if (font_name_count
+ 1 >= font_name_table_size
)
7388 font_name_table_size
*= 2;
7389 font_name_table
= (char **)
7390 xrealloc (font_name_table
,
7391 font_name_table_size
* sizeof (char *));
7394 font_name_table
[font_name_count
++] = font_name
;
7398 add_mac_font_name (name
, size
, style
, charset
)
7402 const char *charset
;
7405 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7408 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7409 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7410 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7411 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7418 fm_get_style_from_font (font
)
7422 FMFontStyle style
= normal
;
7425 FMFontFamily font_family
;
7426 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
7428 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
7429 some font (e.g., Optima) even if it is `bold'. */
7430 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
7431 sizeof (mac_style
), &mac_style
, &len
);
7433 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
7434 style
= EndianU16_BtoN (mac_style
);
7436 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
7442 atsu_find_font_from_family_name (family
)
7445 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
7448 Lisp_Object rest
, best
;
7449 FMFontStyle min_style
, style
;
7451 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
7454 return kATSUInvalidFontID
;
7456 rest
= HASH_VALUE (h
, i
);
7457 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
7458 return cons_to_long (rest
);
7460 rest
= Fnreverse (rest
);
7464 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
7467 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
7468 if (style
< min_style
)
7471 if (style
== normal
)
7478 while (!NILP (rest
));
7480 HASH_VALUE (h
, i
) = best
;
7481 return cons_to_long (best
);
7485 fm_style_to_face_attributes (fm_style
)
7486 FMFontStyle fm_style
;
7490 fm_style
&= (bold
| italic
);
7491 tem
= assq_no_quit (make_number (fm_style
),
7492 fm_style_face_attributes_alist
);
7496 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
7497 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
7498 fm_style_face_attributes_alist
=
7499 Fcons (Fcons (make_number (fm_style
), tem
),
7500 fm_style_face_attributes_alist
);
7506 atsu_find_font_family_name (font_id
)
7511 Lisp_Object family
= Qnil
;
7513 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7514 kFontMacintoshPlatform
, kFontNoScript
,
7515 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
7518 family
= make_uninit_string (len
);
7519 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7520 kFontMacintoshPlatform
, kFontNoScript
,
7521 kFontNoLanguage
, len
, SDATA (family
),
7525 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
7531 mac_atsu_font_face_attributes (font_id
)
7534 Lisp_Object family
, style_attrs
;
7536 family
= atsu_find_font_family_name (font_id
);
7539 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
7540 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
7544 /* Sets up the table font_name_table to contain the list of all fonts
7545 in the system the first time the table is used so that the Resource
7546 Manager need not be accessed every time this information is
7550 init_font_name_table ()
7552 #if TARGET_API_MAC_CARBON
7553 FMFontFamilyIterator ffi
;
7554 FMFontFamilyInstanceIterator ffii
;
7556 Lisp_Object text_encoding_info_alist
;
7557 struct gcpro gcpro1
;
7559 text_encoding_info_alist
= create_text_encoding_info_alist ();
7562 #if USE_CG_TEXT_DRAWING
7563 init_cg_text_anti_aliasing_threshold ();
7565 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7566 text_encoding_info_alist
)))
7569 struct Lisp_Hash_Table
*h
;
7571 ItemCount nfonts
, i
;
7572 ATSUFontID
*font_ids
= NULL
;
7573 Lisp_Object prev_family
= Qnil
;
7577 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7578 make_float (DEFAULT_REHASH_SIZE
),
7579 make_float (DEFAULT_REHASH_THRESHOLD
),
7581 h
= XHASH_TABLE (atsu_font_id_hash
);
7583 err
= ATSUFontCount (&nfonts
);
7586 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7587 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7590 for (i
= 0; i
< nfonts
; i
++)
7594 family
= atsu_find_font_family_name (font_ids
[i
]);
7595 if (NILP (family
) || SREF (family
, 0) == '.')
7597 if (!NILP (Fequal (prev_family
, family
)))
7598 family
= prev_family
;
7600 j
= hash_lookup (h
, family
, &hash_code
);
7603 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
7604 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
7607 else if (EQ (prev_family
, family
))
7608 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
7610 prev_family
= family
;
7617 /* Create a dummy instance iterator here to avoid creating and
7618 destroying it in the loop. */
7619 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7621 /* Create an iterator to enumerate the font families. */
7622 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7625 FMDisposeFontFamilyInstanceIterator (&ffii
);
7629 GCPRO1 (text_encoding_info_alist
);
7631 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7637 TextEncoding encoding
;
7638 TextEncodingBase sc
;
7639 Lisp_Object text_encoding_info
, family
;
7641 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7647 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7649 sc
= GetTextEncodingBase (encoding
);
7650 text_encoding_info
= assq_no_quit (make_number (sc
),
7651 text_encoding_info_alist
);
7652 if (NILP (text_encoding_info
))
7653 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7654 text_encoding_info_alist
);
7655 decode_mac_font_name (name
, sizeof (name
),
7656 XCAR (XCDR (text_encoding_info
)));
7657 family
= build_string (name
);
7658 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7660 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7661 fm_font_family_alist
);
7663 /* Point the instance iterator at the current font family. */
7664 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7667 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7670 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7672 if (size
> 0 || style
== normal
)
7673 for (; !NILP (rest
); rest
= XCDR (rest
))
7674 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7680 /* Dispose of the iterators. */
7681 FMDisposeFontFamilyIterator (&ffi
);
7682 FMDisposeFontFamilyInstanceIterator (&ffii
);
7683 #else /* !TARGET_API_MAC_CARBON */
7685 SInt16 fontnum
, old_fontnum
;
7686 int num_mac_fonts
= CountResources('FOND');
7688 Handle font_handle
, font_handle_2
;
7689 short id
, scriptcode
;
7692 struct FontAssoc
*fat
;
7693 struct AsscEntry
*assc_entry
;
7694 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7695 struct gcpro gcpro1
;
7697 GetPort (&port
); /* save the current font number used */
7698 old_fontnum
= port
->txFont
;
7700 text_encoding_info_alist
= create_text_encoding_info_alist ();
7702 GCPRO1 (text_encoding_info_alist
);
7704 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7706 font_handle
= GetIndResource ('FOND', i
);
7710 GetResInfo (font_handle
, &id
, &type
, name
);
7711 GetFNum (name
, &fontnum
);
7713 if (fontnum
== 0 || *name
== '.')
7717 scriptcode
= FontToScript (fontnum
);
7718 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7719 text_encoding_info_alist
);
7720 if (NILP (text_encoding_info
))
7721 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7722 text_encoding_info_alist
);
7723 decode_mac_font_name (name
, sizeof (name
),
7724 XCAR (XCDR (text_encoding_info
)));
7725 family
= build_string (name
);
7726 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7728 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7729 fm_font_family_alist
);
7732 HLock (font_handle
);
7734 if (GetResourceSizeOnDisk (font_handle
)
7735 >= sizeof (struct FamRec
))
7737 fat
= (struct FontAssoc
*) (*font_handle
7738 + sizeof (struct FamRec
));
7740 = (struct AsscEntry
*) (*font_handle
7741 + sizeof (struct FamRec
)
7742 + sizeof (struct FontAssoc
));
7744 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7746 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7748 for (; !NILP (rest
); rest
= XCDR (rest
))
7749 add_mac_font_name (name
, assc_entry
->fontSize
,
7750 assc_entry
->fontStyle
,
7751 SDATA (XCAR (rest
)));
7755 HUnlock (font_handle
);
7756 font_handle_2
= GetNextFOND (font_handle
);
7757 ReleaseResource (font_handle
);
7758 font_handle
= font_handle_2
;
7760 while (ResError () == noErr
&& font_handle
);
7765 TextFont (old_fontnum
);
7766 #endif /* !TARGET_API_MAC_CARBON */
7771 mac_clear_font_name_table ()
7775 for (i
= 0; i
< font_name_count
; i
++)
7776 xfree (font_name_table
[i
]);
7777 xfree (font_name_table
);
7778 font_name_table
= NULL
;
7779 font_name_table_size
= font_name_count
= 0;
7780 fm_font_family_alist
= Qnil
;
7784 enum xlfd_scalable_field_index
7786 XLFD_SCL_PIXEL_SIZE
,
7787 XLFD_SCL_POINT_SIZE
,
7792 static const int xlfd_scalable_fields
[] =
7801 mac_do_list_fonts (pattern
, maxnames
)
7802 const char *pattern
;
7806 Lisp_Object font_list
= Qnil
;
7807 struct xlfdpat
*pat
;
7810 int scl_val
[XLFD_SCL_LAST
], *val
;
7814 if (font_name_table
== NULL
) /* Initialize when first used. */
7815 init_font_name_table ();
7817 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7820 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7821 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7822 fonts are scaled according to the specified size. */
7825 field
= xlfd_scalable_fields
;
7833 if ('0' <= *ptr
&& *ptr
<= '9')
7835 *val
= *ptr
++ - '0';
7836 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7837 *val
= *val
* 10 + *ptr
++ - '0';
7844 ptr
= strchr (ptr
, '-');
7847 while (ptr
&& i
< 14);
7849 if (i
== 14 && ptr
== NULL
)
7851 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7852 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7853 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7854 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7856 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7857 scl_val
[XLFD_SCL_POINT_SIZE
] =
7858 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7859 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7861 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7862 scl_val
[XLFD_SCL_AVGWIDTH
] =
7863 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7864 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7868 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7870 pat
= xlfdpat_create (pattern
);
7874 exact
= xlfdpat_exact_p (pat
);
7876 for (i
= 0; i
< font_name_count
; i
++)
7878 if (xlfdpat_match (pat
, font_name_table
[i
]))
7880 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7881 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7884 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7885 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7887 int former_len
= ptr
- font_name_table
[i
];
7889 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7890 memcpy (scaled
, font_name_table
[i
], former_len
);
7891 sprintf (scaled
+ former_len
,
7892 "-%d-%d-72-72-m-%d-%s",
7893 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7894 scl_val
[XLFD_SCL_POINT_SIZE
],
7895 scl_val
[XLFD_SCL_AVGWIDTH
],
7896 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7898 if (xlfdpat_match (pat
, scaled
))
7900 font_list
= Fcons (build_string (scaled
), font_list
);
7902 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7910 xlfdpat_destroy (pat
);
7915 /* Return a list of names of available fonts matching PATTERN on frame F.
7917 Frame F null means we have not yet created any frame on Mac, and
7918 consult the first display in x_display_list. MAXNAMES sets a limit
7919 on how many fonts to match. */
7922 x_list_fonts (f
, pattern
, size
, maxnames
)
7924 Lisp_Object pattern
;
7927 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7928 struct mac_display_info
*dpyinfo
7929 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7931 xassert (size
<= 0);
7933 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7934 if (NILP (patterns
))
7935 patterns
= Fcons (pattern
, Qnil
);
7937 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7939 pattern
= XCAR (patterns
);
7941 if (!STRINGP (pattern
))
7944 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7945 key
= Fcons (pattern
, make_number (maxnames
));
7947 list
= Fassoc (key
, tem
);
7950 list
= Fcdr_safe (list
);
7951 /* We have a cashed list. Don't have to get the list again. */
7956 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7959 /* MAC_TODO: add code for matching outline fonts here */
7961 /* Now store the result in the cache. */
7962 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7963 Fcons (Fcons (key
, list
),
7964 XCAR (XCDR (dpyinfo
->name_list_element
))));
7967 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7976 /* Check that FONT is valid on frame F. It is if it can be found in F's
7980 x_check_font (f
, font
)
7985 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7987 xassert (font
!= NULL
);
7989 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7990 if (dpyinfo
->font_table
[i
].name
7991 && font
== dpyinfo
->font_table
[i
].font
)
7994 xassert (i
< dpyinfo
->n_fonts
);
7997 #endif /* GLYPH_DEBUG != 0 */
7999 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8000 Note: There are (broken) X fonts out there with invalid XFontStruct
8001 min_bounds contents. For example, handa@etl.go.jp reports that
8002 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8003 have font->min_bounds.width == 0. */
8006 x_font_min_bounds (font
, w
, h
)
8007 MacFontStruct
*font
;
8010 *h
= FONT_HEIGHT (font
);
8011 *w
= font
->min_bounds
.width
;
8015 /* Compute the smallest character width and smallest font height over
8016 all fonts available on frame F. Set the members smallest_char_width
8017 and smallest_font_height in F's x_display_info structure to
8018 the values computed. Value is non-zero if smallest_font_height or
8019 smallest_char_width become smaller than they were before. */
8022 x_compute_min_glyph_bounds (f
)
8026 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8027 MacFontStruct
*font
;
8028 int old_width
= dpyinfo
->smallest_char_width
;
8029 int old_height
= dpyinfo
->smallest_font_height
;
8031 dpyinfo
->smallest_font_height
= 100000;
8032 dpyinfo
->smallest_char_width
= 100000;
8034 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8035 if (dpyinfo
->font_table
[i
].name
)
8037 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8040 font
= (MacFontStruct
*) fontp
->font
;
8041 xassert (font
!= (MacFontStruct
*) ~0);
8042 x_font_min_bounds (font
, &w
, &h
);
8044 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8045 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8048 xassert (dpyinfo
->smallest_char_width
> 0
8049 && dpyinfo
->smallest_font_height
> 0);
8051 return (dpyinfo
->n_fonts
== 1
8052 || dpyinfo
->smallest_char_width
< old_width
8053 || dpyinfo
->smallest_font_height
< old_height
);
8057 /* Determine whether given string is a fully-specified XLFD: all 14
8058 fields are present, none is '*'. */
8061 is_fully_specified_xlfd (p
)
8070 for (i
= 0; i
< 13; i
++)
8072 q
= strchr (p
+ 1, '-');
8075 if (q
- p
== 2 && *(p
+ 1) == '*')
8080 if (strchr (p
+ 1, '-') != NULL
)
8083 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8090 /* mac_load_query_font creates and returns an internal representation
8091 for a font in a MacFontStruct struct. There is really no concept
8092 corresponding to "loading" a font on the Mac. But we check its
8093 existence and find the font number and all other information for it
8094 and store them in the returned MacFontStruct. */
8096 static MacFontStruct
*
8097 mac_load_query_font (f
, fontname
)
8107 static ATSUFontID font_id
;
8108 ATSUStyle mac_style
= NULL
;
8111 #if TARGET_API_MAC_CARBON
8112 TextEncoding encoding
;
8117 MacFontStruct
*font
;
8118 XCharStruct
*space_bounds
= NULL
, *pcm
;
8120 if (is_fully_specified_xlfd (fontname
))
8124 Lisp_Object matched_fonts
;
8126 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8127 if (NILP (matched_fonts
))
8129 name
= SDATA (XCAR (matched_fonts
));
8132 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8136 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8139 static const ATSUAttributeTag tags
[] =
8140 {kATSUFontTag
, kATSUSizeTag
,
8141 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8142 static const ByteCount sizes
[] =
8143 {sizeof (ATSUFontID
), sizeof (Fixed
),
8144 sizeof (Boolean
), sizeof (Boolean
)};
8145 static Fixed size_fixed
;
8146 static Boolean bold_p
, italic_p
;
8147 static const ATSUAttributeValuePtr values
[] =
8148 {&font_id
, &size_fixed
,
8149 &bold_p
, &italic_p
};
8150 static const ATSUFontFeatureType types
[] =
8151 {kAllTypographicFeaturesType
, kDiacriticsType
};
8152 static const ATSUFontFeatureSelector selectors
[] =
8153 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8156 font_id
= atsu_find_font_from_family_name (family
);
8157 if (font_id
== kATSUInvalidFontID
)
8159 size_fixed
= Long2Fix (size
);
8160 bold_p
= (fontface
& bold
) != 0;
8161 italic_p
= (fontface
& italic
) != 0;
8162 err
= ATSUCreateStyle (&mac_style
);
8165 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8169 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8170 tags
, sizes
, values
);
8173 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8176 scriptcode
= kTextEncodingMacUnicode
;
8181 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8185 fontnum
= XINT (XCDR (tmp
));
8186 #if TARGET_API_MAC_CARBON
8187 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8189 scriptcode
= GetTextEncodingBase (encoding
);
8191 scriptcode
= FontToScript (fontnum
);
8195 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8197 font
->mac_fontnum
= fontnum
;
8198 font
->mac_fontsize
= size
;
8199 font
->mac_fontface
= fontface
;
8200 font
->mac_scriptcode
= scriptcode
;
8202 font
->mac_style
= mac_style
;
8203 #if USE_CG_TEXT_DRAWING
8204 font
->cg_font
= NULL
;
8205 font
->cg_glyphs
= NULL
;
8209 /* Apple Japanese (SJIS) font is listed as both
8210 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8211 (Roman script) in init_font_name_table (). The latter should be
8212 treated as a one-byte font. */
8213 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8214 font
->mac_scriptcode
= smRoman
;
8216 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8219 if (font
->mac_style
)
8224 font
->min_byte1
= 0;
8225 font
->max_byte1
= 0xff;
8226 font
->min_char_or_byte2
= 0;
8227 font
->max_char_or_byte2
= 0xff;
8229 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8230 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8231 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8232 pcm_init (font
->bounds
.rows
[0], 0x100);
8234 #if USE_CG_TEXT_DRAWING
8238 ATSFontRef ats_font
;
8240 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8242 /* Use CG text drawing if italic/bold is not synthesized. */
8243 if (err
== noErr
&& style
== fontface
)
8245 ats_font
= FMGetATSFontRefFromFont (font_id
);
8246 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8252 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8253 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8256 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8257 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8258 &font
->ascent
, &font
->descent
,
8260 #if USE_CG_TEXT_DRAWING
8261 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8268 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8270 mac_unload_font (&one_mac_display_info
, font
);
8274 pcm
= font
->bounds
.rows
[0];
8275 for (c
= 0x21; c
<= 0xff; c
++)
8278 /* Soft hyphen is not supported in ATSUI. */
8282 #if USE_CG_TEXT_DRAWING
8283 if (font
->cg_glyphs
)
8293 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8294 pcm
? pcm
+ c
: NULL
,
8295 #if USE_CG_TEXT_DRAWING
8296 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8303 #if USE_CG_TEXT_DRAWING
8304 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8306 /* Don't use CG text drawing if font substitution occurs in
8307 ASCII or Latin-1 characters. */
8308 CGFontRelease (font
->cg_font
);
8309 font
->cg_font
= NULL
;
8310 xfree (font
->cg_glyphs
);
8311 font
->cg_glyphs
= NULL
;
8322 FontInfo the_fontinfo
;
8323 int is_two_byte_font
;
8326 mac_prepare_for_quickdraw (f
);
8328 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8332 TextFace (fontface
);
8334 GetFontInfo (&the_fontinfo
);
8336 font
->ascent
= the_fontinfo
.ascent
;
8337 font
->descent
= the_fontinfo
.descent
;
8339 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8340 || font
->mac_scriptcode
== smTradChinese
8341 || font
->mac_scriptcode
== smSimpChinese
8342 || font
->mac_scriptcode
== smKorean
);
8344 if (is_two_byte_font
)
8348 font
->min_byte1
= 0xa1;
8349 font
->max_byte1
= 0xfe;
8350 font
->min_char_or_byte2
= 0xa1;
8351 font
->max_char_or_byte2
= 0xfe;
8353 /* Use the width of an "ideographic space" of that font
8354 because the_fontinfo.widMax returns the wrong width for
8356 switch (font
->mac_scriptcode
)
8359 font
->min_byte1
= 0x81;
8360 font
->max_byte1
= 0xfc;
8361 font
->min_char_or_byte2
= 0x40;
8362 font
->max_char_or_byte2
= 0xfc;
8363 char_width
= StringWidth("\p\x81\x40");
8366 font
->min_char_or_byte2
= 0x40;
8367 char_width
= StringWidth("\p\xa1\x40");
8370 char_width
= StringWidth("\p\xa1\xa1");
8373 char_width
= StringWidth("\p\xa1\xa1");
8377 font
->bounds
.per_char
= NULL
;
8379 if (fontface
& italic
)
8380 font
->max_bounds
.rbearing
= char_width
+ 1;
8382 font
->max_bounds
.rbearing
= char_width
;
8383 font
->max_bounds
.lbearing
= 0;
8384 font
->max_bounds
.width
= char_width
;
8385 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8386 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8388 font
->min_bounds
= font
->max_bounds
;
8394 font
->min_byte1
= font
->max_byte1
= 0;
8395 font
->min_char_or_byte2
= 0x20;
8396 font
->max_char_or_byte2
= 0xff;
8398 font
->bounds
.per_char
=
8399 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8400 bzero (font
->bounds
.per_char
,
8401 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8403 space_bounds
= font
->bounds
.per_char
;
8404 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
8405 &font
->descent
, space_bounds
, NULL
);
8406 if (err
!= noErr
|| space_bounds
->width
<= 0)
8408 mac_unload_font (&one_mac_display_info
, font
);
8412 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8413 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8421 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8422 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8425 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8427 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8429 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8431 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8433 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
8436 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8438 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8440 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8442 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8444 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
8449 font
->mac_style
== NULL
&&
8451 font
->max_bounds
.width
== font
->min_bounds
.width
8452 && font
->min_bounds
.lbearing
>= 0
8453 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8455 /* Fixed width and no overhangs. */
8456 xfree (font
->bounds
.per_char
);
8457 font
->bounds
.per_char
= NULL
;
8461 #if !defined (MAC_OS8) || USE_ATSUI
8462 /* AppKit and WebKit do some adjustment to the heights of Courier,
8463 Helvetica, and Times. This only works on the environments where
8464 srcCopy text transfer mode is never used. */
8466 #ifdef MAC_OS8 /* implies USE_ATSUI */
8469 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8470 || strcmp (family
, "times") == 0))
8471 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8479 mac_unload_font (dpyinfo
, font
)
8480 struct mac_display_info
*dpyinfo
;
8483 xfree (font
->full_name
);
8485 if (font
->mac_style
)
8489 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8490 if (font
->bounds
.rows
[i
])
8491 xfree (font
->bounds
.rows
[i
]);
8492 xfree (font
->bounds
.rows
);
8493 ATSUDisposeStyle (font
->mac_style
);
8497 if (font
->bounds
.per_char
)
8498 xfree (font
->bounds
.per_char
);
8499 #if USE_CG_TEXT_DRAWING
8501 CGFontRelease (font
->cg_font
);
8502 if (font
->cg_glyphs
)
8503 xfree (font
->cg_glyphs
);
8509 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8510 pointer to the structure font_info while allocating it dynamically.
8511 If SIZE is 0, load any size of font.
8512 If loading is failed, return NULL. */
8515 x_load_font (f
, fontname
, size
)
8517 register char *fontname
;
8520 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8521 Lisp_Object font_names
;
8523 /* Get a list of all the fonts that match this name. Once we
8524 have a list of matching fonts, we compare them against the fonts
8525 we already have by comparing names. */
8526 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8528 if (!NILP (font_names
))
8533 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8534 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8535 if (dpyinfo
->font_table
[i
].name
8536 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8537 SDATA (XCAR (tail
)))
8538 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8539 SDATA (XCAR (tail
)))))
8540 return (dpyinfo
->font_table
+ i
);
8545 /* Load the font and add it to the table. */
8547 struct MacFontStruct
*font
;
8548 struct font_info
*fontp
;
8551 fontname
= (char *) SDATA (XCAR (font_names
));
8554 font
= mac_load_query_font (f
, fontname
);
8559 /* Find a free slot in the font table. */
8560 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8561 if (dpyinfo
->font_table
[i
].name
== NULL
)
8564 /* If no free slot found, maybe enlarge the font table. */
8565 if (i
== dpyinfo
->n_fonts
8566 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8569 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8570 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8572 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8575 fontp
= dpyinfo
->font_table
+ i
;
8576 if (i
== dpyinfo
->n_fonts
)
8579 /* Now fill in the slots of *FONTP. */
8581 bzero (fontp
, sizeof (*fontp
));
8583 fontp
->font_idx
= i
;
8584 fontp
->charset
= -1; /* fs_load_font sets it. */
8585 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8586 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8588 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8590 /* Fixed width font. */
8591 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8598 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8599 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8601 fontp
->space_width
= pcm
->width
;
8603 fontp
->space_width
= FONT_WIDTH (font
);
8607 int width
= pcm
->width
;
8608 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8609 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8610 width
+= pcm
->width
;
8611 fontp
->average_width
= width
/ 95;
8614 fontp
->average_width
= FONT_WIDTH (font
);
8617 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8618 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8620 fontp
->size
= font
->max_bounds
.width
;
8621 fontp
->height
= FONT_HEIGHT (font
);
8623 /* For some font, ascent and descent in max_bounds field is
8624 larger than the above value. */
8625 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8626 if (max_height
> fontp
->height
)
8627 fontp
->height
= max_height
;
8630 /* MAC_TODO: The script encoding is irrelevant in unicode? */
8631 /* The slot `encoding' specifies how to map a character
8632 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8633 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8634 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8635 2:0xA020..0xFF7F). For the moment, we don't know which charset
8636 uses this font. So, we set information in fontp->encoding_type
8637 which is never used by any charset. If mapping can't be
8638 decided, set FONT_ENCODING_NOT_DECIDED. */
8639 if (font
->mac_scriptcode
== smJapanese
)
8640 fontp
->encoding_type
= 4;
8643 fontp
->encoding_type
8644 = (font
->max_byte1
== 0
8646 ? (font
->min_char_or_byte2
< 0x80
8647 ? (font
->max_char_or_byte2
< 0x80
8648 ? 0 /* 0x20..0x7F */
8649 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8650 : 1) /* 0xA0..0xFF */
8652 : (font
->min_byte1
< 0x80
8653 ? (font
->max_byte1
< 0x80
8654 ? (font
->min_char_or_byte2
< 0x80
8655 ? (font
->max_char_or_byte2
< 0x80
8656 ? 0 /* 0x2020..0x7F7F */
8657 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8658 : 3) /* 0x20A0..0x7FFF */
8659 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8660 : (font
->min_char_or_byte2
< 0x80
8661 ? (font
->max_char_or_byte2
< 0x80
8662 ? 2 /* 0xA020..0xFF7F */
8663 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8664 : 1))); /* 0xA0A0..0xFFFF */
8667 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8668 fontp
->baseline_offset
8669 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8670 ? (long) value
: 0);
8671 fontp
->relative_compose
8672 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8673 ? (long) value
: 0);
8674 fontp
->default_ascent
8675 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8676 ? (long) value
: 0);
8678 fontp
->baseline_offset
= 0;
8679 fontp
->relative_compose
= 0;
8680 fontp
->default_ascent
= 0;
8683 /* Set global flag fonts_changed_p to non-zero if the font loaded
8684 has a character with a smaller width than any other character
8685 before, or if the font loaded has a smaller height than any
8686 other font loaded before. If this happens, it will make a
8687 glyph matrix reallocation necessary. */
8688 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8695 /* Return a pointer to struct font_info of a font named FONTNAME for
8696 frame F. If no such font is loaded, return NULL. */
8699 x_query_font (f
, fontname
)
8701 register char *fontname
;
8703 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8706 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8707 if (dpyinfo
->font_table
[i
].name
8708 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8709 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8710 return (dpyinfo
->font_table
+ i
);
8715 /* Find a CCL program for a font specified by FONTP, and set the member
8716 `encoder' of the structure. */
8719 x_find_ccl_program (fontp
)
8720 struct font_info
*fontp
;
8722 Lisp_Object list
, elt
;
8724 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8728 && STRINGP (XCAR (elt
))
8729 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8735 struct ccl_program
*ccl
8736 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8738 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8741 fontp
->font_encoder
= ccl
;
8745 #if USE_MAC_FONT_PANEL
8746 /* Whether Font Panel has been shown before. The first call to font
8747 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8748 slow. This variable is used for deferring such a call as much as
8750 static int font_panel_shown_p
= 0;
8753 mac_font_panel_visible_p ()
8755 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8759 mac_show_hide_font_panel ()
8761 font_panel_shown_p
= 1;
8763 return FPShowHideFontPanel ();
8767 mac_set_font_info_for_selection (f
, face_id
, c
)
8772 EventTargetRef target
= NULL
;
8773 XFontStruct
*font
= NULL
;
8775 if (!mac_font_panel_visible_p ())
8780 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8782 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8786 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8787 face
= FACE_FROM_ID (f
, face_id
);
8793 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8796 if (font
->mac_fontnum
!= -1)
8798 FontSelectionQDStyle qd_style
;
8800 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8801 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8802 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8803 qd_style
.size
= font
->mac_fontsize
;
8804 qd_style
.hasColor
= false;
8806 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8807 1, &qd_style
, target
);
8810 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8811 1, &font
->mac_style
, target
);
8819 /* The Mac Event loop code */
8821 #if !TARGET_API_MAC_CARBON
8823 #include <Quickdraw.h>
8824 #include <Balloons.h>
8825 #include <Devices.h>
8827 #include <Gestalt.h>
8829 #include <Processes.h>
8831 #include <ToolUtils.h>
8832 #include <TextUtils.h>
8833 #include <Dialogs.h>
8836 #include <Resources.h>
8841 #endif /* ! TARGET_API_MAC_CARBON */
8846 #define DEFAULT_NUM_COLS 80
8848 #define MIN_DOC_SIZE 64
8849 #define MAX_DOC_SIZE 32767
8851 #define EXTRA_STACK_ALLOC (256 * 1024)
8853 #define ARGV_STRING_LIST_ID 129
8854 #define ABOUT_ALERT_ID 128
8855 #define RAM_TOO_LARGE_ALERT_ID 129
8857 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8858 Lisp_Object Qreverse
;
8861 /* Modifier associated with the control key, or nil to ignore. */
8862 Lisp_Object Vmac_control_modifier
;
8864 /* Modifier associated with the option key, or nil to ignore. */
8865 Lisp_Object Vmac_option_modifier
;
8867 /* Modifier associated with the command key, or nil to ignore. */
8868 Lisp_Object Vmac_command_modifier
;
8870 /* Modifier associated with the function key, or nil to ignore. */
8871 Lisp_Object Vmac_function_modifier
;
8873 /* True if the option and command modifiers should be used to emulate
8874 a three button mouse */
8875 Lisp_Object Vmac_emulate_three_button_mouse
;
8877 #if USE_CARBON_EVENTS
8878 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8879 mouse-2, instead of mouse-3. */
8880 int mac_wheel_button_is_mouse_2
;
8882 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8883 for processing before Emacs sees it. */
8884 int mac_pass_command_to_system
;
8886 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8887 for processing before Emacs sees it. */
8888 int mac_pass_control_to_system
;
8891 /* Points to the variable `inev' in the function XTread_socket. It is
8892 used for passing an input event to the function back from
8893 Carbon/Apple event handlers. */
8894 static struct input_event
*read_socket_inev
= NULL
;
8896 /* Whether or not the screen configuration has changed. */
8897 static int mac_screen_config_changed
= 0;
8899 Point saved_menu_event_location
;
8902 #if USE_CARBON_EVENTS
8903 static Lisp_Object Qhi_command
;
8905 extern Lisp_Object Qwindow
;
8906 static Lisp_Object Qtoolbar_switch_mode
;
8908 #if USE_MAC_FONT_PANEL
8909 extern Lisp_Object Qfont
;
8910 static Lisp_Object Qpanel_closed
, Qselection
;
8913 static TSMDocumentID tsm_document_id
;
8914 static Lisp_Object Qtext_input
;
8915 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8916 static Lisp_Object Vmac_ts_active_input_overlay
;
8917 extern Lisp_Object Qbefore_string
;
8918 static Lisp_Object Vmac_ts_script_language_on_focus
;
8919 static Lisp_Object saved_ts_script_language_on_focus
;
8920 static ScriptLanguageRecord saved_ts_language
;
8921 static Component saved_ts_component
;
8924 extern int mac_ready_for_apple_events
;
8925 extern Lisp_Object Qundefined
;
8926 extern void init_apple_event_handler
P_ ((void));
8927 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8928 Lisp_Object
*, Lisp_Object
*,
8930 extern OSErr init_coercion_handler
P_ ((void));
8933 extern OSErr install_drag_handler
P_ ((WindowRef
));
8934 extern void remove_drag_handler
P_ ((WindowRef
));
8936 /* Showing help echo string during menu tracking */
8937 extern OSStatus install_menu_target_item_handler
P_ ((WindowPtr
));
8939 #if USE_CARBON_EVENTS
8941 extern void init_service_handler ();
8942 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8945 /* Window Event Handler */
8946 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8949 OSStatus
install_window_handler (WindowPtr
);
8951 extern void init_emacs_passwd_dir ();
8952 extern int emacs_main (int, char **, char **);
8954 extern void initialize_applescript();
8955 extern void terminate_applescript();
8957 /* Table for translating Mac keycode to X keysym values. Contributed
8959 Mapping for special keys is now identical to that in Apple X11
8960 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8961 on the right of the Cmd key on laptops, and fn + `enter' (->
8963 static const unsigned char keycode_to_xkeysym_table
[] = {
8964 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8965 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8966 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8968 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8969 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8970 /*0x38*/ 0, 0, 0, 0,
8971 /*0x3C*/ 0, 0, 0, 0,
8973 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8974 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8975 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8976 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8978 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8979 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8980 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8981 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8983 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8984 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8985 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8986 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8988 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8989 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8990 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8991 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8995 /* Table for translating Mac keycode with the laptop `fn' key to that
8996 without it. Destination symbols in comments are keys on US
8997 keyboard, and they may not be the same on other types of keyboards.
8998 If the destination is identical to the source (f1 ... f12), it
8999 doesn't map `fn' key to a modifier. */
9000 static const unsigned char fn_keycode_to_keycode_table
[] = {
9001 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9002 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9003 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9005 /*0x30*/ 0, 0, 0, 0,
9006 /*0x34*/ 0, 0, 0, 0,
9007 /*0x38*/ 0, 0, 0, 0,
9008 /*0x3C*/ 0, 0, 0, 0,
9010 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9011 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9012 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9013 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9015 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9016 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9017 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9018 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9020 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9021 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9022 /*0x68*/ 0, 0, 0, 0,
9023 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9025 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9026 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9027 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9030 #endif /* MAC_OSX */
9033 #if USE_CARBON_EVENTS
9034 mac_to_emacs_modifiers (UInt32 mods
)
9036 mac_to_emacs_modifiers (EventModifiers mods
)
9039 unsigned int result
= 0;
9040 if (mods
& shiftKey
)
9041 result
|= shift_modifier
;
9043 /* Deactivated to simplify configuration:
9044 if Vmac_option_modifier is non-NIL, we fully process the Option
9045 key. Otherwise, we only process it if an additional Ctrl or Command
9046 is pressed. That way the system may convert the character to a
9048 if ((mods & optionKey) &&
9049 (( !NILP(Vmac_option_modifier) ||
9050 ((mods & cmdKey) || (mods & controlKey))))) */
9052 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9053 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9055 result
|= XUINT(val
);
9057 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9058 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9060 result
|= XUINT(val
);
9062 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9063 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9065 result
|= XUINT(val
);
9069 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9070 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9072 result
|= XUINT(val
);
9080 mac_mapped_modifiers (modifiers
)
9083 UInt32 mapped_modifiers_all
=
9084 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9085 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9086 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9089 mapped_modifiers_all
|=
9090 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9093 return mapped_modifiers_all
& modifiers
;
9097 mac_get_emulated_btn ( UInt32 modifiers
)
9100 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9101 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9102 if (modifiers
& cmdKey
)
9103 result
= cmdIs3
? 2 : 1;
9104 else if (modifiers
& optionKey
)
9105 result
= cmdIs3
? 1 : 2;
9110 #if TARGET_API_MAC_CARBON
9111 /***** Code to handle C-g testing *****/
9112 extern int quit_char
;
9113 extern int make_ctrl_char
P_ ((int));
9116 mac_quit_char_key_p (modifiers
, key_code
)
9117 UInt32 modifiers
, key_code
;
9120 unsigned long some_state
= 0;
9121 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9122 int c
, emacs_modifiers
;
9124 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9125 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9126 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9127 if (char_code
& ~0xff)
9130 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9131 if (emacs_modifiers
& ctrl_modifier
)
9132 c
= make_ctrl_char (char_code
);
9134 c
|= (emacs_modifiers
9135 & (meta_modifier
| alt_modifier
9136 | hyper_modifier
| super_modifier
));
9138 return c
== quit_char
;
9142 #if USE_CARBON_EVENTS
9143 /* Obtains the event modifiers from the event ref and then calls
9144 mac_to_emacs_modifiers. */
9146 mac_event_to_emacs_modifiers (EventRef eventRef
)
9149 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9150 sizeof (UInt32
), NULL
, &mods
);
9151 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9152 GetEventClass(eventRef
) == kEventClassMouse
)
9154 mods
&= ~(optionKey
| cmdKey
);
9156 return mac_to_emacs_modifiers (mods
);
9159 /* Given an event ref, return the code to use for the mouse button
9160 code in the emacs input_event. */
9162 mac_get_mouse_btn (EventRef ref
)
9164 EventMouseButton result
= kEventMouseButtonPrimary
;
9165 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9166 sizeof (EventMouseButton
), NULL
, &result
);
9169 case kEventMouseButtonPrimary
:
9170 if (NILP (Vmac_emulate_three_button_mouse
))
9174 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9175 sizeof (UInt32
), NULL
, &mods
);
9176 return mac_get_emulated_btn(mods
);
9178 case kEventMouseButtonSecondary
:
9179 return mac_wheel_button_is_mouse_2
? 2 : 1;
9180 case kEventMouseButtonTertiary
:
9181 case 4: /* 4 is the number for the mouse wheel button */
9182 return mac_wheel_button_is_mouse_2
? 1 : 2;
9188 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9189 events. However the click of the mouse wheel is not converted to a
9190 mouseDown or mouseUp event. Likewise for dead key events. This
9191 calls ConvertEventRefToEventRecord, but then checks to see if it is
9192 a mouse up/down, or a dead key Carbon event that has not been
9193 converted, and if so, converts it by hand (to be picked up in the
9194 XTread_socket loop). */
9195 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9198 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9204 switch (GetEventClass (eventRef
))
9206 case kEventClassMouse
:
9207 switch (GetEventKind (eventRef
))
9209 case kEventMouseDown
:
9210 eventRec
->what
= mouseDown
;
9215 eventRec
->what
= mouseUp
;
9224 case kEventClassKeyboard
:
9225 switch (GetEventKind (eventRef
))
9227 case kEventRawKeyDown
:
9229 goto keystroke_common
;
9230 case kEventRawKeyRepeat
:
9232 goto keystroke_common
;
9233 case kEventRawKeyUp
:
9237 unsigned char char_codes
;
9240 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9241 typeChar
, NULL
, sizeof (char),
9244 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9245 typeUInt32
, NULL
, sizeof (UInt32
),
9249 eventRec
->what
= action
;
9250 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9267 /* Need where and when. */
9270 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9271 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9272 /* Use two step process because new event modifiers are 32-bit
9273 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9274 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9275 NULL
, sizeof (UInt32
), NULL
, &mods
);
9276 eventRec
->modifiers
= mods
;
9278 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9290 Handle menubar_handle
;
9291 MenuHandle menu_handle
;
9293 menubar_handle
= GetNewMBar (128);
9294 if(menubar_handle
== NULL
)
9296 SetMenuBar (menubar_handle
);
9299 #if !TARGET_API_MAC_CARBON
9300 menu_handle
= GetMenuHandle (M_APPLE
);
9301 if(menu_handle
!= NULL
)
9302 AppendResMenu (menu_handle
,'DRVR');
9310 do_init_managers (void)
9312 #if !TARGET_API_MAC_CARBON
9313 InitGraf (&qd
.thePort
);
9315 FlushEvents (everyEvent
, 0);
9320 #endif /* !TARGET_API_MAC_CARBON */
9323 #if !TARGET_API_MAC_CARBON
9324 /* set up some extra stack space for use by emacs */
9325 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9327 /* MaxApplZone must be called for AppleScript to execute more
9328 complicated scripts */
9331 #endif /* !TARGET_API_MAC_CARBON */
9335 do_check_ram_size (void)
9337 SInt32 physical_ram_size
, logical_ram_size
;
9339 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
9340 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
9341 || physical_ram_size
> (1 << VALBITS
)
9342 || logical_ram_size
> (1 << VALBITS
))
9344 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
9348 #endif /* MAC_OS8 */
9351 do_window_update (WindowPtr win
)
9353 struct frame
*f
= mac_window_to_frame (win
);
9357 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
9359 if (win
!= tip_window
)
9361 if (f
->async_visible
== 0)
9363 /* Update events may occur when a frame gets iconified. */
9365 f
->async_visible
= 1;
9366 f
->async_iconified
= 0;
9367 SET_FRAME_GARBAGED (f
);
9373 #if TARGET_API_MAC_CARBON
9374 RgnHandle region
= NewRgn ();
9376 GetPortVisibleRegion (GetWindowPort (win
), region
);
9377 GetRegionBounds (region
, &r
);
9378 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9380 mac_prepare_for_quickdraw (f
);
9382 UpdateControls (win
, region
);
9383 DisposeRgn (region
);
9385 r
= (*win
->visRgn
)->rgnBBox
;
9386 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9387 UpdateControls (win
, win
->visRgn
);
9396 is_emacs_window (WindowPtr win
)
9398 Lisp_Object tail
, frame
;
9403 FOR_EACH_FRAME (tail
, frame
)
9404 if (FRAME_MAC_P (XFRAME (frame
)))
9405 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9416 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9418 err
= ActivateTSMDocument (tsm_document_id
);
9422 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9423 && EQ (saved_ts_script_language_on_focus
, Qt
))
9424 slptr
= &saved_ts_language
;
9425 else if (CONSP (Vmac_ts_script_language_on_focus
)
9426 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9427 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9428 && CONSP (saved_ts_script_language_on_focus
)
9429 && EQ (XCAR (saved_ts_script_language_on_focus
),
9430 XCAR (Vmac_ts_script_language_on_focus
))
9431 && EQ (XCDR (saved_ts_script_language_on_focus
),
9432 XCDR (Vmac_ts_script_language_on_focus
)))
9434 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9435 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9442 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9443 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
9444 kKeyboardInputMethodClass
);
9446 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
9449 err
= SetTextServiceLanguage (slptr
);
9451 /* Seems to be needed on Mac OS X 10.2. */
9453 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
9463 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9465 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
9467 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
9469 err
= GetTextServiceLanguage (&saved_ts_language
);
9471 slptr
= &saved_ts_language
;
9473 else if (CONSP (Vmac_ts_script_language_on_focus
)
9474 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9475 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
9477 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9478 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9484 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9485 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
9486 kKeyboardInputMethodClass
);
9488 GetDefaultInputMethod (&saved_ts_component
, slptr
);
9492 err
= DeactivateTSMDocument (tsm_document_id
);
9498 #if !TARGET_API_MAC_CARBON
9500 do_apple_menu (SInt16 menu_item
)
9503 SInt16 da_driver_refnum
;
9505 if (menu_item
== I_ABOUT
)
9506 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9509 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9510 da_driver_refnum
= OpenDeskAcc (item_name
);
9513 #endif /* !TARGET_API_MAC_CARBON */
9515 /* Handle drags in size box. Based on code contributed by Ben
9516 Mesander and IM - Window Manager A. */
9519 do_grow_window (w
, e
)
9521 const EventRecord
*e
;
9524 int rows
, columns
, width
, height
;
9525 struct frame
*f
= mac_window_to_frame (w
);
9526 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
9527 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
9528 #if TARGET_API_MAC_CARBON
9534 if (size_hints
->flags
& PMinSize
)
9536 min_width
= size_hints
->min_width
;
9537 min_height
= size_hints
->min_height
;
9539 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9541 #if TARGET_API_MAC_CARBON
9542 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
9544 height
= new_rect
.bottom
- new_rect
.top
;
9545 width
= new_rect
.right
- new_rect
.left
;
9547 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9548 /* see if it really changed size */
9551 height
= HiWord (grow_size
);
9552 width
= LoWord (grow_size
);
9555 if (width
!= FRAME_PIXEL_WIDTH (f
)
9556 || height
!= FRAME_PIXEL_HEIGHT (f
))
9558 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9559 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9561 x_set_window_size (f
, 0, columns
, rows
);
9566 #if TARGET_API_MAC_CARBON
9568 mac_get_ideal_size (f
)
9571 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9572 WindowPtr w
= FRAME_MAC_WINDOW (f
);
9575 int height
, width
, columns
, rows
;
9577 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9578 ideal_size
.v
= dpyinfo
->height
;
9579 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
9580 /* Adjust the standard size according to character boundaries. */
9581 width
= standard_rect
.right
- standard_rect
.left
;
9582 height
= standard_rect
.bottom
- standard_rect
.top
;
9583 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9584 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9585 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9586 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9592 /* Handle clicks in zoom box. Calculation of "standard state" based
9593 on code in IM - Window Manager A and code contributed by Ben
9594 Mesander. The standard state of an Emacs window is 80-characters
9595 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9598 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9600 Rect zoom_rect
, port_rect
;
9602 struct frame
*f
= mac_window_to_frame (w
);
9603 #if TARGET_API_MAC_CARBON
9604 Point ideal_size
= mac_get_ideal_size (f
);
9606 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9607 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
9608 && port_rect
.left
== zoom_rect
.left
9609 && port_rect
.top
== zoom_rect
.top
)
9610 zoom_in_or_out
= inZoomIn
;
9612 zoom_in_or_out
= inZoomOut
;
9615 mac_clear_window (f
);
9617 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
9618 #else /* not TARGET_API_MAC_CARBON */
9621 int w_title_height
, rows
;
9622 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9624 GetPort (&save_port
);
9626 SetPortWindowPort (w
);
9628 /* Clear window to avoid flicker. */
9629 EraseRect (&(w
->portRect
));
9630 if (zoom_in_or_out
== inZoomOut
)
9632 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9633 LocalToGlobal (&top_left
);
9635 /* calculate height of window's title bar */
9636 w_title_height
= top_left
.v
- 1
9637 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9639 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9640 zoom_rect
= qd
.screenBits
.bounds
;
9641 zoom_rect
.top
+= w_title_height
;
9642 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9644 zoom_rect
.right
= zoom_rect
.left
9645 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9647 /* Adjust the standard size according to character boundaries. */
9648 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9650 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9652 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9656 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9658 SetPort (save_port
);
9659 #endif /* not TARGET_API_MAC_CARBON */
9661 #if !USE_CARBON_EVENTS
9662 /* retrieve window size and update application values */
9663 #if TARGET_API_MAC_CARBON
9664 GetWindowPortBounds (w
, &port_rect
);
9666 port_rect
= w
->portRect
;
9668 height
= port_rect
.bottom
- port_rect
.top
;
9669 width
= port_rect
.right
- port_rect
.left
;
9671 mac_handle_size_change (f
, width
, height
);
9672 mac_handle_origin_change (f
);
9677 mac_store_apple_event (class, id
, desc
)
9678 Lisp_Object
class, id
;
9681 struct input_event buf
;
9685 buf
.kind
= MAC_APPLE_EVENT
;
9688 XSETFRAME (buf
.frame_or_window
,
9689 mac_focus_frame (&one_mac_display_info
));
9690 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9691 is safe to use them during read_socket_hook. */
9692 buf
.arg
= mac_aedesc_to_lisp (desc
);
9693 kbd_buffer_store_event (&buf
);
9696 #if TARGET_API_MAC_CARBON
9698 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9699 event
, num_params
, names
, types
)
9702 Lisp_Object class_key
, id_key
;
9705 const EventParamName
*names
;
9706 const EventParamType
*types
;
9708 OSStatus err
= eventNotHandledErr
;
9709 Lisp_Object binding
;
9711 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9712 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9714 if (INTEGERP (binding
))
9715 err
= XINT (binding
);
9718 AppleEvent apple_event
;
9719 err
= create_apple_event_from_event_ref (event
, num_params
,
9724 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9725 AEDisposeDesc (&apple_event
);
9726 mac_wakeup_from_rne ();
9735 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9741 struct input_event buf
;
9745 buf
.kind
= DRAG_N_DROP_EVENT
;
9746 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9747 buf
.timestamp
= TickCount () * (1000 / 60);
9748 XSETINT (buf
.x
, mouse_pos
.h
);
9749 XSETINT (buf
.y
, mouse_pos
.v
);
9750 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9751 buf
.arg
= mac_aedesc_to_lisp (desc
);
9752 kbd_buffer_store_event (&buf
);
9756 #if USE_CARBON_EVENTS
9757 static pascal OSStatus
9758 mac_handle_command_event (next_handler
, event
, data
)
9759 EventHandlerCallRef next_handler
;
9763 OSStatus result
, err
;
9765 static const EventParamName names
[] =
9766 {kEventParamDirectObject
, kEventParamKeyModifiers
};
9767 static const EventParamType types
[] =
9768 {typeHICommand
, typeUInt32
};
9769 int num_params
= sizeof (names
) / sizeof (names
[0]);
9771 result
= CallNextEventHandler (next_handler
, event
);
9772 if (result
!= eventNotHandledErr
)
9775 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9776 NULL
, sizeof (HICommand
), NULL
, &command
);
9778 if (err
!= noErr
|| command
.commandID
== 0)
9779 return eventNotHandledErr
;
9781 /* A HI command event is mapped to an Apple event whose event class
9782 symbol is `hi-command' and event ID is its command ID. */
9783 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9785 event
, num_params
, names
, types
);
9786 return err
== noErr
? noErr
: eventNotHandledErr
;
9790 init_command_handler ()
9792 static const EventTypeSpec specs
[] =
9793 {{kEventClassCommand
, kEventCommandProcess
}};
9794 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9796 if (handle_command_eventUPP
== NULL
)
9797 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9798 return InstallApplicationEventHandler (handle_command_eventUPP
,
9799 GetEventTypeCount (specs
), specs
,
9803 static pascal OSStatus
9804 mac_handle_window_event (next_handler
, event
, data
)
9805 EventHandlerCallRef next_handler
;
9810 OSStatus result
, err
;
9813 XSizeHints
*size_hints
;
9815 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9816 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9818 return eventNotHandledErr
;
9820 f
= mac_window_to_frame (wp
);
9821 switch (GetEventKind (event
))
9823 case kEventWindowUpdate
:
9824 result
= CallNextEventHandler (next_handler
, event
);
9825 if (result
!= eventNotHandledErr
)
9828 do_window_update (wp
);
9831 case kEventWindowGetIdealSize
:
9832 result
= CallNextEventHandler (next_handler
, event
);
9833 if (result
!= eventNotHandledErr
)
9837 Point ideal_size
= mac_get_ideal_size (f
);
9839 err
= SetEventParameter (event
, kEventParamDimensions
,
9840 typeQDPoint
, sizeof (Point
), &ideal_size
);
9846 case kEventWindowBoundsChanging
:
9847 result
= CallNextEventHandler (next_handler
, event
);
9848 if (result
!= eventNotHandledErr
)
9851 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9852 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9856 size_hints
= FRAME_SIZE_HINTS (f
);
9857 if ((attributes
& kWindowBoundsChangeUserResize
)
9858 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9859 == (PResizeInc
| PBaseSize
| PMinSize
)))
9864 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9865 typeQDRectangle
, NULL
, sizeof (Rect
),
9870 width
= bounds
.right
- bounds
.left
;
9871 height
= bounds
.bottom
- bounds
.top
;
9873 if (width
< size_hints
->min_width
)
9874 width
= size_hints
->min_width
;
9876 width
= size_hints
->base_width
9877 + (int) ((width
- size_hints
->base_width
)
9878 / (float) size_hints
->width_inc
+ .5)
9879 * size_hints
->width_inc
;
9881 if (height
< size_hints
->min_height
)
9882 height
= size_hints
->min_height
;
9884 height
= size_hints
->base_height
9885 + (int) ((height
- size_hints
->base_height
)
9886 / (float) size_hints
->height_inc
+ .5)
9887 * size_hints
->height_inc
;
9889 bounds
.right
= bounds
.left
+ width
;
9890 bounds
.bottom
= bounds
.top
+ height
;
9891 SetEventParameter (event
, kEventParamCurrentBounds
,
9892 typeQDRectangle
, sizeof (Rect
), &bounds
);
9897 case kEventWindowBoundsChanged
:
9898 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9899 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9903 if (attributes
& kWindowBoundsChangeSizeChanged
)
9907 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9908 typeQDRectangle
, NULL
, sizeof (Rect
),
9914 width
= bounds
.right
- bounds
.left
;
9915 height
= bounds
.bottom
- bounds
.top
;
9916 mac_handle_size_change (f
, width
, height
);
9917 mac_wakeup_from_rne ();
9921 if (attributes
& kWindowBoundsChangeOriginChanged
)
9922 mac_handle_origin_change (f
);
9926 case kEventWindowShown
:
9927 case kEventWindowHidden
:
9928 case kEventWindowExpanded
:
9929 case kEventWindowCollapsed
:
9930 result
= CallNextEventHandler (next_handler
, event
);
9932 mac_handle_visibility_change (f
);
9937 case kEventWindowClose
:
9938 result
= CallNextEventHandler (next_handler
, event
);
9940 struct input_event buf
;
9943 buf
.kind
= DELETE_WINDOW_EVENT
;
9944 XSETFRAME (buf
.frame_or_window
, f
);
9946 kbd_buffer_store_event (&buf
);
9951 case kEventWindowToolbarSwitchMode
:
9952 result
= CallNextEventHandler (next_handler
, event
);
9954 static const EventParamName names
[] = {kEventParamDirectObject
,
9955 kEventParamWindowMouseLocation
,
9956 kEventParamKeyModifiers
,
9957 kEventParamMouseButton
,
9958 kEventParamClickCount
,
9959 kEventParamMouseChord
};
9960 static const EventParamType types
[] = {typeWindowRef
,
9966 int num_params
= sizeof (names
) / sizeof (names
[0]);
9968 err
= mac_store_event_ref_as_apple_event (0, 0,
9970 Qtoolbar_switch_mode
,
9974 return err
== noErr
? noErr
: result
;
9978 case kEventWindowFocusAcquired
:
9979 result
= CallNextEventHandler (next_handler
, event
);
9980 err
= mac_tsm_resume ();
9981 return err
== noErr
? noErr
: result
;
9983 case kEventWindowFocusRelinquish
:
9984 result
= CallNextEventHandler (next_handler
, event
);
9985 err
= mac_tsm_suspend ();
9986 return err
== noErr
? noErr
: result
;
9990 return eventNotHandledErr
;
9993 static pascal OSStatus
9994 mac_handle_mouse_event (next_handler
, event
, data
)
9995 EventHandlerCallRef next_handler
;
9999 OSStatus result
, err
;
10001 switch (GetEventKind (event
))
10003 case kEventMouseWheelMoved
:
10007 EventMouseWheelAxis axis
;
10011 result
= CallNextEventHandler (next_handler
, event
);
10012 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
10015 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
10016 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10020 f
= mac_window_to_frame (wp
);
10021 if (f
!= mac_focus_frame (&one_mac_display_info
))
10024 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
10025 typeMouseWheelAxis
, NULL
,
10026 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
10027 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
10030 err
= GetEventParameter (event
, kEventParamMouseLocation
,
10031 typeQDPoint
, NULL
, sizeof (Point
),
10036 SetPortWindowPort (wp
);
10037 GlobalToLocal (&point
);
10038 if (point
.h
< 0 || point
.v
< 0
10039 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
10040 f
->tool_bar_window
))
10043 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
10044 typeSInt32
, NULL
, sizeof (SInt32
),
10049 read_socket_inev
->kind
= WHEEL_EVENT
;
10050 read_socket_inev
->code
= 0;
10051 read_socket_inev
->modifiers
=
10052 (mac_event_to_emacs_modifiers (event
)
10053 | ((delta
< 0) ? down_modifier
: up_modifier
));
10054 XSETINT (read_socket_inev
->x
, point
.h
);
10055 XSETINT (read_socket_inev
->y
, point
.v
);
10056 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10066 return eventNotHandledErr
;
10069 #if USE_MAC_FONT_PANEL
10070 static pascal OSStatus
10071 mac_handle_font_event (next_handler
, event
, data
)
10072 EventHandlerCallRef next_handler
;
10076 OSStatus result
, err
;
10077 Lisp_Object id_key
;
10079 const EventParamName
*names
;
10080 const EventParamType
*types
;
10081 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
10082 kEventParamATSUFontSize
,
10083 kEventParamFMFontFamily
,
10084 kEventParamFMFontSize
,
10085 kEventParamFontColor
};
10086 static const EventParamType types_sel
[] = {typeATSUFontID
,
10092 result
= CallNextEventHandler (next_handler
, event
);
10093 if (result
!= eventNotHandledErr
)
10096 switch (GetEventKind (event
))
10098 case kEventFontPanelClosed
:
10099 id_key
= Qpanel_closed
;
10105 case kEventFontSelection
:
10106 id_key
= Qselection
;
10107 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
10113 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
10117 return err
== noErr
? noErr
: eventNotHandledErr
;
10122 static pascal OSStatus
10123 mac_handle_text_input_event (next_handler
, event
, data
)
10124 EventHandlerCallRef next_handler
;
10128 OSStatus result
, err
= noErr
;
10129 Lisp_Object id_key
= Qnil
;
10131 const EventParamName
*names
;
10132 const EventParamType
*types
;
10133 static UInt32 seqno_uaia
= 0;
10134 static const EventParamName names_uaia
[] =
10135 {kEventParamTextInputSendComponentInstance
,
10136 kEventParamTextInputSendRefCon
,
10137 kEventParamTextInputSendSLRec
,
10138 kEventParamTextInputSendFixLen
,
10139 kEventParamTextInputSendText
,
10140 kEventParamTextInputSendUpdateRng
,
10141 kEventParamTextInputSendHiliteRng
,
10142 kEventParamTextInputSendClauseRng
,
10143 kEventParamTextInputSendPinRng
,
10144 kEventParamTextInputSendTextServiceEncoding
,
10145 kEventParamTextInputSendTextServiceMacEncoding
,
10146 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
10147 static const EventParamType types_uaia
[] =
10148 {typeComponentInstance
,
10150 typeIntlWritingCode
,
10157 typeTextRangeArray
,
10158 typeTextRangeArray
,
10164 static const EventParamName names_ufke
[] =
10165 {kEventParamTextInputSendComponentInstance
,
10166 kEventParamTextInputSendRefCon
,
10167 kEventParamTextInputSendSLRec
,
10168 kEventParamTextInputSendText
};
10169 static const EventParamType types_ufke
[] =
10170 {typeComponentInstance
,
10172 typeIntlWritingCode
,
10175 result
= CallNextEventHandler (next_handler
, event
);
10177 switch (GetEventKind (event
))
10179 case kEventTextInputUpdateActiveInputArea
:
10180 id_key
= Qupdate_active_input_area
;
10181 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
10182 names
= names_uaia
;
10183 types
= types_uaia
;
10184 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
10185 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
10189 case kEventTextInputUnicodeForKeyEvent
:
10191 EventRef kbd_event
;
10192 UInt32 actual_size
, modifiers
;
10194 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
10195 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
10198 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
10200 sizeof (UInt32
), NULL
, &modifiers
);
10201 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
10202 /* There're mapped modifier keys. Process it in
10204 return eventNotHandledErr
;
10206 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10207 typeUnicodeText
, NULL
, 0, &actual_size
,
10209 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
10213 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10214 typeUnicodeText
, NULL
,
10215 sizeof (UniChar
), NULL
, &code
);
10216 if (err
== noErr
&& code
< 0x80)
10218 /* ASCII character. Process it in XTread_socket. */
10219 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
10223 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
10224 typeUInt32
, NULL
, sizeof (UInt32
),
10226 if (!(err
== noErr
&& key_code
<= 0x7f
10227 && keycode_to_xkeysym_table
[key_code
]))
10230 mac_focus_frame (&one_mac_display_info
);
10232 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
10233 read_socket_inev
->code
= code
;
10234 read_socket_inev
->modifiers
=
10235 mac_to_emacs_modifiers (modifiers
);
10236 read_socket_inev
->modifiers
|=
10237 (extra_keyboard_modifiers
10238 & (meta_modifier
| alt_modifier
10239 | hyper_modifier
| super_modifier
));
10240 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10243 return eventNotHandledErr
;
10247 /* Non-ASCII keystrokes without mapped modifiers are processed
10248 at the Lisp level. */
10249 id_key
= Qunicode_for_key_event
;
10250 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
10251 names
= names_ufke
;
10252 types
= types_ufke
;
10255 case kEventTextInputOffsetToPos
:
10261 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
10262 return eventNotHandledErr
;
10264 /* Strictly speaking, this is not always correct because
10265 previous events may change some states about display. */
10266 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
10268 /* Active input area is displayed in the echo area. */
10269 w
= XWINDOW (echo_area_window
);
10270 f
= WINDOW_XFRAME (w
);
10274 /* Active input area is displayed around the current point. */
10275 f
= SELECTED_FRAME ();
10276 w
= XWINDOW (f
->selected_window
);
10279 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
10280 + WINDOW_LEFT_FRINGE_WIDTH (w
));
10281 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
10282 + FONT_BASE (FRAME_FONT (f
)));
10283 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
10284 LocalToGlobal (&p
);
10285 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
10286 typeQDPoint
, sizeof (typeQDPoint
), &p
);
10294 if (!NILP (id_key
))
10295 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
10299 return err
== noErr
? noErr
: result
;
10305 mac_store_service_event (event
)
10309 Lisp_Object id_key
;
10311 const EventParamName
*names
;
10312 const EventParamType
*types
;
10313 static const EventParamName names_pfm
[] =
10314 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10315 static const EventParamType types_pfm
[] =
10316 {typeCFStringRef
, typeCFStringRef
};
10318 switch (GetEventKind (event
))
10320 case kEventServicePaste
:
10327 case kEventServicePerform
:
10329 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10338 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10344 #endif /* MAC_OSX */
10345 #endif /* USE_CARBON_EVENTS */
10349 install_window_handler (window
)
10352 OSStatus err
= noErr
;
10353 #if USE_CARBON_EVENTS
10354 static const EventTypeSpec specs_window
[] =
10355 {{kEventClassWindow
, kEventWindowUpdate
},
10356 {kEventClassWindow
, kEventWindowGetIdealSize
},
10357 {kEventClassWindow
, kEventWindowBoundsChanging
},
10358 {kEventClassWindow
, kEventWindowBoundsChanged
},
10359 {kEventClassWindow
, kEventWindowShown
},
10360 {kEventClassWindow
, kEventWindowHidden
},
10361 {kEventClassWindow
, kEventWindowExpanded
},
10362 {kEventClassWindow
, kEventWindowCollapsed
},
10363 {kEventClassWindow
, kEventWindowClose
},
10365 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
10368 {kEventClassWindow
, kEventWindowFocusAcquired
},
10369 {kEventClassWindow
, kEventWindowFocusRelinquish
},
10372 static const EventTypeSpec specs_mouse
[] =
10373 {{kEventClassMouse
, kEventMouseWheelMoved
}};
10374 static EventHandlerUPP handle_window_eventUPP
= NULL
;
10375 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
10376 #if USE_MAC_FONT_PANEL
10377 static const EventTypeSpec specs_font
[] =
10378 {{kEventClassFont
, kEventFontPanelClosed
},
10379 {kEventClassFont
, kEventFontSelection
}};
10380 static EventHandlerUPP handle_font_eventUPP
= NULL
;
10383 static const EventTypeSpec specs_text_input
[] =
10384 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
10385 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
10386 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
10387 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
10390 if (handle_window_eventUPP
== NULL
)
10391 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
10392 if (handle_mouse_eventUPP
== NULL
)
10393 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
10394 #if USE_MAC_FONT_PANEL
10395 if (handle_font_eventUPP
== NULL
)
10396 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
10399 if (handle_text_input_eventUPP
== NULL
)
10400 handle_text_input_eventUPP
=
10401 NewEventHandlerUPP (mac_handle_text_input_event
);
10403 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
10404 GetEventTypeCount (specs_window
),
10405 specs_window
, NULL
, NULL
);
10407 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
10408 GetEventTypeCount (specs_mouse
),
10409 specs_mouse
, NULL
, NULL
);
10410 #if USE_MAC_FONT_PANEL
10412 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
10413 GetEventTypeCount (specs_font
),
10414 specs_font
, NULL
, NULL
);
10418 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
10419 GetEventTypeCount (specs_text_input
),
10420 specs_text_input
, window
, NULL
);
10424 err
= install_drag_handler (window
);
10426 err
= install_menu_target_item_handler (window
);
10432 remove_window_handler (window
)
10435 remove_drag_handler (window
);
10440 mac_handle_dm_notification (event
)
10443 mac_screen_config_changed
= 1;
10447 init_dm_notification_handler ()
10450 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
10451 ProcessSerialNumber psn
;
10453 if (handle_dm_notificationUPP
== NULL
)
10454 handle_dm_notificationUPP
=
10455 NewDMNotificationUPP (mac_handle_dm_notification
);
10457 err
= GetCurrentProcess (&psn
);
10459 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
10465 mac_get_screen_info (dpyinfo
)
10466 struct mac_display_info
*dpyinfo
;
10469 /* HasDepth returns true if it is possible to have a 32 bit display,
10470 but this may not be what is actually used. Mac OSX can do better. */
10471 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
10472 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
10475 CGDisplayCount ndisps
;
10476 CGDirectDisplayID
*displays
;
10478 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
10481 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
10482 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
10486 CGRect bounds
= CGRectZero
;
10488 while (ndisps
-- > 0)
10489 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
10490 dpyinfo
->height
= CGRectGetHeight (bounds
);
10491 dpyinfo
->width
= CGRectGetWidth (bounds
);
10495 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
10496 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
10499 #else /* !MAC_OSX */
10501 GDHandle gdh
= GetMainDevice ();
10502 Rect rect
= (**gdh
).gdRect
;
10504 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
10505 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10506 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
10509 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
10510 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
10511 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
10513 dpyinfo
->height
= rect
.bottom
- rect
.top
;
10514 dpyinfo
->width
= rect
.right
- rect
.left
;
10516 #endif /* !MAC_OSX */
10522 profiler_exit_proc ()
10524 ProfilerDump ("\pEmacs.prof");
10529 /* These few functions implement Emacs as a normal Mac application
10530 (almost): set up the heap and the Toolbox, handle necessary system
10531 events plus a few simple menu events. They also set up Emacs's
10532 access to functions defined in the rest of this file. Emacs uses
10533 function hooks to perform all its terminal I/O. A complete list of
10534 these functions appear in termhooks.h. For what they do, read the
10535 comments there and see also w32term.c and xterm.c. What's
10536 noticeably missing here is the event loop, which is normally
10537 present in most Mac application. After performing the necessary
10538 Mac initializations, main passes off control to emacs_main
10539 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10540 (defined further below) to read input. This is where
10541 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10548 #if __profile__ /* is the profiler on? */
10549 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10554 /* set creator and type for files created by MSL */
10555 _fcreator
= MAC_EMACS_CREATOR_CODE
;
10559 do_init_managers ();
10563 #ifndef USE_LSB_TAG
10564 do_check_ram_size ();
10567 init_emacs_passwd_dir ();
10571 init_coercion_handler ();
10573 initialize_applescript ();
10575 init_apple_event_handler ();
10577 init_dm_notification_handler ();
10583 /* set up argv array from STR# resource */
10584 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10588 /* free up AppleScript resources on exit */
10589 atexit (terminate_applescript
);
10591 #if __profile__ /* is the profiler on? */
10592 atexit (profiler_exit_proc
);
10595 /* 3rd param "envp" never used in emacs_main */
10596 (void) emacs_main (argc
, argv
, 0);
10599 /* Never reached - real exit in Fkill_emacs */
10604 #if !USE_CARBON_EVENTS
10605 static RgnHandle mouse_region
= NULL
;
10608 mac_wait_next_event (er
, sleep_time
, dequeue
)
10613 static EventRecord er_buf
= {nullEvent
};
10614 UInt32 target_tick
, current_tick
;
10615 EventMask event_mask
;
10617 if (mouse_region
== NULL
)
10618 mouse_region
= NewRgn ();
10620 event_mask
= everyEvent
;
10621 if (!mac_ready_for_apple_events
)
10622 event_mask
-= highLevelEventMask
;
10624 current_tick
= TickCount ();
10625 target_tick
= current_tick
+ sleep_time
;
10627 if (er_buf
.what
== nullEvent
)
10628 while (!WaitNextEvent (event_mask
, &er_buf
,
10629 target_tick
- current_tick
, mouse_region
))
10631 current_tick
= TickCount ();
10632 if (target_tick
<= current_tick
)
10638 er_buf
.what
= nullEvent
;
10641 #endif /* not USE_CARBON_EVENTS */
10643 #if TARGET_API_MAC_CARBON
10645 mac_post_mouse_moved_event ()
10647 EventRef event
= NULL
;
10650 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
10651 kEventAttributeNone
, &event
);
10656 GetGlobalMouse (&mouse_pos
);
10657 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
10658 sizeof (Point
), &mouse_pos
);
10662 UInt32 modifiers
= GetCurrentKeyModifiers ();
10664 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10665 sizeof (UInt32
), &modifiers
);
10668 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10669 kEventPriorityStandard
);
10671 ReleaseEvent (event
);
10677 mac_set_unicode_keystroke_event (code
, buf
)
10679 struct input_event
*buf
;
10681 int charset_id
, c1
, c2
;
10684 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10686 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10691 /* Emacs calls this whenever it wants to read an input event from the
10694 XTread_socket (sd
, expected
, hold_quit
)
10696 struct input_event
*hold_quit
;
10698 struct input_event inev
;
10700 #if USE_CARBON_EVENTS
10702 EventTargetRef toolbox_dispatcher
;
10705 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10707 if (interrupt_input_blocked
)
10709 interrupt_input_pending
= 1;
10713 interrupt_input_pending
= 0;
10716 /* So people can tell when we have read the available input. */
10717 input_signal_count
++;
10721 #if USE_CARBON_EVENTS
10722 toolbox_dispatcher
= GetEventDispatcherTarget ();
10726 mac_prepare_for_quickdraw (NULL
),
10728 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10729 kEventRemoveFromQueue
, &eventRef
))
10730 #else /* !USE_CARBON_EVENTS */
10731 while (mac_wait_next_event (&er
, 0, true))
10732 #endif /* !USE_CARBON_EVENTS */
10736 unsigned long timestamp
;
10739 inev
.kind
= NO_EVENT
;
10742 #if USE_CARBON_EVENTS
10743 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10745 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10748 #if USE_CARBON_EVENTS
10749 /* Handle new events */
10750 if (!mac_convert_event_ref (eventRef
, &er
))
10752 /* There used to be a handler for the kEventMouseWheelMoved
10753 event here. But as of Mac OS X 10.4, this kind of event
10754 is not directly posted to the main event queue by
10755 two-finger scrolling on the trackpad. Instead, some
10756 private event is posted and it is converted to a wheel
10757 event by the default handler for the application target.
10758 The converted one can be received by a Carbon event
10759 handler installed on a window target. */
10760 read_socket_inev
= &inev
;
10761 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10762 read_socket_inev
= NULL
;
10765 #endif /* USE_CARBON_EVENTS */
10771 WindowPtr window_ptr
;
10772 ControlPartCode part_code
;
10773 int tool_bar_p
= 0;
10775 #if USE_CARBON_EVENTS
10776 /* This is needed to send mouse events like aqua window
10777 buttons to the correct handler. */
10778 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10779 != eventNotHandledErr
)
10782 last_mouse_glyph_frame
= 0;
10784 if (dpyinfo
->grabbed
&& last_mouse_frame
10785 && FRAME_LIVE_P (last_mouse_frame
))
10787 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10788 part_code
= inContent
;
10792 part_code
= FindWindow (er
.where
, &window_ptr
);
10793 if (tip_window
&& window_ptr
== tip_window
)
10795 HideWindow (tip_window
);
10796 part_code
= FindWindow (er
.where
, &window_ptr
);
10800 if (er
.what
!= mouseDown
&&
10801 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10807 f
= mac_focus_frame (dpyinfo
);
10808 saved_menu_event_location
= er
.where
;
10809 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10810 XSETFRAME (inev
.frame_or_window
, f
);
10815 #if TARGET_API_MAC_CARBON
10816 FrontNonFloatingWindow ()
10821 || (mac_window_to_frame (window_ptr
)
10822 != dpyinfo
->x_focus_frame
))
10823 SelectWindow (window_ptr
);
10826 ControlPartCode control_part_code
;
10828 Point mouse_loc
= er
.where
;
10830 ControlKind control_kind
;
10833 f
= mac_window_to_frame (window_ptr
);
10834 /* convert to local coordinates of new window */
10835 SetPortWindowPort (window_ptr
);
10837 GlobalToLocal (&mouse_loc
);
10838 #if TARGET_API_MAC_CARBON
10839 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10840 &control_part_code
);
10843 GetControlKind (ch
, &control_kind
);
10846 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10850 #if USE_CARBON_EVENTS
10851 inev
.code
= mac_get_mouse_btn (eventRef
);
10852 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10854 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10855 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10857 XSETINT (inev
.x
, mouse_loc
.h
);
10858 XSETINT (inev
.y
, mouse_loc
.v
);
10860 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10862 #ifndef USE_TOOLKIT_SCROLL_BARS
10863 /* control_part_code becomes kControlNoPart if
10864 a progress indicator is clicked. */
10865 && control_part_code
!= kControlNoPart
10866 #else /* USE_TOOLKIT_SCROLL_BARS */
10868 && control_kind
.kind
== kControlKindScrollBar
10869 #endif /* MAC_OSX */
10870 #endif /* USE_TOOLKIT_SCROLL_BARS */
10873 struct scroll_bar
*bar
;
10875 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10877 bar
= tracked_scroll_bar
;
10878 #ifndef USE_TOOLKIT_SCROLL_BARS
10879 control_part_code
= kControlIndicatorPart
;
10883 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10884 #ifdef USE_TOOLKIT_SCROLL_BARS
10885 /* Make the "Ctrl-Mouse-2 splits window" work
10886 for toolkit scroll bars. */
10887 if (inev
.modifiers
& ctrl_modifier
)
10888 x_scroll_bar_handle_click (bar
, control_part_code
,
10890 else if (er
.what
== mouseDown
)
10891 x_scroll_bar_handle_press (bar
, control_part_code
,
10894 x_scroll_bar_handle_release (bar
, &inev
);
10895 #else /* not USE_TOOLKIT_SCROLL_BARS */
10896 x_scroll_bar_handle_click (bar
, control_part_code
,
10898 if (er
.what
== mouseDown
10899 && control_part_code
== kControlIndicatorPart
)
10900 tracked_scroll_bar
= bar
;
10902 tracked_scroll_bar
= NULL
;
10903 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10907 Lisp_Object window
;
10908 int x
= mouse_loc
.h
;
10909 int y
= mouse_loc
.v
;
10911 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10912 if (EQ (window
, f
->tool_bar_window
))
10914 if (er
.what
== mouseDown
)
10915 handle_tool_bar_click (f
, x
, y
, 1, 0);
10917 handle_tool_bar_click (f
, x
, y
, 0,
10923 XSETFRAME (inev
.frame_or_window
, f
);
10924 inev
.kind
= MOUSE_CLICK_EVENT
;
10928 if (er
.what
== mouseDown
)
10930 dpyinfo
->grabbed
|= (1 << inev
.code
);
10931 last_mouse_frame
= f
;
10934 last_tool_bar_item
= -1;
10938 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10939 /* If a button is released though it was not
10940 previously pressed, that would be because
10941 of multi-button emulation. */
10942 dpyinfo
->grabbed
= 0;
10944 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10947 /* Ignore any mouse motion that happened before
10948 this event; any subsequent mouse-movement Emacs
10949 events should reflect only motion after the
10952 f
->mouse_moved
= 0;
10954 #ifdef USE_TOOLKIT_SCROLL_BARS
10955 if (inev
.kind
== MOUSE_CLICK_EVENT
10956 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
10957 && (inev
.modifiers
& ctrl_modifier
)))
10962 inev
.modifiers
|= down_modifier
;
10965 inev
.modifiers
|= up_modifier
;
10972 #if TARGET_API_MAC_CARBON
10974 if (IsWindowPathSelectClick (window_ptr
, &er
))
10976 WindowPathSelect (window_ptr
, NULL
, NULL
);
10979 if (part_code
== inProxyIcon
10980 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
10981 != errUserWantsToDragWindow
))
10983 DragWindow (window_ptr
, er
.where
, NULL
);
10984 #else /* not TARGET_API_MAC_CARBON */
10985 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10986 #endif /* not TARGET_API_MAC_CARBON */
10987 /* Update the frame parameters. */
10988 #if !USE_CARBON_EVENTS
10990 struct frame
*f
= mac_window_to_frame (window_ptr
);
10992 if (f
&& !f
->async_iconified
)
10993 mac_handle_origin_change (f
);
10999 if (TrackGoAway (window_ptr
, er
.where
))
11001 inev
.kind
= DELETE_WINDOW_EVENT
;
11002 XSETFRAME (inev
.frame_or_window
,
11003 mac_window_to_frame (window_ptr
));
11007 /* window resize handling added --ben */
11009 do_grow_window (window_ptr
, &er
);
11012 /* window zoom handling added --ben */
11015 if (TrackBox (window_ptr
, er
.where
, part_code
))
11016 do_zoom_window (window_ptr
, part_code
);
11026 #if USE_CARBON_EVENTS
11027 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11028 != eventNotHandledErr
)
11031 do_window_update ((WindowPtr
) er
.message
);
11036 #if USE_CARBON_EVENTS
11037 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11038 != eventNotHandledErr
)
11041 switch ((er
.message
>> 24) & 0x000000FF)
11043 case suspendResumeMessage
:
11045 if (er
.message
& resumeFlag
)
11048 mac_tsm_suspend ();
11052 case mouseMovedMessage
:
11053 #if !USE_CARBON_EVENTS
11054 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
11055 er
.where
.h
+ 1, er
.where
.v
+ 1);
11057 previous_help_echo_string
= help_echo_string
;
11058 help_echo_string
= Qnil
;
11060 if (dpyinfo
->grabbed
&& last_mouse_frame
11061 && FRAME_LIVE_P (last_mouse_frame
))
11062 f
= last_mouse_frame
;
11064 f
= dpyinfo
->x_focus_frame
;
11066 if (dpyinfo
->mouse_face_hidden
)
11068 dpyinfo
->mouse_face_hidden
= 0;
11069 clear_mouse_face (dpyinfo
);
11074 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
11075 Point mouse_pos
= er
.where
;
11077 SetPortWindowPort (wp
);
11079 GlobalToLocal (&mouse_pos
);
11081 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11082 #ifdef USE_TOOLKIT_SCROLL_BARS
11083 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
11085 #else /* not USE_TOOLKIT_SCROLL_BARS */
11086 x_scroll_bar_note_movement (tracked_scroll_bar
,
11088 - XINT (tracked_scroll_bar
->top
),
11089 er
.when
* (1000 / 60));
11090 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11093 /* Generate SELECT_WINDOW_EVENTs when needed. */
11094 if (!NILP (Vmouse_autoselect_window
))
11096 Lisp_Object window
;
11098 window
= window_from_coordinates (f
,
11103 /* Window will be selected only when it is
11104 not selected now and last mouse movement
11105 event was not in it. Minibuffer window
11106 will be selected iff it is active. */
11107 if (WINDOWP (window
)
11108 && !EQ (window
, last_window
)
11109 && !EQ (window
, selected_window
))
11111 inev
.kind
= SELECT_WINDOW_EVENT
;
11112 inev
.frame_or_window
= window
;
11115 last_window
=window
;
11117 if (!note_mouse_movement (f
, &mouse_pos
))
11118 help_echo_string
= previous_help_echo_string
;
11122 /* If the contents of the global variable
11123 help_echo_string has changed, generate a
11125 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
11133 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
11135 #if USE_CARBON_EVENTS
11136 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11137 != eventNotHandledErr
)
11140 if (window_ptr
== tip_window
)
11142 HideWindow (tip_window
);
11146 if (!is_emacs_window (window_ptr
))
11149 if ((er
.modifiers
& activeFlag
) != 0)
11151 /* A window has been activated */
11152 Point mouse_loc
= er
.where
;
11154 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11156 SetPortWindowPort (window_ptr
);
11157 GlobalToLocal (&mouse_loc
);
11158 /* Window-activated event counts as mouse movement,
11159 so update things that depend on mouse position. */
11160 note_mouse_movement (mac_window_to_frame (window_ptr
),
11165 /* A window has been deactivated */
11166 #ifdef USE_TOOLKIT_SCROLL_BARS
11167 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11169 struct input_event event
;
11171 EVENT_INIT (event
);
11172 event
.kind
= NO_EVENT
;
11173 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
11174 if (event
.kind
!= NO_EVENT
)
11176 event
.timestamp
= timestamp
;
11177 kbd_buffer_store_event_hold (&event
, hold_quit
);
11182 dpyinfo
->grabbed
= 0;
11184 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11186 f
= mac_window_to_frame (window_ptr
);
11187 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11189 /* If we move outside the frame, then we're
11190 certainly no longer on any text in the
11192 clear_mouse_face (dpyinfo
);
11193 dpyinfo
->mouse_face_mouse_frame
= 0;
11196 /* Generate a nil HELP_EVENT to cancel a help-echo.
11197 Do it only if there's something to cancel.
11198 Otherwise, the startup message is cleared when the
11199 mouse leaves the frame. */
11200 if (any_help_event_p
)
11210 int keycode
= (er
.message
& keyCodeMask
) >> 8;
11211 static SInt16 last_key_script
= -1;
11212 SInt16 current_key_script
;
11213 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
11215 #if USE_CARBON_EVENTS && defined (MAC_OSX)
11216 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
11218 sizeof (UInt32
), NULL
, &modifiers
);
11220 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
11222 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
11223 /* When using Carbon Events, we need to pass raw keyboard
11224 events to the TSM ourselves. If TSM handles it, it
11225 will pass back noErr, otherwise it will pass back
11226 "eventNotHandledErr" and we can process it
11228 if (!(mapped_modifiers
11229 & ~(mac_pass_command_to_system
? cmdKey
: 0)
11230 & ~(mac_pass_control_to_system
? controlKey
: 0)))
11234 read_socket_inev
= &inev
;
11235 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11236 read_socket_inev
= NULL
;
11237 if (err
!= eventNotHandledErr
)
11241 if (er
.what
== keyUp
)
11246 f
= mac_focus_frame (dpyinfo
);
11248 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
11249 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
11251 clear_mouse_face (dpyinfo
);
11252 dpyinfo
->mouse_face_hidden
= 1;
11255 current_key_script
= GetScriptManagerVariable (smKeyScript
);
11256 if (last_key_script
!= current_key_script
)
11258 struct input_event event
;
11260 EVENT_INIT (event
);
11261 event
.kind
= LANGUAGE_CHANGE_EVENT
;
11263 event
.code
= current_key_script
;
11264 event
.timestamp
= timestamp
;
11265 kbd_buffer_store_event (&event
);
11267 last_key_script
= current_key_script
;
11271 if (inev
.kind
!= NO_EVENT
)
11276 if (mapped_modifiers
& kEventKeyModifierFnMask
11278 && fn_keycode_to_keycode_table
[keycode
])
11279 keycode
= fn_keycode_to_keycode_table
[keycode
];
11281 if (keycode
<= 0x7f && keycode_to_xkeysym_table
[keycode
])
11283 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
11284 inev
.code
= 0xff00 | keycode_to_xkeysym_table
[keycode
];
11286 if (modifiers
& kEventKeyModifierFnMask
11288 && fn_keycode_to_keycode_table
[keycode
] == keycode
)
11289 modifiers
&= ~kEventKeyModifierFnMask
;
11292 else if (mapped_modifiers
)
11294 /* translate the keycode back to determine the
11297 UCKeyboardLayout
*uchr_ptr
= NULL
;
11298 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11300 KeyboardLayoutRef layout
;
11302 err
= KLGetCurrentKeyboardLayout (&layout
);
11304 KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
11305 (const void **) &uchr_ptr
);
11307 static SInt16 last_key_layout_id
= 0;
11308 static Handle uchr_handle
= (Handle
)-1;
11309 SInt16 current_key_layout_id
=
11310 GetScriptVariable (current_key_script
, smScriptKeys
);
11312 if (uchr_handle
== (Handle
)-1
11313 || last_key_layout_id
!= current_key_layout_id
)
11315 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
11316 last_key_layout_id
= current_key_layout_id
;
11319 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
11325 UInt16 key_action
= er
.what
- keyDown
;
11326 UInt32 modifier_key_state
=
11327 (modifiers
& ~mapped_modifiers
) >> 8;
11328 UInt32 keyboard_type
= LMGetKbdType ();
11329 SInt32 dead_key_state
= 0;
11331 UniCharCount actual_length
;
11333 status
= UCKeyTranslate (uchr_ptr
,
11334 keycode
, key_action
,
11335 modifier_key_state
,
11337 kUCKeyTranslateNoDeadKeysMask
,
11339 1, &actual_length
, &code
);
11340 if (status
== noErr
&& actual_length
== 1)
11341 mac_set_unicode_keystroke_event (code
, &inev
);
11343 #endif /* MAC_OSX */
11345 if (inev
.kind
== NO_EVENT
)
11347 /* This code comes from Keyboard Resource,
11348 Appendix C of IM - Text. This is necessary
11349 since shift is ignored in KCHR table
11350 translation when option or command is pressed.
11351 It also does not translate correctly
11352 control-shift chars like C-% so mask off shift
11354 /* Mask off modifier keys that are mapped to some
11355 Emacs modifiers. */
11356 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
11357 /* set high byte of keycode to modifier high byte*/
11358 int new_keycode
= keycode
| new_modifiers
;
11359 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
11360 unsigned long some_state
= 0;
11361 UInt32 new_char_code
;
11363 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
11365 if (new_char_code
== 0)
11366 /* Seems like a dead key. Append up-stroke. */
11367 new_char_code
= KeyTranslate (kchr_ptr
,
11368 new_keycode
| 0x80,
11372 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11373 inev
.code
= new_char_code
& 0xff;
11378 if (inev
.kind
== NO_EVENT
)
11380 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11381 inev
.code
= er
.message
& charCodeMask
;
11384 inev
.modifiers
= mac_to_emacs_modifiers (modifiers
);
11385 inev
.modifiers
|= (extra_keyboard_modifiers
11386 & (meta_modifier
| alt_modifier
11387 | hyper_modifier
| super_modifier
));
11388 XSETFRAME (inev
.frame_or_window
, f
);
11390 #if TARGET_API_MAC_CARBON
11391 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
11392 && inev
.code
>= 0x80 && inev
.modifiers
)
11395 TextEncoding encoding
= kTextEncodingMacRoman
;
11396 TextToUnicodeInfo ttu_info
;
11398 UpgradeScriptInfoToTextEncoding (current_key_script
,
11399 kTextLanguageDontCare
,
11400 kTextRegionDontCare
,
11402 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
11407 ByteCount unicode_len
;
11410 pstr
[1] = inev
.code
;
11411 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
11413 &unicode_len
, &code
);
11414 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
11415 mac_set_unicode_keystroke_event (code
, &inev
);
11416 DisposeTextToUnicodeInfo (&ttu_info
);
11423 case kHighLevelEvent
:
11424 AEProcessAppleEvent (&er
);
11430 #if USE_CARBON_EVENTS
11431 ReleaseEvent (eventRef
);
11434 if (inev
.kind
!= NO_EVENT
)
11436 inev
.timestamp
= timestamp
;
11437 kbd_buffer_store_event_hold (&inev
, hold_quit
);
11442 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
11447 XSETFRAME (frame
, f
);
11453 any_help_event_p
= 1;
11454 gen_help_event (help_echo_string
, frame
, help_echo_window
,
11455 help_echo_object
, help_echo_pos
);
11459 help_echo_string
= Qnil
;
11460 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
11467 /* If the focus was just given to an autoraising frame,
11469 /* ??? This ought to be able to handle more than one such frame. */
11470 if (pending_autoraise_frame
)
11472 x_raise_frame (pending_autoraise_frame
);
11473 pending_autoraise_frame
= 0;
11476 if (mac_screen_config_changed
)
11478 mac_get_screen_info (dpyinfo
);
11479 mac_screen_config_changed
= 0;
11482 #if !USE_CARBON_EVENTS
11483 /* Check which frames are still visible. We do this here because
11484 there doesn't seem to be any direct notification from the Window
11485 Manager that the visibility of a window has changed (at least,
11486 not in all cases). */
11488 Lisp_Object tail
, frame
;
11490 FOR_EACH_FRAME (tail
, frame
)
11492 struct frame
*f
= XFRAME (frame
);
11494 /* The tooltip has been drawn already. Avoid the
11495 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11496 if (EQ (frame
, tip_frame
))
11499 if (FRAME_MAC_P (f
))
11500 mac_handle_visibility_change (f
);
11511 /* Need to override CodeWarrior's input function so no conversion is
11512 done on newlines Otherwise compiled functions in .elc files will be
11513 read incorrectly. Defined in ...:MSL C:MSL
11514 Common:Source:buffer_io.c. */
11517 __convert_to_newlines (unsigned char * p
, size_t * n
)
11519 #pragma unused(p,n)
11523 __convert_from_newlines (unsigned char * p
, size_t * n
)
11525 #pragma unused(p,n)
11531 make_mac_terminal_frame (struct frame
*f
)
11536 XSETFRAME (frame
, f
);
11538 f
->output_method
= output_mac
;
11539 f
->output_data
.mac
= (struct mac_output
*)
11540 xmalloc (sizeof (struct mac_output
));
11541 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
11543 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
11545 FRAME_COLS (f
) = 96;
11546 FRAME_LINES (f
) = 4;
11548 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
11549 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
11551 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
11553 f
->output_data
.mac
->cursor_pixel
= 0;
11554 f
->output_data
.mac
->border_pixel
= 0x00ff00;
11555 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
11556 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
11558 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
11559 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
11560 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
11561 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
11562 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
11563 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
11565 FRAME_FONTSET (f
) = -1;
11566 f
->output_data
.mac
->explicit_parent
= 0;
11569 f
->border_width
= 0;
11571 f
->internal_border_width
= 0;
11576 f
->new_text_cols
= 0;
11577 f
->new_text_lines
= 0;
11579 SetRect (&r
, f
->left_pos
, f
->top_pos
,
11580 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
11581 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
11585 if (!(FRAME_MAC_WINDOW (f
) =
11586 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
11587 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
11589 /* so that update events can find this mac_output struct */
11590 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
11596 /* Need to be initialized for unshow_buffer in window.c. */
11597 selected_window
= f
->selected_window
;
11599 Fmodify_frame_parameters (frame
,
11600 Fcons (Fcons (Qfont
,
11601 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
11602 Fmodify_frame_parameters (frame
,
11603 Fcons (Fcons (Qforeground_color
,
11604 build_string ("black")), Qnil
));
11605 Fmodify_frame_parameters (frame
,
11606 Fcons (Fcons (Qbackground_color
,
11607 build_string ("white")), Qnil
));
11612 /***********************************************************************
11614 ***********************************************************************/
11616 static int mac_initialized
= 0;
11619 mac_make_rdb (xrm_option
)
11620 const char *xrm_option
;
11622 XrmDatabase database
;
11624 database
= xrm_get_preference_database (NULL
);
11626 xrm_merge_string_database (database
, xrm_option
);
11631 struct mac_display_info
*
11632 mac_term_init (display_name
, xrm_option
, resource_name
)
11633 Lisp_Object display_name
;
11635 char *resource_name
;
11637 struct mac_display_info
*dpyinfo
;
11641 if (!mac_initialized
)
11644 mac_initialized
= 1;
11647 if (x_display_list
)
11648 error ("Sorry, this version can only handle one display");
11650 dpyinfo
= &one_mac_display_info
;
11651 bzero (dpyinfo
, sizeof (*dpyinfo
));
11654 dpyinfo
->mac_id_name
11655 = (char *) xmalloc (SCHARS (Vinvocation_name
)
11656 + SCHARS (Vsystem_name
)
11658 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
11659 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11661 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
11662 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
11665 dpyinfo
->reference_count
= 0;
11666 dpyinfo
->resx
= 72.0;
11667 dpyinfo
->resy
= 72.0;
11669 mac_get_screen_info (dpyinfo
);
11671 dpyinfo
->grabbed
= 0;
11672 dpyinfo
->root_window
= NULL
;
11673 dpyinfo
->image_cache
= make_image_cache ();
11675 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11676 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11677 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11678 dpyinfo
->mouse_face_window
= Qnil
;
11679 dpyinfo
->mouse_face_overlay
= Qnil
;
11680 dpyinfo
->mouse_face_hidden
= 0;
11682 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11684 /* Put this display on the chain. */
11685 dpyinfo
->next
= x_display_list
;
11686 x_display_list
= dpyinfo
;
11688 /* Put it on x_display_name_list. */
11689 x_display_name_list
= Fcons (Fcons (display_name
,
11690 Fcons (Qnil
, dpyinfo
->xrdb
)),
11691 x_display_name_list
);
11692 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11699 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11702 x_delete_display (dpyinfo
)
11703 struct mac_display_info
*dpyinfo
;
11707 /* Discard this display from x_display_name_list and x_display_list.
11708 We can't use Fdelq because that can quit. */
11709 if (! NILP (x_display_name_list
)
11710 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11711 x_display_name_list
= XCDR (x_display_name_list
);
11716 tail
= x_display_name_list
;
11717 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11719 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11721 XSETCDR (tail
, XCDR (XCDR (tail
)));
11724 tail
= XCDR (tail
);
11728 if (x_display_list
== dpyinfo
)
11729 x_display_list
= dpyinfo
->next
;
11732 struct x_display_info
*tail
;
11734 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11735 if (tail
->next
== dpyinfo
)
11736 tail
->next
= tail
->next
->next
;
11739 /* Free the font names in the font table. */
11740 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11741 if (dpyinfo
->font_table
[i
].name
)
11743 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11744 xfree (dpyinfo
->font_table
[i
].full_name
);
11745 xfree (dpyinfo
->font_table
[i
].name
);
11748 if (dpyinfo
->font_table
)
11750 if (dpyinfo
->font_table
->font_encoder
)
11751 xfree (dpyinfo
->font_table
->font_encoder
);
11752 xfree (dpyinfo
->font_table
);
11754 if (dpyinfo
->mac_id_name
)
11755 xfree (dpyinfo
->mac_id_name
);
11757 if (x_display_list
== 0)
11759 mac_clear_font_name_table ();
11760 bzero (dpyinfo
, sizeof (*dpyinfo
));
11771 MenuItemIndex menu_index
;
11773 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11774 &menu
, &menu_index
);
11776 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11777 #if USE_CARBON_EVENTS
11778 EnableMenuCommand (NULL
, kHICommandPreferences
);
11779 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11780 &menu
, &menu_index
);
11783 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11784 InsertMenuItemTextWithCFString (menu
, NULL
,
11785 0, kMenuItemAttrSeparator
, 0);
11786 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11787 0, 0, kHICommandAbout
);
11789 #endif /* USE_CARBON_EVENTS */
11790 #else /* !MAC_OSX */
11791 #if USE_CARBON_EVENTS
11792 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11802 static InterfaceTypeList types
= {kUnicodeDocument
};
11804 static InterfaceTypeList types
= {kTextService
};
11807 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11808 &tsm_document_id
, 0);
11812 /* Set up use of X before we make the first connection. */
11814 extern frame_parm_handler mac_frame_parm_handlers
[];
11816 static struct redisplay_interface x_redisplay_interface
=
11818 mac_frame_parm_handlers
,
11822 x_clear_end_of_line
,
11824 x_after_update_window_line
,
11825 x_update_window_begin
,
11826 x_update_window_end
,
11830 mac_flush_display_optional
,
11832 0, /* flush_display_optional */
11834 x_clear_window_mouse_face
,
11835 x_get_glyph_overhangs
,
11836 x_fix_overlapping_area
,
11837 x_draw_fringe_bitmap
,
11839 mac_define_fringe_bitmap
,
11840 mac_destroy_fringe_bitmap
,
11842 0, /* define_fringe_bitmap */
11843 0, /* destroy_fringe_bitmap */
11845 mac_per_char_metric
,
11847 mac_compute_glyph_string_overhangs
,
11848 x_draw_glyph_string
,
11849 mac_define_frame_cursor
,
11850 mac_clear_frame_area
,
11851 mac_draw_window_cursor
,
11852 mac_draw_vertical_window_border
,
11853 mac_shift_glyphs_for_insert
11859 rif
= &x_redisplay_interface
;
11861 clear_frame_hook
= x_clear_frame
;
11862 ins_del_lines_hook
= x_ins_del_lines
;
11863 delete_glyphs_hook
= x_delete_glyphs
;
11864 ring_bell_hook
= XTring_bell
;
11865 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11866 set_terminal_modes_hook
= XTset_terminal_modes
;
11867 update_begin_hook
= x_update_begin
;
11868 update_end_hook
= x_update_end
;
11869 set_terminal_window_hook
= XTset_terminal_window
;
11870 read_socket_hook
= XTread_socket
;
11871 frame_up_to_date_hook
= XTframe_up_to_date
;
11872 mouse_position_hook
= XTmouse_position
;
11873 frame_rehighlight_hook
= XTframe_rehighlight
;
11874 frame_raise_lower_hook
= XTframe_raise_lower
;
11876 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11877 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11878 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11879 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11881 scroll_region_ok
= 1; /* we'll scroll partial frames */
11882 char_ins_del_ok
= 1;
11883 line_ins_del_ok
= 1; /* we'll just blt 'em */
11884 fast_clear_end_of_line
= 1; /* X does this well */
11885 memory_below_frame
= 0; /* we don't remember what scrolls
11889 last_tool_bar_item
= -1;
11890 any_help_event_p
= 0;
11892 /* Try to use interrupt input; if we can't, then start polling. */
11893 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11897 #if TARGET_API_MAC_CARBON
11899 #if USE_CARBON_EVENTS
11901 init_service_handler ();
11902 #endif /* MAC_OSX */
11904 init_command_handler ();
11911 #endif /* USE_CARBON_EVENTS */
11914 init_coercion_handler ();
11916 init_apple_event_handler ();
11918 init_dm_notification_handler ();
11920 if (!inhibit_window_system
)
11922 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
11924 SetFrontProcess (&psn
);
11932 mac_init_fringe ();
11943 staticpro (&x_error_message_string
);
11944 x_error_message_string
= Qnil
;
11947 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11948 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11949 Qalt
= intern ("alt"); staticpro (&Qalt
);
11950 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
11951 Qsuper
= intern ("super"); staticpro (&Qsuper
);
11952 Qmodifier_value
= intern ("modifier-value");
11953 staticpro (&Qmodifier_value
);
11955 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
11956 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11957 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11958 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11959 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11961 #if USE_CARBON_EVENTS
11962 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
11964 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
11965 staticpro (&Qtoolbar_switch_mode
);
11966 #if USE_MAC_FONT_PANEL
11967 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
11968 Qselection
= intern ("selection"); staticpro (&Qselection
);
11971 Qservice
= intern ("service"); staticpro (&Qservice
);
11972 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
11973 Qperform
= intern ("perform"); staticpro (&Qperform
);
11976 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
11977 Qupdate_active_input_area
= intern ("update-active-input-area");
11978 staticpro (&Qupdate_active_input_area
);
11979 Qunicode_for_key_event
= intern ("unicode-for-key-event");
11980 staticpro (&Qunicode_for_key_event
);
11985 Fprovide (intern ("mac-carbon"), Qnil
);
11988 staticpro (&Qreverse
);
11989 Qreverse
= intern ("reverse");
11991 staticpro (&x_display_name_list
);
11992 x_display_name_list
= Qnil
;
11994 staticpro (&last_mouse_scroll_bar
);
11995 last_mouse_scroll_bar
= Qnil
;
11997 staticpro (&fm_font_family_alist
);
11998 fm_font_family_alist
= Qnil
;
12001 staticpro (&atsu_font_id_hash
);
12002 atsu_font_id_hash
= Qnil
;
12004 staticpro (&fm_style_face_attributes_alist
);
12005 fm_style_face_attributes_alist
= Qnil
;
12009 staticpro (&saved_ts_script_language_on_focus
);
12010 saved_ts_script_language_on_focus
= Qnil
;
12013 /* We don't yet support this, but defining this here avoids whining
12014 from cus-start.el and other places, like "M-x set-variable". */
12015 DEFVAR_BOOL ("x-use-underline-position-properties",
12016 &x_use_underline_position_properties
,
12017 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12018 A value of nil means ignore them. If you encounter fonts with bogus
12019 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12020 to 4.1, set this to nil.
12022 NOTE: Not supported on Mac yet. */);
12023 x_use_underline_position_properties
= 0;
12025 DEFVAR_BOOL ("x-underline-at-descent-line",
12026 &x_underline_at_descent_line
,
12027 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12028 A value of nil means to draw the underline according to the value of the
12029 variable `x-use-underline-position-properties', which is usually at the
12030 baseline level. The default value is nil. */);
12031 x_underline_at_descent_line
= 0;
12033 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12034 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12035 #ifdef USE_TOOLKIT_SCROLL_BARS
12036 Vx_toolkit_scroll_bars
= Qt
;
12038 Vx_toolkit_scroll_bars
= Qnil
;
12041 staticpro (&last_mouse_motion_frame
);
12042 last_mouse_motion_frame
= Qnil
;
12044 /* Variables to configure modifier key assignment. */
12046 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12047 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12048 The value can be `control', `meta', `alt', `hyper', or `super' for the
12049 respective modifier. The default is `control'. */);
12050 Vmac_control_modifier
= Qcontrol
;
12052 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12053 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12054 The value can be `control', `meta', `alt', `hyper', or `super' for the
12055 respective modifier. If the value is nil then the key will act as the
12056 normal Mac control modifier, and the option key can be used to compose
12057 characters depending on the chosen Mac keyboard setting. */);
12058 Vmac_option_modifier
= Qnil
;
12060 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12061 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12062 The value can be `control', `meta', `alt', `hyper', or `super' for the
12063 respective modifier. The default is `meta'. */);
12064 Vmac_command_modifier
= Qmeta
;
12066 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12067 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12068 The value can be `control', `meta', `alt', `hyper', or `super' for the
12069 respective modifier. Note that remapping the function key may lead to
12070 unexpected results for some keys on non-US/GB keyboards. */);
12071 Vmac_function_modifier
= Qnil
;
12073 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12074 &Vmac_emulate_three_button_mouse
,
12075 doc
: /* *Specify a way of three button mouse emulation.
12076 The value can be nil, t, or the symbol `reverse'.
12077 A value of nil means that no emulation should be done and the modifiers
12078 should be placed on the mouse-1 event.
12079 t means that when the option-key is held down while pressing the mouse
12080 button, the click will register as mouse-2 and while the command-key
12081 is held down, the click will register as mouse-3.
12082 The symbol `reverse' means that the option-key will register for
12083 mouse-3 and the command-key will register for mouse-2. */);
12084 Vmac_emulate_three_button_mouse
= Qnil
;
12086 #if USE_CARBON_EVENTS
12087 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12088 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12089 Otherwise, the right click will be treated as mouse-2 and the wheel
12090 button will be mouse-3. */);
12091 mac_wheel_button_is_mouse_2
= 1;
12093 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12094 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12095 mac_pass_command_to_system
= 1;
12097 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12098 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12099 mac_pass_control_to_system
= 1;
12103 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
12104 doc
: /* *If non-nil, allow anti-aliasing.
12105 The text will be rendered using Core Graphics text rendering which
12106 may anti-alias the text. */);
12108 mac_use_core_graphics
= 1;
12110 mac_use_core_graphics
= 0;
12113 /* Register an entry for `mac-roman' so that it can be used when
12114 creating the terminal frame on Mac OS 9 before loading
12115 term/mac-win.elc. */
12116 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
12117 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
12118 Each entry should be of the form:
12120 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12122 where CHARSET-NAME is a string used in font names to identify the
12123 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12124 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12125 Vmac_charset_info_alist
=
12126 Fcons (list3 (build_string ("mac-roman"),
12127 make_number (smRoman
), Qnil
), Qnil
);
12130 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
12131 doc
: /* Overlay used to display Mac TSM active input area. */);
12132 Vmac_ts_active_input_overlay
= Qnil
;
12134 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
12135 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
12136 If the value is t, the input script and language are restored to those
12137 used in the last focus frame. If the value is a pair of integers, the
12138 input script and language codes, which are defined in the Script
12139 Manager, are set to its car and cdr parts, respectively. Otherwise,
12140 Emacs doesn't set them and thus follows the system default behavior. */);
12141 Vmac_ts_script_language_on_focus
= Qnil
;
12145 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12146 (do not change this comment) */