1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
56 #if defined (__MRC__) || (__MSL__ >= 0x6000)
57 #include <ControlDefinitions.h>
63 #endif /* not TARGET_API_MAC_CARBON */
76 #include "dispextern.h"
78 #include "termhooks.h"
85 #include "intervals.h"
91 /* Non-nil means Emacs uses toolkit scroll bars. */
93 Lisp_Object Vx_toolkit_scroll_bars
;
95 /* If non-zero, the text will be rendered using Core Graphics text
96 rendering which may anti-alias the text. */
97 int mac_use_core_graphics
;
100 /* Non-zero means that a HELP_EVENT has been generated since Emacs
103 static int any_help_event_p
;
105 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
106 static Lisp_Object last_window
;
108 /* Non-zero means make use of UNDERLINE_POSITION font properties.
109 (Not yet supported.) */
110 int x_use_underline_position_properties
;
112 /* Non-zero means to draw the underline at the same place as the descent line. */
114 int x_underline_at_descent_line
;
116 /* This is a chain of structures for all the X displays currently in
119 struct x_display_info
*x_display_list
;
121 /* This is a list of cons cells, each of the form (NAME
122 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
123 x_display_list and in the same order. NAME is the name of the
124 frame. FONT-LIST-CACHE records previous values returned by
125 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
126 equivalent, which is implemented with a Lisp object, for the
129 Lisp_Object x_display_name_list
;
131 /* This is display since Mac does not support multiple ones. */
132 struct mac_display_info one_mac_display_info
;
134 /* Frame being updated by update_frame. This is declared in term.c.
135 This is set by update_begin and looked at by all the XT functions.
136 It is zero while not inside an update. In that case, the XT
137 functions assume that `selected_frame' is the frame to apply to. */
139 extern struct frame
*updating_frame
;
141 /* This is a frame waiting to be auto-raised, within XTread_socket. */
143 struct frame
*pending_autoraise_frame
;
147 Formerly, we used PointerMotionHintMask (in standard_event_mask)
148 so that we would have to call XQueryPointer after each MotionNotify
149 event to ask for another such event. However, this made mouse tracking
150 slow, and there was a bug that made it eventually stop.
152 Simply asking for MotionNotify all the time seems to work better.
154 In order to avoid asking for motion events and then throwing most
155 of them away or busy-polling the server for mouse positions, we ask
156 the server for pointer motion hints. This means that we get only
157 one event per group of mouse movements. "Groups" are delimited by
158 other kinds of events (focus changes and button clicks, for
159 example), or by XQueryPointer calls; when one of these happens, we
160 get another MotionNotify event the next time the mouse moves. This
161 is at least as efficient as getting motion events when mouse
162 tracking is on, and I suspect only negligibly worse when tracking
165 /* Where the mouse was last time we reported a mouse event. */
167 static Rect last_mouse_glyph
;
168 static FRAME_PTR last_mouse_glyph_frame
;
170 /* The scroll bar in which the last X motion event occurred.
172 If the last X motion event occurred in a scroll bar, we set this so
173 XTmouse_position can know whether to report a scroll bar motion or
176 If the last X motion event didn't occur in a scroll bar, we set
177 this to Qnil, to tell XTmouse_position to return an ordinary motion
180 static Lisp_Object last_mouse_scroll_bar
;
182 /* This is a hack. We would really prefer that XTmouse_position would
183 return the time associated with the position it returns, but there
184 doesn't seem to be any way to wrest the time-stamp from the server
185 along with the position query. So, we just keep track of the time
186 of the last movement we received, and return that in hopes that
187 it's somewhat accurate. */
189 static Time last_mouse_movement_time
;
191 struct scroll_bar
*tracked_scroll_bar
= NULL
;
193 /* Incremented by XTread_socket whenever it really tries to read
197 static int volatile input_signal_count
;
199 static int input_signal_count
;
202 extern Lisp_Object Vsystem_name
;
204 extern Lisp_Object Qeql
;
206 /* A mask of extra modifier bits to put into every keyboard char. */
208 extern EMACS_INT extra_keyboard_modifiers
;
210 /* The keysyms to use for the various modifiers. */
212 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
214 extern int inhibit_window_system
;
216 #if __MRC__ && !TARGET_API_MAC_CARBON
217 QDGlobals qd
; /* QuickDraw global information structure. */
220 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
222 struct mac_display_info
*mac_display_info_for_display (Display
*);
223 static void x_update_window_end
P_ ((struct window
*, int, int));
224 int x_catch_errors
P_ ((Display
*));
225 void x_uncatch_errors
P_ ((Display
*, int));
226 void x_lower_frame
P_ ((struct frame
*));
227 void x_scroll_bar_clear
P_ ((struct frame
*));
228 int x_had_errors_p
P_ ((Display
*));
229 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
230 void x_raise_frame
P_ ((struct frame
*));
231 void x_set_window_size
P_ ((struct frame
*, int, int, int));
232 void x_wm_set_window_state
P_ ((struct frame
*, int));
233 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
234 static void mac_initialize
P_ ((void));
235 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
236 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
237 static void x_update_end
P_ ((struct frame
*));
238 static void XTframe_up_to_date
P_ ((struct frame
*));
239 static void XTset_terminal_modes
P_ ((struct terminal
*));
240 static void XTreset_terminal_modes
P_ ((struct terminal
*));
241 static void x_clear_frame
P_ ((struct frame
*));
242 static void frame_highlight
P_ ((struct frame
*));
243 static void frame_unhighlight
P_ ((struct frame
*));
244 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
245 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
246 struct frame
*, struct input_event
*));
247 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
249 struct input_event
*));
250 static void XTframe_rehighlight
P_ ((struct frame
*));
251 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
252 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
253 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
254 enum text_cursor_kinds
));
256 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
257 static void x_flush
P_ ((struct frame
*f
));
258 static void x_update_begin
P_ ((struct frame
*));
259 static void x_update_window_begin
P_ ((struct window
*));
260 static void x_after_update_window_line
P_ ((struct glyph_row
*));
261 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
262 enum scroll_bar_part
*,
263 Lisp_Object
*, Lisp_Object
*,
266 static int is_emacs_window
P_ ((WindowPtr
));
267 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
268 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
269 static struct terminal
*mac_create_terminal
P_ ((struct mac_display_info
*dpyinfo
));
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 (struct terminal
*t
)
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 (struct terminal
*t
)
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
*, int *));
2336 pcm_init (pcm
, count
)
2340 bzero (pcm
, sizeof (XCharStruct
) * count
);
2341 while (--count
>= 0)
2343 pcm
->descent
= PCM_INVALID
;
2348 static enum pcm_status
2349 pcm_get_status (pcm
)
2350 const XCharStruct
*pcm
;
2352 int height
= pcm
->ascent
+ pcm
->descent
;
2354 /* Negative height means some special status. */
2355 return height
>= 0 ? PCM_VALID
: height
;
2358 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2359 is not contained in the font. */
2361 static INLINE XCharStruct
*
2362 x_per_char_metric (font
, char2b
)
2366 /* The result metric information. */
2367 XCharStruct
*pcm
= NULL
;
2369 xassert (font
&& char2b
);
2372 if (font
->mac_style
)
2374 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2378 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2379 pcm_init (*row
, 0x100);
2381 pcm
= *row
+ char2b
->byte2
;
2382 if (pcm_get_status (pcm
) != PCM_VALID
)
2385 mac_query_char_extents (font
->mac_style
,
2386 (char2b
->byte1
<< 8) + char2b
->byte2
,
2387 NULL
, NULL
, pcm
, NULL
);
2394 if (font
->bounds
.per_char
!= NULL
)
2396 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2398 /* min_char_or_byte2 specifies the linear character index
2399 corresponding to the first element of the per_char array,
2400 max_char_or_byte2 is the index of the last character. A
2401 character with non-zero CHAR2B->byte1 is not in the font.
2402 A character with byte2 less than min_char_or_byte2 or
2403 greater max_char_or_byte2 is not in the font. */
2404 if (char2b
->byte1
== 0
2405 && char2b
->byte2
>= font
->min_char_or_byte2
2406 && char2b
->byte2
<= font
->max_char_or_byte2
)
2407 pcm
= font
->bounds
.per_char
2408 + (char2b
->byte2
- font
->min_char_or_byte2
);
2412 /* If either min_byte1 or max_byte1 are nonzero, both
2413 min_char_or_byte2 and max_char_or_byte2 are less than
2414 256, and the 2-byte character index values corresponding
2415 to the per_char array element N (counting from 0) are:
2417 byte1 = N/D + min_byte1
2418 byte2 = N\D + min_char_or_byte2
2422 D = max_char_or_byte2 - min_char_or_byte2 + 1
2423 / = integer division
2424 \ = integer modulus */
2425 if (char2b
->byte1
>= font
->min_byte1
2426 && char2b
->byte1
<= font
->max_byte1
2427 && char2b
->byte2
>= font
->min_char_or_byte2
2428 && char2b
->byte2
<= font
->max_char_or_byte2
)
2430 pcm
= (font
->bounds
.per_char
2431 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2432 * (char2b
->byte1
- font
->min_byte1
))
2433 + (char2b
->byte2
- font
->min_char_or_byte2
));
2439 /* If the per_char pointer is null, all glyphs between the first
2440 and last character indexes inclusive have the same
2441 information, as given by both min_bounds and max_bounds. */
2442 if (char2b
->byte2
>= font
->min_char_or_byte2
2443 && char2b
->byte2
<= font
->max_char_or_byte2
)
2444 pcm
= &font
->max_bounds
;
2450 return ((pcm
== NULL
2452 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2453 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2462 static XCharStruct
*
2463 mac_per_char_metric (font
, char2b
, font_type
)
2468 return x_per_char_metric (font
, char2b
);
2472 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2473 the two-byte form of C. Encoding is returned in *CHAR2B. */
2476 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2479 struct font_info
*font_info
;
2482 int charset
= CHAR_CHARSET (c
);
2483 XFontStruct
*font
= font_info
->font
;
2485 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2486 This may be either a program in a special encoder language or a
2488 if (font_info
->font_encoder
)
2490 /* It's a program. */
2491 struct ccl_program
*ccl
= font_info
->font_encoder
;
2493 check_ccl_update (ccl
);
2494 if (CHARSET_DIMENSION (charset
) == 1)
2496 ccl
->reg
[0] = charset
;
2497 ccl
->reg
[1] = char2b
->byte2
;
2502 ccl
->reg
[0] = charset
;
2503 ccl
->reg
[1] = char2b
->byte1
;
2504 ccl
->reg
[2] = char2b
->byte2
;
2507 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2509 /* We assume that MSBs are appropriately set/reset by CCL
2511 if (font
->max_byte1
== 0) /* 1-byte font */
2512 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2514 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2516 else if (font_info
->encoding
[charset
])
2518 /* Fixed encoding scheme. See fontset.h for the meaning of the
2519 encoding numbers. */
2520 int enc
= font_info
->encoding
[charset
];
2522 if ((enc
== 1 || enc
== 2)
2523 && CHARSET_DIMENSION (charset
) == 2)
2524 char2b
->byte1
|= 0x80;
2526 if (enc
== 1 || enc
== 3)
2527 char2b
->byte2
|= 0x80;
2533 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2534 char2b
->byte1
= sjis1
;
2535 char2b
->byte2
= sjis2
;
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
);
2657 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
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. */
3962 x_clear_frame (struct frame
*f
)
3964 /* Clearing the frame will erase any cursor, so mark them all as no
3966 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3967 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3968 output_cursor
.x
= -1;
3970 /* We don't set the output cursor here because there will always
3971 follow an explicit cursor_to. */
3973 mac_clear_window (f
);
3975 /* We have to clear the scroll bars, too. If we have changed
3976 colors or something like that, then they should be notified. */
3977 x_scroll_bar_clear (f
);
3979 XFlush (FRAME_MAC_DISPLAY (f
));
3985 /* Invert the middle quarter of the frame for .15 sec. */
3987 /* We use the select system call to do the waiting, so we have to make
3988 sure it's available. If it isn't, we just won't do visual bells. */
3990 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3993 /* Subtract the `struct timeval' values X and Y, storing the result in
3994 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3997 timeval_subtract (result
, x
, y
)
3998 struct timeval
*result
, x
, y
;
4000 /* Perform the carry for the later subtraction by updating y. This
4001 is safer because on some systems the tv_sec member is unsigned. */
4002 if (x
.tv_usec
< y
.tv_usec
)
4004 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4005 y
.tv_usec
-= 1000000 * nsec
;
4009 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4011 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4012 y
.tv_usec
+= 1000000 * nsec
;
4016 /* Compute the time remaining to wait. tv_usec is certainly
4018 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4019 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4021 /* Return indication of whether the result should be considered
4023 return x
.tv_sec
< y
.tv_sec
;
4030 /* Get the height not including a menu bar widget. */
4031 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4032 /* Height of each line to flash. */
4033 int flash_height
= FRAME_LINE_HEIGHT (f
);
4034 /* These will be the left and right margins of the rectangles. */
4035 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4036 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4040 /* Don't flash the area between a scroll bar and the frame
4041 edge it is next to. */
4042 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4044 case vertical_scroll_bar_left
:
4045 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4048 case vertical_scroll_bar_right
:
4049 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4056 width
= flash_right
- flash_left
;
4060 /* If window is tall, flash top and bottom line. */
4061 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4063 mac_invert_rectangle (f
, flash_left
,
4064 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4065 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4066 width
, flash_height
);
4067 mac_invert_rectangle (f
, flash_left
,
4068 (height
- flash_height
4069 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4070 width
, flash_height
);
4073 /* If it is short, flash it all. */
4074 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4075 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4080 struct timeval wakeup
;
4082 EMACS_GET_TIME (wakeup
);
4084 /* Compute time to wait until, propagating carry from usecs. */
4085 wakeup
.tv_usec
+= 150000;
4086 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4087 wakeup
.tv_usec
%= 1000000;
4089 /* Keep waiting until past the time wakeup or any input gets
4091 while (! detect_input_pending ())
4093 struct timeval current
;
4094 struct timeval timeout
;
4096 EMACS_GET_TIME (current
);
4098 /* Break if result would be negative. */
4099 if (timeval_subtract (¤t
, wakeup
, current
))
4102 /* How long `select' should wait. */
4104 timeout
.tv_usec
= 10000;
4106 /* Try to wait that long--but we might wake up sooner. */
4107 select (0, NULL
, NULL
, NULL
, &timeout
);
4111 /* If window is tall, flash top and bottom line. */
4112 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4114 mac_invert_rectangle (f
, flash_left
,
4115 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4116 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4117 width
, flash_height
);
4118 mac_invert_rectangle (f
, flash_left
,
4119 (height
- flash_height
4120 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4121 width
, flash_height
);
4124 /* If it is short, flash it all. */
4125 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4126 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4133 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4136 /* Make audible bell. */
4141 struct frame
*f
= SELECTED_FRAME ();
4143 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4151 XFlush (FRAME_MAC_DISPLAY (f
));
4157 /* Specify how many text lines, from the top of the window,
4158 should be affected by insert-lines and delete-lines operations.
4159 This, and those operations, are used only within an update
4160 that is bounded by calls to x_update_begin and x_update_end. */
4163 XTset_terminal_window (n
)
4166 /* This function intentionally left blank. */
4171 /***********************************************************************
4173 ***********************************************************************/
4175 /* Perform an insert-lines or delete-lines operation, inserting N
4176 lines or deleting -N lines at vertical position VPOS. */
4179 x_ins_del_lines (vpos
, n
)
4186 /* Scroll part of the display as described by RUN. */
4189 x_scroll_run (w
, run
)
4193 struct frame
*f
= XFRAME (w
->frame
);
4194 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4196 /* Get frame-relative bounding box of the text display area of W,
4197 without mode lines. Include in this box the left and right
4199 window_box (w
, -1, &x
, &y
, &width
, &height
);
4201 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4202 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4203 bottom_y
= y
+ height
;
4207 /* Scrolling up. Make sure we don't copy part of the mode
4208 line at the bottom. */
4209 if (from_y
+ run
->height
> bottom_y
)
4210 height
= bottom_y
- from_y
;
4212 height
= run
->height
;
4216 /* Scolling down. Make sure we don't copy over the mode line.
4218 if (to_y
+ run
->height
> bottom_y
)
4219 height
= bottom_y
- to_y
;
4221 height
= run
->height
;
4226 /* Cursor off. Will be switched on again in x_update_window_end. */
4230 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4240 /***********************************************************************
4242 ***********************************************************************/
4250 ControlRef root_control
;
4253 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4255 ActivateControl (root_control
);
4257 x_update_cursor (f
, 1);
4261 frame_unhighlight (f
)
4265 ControlRef root_control
;
4268 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4270 DeactivateControl (root_control
);
4272 x_update_cursor (f
, 1);
4275 /* The focus has changed. Update the frames as necessary to reflect
4276 the new situation. Note that we can't change the selected frame
4277 here, because the Lisp code we are interrupting might become confused.
4278 Each event gets marked with the frame in which it occurred, so the
4279 Lisp code can tell when the switch took place by examining the events. */
4282 x_new_focus_frame (dpyinfo
, frame
)
4283 struct x_display_info
*dpyinfo
;
4284 struct frame
*frame
;
4286 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4288 if (frame
!= dpyinfo
->x_focus_frame
)
4290 /* Set this before calling other routines, so that they see
4291 the correct value of x_focus_frame. */
4292 dpyinfo
->x_focus_frame
= frame
;
4294 if (old_focus
&& old_focus
->auto_lower
)
4295 x_lower_frame (old_focus
);
4298 selected_frame
= frame
;
4299 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4301 Fselect_window (selected_frame
->selected_window
, Qnil
);
4302 choose_minibuf_frame ();
4305 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4306 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4308 pending_autoraise_frame
= 0;
4310 #if USE_MAC_FONT_PANEL
4312 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4316 x_frame_rehighlight (dpyinfo
);
4319 /* Handle FocusIn and FocusOut state changes for FRAME.
4320 If FRAME has focus and there exists more than one frame, puts
4321 a FOCUS_IN_EVENT into *BUFP. */
4324 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4326 struct mac_display_info
*dpyinfo
;
4327 struct frame
*frame
;
4328 struct input_event
*bufp
;
4330 if (type
== activeFlag
)
4332 if (dpyinfo
->x_focus_event_frame
!= frame
)
4334 x_new_focus_frame (dpyinfo
, frame
);
4335 dpyinfo
->x_focus_event_frame
= frame
;
4337 /* Don't stop displaying the initial startup message
4338 for a switch-frame event we don't need. */
4339 if (GC_NILP (Vterminal_frame
)
4340 && GC_CONSP (Vframe_list
)
4341 && !GC_NILP (XCDR (Vframe_list
)))
4343 bufp
->kind
= FOCUS_IN_EVENT
;
4344 XSETFRAME (bufp
->frame_or_window
, frame
);
4350 if (dpyinfo
->x_focus_event_frame
== frame
)
4352 dpyinfo
->x_focus_event_frame
= 0;
4353 x_new_focus_frame (dpyinfo
, 0);
4358 /* The focus may have changed. Figure out if it is a real focus change,
4359 by checking both FocusIn/Out and Enter/LeaveNotify events.
4361 Returns FOCUS_IN_EVENT event in *BUFP. */
4364 x_detect_focus_change (dpyinfo
, event
, bufp
)
4365 struct mac_display_info
*dpyinfo
;
4366 const EventRecord
*event
;
4367 struct input_event
*bufp
;
4369 struct frame
*frame
;
4371 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4375 /* On Mac, this is only called from focus events, so no switch needed. */
4376 mac_focus_changed ((event
->modifiers
& activeFlag
),
4377 dpyinfo
, frame
, bufp
);
4381 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4384 x_mouse_leave (dpyinfo
)
4385 struct x_display_info
*dpyinfo
;
4387 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4390 /* The focus has changed, or we have redirected a frame's focus to
4391 another frame (this happens when a frame uses a surrogate
4392 mini-buffer frame). Shift the highlight as appropriate.
4394 The FRAME argument doesn't necessarily have anything to do with which
4395 frame is being highlighted or un-highlighted; we only use it to find
4396 the appropriate X display info. */
4399 XTframe_rehighlight (frame
)
4400 struct frame
*frame
;
4402 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4406 x_frame_rehighlight (dpyinfo
)
4407 struct x_display_info
*dpyinfo
;
4409 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4411 if (dpyinfo
->x_focus_frame
)
4413 dpyinfo
->x_highlight_frame
4414 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4415 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4416 : dpyinfo
->x_focus_frame
);
4417 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4419 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4420 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4424 dpyinfo
->x_highlight_frame
= 0;
4426 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4429 frame_unhighlight (old_highlight
);
4430 if (dpyinfo
->x_highlight_frame
)
4431 frame_highlight (dpyinfo
->x_highlight_frame
);
4437 /* Convert a keysym to its name. */
4440 x_get_keysym_name (keysym
)
4447 value
= XKeysymToString (keysym
);
4458 /* Function to report a mouse movement to the mainstream Emacs code.
4459 The input handler calls this.
4461 We have received a mouse movement event, which is given in *event.
4462 If the mouse is over a different glyph than it was last time, tell
4463 the mainstream emacs code by setting mouse_moved. If not, ask for
4464 another motion event, so we can check again the next time it moves. */
4466 static Point last_mouse_motion_position
;
4467 static Lisp_Object last_mouse_motion_frame
;
4470 note_mouse_movement (frame
, pos
)
4474 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4475 #if TARGET_API_MAC_CARBON
4479 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4480 last_mouse_motion_position
= *pos
;
4481 XSETFRAME (last_mouse_motion_frame
, frame
);
4483 if (frame
== dpyinfo
->mouse_face_mouse_frame
4484 #if TARGET_API_MAC_CARBON
4485 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4487 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4491 /* This case corresponds to LeaveNotify in X11. If we move
4492 outside the frame, then we're certainly no longer on any text
4494 clear_mouse_face (dpyinfo
);
4495 dpyinfo
->mouse_face_mouse_frame
= 0;
4496 if (!dpyinfo
->grabbed
)
4497 FRAME_RIF (frame
)->define_frame_cursor (frame
,
4498 frame
->output_data
.mac
->nontext_cursor
);
4501 /* Has the mouse moved off the glyph it was on at the last sighting? */
4502 if (frame
!= last_mouse_glyph_frame
4503 || !PtInRect (*pos
, &last_mouse_glyph
))
4505 frame
->mouse_moved
= 1;
4506 last_mouse_scroll_bar
= Qnil
;
4507 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4508 /* Remember which glyph we're now on. */
4509 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4510 last_mouse_glyph_frame
= frame
;
4518 /************************************************************************
4520 ************************************************************************/
4522 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4525 redo_mouse_highlight ()
4527 if (!NILP (last_mouse_motion_frame
)
4528 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4529 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4530 last_mouse_motion_position
.h
,
4531 last_mouse_motion_position
.v
);
4535 static struct frame
*
4536 mac_focus_frame (dpyinfo
)
4537 struct mac_display_info
*dpyinfo
;
4539 if (dpyinfo
->x_focus_frame
)
4540 return dpyinfo
->x_focus_frame
;
4542 /* Mac version may get events, such as a menu bar click, even when
4543 all the frames are invisible. In this case, we regard the
4544 event came to the selected frame. */
4545 return SELECTED_FRAME ();
4549 /* Return the current position of the mouse.
4550 *FP should be a frame which indicates which display to ask about.
4552 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4553 and *PART to the frame, window, and scroll bar part that the mouse
4554 is over. Set *X and *Y to the portion and whole of the mouse's
4555 position on the scroll bar.
4557 If the mouse movement started elsewhere, set *FP to the frame the
4558 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4561 Set *TIME to the server time-stamp for the time at which the mouse
4562 was at this position.
4564 Don't store anything if we don't have a valid set of values to report.
4566 This clears the mouse_moved flag, so we can wait for the next mouse
4570 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4573 Lisp_Object
*bar_window
;
4574 enum scroll_bar_part
*part
;
4576 unsigned long *time
;
4582 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4583 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4586 Lisp_Object frame
, tail
;
4588 /* Clear the mouse-moved flag for every frame on this display. */
4589 FOR_EACH_FRAME (tail
, frame
)
4590 XFRAME (frame
)->mouse_moved
= 0;
4592 last_mouse_scroll_bar
= Qnil
;
4594 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4595 && FRAME_LIVE_P (last_mouse_frame
))
4596 f1
= last_mouse_frame
;
4598 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4602 /* Ok, we found a frame. Store all the values.
4603 last_mouse_glyph is a rectangle used to reduce the
4604 generation of mouse events. To not miss any motion
4605 events, we must divide the frame into rectangles of the
4606 size of the smallest character that could be displayed
4607 on it, i.e. into the same rectangles that matrices on
4608 the frame are divided into. */
4611 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4612 GetMouse (&mouse_pos
);
4613 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4615 last_mouse_glyph_frame
= f1
;
4620 XSETINT (*x
, mouse_pos
.h
);
4621 XSETINT (*y
, mouse_pos
.v
);
4622 *time
= last_mouse_movement_time
;
4630 /************************************************************************
4632 ************************************************************************/
4634 #ifdef USE_TOOLKIT_SCROLL_BARS
4636 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4637 static OSStatus install_scroll_bar_timer
P_ ((void));
4638 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4639 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4640 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4641 struct input_event
*));
4642 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4644 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4645 ControlPartCode
, Point
,
4646 struct input_event
*));
4647 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4648 struct input_event
*));
4649 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4650 Point
, struct input_event
*));
4651 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4654 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4656 static int last_scroll_bar_part
;
4658 static EventLoopTimerRef scroll_bar_timer
;
4660 static int scroll_bar_timer_event_posted_p
;
4662 #define SCROLL_BAR_FIRST_DELAY 0.5
4663 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4666 scroll_bar_timer_callback (timer
, data
)
4667 EventLoopTimerRef timer
;
4672 err
= mac_post_mouse_moved_event ();
4674 scroll_bar_timer_event_posted_p
= 1;
4678 install_scroll_bar_timer ()
4680 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4682 if (scroll_bar_timer_callbackUPP
== NULL
)
4683 scroll_bar_timer_callbackUPP
=
4684 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4686 if (scroll_bar_timer
== NULL
)
4687 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4688 kEventDurationForever as delays. */
4690 InstallEventLoopTimer (GetCurrentEventLoop (),
4691 kEventDurationForever
, kEventDurationForever
,
4692 scroll_bar_timer_callbackUPP
, NULL
,
4697 set_scroll_bar_timer (delay
)
4698 EventTimerInterval delay
;
4700 if (scroll_bar_timer
== NULL
)
4701 install_scroll_bar_timer ();
4703 scroll_bar_timer_event_posted_p
= 0;
4705 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4709 control_part_code_to_scroll_bar_part (part_code
)
4710 ControlPartCode part_code
;
4714 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4715 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4716 case kControlPageUpPart
: return scroll_bar_above_handle
;
4717 case kControlPageDownPart
: return scroll_bar_below_handle
;
4718 case kControlIndicatorPart
: return scroll_bar_handle
;
4725 construct_scroll_bar_click (bar
, part
, bufp
)
4726 struct scroll_bar
*bar
;
4728 struct input_event
*bufp
;
4730 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4731 bufp
->frame_or_window
= bar
->window
;
4735 XSETINT (bufp
->x
, 0);
4736 XSETINT (bufp
->y
, 0);
4737 bufp
->modifiers
= 0;
4741 get_control_part_bounds (ch
, part_code
, rect
)
4743 ControlPartCode part_code
;
4746 RgnHandle region
= NewRgn ();
4749 err
= GetControlRegion (ch
, part_code
, region
);
4751 GetRegionBounds (region
, rect
);
4752 DisposeRgn (region
);
4758 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4759 struct scroll_bar
*bar
;
4760 ControlPartCode part_code
;
4762 struct input_event
*bufp
;
4764 int part
= control_part_code_to_scroll_bar_part (part_code
);
4769 if (part
!= scroll_bar_handle
)
4771 construct_scroll_bar_click (bar
, part
, bufp
);
4772 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4773 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4774 bar
->dragging
= Qnil
;
4780 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4781 kControlIndicatorPart
, &r
);
4782 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4785 last_scroll_bar_part
= part
;
4786 tracked_scroll_bar
= bar
;
4790 x_scroll_bar_handle_release (bar
, bufp
)
4791 struct scroll_bar
*bar
;
4792 struct input_event
*bufp
;
4794 if (last_scroll_bar_part
!= scroll_bar_handle
4795 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4796 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4798 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4799 set_scroll_bar_timer (kEventDurationForever
);
4801 last_scroll_bar_part
= -1;
4802 bar
->dragging
= Qnil
;
4803 tracked_scroll_bar
= NULL
;
4807 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4809 struct scroll_bar
*bar
;
4811 struct input_event
*bufp
;
4813 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4815 if (last_scroll_bar_part
== scroll_bar_handle
)
4820 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4821 kControlIndicatorPart
, &r
);
4823 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4824 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4826 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4827 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4831 if (top
> top_range
)
4834 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4835 XSETINT (bufp
->x
, top
);
4836 XSETINT (bufp
->y
, top_range
);
4840 ControlPartCode part_code
;
4841 int unhilite_p
= 0, part
;
4843 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4847 part
= control_part_code_to_scroll_bar_part (part_code
);
4849 switch (last_scroll_bar_part
)
4851 case scroll_bar_above_handle
:
4852 case scroll_bar_below_handle
:
4853 if (part
!= scroll_bar_above_handle
4854 && part
!= scroll_bar_below_handle
)
4858 case scroll_bar_up_arrow
:
4859 case scroll_bar_down_arrow
:
4860 if (part
!= scroll_bar_up_arrow
4861 && part
!= scroll_bar_down_arrow
)
4868 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4869 else if (part
!= last_scroll_bar_part
4870 || scroll_bar_timer_event_posted_p
)
4872 construct_scroll_bar_click (bar
, part
, bufp
);
4873 last_scroll_bar_part
= part
;
4874 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4875 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4880 /* Set the thumb size and position of scroll bar BAR. We are currently
4881 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4884 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4885 struct scroll_bar
*bar
;
4886 int portion
, position
, whole
;
4888 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4889 int value
, viewsize
, maximum
;
4891 if (XINT (bar
->track_height
) == 0)
4894 if (whole
<= portion
)
4895 value
= 0, viewsize
= 1, maximum
= 0;
4900 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4901 scale
= (float) maximum
/ (whole
- portion
);
4902 value
= position
* scale
+ 0.5f
;
4903 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
4908 if (GetControlViewSize (ch
) != viewsize
4909 || GetControl32BitValue (ch
) != value
4910 || GetControl32BitMaximum (ch
) != maximum
)
4912 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4913 SetControlVisibility (ch
, false, false);
4915 SetControl32BitMaximum (ch
, maximum
);
4916 SetControl32BitValue (ch
, value
);
4917 SetControlViewSize (ch
, viewsize
);
4919 SetControlVisibility (ch
, true, true);
4925 #endif /* USE_TOOLKIT_SCROLL_BARS */
4929 /************************************************************************
4930 Scroll bars, general
4931 ************************************************************************/
4933 /* Create a scroll bar and return the scroll bar vector for it. W is
4934 the Emacs window on which to create the scroll bar. TOP, LEFT,
4935 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4938 static struct scroll_bar
*
4939 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4941 int top
, left
, width
, height
, disp_top
, disp_height
;
4943 struct frame
*f
= XFRAME (w
->frame
);
4944 struct scroll_bar
*bar
4945 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4953 r
.right
= left
+ width
;
4954 r
.bottom
= disp_top
+ disp_height
;
4957 mac_prepare_for_quickdraw (f
);
4959 #if TARGET_API_MAC_CARBON
4960 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4961 #ifdef USE_TOOLKIT_SCROLL_BARS
4964 width
< disp_height
,
4966 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4968 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4969 0, 0, 0, scrollBarProc
, (long) bar
);
4971 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4973 XSETWINDOW (bar
->window
, w
);
4974 XSETINT (bar
->top
, top
);
4975 XSETINT (bar
->left
, left
);
4976 XSETINT (bar
->width
, width
);
4977 XSETINT (bar
->height
, height
);
4978 XSETINT (bar
->start
, 0);
4979 XSETINT (bar
->end
, 0);
4980 bar
->dragging
= Qnil
;
4981 #ifdef USE_TOOLKIT_SCROLL_BARS
4982 bar
->track_top
= Qnil
;
4983 bar
->track_height
= Qnil
;
4984 bar
->min_handle
= Qnil
;
4987 /* Add bar to its frame's list of scroll bars. */
4988 bar
->next
= FRAME_SCROLL_BARS (f
);
4990 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4991 if (!NILP (bar
->next
))
4992 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4999 /* Draw BAR's handle in the proper position.
5001 If the handle is already drawn from START to END, don't bother
5002 redrawing it, unless REBUILD is non-zero; in that case, always
5003 redraw it. (REBUILD is handy for drawing the handle after expose
5006 Normally, we want to constrain the start and end of the handle to
5007 fit inside its rectangle, but if the user is dragging the scroll
5008 bar handle, we want to let them drag it down all the way, so that
5009 the bar's top is as far down as it goes; otherwise, there's no way
5010 to move to the very end of the buffer. */
5012 #ifndef USE_TOOLKIT_SCROLL_BARS
5015 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5016 struct scroll_bar
*bar
;
5020 int dragging
= ! NILP (bar
->dragging
);
5021 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5022 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5023 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5024 int length
= end
- start
;
5026 /* If the display is already accurate, do nothing. */
5028 && start
== XINT (bar
->start
)
5029 && end
== XINT (bar
->end
))
5034 /* Make sure the values are reasonable, and try to preserve the
5035 distance between start and end. */
5038 else if (start
> top_range
)
5040 end
= start
+ length
;
5044 else if (end
> top_range
&& ! dragging
)
5047 /* Store the adjusted setting in the scroll bar. */
5048 XSETINT (bar
->start
, start
);
5049 XSETINT (bar
->end
, end
);
5051 /* Clip the end position, just for display. */
5052 if (end
> top_range
)
5055 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5056 top positions, to make sure the handle is always at least that
5057 many pixels tall. */
5058 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5060 SetControlMinimum (ch
, 0);
5061 /* Don't inadvertently activate deactivated scroll bars */
5062 if (GetControlMaximum (ch
) != -1)
5063 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5065 SetControlValue (ch
, start
);
5066 #if TARGET_API_MAC_CARBON
5067 SetControlViewSize (ch
, end
- start
);
5073 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5075 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5079 x_scroll_bar_remove (bar
)
5080 struct scroll_bar
*bar
;
5082 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5087 mac_prepare_for_quickdraw (f
);
5089 /* Destroy the Mac scroll bar control */
5090 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
5092 /* Disassociate this scroll bar from its window. */
5093 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5099 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5100 that we are displaying PORTION characters out of a total of WHOLE
5101 characters, starting at POSITION. If WINDOW has no scroll bar,
5105 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5107 int portion
, whole
, position
;
5109 struct frame
*f
= XFRAME (w
->frame
);
5110 struct scroll_bar
*bar
;
5111 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5112 int window_y
, window_height
;
5114 /* Get window dimensions. */
5115 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5117 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5118 height
= window_height
;
5120 /* Compute the left edge of the scroll bar area. */
5121 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5123 /* Compute the width of the scroll bar which might be less than
5124 the width of the area reserved for the scroll bar. */
5125 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5126 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5130 /* Compute the left edge of the scroll bar. */
5131 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5134 sb_left
= left
+ width
- sb_width
;
5136 /* Adjustments according to Inside Macintosh to make it look nice */
5138 disp_height
= height
;
5145 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5151 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5155 /* Does the scroll bar exist yet? */
5156 if (NILP (w
->vertical_scroll_bar
))
5159 mac_clear_area (f
, left
, top
, width
, height
);
5161 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5163 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5167 /* It may just need to be moved and resized. */
5170 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5171 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5175 /* If already correctly positioned, do nothing. */
5176 if (!(XINT (bar
->left
) == sb_left
5177 && XINT (bar
->top
) == top
5178 && XINT (bar
->width
) == sb_width
5179 && XINT (bar
->height
) == height
))
5181 /* Since toolkit scroll bars are smaller than the space reserved
5182 for them on the frame, we have to clear "under" them. */
5183 mac_clear_area (f
, left
, top
, width
, height
);
5186 mac_prepare_for_quickdraw (f
);
5189 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5190 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5192 #ifndef USE_TOOLKIT_SCROLL_BARS
5193 if (sb_width
< disp_height
)
5197 /* Remember new settings. */
5198 XSETINT (bar
->left
, sb_left
);
5199 XSETINT (bar
->top
, top
);
5200 XSETINT (bar
->width
, sb_width
);
5201 XSETINT (bar
->height
, height
);
5202 #ifdef USE_TOOLKIT_SCROLL_BARS
5203 bar
->track_top
= Qnil
;
5204 bar
->track_height
= Qnil
;
5205 bar
->min_handle
= Qnil
;
5212 #ifdef USE_TOOLKIT_SCROLL_BARS
5213 if (NILP (bar
->track_top
))
5215 if (sb_width
>= disp_height
5217 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5221 XSETINT (bar
->track_top
, 0);
5222 XSETINT (bar
->track_height
, 0);
5223 XSETINT (bar
->min_handle
, 0);
5227 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5232 SetControl32BitMinimum (ch
, 0);
5233 SetControl32BitMaximum (ch
, 1 << 30);
5234 SetControlViewSize (ch
, 1);
5236 /* Move the scroll bar thumb to the top. */
5237 SetControl32BitValue (ch
, 0);
5238 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5240 /* Move the scroll bar thumb to the bottom. */
5241 SetControl32BitValue (ch
, 1 << 30);
5242 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5244 UnionRect (&r0
, &r1
, &r0
);
5245 XSETINT (bar
->track_top
, r0
.top
);
5246 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5247 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5249 /* Don't show the scroll bar if its height is not enough to
5250 display the scroll bar thumb. */
5251 if (r0
.bottom
- r0
.top
> 0)
5258 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5259 #else /* not USE_TOOLKIT_SCROLL_BARS */
5260 /* Set the scroll bar's current state, unless we're currently being
5262 if (NILP (bar
->dragging
))
5264 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5267 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5270 int start
= ((double) position
* top_range
) / whole
;
5271 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5272 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5275 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5279 /* The following three hooks are used when we're doing a thorough
5280 redisplay of the frame. We don't explicitly know which scroll bars
5281 are going to be deleted, because keeping track of when windows go
5282 away is a real pain - "Can you say set-window-configuration, boys
5283 and girls?" Instead, we just assert at the beginning of redisplay
5284 that *all* scroll bars are to be removed, and then save a scroll bar
5285 from the fiery pit when we actually redisplay its window. */
5287 /* Arrange for all scroll bars on FRAME to be removed at the next call
5288 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5289 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5292 XTcondemn_scroll_bars (frame
)
5295 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5296 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5299 bar
= FRAME_SCROLL_BARS (frame
);
5300 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5301 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5302 XSCROLL_BAR (bar
)->prev
= Qnil
;
5303 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5304 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5305 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5310 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5311 Note that WINDOW isn't necessarily condemned at all. */
5314 XTredeem_scroll_bar (window
)
5315 struct window
*window
;
5317 struct scroll_bar
*bar
;
5320 /* We can't redeem this window's scroll bar if it doesn't have one. */
5321 if (NILP (window
->vertical_scroll_bar
))
5324 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5326 /* Unlink it from the condemned list. */
5327 f
= XFRAME (WINDOW_FRAME (window
));
5328 if (NILP (bar
->prev
))
5330 /* If the prev pointer is nil, it must be the first in one of
5332 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5333 /* It's not condemned. Everything's fine. */
5335 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5336 window
->vertical_scroll_bar
))
5337 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5339 /* If its prev pointer is nil, it must be at the front of
5340 one or the other! */
5344 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5346 if (! NILP (bar
->next
))
5347 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5349 bar
->next
= FRAME_SCROLL_BARS (f
);
5351 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5352 if (! NILP (bar
->next
))
5353 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5356 /* Remove all scroll bars on FRAME that haven't been saved since the
5357 last call to `*condemn_scroll_bars_hook'. */
5360 XTjudge_scroll_bars (f
)
5363 Lisp_Object bar
, next
;
5365 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5367 /* Clear out the condemned list now so we won't try to process any
5368 more events on the hapless scroll bars. */
5369 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5371 for (; ! NILP (bar
); bar
= next
)
5373 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5375 x_scroll_bar_remove (b
);
5378 b
->next
= b
->prev
= Qnil
;
5381 /* Now there should be no references to the condemned scroll bars,
5382 and they should get garbage-collected. */
5386 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5387 is set to something other than NO_EVENT, it is enqueued.
5389 This may be called from a signal handler, so we have to ignore GC
5393 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5394 struct scroll_bar
*bar
;
5395 ControlPartCode part_code
;
5396 const EventRecord
*er
;
5397 struct input_event
*bufp
;
5399 int win_y
, top_range
;
5401 if (! GC_WINDOWP (bar
->window
))
5404 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5405 bufp
->frame_or_window
= bar
->window
;
5408 bar
->dragging
= Qnil
;
5412 case kControlUpButtonPart
:
5413 bufp
->part
= scroll_bar_up_arrow
;
5415 case kControlDownButtonPart
:
5416 bufp
->part
= scroll_bar_down_arrow
;
5418 case kControlPageUpPart
:
5419 bufp
->part
= scroll_bar_above_handle
;
5421 case kControlPageDownPart
:
5422 bufp
->part
= scroll_bar_below_handle
;
5424 #if TARGET_API_MAC_CARBON
5427 case kControlIndicatorPart
:
5429 if (er
->what
== mouseDown
)
5430 bar
->dragging
= make_number (0);
5431 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5432 bufp
->part
= scroll_bar_handle
;
5436 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5437 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5439 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5443 if (! NILP (bar
->dragging
))
5444 win_y
-= XINT (bar
->dragging
);
5448 if (win_y
> top_range
)
5451 XSETINT (bufp
->x
, win_y
);
5452 XSETINT (bufp
->y
, top_range
);
5455 #ifndef USE_TOOLKIT_SCROLL_BARS
5457 /* Handle some mouse motion while someone is dragging the scroll bar.
5459 This may be called from a signal handler, so we have to ignore GC
5463 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5464 struct scroll_bar
*bar
;
5468 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5470 last_mouse_movement_time
= t
;
5473 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5475 /* If we're dragging the bar, display it. */
5476 if (! GC_NILP (bar
->dragging
))
5478 /* Where should the handle be now? */
5479 int new_start
= y_pos
- 24;
5481 if (new_start
!= XINT (bar
->start
))
5483 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5485 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5490 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5492 /* Return information to the user about the current position of the mouse
5493 on the scroll bar. */
5496 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5498 Lisp_Object
*bar_window
;
5499 enum scroll_bar_part
*part
;
5501 unsigned long *time
;
5503 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5504 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5505 #if TARGET_API_MAC_CARBON
5506 WindowPtr wp
= GetControlOwner (ch
);
5508 WindowPtr wp
= (*ch
)->contrlOwner
;
5511 struct frame
*f
= mac_window_to_frame (wp
);
5512 int win_y
, top_range
;
5514 SetPortWindowPort (wp
);
5516 GetMouse (&mouse_pos
);
5518 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5519 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5521 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5525 if (! NILP (bar
->dragging
))
5526 win_y
-= XINT (bar
->dragging
);
5530 if (win_y
> top_range
)
5534 *bar_window
= bar
->window
;
5536 if (! NILP (bar
->dragging
))
5537 *part
= scroll_bar_handle
;
5538 else if (win_y
< XINT (bar
->start
))
5539 *part
= scroll_bar_above_handle
;
5540 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5541 *part
= scroll_bar_handle
;
5543 *part
= scroll_bar_below_handle
;
5545 XSETINT (*x
, win_y
);
5546 XSETINT (*y
, top_range
);
5549 last_mouse_scroll_bar
= Qnil
;
5551 *time
= last_mouse_movement_time
;
5555 /* The screen has been cleared so we may have changed foreground or
5556 background colors, and the scroll bars may need to be redrawn.
5557 Clear out the scroll bars, and ask for expose events, so we can
5561 x_scroll_bar_clear (f
)
5564 XTcondemn_scroll_bars (f
);
5565 XTjudge_scroll_bars (f
);
5569 /***********************************************************************
5571 ***********************************************************************/
5573 /* Set clipping for output in glyph row ROW. W is the window in which
5574 we operate. GC is the graphics context to set clipping in.
5576 ROW may be a text row or, e.g., a mode line. Text rows must be
5577 clipped to the interior of the window dedicated to text display,
5578 mode lines must be clipped to the whole window. */
5581 x_clip_to_row (w
, row
, area
, gc
)
5583 struct glyph_row
*row
;
5587 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5589 int window_x
, window_y
, window_width
;
5591 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5593 clip_rect
.left
= window_x
;
5594 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5595 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5596 clip_rect
.right
= clip_rect
.left
+ window_width
;
5597 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5599 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5603 /* Draw a hollow box cursor on window W in glyph row ROW. */
5606 x_draw_hollow_cursor (w
, row
)
5608 struct glyph_row
*row
;
5610 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5611 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5612 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5615 struct glyph
*cursor_glyph
;
5618 /* Get the glyph the cursor is on. If we can't tell because
5619 the current matrix is invalid or such, give up. */
5620 cursor_glyph
= get_phys_cursor_glyph (w
);
5621 if (cursor_glyph
== NULL
)
5624 /* Compute frame-relative coordinates for phys cursor. */
5625 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5626 wd
= w
->phys_cursor_width
;
5628 /* The foreground of cursor_gc is typically the same as the normal
5629 background color, which can cause the cursor box to be invisible. */
5630 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5631 if (dpyinfo
->scratch_cursor_gc
)
5632 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5634 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5635 GCForeground
, &xgcv
);
5636 gc
= dpyinfo
->scratch_cursor_gc
;
5638 /* Set clipping, draw the rectangle, and reset clipping again. */
5639 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5640 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5641 mac_reset_clip_rectangles (dpy
, gc
);
5645 /* Draw a bar cursor on window W in glyph row ROW.
5647 Implementation note: One would like to draw a bar cursor with an
5648 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5649 Unfortunately, I didn't find a font yet that has this property set.
5653 x_draw_bar_cursor (w
, row
, width
, kind
)
5655 struct glyph_row
*row
;
5657 enum text_cursor_kinds kind
;
5659 struct frame
*f
= XFRAME (w
->frame
);
5660 struct glyph
*cursor_glyph
;
5662 /* If cursor is out of bounds, don't draw garbage. This can happen
5663 in mini-buffer windows when switching between echo area glyphs
5665 cursor_glyph
= get_phys_cursor_glyph (w
);
5666 if (cursor_glyph
== NULL
)
5669 /* If on an image, draw like a normal cursor. That's usually better
5670 visible than drawing a bar, esp. if the image is large so that
5671 the bar might not be in the window. */
5672 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5674 struct glyph_row
*row
;
5675 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5676 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5680 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5681 Window window
= FRAME_MAC_WINDOW (f
);
5682 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5683 unsigned long mask
= GCForeground
| GCBackground
;
5684 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5687 /* If the glyph's background equals the color we normally draw
5688 the bar cursor in, the bar cursor in its normal color is
5689 invisible. Use the glyph's foreground color instead in this
5690 case, on the assumption that the glyph's colors are chosen so
5691 that the glyph is legible. */
5692 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5693 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5695 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5698 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5701 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5702 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5706 width
= FRAME_CURSOR_WIDTH (f
);
5707 width
= min (cursor_glyph
->pixel_width
, width
);
5709 w
->phys_cursor_width
= width
;
5710 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5712 if (kind
== BAR_CURSOR
)
5713 mac_fill_rectangle (f
, gc
,
5714 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5715 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5716 width
, row
->height
);
5718 mac_fill_rectangle (f
, gc
,
5719 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5720 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5721 row
->height
- width
),
5722 cursor_glyph
->pixel_width
,
5725 mac_reset_clip_rectangles (dpy
, gc
);
5730 /* RIF: Define cursor CURSOR on frame F. */
5733 mac_define_frame_cursor (f
, cursor
)
5737 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5739 if (dpyinfo
->x_focus_frame
== f
)
5740 SetThemeCursor (cursor
);
5744 /* RIF: Clear area on frame F. */
5747 mac_clear_frame_area (f
, x
, y
, width
, height
)
5749 int x
, y
, width
, height
;
5751 mac_clear_area (f
, x
, y
, width
, height
);
5755 /* RIF: Draw cursor on window W. */
5758 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5760 struct glyph_row
*glyph_row
;
5762 int cursor_type
, cursor_width
;
5767 w
->phys_cursor_type
= cursor_type
;
5768 w
->phys_cursor_on_p
= 1;
5770 if (glyph_row
->exact_window_width_line_p
5771 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5773 glyph_row
->cursor_in_fringe_p
= 1;
5774 draw_fringe_bitmap (w
, glyph_row
, 0);
5777 switch (cursor_type
)
5779 case HOLLOW_BOX_CURSOR
:
5780 x_draw_hollow_cursor (w
, glyph_row
);
5783 case FILLED_BOX_CURSOR
:
5784 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5788 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5792 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5796 w
->phys_cursor_width
= 0;
5808 #if 0 /* MAC_TODO: no icon support yet. */
5810 x_bitmap_icon (f
, icon
)
5816 if (FRAME_W32_WINDOW (f
) == 0)
5820 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5821 else if (STRINGP (icon
))
5822 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5823 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5824 else if (SYMBOLP (icon
))
5828 if (EQ (icon
, intern ("application")))
5829 name
= (LPCTSTR
) IDI_APPLICATION
;
5830 else if (EQ (icon
, intern ("hand")))
5831 name
= (LPCTSTR
) IDI_HAND
;
5832 else if (EQ (icon
, intern ("question")))
5833 name
= (LPCTSTR
) IDI_QUESTION
;
5834 else if (EQ (icon
, intern ("exclamation")))
5835 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5836 else if (EQ (icon
, intern ("asterisk")))
5837 name
= (LPCTSTR
) IDI_ASTERISK
;
5838 else if (EQ (icon
, intern ("winlogo")))
5839 name
= (LPCTSTR
) IDI_WINLOGO
;
5843 hicon
= LoadIcon (NULL
, name
);
5851 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5856 #endif /* MAC_TODO */
5858 /************************************************************************
5860 ************************************************************************/
5862 /* Display Error Handling functions not used on W32. Listing them here
5863 helps diff stay in step when comparing w32term.c with xterm.c.
5865 x_error_catcher (display, error)
5866 x_catch_errors (dpy)
5867 x_catch_errors_unwind (old_val)
5868 x_check_errors (dpy, format)
5869 x_had_errors_p (dpy)
5870 x_clear_errors (dpy)
5871 x_uncatch_errors (dpy, count)
5873 x_connection_signal (signalnum)
5874 x_connection_closed (dpy, error_message)
5875 x_error_quitter (display, error)
5876 x_error_handler (display, error)
5877 x_io_error_quitter (display)
5882 /* Changing the font of the frame. */
5884 /* Give frame F the font named FONTNAME as its default font, and
5885 return the full name of that font. FONTNAME may be a wildcard
5886 pattern; in that case, we choose some font that fits the pattern.
5887 The return value shows which font we chose. */
5890 x_new_font (f
, fontname
)
5892 register char *fontname
;
5894 struct font_info
*fontp
5895 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5900 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5901 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5902 FRAME_FONTSET (f
) = -1;
5904 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5905 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5906 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5908 compute_fringe_widths (f
, 1);
5910 /* Compute the scroll bar width in character columns. */
5911 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5913 int wid
= FRAME_COLUMN_WIDTH (f
);
5914 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5915 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5919 int wid
= FRAME_COLUMN_WIDTH (f
);
5920 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5923 /* Now make the frame display the given font. */
5924 if (FRAME_MAC_WINDOW (f
) != 0)
5926 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5928 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5930 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5933 /* Don't change the size of a tip frame; there's no point in
5934 doing it because it's done in Fx_show_tip, and it leads to
5935 problems because the tip frame has no widget. */
5936 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5937 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5940 return build_string (fontp
->full_name
);
5943 /* Give frame F the fontset named FONTSETNAME as its default font, and
5944 return the full name of that fontset. FONTSETNAME may be a wildcard
5945 pattern; in that case, we choose some fontset that fits the pattern.
5946 The return value shows which fontset we chose. */
5949 x_new_fontset (f
, fontsetname
)
5953 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5959 if (FRAME_FONTSET (f
) == fontset
)
5960 /* This fontset is already set in frame F. There's nothing more
5962 return fontset_name (fontset
);
5964 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5966 if (!STRINGP (result
))
5967 /* Can't load ASCII font. */
5970 /* Since x_new_font doesn't update any fontset information, do it now. */
5971 FRAME_FONTSET (f
) = fontset
;
5973 return build_string (fontsetname
);
5977 /***********************************************************************
5978 TODO: W32 Input Methods
5979 ***********************************************************************/
5980 /* Listing missing functions from xterm.c helps diff stay in step.
5982 xim_destroy_callback (xim, client_data, call_data)
5983 xim_open_dpy (dpyinfo, resource_name)
5985 xim_instantiate_callback (display, client_data, call_data)
5986 xim_initialize (dpyinfo, resource_name)
5987 xim_close_dpy (dpyinfo)
5993 mac_get_window_bounds (f
, inner
, outer
)
5995 Rect
*inner
, *outer
;
5997 #if TARGET_API_MAC_CARBON
5998 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5999 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6000 #else /* not TARGET_API_MAC_CARBON */
6001 RgnHandle region
= NewRgn ();
6003 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6004 *inner
= (*region
)->rgnBBox
;
6005 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6006 *outer
= (*region
)->rgnBBox
;
6007 DisposeRgn (region
);
6008 #endif /* not TARGET_API_MAC_CARBON */
6012 mac_handle_origin_change (f
)
6015 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6019 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6021 int pixelwidth
, pixelheight
;
6025 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6026 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6028 if (cols
!= FRAME_COLS (f
)
6029 || rows
!= FRAME_LINES (f
)
6030 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6031 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6033 /* We pass 1 for DELAY since we can't run Lisp code inside of
6035 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6036 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6037 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6038 SET_FRAME_GARBAGED (f
);
6040 /* If cursor was outside the new size, mark it as off. */
6041 mark_window_cursors_off (XWINDOW (f
->root_window
));
6043 /* Clear out any recollection of where the mouse highlighting
6044 was, since it might be in a place that's outside the new
6045 frame size. Actually checking whether it is outside is a
6046 pain in the neck, so don't try--just let the highlighting be
6047 done afresh with new size. */
6048 cancel_mouse_face (f
);
6050 #if TARGET_API_MAC_CARBON
6051 if (f
->output_data
.mac
->hourglass_control
)
6054 mac_prepare_for_quickdraw (f
);
6056 MoveControl (f
->output_data
.mac
->hourglass_control
,
6057 pixelwidth
- HOURGLASS_WIDTH
, 0);
6064 /* Calculate the absolute position in frame F
6065 from its current recorded position values and gravity. */
6068 x_calc_absolute_position (f
)
6071 int width_diff
= 0, height_diff
= 0;
6072 int flags
= f
->size_hint_flags
;
6075 /* We have nothing to do if the current position
6076 is already for the top-left corner. */
6077 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6080 /* Find the offsets of the outside upper-left corner of
6081 the inner window, with respect to the outer window. */
6083 mac_get_window_bounds (f
, &inner
, &outer
);
6086 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6087 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6089 /* Treat negative positions as relative to the leftmost bottommost
6090 position that fits on the screen. */
6091 if (flags
& XNegative
)
6092 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6094 - FRAME_PIXEL_WIDTH (f
)
6097 if (flags
& YNegative
)
6098 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6100 - FRAME_PIXEL_HEIGHT (f
)
6103 /* The left_pos and top_pos
6104 are now relative to the top and left screen edges,
6105 so the flags should correspond. */
6106 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6109 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6110 to really change the position, and 0 when calling from
6111 x_make_frame_visible (in that case, XOFF and YOFF are the current
6112 position values). It is -1 when calling from x_set_frame_parameters,
6113 which means, do adjust for borders but don't change the gravity. */
6116 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6118 register int xoff
, yoff
;
6121 if (change_gravity
> 0)
6125 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6127 f
->size_hint_flags
|= XNegative
;
6129 f
->size_hint_flags
|= YNegative
;
6130 f
->win_gravity
= NorthWestGravity
;
6132 x_calc_absolute_position (f
);
6135 x_wm_set_size_hint (f
, (long) 0, 0);
6137 #if TARGET_API_MAC_CARBON
6138 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6139 /* If the title bar is completely outside the screen, adjust the
6141 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6142 kWindowConstrainMoveRegardlessOfFit
6143 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6144 #if USE_CARBON_EVENTS
6145 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6147 mac_handle_origin_change (f
);
6150 Rect inner
, outer
, screen_rect
, dummy
;
6151 RgnHandle region
= NewRgn ();
6153 mac_get_window_bounds (f
, &inner
, &outer
);
6154 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6155 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6156 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6157 f
->top_pos
+ f
->y_pixels_diff
, false);
6159 /* If the title bar is completely outside the screen, adjust the
6160 position. The variable `outer' holds the title bar rectangle.
6161 The variable `inner' holds slightly smaller one than `outer',
6162 so that the calculation of overlapping may not become too
6164 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6165 outer
= (*region
)->rgnBBox
;
6166 DisposeRgn (region
);
6168 InsetRect (&inner
, 8, 8);
6169 screen_rect
= qd
.screenBits
.bounds
;
6170 screen_rect
.top
+= GetMBarHeight ();
6172 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6174 if (inner
.right
<= screen_rect
.left
)
6175 f
->left_pos
= screen_rect
.left
;
6176 else if (inner
.left
>= screen_rect
.right
)
6177 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6179 if (inner
.bottom
<= screen_rect
.top
)
6180 f
->top_pos
= screen_rect
.top
;
6181 else if (inner
.top
>= screen_rect
.bottom
)
6182 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6184 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6185 f
->top_pos
+ f
->y_pixels_diff
, false);
6193 /* Call this to change the size of frame F's x-window.
6194 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6195 for this size change and subsequent size changes.
6196 Otherwise we leave the window gravity unchanged. */
6199 x_set_window_size (f
, change_gravity
, cols
, rows
)
6204 int pixelwidth
, pixelheight
;
6208 check_frame_size (f
, &rows
, &cols
);
6209 f
->scroll_bar_actual_width
6210 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6212 compute_fringe_widths (f
, 0);
6214 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6215 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6217 f
->win_gravity
= NorthWestGravity
;
6218 x_wm_set_size_hint (f
, (long) 0, 0);
6220 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6222 #if USE_CARBON_EVENTS
6223 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6225 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6227 if (f
->output_data
.mac
->internal_border_width
6228 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6230 mac_clear_window (f
);
6231 f
->output_data
.mac
->internal_border_width
6232 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6235 SET_FRAME_GARBAGED (f
);
6240 /* Mouse warping. */
6242 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6245 x_set_mouse_position (f
, x
, y
)
6251 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6252 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6254 if (pix_x
< 0) pix_x
= 0;
6255 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6257 if (pix_y
< 0) pix_y
= 0;
6258 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6260 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6264 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6273 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
6279 CGWarpMouseCursorPosition (point
);
6282 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6285 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6286 0, 0, 0, 0, pix_x
, pix_y
);
6292 /* focus shifting, raising and lowering. */
6295 x_focus_on_frame (f
)
6298 #if 0 /* This proves to be unpleasant. */
6302 /* I don't think that the ICCCM allows programs to do things like this
6303 without the interaction of the window manager. Whatever you end up
6304 doing with this code, do it to x_unfocus_frame too. */
6305 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6306 RevertToPointerRoot
, CurrentTime
);
6316 /* Raise frame F. */
6322 if (f
->async_visible
)
6325 BringToFront (FRAME_MAC_WINDOW (f
));
6330 /* Lower frame F. */
6336 if (f
->async_visible
)
6339 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6345 XTframe_raise_lower (f
, raise_flag
)
6355 /* Change of visibility. */
6358 mac_handle_visibility_change (f
)
6361 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6362 int visible
= 0, iconified
= 0;
6363 struct input_event buf
;
6365 if (IsWindowVisible (wp
))
6367 if (IsWindowCollapsed (wp
))
6373 if (!f
->async_visible
&& visible
)
6377 /* wait_reading_process_output will notice this and update
6378 the frame's display structures. If we were made
6379 invisible, we should not set garbaged, because that stops
6380 redrawing on Update events. */
6381 SET_FRAME_GARBAGED (f
);
6384 buf
.kind
= DEICONIFY_EVENT
;
6385 XSETFRAME (buf
.frame_or_window
, f
);
6387 kbd_buffer_store_event (&buf
);
6389 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6390 /* Force a redisplay sooner or later to update the
6391 frame titles in case this is the second frame. */
6392 record_asynch_buffer_change ();
6394 else if (f
->async_visible
&& !visible
)
6398 buf
.kind
= ICONIFY_EVENT
;
6399 XSETFRAME (buf
.frame_or_window
, f
);
6401 kbd_buffer_store_event (&buf
);
6404 f
->async_visible
= visible
;
6405 f
->async_iconified
= iconified
;
6408 /* This tries to wait until the frame is really visible.
6409 However, if the window manager asks the user where to position
6410 the frame, this will return before the user finishes doing that.
6411 The frame will not actually be visible at that time,
6412 but it will become visible later when the window manager
6413 finishes with it. */
6416 x_make_frame_visible (f
)
6421 if (! FRAME_VISIBLE_P (f
))
6423 /* We test FRAME_GARBAGED_P here to make sure we don't
6424 call x_set_offset a second time
6425 if we get to x_make_frame_visible a second time
6426 before the window gets really visible. */
6427 if (! FRAME_ICONIFIED_P (f
)
6428 && ! f
->output_data
.mac
->asked_for_visible
)
6430 #if TARGET_API_MAC_CARBON
6431 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6433 struct frame
*sf
= SELECTED_FRAME ();
6434 if (!FRAME_MAC_P (sf
))
6435 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6436 kWindowCenterOnMainScreen
);
6438 RepositionWindow (FRAME_MAC_WINDOW (f
),
6439 FRAME_MAC_WINDOW (sf
),
6440 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6441 kWindowCascadeStartAtParentWindowScreen
6443 kWindowCascadeOnParentWindowScreen
6446 #if USE_CARBON_EVENTS
6447 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6449 mac_handle_origin_change (f
);
6453 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6456 f
->output_data
.mac
->asked_for_visible
= 1;
6458 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6459 ShowWindow (FRAME_MAC_WINDOW (f
));
6462 XFlush (FRAME_MAC_DISPLAY (f
));
6464 /* Synchronize to ensure Emacs knows the frame is visible
6465 before we do anything else. We do this loop with input not blocked
6466 so that incoming events are handled. */
6471 /* This must come after we set COUNT. */
6474 XSETFRAME (frame
, f
);
6476 /* Wait until the frame is visible. Process X events until a
6477 MapNotify event has been seen, or until we think we won't get a
6478 MapNotify at all.. */
6479 for (count
= input_signal_count
+ 10;
6480 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6482 /* Force processing of queued events. */
6485 /* Machines that do polling rather than SIGIO have been
6486 observed to go into a busy-wait here. So we'll fake an
6487 alarm signal to let the handler know that there's something
6488 to be read. We used to raise a real alarm, but it seems
6489 that the handler isn't always enabled here. This is
6491 if (input_polling_used ())
6493 /* It could be confusing if a real alarm arrives while
6494 processing the fake one. Turn it off and let the
6495 handler reset it. */
6496 extern void poll_for_input_1
P_ ((void));
6497 int old_poll_suppress_count
= poll_suppress_count
;
6498 poll_suppress_count
= 1;
6499 poll_for_input_1 ();
6500 poll_suppress_count
= old_poll_suppress_count
;
6503 /* See if a MapNotify event has been processed. */
6504 FRAME_SAMPLE_VISIBILITY (f
);
6509 /* Change from mapped state to withdrawn state. */
6511 /* Make the frame visible (mapped and not iconified). */
6514 x_make_frame_invisible (f
)
6517 /* A deactivate event does not occur when the last visible frame is
6518 made invisible. So if we clear the highlight here, it will not
6519 be rehighlighted when it is made visible. */
6521 /* Don't keep the highlight on an invisible frame. */
6522 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6523 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6528 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6529 that the current position of the window is user-specified, rather than
6530 program-specified, so that when the window is mapped again, it will be
6531 placed at the same location, without forcing the user to position it
6532 by hand again (they have already done that once for this window.) */
6533 x_wm_set_size_hint (f
, (long) 0, 1);
6535 HideWindow (FRAME_MAC_WINDOW (f
));
6539 #if !USE_CARBON_EVENTS
6540 mac_handle_visibility_change (f
);
6544 /* Change window state from mapped to iconified. */
6552 /* A deactivate event does not occur when the last visible frame is
6553 iconified. So if we clear the highlight here, it will not be
6554 rehighlighted when it is deiconified. */
6556 /* Don't keep the highlight on an invisible frame. */
6557 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6558 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6561 if (f
->async_iconified
)
6566 FRAME_SAMPLE_VISIBILITY (f
);
6568 if (! FRAME_VISIBLE_P (f
))
6569 ShowWindow (FRAME_MAC_WINDOW (f
));
6571 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6576 error ("Can't notify window manager of iconification");
6578 #if !USE_CARBON_EVENTS
6579 mac_handle_visibility_change (f
);
6584 /* Free X resources of frame F. */
6587 x_free_frame_resources (f
)
6590 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6591 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6595 if (wp
!= tip_window
)
6596 remove_window_handler (wp
);
6599 mac_prepare_for_quickdraw (f
);
6602 if (wp
== tip_window
)
6603 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6604 closed' event. So we reset tip_window here. */
6607 free_frame_menubar (f
);
6609 if (FRAME_FACE_CACHE (f
))
6610 free_frame_faces (f
);
6614 if (FRAME_SIZE_HINTS (f
))
6615 xfree (FRAME_SIZE_HINTS (f
));
6617 xfree (f
->output_data
.mac
);
6618 f
->output_data
.mac
= NULL
;
6620 if (f
== dpyinfo
->x_focus_frame
)
6622 dpyinfo
->x_focus_frame
= 0;
6623 #if USE_MAC_FONT_PANEL
6624 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6627 if (f
== dpyinfo
->x_focus_event_frame
)
6628 dpyinfo
->x_focus_event_frame
= 0;
6629 if (f
== dpyinfo
->x_highlight_frame
)
6630 dpyinfo
->x_highlight_frame
= 0;
6632 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6634 dpyinfo
->mouse_face_beg_row
6635 = dpyinfo
->mouse_face_beg_col
= -1;
6636 dpyinfo
->mouse_face_end_row
6637 = dpyinfo
->mouse_face_end_col
= -1;
6638 dpyinfo
->mouse_face_window
= Qnil
;
6639 dpyinfo
->mouse_face_deferred_gc
= 0;
6640 dpyinfo
->mouse_face_mouse_frame
= 0;
6647 /* Destroy the X window of frame F. */
6650 x_destroy_window (f
)
6653 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6655 x_free_frame_resources (f
);
6657 dpyinfo
->reference_count
--;
6661 /* Setting window manager hints. */
6663 /* Set the normal size hints for the window manager, for frame F.
6664 FLAGS is the flags word to use--or 0 meaning preserve the flags
6665 that the window now has.
6666 If USER_POSITION is nonzero, we set the USPosition
6667 flag (this is useful when FLAGS is 0). */
6669 x_wm_set_size_hint (f
, flags
, user_position
)
6674 int base_width
, base_height
, width_inc
, height_inc
;
6675 int min_rows
= 0, min_cols
= 0;
6676 XSizeHints
*size_hints
;
6678 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6679 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6680 width_inc
= FRAME_COLUMN_WIDTH (f
);
6681 height_inc
= FRAME_LINE_HEIGHT (f
);
6683 check_frame_size (f
, &min_rows
, &min_cols
);
6685 size_hints
= FRAME_SIZE_HINTS (f
);
6686 if (size_hints
== NULL
)
6688 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6689 bzero (size_hints
, sizeof (XSizeHints
));
6692 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6693 size_hints
->width_inc
= width_inc
;
6694 size_hints
->height_inc
= height_inc
;
6695 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6696 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6697 size_hints
->base_width
= base_width
;
6698 size_hints
->base_height
= base_height
;
6701 size_hints
->flags
= flags
;
6702 else if (user_position
)
6704 size_hints
->flags
&= ~ PPosition
;
6705 size_hints
->flags
|= USPosition
;
6709 #if 0 /* MAC_TODO: hide application instead of iconify? */
6710 /* Used for IconicState or NormalState */
6713 x_wm_set_window_state (f
, state
)
6717 #ifdef USE_X_TOOLKIT
6720 XtSetArg (al
[0], XtNinitialState
, state
);
6721 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6722 #else /* not USE_X_TOOLKIT */
6723 Window window
= FRAME_X_WINDOW (f
);
6725 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6726 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6728 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6729 #endif /* not USE_X_TOOLKIT */
6733 x_wm_set_icon_pixmap (f
, pixmap_id
)
6739 #ifndef USE_X_TOOLKIT
6740 Window window
= FRAME_X_WINDOW (f
);
6745 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6746 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6750 /* It seems there is no way to turn off use of an icon pixmap.
6751 The following line does it, only if no icon has yet been created,
6752 for some window managers. But with mwm it crashes.
6753 Some people say it should clear the IconPixmapHint bit in this case,
6754 but that doesn't work, and the X consortium said it isn't the
6755 right thing at all. Since there is no way to win,
6756 best to explicitly give up. */
6758 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6764 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6768 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6769 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6772 #else /* not USE_X_TOOLKIT */
6774 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6775 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6777 #endif /* not USE_X_TOOLKIT */
6780 #endif /* MAC_TODO */
6783 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6787 #if 0 /* MAC_TODO: no icons on Mac */
6788 #ifdef USE_X_TOOLKIT
6789 Window window
= XtWindow (f
->output_data
.x
->widget
);
6791 Window window
= FRAME_X_WINDOW (f
);
6794 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6795 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6796 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6798 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6799 #endif /* MAC_TODO */
6803 /***********************************************************************
6805 ***********************************************************************/
6807 /* An XLFD pattern is divided into blocks delimited by '*'. This
6808 structure holds information for each block. */
6809 struct xlfdpat_block
6811 /* Length of the pattern string in this block. Non-zero except for
6812 the first and the last blocks. */
6815 /* Pattern string except the last character in this block. The last
6816 character is replaced with NUL in order to use it as a
6818 unsigned char *pattern
;
6820 /* Last character of the pattern string. Must not be '?'. */
6821 unsigned char last_char
;
6823 /* One of the tables for the Boyer-Moore string search. It
6824 specifies the number of positions to proceed for each character
6825 with which the match fails. */
6828 /* The skip value for the last character in the above `skip' is
6829 assigned to `infinity' in order to simplify a loop condition.
6830 The original value is saved here. */
6836 /* Normalized pattern string. "Normalized" means that capital
6837 letters are lowered, blocks are not empty except the first and
6838 the last ones, and trailing '?'s in a block that is not the last
6839 one are moved to the next one. The last character in each block
6840 is replaced with NUL. */
6843 /* Number of characters except '*'s and trailing '?'s in the
6844 normalized pattern string. */
6847 /* Number of trailing '?'s in the normalized pattern string. */
6848 int trailing_anychars
;
6850 /* Number of blocks and information for each block. The latter is
6851 NULL if the pattern is exact (no '*' or '?' in it). */
6853 struct xlfdpat_block
*blocks
;
6857 xlfdpat_destroy (pat
)
6858 struct xlfdpat
*pat
;
6865 xfree (pat
->blocks
);
6872 static struct xlfdpat
*
6873 xlfdpat_create (pattern
)
6874 const char *pattern
;
6876 struct xlfdpat
*pat
;
6877 int nblocks
, i
, skip
;
6878 unsigned char last_char
, *p
, *q
, *anychar_head
;
6879 const unsigned char *ptr
;
6880 struct xlfdpat_block
*blk
;
6882 pat
= xmalloc (sizeof (struct xlfdpat
));
6883 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6885 /* Normalize the pattern string and store it to `pat->buf'. */
6887 anychar_head
= NULL
;
6890 for (ptr
= pattern
; *ptr
; ptr
++)
6892 unsigned char c
= *ptr
;
6895 if (last_char
== '*')
6896 /* ...a** -> ...a* */
6900 if (last_char
== '?')
6902 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6903 /* ...*??* -> ...*?? */
6906 /* ...a??* -> ...a*?? */
6908 *anychar_head
++ = '*';
6916 if (last_char
!= '?')
6920 /* On Mac OS X 10.3, tolower also converts non-ASCII
6921 characters for some locales. */
6925 *q
++ = last_char
= c
;
6929 pat
->nblocks
= nblocks
;
6930 if (last_char
!= '?')
6931 pat
->trailing_anychars
= 0;
6934 pat
->trailing_anychars
= q
- anychar_head
;
6937 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6939 if (anychar_head
== NULL
&& nblocks
== 1)
6941 /* The pattern is exact. */
6946 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6948 /* Divide the normalized pattern into blocks. */
6950 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6955 blk
->len
= p
- blk
->pattern
;
6959 blk
->len
= q
- blk
->pattern
;
6961 /* Setup a table for the Boyer-Moore string search. */
6962 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6965 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6966 blk
->pattern
[blk
->len
- 1] = '\0';
6968 for (skip
= 1; skip
< blk
->len
; skip
++)
6969 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6972 for (i
= 0; i
< 256; i
++)
6973 blk
->skip
[i
] = skip
;
6975 p
= blk
->pattern
+ (blk
->len
- skip
);
6977 blk
->skip
[*p
++] = skip
;
6979 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6986 xlfdpat_exact_p (pat
)
6987 struct xlfdpat
*pat
;
6989 return pat
->blocks
== NULL
;
6992 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6993 that the pattern in *BLK matches with its prefix. Return NULL
6994 there is no such strings. STRING must be lowered in advance. */
6997 xlfdpat_block_match_1 (blk
, string
, start_max
)
6998 struct xlfdpat_block
*blk
;
6999 const unsigned char *string
;
7002 int start
, infinity
;
7004 const unsigned char *s
;
7006 xassert (blk
->len
> 0);
7007 xassert (start_max
+ blk
->len
<= strlen (string
));
7008 xassert (blk
->last_char
!= '?');
7010 /* See the comments in the function `boyer_moore' (search.c) for the
7011 use of `infinity'. */
7012 infinity
= start_max
+ blk
->len
+ 1;
7013 blk
->skip
[blk
->last_char
] = infinity
;
7018 /* Check the last character of the pattern. */
7019 s
= string
+ blk
->len
- 1;
7022 start
+= blk
->skip
[*(s
+ start
)];
7024 while (start
<= start_max
);
7026 if (start
< infinity
)
7027 /* Couldn't find the last character. */
7030 /* No less than `infinity' means we could find the last
7031 character at `s[start - infinity]'. */
7034 /* Check the remaining characters. We prefer making no-'?'
7035 cases faster because the use of '?' is really rare. */
7040 while (*p
++ == *s
++)
7043 while (*(p
- 1) == '?');
7045 if (*(p
- 1) == '\0')
7047 return string
+ start
;
7050 start
+= blk
->last_char_skip
;
7052 while (start
<= start_max
);
7057 #define xlfdpat_block_match(b, s, m) \
7058 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7059 : xlfdpat_block_match_1 (b, s, m))
7061 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7062 matches with STRING. STRING must be lowered in advance. */
7065 xlfdpat_match (pat
, string
)
7066 struct xlfdpat
*pat
;
7067 const unsigned char *string
;
7069 int str_len
, nblocks
, i
, start_max
;
7070 struct xlfdpat_block
*blk
;
7071 const unsigned char *s
;
7073 xassert (pat
->nblocks
> 0);
7075 if (xlfdpat_exact_p (pat
))
7076 return strcmp (pat
->buf
, string
) == 0;
7078 /* The number of the characters in the string must not be smaller
7079 than that in the pattern. */
7080 str_len
= strlen (string
);
7081 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7084 /* Chop off the trailing '?'s. */
7085 str_len
-= pat
->trailing_anychars
;
7087 /* The last block. When it is non-empty, it must match at the end
7089 nblocks
= pat
->nblocks
;
7090 blk
= pat
->blocks
+ (nblocks
- 1);
7092 /* The last block is also the first one. */
7093 return (str_len
== blk
->len
7094 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7095 else if (blk
->len
!= 0)
7096 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7099 /* The first block. When it is non-empty, it must match at the
7100 beginning of the string. */
7104 s
= xlfdpat_block_match (blk
, string
, 0);
7107 string
= s
+ blk
->len
;
7110 /* The rest of the blocks. */
7111 start_max
= str_len
- pat
->nchars
;
7112 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7114 s
= xlfdpat_block_match (blk
, string
, start_max
);
7117 start_max
-= s
- string
;
7118 string
= s
+ blk
->len
;
7125 /***********************************************************************
7127 ***********************************************************************/
7129 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7132 x_get_font_info (f
, font_idx
)
7136 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7139 /* the global font name table */
7140 static char **font_name_table
= NULL
;
7141 static int font_name_table_size
= 0;
7142 static int font_name_count
= 0;
7144 /* Alist linking font family names to Font Manager font family
7145 references (which can also be used as QuickDraw font IDs). We use
7146 an alist because hash tables are not ready when the terminal frame
7147 for Mac OS Classic is created. */
7148 static Lisp_Object fm_font_family_alist
;
7150 /* Hash table linking font family names to ATSU font IDs. */
7151 static Lisp_Object atsu_font_id_hash
;
7152 /* Alist linking Font Manager style to face attributes. */
7153 static Lisp_Object fm_style_face_attributes_alist
;
7154 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7157 /* Alist linking character set strings to Mac text encoding and Emacs
7159 static Lisp_Object Vmac_charset_info_alist
;
7162 create_text_encoding_info_alist ()
7164 Lisp_Object result
= Qnil
, rest
;
7166 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7168 Lisp_Object charset_info
= XCAR (rest
);
7169 Lisp_Object charset
, coding_system
, text_encoding
;
7170 Lisp_Object existing_info
;
7172 if (!(CONSP (charset_info
)
7173 && (charset
= XCAR (charset_info
),
7175 && CONSP (XCDR (charset_info
))
7176 && (text_encoding
= XCAR (XCDR (charset_info
)),
7177 INTEGERP (text_encoding
))
7178 && CONSP (XCDR (XCDR (charset_info
)))
7179 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7180 SYMBOLP (coding_system
))))
7183 existing_info
= assq_no_quit (text_encoding
, result
);
7184 if (NILP (existing_info
))
7185 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7188 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7189 XSETCDR (XCDR (existing_info
),
7190 Fcons (charset
, XCDR (XCDR (existing_info
))));
7198 decode_mac_font_name (name
, size
, coding_system
)
7201 Lisp_Object coding_system
;
7203 struct coding_system coding
;
7206 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7208 for (p
= name
; *p
; p
++)
7209 if (!isascii (*p
) || iscntrl (*p
))
7214 setup_coding_system (coding_system
, &coding
);
7215 coding
.src_multibyte
= 0;
7216 coding
.dst_multibyte
= 1;
7217 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7218 coding
.composing
= COMPOSITION_DISABLED
;
7219 buf
= (char *) alloca (size
);
7221 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7222 bcopy (buf
, name
, coding
.produced
);
7223 name
[coding
.produced
] = '\0';
7227 /* If there's just one occurrence of '-' in the family name, it is
7228 replaced with '_'. (More than one occurrence of '-' means a
7229 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7230 p
= strchr (name
, '-');
7231 if (p
&& strchr (p
+ 1, '-') == NULL
)
7234 for (p
= name
; *p
; p
++)
7235 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7236 for some locales. */
7243 mac_to_x_fontname (name
, size
, style
, charset
)
7251 char xf
[256], *result
;
7254 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7258 strcpy(foundry
, "Apple");
7259 strcpy(family
, name
);
7262 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7263 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7264 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7266 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7267 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7268 for (p
= result
; *p
; p
++)
7269 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7270 for some locales. */
7277 /* Parse fully-specified and instantiated X11 font spec XF, and store
7278 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7279 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7280 caller must allocate at least 256 and 32 bytes respectively. For
7281 ordinary Mac fonts, the value stored to FAMILY should just be their
7282 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7283 intlfonts collection contain their charset designation in their
7284 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7285 types of font names are handled accordingly. */
7287 const int kDefaultFontSize
= 12;
7290 parse_x_font_name (xf
, family
, size
, style
, charset
)
7297 Str31 foundry
, weight
;
7298 int point_size
, avgwidth
;
7301 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7302 foundry
, family
, weight
, slant
, size
,
7303 &point_size
, &avgwidth
, charset
) != 8
7304 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7305 foundry
, family
, weight
, slant
, size
,
7306 &point_size
, &avgwidth
, charset
) != 8)
7312 *size
= point_size
/ 10;
7313 else if (avgwidth
> 0)
7314 *size
= avgwidth
/ 10;
7317 *size
= kDefaultFontSize
;
7320 if (strcmp (weight
, "bold") == 0)
7325 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7327 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7329 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7331 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7332 but take overlap into account. */
7333 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7334 memcpy (family
, foundry
, foundry_len
);
7335 family
[foundry_len
] = '-';
7336 family
[foundry_len
+ 1 + family_len
] = '-';
7337 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7343 for (p
= family
; *p
; p
++)
7344 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7345 for some locales. */
7354 add_font_name_table_entry (char *font_name
)
7356 if (font_name_table_size
== 0)
7358 font_name_table_size
= 256;
7359 font_name_table
= (char **)
7360 xmalloc (font_name_table_size
* sizeof (char *));
7362 else if (font_name_count
+ 1 >= font_name_table_size
)
7364 font_name_table_size
*= 2;
7365 font_name_table
= (char **)
7366 xrealloc (font_name_table
,
7367 font_name_table_size
* sizeof (char *));
7370 font_name_table
[font_name_count
++] = font_name
;
7374 add_mac_font_name (name
, size
, style
, charset
)
7378 const char *charset
;
7381 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7384 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7385 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7386 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7387 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7394 fm_get_style_from_font (font
)
7398 FMFontStyle style
= normal
;
7401 FMFontFamily font_family
;
7402 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
7404 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
7405 some font (e.g., Optima) even if it is `bold'. */
7406 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
7407 sizeof (mac_style
), &mac_style
, &len
);
7409 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
7410 style
= EndianU16_BtoN (mac_style
);
7412 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
7418 atsu_find_font_from_family_name (family
)
7421 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
7424 Lisp_Object rest
, best
;
7425 FMFontStyle min_style
, style
;
7427 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
7430 return kATSUInvalidFontID
;
7432 rest
= HASH_VALUE (h
, i
);
7433 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
7434 return cons_to_long (rest
);
7436 rest
= Fnreverse (rest
);
7440 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
7443 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
7444 if (style
< min_style
)
7447 if (style
== normal
)
7454 while (!NILP (rest
));
7456 HASH_VALUE (h
, i
) = best
;
7457 return cons_to_long (best
);
7461 fm_style_to_face_attributes (fm_style
)
7462 FMFontStyle fm_style
;
7466 fm_style
&= (bold
| italic
);
7467 tem
= assq_no_quit (make_number (fm_style
),
7468 fm_style_face_attributes_alist
);
7472 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
7473 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
7474 fm_style_face_attributes_alist
=
7475 Fcons (Fcons (make_number (fm_style
), tem
),
7476 fm_style_face_attributes_alist
);
7482 atsu_find_font_family_name (font_id
)
7487 Lisp_Object family
= Qnil
;
7489 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7490 kFontMacintoshPlatform
, kFontNoScript
,
7491 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
7494 family
= make_uninit_string (len
);
7495 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
7496 kFontMacintoshPlatform
, kFontNoScript
,
7497 kFontNoLanguage
, len
, SDATA (family
),
7501 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
7507 mac_atsu_font_face_attributes (font_id
)
7510 Lisp_Object family
, style_attrs
;
7512 family
= atsu_find_font_family_name (font_id
);
7515 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
7516 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
7520 /* Sets up the table font_name_table to contain the list of all fonts
7521 in the system the first time the table is used so that the Resource
7522 Manager need not be accessed every time this information is
7526 init_font_name_table ()
7528 #if TARGET_API_MAC_CARBON
7529 FMFontFamilyIterator ffi
;
7530 FMFontFamilyInstanceIterator ffii
;
7532 Lisp_Object text_encoding_info_alist
;
7533 struct gcpro gcpro1
;
7535 text_encoding_info_alist
= create_text_encoding_info_alist ();
7538 #if USE_CG_TEXT_DRAWING
7539 init_cg_text_anti_aliasing_threshold ();
7541 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7542 text_encoding_info_alist
)))
7545 struct Lisp_Hash_Table
*h
;
7547 ItemCount nfonts
, i
;
7548 ATSUFontID
*font_ids
= NULL
;
7549 Lisp_Object prev_family
= Qnil
;
7553 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7554 make_float (DEFAULT_REHASH_SIZE
),
7555 make_float (DEFAULT_REHASH_THRESHOLD
),
7557 h
= XHASH_TABLE (atsu_font_id_hash
);
7559 err
= ATSUFontCount (&nfonts
);
7562 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7563 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7566 for (i
= 0; i
< nfonts
; i
++)
7570 family
= atsu_find_font_family_name (font_ids
[i
]);
7571 if (NILP (family
) || SREF (family
, 0) == '.')
7573 if (!NILP (Fequal (prev_family
, family
)))
7574 family
= prev_family
;
7576 j
= hash_lookup (h
, family
, &hash_code
);
7579 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
7580 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
7583 else if (EQ (prev_family
, family
))
7584 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
7586 prev_family
= family
;
7593 /* Create a dummy instance iterator here to avoid creating and
7594 destroying it in the loop. */
7595 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7597 /* Create an iterator to enumerate the font families. */
7598 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7601 FMDisposeFontFamilyInstanceIterator (&ffii
);
7605 GCPRO1 (text_encoding_info_alist
);
7607 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7613 TextEncoding encoding
;
7614 TextEncodingBase sc
;
7615 Lisp_Object text_encoding_info
, family
;
7617 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7623 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7625 sc
= GetTextEncodingBase (encoding
);
7626 text_encoding_info
= assq_no_quit (make_number (sc
),
7627 text_encoding_info_alist
);
7628 if (NILP (text_encoding_info
))
7629 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7630 text_encoding_info_alist
);
7631 decode_mac_font_name (name
, sizeof (name
),
7632 XCAR (XCDR (text_encoding_info
)));
7633 family
= build_string (name
);
7634 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7636 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7637 fm_font_family_alist
);
7639 /* Point the instance iterator at the current font family. */
7640 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7643 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7646 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7648 if (size
> 0 || style
== normal
)
7649 for (; !NILP (rest
); rest
= XCDR (rest
))
7650 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7656 /* Dispose of the iterators. */
7657 FMDisposeFontFamilyIterator (&ffi
);
7658 FMDisposeFontFamilyInstanceIterator (&ffii
);
7659 #else /* !TARGET_API_MAC_CARBON */
7661 SInt16 fontnum
, old_fontnum
;
7662 int num_mac_fonts
= CountResources('FOND');
7664 Handle font_handle
, font_handle_2
;
7665 short id
, scriptcode
;
7668 struct FontAssoc
*fat
;
7669 struct AsscEntry
*assc_entry
;
7670 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7671 struct gcpro gcpro1
;
7673 GetPort (&port
); /* save the current font number used */
7674 old_fontnum
= port
->txFont
;
7676 text_encoding_info_alist
= create_text_encoding_info_alist ();
7678 GCPRO1 (text_encoding_info_alist
);
7680 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7682 font_handle
= GetIndResource ('FOND', i
);
7686 GetResInfo (font_handle
, &id
, &type
, name
);
7687 GetFNum (name
, &fontnum
);
7689 if (fontnum
== 0 || *name
== '.')
7693 scriptcode
= FontToScript (fontnum
);
7694 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7695 text_encoding_info_alist
);
7696 if (NILP (text_encoding_info
))
7697 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7698 text_encoding_info_alist
);
7699 decode_mac_font_name (name
, sizeof (name
),
7700 XCAR (XCDR (text_encoding_info
)));
7701 family
= build_string (name
);
7702 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7704 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7705 fm_font_family_alist
);
7708 HLock (font_handle
);
7710 if (GetResourceSizeOnDisk (font_handle
)
7711 >= sizeof (struct FamRec
))
7713 fat
= (struct FontAssoc
*) (*font_handle
7714 + sizeof (struct FamRec
));
7716 = (struct AsscEntry
*) (*font_handle
7717 + sizeof (struct FamRec
)
7718 + sizeof (struct FontAssoc
));
7720 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7722 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7724 for (; !NILP (rest
); rest
= XCDR (rest
))
7725 add_mac_font_name (name
, assc_entry
->fontSize
,
7726 assc_entry
->fontStyle
,
7727 SDATA (XCAR (rest
)));
7731 HUnlock (font_handle
);
7732 font_handle_2
= GetNextFOND (font_handle
);
7733 ReleaseResource (font_handle
);
7734 font_handle
= font_handle_2
;
7736 while (ResError () == noErr
&& font_handle
);
7741 TextFont (old_fontnum
);
7742 #endif /* !TARGET_API_MAC_CARBON */
7747 mac_clear_font_name_table ()
7751 for (i
= 0; i
< font_name_count
; i
++)
7752 xfree (font_name_table
[i
]);
7753 xfree (font_name_table
);
7754 font_name_table
= NULL
;
7755 font_name_table_size
= font_name_count
= 0;
7756 fm_font_family_alist
= Qnil
;
7760 enum xlfd_scalable_field_index
7762 XLFD_SCL_PIXEL_SIZE
,
7763 XLFD_SCL_POINT_SIZE
,
7768 static const int xlfd_scalable_fields
[] =
7777 mac_do_list_fonts (pattern
, maxnames
)
7778 const char *pattern
;
7782 Lisp_Object font_list
= Qnil
;
7783 struct xlfdpat
*pat
;
7786 int scl_val
[XLFD_SCL_LAST
], *val
;
7790 if (font_name_table
== NULL
) /* Initialize when first used. */
7791 init_font_name_table ();
7793 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7796 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7797 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7798 fonts are scaled according to the specified size. */
7801 field
= xlfd_scalable_fields
;
7809 if ('0' <= *ptr
&& *ptr
<= '9')
7811 *val
= *ptr
++ - '0';
7812 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7813 *val
= *val
* 10 + *ptr
++ - '0';
7820 ptr
= strchr (ptr
, '-');
7823 while (ptr
&& i
< 14);
7825 if (i
== 14 && ptr
== NULL
)
7827 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7828 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7829 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7830 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7832 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7833 scl_val
[XLFD_SCL_POINT_SIZE
] =
7834 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7835 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7837 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7838 scl_val
[XLFD_SCL_AVGWIDTH
] =
7839 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7840 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7844 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7846 pat
= xlfdpat_create (pattern
);
7850 exact
= xlfdpat_exact_p (pat
);
7852 for (i
= 0; i
< font_name_count
; i
++)
7854 if (xlfdpat_match (pat
, font_name_table
[i
]))
7856 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7857 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7860 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7861 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7863 int former_len
= ptr
- font_name_table
[i
];
7865 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7866 memcpy (scaled
, font_name_table
[i
], former_len
);
7867 sprintf (scaled
+ former_len
,
7868 "-%d-%d-72-72-m-%d-%s",
7869 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7870 scl_val
[XLFD_SCL_POINT_SIZE
],
7871 scl_val
[XLFD_SCL_AVGWIDTH
],
7872 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7874 if (xlfdpat_match (pat
, scaled
))
7876 font_list
= Fcons (build_string (scaled
), font_list
);
7878 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7886 xlfdpat_destroy (pat
);
7891 /* Return a list of names of available fonts matching PATTERN on frame F.
7893 Frame F null means we have not yet created any frame on Mac, and
7894 consult the first display in x_display_list. MAXNAMES sets a limit
7895 on how many fonts to match. */
7898 x_list_fonts (f
, pattern
, size
, maxnames
)
7900 Lisp_Object pattern
;
7903 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7904 struct mac_display_info
*dpyinfo
7905 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7907 xassert (size
<= 0);
7909 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7910 if (NILP (patterns
))
7911 patterns
= Fcons (pattern
, Qnil
);
7913 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7915 pattern
= XCAR (patterns
);
7917 if (!STRINGP (pattern
))
7920 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7921 key
= Fcons (pattern
, make_number (maxnames
));
7923 list
= Fassoc (key
, tem
);
7926 list
= Fcdr_safe (list
);
7927 /* We have a cashed list. Don't have to get the list again. */
7932 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7935 /* MAC_TODO: add code for matching outline fonts here */
7937 /* Now store the result in the cache. */
7938 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7939 Fcons (Fcons (key
, list
),
7940 XCAR (XCDR (dpyinfo
->name_list_element
))));
7943 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7952 /* Check that FONT is valid on frame F. It is if it can be found in F's
7956 x_check_font (f
, font
)
7961 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7963 xassert (font
!= NULL
);
7965 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7966 if (dpyinfo
->font_table
[i
].name
7967 && font
== dpyinfo
->font_table
[i
].font
)
7970 xassert (i
< dpyinfo
->n_fonts
);
7973 #endif /* GLYPH_DEBUG != 0 */
7975 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7976 Note: There are (broken) X fonts out there with invalid XFontStruct
7977 min_bounds contents. For example, handa@etl.go.jp reports that
7978 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7979 have font->min_bounds.width == 0. */
7982 x_font_min_bounds (font
, w
, h
)
7983 MacFontStruct
*font
;
7986 *h
= FONT_HEIGHT (font
);
7987 *w
= font
->min_bounds
.width
;
7991 /* Compute the smallest character width and smallest font height over
7992 all fonts available on frame F. Set the members smallest_char_width
7993 and smallest_font_height in F's x_display_info structure to
7994 the values computed. Value is non-zero if smallest_font_height or
7995 smallest_char_width become smaller than they were before. */
7998 x_compute_min_glyph_bounds (f
)
8002 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8003 MacFontStruct
*font
;
8004 int old_width
= dpyinfo
->smallest_char_width
;
8005 int old_height
= dpyinfo
->smallest_font_height
;
8007 dpyinfo
->smallest_font_height
= 100000;
8008 dpyinfo
->smallest_char_width
= 100000;
8010 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8011 if (dpyinfo
->font_table
[i
].name
)
8013 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8016 font
= (MacFontStruct
*) fontp
->font
;
8017 xassert (font
!= (MacFontStruct
*) ~0);
8018 x_font_min_bounds (font
, &w
, &h
);
8020 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8021 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8024 xassert (dpyinfo
->smallest_char_width
> 0
8025 && dpyinfo
->smallest_font_height
> 0);
8027 return (dpyinfo
->n_fonts
== 1
8028 || dpyinfo
->smallest_char_width
< old_width
8029 || dpyinfo
->smallest_font_height
< old_height
);
8033 /* Determine whether given string is a fully-specified XLFD: all 14
8034 fields are present, none is '*'. */
8037 is_fully_specified_xlfd (p
)
8046 for (i
= 0; i
< 13; i
++)
8048 q
= strchr (p
+ 1, '-');
8051 if (q
- p
== 2 && *(p
+ 1) == '*')
8056 if (strchr (p
+ 1, '-') != NULL
)
8059 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8066 /* mac_load_query_font creates and returns an internal representation
8067 for a font in a MacFontStruct struct. There is really no concept
8068 corresponding to "loading" a font on the Mac. But we check its
8069 existence and find the font number and all other information for it
8070 and store them in the returned MacFontStruct. */
8072 static MacFontStruct
*
8073 mac_load_query_font (f
, fontname
)
8083 static ATSUFontID font_id
;
8084 ATSUStyle mac_style
= NULL
;
8087 #if TARGET_API_MAC_CARBON
8088 TextEncoding encoding
;
8093 MacFontStruct
*font
;
8094 XCharStruct
*space_bounds
= NULL
, *pcm
;
8096 if (is_fully_specified_xlfd (fontname
))
8100 Lisp_Object matched_fonts
;
8102 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8103 if (NILP (matched_fonts
))
8105 name
= SDATA (XCAR (matched_fonts
));
8108 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8112 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8115 static const ATSUAttributeTag tags
[] =
8116 {kATSUFontTag
, kATSUSizeTag
,
8117 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8118 static const ByteCount sizes
[] =
8119 {sizeof (ATSUFontID
), sizeof (Fixed
),
8120 sizeof (Boolean
), sizeof (Boolean
)};
8121 static Fixed size_fixed
;
8122 static Boolean bold_p
, italic_p
;
8123 static const ATSUAttributeValuePtr values
[] =
8124 {&font_id
, &size_fixed
,
8125 &bold_p
, &italic_p
};
8126 static const ATSUFontFeatureType types
[] =
8127 {kAllTypographicFeaturesType
, kDiacriticsType
};
8128 static const ATSUFontFeatureSelector selectors
[] =
8129 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8132 font_id
= atsu_find_font_from_family_name (family
);
8133 if (font_id
== kATSUInvalidFontID
)
8135 size_fixed
= Long2Fix (size
);
8136 bold_p
= (fontface
& bold
) != 0;
8137 italic_p
= (fontface
& italic
) != 0;
8138 err
= ATSUCreateStyle (&mac_style
);
8141 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8145 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8146 tags
, sizes
, values
);
8149 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8152 scriptcode
= kTextEncodingMacUnicode
;
8157 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8161 fontnum
= XINT (XCDR (tmp
));
8162 #if TARGET_API_MAC_CARBON
8163 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8165 scriptcode
= GetTextEncodingBase (encoding
);
8167 scriptcode
= FontToScript (fontnum
);
8171 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8173 font
->mac_fontnum
= fontnum
;
8174 font
->mac_fontsize
= size
;
8175 font
->mac_fontface
= fontface
;
8176 font
->mac_scriptcode
= scriptcode
;
8178 font
->mac_style
= mac_style
;
8179 #if USE_CG_TEXT_DRAWING
8180 font
->cg_font
= NULL
;
8181 font
->cg_glyphs
= NULL
;
8185 /* Apple Japanese (SJIS) font is listed as both
8186 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8187 (Roman script) in init_font_name_table (). The latter should be
8188 treated as a one-byte font. */
8189 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8190 font
->mac_scriptcode
= smRoman
;
8192 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8195 if (font
->mac_style
)
8200 font
->min_byte1
= 0;
8201 font
->max_byte1
= 0xff;
8202 font
->min_char_or_byte2
= 0;
8203 font
->max_char_or_byte2
= 0xff;
8205 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8206 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8207 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8208 pcm_init (font
->bounds
.rows
[0], 0x100);
8210 #if USE_CG_TEXT_DRAWING
8214 ATSFontRef ats_font
;
8216 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8218 /* Use CG text drawing if italic/bold is not synthesized. */
8219 if (err
== noErr
&& style
== fontface
)
8221 ats_font
= FMGetATSFontRefFromFont (font_id
);
8222 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8228 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8229 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8232 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8233 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8234 &font
->ascent
, &font
->descent
,
8236 #if USE_CG_TEXT_DRAWING
8237 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8244 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8246 mac_unload_font (&one_mac_display_info
, font
);
8250 pcm
= font
->bounds
.rows
[0];
8251 for (c
= 0x21; c
<= 0xff; c
++)
8254 /* Soft hyphen is not supported in ATSUI. */
8258 #if USE_CG_TEXT_DRAWING
8259 if (font
->cg_glyphs
)
8269 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8270 pcm
? pcm
+ c
: NULL
,
8271 #if USE_CG_TEXT_DRAWING
8272 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8279 #if USE_CG_TEXT_DRAWING
8280 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8282 /* Don't use CG text drawing if font substitution occurs in
8283 ASCII or Latin-1 characters. */
8284 CGFontRelease (font
->cg_font
);
8285 font
->cg_font
= NULL
;
8286 xfree (font
->cg_glyphs
);
8287 font
->cg_glyphs
= NULL
;
8298 FontInfo the_fontinfo
;
8299 int is_two_byte_font
;
8302 mac_prepare_for_quickdraw (f
);
8304 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8308 TextFace (fontface
);
8310 GetFontInfo (&the_fontinfo
);
8312 font
->ascent
= the_fontinfo
.ascent
;
8313 font
->descent
= the_fontinfo
.descent
;
8315 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8316 || font
->mac_scriptcode
== smTradChinese
8317 || font
->mac_scriptcode
== smSimpChinese
8318 || font
->mac_scriptcode
== smKorean
);
8320 if (is_two_byte_font
)
8324 font
->min_byte1
= 0xa1;
8325 font
->max_byte1
= 0xfe;
8326 font
->min_char_or_byte2
= 0xa1;
8327 font
->max_char_or_byte2
= 0xfe;
8329 /* Use the width of an "ideographic space" of that font
8330 because the_fontinfo.widMax returns the wrong width for
8332 switch (font
->mac_scriptcode
)
8335 font
->min_byte1
= 0x81;
8336 font
->max_byte1
= 0xfc;
8337 font
->min_char_or_byte2
= 0x40;
8338 font
->max_char_or_byte2
= 0xfc;
8339 char_width
= StringWidth("\p\x81\x40");
8342 font
->min_char_or_byte2
= 0x40;
8343 char_width
= StringWidth("\p\xa1\x40");
8346 char_width
= StringWidth("\p\xa1\xa1");
8349 char_width
= StringWidth("\p\xa1\xa1");
8353 font
->bounds
.per_char
= NULL
;
8355 if (fontface
& italic
)
8356 font
->max_bounds
.rbearing
= char_width
+ 1;
8358 font
->max_bounds
.rbearing
= char_width
;
8359 font
->max_bounds
.lbearing
= 0;
8360 font
->max_bounds
.width
= char_width
;
8361 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8362 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8364 font
->min_bounds
= font
->max_bounds
;
8370 font
->min_byte1
= font
->max_byte1
= 0;
8371 font
->min_char_or_byte2
= 0x20;
8372 font
->max_char_or_byte2
= 0xff;
8374 font
->bounds
.per_char
=
8375 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8376 bzero (font
->bounds
.per_char
,
8377 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8379 space_bounds
= font
->bounds
.per_char
;
8380 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
8381 &font
->descent
, space_bounds
, NULL
);
8382 if (err
!= noErr
|| space_bounds
->width
<= 0)
8384 mac_unload_font (&one_mac_display_info
, font
);
8388 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8389 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8397 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8398 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8401 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8403 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8405 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8407 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8409 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
8412 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8414 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8416 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8418 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8420 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
8425 font
->mac_style
== NULL
&&
8427 font
->max_bounds
.width
== font
->min_bounds
.width
8428 && font
->min_bounds
.lbearing
>= 0
8429 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8431 /* Fixed width and no overhangs. */
8432 xfree (font
->bounds
.per_char
);
8433 font
->bounds
.per_char
= NULL
;
8437 #if !defined (MAC_OS8) || USE_ATSUI
8438 /* AppKit and WebKit do some adjustment to the heights of Courier,
8439 Helvetica, and Times. This only works on the environments where
8440 srcCopy text transfer mode is never used. */
8442 #ifdef MAC_OS8 /* implies USE_ATSUI */
8445 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8446 || strcmp (family
, "times") == 0))
8447 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8455 mac_unload_font (dpyinfo
, font
)
8456 struct mac_display_info
*dpyinfo
;
8459 xfree (font
->full_name
);
8461 if (font
->mac_style
)
8465 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8466 if (font
->bounds
.rows
[i
])
8467 xfree (font
->bounds
.rows
[i
]);
8468 xfree (font
->bounds
.rows
);
8469 ATSUDisposeStyle (font
->mac_style
);
8473 if (font
->bounds
.per_char
)
8474 xfree (font
->bounds
.per_char
);
8475 #if USE_CG_TEXT_DRAWING
8477 CGFontRelease (font
->cg_font
);
8478 if (font
->cg_glyphs
)
8479 xfree (font
->cg_glyphs
);
8485 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8486 pointer to the structure font_info while allocating it dynamically.
8487 If SIZE is 0, load any size of font.
8488 If loading is failed, return NULL. */
8491 x_load_font (f
, fontname
, size
)
8493 register char *fontname
;
8496 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8497 Lisp_Object font_names
;
8499 /* Get a list of all the fonts that match this name. Once we
8500 have a list of matching fonts, we compare them against the fonts
8501 we already have by comparing names. */
8502 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8504 if (!NILP (font_names
))
8509 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8510 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8511 if (dpyinfo
->font_table
[i
].name
8512 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8513 SDATA (XCAR (tail
)))
8514 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8515 SDATA (XCAR (tail
)))))
8516 return (dpyinfo
->font_table
+ i
);
8521 /* Load the font and add it to the table. */
8523 struct MacFontStruct
*font
;
8524 struct font_info
*fontp
;
8527 fontname
= (char *) SDATA (XCAR (font_names
));
8530 font
= mac_load_query_font (f
, fontname
);
8535 /* Find a free slot in the font table. */
8536 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8537 if (dpyinfo
->font_table
[i
].name
== NULL
)
8540 /* If no free slot found, maybe enlarge the font table. */
8541 if (i
== dpyinfo
->n_fonts
8542 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8545 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8546 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8548 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8551 fontp
= dpyinfo
->font_table
+ i
;
8552 if (i
== dpyinfo
->n_fonts
)
8555 /* Now fill in the slots of *FONTP. */
8557 bzero (fontp
, sizeof (*fontp
));
8559 fontp
->font_idx
= i
;
8560 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8561 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8563 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8565 /* Fixed width font. */
8566 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8573 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8574 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8576 fontp
->space_width
= pcm
->width
;
8578 fontp
->space_width
= FONT_WIDTH (font
);
8582 int width
= pcm
->width
;
8583 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8584 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8585 width
+= pcm
->width
;
8586 fontp
->average_width
= width
/ 95;
8589 fontp
->average_width
= FONT_WIDTH (font
);
8592 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8593 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8595 fontp
->size
= font
->max_bounds
.width
;
8596 fontp
->height
= FONT_HEIGHT (font
);
8598 /* For some font, ascent and descent in max_bounds field is
8599 larger than the above value. */
8600 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8601 if (max_height
> fontp
->height
)
8602 fontp
->height
= max_height
;
8605 /* The slot `encoding' specifies how to map a character
8606 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8607 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8608 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8609 2:0xA020..0xFF7F). For the moment, we don't know which charset
8610 uses this font. So, we set information in fontp->encoding[1]
8611 which is never used by any charset. If mapping can't be
8612 decided, set FONT_ENCODING_NOT_DECIDED. */
8613 if (font
->mac_scriptcode
== smJapanese
)
8614 fontp
->encoding
[1] = 4;
8618 = (font
->max_byte1
== 0
8620 ? (font
->min_char_or_byte2
< 0x80
8621 ? (font
->max_char_or_byte2
< 0x80
8622 ? 0 /* 0x20..0x7F */
8623 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8624 : 1) /* 0xA0..0xFF */
8626 : (font
->min_byte1
< 0x80
8627 ? (font
->max_byte1
< 0x80
8628 ? (font
->min_char_or_byte2
< 0x80
8629 ? (font
->max_char_or_byte2
< 0x80
8630 ? 0 /* 0x2020..0x7F7F */
8631 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8632 : 3) /* 0x20A0..0x7FFF */
8633 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8634 : (font
->min_char_or_byte2
< 0x80
8635 ? (font
->max_char_or_byte2
< 0x80
8636 ? 2 /* 0xA020..0xFF7F */
8637 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8638 : 1))); /* 0xA0A0..0xFFFF */
8641 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8642 fontp
->baseline_offset
8643 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8644 ? (long) value
: 0);
8645 fontp
->relative_compose
8646 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8647 ? (long) value
: 0);
8648 fontp
->default_ascent
8649 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8650 ? (long) value
: 0);
8652 fontp
->baseline_offset
= 0;
8653 fontp
->relative_compose
= 0;
8654 fontp
->default_ascent
= 0;
8657 /* Set global flag fonts_changed_p to non-zero if the font loaded
8658 has a character with a smaller width than any other character
8659 before, or if the font loaded has a smaller height than any
8660 other font loaded before. If this happens, it will make a
8661 glyph matrix reallocation necessary. */
8662 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8669 /* Return a pointer to struct font_info of a font named FONTNAME for
8670 frame F. If no such font is loaded, return NULL. */
8673 x_query_font (f
, fontname
)
8675 register char *fontname
;
8677 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8680 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8681 if (dpyinfo
->font_table
[i
].name
8682 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8683 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8684 return (dpyinfo
->font_table
+ i
);
8689 /* Find a CCL program for a font specified by FONTP, and set the member
8690 `encoder' of the structure. */
8693 x_find_ccl_program (fontp
)
8694 struct font_info
*fontp
;
8696 Lisp_Object list
, elt
;
8698 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8702 && STRINGP (XCAR (elt
))
8703 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8709 struct ccl_program
*ccl
8710 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8712 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8715 fontp
->font_encoder
= ccl
;
8719 #if USE_MAC_FONT_PANEL
8720 /* Whether Font Panel has been shown before. The first call to font
8721 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8722 slow. This variable is used for deferring such a call as much as
8724 static int font_panel_shown_p
= 0;
8727 mac_font_panel_visible_p ()
8729 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8733 mac_show_hide_font_panel ()
8735 font_panel_shown_p
= 1;
8737 return FPShowHideFontPanel ();
8741 mac_set_font_info_for_selection (f
, face_id
, c
)
8746 EventTargetRef target
= NULL
;
8747 XFontStruct
*font
= NULL
;
8749 if (!mac_font_panel_visible_p ())
8754 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8756 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8760 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8761 face
= FACE_FROM_ID (f
, face_id
);
8767 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8770 if (font
->mac_fontnum
!= -1)
8772 FontSelectionQDStyle qd_style
;
8774 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8775 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8776 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8777 qd_style
.size
= font
->mac_fontsize
;
8778 qd_style
.hasColor
= false;
8780 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8781 1, &qd_style
, target
);
8784 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8785 1, &font
->mac_style
, target
);
8793 /* The Mac Event loop code */
8795 #if !TARGET_API_MAC_CARBON
8797 #include <Quickdraw.h>
8798 #include <Balloons.h>
8799 #include <Devices.h>
8801 #include <Gestalt.h>
8803 #include <Processes.h>
8805 #include <ToolUtils.h>
8806 #include <TextUtils.h>
8807 #include <Dialogs.h>
8810 #include <Resources.h>
8815 #endif /* ! TARGET_API_MAC_CARBON */
8820 #define DEFAULT_NUM_COLS 80
8822 #define MIN_DOC_SIZE 64
8823 #define MAX_DOC_SIZE 32767
8825 #define EXTRA_STACK_ALLOC (256 * 1024)
8827 #define ARGV_STRING_LIST_ID 129
8828 #define ABOUT_ALERT_ID 128
8829 #define RAM_TOO_LARGE_ALERT_ID 129
8831 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8832 Lisp_Object Qreverse
;
8835 /* Modifier associated with the control key, or nil to ignore. */
8836 Lisp_Object Vmac_control_modifier
;
8838 /* Modifier associated with the option key, or nil to ignore. */
8839 Lisp_Object Vmac_option_modifier
;
8841 /* Modifier associated with the command key, or nil to ignore. */
8842 Lisp_Object Vmac_command_modifier
;
8844 /* Modifier associated with the function key, or nil to ignore. */
8845 Lisp_Object Vmac_function_modifier
;
8847 /* True if the option and command modifiers should be used to emulate
8848 a three button mouse */
8849 Lisp_Object Vmac_emulate_three_button_mouse
;
8851 #if USE_CARBON_EVENTS
8852 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8853 mouse-2, instead of mouse-3. */
8854 int mac_wheel_button_is_mouse_2
;
8856 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8857 for processing before Emacs sees it. */
8858 int mac_pass_command_to_system
;
8860 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8861 for processing before Emacs sees it. */
8862 int mac_pass_control_to_system
;
8865 /* Points to the variable `inev' in the function XTread_socket. It is
8866 used for passing an input event to the function back from
8867 Carbon/Apple event handlers. */
8868 static struct input_event
*read_socket_inev
= NULL
;
8870 /* Whether or not the screen configuration has changed. */
8871 static int mac_screen_config_changed
= 0;
8873 Point saved_menu_event_location
;
8876 #if USE_CARBON_EVENTS
8877 static Lisp_Object Qhi_command
;
8879 extern Lisp_Object Qwindow
;
8880 static Lisp_Object Qtoolbar_switch_mode
;
8882 #if USE_MAC_FONT_PANEL
8883 extern Lisp_Object Qfont
;
8884 static Lisp_Object Qpanel_closed
, Qselection
;
8887 static TSMDocumentID tsm_document_id
;
8888 static Lisp_Object Qtext_input
;
8889 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8890 static Lisp_Object Vmac_ts_active_input_overlay
;
8891 extern Lisp_Object Qbefore_string
;
8892 static Lisp_Object Vmac_ts_script_language_on_focus
;
8893 static Lisp_Object saved_ts_script_language_on_focus
;
8894 static ScriptLanguageRecord saved_ts_language
;
8895 static Component saved_ts_component
;
8898 extern int mac_ready_for_apple_events
;
8899 extern Lisp_Object Qundefined
;
8900 extern void init_apple_event_handler
P_ ((void));
8901 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8902 Lisp_Object
*, Lisp_Object
*,
8904 extern OSErr init_coercion_handler
P_ ((void));
8907 extern OSErr install_drag_handler
P_ ((WindowRef
));
8908 extern void remove_drag_handler
P_ ((WindowRef
));
8910 /* Showing help echo string during menu tracking */
8911 extern OSStatus install_menu_target_item_handler
P_ ((WindowPtr
));
8913 #if USE_CARBON_EVENTS
8915 extern void init_service_handler ();
8916 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8919 /* Window Event Handler */
8920 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8923 OSStatus
install_window_handler (WindowPtr
);
8925 extern void init_emacs_passwd_dir ();
8926 extern int emacs_main (int, char **, char **);
8928 extern void initialize_applescript();
8929 extern void terminate_applescript();
8931 /* Table for translating Mac keycode to X keysym values. Contributed
8933 Mapping for special keys is now identical to that in Apple X11
8934 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8935 on the right of the Cmd key on laptops, and fn + `enter' (->
8937 static const unsigned char keycode_to_xkeysym_table
[] = {
8938 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8939 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8940 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8942 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8943 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8944 /*0x38*/ 0, 0, 0, 0,
8945 /*0x3C*/ 0, 0, 0, 0,
8947 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8948 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8949 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8950 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8952 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8953 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8954 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8955 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8957 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8958 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8959 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8960 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8962 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8963 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8964 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8965 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8969 /* Table for translating Mac keycode with the laptop `fn' key to that
8970 without it. Destination symbols in comments are keys on US
8971 keyboard, and they may not be the same on other types of keyboards.
8972 If the destination is identical to the source (f1 ... f12), it
8973 doesn't map `fn' key to a modifier. */
8974 static const unsigned char fn_keycode_to_keycode_table
[] = {
8975 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8976 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8977 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8979 /*0x30*/ 0, 0, 0, 0,
8980 /*0x34*/ 0, 0, 0, 0,
8981 /*0x38*/ 0, 0, 0, 0,
8982 /*0x3C*/ 0, 0, 0, 0,
8984 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8985 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8986 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8987 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8989 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8990 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8991 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8992 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8994 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8995 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8996 /*0x68*/ 0, 0, 0, 0,
8997 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8999 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9000 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9001 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9004 #endif /* MAC_OSX */
9007 #if USE_CARBON_EVENTS
9008 mac_to_emacs_modifiers (UInt32 mods
)
9010 mac_to_emacs_modifiers (EventModifiers mods
)
9013 unsigned int result
= 0;
9014 if (mods
& shiftKey
)
9015 result
|= shift_modifier
;
9017 /* Deactivated to simplify configuration:
9018 if Vmac_option_modifier is non-NIL, we fully process the Option
9019 key. Otherwise, we only process it if an additional Ctrl or Command
9020 is pressed. That way the system may convert the character to a
9022 if ((mods & optionKey) &&
9023 (( !NILP(Vmac_option_modifier) ||
9024 ((mods & cmdKey) || (mods & controlKey))))) */
9026 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9027 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9029 result
|= XUINT(val
);
9031 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9032 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9034 result
|= XUINT(val
);
9036 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9037 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9039 result
|= XUINT(val
);
9043 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9044 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9046 result
|= XUINT(val
);
9054 mac_mapped_modifiers (modifiers
)
9057 UInt32 mapped_modifiers_all
=
9058 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9059 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9060 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9063 mapped_modifiers_all
|=
9064 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9067 return mapped_modifiers_all
& modifiers
;
9071 mac_get_emulated_btn ( UInt32 modifiers
)
9074 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9075 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9076 if (modifiers
& cmdKey
)
9077 result
= cmdIs3
? 2 : 1;
9078 else if (modifiers
& optionKey
)
9079 result
= cmdIs3
? 1 : 2;
9084 #if TARGET_API_MAC_CARBON
9085 /***** Code to handle C-g testing *****/
9086 extern int quit_char
;
9087 extern int make_ctrl_char
P_ ((int));
9090 mac_quit_char_key_p (modifiers
, key_code
)
9091 UInt32 modifiers
, key_code
;
9094 unsigned long some_state
= 0;
9095 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9096 int c
, emacs_modifiers
;
9098 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9099 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9100 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9101 if (char_code
& ~0xff)
9104 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9105 if (emacs_modifiers
& ctrl_modifier
)
9106 c
= make_ctrl_char (char_code
);
9108 c
|= (emacs_modifiers
9109 & (meta_modifier
| alt_modifier
9110 | hyper_modifier
| super_modifier
));
9112 return c
== quit_char
;
9116 #if USE_CARBON_EVENTS
9117 /* Obtains the event modifiers from the event ref and then calls
9118 mac_to_emacs_modifiers. */
9120 mac_event_to_emacs_modifiers (EventRef eventRef
)
9123 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9124 sizeof (UInt32
), NULL
, &mods
);
9125 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9126 GetEventClass(eventRef
) == kEventClassMouse
)
9128 mods
&= ~(optionKey
| cmdKey
);
9130 return mac_to_emacs_modifiers (mods
);
9133 /* Given an event ref, return the code to use for the mouse button
9134 code in the emacs input_event. */
9136 mac_get_mouse_btn (EventRef ref
)
9138 EventMouseButton result
= kEventMouseButtonPrimary
;
9139 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9140 sizeof (EventMouseButton
), NULL
, &result
);
9143 case kEventMouseButtonPrimary
:
9144 if (NILP (Vmac_emulate_three_button_mouse
))
9148 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9149 sizeof (UInt32
), NULL
, &mods
);
9150 return mac_get_emulated_btn(mods
);
9152 case kEventMouseButtonSecondary
:
9153 return mac_wheel_button_is_mouse_2
? 2 : 1;
9154 case kEventMouseButtonTertiary
:
9155 case 4: /* 4 is the number for the mouse wheel button */
9156 return mac_wheel_button_is_mouse_2
? 1 : 2;
9162 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9163 events. However the click of the mouse wheel is not converted to a
9164 mouseDown or mouseUp event. Likewise for dead key events. This
9165 calls ConvertEventRefToEventRecord, but then checks to see if it is
9166 a mouse up/down, or a dead key Carbon event that has not been
9167 converted, and if so, converts it by hand (to be picked up in the
9168 XTread_socket loop). */
9169 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9172 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9178 switch (GetEventClass (eventRef
))
9180 case kEventClassMouse
:
9181 switch (GetEventKind (eventRef
))
9183 case kEventMouseDown
:
9184 eventRec
->what
= mouseDown
;
9189 eventRec
->what
= mouseUp
;
9198 case kEventClassKeyboard
:
9199 switch (GetEventKind (eventRef
))
9201 case kEventRawKeyDown
:
9203 goto keystroke_common
;
9204 case kEventRawKeyRepeat
:
9206 goto keystroke_common
;
9207 case kEventRawKeyUp
:
9211 unsigned char char_codes
;
9214 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9215 typeChar
, NULL
, sizeof (char),
9218 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9219 typeUInt32
, NULL
, sizeof (UInt32
),
9223 eventRec
->what
= action
;
9224 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9241 /* Need where and when. */
9244 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9245 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9246 /* Use two step process because new event modifiers are 32-bit
9247 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9248 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9249 NULL
, sizeof (UInt32
), NULL
, &mods
);
9250 eventRec
->modifiers
= mods
;
9252 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9264 Handle menubar_handle
;
9265 MenuHandle menu_handle
;
9267 menubar_handle
= GetNewMBar (128);
9268 if(menubar_handle
== NULL
)
9270 SetMenuBar (menubar_handle
);
9273 #if !TARGET_API_MAC_CARBON
9274 menu_handle
= GetMenuHandle (M_APPLE
);
9275 if(menu_handle
!= NULL
)
9276 AppendResMenu (menu_handle
,'DRVR');
9284 do_init_managers (void)
9286 #if !TARGET_API_MAC_CARBON
9287 InitGraf (&qd
.thePort
);
9289 FlushEvents (everyEvent
, 0);
9294 #endif /* !TARGET_API_MAC_CARBON */
9297 #if !TARGET_API_MAC_CARBON
9298 /* set up some extra stack space for use by emacs */
9299 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9301 /* MaxApplZone must be called for AppleScript to execute more
9302 complicated scripts */
9305 #endif /* !TARGET_API_MAC_CARBON */
9309 do_check_ram_size (void)
9311 SInt32 physical_ram_size
, logical_ram_size
;
9313 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
9314 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
9315 || physical_ram_size
> (1 << VALBITS
)
9316 || logical_ram_size
> (1 << VALBITS
))
9318 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
9322 #endif /* MAC_OS8 */
9325 do_window_update (WindowPtr win
)
9327 struct frame
*f
= mac_window_to_frame (win
);
9331 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
9333 if (win
!= tip_window
)
9335 if (f
->async_visible
== 0)
9337 /* Update events may occur when a frame gets iconified. */
9339 f
->async_visible
= 1;
9340 f
->async_iconified
= 0;
9341 SET_FRAME_GARBAGED (f
);
9347 #if TARGET_API_MAC_CARBON
9348 RgnHandle region
= NewRgn ();
9350 GetPortVisibleRegion (GetWindowPort (win
), region
);
9351 GetRegionBounds (region
, &r
);
9352 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9354 mac_prepare_for_quickdraw (f
);
9356 UpdateControls (win
, region
);
9357 DisposeRgn (region
);
9359 r
= (*win
->visRgn
)->rgnBBox
;
9360 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9361 UpdateControls (win
, win
->visRgn
);
9370 is_emacs_window (WindowPtr win
)
9372 Lisp_Object tail
, frame
;
9377 FOR_EACH_FRAME (tail
, frame
)
9378 if (FRAME_MAC_P (XFRAME (frame
)))
9379 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9390 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9392 err
= ActivateTSMDocument (tsm_document_id
);
9396 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9397 && EQ (saved_ts_script_language_on_focus
, Qt
))
9398 slptr
= &saved_ts_language
;
9399 else if (CONSP (Vmac_ts_script_language_on_focus
)
9400 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9401 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9402 && CONSP (saved_ts_script_language_on_focus
)
9403 && EQ (XCAR (saved_ts_script_language_on_focus
),
9404 XCAR (Vmac_ts_script_language_on_focus
))
9405 && EQ (XCDR (saved_ts_script_language_on_focus
),
9406 XCDR (Vmac_ts_script_language_on_focus
)))
9408 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9409 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9416 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9417 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
9418 kKeyboardInputMethodClass
);
9420 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
9423 err
= SetTextServiceLanguage (slptr
);
9425 /* Seems to be needed on Mac OS X 10.2. */
9427 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
9437 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9439 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
9441 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
9443 err
= GetTextServiceLanguage (&saved_ts_language
);
9445 slptr
= &saved_ts_language
;
9447 else if (CONSP (Vmac_ts_script_language_on_focus
)
9448 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9449 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
9451 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9452 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9458 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9459 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
9460 kKeyboardInputMethodClass
);
9462 GetDefaultInputMethod (&saved_ts_component
, slptr
);
9466 err
= DeactivateTSMDocument (tsm_document_id
);
9472 #if !TARGET_API_MAC_CARBON
9474 do_apple_menu (SInt16 menu_item
)
9477 SInt16 da_driver_refnum
;
9479 if (menu_item
== I_ABOUT
)
9480 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9483 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9484 da_driver_refnum
= OpenDeskAcc (item_name
);
9487 #endif /* !TARGET_API_MAC_CARBON */
9489 /* Handle drags in size box. Based on code contributed by Ben
9490 Mesander and IM - Window Manager A. */
9493 do_grow_window (w
, e
)
9495 const EventRecord
*e
;
9498 int rows
, columns
, width
, height
;
9499 struct frame
*f
= mac_window_to_frame (w
);
9500 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
9501 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
9502 #if TARGET_API_MAC_CARBON
9508 if (size_hints
->flags
& PMinSize
)
9510 min_width
= size_hints
->min_width
;
9511 min_height
= size_hints
->min_height
;
9513 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9515 #if TARGET_API_MAC_CARBON
9516 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
9518 height
= new_rect
.bottom
- new_rect
.top
;
9519 width
= new_rect
.right
- new_rect
.left
;
9521 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9522 /* see if it really changed size */
9525 height
= HiWord (grow_size
);
9526 width
= LoWord (grow_size
);
9529 if (width
!= FRAME_PIXEL_WIDTH (f
)
9530 || height
!= FRAME_PIXEL_HEIGHT (f
))
9532 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9533 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9535 x_set_window_size (f
, 0, columns
, rows
);
9540 #if TARGET_API_MAC_CARBON
9542 mac_get_ideal_size (f
)
9545 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9546 WindowPtr w
= FRAME_MAC_WINDOW (f
);
9549 int height
, width
, columns
, rows
;
9551 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9552 ideal_size
.v
= dpyinfo
->height
;
9553 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
9554 /* Adjust the standard size according to character boundaries. */
9555 width
= standard_rect
.right
- standard_rect
.left
;
9556 height
= standard_rect
.bottom
- standard_rect
.top
;
9557 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9558 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9559 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9560 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9566 /* Handle clicks in zoom box. Calculation of "standard state" based
9567 on code in IM - Window Manager A and code contributed by Ben
9568 Mesander. The standard state of an Emacs window is 80-characters
9569 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9572 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9574 Rect zoom_rect
, port_rect
;
9576 struct frame
*f
= mac_window_to_frame (w
);
9577 #if TARGET_API_MAC_CARBON
9578 Point ideal_size
= mac_get_ideal_size (f
);
9580 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9581 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
9582 && port_rect
.left
== zoom_rect
.left
9583 && port_rect
.top
== zoom_rect
.top
)
9584 zoom_in_or_out
= inZoomIn
;
9586 zoom_in_or_out
= inZoomOut
;
9589 mac_clear_window (f
);
9591 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
9592 #else /* not TARGET_API_MAC_CARBON */
9595 int w_title_height
, rows
;
9596 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9598 GetPort (&save_port
);
9600 SetPortWindowPort (w
);
9602 /* Clear window to avoid flicker. */
9603 EraseRect (&(w
->portRect
));
9604 if (zoom_in_or_out
== inZoomOut
)
9606 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9607 LocalToGlobal (&top_left
);
9609 /* calculate height of window's title bar */
9610 w_title_height
= top_left
.v
- 1
9611 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9613 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9614 zoom_rect
= qd
.screenBits
.bounds
;
9615 zoom_rect
.top
+= w_title_height
;
9616 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9618 zoom_rect
.right
= zoom_rect
.left
9619 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9621 /* Adjust the standard size according to character boundaries. */
9622 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9624 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9626 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9630 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9632 SetPort (save_port
);
9633 #endif /* not TARGET_API_MAC_CARBON */
9635 #if !USE_CARBON_EVENTS
9636 /* retrieve window size and update application values */
9637 #if TARGET_API_MAC_CARBON
9638 GetWindowPortBounds (w
, &port_rect
);
9640 port_rect
= w
->portRect
;
9642 height
= port_rect
.bottom
- port_rect
.top
;
9643 width
= port_rect
.right
- port_rect
.left
;
9645 mac_handle_size_change (f
, width
, height
);
9646 mac_handle_origin_change (f
);
9651 mac_store_apple_event (class, id
, desc
)
9652 Lisp_Object
class, id
;
9655 struct input_event buf
;
9659 buf
.kind
= MAC_APPLE_EVENT
;
9662 XSETFRAME (buf
.frame_or_window
,
9663 mac_focus_frame (&one_mac_display_info
));
9664 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9665 is safe to use them during read_socket_hook. */
9666 buf
.arg
= mac_aedesc_to_lisp (desc
);
9667 kbd_buffer_store_event (&buf
);
9670 #if TARGET_API_MAC_CARBON
9672 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9673 event
, num_params
, names
, types
)
9676 Lisp_Object class_key
, id_key
;
9679 const EventParamName
*names
;
9680 const EventParamType
*types
;
9682 OSStatus err
= eventNotHandledErr
;
9683 Lisp_Object binding
;
9685 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9686 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9688 if (INTEGERP (binding
))
9689 err
= XINT (binding
);
9692 AppleEvent apple_event
;
9693 err
= create_apple_event_from_event_ref (event
, num_params
,
9698 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9699 AEDisposeDesc (&apple_event
);
9700 mac_wakeup_from_rne ();
9709 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9715 struct input_event buf
;
9719 buf
.kind
= DRAG_N_DROP_EVENT
;
9720 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9721 buf
.timestamp
= TickCount () * (1000 / 60);
9722 XSETINT (buf
.x
, mouse_pos
.h
);
9723 XSETINT (buf
.y
, mouse_pos
.v
);
9724 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9725 buf
.arg
= mac_aedesc_to_lisp (desc
);
9726 kbd_buffer_store_event (&buf
);
9730 #if USE_CARBON_EVENTS
9731 static pascal OSStatus
9732 mac_handle_command_event (next_handler
, event
, data
)
9733 EventHandlerCallRef next_handler
;
9737 OSStatus result
, err
;
9739 static const EventParamName names
[] =
9740 {kEventParamDirectObject
, kEventParamKeyModifiers
};
9741 static const EventParamType types
[] =
9742 {typeHICommand
, typeUInt32
};
9743 int num_params
= sizeof (names
) / sizeof (names
[0]);
9745 result
= CallNextEventHandler (next_handler
, event
);
9746 if (result
!= eventNotHandledErr
)
9749 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9750 NULL
, sizeof (HICommand
), NULL
, &command
);
9752 if (err
!= noErr
|| command
.commandID
== 0)
9753 return eventNotHandledErr
;
9755 /* A HI command event is mapped to an Apple event whose event class
9756 symbol is `hi-command' and event ID is its command ID. */
9757 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9759 event
, num_params
, names
, types
);
9760 return err
== noErr
? noErr
: eventNotHandledErr
;
9764 init_command_handler ()
9766 static const EventTypeSpec specs
[] =
9767 {{kEventClassCommand
, kEventCommandProcess
}};
9768 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9770 if (handle_command_eventUPP
== NULL
)
9771 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9772 return InstallApplicationEventHandler (handle_command_eventUPP
,
9773 GetEventTypeCount (specs
), specs
,
9777 static pascal OSStatus
9778 mac_handle_window_event (next_handler
, event
, data
)
9779 EventHandlerCallRef next_handler
;
9784 OSStatus result
, err
;
9787 XSizeHints
*size_hints
;
9789 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9790 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9792 return eventNotHandledErr
;
9794 f
= mac_window_to_frame (wp
);
9795 switch (GetEventKind (event
))
9797 case kEventWindowUpdate
:
9798 result
= CallNextEventHandler (next_handler
, event
);
9799 if (result
!= eventNotHandledErr
)
9802 do_window_update (wp
);
9805 case kEventWindowGetIdealSize
:
9806 result
= CallNextEventHandler (next_handler
, event
);
9807 if (result
!= eventNotHandledErr
)
9811 Point ideal_size
= mac_get_ideal_size (f
);
9813 err
= SetEventParameter (event
, kEventParamDimensions
,
9814 typeQDPoint
, sizeof (Point
), &ideal_size
);
9820 case kEventWindowBoundsChanging
:
9821 result
= CallNextEventHandler (next_handler
, event
);
9822 if (result
!= eventNotHandledErr
)
9825 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9826 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9830 size_hints
= FRAME_SIZE_HINTS (f
);
9831 if ((attributes
& kWindowBoundsChangeUserResize
)
9832 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9833 == (PResizeInc
| PBaseSize
| PMinSize
)))
9838 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9839 typeQDRectangle
, NULL
, sizeof (Rect
),
9844 width
= bounds
.right
- bounds
.left
;
9845 height
= bounds
.bottom
- bounds
.top
;
9847 if (width
< size_hints
->min_width
)
9848 width
= size_hints
->min_width
;
9850 width
= size_hints
->base_width
9851 + (int) ((width
- size_hints
->base_width
)
9852 / (float) size_hints
->width_inc
+ .5)
9853 * size_hints
->width_inc
;
9855 if (height
< size_hints
->min_height
)
9856 height
= size_hints
->min_height
;
9858 height
= size_hints
->base_height
9859 + (int) ((height
- size_hints
->base_height
)
9860 / (float) size_hints
->height_inc
+ .5)
9861 * size_hints
->height_inc
;
9863 bounds
.right
= bounds
.left
+ width
;
9864 bounds
.bottom
= bounds
.top
+ height
;
9865 SetEventParameter (event
, kEventParamCurrentBounds
,
9866 typeQDRectangle
, sizeof (Rect
), &bounds
);
9871 case kEventWindowBoundsChanged
:
9872 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9873 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9877 if (attributes
& kWindowBoundsChangeSizeChanged
)
9881 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9882 typeQDRectangle
, NULL
, sizeof (Rect
),
9888 width
= bounds
.right
- bounds
.left
;
9889 height
= bounds
.bottom
- bounds
.top
;
9890 mac_handle_size_change (f
, width
, height
);
9891 mac_wakeup_from_rne ();
9895 if (attributes
& kWindowBoundsChangeOriginChanged
)
9896 mac_handle_origin_change (f
);
9900 case kEventWindowShown
:
9901 case kEventWindowHidden
:
9902 case kEventWindowExpanded
:
9903 case kEventWindowCollapsed
:
9904 result
= CallNextEventHandler (next_handler
, event
);
9906 mac_handle_visibility_change (f
);
9911 case kEventWindowClose
:
9912 result
= CallNextEventHandler (next_handler
, event
);
9914 struct input_event buf
;
9917 buf
.kind
= DELETE_WINDOW_EVENT
;
9918 XSETFRAME (buf
.frame_or_window
, f
);
9920 kbd_buffer_store_event (&buf
);
9925 case kEventWindowToolbarSwitchMode
:
9926 result
= CallNextEventHandler (next_handler
, event
);
9928 static const EventParamName names
[] = {kEventParamDirectObject
,
9929 kEventParamWindowMouseLocation
,
9930 kEventParamKeyModifiers
,
9931 kEventParamMouseButton
,
9932 kEventParamClickCount
,
9933 kEventParamMouseChord
};
9934 static const EventParamType types
[] = {typeWindowRef
,
9940 int num_params
= sizeof (names
) / sizeof (names
[0]);
9942 err
= mac_store_event_ref_as_apple_event (0, 0,
9944 Qtoolbar_switch_mode
,
9948 return err
== noErr
? noErr
: result
;
9952 case kEventWindowFocusAcquired
:
9953 result
= CallNextEventHandler (next_handler
, event
);
9954 err
= mac_tsm_resume ();
9955 return err
== noErr
? noErr
: result
;
9957 case kEventWindowFocusRelinquish
:
9958 result
= CallNextEventHandler (next_handler
, event
);
9959 err
= mac_tsm_suspend ();
9960 return err
== noErr
? noErr
: result
;
9964 return eventNotHandledErr
;
9967 static pascal OSStatus
9968 mac_handle_mouse_event (next_handler
, event
, data
)
9969 EventHandlerCallRef next_handler
;
9973 OSStatus result
, err
;
9975 switch (GetEventKind (event
))
9977 case kEventMouseWheelMoved
:
9981 EventMouseWheelAxis axis
;
9985 result
= CallNextEventHandler (next_handler
, event
);
9986 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9989 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9990 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9994 f
= mac_window_to_frame (wp
);
9995 if (f
!= mac_focus_frame (&one_mac_display_info
))
9998 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
9999 typeMouseWheelAxis
, NULL
,
10000 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
10001 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
10004 err
= GetEventParameter (event
, kEventParamMouseLocation
,
10005 typeQDPoint
, NULL
, sizeof (Point
),
10010 SetPortWindowPort (wp
);
10011 GlobalToLocal (&point
);
10012 if (point
.h
< 0 || point
.v
< 0
10013 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
10014 f
->tool_bar_window
))
10017 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
10018 typeSInt32
, NULL
, sizeof (SInt32
),
10023 read_socket_inev
->kind
= WHEEL_EVENT
;
10024 read_socket_inev
->code
= 0;
10025 read_socket_inev
->modifiers
=
10026 (mac_event_to_emacs_modifiers (event
)
10027 | ((delta
< 0) ? down_modifier
: up_modifier
));
10028 XSETINT (read_socket_inev
->x
, point
.h
);
10029 XSETINT (read_socket_inev
->y
, point
.v
);
10030 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10040 return eventNotHandledErr
;
10043 #if USE_MAC_FONT_PANEL
10044 static pascal OSStatus
10045 mac_handle_font_event (next_handler
, event
, data
)
10046 EventHandlerCallRef next_handler
;
10050 OSStatus result
, err
;
10051 Lisp_Object id_key
;
10053 const EventParamName
*names
;
10054 const EventParamType
*types
;
10055 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
10056 kEventParamATSUFontSize
,
10057 kEventParamFMFontFamily
,
10058 kEventParamFMFontSize
,
10059 kEventParamFontColor
};
10060 static const EventParamType types_sel
[] = {typeATSUFontID
,
10066 result
= CallNextEventHandler (next_handler
, event
);
10067 if (result
!= eventNotHandledErr
)
10070 switch (GetEventKind (event
))
10072 case kEventFontPanelClosed
:
10073 id_key
= Qpanel_closed
;
10079 case kEventFontSelection
:
10080 id_key
= Qselection
;
10081 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
10087 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
10091 return err
== noErr
? noErr
: eventNotHandledErr
;
10096 static pascal OSStatus
10097 mac_handle_text_input_event (next_handler
, event
, data
)
10098 EventHandlerCallRef next_handler
;
10102 OSStatus result
, err
= noErr
;
10103 Lisp_Object id_key
= Qnil
;
10105 const EventParamName
*names
;
10106 const EventParamType
*types
;
10107 static UInt32 seqno_uaia
= 0;
10108 static const EventParamName names_uaia
[] =
10109 {kEventParamTextInputSendComponentInstance
,
10110 kEventParamTextInputSendRefCon
,
10111 kEventParamTextInputSendSLRec
,
10112 kEventParamTextInputSendFixLen
,
10113 kEventParamTextInputSendText
,
10114 kEventParamTextInputSendUpdateRng
,
10115 kEventParamTextInputSendHiliteRng
,
10116 kEventParamTextInputSendClauseRng
,
10117 kEventParamTextInputSendPinRng
,
10118 kEventParamTextInputSendTextServiceEncoding
,
10119 kEventParamTextInputSendTextServiceMacEncoding
,
10120 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
10121 static const EventParamType types_uaia
[] =
10122 {typeComponentInstance
,
10124 typeIntlWritingCode
,
10131 typeTextRangeArray
,
10132 typeTextRangeArray
,
10138 static const EventParamName names_ufke
[] =
10139 {kEventParamTextInputSendComponentInstance
,
10140 kEventParamTextInputSendRefCon
,
10141 kEventParamTextInputSendSLRec
,
10142 kEventParamTextInputSendText
};
10143 static const EventParamType types_ufke
[] =
10144 {typeComponentInstance
,
10146 typeIntlWritingCode
,
10149 result
= CallNextEventHandler (next_handler
, event
);
10151 switch (GetEventKind (event
))
10153 case kEventTextInputUpdateActiveInputArea
:
10154 id_key
= Qupdate_active_input_area
;
10155 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
10156 names
= names_uaia
;
10157 types
= types_uaia
;
10158 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
10159 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
10163 case kEventTextInputUnicodeForKeyEvent
:
10165 EventRef kbd_event
;
10166 UInt32 actual_size
, modifiers
;
10168 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
10169 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
10172 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
10174 sizeof (UInt32
), NULL
, &modifiers
);
10175 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
10176 /* There're mapped modifier keys. Process it in
10178 return eventNotHandledErr
;
10180 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10181 typeUnicodeText
, NULL
, 0, &actual_size
,
10183 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
10187 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
10188 typeUnicodeText
, NULL
,
10189 sizeof (UniChar
), NULL
, &code
);
10190 if (err
== noErr
&& code
< 0x80)
10192 /* ASCII character. Process it in XTread_socket. */
10193 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
10197 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
10198 typeUInt32
, NULL
, sizeof (UInt32
),
10200 if (!(err
== noErr
&& key_code
<= 0x7f
10201 && keycode_to_xkeysym_table
[key_code
]))
10204 mac_focus_frame (&one_mac_display_info
);
10206 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
10207 read_socket_inev
->code
= code
;
10208 read_socket_inev
->modifiers
=
10209 mac_to_emacs_modifiers (modifiers
);
10210 read_socket_inev
->modifiers
|=
10211 (extra_keyboard_modifiers
10212 & (meta_modifier
| alt_modifier
10213 | hyper_modifier
| super_modifier
));
10214 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
10217 return eventNotHandledErr
;
10221 /* Non-ASCII keystrokes without mapped modifiers are processed
10222 at the Lisp level. */
10223 id_key
= Qunicode_for_key_event
;
10224 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
10225 names
= names_ufke
;
10226 types
= types_ufke
;
10229 case kEventTextInputOffsetToPos
:
10235 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
10236 return eventNotHandledErr
;
10238 /* Strictly speaking, this is not always correct because
10239 previous events may change some states about display. */
10240 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
10242 /* Active input area is displayed in the echo area. */
10243 w
= XWINDOW (echo_area_window
);
10244 f
= WINDOW_XFRAME (w
);
10248 /* Active input area is displayed around the current point. */
10249 f
= SELECTED_FRAME ();
10250 w
= XWINDOW (f
->selected_window
);
10253 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
10254 + WINDOW_LEFT_FRINGE_WIDTH (w
));
10255 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
10256 + FONT_BASE (FRAME_FONT (f
)));
10257 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
10258 LocalToGlobal (&p
);
10259 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
10260 typeQDPoint
, sizeof (typeQDPoint
), &p
);
10268 if (!NILP (id_key
))
10269 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
10273 return err
== noErr
? noErr
: result
;
10279 mac_store_service_event (event
)
10283 Lisp_Object id_key
;
10285 const EventParamName
*names
;
10286 const EventParamType
*types
;
10287 static const EventParamName names_pfm
[] =
10288 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10289 static const EventParamType types_pfm
[] =
10290 {typeCFStringRef
, typeCFStringRef
};
10292 switch (GetEventKind (event
))
10294 case kEventServicePaste
:
10301 case kEventServicePerform
:
10303 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10312 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10318 #endif /* MAC_OSX */
10319 #endif /* USE_CARBON_EVENTS */
10323 install_window_handler (window
)
10326 OSStatus err
= noErr
;
10327 #if USE_CARBON_EVENTS
10328 static const EventTypeSpec specs_window
[] =
10329 {{kEventClassWindow
, kEventWindowUpdate
},
10330 {kEventClassWindow
, kEventWindowGetIdealSize
},
10331 {kEventClassWindow
, kEventWindowBoundsChanging
},
10332 {kEventClassWindow
, kEventWindowBoundsChanged
},
10333 {kEventClassWindow
, kEventWindowShown
},
10334 {kEventClassWindow
, kEventWindowHidden
},
10335 {kEventClassWindow
, kEventWindowExpanded
},
10336 {kEventClassWindow
, kEventWindowCollapsed
},
10337 {kEventClassWindow
, kEventWindowClose
},
10339 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
10342 {kEventClassWindow
, kEventWindowFocusAcquired
},
10343 {kEventClassWindow
, kEventWindowFocusRelinquish
},
10346 static const EventTypeSpec specs_mouse
[] =
10347 {{kEventClassMouse
, kEventMouseWheelMoved
}};
10348 static EventHandlerUPP handle_window_eventUPP
= NULL
;
10349 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
10350 #if USE_MAC_FONT_PANEL
10351 static const EventTypeSpec specs_font
[] =
10352 {{kEventClassFont
, kEventFontPanelClosed
},
10353 {kEventClassFont
, kEventFontSelection
}};
10354 static EventHandlerUPP handle_font_eventUPP
= NULL
;
10357 static const EventTypeSpec specs_text_input
[] =
10358 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
10359 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
10360 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
10361 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
10364 if (handle_window_eventUPP
== NULL
)
10365 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
10366 if (handle_mouse_eventUPP
== NULL
)
10367 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
10368 #if USE_MAC_FONT_PANEL
10369 if (handle_font_eventUPP
== NULL
)
10370 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
10373 if (handle_text_input_eventUPP
== NULL
)
10374 handle_text_input_eventUPP
=
10375 NewEventHandlerUPP (mac_handle_text_input_event
);
10377 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
10378 GetEventTypeCount (specs_window
),
10379 specs_window
, NULL
, NULL
);
10381 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
10382 GetEventTypeCount (specs_mouse
),
10383 specs_mouse
, NULL
, NULL
);
10384 #if USE_MAC_FONT_PANEL
10386 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
10387 GetEventTypeCount (specs_font
),
10388 specs_font
, NULL
, NULL
);
10392 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
10393 GetEventTypeCount (specs_text_input
),
10394 specs_text_input
, window
, NULL
);
10398 err
= install_drag_handler (window
);
10400 err
= install_menu_target_item_handler (window
);
10406 remove_window_handler (window
)
10409 remove_drag_handler (window
);
10414 mac_handle_dm_notification (event
)
10417 mac_screen_config_changed
= 1;
10421 init_dm_notification_handler ()
10424 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
10425 ProcessSerialNumber psn
;
10427 if (handle_dm_notificationUPP
== NULL
)
10428 handle_dm_notificationUPP
=
10429 NewDMNotificationUPP (mac_handle_dm_notification
);
10431 err
= GetCurrentProcess (&psn
);
10433 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
10439 mac_get_screen_info (dpyinfo
)
10440 struct mac_display_info
*dpyinfo
;
10443 /* HasDepth returns true if it is possible to have a 32 bit display,
10444 but this may not be what is actually used. Mac OSX can do better. */
10445 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
10446 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
10449 CGDisplayCount ndisps
;
10450 CGDirectDisplayID
*displays
;
10452 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
10455 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
10456 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
10460 CGRect bounds
= CGRectZero
;
10462 while (ndisps
-- > 0)
10463 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
10464 dpyinfo
->height
= CGRectGetHeight (bounds
);
10465 dpyinfo
->width
= CGRectGetWidth (bounds
);
10469 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
10470 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
10473 #else /* !MAC_OSX */
10475 GDHandle gdh
= GetMainDevice ();
10476 Rect rect
= (**gdh
).gdRect
;
10478 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
10479 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10480 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
10483 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
10484 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
10485 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
10487 dpyinfo
->height
= rect
.bottom
- rect
.top
;
10488 dpyinfo
->width
= rect
.right
- rect
.left
;
10490 #endif /* !MAC_OSX */
10496 profiler_exit_proc ()
10498 ProfilerDump ("\pEmacs.prof");
10503 /* These few functions implement Emacs as a normal Mac application
10504 (almost): set up the heap and the Toolbox, handle necessary system
10505 events plus a few simple menu events. They also set up Emacs's
10506 access to functions defined in the rest of this file. Emacs uses
10507 function hooks to perform all its terminal I/O. A complete list of
10508 these functions appear in termhooks.h. For what they do, read the
10509 comments there and see also w32term.c and xterm.c. What's
10510 noticeably missing here is the event loop, which is normally
10511 present in most Mac application. After performing the necessary
10512 Mac initializations, main passes off control to emacs_main
10513 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10514 (defined further below) to read input. This is where
10515 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10522 #if __profile__ /* is the profiler on? */
10523 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10528 /* set creator and type for files created by MSL */
10529 _fcreator
= MAC_EMACS_CREATOR_CODE
;
10533 do_init_managers ();
10537 #ifndef USE_LSB_TAG
10538 do_check_ram_size ();
10541 init_emacs_passwd_dir ();
10545 init_coercion_handler ();
10547 initialize_applescript ();
10549 init_apple_event_handler ();
10551 init_dm_notification_handler ();
10557 /* set up argv array from STR# resource */
10558 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10562 /* free up AppleScript resources on exit */
10563 atexit (terminate_applescript
);
10565 #if __profile__ /* is the profiler on? */
10566 atexit (profiler_exit_proc
);
10569 /* 3rd param "envp" never used in emacs_main */
10570 (void) emacs_main (argc
, argv
, 0);
10573 /* Never reached - real exit in Fkill_emacs */
10578 #if !USE_CARBON_EVENTS
10579 static RgnHandle mouse_region
= NULL
;
10582 mac_wait_next_event (er
, sleep_time
, dequeue
)
10587 static EventRecord er_buf
= {nullEvent
};
10588 UInt32 target_tick
, current_tick
;
10589 EventMask event_mask
;
10591 if (mouse_region
== NULL
)
10592 mouse_region
= NewRgn ();
10594 event_mask
= everyEvent
;
10595 if (!mac_ready_for_apple_events
)
10596 event_mask
-= highLevelEventMask
;
10598 current_tick
= TickCount ();
10599 target_tick
= current_tick
+ sleep_time
;
10601 if (er_buf
.what
== nullEvent
)
10602 while (!WaitNextEvent (event_mask
, &er_buf
,
10603 target_tick
- current_tick
, mouse_region
))
10605 current_tick
= TickCount ();
10606 if (target_tick
<= current_tick
)
10612 er_buf
.what
= nullEvent
;
10615 #endif /* not USE_CARBON_EVENTS */
10617 #if TARGET_API_MAC_CARBON
10619 mac_post_mouse_moved_event ()
10621 EventRef event
= NULL
;
10624 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
10625 kEventAttributeNone
, &event
);
10630 GetGlobalMouse (&mouse_pos
);
10631 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
10632 sizeof (Point
), &mouse_pos
);
10636 UInt32 modifiers
= GetCurrentKeyModifiers ();
10638 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10639 sizeof (UInt32
), &modifiers
);
10642 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10643 kEventPriorityStandard
);
10645 ReleaseEvent (event
);
10651 mac_set_unicode_keystroke_event (code
, buf
)
10653 struct input_event
*buf
;
10655 int charset_id
, c1
, c2
;
10659 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10662 else if (code
< 0x100)
10665 charset_id
= CHARSET_8_BIT_CONTROL
;
10667 charset_id
= charset_latin_iso8859_1
;
10668 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10669 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10674 charset_id
= charset_mule_unicode_0100_24ff
,
10676 else if (code
< 0x33FF)
10677 charset_id
= charset_mule_unicode_2500_33ff
,
10679 else if (code
>= 0xE000)
10680 charset_id
= charset_mule_unicode_e000_ffff
,
10682 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10683 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10684 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10689 /* Emacs calls this whenever it wants to read an input event from the
10692 XTread_socket (sd
, expected
, hold_quit
)
10694 struct input_event
*hold_quit
;
10696 struct input_event inev
;
10698 #if USE_CARBON_EVENTS
10700 EventTargetRef toolbox_dispatcher
;
10703 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10705 if (interrupt_input_blocked
)
10707 interrupt_input_pending
= 1;
10711 interrupt_input_pending
= 0;
10714 /* So people can tell when we have read the available input. */
10715 input_signal_count
++;
10719 #if USE_CARBON_EVENTS
10720 toolbox_dispatcher
= GetEventDispatcherTarget ();
10724 mac_prepare_for_quickdraw (NULL
),
10726 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10727 kEventRemoveFromQueue
, &eventRef
))
10728 #else /* !USE_CARBON_EVENTS */
10729 while (mac_wait_next_event (&er
, 0, true))
10730 #endif /* !USE_CARBON_EVENTS */
10734 unsigned long timestamp
;
10737 inev
.kind
= NO_EVENT
;
10740 #if USE_CARBON_EVENTS
10741 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10743 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10746 #if USE_CARBON_EVENTS
10747 /* Handle new events */
10748 if (!mac_convert_event_ref (eventRef
, &er
))
10750 /* There used to be a handler for the kEventMouseWheelMoved
10751 event here. But as of Mac OS X 10.4, this kind of event
10752 is not directly posted to the main event queue by
10753 two-finger scrolling on the trackpad. Instead, some
10754 private event is posted and it is converted to a wheel
10755 event by the default handler for the application target.
10756 The converted one can be received by a Carbon event
10757 handler installed on a window target. */
10758 read_socket_inev
= &inev
;
10759 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10760 read_socket_inev
= NULL
;
10763 #endif /* USE_CARBON_EVENTS */
10769 WindowPtr window_ptr
;
10770 ControlPartCode part_code
;
10771 int tool_bar_p
= 0;
10773 #if USE_CARBON_EVENTS
10774 /* This is needed to send mouse events like aqua window
10775 buttons to the correct handler. */
10776 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10777 != eventNotHandledErr
)
10780 last_mouse_glyph_frame
= 0;
10782 if (dpyinfo
->grabbed
&& last_mouse_frame
10783 && FRAME_LIVE_P (last_mouse_frame
))
10785 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10786 part_code
= inContent
;
10790 part_code
= FindWindow (er
.where
, &window_ptr
);
10791 if (tip_window
&& window_ptr
== tip_window
)
10793 HideWindow (tip_window
);
10794 part_code
= FindWindow (er
.where
, &window_ptr
);
10798 if (er
.what
!= mouseDown
&&
10799 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10805 f
= mac_focus_frame (dpyinfo
);
10806 saved_menu_event_location
= er
.where
;
10807 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10808 XSETFRAME (inev
.frame_or_window
, f
);
10813 #if TARGET_API_MAC_CARBON
10814 FrontNonFloatingWindow ()
10819 || (mac_window_to_frame (window_ptr
)
10820 != dpyinfo
->x_focus_frame
))
10821 SelectWindow (window_ptr
);
10824 ControlPartCode control_part_code
;
10826 Point mouse_loc
= er
.where
;
10828 ControlKind control_kind
;
10831 f
= mac_window_to_frame (window_ptr
);
10832 /* convert to local coordinates of new window */
10833 SetPortWindowPort (window_ptr
);
10835 GlobalToLocal (&mouse_loc
);
10836 #if TARGET_API_MAC_CARBON
10837 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10838 &control_part_code
);
10841 GetControlKind (ch
, &control_kind
);
10844 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10848 #if USE_CARBON_EVENTS
10849 inev
.code
= mac_get_mouse_btn (eventRef
);
10850 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10852 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10853 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10855 XSETINT (inev
.x
, mouse_loc
.h
);
10856 XSETINT (inev
.y
, mouse_loc
.v
);
10858 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10860 #ifndef USE_TOOLKIT_SCROLL_BARS
10861 /* control_part_code becomes kControlNoPart if
10862 a progress indicator is clicked. */
10863 && control_part_code
!= kControlNoPart
10864 #else /* USE_TOOLKIT_SCROLL_BARS */
10866 && control_kind
.kind
== kControlKindScrollBar
10867 #endif /* MAC_OSX */
10868 #endif /* USE_TOOLKIT_SCROLL_BARS */
10871 struct scroll_bar
*bar
;
10873 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10875 bar
= tracked_scroll_bar
;
10876 #ifndef USE_TOOLKIT_SCROLL_BARS
10877 control_part_code
= kControlIndicatorPart
;
10881 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10882 #ifdef USE_TOOLKIT_SCROLL_BARS
10883 /* Make the "Ctrl-Mouse-2 splits window" work
10884 for toolkit scroll bars. */
10885 if (inev
.modifiers
& ctrl_modifier
)
10886 x_scroll_bar_handle_click (bar
, control_part_code
,
10888 else if (er
.what
== mouseDown
)
10889 x_scroll_bar_handle_press (bar
, control_part_code
,
10892 x_scroll_bar_handle_release (bar
, &inev
);
10893 #else /* not USE_TOOLKIT_SCROLL_BARS */
10894 x_scroll_bar_handle_click (bar
, control_part_code
,
10896 if (er
.what
== mouseDown
10897 && control_part_code
== kControlIndicatorPart
)
10898 tracked_scroll_bar
= bar
;
10900 tracked_scroll_bar
= NULL
;
10901 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10905 Lisp_Object window
;
10906 int x
= mouse_loc
.h
;
10907 int y
= mouse_loc
.v
;
10909 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10910 if (EQ (window
, f
->tool_bar_window
))
10912 if (er
.what
== mouseDown
)
10913 handle_tool_bar_click (f
, x
, y
, 1, 0);
10915 handle_tool_bar_click (f
, x
, y
, 0,
10921 XSETFRAME (inev
.frame_or_window
, f
);
10922 inev
.kind
= MOUSE_CLICK_EVENT
;
10926 if (er
.what
== mouseDown
)
10928 dpyinfo
->grabbed
|= (1 << inev
.code
);
10929 last_mouse_frame
= f
;
10932 last_tool_bar_item
= -1;
10936 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10937 /* If a button is released though it was not
10938 previously pressed, that would be because
10939 of multi-button emulation. */
10940 dpyinfo
->grabbed
= 0;
10942 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10945 /* Ignore any mouse motion that happened before
10946 this event; any subsequent mouse-movement Emacs
10947 events should reflect only motion after the
10950 f
->mouse_moved
= 0;
10952 #ifdef USE_TOOLKIT_SCROLL_BARS
10953 if (inev
.kind
== MOUSE_CLICK_EVENT
10954 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
10955 && (inev
.modifiers
& ctrl_modifier
)))
10960 inev
.modifiers
|= down_modifier
;
10963 inev
.modifiers
|= up_modifier
;
10970 #if TARGET_API_MAC_CARBON
10972 if (IsWindowPathSelectClick (window_ptr
, &er
))
10974 WindowPathSelect (window_ptr
, NULL
, NULL
);
10977 if (part_code
== inProxyIcon
10978 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
10979 != errUserWantsToDragWindow
))
10981 DragWindow (window_ptr
, er
.where
, NULL
);
10982 #else /* not TARGET_API_MAC_CARBON */
10983 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10984 #endif /* not TARGET_API_MAC_CARBON */
10985 /* Update the frame parameters. */
10986 #if !USE_CARBON_EVENTS
10988 struct frame
*f
= mac_window_to_frame (window_ptr
);
10990 if (f
&& !f
->async_iconified
)
10991 mac_handle_origin_change (f
);
10997 if (TrackGoAway (window_ptr
, er
.where
))
10999 inev
.kind
= DELETE_WINDOW_EVENT
;
11000 XSETFRAME (inev
.frame_or_window
,
11001 mac_window_to_frame (window_ptr
));
11005 /* window resize handling added --ben */
11007 do_grow_window (window_ptr
, &er
);
11010 /* window zoom handling added --ben */
11013 if (TrackBox (window_ptr
, er
.where
, part_code
))
11014 do_zoom_window (window_ptr
, part_code
);
11024 #if USE_CARBON_EVENTS
11025 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11026 != eventNotHandledErr
)
11029 do_window_update ((WindowPtr
) er
.message
);
11034 #if USE_CARBON_EVENTS
11035 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11036 != eventNotHandledErr
)
11039 switch ((er
.message
>> 24) & 0x000000FF)
11041 case suspendResumeMessage
:
11043 if (er
.message
& resumeFlag
)
11046 mac_tsm_suspend ();
11050 case mouseMovedMessage
:
11051 #if !USE_CARBON_EVENTS
11052 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
11053 er
.where
.h
+ 1, er
.where
.v
+ 1);
11055 previous_help_echo_string
= help_echo_string
;
11056 help_echo_string
= Qnil
;
11058 if (dpyinfo
->grabbed
&& last_mouse_frame
11059 && FRAME_LIVE_P (last_mouse_frame
))
11060 f
= last_mouse_frame
;
11062 f
= dpyinfo
->x_focus_frame
;
11064 if (dpyinfo
->mouse_face_hidden
)
11066 dpyinfo
->mouse_face_hidden
= 0;
11067 clear_mouse_face (dpyinfo
);
11072 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
11073 Point mouse_pos
= er
.where
;
11075 SetPortWindowPort (wp
);
11077 GlobalToLocal (&mouse_pos
);
11079 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11080 #ifdef USE_TOOLKIT_SCROLL_BARS
11081 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
11083 #else /* not USE_TOOLKIT_SCROLL_BARS */
11084 x_scroll_bar_note_movement (tracked_scroll_bar
,
11086 - XINT (tracked_scroll_bar
->top
),
11087 er
.when
* (1000 / 60));
11088 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11091 /* Generate SELECT_WINDOW_EVENTs when needed. */
11092 if (!NILP (Vmouse_autoselect_window
))
11094 Lisp_Object window
;
11096 window
= window_from_coordinates (f
,
11101 /* Window will be selected only when it is
11102 not selected now and last mouse movement
11103 event was not in it. Minibuffer window
11104 will be selected iff it is active. */
11105 if (WINDOWP (window
)
11106 && !EQ (window
, last_window
)
11107 && !EQ (window
, selected_window
))
11109 inev
.kind
= SELECT_WINDOW_EVENT
;
11110 inev
.frame_or_window
= window
;
11113 last_window
=window
;
11115 if (!note_mouse_movement (f
, &mouse_pos
))
11116 help_echo_string
= previous_help_echo_string
;
11120 /* If the contents of the global variable
11121 help_echo_string has changed, generate a
11123 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
11131 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
11133 #if USE_CARBON_EVENTS
11134 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
11135 != eventNotHandledErr
)
11138 if (window_ptr
== tip_window
)
11140 HideWindow (tip_window
);
11144 if (!is_emacs_window (window_ptr
))
11147 if ((er
.modifiers
& activeFlag
) != 0)
11149 /* A window has been activated */
11150 Point mouse_loc
= er
.where
;
11152 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11154 SetPortWindowPort (window_ptr
);
11155 GlobalToLocal (&mouse_loc
);
11156 /* Window-activated event counts as mouse movement,
11157 so update things that depend on mouse position. */
11158 note_mouse_movement (mac_window_to_frame (window_ptr
),
11163 /* A window has been deactivated */
11164 #ifdef USE_TOOLKIT_SCROLL_BARS
11165 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11167 struct input_event event
;
11169 EVENT_INIT (event
);
11170 event
.kind
= NO_EVENT
;
11171 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
11172 if (event
.kind
!= NO_EVENT
)
11174 event
.timestamp
= timestamp
;
11175 kbd_buffer_store_event_hold (&event
, hold_quit
);
11180 dpyinfo
->grabbed
= 0;
11182 x_detect_focus_change (dpyinfo
, &er
, &inev
);
11184 f
= mac_window_to_frame (window_ptr
);
11185 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11187 /* If we move outside the frame, then we're
11188 certainly no longer on any text in the
11190 clear_mouse_face (dpyinfo
);
11191 dpyinfo
->mouse_face_mouse_frame
= 0;
11194 /* Generate a nil HELP_EVENT to cancel a help-echo.
11195 Do it only if there's something to cancel.
11196 Otherwise, the startup message is cleared when the
11197 mouse leaves the frame. */
11198 if (any_help_event_p
)
11208 int keycode
= (er
.message
& keyCodeMask
) >> 8;
11209 static SInt16 last_key_script
= -1;
11210 SInt16 current_key_script
;
11211 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
11213 #if USE_CARBON_EVENTS && defined (MAC_OSX)
11214 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
11216 sizeof (UInt32
), NULL
, &modifiers
);
11218 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
11220 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
11221 /* When using Carbon Events, we need to pass raw keyboard
11222 events to the TSM ourselves. If TSM handles it, it
11223 will pass back noErr, otherwise it will pass back
11224 "eventNotHandledErr" and we can process it
11226 if (!(mapped_modifiers
11227 & ~(mac_pass_command_to_system
? cmdKey
: 0)
11228 & ~(mac_pass_control_to_system
? controlKey
: 0)))
11232 read_socket_inev
= &inev
;
11233 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11234 read_socket_inev
= NULL
;
11235 if (err
!= eventNotHandledErr
)
11239 if (er
.what
== keyUp
)
11244 f
= mac_focus_frame (dpyinfo
);
11246 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
11247 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
11249 clear_mouse_face (dpyinfo
);
11250 dpyinfo
->mouse_face_hidden
= 1;
11253 current_key_script
= GetScriptManagerVariable (smKeyScript
);
11254 if (last_key_script
!= current_key_script
)
11256 struct input_event event
;
11258 EVENT_INIT (event
);
11259 event
.kind
= LANGUAGE_CHANGE_EVENT
;
11261 event
.code
= current_key_script
;
11262 event
.timestamp
= timestamp
;
11263 kbd_buffer_store_event (&event
);
11265 last_key_script
= current_key_script
;
11269 if (inev
.kind
!= NO_EVENT
)
11274 if (mapped_modifiers
& kEventKeyModifierFnMask
11276 && fn_keycode_to_keycode_table
[keycode
])
11277 keycode
= fn_keycode_to_keycode_table
[keycode
];
11279 if (keycode
<= 0x7f && keycode_to_xkeysym_table
[keycode
])
11281 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
11282 inev
.code
= 0xff00 | keycode_to_xkeysym_table
[keycode
];
11284 if (modifiers
& kEventKeyModifierFnMask
11286 && fn_keycode_to_keycode_table
[keycode
] == keycode
)
11287 modifiers
&= ~kEventKeyModifierFnMask
;
11290 else if (mapped_modifiers
)
11292 /* translate the keycode back to determine the
11295 UCKeyboardLayout
*uchr_ptr
= NULL
;
11296 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11298 KeyboardLayoutRef layout
;
11300 err
= KLGetCurrentKeyboardLayout (&layout
);
11302 KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
11303 (const void **) &uchr_ptr
);
11305 static SInt16 last_key_layout_id
= 0;
11306 static Handle uchr_handle
= (Handle
)-1;
11307 SInt16 current_key_layout_id
=
11308 GetScriptVariable (current_key_script
, smScriptKeys
);
11310 if (uchr_handle
== (Handle
)-1
11311 || last_key_layout_id
!= current_key_layout_id
)
11313 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
11314 last_key_layout_id
= current_key_layout_id
;
11317 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
11323 UInt16 key_action
= er
.what
- keyDown
;
11324 UInt32 modifier_key_state
=
11325 (modifiers
& ~mapped_modifiers
) >> 8;
11326 UInt32 keyboard_type
= LMGetKbdType ();
11327 SInt32 dead_key_state
= 0;
11329 UniCharCount actual_length
;
11331 status
= UCKeyTranslate (uchr_ptr
,
11332 keycode
, key_action
,
11333 modifier_key_state
,
11335 kUCKeyTranslateNoDeadKeysMask
,
11337 1, &actual_length
, &code
);
11338 if (status
== noErr
&& actual_length
== 1)
11339 mac_set_unicode_keystroke_event (code
, &inev
);
11341 #endif /* MAC_OSX */
11343 if (inev
.kind
== NO_EVENT
)
11345 /* This code comes from Keyboard Resource,
11346 Appendix C of IM - Text. This is necessary
11347 since shift is ignored in KCHR table
11348 translation when option or command is pressed.
11349 It also does not translate correctly
11350 control-shift chars like C-% so mask off shift
11352 /* Mask off modifier keys that are mapped to some
11353 Emacs modifiers. */
11354 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
11355 /* set high byte of keycode to modifier high byte*/
11356 int new_keycode
= keycode
| new_modifiers
;
11357 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
11358 unsigned long some_state
= 0;
11359 UInt32 new_char_code
;
11361 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
11363 if (new_char_code
== 0)
11364 /* Seems like a dead key. Append up-stroke. */
11365 new_char_code
= KeyTranslate (kchr_ptr
,
11366 new_keycode
| 0x80,
11370 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11371 inev
.code
= new_char_code
& 0xff;
11376 if (inev
.kind
== NO_EVENT
)
11378 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
11379 inev
.code
= er
.message
& charCodeMask
;
11382 inev
.modifiers
= mac_to_emacs_modifiers (modifiers
);
11383 inev
.modifiers
|= (extra_keyboard_modifiers
11384 & (meta_modifier
| alt_modifier
11385 | hyper_modifier
| super_modifier
));
11386 XSETFRAME (inev
.frame_or_window
, f
);
11388 #if TARGET_API_MAC_CARBON
11389 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
11390 && inev
.code
>= 0x80 && inev
.modifiers
)
11393 TextEncoding encoding
= kTextEncodingMacRoman
;
11394 TextToUnicodeInfo ttu_info
;
11396 UpgradeScriptInfoToTextEncoding (current_key_script
,
11397 kTextLanguageDontCare
,
11398 kTextRegionDontCare
,
11400 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
11405 ByteCount unicode_len
;
11408 pstr
[1] = inev
.code
;
11409 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
11411 &unicode_len
, &code
);
11412 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
11413 mac_set_unicode_keystroke_event (code
, &inev
);
11414 DisposeTextToUnicodeInfo (&ttu_info
);
11421 case kHighLevelEvent
:
11422 AEProcessAppleEvent (&er
);
11428 #if USE_CARBON_EVENTS
11429 ReleaseEvent (eventRef
);
11432 if (inev
.kind
!= NO_EVENT
)
11434 inev
.timestamp
= timestamp
;
11435 kbd_buffer_store_event_hold (&inev
, hold_quit
);
11440 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
11445 XSETFRAME (frame
, f
);
11451 any_help_event_p
= 1;
11452 gen_help_event (help_echo_string
, frame
, help_echo_window
,
11453 help_echo_object
, help_echo_pos
);
11457 help_echo_string
= Qnil
;
11458 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
11465 /* If the focus was just given to an autoraising frame,
11467 /* ??? This ought to be able to handle more than one such frame. */
11468 if (pending_autoraise_frame
)
11470 x_raise_frame (pending_autoraise_frame
);
11471 pending_autoraise_frame
= 0;
11474 if (mac_screen_config_changed
)
11476 mac_get_screen_info (dpyinfo
);
11477 mac_screen_config_changed
= 0;
11480 #if !USE_CARBON_EVENTS
11481 /* Check which frames are still visible. We do this here because
11482 there doesn't seem to be any direct notification from the Window
11483 Manager that the visibility of a window has changed (at least,
11484 not in all cases). */
11486 Lisp_Object tail
, frame
;
11488 FOR_EACH_FRAME (tail
, frame
)
11490 struct frame
*f
= XFRAME (frame
);
11492 /* The tooltip has been drawn already. Avoid the
11493 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11494 if (EQ (frame
, tip_frame
))
11497 if (FRAME_MAC_P (f
))
11498 mac_handle_visibility_change (f
);
11509 /* Need to override CodeWarrior's input function so no conversion is
11510 done on newlines Otherwise compiled functions in .elc files will be
11511 read incorrectly. Defined in ...:MSL C:MSL
11512 Common:Source:buffer_io.c. */
11515 __convert_to_newlines (unsigned char * p
, size_t * n
)
11517 #pragma unused(p,n)
11521 __convert_from_newlines (unsigned char * p
, size_t * n
)
11523 #pragma unused(p,n)
11529 make_mac_terminal_frame (struct frame
*f
)
11534 XSETFRAME (frame
, f
);
11536 f
->output_method
= output_mac
;
11537 f
->output_data
.mac
= (struct mac_output
*)
11538 xmalloc (sizeof (struct mac_output
));
11539 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
11541 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
11543 FRAME_COLS (f
) = 96;
11544 FRAME_LINES (f
) = 4;
11546 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
11547 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
11549 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
11551 f
->output_data
.mac
->cursor_pixel
= 0;
11552 f
->output_data
.mac
->border_pixel
= 0x00ff00;
11553 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
11554 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
11556 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
11557 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
11558 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
11559 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
11560 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
11561 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
11563 FRAME_FONTSET (f
) = -1;
11564 f
->output_data
.mac
->explicit_parent
= 0;
11567 f
->border_width
= 0;
11569 f
->internal_border_width
= 0;
11574 f
->new_text_cols
= 0;
11575 f
->new_text_lines
= 0;
11577 SetRect (&r
, f
->left_pos
, f
->top_pos
,
11578 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
11579 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
11583 if (!(FRAME_MAC_WINDOW (f
) =
11584 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
11585 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
11587 /* so that update events can find this mac_output struct */
11588 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
11594 /* Need to be initialized for unshow_buffer in window.c. */
11595 selected_window
= f
->selected_window
;
11597 Fmodify_frame_parameters (frame
,
11598 Fcons (Fcons (Qfont
,
11599 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
11600 Fmodify_frame_parameters (frame
,
11601 Fcons (Fcons (Qforeground_color
,
11602 build_string ("black")), Qnil
));
11603 Fmodify_frame_parameters (frame
,
11604 Fcons (Fcons (Qbackground_color
,
11605 build_string ("white")), Qnil
));
11610 /***********************************************************************
11612 ***********************************************************************/
11614 static int mac_initialized
= 0;
11617 mac_make_rdb (xrm_option
)
11618 const char *xrm_option
;
11620 XrmDatabase database
;
11622 database
= xrm_get_preference_database (NULL
);
11624 xrm_merge_string_database (database
, xrm_option
);
11629 struct mac_display_info
*
11630 mac_term_init (display_name
, xrm_option
, resource_name
)
11631 Lisp_Object display_name
;
11633 char *resource_name
;
11635 struct mac_display_info
*dpyinfo
;
11636 struct terminal
*terminal
;
11640 if (!mac_initialized
)
11643 mac_initialized
= 1;
11646 if (x_display_list
)
11647 error ("Sorry, this version can only handle one display");
11649 dpyinfo
= &one_mac_display_info
;
11650 bzero (dpyinfo
, sizeof (*dpyinfo
));
11652 terminal
= mac_create_terminal (dpyinfo
);
11654 /* Set the name of the terminal. */
11655 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
11656 strncpy (terminal
->name
, SDATA (display_name
), SBYTES (display_name
));
11657 terminal
->name
[SBYTES (display_name
)] = 0;
11660 dpyinfo
->mac_id_name
11661 = (char *) xmalloc (SCHARS (Vinvocation_name
)
11662 + SCHARS (Vsystem_name
)
11664 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
11665 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11667 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
11668 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
11671 dpyinfo
->reference_count
= 0;
11672 dpyinfo
->resx
= 72.0;
11673 dpyinfo
->resy
= 72.0;
11675 mac_get_screen_info (dpyinfo
);
11677 dpyinfo
->grabbed
= 0;
11678 dpyinfo
->root_window
= NULL
;
11679 dpyinfo
->image_cache
= make_image_cache ();
11681 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11682 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11683 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11684 dpyinfo
->mouse_face_window
= Qnil
;
11685 dpyinfo
->mouse_face_overlay
= Qnil
;
11686 dpyinfo
->mouse_face_hidden
= 0;
11688 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11690 /* Put this display on the chain. */
11691 dpyinfo
->next
= x_display_list
;
11692 x_display_list
= dpyinfo
;
11694 /* Put it on x_display_name_list. */
11695 x_display_name_list
= Fcons (Fcons (display_name
,
11696 Fcons (Qnil
, dpyinfo
->xrdb
)),
11697 x_display_name_list
);
11698 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11705 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11708 x_delete_display (dpyinfo
)
11709 struct mac_display_info
*dpyinfo
;
11713 /* Discard this display from x_display_name_list and x_display_list.
11714 We can't use Fdelq because that can quit. */
11715 if (! NILP (x_display_name_list
)
11716 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11717 x_display_name_list
= XCDR (x_display_name_list
);
11722 tail
= x_display_name_list
;
11723 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11725 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11727 XSETCDR (tail
, XCDR (XCDR (tail
)));
11730 tail
= XCDR (tail
);
11734 if (x_display_list
== dpyinfo
)
11735 x_display_list
= dpyinfo
->next
;
11738 struct x_display_info
*tail
;
11740 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11741 if (tail
->next
== dpyinfo
)
11742 tail
->next
= tail
->next
->next
;
11745 /* Free the font names in the font table. */
11746 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11747 if (dpyinfo
->font_table
[i
].name
)
11749 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11750 xfree (dpyinfo
->font_table
[i
].full_name
);
11751 xfree (dpyinfo
->font_table
[i
].name
);
11754 if (dpyinfo
->font_table
)
11756 if (dpyinfo
->font_table
->font_encoder
)
11757 xfree (dpyinfo
->font_table
->font_encoder
);
11758 xfree (dpyinfo
->font_table
);
11760 if (dpyinfo
->mac_id_name
)
11761 xfree (dpyinfo
->mac_id_name
);
11763 if (x_display_list
== 0)
11765 mac_clear_font_name_table ();
11766 bzero (dpyinfo
, sizeof (*dpyinfo
));
11777 MenuItemIndex menu_index
;
11779 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11780 &menu
, &menu_index
);
11782 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11783 #if USE_CARBON_EVENTS
11784 EnableMenuCommand (NULL
, kHICommandPreferences
);
11785 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11786 &menu
, &menu_index
);
11789 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11790 InsertMenuItemTextWithCFString (menu
, NULL
,
11791 0, kMenuItemAttrSeparator
, 0);
11792 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11793 0, 0, kHICommandAbout
);
11795 #endif /* USE_CARBON_EVENTS */
11796 #else /* !MAC_OSX */
11797 #if USE_CARBON_EVENTS
11798 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11808 static InterfaceTypeList types
= {kUnicodeDocument
};
11810 static InterfaceTypeList types
= {kTextService
};
11813 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11814 &tsm_document_id
, 0);
11818 /* Set up use of X before we make the first connection. */
11820 extern frame_parm_handler mac_frame_parm_handlers
[];
11822 static struct redisplay_interface x_redisplay_interface
=
11824 mac_frame_parm_handlers
,
11828 x_clear_end_of_line
,
11830 x_after_update_window_line
,
11831 x_update_window_begin
,
11832 x_update_window_end
,
11836 mac_flush_display_optional
,
11838 0, /* flush_display_optional */
11840 x_clear_window_mouse_face
,
11841 x_get_glyph_overhangs
,
11842 x_fix_overlapping_area
,
11843 x_draw_fringe_bitmap
,
11845 mac_define_fringe_bitmap
,
11846 mac_destroy_fringe_bitmap
,
11848 0, /* define_fringe_bitmap */
11849 0, /* destroy_fringe_bitmap */
11851 mac_per_char_metric
,
11853 mac_compute_glyph_string_overhangs
,
11854 x_draw_glyph_string
,
11855 mac_define_frame_cursor
,
11856 mac_clear_frame_area
,
11857 mac_draw_window_cursor
,
11858 mac_draw_vertical_window_border
,
11859 mac_shift_glyphs_for_insert
11862 static struct terminal
*
11863 mac_create_terminal (struct mac_display_info
*dpyinfo
)
11865 struct terminal
*terminal
;
11867 terminal
= create_terminal ();
11869 terminal
->type
= output_mac
;
11870 terminal
->display_info
.mac
= dpyinfo
;
11871 dpyinfo
->terminal
= terminal
;
11873 terminal
->rif
= &x_redisplay_interface
;
11874 terminal
->clear_frame_hook
= x_clear_frame
;
11875 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
11876 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
11877 terminal
->ring_bell_hook
= XTring_bell
;
11878 terminal
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
11879 terminal
->set_terminal_modes_hook
= XTset_terminal_modes
;
11880 terminal
->update_begin_hook
= x_update_begin
;
11881 terminal
->update_end_hook
= x_update_end
;
11882 terminal
->set_terminal_window_hook
= XTset_terminal_window
;
11883 terminal
->read_socket_hook
= XTread_socket
;
11884 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
11885 terminal
->mouse_position_hook
= XTmouse_position
;
11886 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
11887 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
11889 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11890 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11891 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11892 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11895 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
11896 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
11897 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
11898 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
11899 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
11903 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
11904 terminal
->char_ins_del_ok
= 1;
11905 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
11906 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
11907 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
11920 last_tool_bar_item
= -1;
11921 any_help_event_p
= 0;
11923 /* Try to use interrupt input; if we can't, then start polling. */
11924 Fset_input_interrupt_mode (Qt
);
11928 #if TARGET_API_MAC_CARBON
11930 #if USE_CARBON_EVENTS
11932 init_service_handler ();
11933 #endif /* MAC_OSX */
11935 init_command_handler ();
11942 #endif /* USE_CARBON_EVENTS */
11945 init_coercion_handler ();
11947 init_apple_event_handler ();
11949 init_dm_notification_handler ();
11951 if (!inhibit_window_system
)
11953 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
11955 SetFrontProcess (&psn
);
11963 mac_init_fringe ();
11975 staticpro (&x_error_message_string
);
11976 x_error_message_string
= Qnil
;
11979 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11980 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11981 Qalt
= intern ("alt"); staticpro (&Qalt
);
11982 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
11983 Qsuper
= intern ("super"); staticpro (&Qsuper
);
11984 Qmodifier_value
= intern ("modifier-value");
11985 staticpro (&Qmodifier_value
);
11987 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
11988 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11989 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11990 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11991 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11993 #if USE_CARBON_EVENTS
11994 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
11996 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
11997 staticpro (&Qtoolbar_switch_mode
);
11998 #if USE_MAC_FONT_PANEL
11999 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12000 Qselection
= intern ("selection"); staticpro (&Qselection
);
12003 Qservice
= intern ("service"); staticpro (&Qservice
);
12004 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12005 Qperform
= intern ("perform"); staticpro (&Qperform
);
12008 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12009 Qupdate_active_input_area
= intern ("update-active-input-area");
12010 staticpro (&Qupdate_active_input_area
);
12011 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12012 staticpro (&Qunicode_for_key_event
);
12017 Fprovide (intern ("mac-carbon"), Qnil
);
12020 staticpro (&Qreverse
);
12021 Qreverse
= intern ("reverse");
12023 staticpro (&x_display_name_list
);
12024 x_display_name_list
= Qnil
;
12026 staticpro (&last_mouse_scroll_bar
);
12027 last_mouse_scroll_bar
= Qnil
;
12029 staticpro (&fm_font_family_alist
);
12030 fm_font_family_alist
= Qnil
;
12033 staticpro (&atsu_font_id_hash
);
12034 atsu_font_id_hash
= Qnil
;
12036 staticpro (&fm_style_face_attributes_alist
);
12037 fm_style_face_attributes_alist
= Qnil
;
12041 staticpro (&saved_ts_script_language_on_focus
);
12042 saved_ts_script_language_on_focus
= Qnil
;
12045 /* We don't yet support this, but defining this here avoids whining
12046 from cus-start.el and other places, like "M-x set-variable". */
12047 DEFVAR_BOOL ("x-use-underline-position-properties",
12048 &x_use_underline_position_properties
,
12049 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12050 A value of nil means ignore them. If you encounter fonts with bogus
12051 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12052 to 4.1, set this to nil.
12054 NOTE: Not supported on Mac yet. */);
12055 x_use_underline_position_properties
= 0;
12057 DEFVAR_BOOL ("x-underline-at-descent-line",
12058 &x_underline_at_descent_line
,
12059 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12060 A value of nil means to draw the underline according to the value of the
12061 variable `x-use-underline-position-properties', which is usually at the
12062 baseline level. The default value is nil. */);
12063 x_underline_at_descent_line
= 0;
12065 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12066 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12067 #ifdef USE_TOOLKIT_SCROLL_BARS
12068 Vx_toolkit_scroll_bars
= Qt
;
12070 Vx_toolkit_scroll_bars
= Qnil
;
12073 staticpro (&last_mouse_motion_frame
);
12074 last_mouse_motion_frame
= Qnil
;
12076 /* Variables to configure modifier key assignment. */
12078 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12079 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12080 The value can be `control', `meta', `alt', `hyper', or `super' for the
12081 respective modifier. The default is `control'. */);
12082 Vmac_control_modifier
= Qcontrol
;
12084 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12085 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12086 The value can be `control', `meta', `alt', `hyper', or `super' for the
12087 respective modifier. If the value is nil then the key will act as the
12088 normal Mac control modifier, and the option key can be used to compose
12089 characters depending on the chosen Mac keyboard setting. */);
12090 Vmac_option_modifier
= Qnil
;
12092 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12093 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12094 The value can be `control', `meta', `alt', `hyper', or `super' for the
12095 respective modifier. The default is `meta'. */);
12096 Vmac_command_modifier
= Qmeta
;
12098 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12099 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12100 The value can be `control', `meta', `alt', `hyper', or `super' for the
12101 respective modifier. Note that remapping the function key may lead to
12102 unexpected results for some keys on non-US/GB keyboards. */);
12103 Vmac_function_modifier
= Qnil
;
12105 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12106 &Vmac_emulate_three_button_mouse
,
12107 doc
: /* *Specify a way of three button mouse emulation.
12108 The value can be nil, t, or the symbol `reverse'.
12109 A value of nil means that no emulation should be done and the modifiers
12110 should be placed on the mouse-1 event.
12111 t means that when the option-key is held down while pressing the mouse
12112 button, the click will register as mouse-2 and while the command-key
12113 is held down, the click will register as mouse-3.
12114 The symbol `reverse' means that the option-key will register for
12115 mouse-3 and the command-key will register for mouse-2. */);
12116 Vmac_emulate_three_button_mouse
= Qnil
;
12118 #if USE_CARBON_EVENTS
12119 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12120 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12121 Otherwise, the right click will be treated as mouse-2 and the wheel
12122 button will be mouse-3. */);
12123 mac_wheel_button_is_mouse_2
= 1;
12125 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12126 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12127 mac_pass_command_to_system
= 1;
12129 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12130 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12131 mac_pass_control_to_system
= 1;
12135 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
12136 doc
: /* *If non-nil, allow anti-aliasing.
12137 The text will be rendered using Core Graphics text rendering which
12138 may anti-alias the text. */);
12140 mac_use_core_graphics
= 1;
12142 mac_use_core_graphics
= 0;
12145 /* Register an entry for `mac-roman' so that it can be used when
12146 creating the terminal frame on Mac OS 9 before loading
12147 term/mac-win.elc. */
12148 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
12149 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
12150 Each entry should be of the form:
12152 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12154 where CHARSET-NAME is a string used in font names to identify the
12155 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12156 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12157 Vmac_charset_info_alist
=
12158 Fcons (list3 (build_string ("mac-roman"),
12159 make_number (smRoman
), Qnil
), Qnil
);
12162 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
12163 doc
: /* Overlay used to display Mac TSM active input area. */);
12164 Vmac_ts_active_input_overlay
= Qnil
;
12166 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
12167 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
12168 If the value is t, the input script and language are restored to those
12169 used in the last focus frame. If the value is a pair of integers, the
12170 input script and language codes, which are defined in the Script
12171 Manager, are set to its car and cdr parts, respectively. Otherwise,
12172 Emacs doesn't set them and thus follows the system default behavior. */);
12173 Vmac_ts_script_language_on_focus
= Qnil
;
12177 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12178 (do not change this comment) */