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 #include <Quickdraw.h>
40 #include <ToolUtils.h>
44 #include <Resources.h>
46 #include <TextUtils.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
58 #endif /* not TARGET_API_MAC_CARBON */
71 #include "dispextern.h"
73 #include "termhooks.h"
80 #include "intervals.h"
86 /* Non-nil means Emacs uses toolkit scroll bars. */
88 Lisp_Object Vx_toolkit_scroll_bars
;
90 /* If non-zero, the text will be rendered using Core Graphics text
91 rendering which may anti-alias the text. */
92 int mac_use_core_graphics
;
95 /* Non-zero means that a HELP_EVENT has been generated since Emacs
98 static int any_help_event_p
;
100 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
101 static Lisp_Object last_window
;
103 /* Non-zero means make use of UNDERLINE_POSITION font properties.
104 (Not yet supported.) */
105 int x_use_underline_position_properties
;
107 /* Non-zero means to draw the underline at the same place as the descent line. */
109 int x_underline_at_descent_line
;
111 /* This is a chain of structures for all the X displays currently in
114 struct x_display_info
*x_display_list
;
116 /* This is a list of cons cells, each of the form (NAME
117 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
118 x_display_list and in the same order. NAME is the name of the
119 frame. FONT-LIST-CACHE records previous values returned by
120 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
121 equivalent, which is implemented with a Lisp object, for the
124 Lisp_Object x_display_name_list
;
126 /* This is display since Mac does not support multiple ones. */
127 struct mac_display_info one_mac_display_info
;
129 /* Frame being updated by update_frame. This is declared in term.c.
130 This is set by update_begin and looked at by all the XT functions.
131 It is zero while not inside an update. In that case, the XT
132 functions assume that `selected_frame' is the frame to apply to. */
134 extern struct frame
*updating_frame
;
136 /* This is a frame waiting to be auto-raised, within XTread_socket. */
138 struct frame
*pending_autoraise_frame
;
142 Formerly, we used PointerMotionHintMask (in standard_event_mask)
143 so that we would have to call XQueryPointer after each MotionNotify
144 event to ask for another such event. However, this made mouse tracking
145 slow, and there was a bug that made it eventually stop.
147 Simply asking for MotionNotify all the time seems to work better.
149 In order to avoid asking for motion events and then throwing most
150 of them away or busy-polling the server for mouse positions, we ask
151 the server for pointer motion hints. This means that we get only
152 one event per group of mouse movements. "Groups" are delimited by
153 other kinds of events (focus changes and button clicks, for
154 example), or by XQueryPointer calls; when one of these happens, we
155 get another MotionNotify event the next time the mouse moves. This
156 is at least as efficient as getting motion events when mouse
157 tracking is on, and I suspect only negligibly worse when tracking
160 /* Where the mouse was last time we reported a mouse event. */
162 static Rect last_mouse_glyph
;
163 static FRAME_PTR last_mouse_glyph_frame
;
165 /* The scroll bar in which the last X motion event occurred.
167 If the last X motion event occurred in a scroll bar, we set this so
168 XTmouse_position can know whether to report a scroll bar motion or
171 If the last X motion event didn't occur in a scroll bar, we set
172 this to Qnil, to tell XTmouse_position to return an ordinary motion
175 static Lisp_Object last_mouse_scroll_bar
;
177 /* This is a hack. We would really prefer that XTmouse_position would
178 return the time associated with the position it returns, but there
179 doesn't seem to be any way to wrest the time-stamp from the server
180 along with the position query. So, we just keep track of the time
181 of the last movement we received, and return that in hopes that
182 it's somewhat accurate. */
184 static Time last_mouse_movement_time
;
186 struct scroll_bar
*tracked_scroll_bar
= NULL
;
188 /* Incremented by XTread_socket whenever it really tries to read
192 static int volatile input_signal_count
;
194 static int input_signal_count
;
197 extern Lisp_Object Vsystem_name
;
199 extern Lisp_Object Qeql
;
201 /* A mask of extra modifier bits to put into every keyboard char. */
203 extern EMACS_INT extra_keyboard_modifiers
;
205 /* The keysyms to use for the various modifiers. */
207 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
209 extern int inhibit_window_system
;
211 #if __MRC__ && !TARGET_API_MAC_CARBON
212 QDGlobals qd
; /* QuickDraw global information structure. */
215 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
217 struct mac_display_info
*mac_display_info_for_display (Display
*);
218 static void x_update_window_end
P_ ((struct window
*, int, int));
219 int x_catch_errors
P_ ((Display
*));
220 void x_uncatch_errors
P_ ((Display
*, int));
221 void x_lower_frame
P_ ((struct frame
*));
222 void x_scroll_bar_clear
P_ ((struct frame
*));
223 int x_had_errors_p
P_ ((Display
*));
224 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
225 void x_raise_frame
P_ ((struct frame
*));
226 void x_set_window_size
P_ ((struct frame
*, int, int, int));
227 void x_wm_set_window_state
P_ ((struct frame
*, int));
228 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
229 void mac_initialize
P_ ((void));
230 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
231 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
232 static void x_update_end
P_ ((struct frame
*));
233 static void XTframe_up_to_date
P_ ((struct frame
*));
234 static void XTset_terminal_modes
P_ ((void));
235 static void XTreset_terminal_modes
P_ ((void));
236 static void x_clear_frame
P_ ((void));
237 static void frame_highlight
P_ ((struct frame
*));
238 static void frame_unhighlight
P_ ((struct frame
*));
239 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
240 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
241 struct frame
*, struct input_event
*));
242 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
244 struct input_event
*));
245 static void XTframe_rehighlight
P_ ((struct frame
*));
246 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
247 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
248 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
249 enum text_cursor_kinds
));
251 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
252 static void x_flush
P_ ((struct frame
*f
));
253 static void x_update_begin
P_ ((struct frame
*));
254 static void x_update_window_begin
P_ ((struct window
*));
255 static void x_after_update_window_line
P_ ((struct glyph_row
*));
256 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
257 enum scroll_bar_part
*,
258 Lisp_Object
*, Lisp_Object
*,
261 static int is_emacs_window
P_ ((WindowRef
));
262 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
263 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
265 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
266 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
267 #define GC_FONT(gc) ((gc)->xgcv.font)
268 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
270 #define CG_SET_FILL_COLOR(context, color) \
271 CGContextSetRGBFillColor (context, \
272 RED_FROM_ULONG (color) / 255.0f, \
273 GREEN_FROM_ULONG (color) / 255.0f, \
274 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
275 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
276 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
277 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
279 if (CGColorGetTypeID != NULL) \
280 CGContextSetFillColorWithColor (context, cg_color); \
282 CG_SET_FILL_COLOR (context, color); \
285 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
286 CGContextSetFillColorWithColor (context, cg_color)
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CG_SET_FILL_COLOR (context, color)
292 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
293 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
295 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
296 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
300 #define CG_SET_STROKE_COLOR(context, color) \
301 CGContextSetRGBStrokeColor (context, \
302 RED_FROM_ULONG (color) / 255.0f, \
303 GREEN_FROM_ULONG (color) / 255.0f, \
304 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
305 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
306 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
307 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
309 if (CGColorGetTypeID != NULL) \
310 CGContextSetStrokeColorWithColor (context, cg_color); \
312 CG_SET_STROKE_COLOR (context, color); \
315 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
316 CGContextSetStrokeColorWithColor (context, cg_color)
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CG_SET_STROKE_COLOR (context, color)
322 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
323 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
327 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
329 /* Fringe bitmaps. */
331 static int max_fringe_bmp
= 0;
332 static CGImageRef
*fringe_bmp
= 0;
334 static CGColorSpaceRef mac_cg_color_space_rgb
;
335 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
336 static CGColorRef mac_cg_color_black
;
342 mac_cg_color_space_rgb
= CGColorSpaceCreateDeviceRGB ();
343 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
344 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
345 /* Don't check the availability of CGColorCreate; this symbol is
346 defined even in Mac OS X 10.1. */
347 if (CGColorGetTypeID
!= NULL
)
350 float rgba
[] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
352 mac_cg_color_black
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
358 mac_begin_cg_clip (f
, gc
)
362 CGContextRef context
= FRAME_CG_CONTEXT (f
);
366 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
367 FRAME_CG_CONTEXT (f
) = context
;
370 CGContextSaveGState (context
);
371 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
372 CGContextScaleCTM (context
, 1, -1);
373 if (gc
&& gc
->n_clip_rects
)
374 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
383 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
387 mac_prepare_for_quickdraw (f
)
392 Lisp_Object rest
, frame
;
393 FOR_EACH_FRAME (rest
, frame
)
394 if (FRAME_MAC_P (XFRAME (frame
)))
395 mac_prepare_for_quickdraw (XFRAME (frame
));
399 CGContextRef context
= FRAME_CG_CONTEXT (f
);
403 CGContextSynchronize (context
);
404 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
405 &FRAME_CG_CONTEXT (f
));
411 static RgnHandle saved_port_clip_region
= NULL
;
414 mac_begin_clip (f
, gc
)
418 static RgnHandle new_region
= NULL
;
420 if (saved_port_clip_region
== NULL
)
421 saved_port_clip_region
= NewRgn ();
422 if (new_region
== NULL
)
423 new_region
= NewRgn ();
426 mac_prepare_for_quickdraw (f
);
428 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
430 if (gc
->n_clip_rects
)
432 GetClip (saved_port_clip_region
);
433 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
434 SetClip (new_region
);
442 if (gc
->n_clip_rects
)
443 SetClip (saved_port_clip_region
);
447 /* X display function emulation */
449 /* Mac version of XDrawLine. */
452 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
458 CGContextRef context
;
459 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
462 gx1
+= 0.5f
, gx2
+= 0.5f
;
464 gy1
+= 0.5f
, gy2
+= 0.5f
;
466 context
= mac_begin_cg_clip (f
, gc
);
467 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
468 CGContextBeginPath (context
);
469 CGContextMoveToPoint (context
, gx1
, gy1
);
470 CGContextAddLineToPoint (context
, gx2
, gy2
);
471 CGContextClosePath (context
);
472 CGContextStrokePath (context
);
490 mac_begin_clip (f
, gc
);
491 RGBForeColor (GC_FORE_COLOR (gc
));
498 /* Mac version of XDrawLine (to Pixmap). */
501 XDrawLine (display
, p
, gc
, x1
, y1
, x2
, y2
)
525 GetGWorld (&old_port
, &old_gdh
);
528 RGBForeColor (GC_FORE_COLOR (gc
));
530 LockPixels (GetGWorldPixMap (p
));
533 UnlockPixels (GetGWorldPixMap (p
));
535 SetGWorld (old_port
, old_gdh
);
540 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
544 unsigned int width
, height
;
548 CGContextRef context
;
550 context
= mac_begin_cg_clip (f
, gc
);
551 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
552 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
559 mac_begin_clip (f
, gc
);
560 RGBBackColor (GC_BACK_COLOR (gc
));
561 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
563 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
570 /* Mac version of XClearArea. */
573 mac_clear_area (f
, x
, y
, width
, height
)
576 unsigned int width
, height
;
578 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
581 /* Mac version of XClearWindow. */
589 CGContextRef context
;
590 GC gc
= FRAME_NORMAL_GC (f
);
592 context
= mac_begin_cg_clip (f
, NULL
);
593 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
594 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
595 FRAME_PIXEL_HEIGHT (f
)));
598 #else /* !USE_CG_DRAWING */
599 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
601 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
603 #if TARGET_API_MAC_CARBON
607 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
610 #else /* not TARGET_API_MAC_CARBON */
611 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
612 #endif /* not TARGET_API_MAC_CARBON */
617 /* Mac replacement for XCopyArea. */
621 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
622 dest_x
, dest_y
, overlay_p
)
627 unsigned int width
, height
;
628 int dest_x
, dest_y
, overlay_p
;
630 CGContextRef context
;
631 float port_height
= FRAME_PIXEL_HEIGHT (f
);
632 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
634 context
= mac_begin_cg_clip (f
, gc
);
637 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
638 CGContextFillRect (context
, dest_rect
);
640 CGContextClipToRect (context
, dest_rect
);
641 CGContextScaleCTM (context
, 1, -1);
642 CGContextTranslateCTM (context
, 0, -port_height
);
643 if (CGImageIsMask (image
))
644 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
645 CGContextDrawImage (context
,
646 CGRectMake (dest_x
- src_x
,
647 port_height
- (dest_y
- src_y
648 + CGImageGetHeight (image
)),
649 CGImageGetWidth (image
),
650 CGImageGetHeight (image
)),
655 #else /* !USE_CG_DRAWING */
658 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
661 int x
, y
, width
, height
;
662 unsigned short *bits
;
668 bitmap
.rowBytes
= sizeof(unsigned short);
669 bitmap
.baseAddr
= (char *)bits
;
670 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
672 mac_begin_clip (f
, gc
);
673 RGBForeColor (GC_FORE_COLOR (gc
));
674 RGBBackColor (GC_BACK_COLOR (gc
));
675 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
676 #if TARGET_API_MAC_CARBON
682 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
683 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
684 UnlockPortBits (port
);
686 #else /* not TARGET_API_MAC_CARBON */
687 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
688 overlay_p
? srcOr
: srcCopy
, 0);
689 #endif /* not TARGET_API_MAC_CARBON */
690 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
693 #endif /* !USE_CG_DRAWING */
696 /* Mac replacement for XCreateBitmapFromBitmapData. */
699 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
704 static const unsigned char swap_nibble
[16]
705 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
706 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
707 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
708 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
712 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
713 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
714 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
715 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
716 for (i
= 0; i
< h
; i
++)
718 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
719 for (j
= 0; j
< w1
; j
++)
721 /* Bitswap XBM bytes to match how Mac does things. */
722 unsigned char c
= *bits
++;
723 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
724 | (swap_nibble
[(c
>>4) & 0xf]));
728 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
733 mac_free_bitmap (bitmap
)
736 xfree (bitmap
->baseAddr
);
741 XCreatePixmap (display
, w
, width
, height
, depth
)
744 unsigned int width
, height
;
751 SetPortWindowPort (w
);
753 SetRect (&r
, 0, 0, width
, height
);
754 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
757 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
758 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
760 /* CreateCGImageFromPixMaps requires ARGB format. */
761 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
770 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
774 unsigned int width
, height
;
775 unsigned long fg
, bg
;
785 gc
= XCreateGC (display
, w
, 0, NULL
);
787 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
791 GetGWorld (&old_port
, &old_gdh
);
792 SetGWorld (pixmap
, NULL
);
793 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
794 XSetForeground (display
, gc
, fg
);
795 XSetBackground (display
, gc
, bg
);
796 RGBForeColor (GC_FORE_COLOR (gc
));
797 RGBBackColor (GC_BACK_COLOR (gc
));
798 LockPixels (GetGWorldPixMap (pixmap
));
799 #if TARGET_API_MAC_CARBON
800 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
801 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
802 #else /* not TARGET_API_MAC_CARBON */
803 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
804 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
805 #endif /* not TARGET_API_MAC_CARBON */
806 UnlockPixels (GetGWorldPixMap (pixmap
));
807 SetGWorld (old_port
, old_gdh
);
808 mac_free_bitmap (&bitmap
);
815 XFreePixmap (display
, pixmap
)
819 DisposeGWorld (pixmap
);
823 /* Mac replacement for XFillRectangle. */
826 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
830 unsigned int width
, height
;
833 CGContextRef context
;
835 context
= mac_begin_cg_clip (f
, gc
);
836 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
837 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
842 mac_begin_clip (f
, gc
);
843 RGBForeColor (GC_FORE_COLOR (gc
));
844 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
845 PaintRect (&r
); /* using foreground color of gc */
851 /* Mac replacement for XDrawRectangle: dest is a window. */
854 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
858 unsigned int width
, height
;
861 CGContextRef context
;
863 context
= mac_begin_cg_clip (f
, gc
);
864 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context
, gc
);
865 CGContextStrokeRect (context
,
866 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
871 mac_begin_clip (f
, gc
);
872 RGBForeColor (GC_FORE_COLOR (gc
));
873 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
874 FrameRect (&r
); /* using foreground color of gc */
881 mac_invert_rectangle (f
, x
, y
, width
, height
)
884 unsigned int width
, height
;
889 mac_prepare_for_quickdraw (f
);
891 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
893 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
901 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
902 ConstUniCharArrayPtr text
;
903 UniCharCount text_length
;
905 ATSUTextLayout
*text_layout
;
908 static ATSUTextLayout saved_text_layout
= NULL
;
910 if (saved_text_layout
== NULL
)
912 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
913 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
914 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
915 static ATSLineLayoutOptions line_layout
=
916 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
917 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
918 | kATSLineUseQDRendering
920 kATSLineIsDisplayOnly
| kATSLineFractDisable
923 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
925 err
= ATSUCreateTextLayoutWithTextPtr (text
,
926 kATSUFromTextBeginning
,
932 err
= ATSUSetLayoutControls (saved_text_layout
,
933 sizeof (tags
) / sizeof (tags
[0]),
934 tags
, sizes
, values
);
936 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
940 err
= ATSUSetRunStyle (saved_text_layout
, style
,
941 kATSUFromTextBeginning
, kATSUToTextEnd
);
943 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
944 kATSUFromTextBeginning
,
950 *text_layout
= saved_text_layout
;
956 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
957 overstrike_p
, bytes_per_char
)
962 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
965 ATSUTextLayout text_layout
;
967 xassert (bytes_per_char
== 2);
969 #ifndef WORDS_BIG_ENDIAN
972 UniChar
*text
= (UniChar
*)buf
;
974 for (i
= 0; i
< nchars
; i
++)
975 text
[i
] = EndianU16_BtoN (text
[i
]);
978 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
980 GC_FONT (gc
)->mac_style
,
985 if (!mac_use_core_graphics
)
988 mac_begin_clip (f
, gc
);
989 RGBForeColor (GC_FORE_COLOR (gc
));
994 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
995 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
996 RGBBackColor (GC_BACK_COLOR (gc
));
998 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1001 ATSUDrawText (text_layout
,
1002 kATSUFromTextBeginning
, kATSUToTextEnd
,
1003 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1007 ATSUDrawText (text_layout
,
1008 kATSUFromTextBeginning
, kATSUToTextEnd
,
1009 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
1016 static CGContextRef context
;
1017 float port_height
= FRAME_PIXEL_HEIGHT (f
);
1018 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
1019 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
1020 static const ATSUAttributeValuePtr values
[] = {&context
};
1023 context
= mac_begin_cg_clip (f
, gc
);
1028 QDBeginCGContext (port
, &context
);
1029 if (gc
->n_clip_rects
|| bg_width
)
1031 CGContextTranslateCTM (context
, 0, port_height
);
1032 CGContextScaleCTM (context
, 1, -1);
1033 if (gc
->n_clip_rects
)
1034 CGContextClipToRects (context
, gc
->clip_rects
,
1039 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1040 CGContextFillRect (context
,
1041 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
1043 FONT_HEIGHT (GC_FONT (gc
))));
1045 CGContextScaleCTM (context
, 1, -1);
1046 CGContextTranslateCTM (context
, 0, -port_height
);
1050 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1051 err
= ATSUSetLayoutControls (text_layout
,
1052 sizeof (tags
) / sizeof (tags
[0]),
1053 tags
, sizes
, values
);
1056 ATSUDrawText (text_layout
,
1057 kATSUFromTextBeginning
, kATSUToTextEnd
,
1058 Long2Fix (x
), Long2Fix (port_height
- y
));
1060 ATSUDrawText (text_layout
,
1061 kATSUFromTextBeginning
, kATSUToTextEnd
,
1062 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1065 mac_end_cg_clip (f
);
1068 CGContextSynchronize (context
);
1069 QDEndCGContext (port
, &context
);
1072 /* This doesn't work on Mac OS X 10.1. */
1073 ATSUClearLayoutControls (text_layout
,
1074 sizeof (tags
) / sizeof (tags
[0]), tags
);
1076 ATSUSetLayoutControls (text_layout
,
1077 sizeof (tags
) / sizeof (tags
[0]),
1078 tags
, sizes
, values
);
1081 #endif /* MAC_OSX */
1083 #endif /* USE_ATSUI */
1087 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1088 overstrike_p
, bytes_per_char
)
1093 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1095 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1099 mac_begin_clip (f
, gc
);
1100 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1101 if (mac_use_core_graphics
)
1102 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1104 RGBForeColor (GC_FORE_COLOR (gc
));
1108 RGBBackColor (GC_BACK_COLOR (gc
));
1114 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1116 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1117 into an offscreen graphics world first. So performance gain
1118 cannot be expected.)
1119 - It lowers rendering quality.
1120 - Some fonts leave garbage on cursor movement. */
1125 RGBBackColor (GC_BACK_COLOR (gc
));
1126 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1127 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1132 TextFont (GC_FONT (gc
)->mac_fontnum
);
1133 TextSize (GC_FONT (gc
)->mac_fontsize
);
1134 TextFace (GC_FONT (gc
)->mac_fontface
);
1136 DrawText (buf
, 0, nchars
* bytes_per_char
);
1141 DrawText (buf
, 0, nchars
* bytes_per_char
);
1144 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1147 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1148 if (mac_use_core_graphics
)
1149 SwapQDTextFlags(savedFlags
);
1155 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1156 overstrike_p
, bytes_per_char
)
1161 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
1164 if (GC_FONT (gc
)->mac_style
)
1165 mac_draw_image_string_atsui (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1166 overstrike_p
, bytes_per_char
);
1168 #endif /* USE_ATSUI */
1169 mac_draw_image_string_qd (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1170 overstrike_p
, bytes_per_char
);
1174 /* Mac replacement for XDrawImageString. */
1177 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1182 int nchars
, bg_width
, overstrike_p
;
1184 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1189 /* Mac replacement for XDrawImageString16. */
1192 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1197 int nchars
, bg_width
, overstrike_p
;
1199 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1204 /* Mac replacement for XQueryTextExtents, but takes a character. If
1205 STYLE is NULL, measurement is done by QuickDraw Text routines for
1206 the font of the current graphics port. If CG_GLYPH is not NULL,
1207 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1210 mac_query_char_extents (style
, c
,
1211 font_ascent_return
, font_descent_return
,
1212 overall_return
, cg_glyph
)
1219 int *font_ascent_return
, *font_descent_return
;
1220 XCharStruct
*overall_return
;
1221 #if USE_CG_TEXT_DRAWING
1227 OSStatus err
= noErr
;
1234 ATSUTextLayout text_layout
;
1237 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1239 && (font_ascent_return
|| font_descent_return
|| overall_return
))
1241 ATSTrapezoid glyph_bounds
;
1243 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1244 kATSUFromTextBeginning
, kATSUToTextEnd
,
1245 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1246 kATSUseFractionalOrigins
,
1248 kATSUseDeviceOrigins
,
1250 1, &glyph_bounds
, NULL
);
1253 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1254 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1256 width
= Fix2Long (glyph_bounds
.upperRight
.x
1257 - glyph_bounds
.upperLeft
.x
);
1258 if (font_ascent_return
)
1259 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1260 if (font_descent_return
)
1261 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1264 if (err
== noErr
&& overall_return
)
1266 err
= ATSUMeasureTextImage (text_layout
,
1267 kATSUFromTextBeginning
, kATSUToTextEnd
,
1268 0, 0, &char_bounds
);
1270 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1271 #if USE_CG_TEXT_DRAWING
1272 if (err
== noErr
&& cg_glyph
)
1275 ATSUGlyphInfoArray glyph_info_array
;
1276 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1278 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1279 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1281 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1282 kATSUToTextEnd
, &count
,
1285 /* Make sure that we don't have to make layout
1287 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1288 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1289 && glyph_info_array
.glyphs
[0].screenX
== 0)
1291 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1292 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1303 if (font_ascent_return
|| font_descent_return
)
1307 GetFontInfo (&font_info
);
1308 if (font_ascent_return
)
1309 *font_ascent_return
= font_info
.ascent
;
1310 if (font_descent_return
)
1311 *font_descent_return
= font_info
.descent
;
1317 width
= CharWidth (ch
);
1318 QDTextBounds (1, &ch
, &char_bounds
);
1319 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1327 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1330 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1331 XFontStruct
*font_struct
;
1334 XCharStruct
*overall_return
;
1337 short width
= 0, lbearing
= 0, rbearing
= 0;
1340 for (i
= 0; i
< nchars
; i
++)
1342 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1344 width
+= FONT_WIDTH (font_struct
);
1347 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1348 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1349 width
+= pcm
->width
;
1354 overall_return
->lbearing
= lbearing
;
1355 overall_return
->rbearing
= rbearing
;
1356 overall_return
->width
= width
;
1358 /* What's the meaning of the return value of XTextExtents16? */
1362 #if USE_CG_TEXT_DRAWING
1363 static int cg_text_anti_aliasing_threshold
= 8;
1366 init_cg_text_anti_aliasing_threshold ()
1372 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1373 kCFPreferencesCurrentApplication
,
1376 cg_text_anti_aliasing_threshold
= threshold
;
1380 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1385 int nchars
, bg_width
, overstrike_p
;
1387 float port_height
, gx
, gy
;
1389 CGContextRef context
;
1393 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1396 port_height
= FRAME_PIXEL_HEIGHT (f
);
1398 gy
= port_height
- y
;
1399 glyphs
= (CGGlyph
*)buf
;
1400 advances
= alloca (sizeof (CGSize
) * nchars
);
1401 if (advances
== NULL
)
1403 for (i
= 0; i
< nchars
; i
++)
1405 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1407 advances
[i
].width
= pcm
->width
;
1408 advances
[i
].height
= 0;
1409 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1414 context
= mac_begin_cg_clip (f
, gc
);
1416 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1417 if (gc
->n_clip_rects
|| bg_width
)
1419 CGContextTranslateCTM (context
, 0, port_height
);
1420 CGContextScaleCTM (context
, 1, -1);
1421 if (gc
->n_clip_rects
)
1422 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1426 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context
, gc
);
1429 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1430 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1432 CGContextScaleCTM (context
, 1, -1);
1433 CGContextTranslateCTM (context
, 0, -port_height
);
1437 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context
, gc
);
1438 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1439 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1440 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1441 CGContextSetShouldAntialias (context
, false);
1442 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1443 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1444 if (CGContextShowGlyphsWithAdvances
!= NULL
)
1447 CGContextSetTextPosition (context
, gx
, gy
);
1448 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1451 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1452 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1455 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1456 else /* CGContextShowGlyphsWithAdvances == NULL */
1458 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1459 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1461 for (i
= 0; i
< nchars
; i
++)
1463 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1465 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1466 gx
+= advances
[i
].width
;
1471 mac_end_cg_clip (f
);
1473 CGContextSynchronize (context
);
1474 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1483 /* Mac replacement for XCopyArea: dest must be window. */
1486 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1491 unsigned int width
, height
;
1496 mac_begin_clip (f
, gc
);
1498 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1499 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1501 ForeColor (blackColor
);
1502 BackColor (whiteColor
);
1504 LockPixels (GetGWorldPixMap (src
));
1505 #if TARGET_API_MAC_CARBON
1510 LockPortBits (port
);
1511 CopyBits (GetPortBitMapForCopyBits (src
),
1512 GetPortBitMapForCopyBits (port
),
1513 &src_r
, &dest_r
, srcCopy
, 0);
1514 UnlockPortBits (port
);
1516 #else /* not TARGET_API_MAC_CARBON */
1517 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1518 &src_r
, &dest_r
, srcCopy
, 0);
1519 #endif /* not TARGET_API_MAC_CARBON */
1520 UnlockPixels (GetGWorldPixMap (src
));
1522 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1529 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1530 width
, height
, dest_x
, dest_y
)
1535 unsigned int width
, height
;
1540 mac_begin_clip (f
, gc
);
1542 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1543 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1545 ForeColor (blackColor
);
1546 BackColor (whiteColor
);
1548 LockPixels (GetGWorldPixMap (src
));
1549 LockPixels (GetGWorldPixMap (mask
));
1550 #if TARGET_API_MAC_CARBON
1555 LockPortBits (port
);
1556 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1557 GetPortBitMapForCopyBits (port
),
1558 &src_r
, &src_r
, &dest_r
);
1559 UnlockPortBits (port
);
1561 #else /* not TARGET_API_MAC_CARBON */
1562 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1563 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1564 #endif /* not TARGET_API_MAC_CARBON */
1565 UnlockPixels (GetGWorldPixMap (mask
));
1566 UnlockPixels (GetGWorldPixMap (src
));
1568 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1572 #endif /* !USE_CG_DRAWING */
1575 /* Mac replacement for XCopyArea: used only for scrolling. */
1578 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1582 unsigned int width
, height
;
1585 #if TARGET_API_MAC_CARBON
1587 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1589 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1591 mac_prepare_for_quickdraw (f
);
1593 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1594 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1595 kScrollWindowNoOptions
, dummy
);
1597 #else /* not TARGET_API_MAC_CARBON */
1599 WindowRef w
= FRAME_MAC_WINDOW (f
);
1601 mac_begin_clip (f
, gc
);
1603 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1604 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1606 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1607 color mapping in CopyBits. Otherwise, it will be slow. */
1608 ForeColor (blackColor
);
1609 BackColor (whiteColor
);
1610 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1612 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1615 #endif /* not TARGET_API_MAC_CARBON */
1619 /* Mac replacement for XChangeGC. */
1622 XChangeGC (display
, gc
, mask
, xgcv
)
1628 if (mask
& GCForeground
)
1629 XSetForeground (display
, gc
, xgcv
->foreground
);
1630 if (mask
& GCBackground
)
1631 XSetBackground (display
, gc
, xgcv
->background
);
1633 XSetFont (display
, gc
, xgcv
->font
);
1637 /* Mac replacement for XCreateGC. */
1640 XCreateGC (display
, d
, mask
, xgcv
)
1646 GC gc
= xmalloc (sizeof (*gc
));
1648 bzero (gc
, sizeof (*gc
));
1649 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1650 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1651 if (CGColorGetTypeID
!= NULL
)
1654 gc
->cg_fore_color
= gc
->cg_back_color
= mac_cg_color_black
;
1655 CGColorRetain (gc
->cg_fore_color
);
1656 CGColorRetain (gc
->cg_back_color
);
1659 XChangeGC (display
, gc
, mask
, xgcv
);
1665 /* Used in xfaces.c. */
1668 XFreeGC (display
, gc
)
1672 if (gc
->clip_region
)
1673 DisposeRgn (gc
->clip_region
);
1674 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1675 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1676 if (CGColorGetTypeID
!= NULL
)
1679 CGColorRelease (gc
->cg_fore_color
);
1680 CGColorRelease (gc
->cg_back_color
);
1687 /* Mac replacement for XGetGCValues. */
1690 XGetGCValues (display
, gc
, mask
, xgcv
)
1696 if (mask
& GCForeground
)
1697 xgcv
->foreground
= gc
->xgcv
.foreground
;
1698 if (mask
& GCBackground
)
1699 xgcv
->background
= gc
->xgcv
.background
;
1701 xgcv
->font
= gc
->xgcv
.font
;
1705 /* Mac replacement for XSetForeground. */
1708 XSetForeground (display
, gc
, color
)
1711 unsigned long color
;
1713 if (gc
->xgcv
.foreground
!= color
)
1715 gc
->xgcv
.foreground
= color
;
1716 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1717 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1718 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1719 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1720 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1721 if (CGColorGetTypeID
!= NULL
)
1724 CGColorRelease (gc
->cg_fore_color
);
1727 gc
->cg_fore_color
= mac_cg_color_black
;
1728 CGColorRetain (gc
->cg_fore_color
);
1734 rgba
[0] = gc
->fore_color
.red
/ 65535.0f
;
1735 rgba
[1] = gc
->fore_color
.green
/ 65535.0f
;
1736 rgba
[2] = gc
->fore_color
.blue
/ 65535.0f
;
1738 gc
->cg_fore_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1746 /* Mac replacement for XSetBackground. */
1749 XSetBackground (display
, gc
, color
)
1752 unsigned long color
;
1754 if (gc
->xgcv
.background
!= color
)
1756 gc
->xgcv
.background
= color
;
1757 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1758 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1759 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1760 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1761 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1762 if (CGColorGetTypeID
!= NULL
)
1765 CGColorRelease (gc
->cg_back_color
);
1768 gc
->cg_back_color
= mac_cg_color_black
;
1769 CGColorRetain (gc
->cg_back_color
);
1775 rgba
[0] = gc
->back_color
.red
/ 65535.0f
;
1776 rgba
[1] = gc
->back_color
.green
/ 65535.0f
;
1777 rgba
[2] = gc
->back_color
.blue
/ 65535.0f
;
1779 gc
->cg_back_color
= CGColorCreate (mac_cg_color_space_rgb
, rgba
);
1787 /* Mac replacement for XSetFont. */
1790 XSetFont (display
, gc
, font
)
1795 gc
->xgcv
.font
= font
;
1799 /* Mac replacement for XSetClipRectangles. */
1802 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1810 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1812 gc
->n_clip_rects
= n
;
1815 if (gc
->clip_region
== NULL
)
1816 gc
->clip_region
= NewRgn ();
1817 RectRgn (gc
->clip_region
, rectangles
);
1820 RgnHandle region
= NewRgn ();
1822 for (i
= 1; i
< n
; i
++)
1824 RectRgn (region
, rectangles
+ i
);
1825 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1827 DisposeRgn (region
);
1830 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1831 for (i
= 0; i
< n
; i
++)
1833 Rect
*rect
= rectangles
+ i
;
1835 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1836 rect
->right
- rect
->left
,
1837 rect
->bottom
- rect
->top
);
1843 /* Mac replacement for XSetClipMask. */
1846 mac_reset_clip_rectangles (display
, gc
)
1850 gc
->n_clip_rects
= 0;
1854 /* Mac replacement for XSetWindowBackground. */
1857 XSetWindowBackground (display
, w
, color
)
1860 unsigned long color
;
1862 #if !TARGET_API_MAC_CARBON
1863 AuxWinHandle aw_handle
;
1864 CTabHandle ctab_handle
;
1865 ColorSpecPtr ct_table
;
1870 bg_color
.red
= RED16_FROM_ULONG (color
);
1871 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1872 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1874 #if TARGET_API_MAC_CARBON
1875 SetWindowContentColor (w
, &bg_color
);
1877 if (GetAuxWin (w
, &aw_handle
))
1879 ctab_handle
= (*aw_handle
)->awCTable
;
1880 HandToHand ((Handle
*) &ctab_handle
);
1881 ct_table
= (*ctab_handle
)->ctTable
;
1882 ct_size
= (*ctab_handle
)->ctSize
;
1883 while (ct_size
> -1)
1885 if (ct_table
->value
== 0)
1887 ct_table
->rgb
= bg_color
;
1888 CTabChanged (ctab_handle
);
1889 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1897 /* Flush display of frame F, or of all frames if F is null. */
1903 #if TARGET_API_MAC_CARBON
1906 mac_prepare_for_quickdraw (f
);
1909 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1911 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1917 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1918 Calls to XFlush should be unnecessary because the X output buffer
1919 is flushed automatically as needed by calls to XPending,
1920 XNextEvent, or XWindowEvent according to the XFlush man page.
1921 XTread_socket calls XPending. Removing XFlush improves
1924 #define XFlush(DISPLAY) (void) 0
1928 mac_flush_display_optional (f
)
1932 mac_prepare_for_quickdraw (f
);
1937 /***********************************************************************
1938 Starting and ending an update
1939 ***********************************************************************/
1941 /* Start an update of frame F. This function is installed as a hook
1942 for update_begin, i.e. it is called when update_begin is called.
1943 This function is called prior to calls to x_update_window_begin for
1944 each window being updated. */
1950 #if TARGET_API_MAC_CARBON
1951 /* During update of a frame, availability of input events is
1952 periodically checked with ReceiveNextEvent if
1953 redisplay-dont-pause is nil. That normally flushes window buffer
1954 changes for every check, and thus screen update looks waving even
1955 if no input is available. So we disable screen updates during
1956 update of a frame. */
1958 DisableScreenUpdates ();
1964 /* Start update of window W. Set the global variable updated_window
1965 to the window being updated and set output_cursor to the cursor
1969 x_update_window_begin (w
)
1972 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1973 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1976 set_output_cursor (&w
->cursor
);
1980 if (f
== display_info
->mouse_face_mouse_frame
)
1982 /* Don't do highlighting for mouse motion during the update. */
1983 display_info
->mouse_face_defer
= 1;
1985 /* If F needs to be redrawn, simply forget about any prior mouse
1987 if (FRAME_GARBAGED_P (f
))
1988 display_info
->mouse_face_window
= Qnil
;
1990 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1991 their mouse_face_p flag set, which means that they are always
1992 unequal to rows in a desired matrix which never have that
1993 flag set. So, rows containing mouse-face glyphs are never
1994 scrolled, and we don't have to switch the mouse highlight off
1995 here to prevent it from being scrolled. */
1997 /* Can we tell that this update does not affect the window
1998 where the mouse highlight is? If so, no need to turn off.
1999 Likewise, don't do anything if the frame is garbaged;
2000 in that case, the frame's current matrix that we would use
2001 is all wrong, and we will redisplay that line anyway. */
2002 if (!NILP (display_info
->mouse_face_window
)
2003 && w
== XWINDOW (display_info
->mouse_face_window
))
2007 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
2008 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
2011 if (i
< w
->desired_matrix
->nrows
)
2012 clear_mouse_face (display_info
);
2021 /* Draw a vertical window border from (x,y0) to (x,y1) */
2024 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
2028 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2031 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
2033 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
2036 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
2039 /* End update of window W (which is equal to updated_window).
2041 Draw vertical borders between horizontally adjacent windows, and
2042 display W's cursor if CURSOR_ON_P is non-zero.
2044 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2045 glyphs in mouse-face were overwritten. In that case we have to
2046 make sure that the mouse-highlight is properly redrawn.
2048 W may be a menu bar pseudo-window in case we don't have X toolkit
2049 support. Such windows don't have a cursor, so don't display it
2053 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
2055 int cursor_on_p
, mouse_face_overwritten_p
;
2057 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
2059 if (!w
->pseudo_window_p
)
2064 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
2066 output_cursor
.x
, output_cursor
.y
);
2068 if (draw_window_fringes (w
, 1))
2069 x_draw_vertical_border (w
);
2074 /* If a row with mouse-face was overwritten, arrange for
2075 XTframe_up_to_date to redisplay the mouse highlight. */
2076 if (mouse_face_overwritten_p
)
2078 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2079 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2080 dpyinfo
->mouse_face_window
= Qnil
;
2083 updated_window
= NULL
;
2087 /* End update of frame F. This function is installed as a hook in
2094 /* Mouse highlight may be displayed again. */
2095 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
2098 #if TARGET_API_MAC_CARBON
2099 EnableScreenUpdates ();
2101 XFlush (FRAME_MAC_DISPLAY (f
));
2106 /* This function is called from various places in xdisp.c whenever a
2107 complete update has been performed. The global variable
2108 updated_window is not available here. */
2111 XTframe_up_to_date (f
)
2114 if (FRAME_MAC_P (f
))
2116 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2118 if (dpyinfo
->mouse_face_deferred_gc
2119 || f
== dpyinfo
->mouse_face_mouse_frame
)
2122 if (dpyinfo
->mouse_face_mouse_frame
)
2123 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
2124 dpyinfo
->mouse_face_mouse_x
,
2125 dpyinfo
->mouse_face_mouse_y
);
2126 dpyinfo
->mouse_face_deferred_gc
= 0;
2133 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2134 arrow bitmaps, or clear the fringes if no bitmaps are required
2135 before DESIRED_ROW is made current. The window being updated is
2136 found in updated_window. This function is called from
2137 update_window_line only if it is known that there are differences
2138 between bitmaps to be drawn between current row and DESIRED_ROW. */
2141 x_after_update_window_line (desired_row
)
2142 struct glyph_row
*desired_row
;
2144 struct window
*w
= updated_window
;
2150 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2151 desired_row
->redraw_fringe_bitmaps_p
= 1;
2153 /* When a window has disappeared, make sure that no rest of
2154 full-width rows stays visible in the internal border. Could
2155 check here if updated_window is the leftmost/rightmost window,
2156 but I guess it's not worth doing since vertically split windows
2157 are almost never used, internal border is rarely set, and the
2158 overhead is very small. */
2159 if (windows_or_buffers_changed
2160 && desired_row
->full_width_p
2161 && (f
= XFRAME (w
->frame
),
2162 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2164 && (height
= desired_row
->visible_height
,
2167 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2169 /* Internal border is drawn below the tool bar. */
2170 if (WINDOWP (f
->tool_bar_window
)
2171 && w
== XWINDOW (f
->tool_bar_window
))
2175 mac_clear_area (f
, 0, y
, width
, height
);
2176 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2182 /* Draw the bitmap WHICH in one of the left or right fringes of
2183 window W. ROW is the glyph row for which to display the bitmap; it
2184 determines the vertical position at which the bitmap has to be
2188 x_draw_fringe_bitmap (w
, row
, p
)
2190 struct glyph_row
*row
;
2191 struct draw_fringe_bitmap_params
*p
;
2193 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2194 Display
*display
= FRAME_MAC_DISPLAY (f
);
2195 struct face
*face
= p
->face
;
2197 int overlay_p
= p
->overlay_p
;
2202 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2204 #if 0 /* MAC_TODO: stipple */
2205 /* In case the same realized face is used for fringes and
2206 for something displayed in the text (e.g. face `region' on
2207 mono-displays, the fill style may have been changed to
2208 FillSolid in x_draw_glyph_string_background. */
2210 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2212 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2215 /* If the fringe is adjacent to the left (right) scroll bar of a
2216 leftmost (rightmost, respectively) window, then extend its
2217 background to the gap between the fringe and the bar. */
2218 if ((WINDOW_LEFTMOST_P (w
)
2219 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
2220 || (WINDOW_RIGHTMOST_P (w
)
2221 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
2223 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
2227 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
2228 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
2229 * FRAME_COLUMN_WIDTH (f
));
2232 && (left
+ width
== p
->x
2233 || p
->x
+ p
->wd
== left
))
2235 /* Bitmap fills the fringe and we need background
2237 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
2241 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
2243 ny
= row
->visible_height
;
2248 if (left
+ width
== bx
)
2250 bx
= left
+ sb_width
;
2251 nx
+= width
- sb_width
;
2253 else if (bx
+ nx
== left
)
2254 nx
+= width
- sb_width
;
2261 mac_erase_rectangle (f
, face
->gc
, bx
, by
, nx
, ny
);
2262 /* The fringe background has already been filled. */
2266 #if 0 /* MAC_TODO: stipple */
2268 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2271 #endif /* MAC_OSX */
2273 /* Must clip because of partially visible lines. */
2274 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2277 /* Adjust position of "bottom aligned" bitmap on partially
2278 visible last row. */
2280 int oldVH
= row
->visible_height
;
2281 row
->visible_height
= p
->h
;
2282 row
->y
-= rowY
- p
->y
;
2283 x_clip_to_row (w
, row
, -1, face
->gc
);
2285 row
->visible_height
= oldVH
;
2288 x_clip_to_row (w
, row
, -1, face
->gc
);
2291 if (p
->bx
>= 0 && !p
->overlay_p
)
2293 #if 0 /* MAC_TODO: stipple */
2294 /* In case the same realized face is used for fringes and
2295 for something displayed in the text (e.g. face `region' on
2296 mono-displays, the fill style may have been changed to
2297 FillSolid in x_draw_glyph_string_background. */
2299 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2301 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2304 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2306 #if 0 /* MAC_TODO: stipple */
2308 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2311 #endif /* !MAC_OSX */
2315 && p
->which
< max_fringe_bmp
2321 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2322 XSetForeground (display
, face
->gc
,
2324 ? (p
->overlay_p
? face
->background
2325 : f
->output_data
.mac
->cursor_pixel
)
2326 : face
->foreground
));
2328 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2329 p
->wd
, p
->h
, p
->x
, p
->y
, overlay_p
);
2331 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2332 p
->wd
, p
->h
, p
->bits
+ p
->dh
, overlay_p
);
2334 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2337 mac_reset_clip_rectangles (display
, face
->gc
);
2342 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2344 unsigned short *bits
;
2348 CGDataProviderRef provider
;
2350 if (which
>= max_fringe_bmp
)
2353 max_fringe_bmp
= which
+ 20;
2354 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2355 while (i
< max_fringe_bmp
)
2356 fringe_bmp
[i
++] = 0;
2359 for (i
= 0; i
< h
; i
++)
2361 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2362 sizeof (unsigned short) * h
, NULL
);
2365 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2366 sizeof (unsigned short),
2368 CGDataProviderRelease (provider
);
2373 mac_destroy_fringe_bitmap (which
)
2376 if (which
>= max_fringe_bmp
)
2379 if (fringe_bmp
[which
])
2380 CGImageRelease (fringe_bmp
[which
]);
2381 fringe_bmp
[which
] = 0;
2386 /* This is called when starting Emacs and when restarting after
2387 suspend. When starting Emacs, no window is mapped. And nothing
2388 must be done to Emacs's own window if it is suspended (though that
2392 XTset_terminal_modes ()
2396 /* This is called when exiting or suspending Emacs. Exiting will make
2397 the windows go away, and suspending requires no action. */
2400 XTreset_terminal_modes ()
2406 /***********************************************************************
2408 ***********************************************************************/
2410 /* Function prototypes of this page. */
2412 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2413 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2417 pcm_init (pcm
, count
)
2421 bzero (pcm
, sizeof (XCharStruct
) * count
);
2422 while (--count
>= 0)
2424 pcm
->descent
= PCM_INVALID
;
2429 static enum pcm_status
2430 pcm_get_status (pcm
)
2431 const XCharStruct
*pcm
;
2433 int height
= pcm
->ascent
+ pcm
->descent
;
2435 /* Negative height means some special status. */
2436 return height
>= 0 ? PCM_VALID
: height
;
2439 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2440 is not contained in the font. */
2442 static INLINE XCharStruct
*
2443 x_per_char_metric (font
, char2b
)
2447 /* The result metric information. */
2448 XCharStruct
*pcm
= NULL
;
2450 xassert (font
&& char2b
);
2453 if (font
->mac_style
)
2455 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2459 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2460 pcm_init (*row
, 0x100);
2462 pcm
= *row
+ char2b
->byte2
;
2463 if (pcm_get_status (pcm
) != PCM_VALID
)
2466 mac_query_char_extents (font
->mac_style
,
2467 (char2b
->byte1
<< 8) + char2b
->byte2
,
2468 NULL
, NULL
, pcm
, NULL
);
2475 if (font
->bounds
.per_char
!= NULL
)
2477 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2479 /* min_char_or_byte2 specifies the linear character index
2480 corresponding to the first element of the per_char array,
2481 max_char_or_byte2 is the index of the last character. A
2482 character with non-zero CHAR2B->byte1 is not in the font.
2483 A character with byte2 less than min_char_or_byte2 or
2484 greater max_char_or_byte2 is not in the font. */
2485 if (char2b
->byte1
== 0
2486 && char2b
->byte2
>= font
->min_char_or_byte2
2487 && char2b
->byte2
<= font
->max_char_or_byte2
)
2488 pcm
= font
->bounds
.per_char
2489 + (char2b
->byte2
- font
->min_char_or_byte2
);
2493 /* If either min_byte1 or max_byte1 are nonzero, both
2494 min_char_or_byte2 and max_char_or_byte2 are less than
2495 256, and the 2-byte character index values corresponding
2496 to the per_char array element N (counting from 0) are:
2498 byte1 = N/D + min_byte1
2499 byte2 = N\D + min_char_or_byte2
2503 D = max_char_or_byte2 - min_char_or_byte2 + 1
2504 / = integer division
2505 \ = integer modulus */
2506 if (char2b
->byte1
>= font
->min_byte1
2507 && char2b
->byte1
<= font
->max_byte1
2508 && char2b
->byte2
>= font
->min_char_or_byte2
2509 && char2b
->byte2
<= font
->max_char_or_byte2
)
2511 pcm
= (font
->bounds
.per_char
2512 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2513 * (char2b
->byte1
- font
->min_byte1
))
2514 + (char2b
->byte2
- font
->min_char_or_byte2
));
2520 /* If the per_char pointer is null, all glyphs between the first
2521 and last character indexes inclusive have the same
2522 information, as given by both min_bounds and max_bounds. */
2523 if (char2b
->byte2
>= font
->min_char_or_byte2
2524 && char2b
->byte2
<= font
->max_char_or_byte2
)
2525 pcm
= &font
->max_bounds
;
2531 return ((pcm
== NULL
2533 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2534 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2543 static XCharStruct
*
2544 mac_per_char_metric (font
, char2b
, font_type
)
2549 return x_per_char_metric (font
, char2b
);
2553 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2554 the two-byte form of C. Encoding is returned in *CHAR2B. */
2557 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2560 struct font_info
*font_info
;
2563 int charset
= CHAR_CHARSET (c
);
2564 XFontStruct
*font
= font_info
->font
;
2566 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2567 This may be either a program in a special encoder language or a
2569 if (font_info
->font_encoder
)
2571 /* It's a program. */
2572 struct ccl_program
*ccl
= font_info
->font_encoder
;
2574 check_ccl_update (ccl
);
2575 if (CHARSET_DIMENSION (charset
) == 1)
2577 ccl
->reg
[0] = charset
;
2578 ccl
->reg
[1] = char2b
->byte2
;
2583 ccl
->reg
[0] = charset
;
2584 ccl
->reg
[1] = char2b
->byte1
;
2585 ccl
->reg
[2] = char2b
->byte2
;
2588 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2590 /* We assume that MSBs are appropriately set/reset by CCL
2592 if (font
->max_byte1
== 0) /* 1-byte font */
2593 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2595 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2597 else if (font_info
->encoding
[charset
])
2599 /* Fixed encoding scheme. See fontset.h for the meaning of the
2600 encoding numbers. */
2601 int enc
= font_info
->encoding
[charset
];
2603 if ((enc
== 1 || enc
== 2)
2604 && CHARSET_DIMENSION (charset
) == 2)
2605 char2b
->byte1
|= 0x80;
2607 if (enc
== 1 || enc
== 3)
2608 char2b
->byte2
|= 0x80;
2614 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2615 char2b
->byte1
= sjis1
;
2616 char2b
->byte2
= sjis2
;
2621 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2623 return FONT_TYPE_UNKNOWN
;
2628 /***********************************************************************
2630 ***********************************************************************/
2634 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2635 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2636 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2638 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2639 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2640 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2641 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2642 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2643 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2644 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2645 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2646 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2647 unsigned long *, double, int));*/
2648 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2649 double, int, unsigned long));
2650 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2651 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2652 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2653 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2654 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2656 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2657 int, int, int, int, int, int,
2659 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2660 int, int, int, Rect
*));
2663 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2667 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2672 struct glyph_string
*s
;
2674 if (s
->font
== FRAME_FONT (s
->f
)
2675 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2676 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2678 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2681 /* Cursor on non-default face: must merge. */
2685 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2686 xgcv
.foreground
= s
->face
->background
;
2688 /* If the glyph would be invisible, try a different foreground. */
2689 if (xgcv
.foreground
== xgcv
.background
)
2690 xgcv
.foreground
= s
->face
->foreground
;
2691 if (xgcv
.foreground
== xgcv
.background
)
2692 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2693 if (xgcv
.foreground
== xgcv
.background
)
2694 xgcv
.foreground
= s
->face
->foreground
;
2696 /* Make sure the cursor is distinct from text in this face. */
2697 if (xgcv
.background
== s
->face
->background
2698 && xgcv
.foreground
== s
->face
->foreground
)
2700 xgcv
.background
= s
->face
->foreground
;
2701 xgcv
.foreground
= s
->face
->background
;
2704 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2705 xgcv
.font
= s
->font
;
2706 mask
= GCForeground
| GCBackground
| GCFont
;
2708 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2709 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2712 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2713 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2715 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2720 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2723 x_set_mouse_face_gc (s
)
2724 struct glyph_string
*s
;
2729 /* What face has to be used last for the mouse face? */
2730 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2731 face
= FACE_FROM_ID (s
->f
, face_id
);
2733 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2735 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2736 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2738 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2739 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2740 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2742 /* If font in this face is same as S->font, use it. */
2743 if (s
->font
== s
->face
->font
)
2744 s
->gc
= s
->face
->gc
;
2747 /* Otherwise construct scratch_cursor_gc with values from FACE
2752 xgcv
.background
= s
->face
->background
;
2753 xgcv
.foreground
= s
->face
->foreground
;
2754 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2755 xgcv
.font
= s
->font
;
2756 mask
= GCForeground
| GCBackground
| GCFont
;
2758 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2759 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2762 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2763 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2765 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2768 xassert (s
->gc
!= 0);
2772 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2773 Faces to use in the mode line have already been computed when the
2774 matrix was built, so there isn't much to do, here. */
2777 x_set_mode_line_face_gc (s
)
2778 struct glyph_string
*s
;
2780 s
->gc
= s
->face
->gc
;
2784 /* Set S->gc of glyph string S for drawing that glyph string. Set
2785 S->stippled_p to a non-zero value if the face of S has a stipple
2789 x_set_glyph_string_gc (s
)
2790 struct glyph_string
*s
;
2792 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2794 if (s
->hl
== DRAW_NORMAL_TEXT
)
2796 s
->gc
= s
->face
->gc
;
2797 s
->stippled_p
= s
->face
->stipple
!= 0;
2799 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2801 x_set_mode_line_face_gc (s
);
2802 s
->stippled_p
= s
->face
->stipple
!= 0;
2804 else if (s
->hl
== DRAW_CURSOR
)
2806 x_set_cursor_gc (s
);
2809 else if (s
->hl
== DRAW_MOUSE_FACE
)
2811 x_set_mouse_face_gc (s
);
2812 s
->stippled_p
= s
->face
->stipple
!= 0;
2814 else if (s
->hl
== DRAW_IMAGE_RAISED
2815 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2817 s
->gc
= s
->face
->gc
;
2818 s
->stippled_p
= s
->face
->stipple
!= 0;
2822 s
->gc
= s
->face
->gc
;
2823 s
->stippled_p
= s
->face
->stipple
!= 0;
2826 /* GC must have been set. */
2827 xassert (s
->gc
!= 0);
2831 /* Set clipping for output of glyph string S. S may be part of a mode
2832 line or menu if we don't have X toolkit support. */
2835 x_set_glyph_string_clipping (s
)
2836 struct glyph_string
*s
;
2838 Rect rects
[MAX_CLIP_RECTS
];
2841 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2842 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2847 Compute left and right overhang of glyph string S. If S is a glyph
2848 string for a composition, assume overhangs don't exist. */
2851 mac_compute_glyph_string_overhangs (s
)
2852 struct glyph_string
*s
;
2854 if (!(s
->cmp
== NULL
2855 && s
->first_glyph
->type
== CHAR_GLYPH
))
2860 || s
->font
->mac_style
2866 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2867 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2868 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2873 MacFontStruct
*font
= s
->font
;
2876 mac_prepare_for_quickdraw (s
->f
);
2878 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2880 TextFont (font
->mac_fontnum
);
2881 TextSize (font
->mac_fontsize
);
2882 TextFace (font
->mac_fontface
);
2884 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2886 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2887 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2892 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2895 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2896 struct glyph_string
*s
;
2899 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2903 /* Draw the background of glyph_string S. If S->background_filled_p
2904 is non-zero don't draw it. FORCE_P non-zero means draw the
2905 background even if it wouldn't be drawn normally. This is used
2906 when a string preceding S draws into the background of S, or S
2907 contains the first component of a composition. */
2910 x_draw_glyph_string_background (s
, force_p
)
2911 struct glyph_string
*s
;
2914 /* Nothing to do if background has already been drawn or if it
2915 shouldn't be drawn in the first place. */
2916 if (!s
->background_filled_p
)
2918 int box_line_width
= max (s
->face
->box_line_width
, 0);
2920 #if 0 /* MAC_TODO: stipple */
2923 /* Fill background with a stipple pattern. */
2924 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2925 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2926 s
->y
+ box_line_width
,
2927 s
->background_width
,
2928 s
->height
- 2 * box_line_width
);
2929 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2930 s
->background_filled_p
= 1;
2934 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2935 || s
->font_not_found_p
2936 || s
->extends_to_end_of_line_p
2939 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2940 s
->background_width
,
2941 s
->height
- 2 * box_line_width
);
2942 s
->background_filled_p
= 1;
2948 /* Draw the foreground of glyph string S. */
2951 x_draw_glyph_string_foreground (s
)
2952 struct glyph_string
*s
;
2956 /* If first glyph of S has a left box line, start drawing the text
2957 of S to the right of that box line. */
2958 if (s
->face
->box
!= FACE_NO_BOX
2959 && s
->first_glyph
->left_box_line_p
)
2960 x
= s
->x
+ abs (s
->face
->box_line_width
);
2964 /* Draw characters of S as rectangles if S's font could not be
2966 if (s
->font_not_found_p
)
2968 for (i
= 0; i
< s
->nchars
; ++i
)
2970 struct glyph
*g
= s
->first_glyph
+ i
;
2971 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2972 g
->pixel_width
- 1, s
->height
- 1);
2973 x
+= g
->pixel_width
;
2978 char *char1b
= (char *) s
->char2b
;
2979 int boff
= s
->font_info
->baseline_offset
;
2981 if (s
->font_info
->vertical_centering
)
2982 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2984 /* If we can use 8-bit functions, condense S->char2b. */
2987 && GC_FONT (s
->gc
)->mac_style
== NULL
2990 for (i
= 0; i
< s
->nchars
; ++i
)
2991 char1b
[i
] = s
->char2b
[i
].byte2
;
2993 /* Draw text with XDrawString if background has already been
2994 filled. Otherwise, use XDrawImageString. (Note that
2995 XDrawImageString is usually faster than XDrawString.) Always
2996 use XDrawImageString when drawing the cursor so that there is
2997 no chance that characters under a box cursor are invisible. */
2999 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3000 bg_width
= 0; /* Corresponds to XDrawString. */
3002 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
3006 || GC_FONT (s
->gc
)->mac_style
3009 #if USE_CG_TEXT_DRAWING
3011 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3012 s
->char2b
, s
->nchars
, bg_width
,
3013 s
->face
->overstrike
))
3017 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3018 s
->char2b
, s
->nchars
, bg_width
,
3019 s
->face
->overstrike
);
3021 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
3022 char1b
, s
->nchars
, bg_width
,
3023 s
->face
->overstrike
);
3027 /* Draw the foreground of composite glyph string S. */
3030 x_draw_composite_glyph_string_foreground (s
)
3031 struct glyph_string
*s
;
3035 /* If first glyph of S has a left box line, start drawing the text
3036 of S to the right of that box line. */
3037 if (s
->face
->box
!= FACE_NO_BOX
3038 && s
->first_glyph
->left_box_line_p
)
3039 x
= s
->x
+ abs (s
->face
->box_line_width
);
3043 /* S is a glyph string for a composition. S->gidx is the index of
3044 the first character drawn for glyphs of this composition.
3045 S->gidx == 0 means we are drawing the very first character of
3046 this composition. */
3048 /* Draw a rectangle for the composition if the font for the very
3049 first character of the composition could not be loaded. */
3050 if (s
->font_not_found_p
)
3053 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
3054 s
->width
- 1, s
->height
- 1);
3058 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3059 mac_draw_image_string_16 (s
->f
, s
->gc
,
3060 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3061 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3062 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
3067 #ifdef USE_X_TOOLKIT
3069 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3072 /* Return the frame on which widget WIDGET is used.. Abort if frame
3073 cannot be determined. */
3075 static struct frame
*
3076 x_frame_of_widget (widget
)
3079 struct x_display_info
*dpyinfo
;
3083 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3085 /* Find the top-level shell of the widget. Note that this function
3086 can be called when the widget is not yet realized, so XtWindow
3087 (widget) == 0. That's the reason we can't simply use
3088 x_any_window_to_frame. */
3089 while (!XtIsTopLevelShell (widget
))
3090 widget
= XtParent (widget
);
3092 /* Look for a frame with that top-level widget. Allocate the color
3093 on that frame to get the right gamma correction value. */
3094 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3095 if (GC_FRAMEP (XCAR (tail
))
3096 && (f
= XFRAME (XCAR (tail
)),
3097 (f
->output_data
.nothing
!= 1
3098 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3099 && f
->output_data
.x
->widget
== widget
)
3106 /* Allocate the color COLOR->pixel on the screen and display of
3107 widget WIDGET in colormap CMAP. If an exact match cannot be
3108 allocated, try the nearest color available. Value is non-zero
3109 if successful. This is called from lwlib. */
3112 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3117 struct frame
*f
= x_frame_of_widget (widget
);
3118 return x_alloc_nearest_color (f
, cmap
, color
);
3122 #endif /* USE_X_TOOLKIT */
3124 #if 0 /* MAC_TODO */
3126 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3127 CMAP. If an exact match can't be allocated, try the nearest color
3128 available. Value is non-zero if successful. Set *COLOR to the
3132 x_alloc_nearest_color (f
, cmap
, color
)
3137 Display
*display
= FRAME_X_DISPLAY (f
);
3138 Screen
*screen
= FRAME_X_SCREEN (f
);
3141 gamma_correct (f
, color
);
3142 rc
= XAllocColor (display
, cmap
, color
);
3145 /* If we got to this point, the colormap is full, so we're going
3146 to try to get the next closest color. The algorithm used is
3147 a least-squares matching, which is what X uses for closest
3148 color matching with StaticColor visuals. */
3150 unsigned long nearest_delta
= ~0;
3151 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3152 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3154 for (i
= 0; i
< ncells
; ++i
)
3156 XQueryColors (display
, cmap
, cells
, ncells
);
3158 for (nearest
= i
= 0; i
< ncells
; ++i
)
3160 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3161 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3162 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3163 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3165 if (delta
< nearest_delta
)
3168 nearest_delta
= delta
;
3172 color
->red
= cells
[nearest
].red
;
3173 color
->green
= cells
[nearest
].green
;
3174 color
->blue
= cells
[nearest
].blue
;
3175 rc
= XAllocColor (display
, cmap
, color
);
3178 #ifdef DEBUG_X_COLORS
3180 register_color (color
->pixel
);
3181 #endif /* DEBUG_X_COLORS */
3187 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3188 It's necessary to do this instead of just using PIXEL directly to
3189 get color reference counts right. */
3192 x_copy_color (f
, pixel
)
3194 unsigned long pixel
;
3198 color
.pixel
= pixel
;
3200 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3201 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3203 #ifdef DEBUG_X_COLORS
3204 register_color (pixel
);
3210 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3211 It's necessary to do this instead of just using PIXEL directly to
3212 get color reference counts right. */
3215 x_copy_dpy_color (dpy
, cmap
, pixel
)
3218 unsigned long pixel
;
3222 color
.pixel
= pixel
;
3224 XQueryColor (dpy
, cmap
, &color
);
3225 XAllocColor (dpy
, cmap
, &color
);
3227 #ifdef DEBUG_X_COLORS
3228 register_color (pixel
);
3233 #endif /* MAC_TODO */
3236 /* Brightness beyond which a color won't have its highlight brightness
3239 Nominally, highlight colors for `3d' faces are calculated by
3240 brightening an object's color by a constant scale factor, but this
3241 doesn't yield good results for dark colors, so for colors who's
3242 brightness is less than this value (on a scale of 0-255) have to
3243 use an additional additive factor.
3245 The value here is set so that the default menu-bar/mode-line color
3246 (grey75) will not have its highlights changed at all. */
3247 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3250 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3251 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3252 If this produces the same color as COLOR, try a color where all RGB
3253 values have DELTA added. Return the allocated color in *COLOR.
3254 DISPLAY is the X display, CMAP is the colormap to operate on.
3255 Value is non-zero if successful. */
3258 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3260 unsigned long *color
;
3267 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3270 /* Change RGB values by specified FACTOR. Avoid overflow! */
3271 xassert (factor
>= 0);
3272 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3273 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3274 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3276 /* Calculate brightness of COLOR. */
3277 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3278 + BLUE_FROM_ULONG (*color
)) / 6;
3280 /* We only boost colors that are darker than
3281 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3282 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3283 /* Make an additive adjustment to NEW, because it's dark enough so
3284 that scaling by FACTOR alone isn't enough. */
3286 /* How far below the limit this color is (0 - 1, 1 being darker). */
3287 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3288 /* The additive adjustment. */
3289 int min_delta
= delta
* dimness
* factor
/ 2;
3292 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3293 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3294 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3296 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3297 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3298 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3302 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3303 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3304 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3306 /* MAC_TODO: Map to palette and retry with delta if same? */
3307 /* MAC_TODO: Free colors (if using palette)? */
3318 /* Set up the foreground color for drawing relief lines of glyph
3319 string S. RELIEF is a pointer to a struct relief containing the GC
3320 with which lines will be drawn. Use a color that is FACTOR or
3321 DELTA lighter or darker than the relief's background which is found
3322 in S->f->output_data.x->relief_background. If such a color cannot
3323 be allocated, use DEFAULT_PIXEL, instead. */
3326 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3328 struct relief
*relief
;
3331 unsigned long default_pixel
;
3334 struct mac_output
*di
= f
->output_data
.mac
;
3335 unsigned long mask
= GCForeground
;
3336 unsigned long pixel
;
3337 unsigned long background
= di
->relief_background
;
3338 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3340 /* MAC_TODO: Free colors (if using palette)? */
3342 /* Allocate new color. */
3343 xgcv
.foreground
= default_pixel
;
3345 if (dpyinfo
->n_planes
!= 1
3346 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3348 relief
->allocated_p
= 1;
3349 xgcv
.foreground
= relief
->pixel
= pixel
;
3352 if (relief
->gc
== 0)
3354 #if 0 /* MAC_TODO: stipple */
3355 xgcv
.stipple
= dpyinfo
->gray
;
3358 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3361 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3365 /* Set up colors for the relief lines around glyph string S. */
3368 x_setup_relief_colors (s
)
3369 struct glyph_string
*s
;
3371 struct mac_output
*di
= s
->f
->output_data
.mac
;
3372 unsigned long color
;
3374 if (s
->face
->use_box_color_for_shadows_p
)
3375 color
= s
->face
->box_color
;
3376 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3378 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3379 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3384 /* Get the background color of the face. */
3385 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3386 color
= xgcv
.background
;
3389 if (di
->white_relief
.gc
== 0
3390 || color
!= di
->relief_background
)
3392 di
->relief_background
= color
;
3393 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3394 WHITE_PIX_DEFAULT (s
->f
));
3395 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3396 BLACK_PIX_DEFAULT (s
->f
));
3401 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3402 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3403 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3404 relief. LEFT_P non-zero means draw a relief on the left side of
3405 the rectangle. RIGHT_P non-zero means draw a relief on the right
3406 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3410 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3411 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3413 int left_x
, top_y
, right_x
, bottom_y
, width
;
3414 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3417 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3422 gc
= f
->output_data
.mac
->white_relief
.gc
;
3424 gc
= f
->output_data
.mac
->black_relief
.gc
;
3425 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3429 for (i
= 0; i
< width
; ++i
)
3430 mac_draw_line (f
, gc
,
3431 left_x
+ i
* left_p
, top_y
+ i
,
3432 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3436 for (i
= 0; i
< width
; ++i
)
3437 mac_draw_line (f
, gc
,
3438 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3440 mac_reset_clip_rectangles (dpy
, gc
);
3442 gc
= f
->output_data
.mac
->black_relief
.gc
;
3444 gc
= f
->output_data
.mac
->white_relief
.gc
;
3445 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3449 for (i
= 0; i
< width
; ++i
)
3450 mac_draw_line (f
, gc
,
3451 left_x
+ i
* left_p
, bottom_y
- i
,
3452 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3456 for (i
= 0; i
< width
; ++i
)
3457 mac_draw_line (f
, gc
,
3458 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3460 mac_reset_clip_rectangles (dpy
, gc
);
3464 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3465 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3466 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3467 left side of the rectangle. RIGHT_P non-zero means draw a line
3468 on the right side of the rectangle. CLIP_RECT is the clipping
3469 rectangle to use when drawing. */
3472 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3473 left_p
, right_p
, clip_rect
)
3474 struct glyph_string
*s
;
3475 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3480 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3481 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3482 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3485 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3486 right_x
- left_x
+ 1, width
);
3490 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3491 width
, bottom_y
- top_y
+ 1);
3494 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3495 right_x
- left_x
+ 1, width
);
3499 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3500 top_y
, width
, bottom_y
- top_y
+ 1);
3502 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3503 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3507 /* Draw a box around glyph string S. */
3510 x_draw_glyph_string_box (s
)
3511 struct glyph_string
*s
;
3513 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3514 int left_p
, right_p
;
3515 struct glyph
*last_glyph
;
3518 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3519 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3520 : window_box_right (s
->w
, s
->area
));
3522 /* The glyph that may have a right box line. */
3523 last_glyph
= (s
->cmp
|| s
->img
3525 : s
->first_glyph
+ s
->nchars
- 1);
3527 width
= abs (s
->face
->box_line_width
);
3528 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3530 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3532 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3534 bottom_y
= top_y
+ s
->height
- 1;
3536 left_p
= (s
->first_glyph
->left_box_line_p
3537 || (s
->hl
== DRAW_MOUSE_FACE
3539 || s
->prev
->hl
!= s
->hl
)));
3540 right_p
= (last_glyph
->right_box_line_p
3541 || (s
->hl
== DRAW_MOUSE_FACE
3543 || s
->next
->hl
!= s
->hl
)));
3545 get_glyph_string_clip_rect (s
, &clip_rect
);
3547 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3548 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3549 left_p
, right_p
, &clip_rect
);
3552 x_setup_relief_colors (s
);
3553 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3554 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3559 /* Draw foreground of image glyph string S. */
3562 x_draw_image_foreground (s
)
3563 struct glyph_string
*s
;
3566 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3568 /* If first glyph of S has a left box line, start drawing it to the
3569 right of that line. */
3570 if (s
->face
->box
!= FACE_NO_BOX
3571 && s
->first_glyph
->left_box_line_p
3573 x
+= abs (s
->face
->box_line_width
);
3575 /* If there is a margin around the image, adjust x- and y-position
3577 if (s
->slice
.x
== 0)
3578 x
+= s
->img
->hmargin
;
3579 if (s
->slice
.y
== 0)
3580 y
+= s
->img
->vmargin
;
3584 x_set_glyph_string_clipping (s
);
3587 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3588 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3589 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3593 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3594 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3595 s
->slice
.width
, s
->slice
.height
, x
, y
);
3602 mac_copy_area (s
->img
->pixmap
,
3603 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3604 s
->slice
.width
, s
->slice
.height
, x
, y
);
3607 /* When the image has a mask, we can expect that at
3608 least part of a mouse highlight or a block cursor will
3609 be visible. If the image doesn't have a mask, make
3610 a block cursor visible by drawing a rectangle around
3611 the image. I believe it's looking better if we do
3612 nothing here for mouse-face. */
3613 if (s
->hl
== DRAW_CURSOR
)
3615 int r
= s
->img
->relief
;
3617 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3618 s
->slice
.width
+ r
*2 - 1,
3619 s
->slice
.height
+ r
*2 - 1);
3624 /* Draw a rectangle if image could not be loaded. */
3625 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3626 s
->slice
.width
- 1, s
->slice
.height
- 1);
3630 /* Draw a relief around the image glyph string S. */
3633 x_draw_image_relief (s
)
3634 struct glyph_string
*s
;
3636 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3639 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3641 /* If first glyph of S has a left box line, start drawing it to the
3642 right of that line. */
3643 if (s
->face
->box
!= FACE_NO_BOX
3644 && s
->first_glyph
->left_box_line_p
3646 x
+= abs (s
->face
->box_line_width
);
3648 /* If there is a margin around the image, adjust x- and y-position
3650 if (s
->slice
.x
== 0)
3651 x
+= s
->img
->hmargin
;
3652 if (s
->slice
.y
== 0)
3653 y
+= s
->img
->vmargin
;
3655 if (s
->hl
== DRAW_IMAGE_SUNKEN
3656 || s
->hl
== DRAW_IMAGE_RAISED
)
3658 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3659 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3663 thick
= abs (s
->img
->relief
);
3664 raised_p
= s
->img
->relief
> 0;
3669 x1
= x
+ s
->slice
.width
+ thick
- 1;
3670 y1
= y
+ s
->slice
.height
+ thick
- 1;
3672 x_setup_relief_colors (s
);
3673 get_glyph_string_clip_rect (s
, &r
);
3674 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3676 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3678 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3683 /* Draw part of the background of glyph string S. X, Y, W, and H
3684 give the rectangle to draw. */
3687 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3688 struct glyph_string
*s
;
3691 #if 0 /* MAC_TODO: stipple */
3694 /* Fill background with a stipple pattern. */
3695 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3696 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3697 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3700 #endif /* MAC_TODO */
3701 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3705 /* Draw image glyph string S.
3708 s->x +-------------------------
3711 | +-------------------------
3714 | | +-------------------
3720 x_draw_image_glyph_string (s
)
3721 struct glyph_string
*s
;
3724 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3725 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3728 height
= s
->height
- 2 * box_line_vwidth
;
3731 /* Fill background with face under the image. Do it only if row is
3732 taller than image or if image has a clip mask to reduce
3734 s
->stippled_p
= s
->face
->stipple
!= 0;
3735 if (height
> s
->slice
.height
3739 || s
->img
->pixmap
== 0
3740 || s
->width
!= s
->background_width
)
3743 if (s
->first_glyph
->left_box_line_p
3745 x
+= box_line_hwidth
;
3748 if (s
->slice
.y
== 0)
3749 y
+= box_line_vwidth
;
3751 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3753 s
->background_filled_p
= 1;
3756 /* Draw the foreground. */
3757 x_draw_image_foreground (s
);
3759 /* If we must draw a relief around the image, do it. */
3761 || s
->hl
== DRAW_IMAGE_RAISED
3762 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3763 x_draw_image_relief (s
);
3767 /* Draw stretch glyph string S. */
3770 x_draw_stretch_glyph_string (s
)
3771 struct glyph_string
*s
;
3773 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3774 s
->stippled_p
= s
->face
->stipple
!= 0;
3776 if (s
->hl
== DRAW_CURSOR
3777 && !x_stretch_cursor_p
)
3779 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3780 as wide as the stretch glyph. */
3781 int width
, background_width
= s
->background_width
;
3782 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3786 background_width
-= left_x
- x
;
3789 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3792 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3794 /* Clear rest using the GC of the original non-cursor face. */
3795 if (width
< background_width
)
3798 int w
= background_width
- width
, h
= s
->height
;
3803 if (s
->row
->mouse_face_p
3804 && cursor_in_mouse_face_p (s
->w
))
3806 x_set_mouse_face_gc (s
);
3812 get_glyph_string_clip_rect (s
, &r
);
3813 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3815 #if 0 /* MAC_TODO: stipple */
3816 if (s
->face
->stipple
)
3818 /* Fill background with a stipple pattern. */
3819 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3820 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3821 XSetFillStyle (s
->display
, gc
, FillSolid
);
3824 #endif /* MAC_TODO */
3825 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3828 else if (!s
->background_filled_p
)
3830 int background_width
= s
->background_width
;
3831 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3833 /* Don't draw into left margin, fringe or scrollbar area
3834 except for header line and mode line. */
3835 if (x
< left_x
&& !s
->row
->mode_line_p
)
3837 background_width
-= left_x
- x
;
3840 if (background_width
> 0)
3841 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3844 s
->background_filled_p
= 1;
3848 /* Draw glyph string S. */
3851 x_draw_glyph_string (s
)
3852 struct glyph_string
*s
;
3854 int relief_drawn_p
= 0;
3856 /* If S draws into the background of its successor that does not
3857 draw a cursor, draw the background of the successor first so that
3858 S can draw into it. This makes S->next use XDrawString instead
3859 of XDrawImageString. */
3860 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3861 && s
->next
->hl
!= DRAW_CURSOR
)
3863 xassert (s
->next
->img
== NULL
);
3864 x_set_glyph_string_gc (s
->next
);
3865 x_set_glyph_string_clipping (s
->next
);
3866 x_draw_glyph_string_background (s
->next
, 1);
3869 /* Set up S->gc, set clipping and draw S. */
3870 x_set_glyph_string_gc (s
);
3872 /* Draw relief (if any) in advance for char/composition so that the
3873 glyph string can be drawn over it. */
3874 if (!s
->for_overlaps
3875 && s
->face
->box
!= FACE_NO_BOX
3876 && (s
->first_glyph
->type
== CHAR_GLYPH
3877 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3880 x_set_glyph_string_clipping (s
);
3881 x_draw_glyph_string_background (s
, 1);
3882 x_draw_glyph_string_box (s
);
3883 x_set_glyph_string_clipping (s
);
3887 x_set_glyph_string_clipping (s
);
3889 switch (s
->first_glyph
->type
)
3892 x_draw_image_glyph_string (s
);
3896 x_draw_stretch_glyph_string (s
);
3900 if (s
->for_overlaps
)
3901 s
->background_filled_p
= 1;
3903 x_draw_glyph_string_background (s
, 0);
3904 x_draw_glyph_string_foreground (s
);
3907 case COMPOSITE_GLYPH
:
3908 if (s
->for_overlaps
|| s
->gidx
> 0)
3909 s
->background_filled_p
= 1;
3911 x_draw_glyph_string_background (s
, 1);
3912 x_draw_composite_glyph_string_foreground (s
);
3919 if (!s
->for_overlaps
)
3921 /* Draw underline. */
3922 if (s
->face
->underline_p
)
3924 unsigned long tem
, h
;
3928 /* Get the underline thickness. Default is 1 pixel. */
3929 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3933 y
= s
->y
+ s
->height
- h
;
3934 if (!x_underline_at_descent_line
)
3936 /* Get the underline position. This is the recommended
3937 vertical offset in pixels from the baseline to the top of
3938 the underline. This is a signed value according to the
3939 specs, and its default is
3941 ROUND ((maximum descent) / 2), with
3942 ROUND(x) = floor (x + 0.5) */
3945 if (x_use_underline_position_properties
3946 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3947 y
= s
->ybase
+ (long) tem
;
3951 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3954 if (s
->face
->underline_defaulted_p
)
3955 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3956 s
->background_width
, h
);
3960 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3961 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3962 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3963 s
->background_width
, h
);
3964 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3968 /* Draw overline. */
3969 if (s
->face
->overline_p
)
3971 unsigned long dy
= 0, h
= 1;
3973 if (s
->face
->overline_color_defaulted_p
)
3974 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3975 s
->background_width
, h
);
3979 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3980 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3981 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3982 s
->background_width
, h
);
3983 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3987 /* Draw strike-through. */
3988 if (s
->face
->strike_through_p
)
3990 unsigned long h
= 1;
3991 unsigned long dy
= (s
->height
- h
) / 2;
3993 if (s
->face
->strike_through_color_defaulted_p
)
3994 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3999 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4000 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4001 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
4003 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4007 /* Draw relief if not yet drawn. */
4008 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4009 x_draw_glyph_string_box (s
);
4012 /* Reset clipping. */
4013 mac_reset_clip_rectangles (s
->display
, s
->gc
);
4016 /* Shift display to make room for inserted glyphs. */
4019 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
4021 int x
, y
, width
, height
, shift_by
;
4023 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4024 x
, y
, width
, height
,
4028 /* Delete N glyphs at the nominal cursor position. Not implemented
4039 /* Clear entire frame. If updating_frame is non-null, clear that
4040 frame. Otherwise clear the selected frame. */
4050 f
= SELECTED_FRAME ();
4052 /* Clearing the frame will erase any cursor, so mark them all as no
4054 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4055 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4056 output_cursor
.x
= -1;
4058 /* We don't set the output cursor here because there will always
4059 follow an explicit cursor_to. */
4061 mac_clear_window (f
);
4063 /* We have to clear the scroll bars, too. If we have changed
4064 colors or something like that, then they should be notified. */
4065 x_scroll_bar_clear (f
);
4067 XFlush (FRAME_MAC_DISPLAY (f
));
4073 /* Invert the middle quarter of the frame for .15 sec. */
4075 /* We use the select system call to do the waiting, so we have to make
4076 sure it's available. If it isn't, we just won't do visual bells. */
4078 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4081 /* Subtract the `struct timeval' values X and Y, storing the result in
4082 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4085 timeval_subtract (result
, x
, y
)
4086 struct timeval
*result
, x
, y
;
4088 /* Perform the carry for the later subtraction by updating y. This
4089 is safer because on some systems the tv_sec member is unsigned. */
4090 if (x
.tv_usec
< y
.tv_usec
)
4092 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4093 y
.tv_usec
-= 1000000 * nsec
;
4097 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4099 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4100 y
.tv_usec
+= 1000000 * nsec
;
4104 /* Compute the time remaining to wait. tv_usec is certainly
4106 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4107 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4109 /* Return indication of whether the result should be considered
4111 return x
.tv_sec
< y
.tv_sec
;
4118 /* Get the height not including a menu bar widget. */
4119 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
4120 /* Height of each line to flash. */
4121 int flash_height
= FRAME_LINE_HEIGHT (f
);
4122 /* These will be the left and right margins of the rectangles. */
4123 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4124 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4128 /* Don't flash the area between a scroll bar and the frame
4129 edge it is next to. */
4130 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4132 case vertical_scroll_bar_left
:
4133 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4136 case vertical_scroll_bar_right
:
4137 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4144 width
= flash_right
- flash_left
;
4148 /* If window is tall, flash top and bottom line. */
4149 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4151 mac_invert_rectangle (f
, flash_left
,
4152 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4153 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4154 width
, flash_height
);
4155 mac_invert_rectangle (f
, flash_left
,
4156 (height
- flash_height
4157 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4158 width
, flash_height
);
4161 /* If it is short, flash it all. */
4162 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4163 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4168 struct timeval wakeup
;
4170 EMACS_GET_TIME (wakeup
);
4172 /* Compute time to wait until, propagating carry from usecs. */
4173 wakeup
.tv_usec
+= 150000;
4174 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4175 wakeup
.tv_usec
%= 1000000;
4177 /* Keep waiting until past the time wakeup or any input gets
4179 while (! detect_input_pending ())
4181 struct timeval current
;
4182 struct timeval timeout
;
4184 EMACS_GET_TIME (current
);
4186 /* Break if result would be negative. */
4187 if (timeval_subtract (¤t
, wakeup
, current
))
4190 /* How long `select' should wait. */
4192 timeout
.tv_usec
= 10000;
4194 /* Try to wait that long--but we might wake up sooner. */
4195 select (0, NULL
, NULL
, NULL
, &timeout
);
4199 /* If window is tall, flash top and bottom line. */
4200 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4202 mac_invert_rectangle (f
, flash_left
,
4203 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4204 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
4205 width
, flash_height
);
4206 mac_invert_rectangle (f
, flash_left
,
4207 (height
- flash_height
4208 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4209 width
, flash_height
);
4212 /* If it is short, flash it all. */
4213 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4214 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4221 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4224 /* Make audible bell. */
4229 struct frame
*f
= SELECTED_FRAME ();
4231 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4239 XFlush (FRAME_MAC_DISPLAY (f
));
4245 /* Specify how many text lines, from the top of the window,
4246 should be affected by insert-lines and delete-lines operations.
4247 This, and those operations, are used only within an update
4248 that is bounded by calls to x_update_begin and x_update_end. */
4251 XTset_terminal_window (n
)
4254 /* This function intentionally left blank. */
4259 /***********************************************************************
4261 ***********************************************************************/
4263 /* Perform an insert-lines or delete-lines operation, inserting N
4264 lines or deleting -N lines at vertical position VPOS. */
4267 x_ins_del_lines (vpos
, n
)
4274 /* Scroll part of the display as described by RUN. */
4277 x_scroll_run (w
, run
)
4281 struct frame
*f
= XFRAME (w
->frame
);
4282 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4284 /* Get frame-relative bounding box of the text display area of W,
4285 without mode lines. Include in this box the left and right
4287 window_box (w
, -1, &x
, &y
, &width
, &height
);
4289 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4290 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4291 bottom_y
= y
+ height
;
4295 /* Scrolling up. Make sure we don't copy part of the mode
4296 line at the bottom. */
4297 if (from_y
+ run
->height
> bottom_y
)
4298 height
= bottom_y
- from_y
;
4300 height
= run
->height
;
4304 /* Scolling down. Make sure we don't copy over the mode line.
4306 if (to_y
+ run
->height
> bottom_y
)
4307 height
= bottom_y
- to_y
;
4309 height
= run
->height
;
4314 /* Cursor off. Will be switched on again in x_update_window_end. */
4318 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4328 /***********************************************************************
4330 ***********************************************************************/
4338 ControlRef root_control
;
4341 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4343 ActivateControl (root_control
);
4345 x_update_cursor (f
, 1);
4349 frame_unhighlight (f
)
4353 ControlRef root_control
;
4356 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4358 DeactivateControl (root_control
);
4360 x_update_cursor (f
, 1);
4363 /* The focus has changed. Update the frames as necessary to reflect
4364 the new situation. Note that we can't change the selected frame
4365 here, because the Lisp code we are interrupting might become confused.
4366 Each event gets marked with the frame in which it occurred, so the
4367 Lisp code can tell when the switch took place by examining the events. */
4370 x_new_focus_frame (dpyinfo
, frame
)
4371 struct x_display_info
*dpyinfo
;
4372 struct frame
*frame
;
4374 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4376 if (frame
!= dpyinfo
->x_focus_frame
)
4378 /* Set this before calling other routines, so that they see
4379 the correct value of x_focus_frame. */
4380 dpyinfo
->x_focus_frame
= frame
;
4382 if (old_focus
&& old_focus
->auto_lower
)
4383 x_lower_frame (old_focus
);
4386 selected_frame
= frame
;
4387 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4389 Fselect_window (selected_frame
->selected_window
, Qnil
);
4390 choose_minibuf_frame ();
4393 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4394 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4396 pending_autoraise_frame
= 0;
4398 #if USE_MAC_FONT_PANEL
4400 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4404 x_frame_rehighlight (dpyinfo
);
4407 /* Handle FocusIn and FocusOut state changes for FRAME.
4408 If FRAME has focus and there exists more than one frame, puts
4409 a FOCUS_IN_EVENT into *BUFP. */
4412 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4414 struct mac_display_info
*dpyinfo
;
4415 struct frame
*frame
;
4416 struct input_event
*bufp
;
4418 if (type
== activeFlag
)
4420 if (dpyinfo
->x_focus_event_frame
!= frame
)
4422 x_new_focus_frame (dpyinfo
, frame
);
4423 dpyinfo
->x_focus_event_frame
= frame
;
4425 /* Don't stop displaying the initial startup message
4426 for a switch-frame event we don't need. */
4427 if (GC_NILP (Vterminal_frame
)
4428 && GC_CONSP (Vframe_list
)
4429 && !GC_NILP (XCDR (Vframe_list
)))
4431 bufp
->kind
= FOCUS_IN_EVENT
;
4432 XSETFRAME (bufp
->frame_or_window
, frame
);
4438 if (dpyinfo
->x_focus_event_frame
== frame
)
4440 dpyinfo
->x_focus_event_frame
= 0;
4441 x_new_focus_frame (dpyinfo
, 0);
4446 /* The focus may have changed. Figure out if it is a real focus change,
4447 by checking both FocusIn/Out and Enter/LeaveNotify events.
4449 Returns FOCUS_IN_EVENT event in *BUFP. */
4452 x_detect_focus_change (dpyinfo
, event
, bufp
)
4453 struct mac_display_info
*dpyinfo
;
4454 const EventRecord
*event
;
4455 struct input_event
*bufp
;
4457 struct frame
*frame
;
4459 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
4463 /* On Mac, this is only called from focus events, so no switch needed. */
4464 mac_focus_changed ((event
->modifiers
& activeFlag
),
4465 dpyinfo
, frame
, bufp
);
4469 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4472 x_mouse_leave (dpyinfo
)
4473 struct x_display_info
*dpyinfo
;
4475 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4478 /* The focus has changed, or we have redirected a frame's focus to
4479 another frame (this happens when a frame uses a surrogate
4480 mini-buffer frame). Shift the highlight as appropriate.
4482 The FRAME argument doesn't necessarily have anything to do with which
4483 frame is being highlighted or un-highlighted; we only use it to find
4484 the appropriate X display info. */
4487 XTframe_rehighlight (frame
)
4488 struct frame
*frame
;
4490 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4494 x_frame_rehighlight (dpyinfo
)
4495 struct x_display_info
*dpyinfo
;
4497 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4499 if (dpyinfo
->x_focus_frame
)
4501 dpyinfo
->x_highlight_frame
4502 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4503 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4504 : dpyinfo
->x_focus_frame
);
4505 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4507 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4508 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4512 dpyinfo
->x_highlight_frame
= 0;
4514 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4517 frame_unhighlight (old_highlight
);
4518 if (dpyinfo
->x_highlight_frame
)
4519 frame_highlight (dpyinfo
->x_highlight_frame
);
4525 /* Convert a keysym to its name. */
4528 x_get_keysym_name (keysym
)
4535 value
= XKeysymToString (keysym
);
4546 /* Function to report a mouse movement to the mainstream Emacs code.
4547 The input handler calls this.
4549 We have received a mouse movement event, which is given in *event.
4550 If the mouse is over a different glyph than it was last time, tell
4551 the mainstream emacs code by setting mouse_moved. If not, ask for
4552 another motion event, so we can check again the next time it moves. */
4554 static Point last_mouse_motion_position
;
4555 static Lisp_Object last_mouse_motion_frame
;
4558 note_mouse_movement (frame
, pos
)
4562 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4563 #if TARGET_API_MAC_CARBON
4567 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4568 last_mouse_motion_position
= *pos
;
4569 XSETFRAME (last_mouse_motion_frame
, frame
);
4571 if (frame
== dpyinfo
->mouse_face_mouse_frame
4572 #if TARGET_API_MAC_CARBON
4573 && !PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
))
4575 && !PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
)
4579 /* This case corresponds to LeaveNotify in X11. If we move
4580 outside the frame, then we're certainly no longer on any text
4582 clear_mouse_face (dpyinfo
);
4583 dpyinfo
->mouse_face_mouse_frame
= 0;
4584 if (!dpyinfo
->grabbed
)
4585 rif
->define_frame_cursor (frame
,
4586 frame
->output_data
.mac
->nontext_cursor
);
4589 /* Has the mouse moved off the glyph it was on at the last sighting? */
4590 if (frame
!= last_mouse_glyph_frame
4591 || !PtInRect (*pos
, &last_mouse_glyph
))
4593 frame
->mouse_moved
= 1;
4594 last_mouse_scroll_bar
= Qnil
;
4595 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4596 /* Remember which glyph we're now on. */
4597 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4598 last_mouse_glyph_frame
= frame
;
4606 /************************************************************************
4608 ************************************************************************/
4610 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4613 redo_mouse_highlight ()
4615 if (!NILP (last_mouse_motion_frame
)
4616 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4617 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4618 last_mouse_motion_position
.h
,
4619 last_mouse_motion_position
.v
);
4623 static struct frame
*
4624 mac_focus_frame (dpyinfo
)
4625 struct mac_display_info
*dpyinfo
;
4627 if (dpyinfo
->x_focus_frame
)
4628 return dpyinfo
->x_focus_frame
;
4630 /* Mac version may get events, such as a menu bar click, even when
4631 all the frames are invisible. In this case, we regard the
4632 event came to the selected frame. */
4633 return SELECTED_FRAME ();
4637 /* Return the current position of the mouse.
4638 *FP should be a frame which indicates which display to ask about.
4640 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4641 and *PART to the frame, window, and scroll bar part that the mouse
4642 is over. Set *X and *Y to the portion and whole of the mouse's
4643 position on the scroll bar.
4645 If the mouse movement started elsewhere, set *FP to the frame the
4646 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4649 Set *TIME to the server time-stamp for the time at which the mouse
4650 was at this position.
4652 Don't store anything if we don't have a valid set of values to report.
4654 This clears the mouse_moved flag, so we can wait for the next mouse
4658 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4661 Lisp_Object
*bar_window
;
4662 enum scroll_bar_part
*part
;
4664 unsigned long *time
;
4670 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4671 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4674 Lisp_Object frame
, tail
;
4676 /* Clear the mouse-moved flag for every frame on this display. */
4677 FOR_EACH_FRAME (tail
, frame
)
4678 XFRAME (frame
)->mouse_moved
= 0;
4680 last_mouse_scroll_bar
= Qnil
;
4682 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4683 && FRAME_LIVE_P (last_mouse_frame
))
4684 f1
= last_mouse_frame
;
4686 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4690 /* Ok, we found a frame. Store all the values.
4691 last_mouse_glyph is a rectangle used to reduce the
4692 generation of mouse events. To not miss any motion
4693 events, we must divide the frame into rectangles of the
4694 size of the smallest character that could be displayed
4695 on it, i.e. into the same rectangles that matrices on
4696 the frame are divided into. */
4699 #if TARGET_API_MAC_CARBON
4700 GetGlobalMouse (&mouse_pos
);
4701 mouse_pos
.h
-= f1
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f1
);
4702 mouse_pos
.v
-= f1
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f1
);
4704 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4705 GetMouse (&mouse_pos
);
4707 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4709 last_mouse_glyph_frame
= f1
;
4714 XSETINT (*x
, mouse_pos
.h
);
4715 XSETINT (*y
, mouse_pos
.v
);
4716 *time
= last_mouse_movement_time
;
4724 /************************************************************************
4726 ************************************************************************/
4728 #ifdef USE_TOOLKIT_SCROLL_BARS
4730 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4731 static OSStatus install_scroll_bar_timer
P_ ((void));
4732 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4733 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4734 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4735 struct input_event
*));
4736 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
4738 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4739 ControlPartCode
, Point
,
4740 struct input_event
*));
4741 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4742 struct input_event
*));
4743 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
4744 Point
, struct input_event
*));
4745 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4748 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4750 static int last_scroll_bar_part
;
4752 static EventLoopTimerRef scroll_bar_timer
;
4754 static int scroll_bar_timer_event_posted_p
;
4756 #define SCROLL_BAR_FIRST_DELAY 0.5
4757 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4760 scroll_bar_timer_callback (timer
, data
)
4761 EventLoopTimerRef timer
;
4766 err
= mac_post_mouse_moved_event ();
4768 scroll_bar_timer_event_posted_p
= 1;
4772 install_scroll_bar_timer ()
4774 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4776 if (scroll_bar_timer_callbackUPP
== NULL
)
4777 scroll_bar_timer_callbackUPP
=
4778 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4780 if (scroll_bar_timer
== NULL
)
4781 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4782 kEventDurationForever as delays. */
4784 InstallEventLoopTimer (GetCurrentEventLoop (),
4785 kEventDurationForever
, kEventDurationForever
,
4786 scroll_bar_timer_callbackUPP
, NULL
,
4791 set_scroll_bar_timer (delay
)
4792 EventTimerInterval delay
;
4794 if (scroll_bar_timer
== NULL
)
4795 install_scroll_bar_timer ();
4797 scroll_bar_timer_event_posted_p
= 0;
4799 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4803 control_part_code_to_scroll_bar_part (part_code
)
4804 ControlPartCode part_code
;
4808 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4809 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4810 case kControlPageUpPart
: return scroll_bar_above_handle
;
4811 case kControlPageDownPart
: return scroll_bar_below_handle
;
4812 case kControlIndicatorPart
: return scroll_bar_handle
;
4819 construct_scroll_bar_click (bar
, part
, bufp
)
4820 struct scroll_bar
*bar
;
4822 struct input_event
*bufp
;
4824 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4825 bufp
->frame_or_window
= bar
->window
;
4829 XSETINT (bufp
->x
, 0);
4830 XSETINT (bufp
->y
, 0);
4831 bufp
->modifiers
= 0;
4835 get_control_part_bounds (ch
, part_code
, rect
)
4837 ControlPartCode part_code
;
4840 RgnHandle region
= NewRgn ();
4843 err
= GetControlRegion (ch
, part_code
, region
);
4845 GetRegionBounds (region
, rect
);
4846 DisposeRgn (region
);
4852 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
4853 struct scroll_bar
*bar
;
4854 ControlPartCode part_code
;
4856 struct input_event
*bufp
;
4858 int part
= control_part_code_to_scroll_bar_part (part_code
);
4863 if (part
!= scroll_bar_handle
)
4865 construct_scroll_bar_click (bar
, part
, bufp
);
4866 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4867 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4868 bar
->dragging
= Qnil
;
4874 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4875 kControlIndicatorPart
, &r
);
4876 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
4879 last_scroll_bar_part
= part
;
4880 tracked_scroll_bar
= bar
;
4884 x_scroll_bar_handle_release (bar
, bufp
)
4885 struct scroll_bar
*bar
;
4886 struct input_event
*bufp
;
4888 if (last_scroll_bar_part
!= scroll_bar_handle
4889 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
4890 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4892 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4893 set_scroll_bar_timer (kEventDurationForever
);
4895 last_scroll_bar_part
= -1;
4896 bar
->dragging
= Qnil
;
4897 tracked_scroll_bar
= NULL
;
4901 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4903 struct scroll_bar
*bar
;
4905 struct input_event
*bufp
;
4907 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4909 if (last_scroll_bar_part
== scroll_bar_handle
)
4914 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
4915 kControlIndicatorPart
, &r
);
4917 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
4918 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
4920 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4921 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4925 if (top
> top_range
)
4928 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4929 XSETINT (bufp
->x
, top
);
4930 XSETINT (bufp
->y
, top_range
);
4934 ControlPartCode part_code
;
4935 int unhilite_p
= 0, part
;
4937 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4941 part
= control_part_code_to_scroll_bar_part (part_code
);
4943 switch (last_scroll_bar_part
)
4945 case scroll_bar_above_handle
:
4946 case scroll_bar_below_handle
:
4947 if (part
!= scroll_bar_above_handle
4948 && part
!= scroll_bar_below_handle
)
4952 case scroll_bar_up_arrow
:
4953 case scroll_bar_down_arrow
:
4954 if (part
!= scroll_bar_up_arrow
4955 && part
!= scroll_bar_down_arrow
)
4962 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
4963 else if (part
!= last_scroll_bar_part
4964 || scroll_bar_timer_event_posted_p
)
4966 construct_scroll_bar_click (bar
, part
, bufp
);
4967 last_scroll_bar_part
= part
;
4968 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
4969 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4974 /* Set the thumb size and position of scroll bar BAR. We are currently
4975 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4978 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4979 struct scroll_bar
*bar
;
4980 int portion
, position
, whole
;
4982 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
4983 int value
, viewsize
, maximum
;
4985 if (XINT (bar
->track_height
) == 0)
4988 if (whole
<= portion
)
4989 value
= 0, viewsize
= 1, maximum
= 0;
4994 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
4995 scale
= (float) maximum
/ (whole
- portion
);
4996 value
= position
* scale
+ 0.5f
;
4997 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
5002 if (GetControlViewSize (ch
) != viewsize
5003 || GetControl32BitValue (ch
) != value
5004 || GetControl32BitMaximum (ch
) != maximum
)
5006 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5007 SetControlVisibility (ch
, false, false);
5009 SetControl32BitMaximum (ch
, maximum
);
5010 SetControl32BitValue (ch
, value
);
5011 SetControlViewSize (ch
, viewsize
);
5013 SetControlVisibility (ch
, true, true);
5019 #endif /* USE_TOOLKIT_SCROLL_BARS */
5023 /************************************************************************
5024 Scroll bars, general
5025 ************************************************************************/
5027 /* Create a scroll bar and return the scroll bar vector for it. W is
5028 the Emacs window on which to create the scroll bar. TOP, LEFT,
5029 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5032 static struct scroll_bar
*
5033 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5035 int top
, left
, width
, height
, disp_top
, disp_height
;
5037 struct frame
*f
= XFRAME (w
->frame
);
5038 struct scroll_bar
*bar
5039 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5047 r
.right
= left
+ width
;
5048 r
.bottom
= disp_top
+ disp_height
;
5051 mac_prepare_for_quickdraw (f
);
5053 #if TARGET_API_MAC_CARBON
5054 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
5055 #ifdef USE_TOOLKIT_SCROLL_BARS
5058 width
< disp_height
,
5060 0, 0, 0, kControlScrollBarProc
, (long) bar
);
5062 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
5063 0, 0, 0, scrollBarProc
, (long) bar
);
5065 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
5067 XSETWINDOW (bar
->window
, w
);
5068 XSETINT (bar
->top
, top
);
5069 XSETINT (bar
->left
, left
);
5070 XSETINT (bar
->width
, width
);
5071 XSETINT (bar
->height
, height
);
5072 XSETINT (bar
->start
, 0);
5073 XSETINT (bar
->end
, 0);
5074 bar
->dragging
= Qnil
;
5076 bar
->fringe_extended_p
= Qnil
;
5078 #ifdef USE_TOOLKIT_SCROLL_BARS
5079 bar
->track_top
= Qnil
;
5080 bar
->track_height
= Qnil
;
5081 bar
->min_handle
= Qnil
;
5084 /* Add bar to its frame's list of scroll bars. */
5085 bar
->next
= FRAME_SCROLL_BARS (f
);
5087 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5088 if (!NILP (bar
->next
))
5089 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5096 /* Draw BAR's handle in the proper position.
5098 If the handle is already drawn from START to END, don't bother
5099 redrawing it, unless REBUILD is non-zero; in that case, always
5100 redraw it. (REBUILD is handy for drawing the handle after expose
5103 Normally, we want to constrain the start and end of the handle to
5104 fit inside its rectangle, but if the user is dragging the scroll
5105 bar handle, we want to let them drag it down all the way, so that
5106 the bar's top is as far down as it goes; otherwise, there's no way
5107 to move to the very end of the buffer. */
5109 #ifndef USE_TOOLKIT_SCROLL_BARS
5112 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5113 struct scroll_bar
*bar
;
5117 int dragging
= ! NILP (bar
->dragging
);
5118 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5119 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5120 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5121 int length
= end
- start
;
5123 /* If the display is already accurate, do nothing. */
5125 && start
== XINT (bar
->start
)
5126 && end
== XINT (bar
->end
))
5131 /* Make sure the values are reasonable, and try to preserve the
5132 distance between start and end. */
5135 else if (start
> top_range
)
5137 end
= start
+ length
;
5141 else if (end
> top_range
&& ! dragging
)
5144 /* Store the adjusted setting in the scroll bar. */
5145 XSETINT (bar
->start
, start
);
5146 XSETINT (bar
->end
, end
);
5148 /* Clip the end position, just for display. */
5149 if (end
> top_range
)
5152 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5153 top positions, to make sure the handle is always at least that
5154 many pixels tall. */
5155 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5157 SetControlMinimum (ch
, 0);
5158 /* Don't inadvertently activate deactivated scroll bars */
5159 if (GetControlMaximum (ch
) != -1)
5160 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
5162 SetControlValue (ch
, start
);
5163 #if TARGET_API_MAC_CARBON
5164 SetControlViewSize (ch
, end
- start
);
5170 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5172 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5176 x_scroll_bar_remove (bar
)
5177 struct scroll_bar
*bar
;
5179 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5184 mac_prepare_for_quickdraw (f
);
5186 /* Destroy the Mac scroll bar control */
5187 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
5189 /* Disassociate this scroll bar from its window. */
5190 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5196 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5197 that we are displaying PORTION characters out of a total of WHOLE
5198 characters, starting at POSITION. If WINDOW has no scroll bar,
5202 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5204 int portion
, whole
, position
;
5206 struct frame
*f
= XFRAME (w
->frame
);
5207 struct scroll_bar
*bar
;
5208 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
5209 int window_y
, window_height
;
5211 int fringe_extended_p
;
5214 /* Get window dimensions. */
5215 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5217 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5218 height
= window_height
;
5220 /* Compute the left edge of the scroll bar area. */
5221 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5223 /* Compute the width of the scroll bar which might be less than
5224 the width of the area reserved for the scroll bar. */
5225 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5226 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5230 /* Compute the left edge of the scroll bar. */
5231 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5232 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5234 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5236 /* Adjustments according to Inside Macintosh to make it look nice */
5238 disp_height
= height
;
5245 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
5251 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5256 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5257 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5258 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5259 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5260 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5262 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5263 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5264 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5265 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5268 /* Does the scroll bar exist yet? */
5269 if (NILP (w
->vertical_scroll_bar
))
5273 if (fringe_extended_p
)
5274 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5277 mac_clear_area (f
, left
, top
, width
, height
);
5279 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5281 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5285 /* It may just need to be moved and resized. */
5288 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5289 ch
= SCROLL_BAR_CONTROL_REF (bar
);
5293 /* If already correctly positioned, do nothing. */
5294 if (!(XINT (bar
->left
) == sb_left
5295 && XINT (bar
->top
) == top
5296 && XINT (bar
->width
) == sb_width
5297 && XINT (bar
->height
) == height
5299 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
5303 /* Since toolkit scroll bars are smaller than the space reserved
5304 for them on the frame, we have to clear "under" them. */
5306 if (fringe_extended_p
)
5307 mac_clear_area (f
, sb_left
, top
, sb_width
, height
);
5310 mac_clear_area (f
, left
, top
, width
, height
);
5313 mac_prepare_for_quickdraw (f
);
5316 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5317 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5319 #ifndef USE_TOOLKIT_SCROLL_BARS
5320 if (sb_width
< disp_height
)
5324 /* Remember new settings. */
5325 XSETINT (bar
->left
, sb_left
);
5326 XSETINT (bar
->top
, top
);
5327 XSETINT (bar
->width
, sb_width
);
5328 XSETINT (bar
->height
, height
);
5329 #ifdef USE_TOOLKIT_SCROLL_BARS
5330 bar
->track_top
= Qnil
;
5331 bar
->track_height
= Qnil
;
5332 bar
->min_handle
= Qnil
;
5340 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
5343 #ifdef USE_TOOLKIT_SCROLL_BARS
5344 if (NILP (bar
->track_top
))
5346 if (sb_width
>= disp_height
5348 || sb_width
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5352 XSETINT (bar
->track_top
, 0);
5353 XSETINT (bar
->track_height
, 0);
5354 XSETINT (bar
->min_handle
, 0);
5358 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5363 SetControl32BitMinimum (ch
, 0);
5364 SetControl32BitMaximum (ch
, 1 << 30);
5365 SetControlViewSize (ch
, 1);
5367 /* Move the scroll bar thumb to the top. */
5368 SetControl32BitValue (ch
, 0);
5369 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5371 /* Move the scroll bar thumb to the bottom. */
5372 SetControl32BitValue (ch
, 1 << 30);
5373 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5375 UnionRect (&r0
, &r1
, &r0
);
5376 XSETINT (bar
->track_top
, r0
.top
);
5377 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5378 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
5380 /* Don't show the scroll bar if its height is not enough to
5381 display the scroll bar thumb. */
5382 if (r0
.bottom
- r0
.top
> 0)
5389 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5390 #else /* not USE_TOOLKIT_SCROLL_BARS */
5391 /* Set the scroll bar's current state, unless we're currently being
5393 if (NILP (bar
->dragging
))
5395 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5398 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5401 int start
= ((double) position
* top_range
) / whole
;
5402 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5403 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5406 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5410 /* The following three hooks are used when we're doing a thorough
5411 redisplay of the frame. We don't explicitly know which scroll bars
5412 are going to be deleted, because keeping track of when windows go
5413 away is a real pain - "Can you say set-window-configuration, boys
5414 and girls?" Instead, we just assert at the beginning of redisplay
5415 that *all* scroll bars are to be removed, and then save a scroll bar
5416 from the fiery pit when we actually redisplay its window. */
5418 /* Arrange for all scroll bars on FRAME to be removed at the next call
5419 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5420 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5423 XTcondemn_scroll_bars (frame
)
5426 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5427 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5430 bar
= FRAME_SCROLL_BARS (frame
);
5431 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5432 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5433 XSCROLL_BAR (bar
)->prev
= Qnil
;
5434 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5435 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5436 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5441 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5442 Note that WINDOW isn't necessarily condemned at all. */
5445 XTredeem_scroll_bar (window
)
5446 struct window
*window
;
5448 struct scroll_bar
*bar
;
5451 /* We can't redeem this window's scroll bar if it doesn't have one. */
5452 if (NILP (window
->vertical_scroll_bar
))
5455 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5457 /* Unlink it from the condemned list. */
5458 f
= XFRAME (WINDOW_FRAME (window
));
5459 if (NILP (bar
->prev
))
5461 /* If the prev pointer is nil, it must be the first in one of
5463 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5464 /* It's not condemned. Everything's fine. */
5466 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5467 window
->vertical_scroll_bar
))
5468 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5470 /* If its prev pointer is nil, it must be at the front of
5471 one or the other! */
5475 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5477 if (! NILP (bar
->next
))
5478 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5480 bar
->next
= FRAME_SCROLL_BARS (f
);
5482 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5483 if (! NILP (bar
->next
))
5484 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5487 /* Remove all scroll bars on FRAME that haven't been saved since the
5488 last call to `*condemn_scroll_bars_hook'. */
5491 XTjudge_scroll_bars (f
)
5494 Lisp_Object bar
, next
;
5496 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5498 /* Clear out the condemned list now so we won't try to process any
5499 more events on the hapless scroll bars. */
5500 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5502 for (; ! NILP (bar
); bar
= next
)
5504 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5506 x_scroll_bar_remove (b
);
5509 b
->next
= b
->prev
= Qnil
;
5512 /* Now there should be no references to the condemned scroll bars,
5513 and they should get garbage-collected. */
5517 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5518 is set to something other than NO_EVENT, it is enqueued.
5520 This may be called from a signal handler, so we have to ignore GC
5524 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5525 struct scroll_bar
*bar
;
5526 ControlPartCode part_code
;
5527 const EventRecord
*er
;
5528 struct input_event
*bufp
;
5530 int win_y
, top_range
;
5532 if (! GC_WINDOWP (bar
->window
))
5535 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5536 bufp
->frame_or_window
= bar
->window
;
5539 bar
->dragging
= Qnil
;
5543 case kControlUpButtonPart
:
5544 bufp
->part
= scroll_bar_up_arrow
;
5546 case kControlDownButtonPart
:
5547 bufp
->part
= scroll_bar_down_arrow
;
5549 case kControlPageUpPart
:
5550 bufp
->part
= scroll_bar_above_handle
;
5552 case kControlPageDownPart
:
5553 bufp
->part
= scroll_bar_below_handle
;
5555 #if TARGET_API_MAC_CARBON
5558 case kControlIndicatorPart
:
5560 if (er
->what
== mouseDown
)
5561 bar
->dragging
= make_number (0);
5562 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5563 bufp
->part
= scroll_bar_handle
;
5567 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5568 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5570 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5574 if (! NILP (bar
->dragging
))
5575 win_y
-= XINT (bar
->dragging
);
5579 if (win_y
> top_range
)
5582 XSETINT (bufp
->x
, win_y
);
5583 XSETINT (bufp
->y
, top_range
);
5586 #ifndef USE_TOOLKIT_SCROLL_BARS
5588 /* Handle some mouse motion while someone is dragging the scroll bar.
5590 This may be called from a signal handler, so we have to ignore GC
5594 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5595 struct scroll_bar
*bar
;
5599 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5601 last_mouse_movement_time
= t
;
5604 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5606 /* If we're dragging the bar, display it. */
5607 if (! GC_NILP (bar
->dragging
))
5609 /* Where should the handle be now? */
5610 int new_start
= y_pos
- 24;
5612 if (new_start
!= XINT (bar
->start
))
5614 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5616 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5621 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5623 /* Return information to the user about the current position of the mouse
5624 on the scroll bar. */
5627 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5629 Lisp_Object
*bar_window
;
5630 enum scroll_bar_part
*part
;
5632 unsigned long *time
;
5634 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5635 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
5636 #if TARGET_API_MAC_CARBON
5637 WindowRef wp
= GetControlOwner (ch
);
5639 WindowRef wp
= (*ch
)->contrlOwner
;
5642 struct frame
*f
= mac_window_to_frame (wp
);
5643 int win_y
, top_range
;
5645 #if TARGET_API_MAC_CARBON
5646 GetGlobalMouse (&mouse_pos
);
5647 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
5648 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
5650 SetPortWindowPort (wp
);
5651 GetMouse (&mouse_pos
);
5654 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5655 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5657 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5661 if (! NILP (bar
->dragging
))
5662 win_y
-= XINT (bar
->dragging
);
5666 if (win_y
> top_range
)
5670 *bar_window
= bar
->window
;
5672 if (! NILP (bar
->dragging
))
5673 *part
= scroll_bar_handle
;
5674 else if (win_y
< XINT (bar
->start
))
5675 *part
= scroll_bar_above_handle
;
5676 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5677 *part
= scroll_bar_handle
;
5679 *part
= scroll_bar_below_handle
;
5681 XSETINT (*x
, win_y
);
5682 XSETINT (*y
, top_range
);
5685 last_mouse_scroll_bar
= Qnil
;
5687 *time
= last_mouse_movement_time
;
5691 /* The screen has been cleared so we may have changed foreground or
5692 background colors, and the scroll bars may need to be redrawn.
5693 Clear out the scroll bars, and ask for expose events, so we can
5697 x_scroll_bar_clear (f
)
5700 XTcondemn_scroll_bars (f
);
5701 XTjudge_scroll_bars (f
);
5705 /***********************************************************************
5707 ***********************************************************************/
5710 /* In identifiers such as function/variable names, Emacs tool bar is
5711 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5713 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5714 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5716 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5717 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5718 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5719 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5720 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5721 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5722 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5724 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
5725 static void mac_handle_origin_change
P_ ((struct frame
*));
5726 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
5730 mac_move_window_with_gravity (f
, win_gravity
, left
, top
)
5737 mac_get_window_bounds (f
, &inner
, &outer
);
5739 switch (win_gravity
)
5741 case NorthWestGravity
:
5743 case SouthWestGravity
:
5744 left
+= inner
.left
- outer
.left
;
5750 left
+= ((inner
.left
- outer
.left
) + (inner
.right
- outer
.right
)) / 2;
5753 case NorthEastGravity
:
5755 case SouthEastGravity
:
5756 left
+= inner
.right
- outer
.right
;
5760 switch (win_gravity
)
5762 case NorthWestGravity
:
5764 case NorthEastGravity
:
5765 top
+= inner
.top
- outer
.top
;
5771 top
+= ((inner
.top
- outer
.top
) + (inner
.bottom
- outer
.bottom
)) / 2;
5774 case SouthWestGravity
:
5776 case SouthEastGravity
:
5777 top
+= inner
.bottom
- outer
.bottom
;
5781 MoveWindow (FRAME_MAC_WINDOW (f
), left
, top
, false);
5785 mac_get_window_origin_with_gravity (f
, win_gravity
, left
, top
)
5792 mac_get_window_bounds (f
, &inner
, &outer
);
5794 switch (win_gravity
)
5796 case NorthWestGravity
:
5798 case SouthWestGravity
:
5805 *left
= outer
.left
+ ((outer
.right
- outer
.left
)
5806 - (inner
.right
- inner
.left
)) / 2;
5809 case NorthEastGravity
:
5811 case SouthEastGravity
:
5812 *left
= outer
.right
- (inner
.right
- inner
.left
);
5816 switch (win_gravity
)
5818 case NorthWestGravity
:
5820 case NorthEastGravity
:
5827 *top
= outer
.top
+ ((outer
.bottom
- outer
.top
)
5828 - (inner
.bottom
- inner
.top
)) / 2;
5831 case SouthWestGravity
:
5833 case SouthEastGravity
:
5834 *top
= outer
.bottom
- (inner
.bottom
- inner
.top
);
5840 mac_handle_toolbar_event (next_handler
, event
, data
)
5841 EventHandlerCallRef next_handler
;
5845 OSStatus err
, result
= eventNotHandledErr
;
5847 switch (GetEventKind (event
))
5849 case kEventToolbarGetDefaultIdentifiers
:
5853 case kEventToolbarGetAllowedIdentifiers
:
5855 CFMutableArrayRef array
;
5857 GetEventParameter (event
, kEventParamMutableArray
,
5858 typeCFMutableArrayRef
, NULL
,
5859 sizeof (CFMutableArrayRef
), NULL
, &array
);
5860 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
5865 case kEventToolbarCreateItemWithIdentifier
:
5867 CFStringRef identifier
;
5868 HIToolbarItemRef item
= NULL
;
5870 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
5871 typeCFStringRef
, NULL
,
5872 sizeof (CFStringRef
), NULL
, &identifier
);
5874 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
5875 == kCFCompareEqualTo
)
5876 HIToolbarItemCreate (identifier
,
5877 kHIToolbarItemAllowDuplicates
5878 | kHIToolbarItemCantBeRemoved
, &item
);
5882 SetEventParameter (event
, kEventParamToolbarItem
,
5883 typeHIToolbarItemRef
,
5884 sizeof (HIToolbarItemRef
), &item
);
5898 mac_image_spec_to_cg_image (f
, image
)
5902 if (!valid_image_p (image
))
5906 int img_id
= lookup_image (f
, image
);
5907 struct image
*img
= IMAGE_FROM_ID (f
, img_id
);
5909 prepare_image_for_display (f
, img
);
5911 return img
->data
.ptr_val
;
5915 /* Create a tool bar for frame F. */
5918 mac_create_frame_tool_bar (f
)
5922 HIToolbarRef toolbar
;
5924 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
5928 static const EventTypeSpec specs
[] =
5929 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
5930 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
5931 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
5933 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
5934 mac_handle_toolbar_event
,
5935 GetEventTypeCount (specs
), specs
,
5940 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
5943 static const EventTypeSpec specs
[] =
5944 {{kEventClassCommand
, kEventCommandProcess
}};
5946 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
5947 mac_handle_toolbar_command_event
,
5948 GetEventTypeCount (specs
),
5952 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
5955 CFRelease (toolbar
);
5960 /* Update the tool bar for frame F. Add new buttons and remove old. */
5963 update_frame_tool_bar (f
)
5966 HIToolbarRef toolbar
= NULL
;
5968 CFArrayRef old_items
= NULL
;
5970 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
5971 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5975 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5976 if (toolbar
== NULL
)
5978 mac_create_frame_tool_bar (f
);
5979 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
5980 if (toolbar
== NULL
)
5982 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
5983 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
5986 HIToolbarCopyItems (toolbar
, &old_items
);
5987 if (old_items
== NULL
)
5990 old_count
= CFArrayGetCount (old_items
);
5992 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
5994 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5996 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
5997 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
6000 CGImageRef cg_image
;
6002 HIToolbarItemRef item
;
6004 /* If image is a vector, choose the image according to the
6006 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
6007 if (VECTORP (image
))
6011 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6012 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
6015 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6016 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
6018 xassert (ASIZE (image
) >= idx
);
6019 image
= AREF (image
, idx
);
6024 cg_image
= mac_image_spec_to_cg_image (f
, image
);
6025 /* Ignore invalid image specifications. */
6026 if (cg_image
== NULL
)
6029 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
6033 if (pos
< old_count
)
6035 CGImageRef old_cg_image
= NULL
;
6036 CFStringRef old_label
= NULL
;
6037 Boolean old_enabled_p
;
6039 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
6041 HIToolbarItemCopyImage (item
, &old_cg_image
);
6042 if (cg_image
!= old_cg_image
)
6043 HIToolbarItemSetImage (item
, cg_image
);
6044 CGImageRelease (old_cg_image
);
6046 HIToolbarItemCopyLabel (item
, &old_label
);
6047 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
6048 HIToolbarItemSetLabel (item
, label
);
6049 CFRelease (old_label
);
6051 old_enabled_p
= HIToolbarItemIsEnabled (item
);
6052 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
6053 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6058 HIToolbarCreateItemWithIdentifier (toolbar
,
6059 TOOLBAR_ICON_ITEM_IDENTIFIER
,
6063 HIToolbarItemSetImage (item
, cg_image
);
6064 HIToolbarItemSetLabel (item
, label
);
6065 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
6066 HIToolbarAppendItem (toolbar
, item
);
6074 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
6079 CFRelease (old_items
);
6081 while (pos
< old_count
)
6082 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
6084 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
6085 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
6086 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6087 toolbar visibility change. */
6088 mac_handle_origin_change (f
);
6089 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
6091 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
6092 /* If the title bar is completely outside the screen, adjust the
6094 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6095 kWindowConstrainMoveRegardlessOfFit
6096 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6097 f
->output_data
.mac
->toolbar_win_gravity
= 0;
6104 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6105 doesn't deallocate the resources. */
6108 free_frame_tool_bar (f
)
6111 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
6113 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6116 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
6117 f
== mac_focus_frame (dpyinfo
));
6118 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6119 on toolbar visibility change. */
6120 mac_handle_origin_change (f
);
6126 mac_tool_bar_note_mouse_movement (f
, event
)
6131 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6133 HIViewRef item_view
;
6136 mouse_down_p
= (dpyinfo
->grabbed
6137 && f
== last_mouse_frame
6138 && FRAME_LIVE_P (f
));
6142 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6144 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6145 toolbar item view seems to have the same command ID with that of
6146 the toolbar item. */
6148 err
= GetControlCommandID (item_view
, &command_id
);
6149 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
6151 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
6153 if (i
< f
->n_tool_bar_items
)
6156 HIViewRef content_view
;
6158 err
= HIViewGetBounds (item_view
, &bounds
);
6160 err
= HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f
)),
6161 kHIViewWindowContentID
, &content_view
);
6163 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
6165 SetRect (&last_mouse_glyph
,
6166 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
6167 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
6169 help_echo_object
= help_echo_window
= Qnil
;
6171 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
6172 if (NILP (help_echo_string
))
6173 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
6179 mac_handle_toolbar_command_event (next_handler
, event
, data
)
6180 EventHandlerCallRef next_handler
;
6184 OSStatus err
, result
= eventNotHandledErr
;
6185 struct frame
*f
= (struct frame
*) data
;
6188 err
= GetEventParameter (event
, kEventParamDirectObject
,
6189 typeHICommand
, NULL
,
6190 sizeof (HICommand
), NULL
, &command
);
6194 switch (GetEventKind (event
))
6196 case kEventCommandProcess
:
6197 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
6198 result
= CallNextEventHandler (next_handler
, event
);
6201 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
6203 if (i
< f
->n_tool_bar_items
6204 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
6207 struct input_event buf
;
6211 XSETFRAME (frame
, f
);
6212 buf
.kind
= TOOL_BAR_EVENT
;
6213 buf
.frame_or_window
= frame
;
6215 kbd_buffer_store_event (&buf
);
6217 buf
.kind
= TOOL_BAR_EVENT
;
6218 buf
.frame_or_window
= frame
;
6219 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
6220 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
6221 kbd_buffer_store_event (&buf
);
6235 #endif /* USE_MAC_TOOLBAR */
6238 /***********************************************************************
6240 ***********************************************************************/
6242 /* Set clipping for output in glyph row ROW. W is the window in which
6243 we operate. GC is the graphics context to set clipping in.
6245 ROW may be a text row or, e.g., a mode line. Text rows must be
6246 clipped to the interior of the window dedicated to text display,
6247 mode lines must be clipped to the whole window. */
6250 x_clip_to_row (w
, row
, area
, gc
)
6252 struct glyph_row
*row
;
6256 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6258 int window_x
, window_y
, window_width
;
6260 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
6262 clip_rect
.left
= window_x
;
6263 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6264 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6265 clip_rect
.right
= clip_rect
.left
+ window_width
;
6266 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6268 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
6272 /* Draw a hollow box cursor on window W in glyph row ROW. */
6275 x_draw_hollow_cursor (w
, row
)
6277 struct glyph_row
*row
;
6279 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6280 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6281 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6284 struct glyph
*cursor_glyph
;
6287 /* Get the glyph the cursor is on. If we can't tell because
6288 the current matrix is invalid or such, give up. */
6289 cursor_glyph
= get_phys_cursor_glyph (w
);
6290 if (cursor_glyph
== NULL
)
6293 /* Compute frame-relative coordinates for phys cursor. */
6294 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
6295 wd
= w
->phys_cursor_width
;
6297 /* The foreground of cursor_gc is typically the same as the normal
6298 background color, which can cause the cursor box to be invisible. */
6299 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6300 if (dpyinfo
->scratch_cursor_gc
)
6301 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6303 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6304 GCForeground
, &xgcv
);
6305 gc
= dpyinfo
->scratch_cursor_gc
;
6307 /* Set clipping, draw the rectangle, and reset clipping again. */
6308 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6309 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
6310 mac_reset_clip_rectangles (dpy
, gc
);
6314 /* Draw a bar cursor on window W in glyph row ROW.
6316 Implementation note: One would like to draw a bar cursor with an
6317 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6318 Unfortunately, I didn't find a font yet that has this property set.
6322 x_draw_bar_cursor (w
, row
, width
, kind
)
6324 struct glyph_row
*row
;
6326 enum text_cursor_kinds kind
;
6328 struct frame
*f
= XFRAME (w
->frame
);
6329 struct glyph
*cursor_glyph
;
6331 /* If cursor is out of bounds, don't draw garbage. This can happen
6332 in mini-buffer windows when switching between echo area glyphs
6334 cursor_glyph
= get_phys_cursor_glyph (w
);
6335 if (cursor_glyph
== NULL
)
6338 /* If on an image, draw like a normal cursor. That's usually better
6339 visible than drawing a bar, esp. if the image is large so that
6340 the bar might not be in the window. */
6341 if (cursor_glyph
->type
== IMAGE_GLYPH
)
6343 struct glyph_row
*row
;
6344 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
6345 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
6349 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6350 Window window
= FRAME_MAC_WINDOW (f
);
6351 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6352 unsigned long mask
= GCForeground
| GCBackground
;
6353 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
6356 /* If the glyph's background equals the color we normally draw
6357 the bar cursor in, the bar cursor in its normal color is
6358 invisible. Use the glyph's foreground color instead in this
6359 case, on the assumption that the glyph's colors are chosen so
6360 that the glyph is legible. */
6361 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
6362 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
6364 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6367 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6370 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6371 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6375 width
= FRAME_CURSOR_WIDTH (f
);
6376 width
= min (cursor_glyph
->pixel_width
, width
);
6378 w
->phys_cursor_width
= width
;
6379 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
6381 if (kind
== BAR_CURSOR
)
6382 mac_fill_rectangle (f
, gc
,
6383 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6384 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6385 width
, row
->height
);
6387 mac_fill_rectangle (f
, gc
,
6388 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6389 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
6390 row
->height
- width
),
6391 cursor_glyph
->pixel_width
,
6394 mac_reset_clip_rectangles (dpy
, gc
);
6399 /* RIF: Define cursor CURSOR on frame F. */
6402 mac_define_frame_cursor (f
, cursor
)
6406 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6408 if (dpyinfo
->x_focus_frame
== f
)
6409 SetThemeCursor (cursor
);
6413 /* RIF: Clear area on frame F. */
6416 mac_clear_frame_area (f
, x
, y
, width
, height
)
6418 int x
, y
, width
, height
;
6420 mac_clear_area (f
, x
, y
, width
, height
);
6424 /* RIF: Draw cursor on window W. */
6427 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
6429 struct glyph_row
*glyph_row
;
6431 int cursor_type
, cursor_width
;
6436 w
->phys_cursor_type
= cursor_type
;
6437 w
->phys_cursor_on_p
= 1;
6439 if (glyph_row
->exact_window_width_line_p
6440 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
6442 glyph_row
->cursor_in_fringe_p
= 1;
6443 draw_fringe_bitmap (w
, glyph_row
, 0);
6446 switch (cursor_type
)
6448 case HOLLOW_BOX_CURSOR
:
6449 x_draw_hollow_cursor (w
, glyph_row
);
6452 case FILLED_BOX_CURSOR
:
6453 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6457 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
6461 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
6465 w
->phys_cursor_width
= 0;
6477 #if 0 /* MAC_TODO: no icon support yet. */
6479 x_bitmap_icon (f
, icon
)
6485 if (FRAME_W32_WINDOW (f
) == 0)
6489 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
6490 else if (STRINGP (icon
))
6491 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
6492 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
6493 else if (SYMBOLP (icon
))
6497 if (EQ (icon
, intern ("application")))
6498 name
= (LPCTSTR
) IDI_APPLICATION
;
6499 else if (EQ (icon
, intern ("hand")))
6500 name
= (LPCTSTR
) IDI_HAND
;
6501 else if (EQ (icon
, intern ("question")))
6502 name
= (LPCTSTR
) IDI_QUESTION
;
6503 else if (EQ (icon
, intern ("exclamation")))
6504 name
= (LPCTSTR
) IDI_EXCLAMATION
;
6505 else if (EQ (icon
, intern ("asterisk")))
6506 name
= (LPCTSTR
) IDI_ASTERISK
;
6507 else if (EQ (icon
, intern ("winlogo")))
6508 name
= (LPCTSTR
) IDI_WINLOGO
;
6512 hicon
= LoadIcon (NULL
, name
);
6520 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
6525 #endif /* MAC_TODO */
6527 /************************************************************************
6529 ************************************************************************/
6531 /* Display Error Handling functions not used on W32. Listing them here
6532 helps diff stay in step when comparing w32term.c with xterm.c.
6534 x_error_catcher (display, error)
6535 x_catch_errors (dpy)
6536 x_catch_errors_unwind (old_val)
6537 x_check_errors (dpy, format)
6538 x_had_errors_p (dpy)
6539 x_clear_errors (dpy)
6540 x_uncatch_errors (dpy, count)
6542 x_connection_signal (signalnum)
6543 x_connection_closed (dpy, error_message)
6544 x_error_quitter (display, error)
6545 x_error_handler (display, error)
6546 x_io_error_quitter (display)
6551 /* Changing the font of the frame. */
6553 /* Give frame F the font named FONTNAME as its default font, and
6554 return the full name of that font. FONTNAME may be a wildcard
6555 pattern; in that case, we choose some font that fits the pattern.
6556 The return value shows which font we chose. */
6559 x_new_font (f
, fontname
)
6561 register char *fontname
;
6563 struct font_info
*fontp
6564 = FS_LOAD_FONT (f
, 0, fontname
, -1);
6569 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
6570 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
6571 FRAME_FONTSET (f
) = -1;
6573 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
6574 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
6575 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
6577 compute_fringe_widths (f
, 1);
6579 /* Compute the scroll bar width in character columns. */
6580 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
6582 int wid
= FRAME_COLUMN_WIDTH (f
);
6583 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
6584 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
6588 int wid
= FRAME_COLUMN_WIDTH (f
);
6589 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
6592 /* Now make the frame display the given font. */
6593 if (FRAME_MAC_WINDOW (f
) != 0)
6595 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
6597 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
6599 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
6602 /* Don't change the size of a tip frame; there's no point in
6603 doing it because it's done in Fx_show_tip, and it leads to
6604 problems because the tip frame has no widget. */
6605 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
6606 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
6609 return build_string (fontp
->full_name
);
6612 /* Give frame F the fontset named FONTSETNAME as its default font, and
6613 return the full name of that fontset. FONTSETNAME may be a wildcard
6614 pattern; in that case, we choose some fontset that fits the pattern.
6615 The return value shows which fontset we chose. */
6618 x_new_fontset (f
, fontsetname
)
6622 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
6628 if (FRAME_FONTSET (f
) == fontset
)
6629 /* This fontset is already set in frame F. There's nothing more
6631 return fontset_name (fontset
);
6633 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
6635 if (!STRINGP (result
))
6636 /* Can't load ASCII font. */
6639 /* Since x_new_font doesn't update any fontset information, do it now. */
6640 FRAME_FONTSET (f
) = fontset
;
6642 return build_string (fontsetname
);
6646 /***********************************************************************
6647 TODO: W32 Input Methods
6648 ***********************************************************************/
6649 /* Listing missing functions from xterm.c helps diff stay in step.
6651 xim_destroy_callback (xim, client_data, call_data)
6652 xim_open_dpy (dpyinfo, resource_name)
6654 xim_instantiate_callback (display, client_data, call_data)
6655 xim_initialize (dpyinfo, resource_name)
6656 xim_close_dpy (dpyinfo)
6662 mac_get_window_bounds (f
, inner
, outer
)
6664 Rect
*inner
, *outer
;
6666 #if TARGET_API_MAC_CARBON
6667 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
6668 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
6669 #else /* not TARGET_API_MAC_CARBON */
6670 RgnHandle region
= NewRgn ();
6672 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
6673 *inner
= (*region
)->rgnBBox
;
6674 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
6675 *outer
= (*region
)->rgnBBox
;
6676 DisposeRgn (region
);
6677 #endif /* not TARGET_API_MAC_CARBON */
6681 mac_handle_origin_change (f
)
6684 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6688 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
6690 int pixelwidth
, pixelheight
;
6694 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
6695 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
6697 if (cols
!= FRAME_COLS (f
)
6698 || rows
!= FRAME_LINES (f
)
6699 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
6700 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
6702 /* We pass 1 for DELAY since we can't run Lisp code inside of
6704 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6705 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6706 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6707 SET_FRAME_GARBAGED (f
);
6709 /* If cursor was outside the new size, mark it as off. */
6710 mark_window_cursors_off (XWINDOW (f
->root_window
));
6712 /* Clear out any recollection of where the mouse highlighting
6713 was, since it might be in a place that's outside the new
6714 frame size. Actually checking whether it is outside is a
6715 pain in the neck, so don't try--just let the highlighting be
6716 done afresh with new size. */
6717 cancel_mouse_face (f
);
6719 #if TARGET_API_MAC_CARBON
6720 if (f
->output_data
.mac
->hourglass_control
)
6723 mac_prepare_for_quickdraw (f
);
6725 MoveControl (f
->output_data
.mac
->hourglass_control
,
6726 pixelwidth
- HOURGLASS_WIDTH
, 0);
6733 /* Calculate the absolute position in frame F
6734 from its current recorded position values and gravity. */
6737 x_calc_absolute_position (f
)
6740 int width_diff
= 0, height_diff
= 0;
6741 int flags
= f
->size_hint_flags
;
6744 /* We have nothing to do if the current position
6745 is already for the top-left corner. */
6746 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
6749 /* Find the offsets of the outside upper-left corner of
6750 the inner window, with respect to the outer window. */
6752 mac_get_window_bounds (f
, &inner
, &outer
);
6755 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
6756 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
6758 /* Treat negative positions as relative to the leftmost bottommost
6759 position that fits on the screen. */
6760 if (flags
& XNegative
)
6761 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
6763 - FRAME_PIXEL_WIDTH (f
)
6766 if (flags
& YNegative
)
6767 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
6769 - FRAME_PIXEL_HEIGHT (f
)
6772 /* The left_pos and top_pos
6773 are now relative to the top and left screen edges,
6774 so the flags should correspond. */
6775 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6778 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6779 to really change the position, and 0 when calling from
6780 x_make_frame_visible (in that case, XOFF and YOFF are the current
6781 position values). It is -1 when calling from x_set_frame_parameters,
6782 which means, do adjust for borders but don't change the gravity. */
6785 x_set_offset (f
, xoff
, yoff
, change_gravity
)
6787 register int xoff
, yoff
;
6790 if (change_gravity
> 0)
6794 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
6796 f
->size_hint_flags
|= XNegative
;
6798 f
->size_hint_flags
|= YNegative
;
6799 f
->win_gravity
= NorthWestGravity
;
6801 x_calc_absolute_position (f
);
6804 x_wm_set_size_hint (f
, (long) 0, 0);
6806 #if TARGET_API_MAC_CARBON
6807 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
6808 /* If the title bar is completely outside the screen, adjust the
6810 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
6811 kWindowConstrainMoveRegardlessOfFit
6812 | kWindowConstrainAllowPartial
, NULL
, NULL
);
6813 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
6814 mac_handle_origin_change (f
);
6817 Rect inner
, outer
, screen_rect
, dummy
;
6818 RgnHandle region
= NewRgn ();
6820 mac_get_window_bounds (f
, &inner
, &outer
);
6821 f
->x_pixels_diff
= inner
.left
- outer
.left
;
6822 f
->y_pixels_diff
= inner
.top
- outer
.top
;
6823 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6824 f
->top_pos
+ f
->y_pixels_diff
, false);
6826 /* If the title bar is completely outside the screen, adjust the
6827 position. The variable `outer' holds the title bar rectangle.
6828 The variable `inner' holds slightly smaller one than `outer',
6829 so that the calculation of overlapping may not become too
6831 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6832 outer
= (*region
)->rgnBBox
;
6833 DisposeRgn (region
);
6835 InsetRect (&inner
, 8, 8);
6836 screen_rect
= qd
.screenBits
.bounds
;
6837 screen_rect
.top
+= GetMBarHeight ();
6839 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6841 if (inner
.right
<= screen_rect
.left
)
6842 f
->left_pos
= screen_rect
.left
;
6843 else if (inner
.left
>= screen_rect
.right
)
6844 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6846 if (inner
.bottom
<= screen_rect
.top
)
6847 f
->top_pos
= screen_rect
.top
;
6848 else if (inner
.top
>= screen_rect
.bottom
)
6849 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6851 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6852 f
->top_pos
+ f
->y_pixels_diff
, false);
6860 /* Call this to change the size of frame F's x-window.
6861 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6862 for this size change and subsequent size changes.
6863 Otherwise we leave the window gravity unchanged. */
6866 x_set_window_size (f
, change_gravity
, cols
, rows
)
6871 int pixelwidth
, pixelheight
;
6875 check_frame_size (f
, &rows
, &cols
);
6876 f
->scroll_bar_actual_width
6877 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6879 compute_fringe_widths (f
, 0);
6881 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6882 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6884 f
->win_gravity
= NorthWestGravity
;
6885 x_wm_set_size_hint (f
, (long) 0, 0);
6887 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6889 #if TARGET_API_MAC_CARBON
6890 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6892 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6894 if (f
->output_data
.mac
->internal_border_width
6895 != FRAME_INTERNAL_BORDER_WIDTH (f
))
6897 mac_clear_window (f
);
6898 f
->output_data
.mac
->internal_border_width
6899 = FRAME_INTERNAL_BORDER_WIDTH (f
);
6902 SET_FRAME_GARBAGED (f
);
6907 /* Mouse warping. */
6909 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6912 x_set_mouse_position (f
, x
, y
)
6918 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6919 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6921 if (pix_x
< 0) pix_x
= 0;
6922 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6924 if (pix_y
< 0) pix_y
= 0;
6925 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6927 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6931 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6936 pix_x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
6937 pix_y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
6940 CGWarpMouseCursorPosition (CGPointMake (pix_x
, pix_y
));
6943 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6946 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6947 0, 0, 0, 0, pix_x
, pix_y
);
6953 /* focus shifting, raising and lowering. */
6956 x_focus_on_frame (f
)
6959 #if 0 /* This proves to be unpleasant. */
6963 /* I don't think that the ICCCM allows programs to do things like this
6964 without the interaction of the window manager. Whatever you end up
6965 doing with this code, do it to x_unfocus_frame too. */
6966 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6967 RevertToPointerRoot
, CurrentTime
);
6977 /* Raise frame F. */
6983 if (f
->async_visible
)
6986 BringToFront (FRAME_MAC_WINDOW (f
));
6991 /* Lower frame F. */
6997 if (f
->async_visible
)
7000 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
7006 XTframe_raise_lower (f
, raise_flag
)
7016 /* Change of visibility. */
7019 mac_handle_visibility_change (f
)
7022 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7023 int visible
= 0, iconified
= 0;
7024 struct input_event buf
;
7026 if (IsWindowVisible (wp
))
7028 if (IsWindowCollapsed (wp
))
7034 if (!f
->async_visible
&& visible
)
7038 /* wait_reading_process_output will notice this and update
7039 the frame's display structures. If we were made
7040 invisible, we should not set garbaged, because that stops
7041 redrawing on Update events. */
7042 SET_FRAME_GARBAGED (f
);
7045 buf
.kind
= DEICONIFY_EVENT
;
7046 XSETFRAME (buf
.frame_or_window
, f
);
7048 kbd_buffer_store_event (&buf
);
7050 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7051 /* Force a redisplay sooner or later to update the
7052 frame titles in case this is the second frame. */
7053 record_asynch_buffer_change ();
7055 else if (f
->async_visible
&& !visible
)
7059 buf
.kind
= ICONIFY_EVENT
;
7060 XSETFRAME (buf
.frame_or_window
, f
);
7062 kbd_buffer_store_event (&buf
);
7065 f
->async_visible
= visible
;
7066 f
->async_iconified
= iconified
;
7069 /* This tries to wait until the frame is really visible.
7070 However, if the window manager asks the user where to position
7071 the frame, this will return before the user finishes doing that.
7072 The frame will not actually be visible at that time,
7073 but it will become visible later when the window manager
7074 finishes with it. */
7077 x_make_frame_visible (f
)
7082 if (! FRAME_VISIBLE_P (f
))
7084 /* We test FRAME_GARBAGED_P here to make sure we don't
7085 call x_set_offset a second time
7086 if we get to x_make_frame_visible a second time
7087 before the window gets really visible. */
7088 if (! FRAME_ICONIFIED_P (f
)
7089 && ! f
->output_data
.mac
->asked_for_visible
)
7090 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
7092 f
->output_data
.mac
->asked_for_visible
= 1;
7094 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
7095 ShowWindow (FRAME_MAC_WINDOW (f
));
7098 XFlush (FRAME_MAC_DISPLAY (f
));
7100 /* Synchronize to ensure Emacs knows the frame is visible
7101 before we do anything else. We do this loop with input not blocked
7102 so that incoming events are handled. */
7107 /* This must come after we set COUNT. */
7110 XSETFRAME (frame
, f
);
7112 /* Wait until the frame is visible. Process X events until a
7113 MapNotify event has been seen, or until we think we won't get a
7114 MapNotify at all.. */
7115 for (count
= input_signal_count
+ 10;
7116 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7118 /* Force processing of queued events. */
7121 /* Machines that do polling rather than SIGIO have been
7122 observed to go into a busy-wait here. So we'll fake an
7123 alarm signal to let the handler know that there's something
7124 to be read. We used to raise a real alarm, but it seems
7125 that the handler isn't always enabled here. This is
7127 if (input_polling_used ())
7129 /* It could be confusing if a real alarm arrives while
7130 processing the fake one. Turn it off and let the
7131 handler reset it. */
7132 extern void poll_for_input_1
P_ ((void));
7133 int old_poll_suppress_count
= poll_suppress_count
;
7134 poll_suppress_count
= 1;
7135 poll_for_input_1 ();
7136 poll_suppress_count
= old_poll_suppress_count
;
7139 /* See if a MapNotify event has been processed. */
7140 FRAME_SAMPLE_VISIBILITY (f
);
7145 /* Change from mapped state to withdrawn state. */
7147 /* Make the frame visible (mapped and not iconified). */
7150 x_make_frame_invisible (f
)
7153 /* A deactivate event does not occur when the last visible frame is
7154 made invisible. So if we clear the highlight here, it will not
7155 be rehighlighted when it is made visible. */
7157 /* Don't keep the highlight on an invisible frame. */
7158 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7159 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7164 #if !TARGET_API_MAC_CARBON
7165 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7166 that the current position of the window is user-specified, rather than
7167 program-specified, so that when the window is mapped again, it will be
7168 placed at the same location, without forcing the user to position it
7169 by hand again (they have already done that once for this window.) */
7170 x_wm_set_size_hint (f
, (long) 0, 1);
7173 HideWindow (FRAME_MAC_WINDOW (f
));
7177 #if !TARGET_API_MAC_CARBON
7178 mac_handle_visibility_change (f
);
7182 /* Change window state from mapped to iconified. */
7190 /* A deactivate event does not occur when the last visible frame is
7191 iconified. So if we clear the highlight here, it will not be
7192 rehighlighted when it is deiconified. */
7194 /* Don't keep the highlight on an invisible frame. */
7195 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7196 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7199 if (f
->async_iconified
)
7204 FRAME_SAMPLE_VISIBILITY (f
);
7206 if (! FRAME_VISIBLE_P (f
))
7207 ShowWindow (FRAME_MAC_WINDOW (f
));
7209 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7214 error ("Can't notify window manager of iconification");
7216 #if !TARGET_API_MAC_CARBON
7217 mac_handle_visibility_change (f
);
7222 /* Free X resources of frame F. */
7225 x_free_frame_resources (f
)
7228 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7229 WindowRef wp
= FRAME_MAC_WINDOW (f
);
7233 if (wp
!= tip_window
)
7234 remove_window_handler (wp
);
7237 mac_prepare_for_quickdraw (f
);
7240 if (wp
== tip_window
)
7241 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7242 closed' event. So we reset tip_window here. */
7245 free_frame_menubar (f
);
7247 if (FRAME_FACE_CACHE (f
))
7248 free_frame_faces (f
);
7252 if (FRAME_SIZE_HINTS (f
))
7253 xfree (FRAME_SIZE_HINTS (f
));
7255 xfree (f
->output_data
.mac
);
7256 f
->output_data
.mac
= NULL
;
7258 if (f
== dpyinfo
->x_focus_frame
)
7260 dpyinfo
->x_focus_frame
= 0;
7261 #if USE_MAC_FONT_PANEL
7262 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
7265 if (f
== dpyinfo
->x_focus_event_frame
)
7266 dpyinfo
->x_focus_event_frame
= 0;
7267 if (f
== dpyinfo
->x_highlight_frame
)
7268 dpyinfo
->x_highlight_frame
= 0;
7270 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7272 dpyinfo
->mouse_face_beg_row
7273 = dpyinfo
->mouse_face_beg_col
= -1;
7274 dpyinfo
->mouse_face_end_row
7275 = dpyinfo
->mouse_face_end_col
= -1;
7276 dpyinfo
->mouse_face_window
= Qnil
;
7277 dpyinfo
->mouse_face_deferred_gc
= 0;
7278 dpyinfo
->mouse_face_mouse_frame
= 0;
7285 /* Destroy the X window of frame F. */
7288 x_destroy_window (f
)
7291 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7293 x_free_frame_resources (f
);
7295 dpyinfo
->reference_count
--;
7299 /* Setting window manager hints. */
7301 /* Set the normal size hints for the window manager, for frame F.
7302 FLAGS is the flags word to use--or 0 meaning preserve the flags
7303 that the window now has.
7304 If USER_POSITION is nonzero, we set the USPosition
7305 flag (this is useful when FLAGS is 0). */
7307 x_wm_set_size_hint (f
, flags
, user_position
)
7312 int base_width
, base_height
, width_inc
, height_inc
;
7313 int min_rows
= 0, min_cols
= 0;
7314 XSizeHints
*size_hints
;
7316 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
7317 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
7318 width_inc
= FRAME_COLUMN_WIDTH (f
);
7319 height_inc
= FRAME_LINE_HEIGHT (f
);
7321 check_frame_size (f
, &min_rows
, &min_cols
);
7323 size_hints
= FRAME_SIZE_HINTS (f
);
7324 if (size_hints
== NULL
)
7326 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
7327 bzero (size_hints
, sizeof (XSizeHints
));
7330 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
7331 size_hints
->width_inc
= width_inc
;
7332 size_hints
->height_inc
= height_inc
;
7333 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
7334 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
7335 size_hints
->base_width
= base_width
;
7336 size_hints
->base_height
= base_height
;
7339 size_hints
->flags
= flags
;
7340 else if (user_position
)
7342 size_hints
->flags
&= ~ PPosition
;
7343 size_hints
->flags
|= USPosition
;
7347 #if 0 /* MAC_TODO: hide application instead of iconify? */
7348 /* Used for IconicState or NormalState */
7351 x_wm_set_window_state (f
, state
)
7355 #ifdef USE_X_TOOLKIT
7358 XtSetArg (al
[0], XtNinitialState
, state
);
7359 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7360 #else /* not USE_X_TOOLKIT */
7361 Window window
= FRAME_X_WINDOW (f
);
7363 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7364 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7366 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7367 #endif /* not USE_X_TOOLKIT */
7371 x_wm_set_icon_pixmap (f
, pixmap_id
)
7377 #ifndef USE_X_TOOLKIT
7378 Window window
= FRAME_X_WINDOW (f
);
7383 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7384 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7388 /* It seems there is no way to turn off use of an icon pixmap.
7389 The following line does it, only if no icon has yet been created,
7390 for some window managers. But with mwm it crashes.
7391 Some people say it should clear the IconPixmapHint bit in this case,
7392 but that doesn't work, and the X consortium said it isn't the
7393 right thing at all. Since there is no way to win,
7394 best to explicitly give up. */
7396 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7402 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7406 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7407 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7410 #else /* not USE_X_TOOLKIT */
7412 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7413 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7415 #endif /* not USE_X_TOOLKIT */
7418 #endif /* MAC_TODO */
7421 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7425 #if 0 /* MAC_TODO: no icons on Mac */
7426 #ifdef USE_X_TOOLKIT
7427 Window window
= XtWindow (f
->output_data
.x
->widget
);
7429 Window window
= FRAME_X_WINDOW (f
);
7432 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7433 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7434 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7436 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7437 #endif /* MAC_TODO */
7441 /***********************************************************************
7443 ***********************************************************************/
7445 /* An XLFD pattern is divided into blocks delimited by '*'. This
7446 structure holds information for each block. */
7447 struct xlfdpat_block
7449 /* Length of the pattern string in this block. Non-zero except for
7450 the first and the last blocks. */
7453 /* Pattern string except the last character in this block. The last
7454 character is replaced with NUL in order to use it as a
7456 unsigned char *pattern
;
7458 /* Last character of the pattern string. Must not be '?'. */
7459 unsigned char last_char
;
7461 /* One of the tables for the Boyer-Moore string search. It
7462 specifies the number of positions to proceed for each character
7463 with which the match fails. */
7466 /* The skip value for the last character in the above `skip' is
7467 assigned to `infinity' in order to simplify a loop condition.
7468 The original value is saved here. */
7474 /* Normalized pattern string. "Normalized" means that capital
7475 letters are lowered, blocks are not empty except the first and
7476 the last ones, and trailing '?'s in a block that is not the last
7477 one are moved to the next one. The last character in each block
7478 is replaced with NUL. */
7481 /* Number of characters except '*'s and trailing '?'s in the
7482 normalized pattern string. */
7485 /* Number of trailing '?'s in the normalized pattern string. */
7486 int trailing_anychars
;
7488 /* Number of blocks and information for each block. The latter is
7489 NULL if the pattern is exact (no '*' or '?' in it). */
7491 struct xlfdpat_block
*blocks
;
7495 xlfdpat_destroy (pat
)
7496 struct xlfdpat
*pat
;
7503 xfree (pat
->blocks
);
7510 static struct xlfdpat
*
7511 xlfdpat_create (pattern
)
7512 const char *pattern
;
7514 struct xlfdpat
*pat
;
7515 int nblocks
, i
, skip
;
7516 unsigned char last_char
, *p
, *q
, *anychar_head
;
7517 const unsigned char *ptr
;
7518 struct xlfdpat_block
*blk
;
7520 pat
= xmalloc (sizeof (struct xlfdpat
));
7521 pat
->buf
= xmalloc (strlen (pattern
) + 1);
7523 /* Normalize the pattern string and store it to `pat->buf'. */
7525 anychar_head
= NULL
;
7528 for (ptr
= pattern
; *ptr
; ptr
++)
7530 unsigned char c
= *ptr
;
7533 if (last_char
== '*')
7534 /* ...a** -> ...a* */
7538 if (last_char
== '?')
7540 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
7541 /* ...*??* -> ...*?? */
7544 /* ...a??* -> ...a*?? */
7546 *anychar_head
++ = '*';
7554 if (last_char
!= '?')
7558 /* On Mac OS X 10.3, tolower also converts non-ASCII
7559 characters for some locales. */
7563 *q
++ = last_char
= c
;
7567 pat
->nblocks
= nblocks
;
7568 if (last_char
!= '?')
7569 pat
->trailing_anychars
= 0;
7572 pat
->trailing_anychars
= q
- anychar_head
;
7575 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
7577 if (anychar_head
== NULL
&& nblocks
== 1)
7579 /* The pattern is exact. */
7584 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
7586 /* Divide the normalized pattern into blocks. */
7588 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
7593 blk
->len
= p
- blk
->pattern
;
7597 blk
->len
= q
- blk
->pattern
;
7599 /* Setup a table for the Boyer-Moore string search. */
7600 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
7603 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
7604 blk
->pattern
[blk
->len
- 1] = '\0';
7606 for (skip
= 1; skip
< blk
->len
; skip
++)
7607 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
7610 for (i
= 0; i
< 256; i
++)
7611 blk
->skip
[i
] = skip
;
7613 p
= blk
->pattern
+ (blk
->len
- skip
);
7615 blk
->skip
[*p
++] = skip
;
7617 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
7624 xlfdpat_exact_p (pat
)
7625 struct xlfdpat
*pat
;
7627 return pat
->blocks
== NULL
;
7630 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7631 that the pattern in *BLK matches with its prefix. Return NULL
7632 there is no such strings. STRING must be lowered in advance. */
7635 xlfdpat_block_match_1 (blk
, string
, start_max
)
7636 struct xlfdpat_block
*blk
;
7637 const unsigned char *string
;
7640 int start
, infinity
;
7642 const unsigned char *s
;
7644 xassert (blk
->len
> 0);
7645 xassert (start_max
+ blk
->len
<= strlen (string
));
7646 xassert (blk
->last_char
!= '?');
7648 /* See the comments in the function `boyer_moore' (search.c) for the
7649 use of `infinity'. */
7650 infinity
= start_max
+ blk
->len
+ 1;
7651 blk
->skip
[blk
->last_char
] = infinity
;
7656 /* Check the last character of the pattern. */
7657 s
= string
+ blk
->len
- 1;
7660 start
+= blk
->skip
[*(s
+ start
)];
7662 while (start
<= start_max
);
7664 if (start
< infinity
)
7665 /* Couldn't find the last character. */
7668 /* No less than `infinity' means we could find the last
7669 character at `s[start - infinity]'. */
7672 /* Check the remaining characters. We prefer making no-'?'
7673 cases faster because the use of '?' is really rare. */
7678 while (*p
++ == *s
++)
7681 while (*(p
- 1) == '?');
7683 if (*(p
- 1) == '\0')
7685 return string
+ start
;
7688 start
+= blk
->last_char_skip
;
7690 while (start
<= start_max
);
7695 #define xlfdpat_block_match(b, s, m) \
7696 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7697 : xlfdpat_block_match_1 (b, s, m))
7699 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7700 matches with STRING. STRING must be lowered in advance. */
7703 xlfdpat_match (pat
, string
)
7704 struct xlfdpat
*pat
;
7705 const unsigned char *string
;
7707 int str_len
, nblocks
, i
, start_max
;
7708 struct xlfdpat_block
*blk
;
7709 const unsigned char *s
;
7711 xassert (pat
->nblocks
> 0);
7713 if (xlfdpat_exact_p (pat
))
7714 return strcmp (pat
->buf
, string
) == 0;
7716 /* The number of the characters in the string must not be smaller
7717 than that in the pattern. */
7718 str_len
= strlen (string
);
7719 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
7722 /* Chop off the trailing '?'s. */
7723 str_len
-= pat
->trailing_anychars
;
7725 /* The last block. When it is non-empty, it must match at the end
7727 nblocks
= pat
->nblocks
;
7728 blk
= pat
->blocks
+ (nblocks
- 1);
7730 /* The last block is also the first one. */
7731 return (str_len
== blk
->len
7732 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
7733 else if (blk
->len
!= 0)
7734 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
7737 /* The first block. When it is non-empty, it must match at the
7738 beginning of the string. */
7742 s
= xlfdpat_block_match (blk
, string
, 0);
7745 string
= s
+ blk
->len
;
7748 /* The rest of the blocks. */
7749 start_max
= str_len
- pat
->nchars
;
7750 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
7752 s
= xlfdpat_block_match (blk
, string
, start_max
);
7755 start_max
-= s
- string
;
7756 string
= s
+ blk
->len
;
7763 /***********************************************************************
7765 ***********************************************************************/
7767 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7770 x_get_font_info (f
, font_idx
)
7774 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7777 /* the global font name table */
7778 static char **font_name_table
= NULL
;
7779 static int font_name_table_size
= 0;
7780 static int font_name_count
= 0;
7782 /* Alist linking font family names to Font Manager font family
7783 references (which can also be used as QuickDraw font IDs). We use
7784 an alist because hash tables are not ready when the terminal frame
7785 for Mac OS Classic is created. */
7786 static Lisp_Object fm_font_family_alist
;
7788 /* Hash table linking font family names to ATSU font IDs. */
7789 static Lisp_Object atsu_font_id_hash
;
7790 /* Alist linking Font Manager style to face attributes. */
7791 static Lisp_Object fm_style_face_attributes_alist
;
7792 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
7795 /* Alist linking character set strings to Mac text encoding and Emacs
7797 static Lisp_Object Vmac_charset_info_alist
;
7800 create_text_encoding_info_alist ()
7802 Lisp_Object result
= Qnil
, rest
;
7804 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
7806 Lisp_Object charset_info
= XCAR (rest
);
7807 Lisp_Object charset
, coding_system
, text_encoding
;
7808 Lisp_Object existing_info
;
7810 if (!(CONSP (charset_info
)
7811 && (charset
= XCAR (charset_info
),
7813 && CONSP (XCDR (charset_info
))
7814 && (text_encoding
= XCAR (XCDR (charset_info
)),
7815 INTEGERP (text_encoding
))
7816 && CONSP (XCDR (XCDR (charset_info
)))
7817 && (coding_system
= XCAR (XCDR (XCDR (charset_info
))),
7818 SYMBOLP (coding_system
))))
7821 existing_info
= assq_no_quit (text_encoding
, result
);
7822 if (NILP (existing_info
))
7823 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7826 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7827 XSETCDR (XCDR (existing_info
),
7828 Fcons (charset
, XCDR (XCDR (existing_info
))));
7836 decode_mac_font_name (name
, size
, coding_system
)
7839 Lisp_Object coding_system
;
7841 struct coding_system coding
;
7844 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7846 for (p
= name
; *p
; p
++)
7847 if (!isascii (*p
) || iscntrl (*p
))
7852 setup_coding_system (coding_system
, &coding
);
7853 coding
.src_multibyte
= 0;
7854 coding
.dst_multibyte
= 1;
7855 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7856 coding
.composing
= COMPOSITION_DISABLED
;
7857 buf
= (char *) alloca (size
);
7859 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7860 bcopy (buf
, name
, coding
.produced
);
7861 name
[coding
.produced
] = '\0';
7865 /* If there's just one occurrence of '-' in the family name, it is
7866 replaced with '_'. (More than one occurrence of '-' means a
7867 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7868 p
= strchr (name
, '-');
7869 if (p
&& strchr (p
+ 1, '-') == NULL
)
7872 for (p
= name
; *p
; p
++)
7873 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7874 for some locales. */
7881 mac_to_x_fontname (name
, size
, style
, charset
)
7889 char xf
[256], *result
;
7892 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7896 strcpy(foundry
, "Apple");
7897 strcpy(family
, name
);
7900 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7901 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7902 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7904 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7905 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7906 for (p
= result
; *p
; p
++)
7907 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7908 for some locales. */
7915 /* Parse fully-specified and instantiated X11 font spec XF, and store
7916 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7917 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7918 caller must allocate at least 256 and 32 bytes respectively. For
7919 ordinary Mac fonts, the value stored to FAMILY should just be their
7920 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7921 intlfonts collection contain their charset designation in their
7922 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7923 types of font names are handled accordingly. */
7925 const int kDefaultFontSize
= 12;
7928 parse_x_font_name (xf
, family
, size
, style
, charset
)
7935 Str31 foundry
, weight
;
7936 int point_size
, avgwidth
;
7939 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7940 foundry
, family
, weight
, slant
, size
,
7941 &point_size
, &avgwidth
, charset
) != 8
7942 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7943 foundry
, family
, weight
, slant
, size
,
7944 &point_size
, &avgwidth
, charset
) != 8)
7950 *size
= point_size
/ 10;
7951 else if (avgwidth
> 0)
7952 *size
= avgwidth
/ 10;
7955 *size
= kDefaultFontSize
;
7958 if (strcmp (weight
, "bold") == 0)
7963 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7965 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7967 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7969 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7970 but take overlap into account. */
7971 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7972 memcpy (family
, foundry
, foundry_len
);
7973 family
[foundry_len
] = '-';
7974 family
[foundry_len
+ 1 + family_len
] = '-';
7975 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7981 for (p
= family
; *p
; p
++)
7982 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7983 for some locales. */
7992 add_font_name_table_entry (char *font_name
)
7994 if (font_name_table_size
== 0)
7996 font_name_table_size
= 256;
7997 font_name_table
= (char **)
7998 xmalloc (font_name_table_size
* sizeof (char *));
8000 else if (font_name_count
+ 1 >= font_name_table_size
)
8002 font_name_table_size
*= 2;
8003 font_name_table
= (char **)
8004 xrealloc (font_name_table
,
8005 font_name_table_size
* sizeof (char *));
8008 font_name_table
[font_name_count
++] = font_name
;
8012 add_mac_font_name (name
, size
, style
, charset
)
8016 const char *charset
;
8019 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
8022 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
8023 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
8024 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
8025 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
8032 fm_get_style_from_font (font
)
8036 FMFontStyle style
= normal
;
8039 FMFontFamily font_family
;
8040 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8042 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8043 some font (e.g., Optima) even if it is `bold'. */
8044 err
= FMGetFontTable (font
, 'head', FONT_HEADER_MAC_STYLE_OFFSET
,
8045 sizeof (mac_style
), &mac_style
, &len
);
8047 && len
>= FONT_HEADER_MAC_STYLE_OFFSET
+ sizeof (mac_style
))
8048 style
= EndianU16_BtoN (mac_style
);
8050 FMGetFontFamilyInstanceFromFont (font
, &font_family
, &style
);
8056 atsu_find_font_from_family_name (family
)
8059 struct Lisp_Hash_Table
*h
= XHASH_TABLE (atsu_font_id_hash
);
8062 Lisp_Object rest
, best
;
8063 FMFontStyle min_style
, style
;
8065 i
= hash_lookup (h
, make_unibyte_string (family
, strlen (family
)),
8068 return kATSUInvalidFontID
;
8070 rest
= HASH_VALUE (h
, i
);
8071 if (INTEGERP (rest
) || (CONSP (rest
) && INTEGERP (XCDR (rest
))))
8072 return cons_to_long (rest
);
8074 rest
= Fnreverse (rest
);
8078 && (min_style
= fm_get_style_from_font (cons_to_long (best
))) != normal
)
8081 style
= fm_get_style_from_font (cons_to_long (XCAR (rest
)));
8082 if (style
< min_style
)
8085 if (style
== normal
)
8092 while (!NILP (rest
));
8094 HASH_VALUE (h
, i
) = best
;
8095 return cons_to_long (best
);
8099 fm_style_to_face_attributes (fm_style
)
8100 FMFontStyle fm_style
;
8104 fm_style
&= (bold
| italic
);
8105 tem
= assq_no_quit (make_number (fm_style
),
8106 fm_style_face_attributes_alist
);
8110 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
8111 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
8112 fm_style_face_attributes_alist
=
8113 Fcons (Fcons (make_number (fm_style
), tem
),
8114 fm_style_face_attributes_alist
);
8120 atsu_find_font_family_name (font_id
)
8125 Lisp_Object family
= Qnil
;
8127 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8128 kFontMacintoshPlatform
, kFontNoScript
,
8129 kFontNoLanguage
, 0, NULL
, &len
, NULL
);
8132 family
= make_uninit_string (len
);
8133 err
= ATSUFindFontName (font_id
, kFontFamilyName
,
8134 kFontMacintoshPlatform
, kFontNoScript
,
8135 kFontNoLanguage
, len
, SDATA (family
),
8139 decode_mac_font_name (SDATA (family
), len
+ 1, Qnil
);
8145 mac_atsu_font_face_attributes (font_id
)
8148 Lisp_Object family
, style_attrs
;
8150 family
= atsu_find_font_family_name (font_id
);
8153 style_attrs
= fm_style_to_face_attributes (fm_get_style_from_font (font_id
));
8154 return Fcons (QCfamily
, Fcons (family
, style_attrs
));
8158 /* Sets up the table font_name_table to contain the list of all fonts
8159 in the system the first time the table is used so that the Resource
8160 Manager need not be accessed every time this information is
8164 init_font_name_table ()
8166 #if TARGET_API_MAC_CARBON
8167 FMFontFamilyIterator ffi
;
8168 FMFontFamilyInstanceIterator ffii
;
8170 Lisp_Object text_encoding_info_alist
;
8171 struct gcpro gcpro1
;
8173 text_encoding_info_alist
= create_text_encoding_info_alist ();
8176 #if USE_CG_TEXT_DRAWING
8177 init_cg_text_anti_aliasing_threshold ();
8179 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
8180 text_encoding_info_alist
)))
8183 struct Lisp_Hash_Table
*h
;
8185 ItemCount nfonts
, i
;
8186 ATSUFontID
*font_ids
= NULL
;
8187 Lisp_Object prev_family
= Qnil
;
8191 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
8192 make_float (DEFAULT_REHASH_SIZE
),
8193 make_float (DEFAULT_REHASH_THRESHOLD
),
8195 h
= XHASH_TABLE (atsu_font_id_hash
);
8197 err
= ATSUFontCount (&nfonts
);
8200 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
8201 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
8204 for (i
= 0; i
< nfonts
; i
++)
8208 family
= atsu_find_font_family_name (font_ids
[i
]);
8209 if (NILP (family
) || SREF (family
, 0) == '.')
8211 if (!NILP (Fequal (prev_family
, family
)))
8212 family
= prev_family
;
8214 j
= hash_lookup (h
, family
, &hash_code
);
8217 add_mac_font_name (SDATA (family
), 0, normal
, "iso10646-1");
8218 j
= hash_put (h
, family
, Fcons (long_to_cons (font_ids
[i
]),
8221 else if (EQ (prev_family
, family
))
8222 HASH_VALUE (h
, j
) = Fcons (long_to_cons (font_ids
[i
]),
8224 prev_family
= family
;
8231 /* Create a dummy instance iterator here to avoid creating and
8232 destroying it in the loop. */
8233 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8235 /* Create an iterator to enumerate the font families. */
8236 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8239 FMDisposeFontFamilyInstanceIterator (&ffii
);
8243 GCPRO1 (text_encoding_info_alist
);
8245 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8251 TextEncoding encoding
;
8252 TextEncodingBase sc
;
8253 Lisp_Object text_encoding_info
, family
;
8255 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8261 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
8263 sc
= GetTextEncodingBase (encoding
);
8264 text_encoding_info
= assq_no_quit (make_number (sc
),
8265 text_encoding_info_alist
);
8266 if (NILP (text_encoding_info
))
8267 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
8268 text_encoding_info_alist
);
8269 decode_mac_font_name (name
, sizeof (name
),
8270 XCAR (XCDR (text_encoding_info
)));
8271 family
= build_string (name
);
8272 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8274 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
8275 fm_font_family_alist
);
8277 /* Point the instance iterator at the current font family. */
8278 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
8281 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8284 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8286 if (size
> 0 || style
== normal
)
8287 for (; !NILP (rest
); rest
= XCDR (rest
))
8288 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
8294 /* Dispose of the iterators. */
8295 FMDisposeFontFamilyIterator (&ffi
);
8296 FMDisposeFontFamilyInstanceIterator (&ffii
);
8297 #else /* !TARGET_API_MAC_CARBON */
8299 SInt16 fontnum
, old_fontnum
;
8300 int num_mac_fonts
= CountResources('FOND');
8302 Handle font_handle
, font_handle_2
;
8303 short id
, scriptcode
;
8306 struct FontAssoc
*fat
;
8307 struct AsscEntry
*assc_entry
;
8308 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
8309 struct gcpro gcpro1
;
8311 GetPort (&port
); /* save the current font number used */
8312 old_fontnum
= port
->txFont
;
8314 text_encoding_info_alist
= create_text_encoding_info_alist ();
8316 GCPRO1 (text_encoding_info_alist
);
8318 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8320 font_handle
= GetIndResource ('FOND', i
);
8324 GetResInfo (font_handle
, &id
, &type
, name
);
8325 GetFNum (name
, &fontnum
);
8327 if (fontnum
== 0 || *name
== '.')
8331 scriptcode
= FontToScript (fontnum
);
8332 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
8333 text_encoding_info_alist
);
8334 if (NILP (text_encoding_info
))
8335 text_encoding_info
= assq_no_quit (make_number (smRoman
),
8336 text_encoding_info_alist
);
8337 decode_mac_font_name (name
, sizeof (name
),
8338 XCAR (XCDR (text_encoding_info
)));
8339 family
= build_string (name
);
8340 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
8342 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
8343 fm_font_family_alist
);
8346 HLock (font_handle
);
8348 if (GetResourceSizeOnDisk (font_handle
)
8349 >= sizeof (struct FamRec
))
8351 fat
= (struct FontAssoc
*) (*font_handle
8352 + sizeof (struct FamRec
));
8354 = (struct AsscEntry
*) (*font_handle
8355 + sizeof (struct FamRec
)
8356 + sizeof (struct FontAssoc
));
8358 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8360 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
8362 for (; !NILP (rest
); rest
= XCDR (rest
))
8363 add_mac_font_name (name
, assc_entry
->fontSize
,
8364 assc_entry
->fontStyle
,
8365 SDATA (XCAR (rest
)));
8369 HUnlock (font_handle
);
8370 font_handle_2
= GetNextFOND (font_handle
);
8371 ReleaseResource (font_handle
);
8372 font_handle
= font_handle_2
;
8374 while (ResError () == noErr
&& font_handle
);
8379 TextFont (old_fontnum
);
8380 #endif /* !TARGET_API_MAC_CARBON */
8385 mac_clear_font_name_table ()
8389 for (i
= 0; i
< font_name_count
; i
++)
8390 xfree (font_name_table
[i
]);
8391 xfree (font_name_table
);
8392 font_name_table
= NULL
;
8393 font_name_table_size
= font_name_count
= 0;
8394 fm_font_family_alist
= Qnil
;
8398 enum xlfd_scalable_field_index
8400 XLFD_SCL_PIXEL_SIZE
,
8401 XLFD_SCL_POINT_SIZE
,
8406 static const int xlfd_scalable_fields
[] =
8415 mac_do_list_fonts (pattern
, maxnames
)
8416 const char *pattern
;
8420 Lisp_Object font_list
= Qnil
;
8421 struct xlfdpat
*pat
;
8424 int scl_val
[XLFD_SCL_LAST
], *val
;
8428 if (font_name_table
== NULL
) /* Initialize when first used. */
8429 init_font_name_table ();
8431 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
8434 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8435 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8436 fonts are scaled according to the specified size. */
8439 field
= xlfd_scalable_fields
;
8447 if ('0' <= *ptr
&& *ptr
<= '9')
8449 *val
= *ptr
++ - '0';
8450 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
8451 *val
= *val
* 10 + *ptr
++ - '0';
8458 ptr
= strchr (ptr
, '-');
8461 while (ptr
&& i
< 14);
8463 if (i
== 14 && ptr
== NULL
)
8465 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
8466 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
8467 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
8468 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
8470 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
8471 scl_val
[XLFD_SCL_POINT_SIZE
] =
8472 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8473 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
8475 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
8476 scl_val
[XLFD_SCL_AVGWIDTH
] =
8477 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
8478 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
8482 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
8484 pat
= xlfdpat_create (pattern
);
8488 exact
= xlfdpat_exact_p (pat
);
8490 for (i
= 0; i
< font_name_count
; i
++)
8492 if (xlfdpat_match (pat
, font_name_table
[i
]))
8494 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
8495 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8498 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
8499 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
8501 int former_len
= ptr
- font_name_table
[i
];
8503 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
8504 memcpy (scaled
, font_name_table
[i
], former_len
);
8505 sprintf (scaled
+ former_len
,
8506 "-%d-%d-72-72-m-%d-%s",
8507 scl_val
[XLFD_SCL_PIXEL_SIZE
],
8508 scl_val
[XLFD_SCL_POINT_SIZE
],
8509 scl_val
[XLFD_SCL_AVGWIDTH
],
8510 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
8512 if (xlfdpat_match (pat
, scaled
))
8514 font_list
= Fcons (build_string (scaled
), font_list
);
8516 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
8524 xlfdpat_destroy (pat
);
8529 /* Return a list of names of available fonts matching PATTERN on frame F.
8531 Frame F null means we have not yet created any frame on Mac, and
8532 consult the first display in x_display_list. MAXNAMES sets a limit
8533 on how many fonts to match. */
8536 x_list_fonts (f
, pattern
, size
, maxnames
)
8538 Lisp_Object pattern
;
8541 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
8542 struct mac_display_info
*dpyinfo
8543 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
8545 xassert (size
<= 0);
8547 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
8548 if (NILP (patterns
))
8549 patterns
= Fcons (pattern
, Qnil
);
8551 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
8553 pattern
= XCAR (patterns
);
8555 if (!STRINGP (pattern
))
8558 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
8559 key
= Fcons (pattern
, make_number (maxnames
));
8561 list
= Fassoc (key
, tem
);
8564 list
= Fcdr_safe (list
);
8565 /* We have a cashed list. Don't have to get the list again. */
8570 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
8573 /* MAC_TODO: add code for matching outline fonts here */
8575 /* Now store the result in the cache. */
8576 XSETCAR (XCDR (dpyinfo
->name_list_element
),
8577 Fcons (Fcons (key
, list
),
8578 XCAR (XCDR (dpyinfo
->name_list_element
))));
8581 if (NILP (list
)) continue; /* Try the remaining alternatives. */
8590 /* Check that FONT is valid on frame F. It is if it can be found in F's
8594 x_check_font (f
, font
)
8599 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8601 xassert (font
!= NULL
);
8603 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8604 if (dpyinfo
->font_table
[i
].name
8605 && font
== dpyinfo
->font_table
[i
].font
)
8608 xassert (i
< dpyinfo
->n_fonts
);
8611 #endif /* GLYPH_DEBUG != 0 */
8613 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8614 Note: There are (broken) X fonts out there with invalid XFontStruct
8615 min_bounds contents. For example, handa@etl.go.jp reports that
8616 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8617 have font->min_bounds.width == 0. */
8620 x_font_min_bounds (font
, w
, h
)
8621 MacFontStruct
*font
;
8624 *h
= FONT_HEIGHT (font
);
8625 *w
= font
->min_bounds
.width
;
8629 /* Compute the smallest character width and smallest font height over
8630 all fonts available on frame F. Set the members smallest_char_width
8631 and smallest_font_height in F's x_display_info structure to
8632 the values computed. Value is non-zero if smallest_font_height or
8633 smallest_char_width become smaller than they were before. */
8636 x_compute_min_glyph_bounds (f
)
8640 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8641 MacFontStruct
*font
;
8642 int old_width
= dpyinfo
->smallest_char_width
;
8643 int old_height
= dpyinfo
->smallest_font_height
;
8645 dpyinfo
->smallest_font_height
= 100000;
8646 dpyinfo
->smallest_char_width
= 100000;
8648 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8649 if (dpyinfo
->font_table
[i
].name
)
8651 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8654 font
= (MacFontStruct
*) fontp
->font
;
8655 xassert (font
!= (MacFontStruct
*) ~0);
8656 x_font_min_bounds (font
, &w
, &h
);
8658 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8659 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8662 xassert (dpyinfo
->smallest_char_width
> 0
8663 && dpyinfo
->smallest_font_height
> 0);
8665 return (dpyinfo
->n_fonts
== 1
8666 || dpyinfo
->smallest_char_width
< old_width
8667 || dpyinfo
->smallest_font_height
< old_height
);
8671 /* Determine whether given string is a fully-specified XLFD: all 14
8672 fields are present, none is '*'. */
8675 is_fully_specified_xlfd (p
)
8684 for (i
= 0; i
< 13; i
++)
8686 q
= strchr (p
+ 1, '-');
8689 if (q
- p
== 2 && *(p
+ 1) == '*')
8694 if (strchr (p
+ 1, '-') != NULL
)
8697 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8704 /* mac_load_query_font creates and returns an internal representation
8705 for a font in a MacFontStruct struct. There is really no concept
8706 corresponding to "loading" a font on the Mac. But we check its
8707 existence and find the font number and all other information for it
8708 and store them in the returned MacFontStruct. */
8710 static MacFontStruct
*
8711 mac_load_query_font (f
, fontname
)
8721 static ATSUFontID font_id
;
8722 ATSUStyle mac_style
= NULL
;
8725 #if TARGET_API_MAC_CARBON
8726 TextEncoding encoding
;
8731 MacFontStruct
*font
;
8732 XCharStruct
*space_bounds
= NULL
, *pcm
;
8734 if (is_fully_specified_xlfd (fontname
))
8738 Lisp_Object matched_fonts
;
8740 matched_fonts
= mac_do_list_fonts (fontname
, 1);
8741 if (NILP (matched_fonts
))
8743 name
= SDATA (XCAR (matched_fonts
));
8746 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
8750 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
8753 static const ATSUAttributeTag tags
[] =
8754 {kATSUFontTag
, kATSUSizeTag
,
8755 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
8756 static const ByteCount sizes
[] =
8757 {sizeof (ATSUFontID
), sizeof (Fixed
),
8758 sizeof (Boolean
), sizeof (Boolean
)};
8759 static Fixed size_fixed
;
8760 static Boolean bold_p
, italic_p
;
8761 static const ATSUAttributeValuePtr values
[] =
8762 {&font_id
, &size_fixed
,
8763 &bold_p
, &italic_p
};
8764 static const ATSUFontFeatureType types
[] =
8765 {kAllTypographicFeaturesType
, kDiacriticsType
};
8766 static const ATSUFontFeatureSelector selectors
[] =
8767 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
8770 font_id
= atsu_find_font_from_family_name (family
);
8771 if (font_id
== kATSUInvalidFontID
)
8773 size_fixed
= Long2Fix (size
);
8774 bold_p
= (fontface
& bold
) != 0;
8775 italic_p
= (fontface
& italic
) != 0;
8776 err
= ATSUCreateStyle (&mac_style
);
8779 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
8783 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
8784 tags
, sizes
, values
);
8787 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
8790 scriptcode
= kTextEncodingMacUnicode
;
8795 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
8799 fontnum
= XINT (XCDR (tmp
));
8800 #if TARGET_API_MAC_CARBON
8801 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
8803 scriptcode
= GetTextEncodingBase (encoding
);
8805 scriptcode
= FontToScript (fontnum
);
8809 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8811 font
->mac_fontnum
= fontnum
;
8812 font
->mac_fontsize
= size
;
8813 font
->mac_fontface
= fontface
;
8814 font
->mac_scriptcode
= scriptcode
;
8816 font
->mac_style
= mac_style
;
8817 #if USE_CG_TEXT_DRAWING
8818 font
->cg_font
= NULL
;
8819 font
->cg_glyphs
= NULL
;
8823 /* Apple Japanese (SJIS) font is listed as both
8824 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8825 (Roman script) in init_font_name_table (). The latter should be
8826 treated as a one-byte font. */
8827 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
8828 font
->mac_scriptcode
= smRoman
;
8830 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
8833 if (font
->mac_style
)
8838 font
->min_byte1
= 0;
8839 font
->max_byte1
= 0xff;
8840 font
->min_char_or_byte2
= 0;
8841 font
->max_char_or_byte2
= 0xff;
8843 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
8844 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
8845 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
8846 pcm_init (font
->bounds
.rows
[0], 0x100);
8848 #if USE_CG_TEXT_DRAWING
8852 ATSFontRef ats_font
;
8854 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
8856 /* Use CG text drawing if italic/bold is not synthesized. */
8857 if (err
== noErr
&& style
== fontface
)
8859 ats_font
= FMGetATSFontRefFromFont (font_id
);
8860 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
8866 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
8867 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
8870 space_bounds
= font
->bounds
.rows
[0] + 0x20;
8871 err
= mac_query_char_extents (font
->mac_style
, 0x20,
8872 &font
->ascent
, &font
->descent
,
8874 #if USE_CG_TEXT_DRAWING
8875 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
8882 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
8884 mac_unload_font (&one_mac_display_info
, font
);
8888 pcm
= font
->bounds
.rows
[0];
8889 for (c
= 0x21; c
<= 0xff; c
++)
8892 /* Soft hyphen is not supported in ATSUI. */
8896 #if USE_CG_TEXT_DRAWING
8897 if (font
->cg_glyphs
)
8907 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
,
8908 pcm
? pcm
+ c
: NULL
,
8909 #if USE_CG_TEXT_DRAWING
8910 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8917 #if USE_CG_TEXT_DRAWING
8918 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8920 /* Don't use CG text drawing if font substitution occurs in
8921 ASCII or Latin-1 characters. */
8922 CGFontRelease (font
->cg_font
);
8923 font
->cg_font
= NULL
;
8924 xfree (font
->cg_glyphs
);
8925 font
->cg_glyphs
= NULL
;
8936 FontInfo the_fontinfo
;
8937 int is_two_byte_font
;
8940 mac_prepare_for_quickdraw (f
);
8942 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8946 TextFace (fontface
);
8948 GetFontInfo (&the_fontinfo
);
8950 font
->ascent
= the_fontinfo
.ascent
;
8951 font
->descent
= the_fontinfo
.descent
;
8953 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8954 || font
->mac_scriptcode
== smTradChinese
8955 || font
->mac_scriptcode
== smSimpChinese
8956 || font
->mac_scriptcode
== smKorean
);
8958 if (is_two_byte_font
)
8962 font
->min_byte1
= 0xa1;
8963 font
->max_byte1
= 0xfe;
8964 font
->min_char_or_byte2
= 0xa1;
8965 font
->max_char_or_byte2
= 0xfe;
8967 /* Use the width of an "ideographic space" of that font
8968 because the_fontinfo.widMax returns the wrong width for
8970 switch (font
->mac_scriptcode
)
8973 font
->min_byte1
= 0x81;
8974 font
->max_byte1
= 0xfc;
8975 font
->min_char_or_byte2
= 0x40;
8976 font
->max_char_or_byte2
= 0xfc;
8977 char_width
= StringWidth("\p\x81\x40");
8980 font
->min_char_or_byte2
= 0x40;
8981 char_width
= StringWidth("\p\xa1\x40");
8984 char_width
= StringWidth("\p\xa1\xa1");
8987 char_width
= StringWidth("\p\xa1\xa1");
8991 font
->bounds
.per_char
= NULL
;
8993 if (fontface
& italic
)
8994 font
->max_bounds
.rbearing
= char_width
+ 1;
8996 font
->max_bounds
.rbearing
= char_width
;
8997 font
->max_bounds
.lbearing
= 0;
8998 font
->max_bounds
.width
= char_width
;
8999 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
9000 font
->max_bounds
.descent
= the_fontinfo
.descent
;
9002 font
->min_bounds
= font
->max_bounds
;
9008 font
->min_byte1
= font
->max_byte1
= 0;
9009 font
->min_char_or_byte2
= 0x20;
9010 font
->max_char_or_byte2
= 0xff;
9012 font
->bounds
.per_char
=
9013 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9014 bzero (font
->bounds
.per_char
,
9015 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
9017 space_bounds
= font
->bounds
.per_char
;
9018 err
= mac_query_char_extents (NULL
, 0x20, &font
->ascent
,
9019 &font
->descent
, space_bounds
, NULL
);
9020 if (err
!= noErr
|| space_bounds
->width
<= 0)
9022 mac_unload_font (&one_mac_display_info
, font
);
9026 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
9027 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
9035 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
9036 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
9039 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
9041 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
9043 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
9045 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
9047 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
9050 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
9052 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
9054 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
9056 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
9058 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
9063 font
->mac_style
== NULL
&&
9065 font
->max_bounds
.width
== font
->min_bounds
.width
9066 && font
->min_bounds
.lbearing
>= 0
9067 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
9069 /* Fixed width and no overhangs. */
9070 xfree (font
->bounds
.per_char
);
9071 font
->bounds
.per_char
= NULL
;
9075 #if !defined (MAC_OS8) || USE_ATSUI
9076 /* AppKit and WebKit do some adjustment to the heights of Courier,
9077 Helvetica, and Times. This only works on the environments where
9078 srcCopy text transfer mode is never used. */
9080 #ifdef MAC_OS8 /* implies USE_ATSUI */
9083 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
9084 || strcmp (family
, "times") == 0))
9085 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
9093 mac_unload_font (dpyinfo
, font
)
9094 struct mac_display_info
*dpyinfo
;
9097 xfree (font
->full_name
);
9099 if (font
->mac_style
)
9103 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
9104 if (font
->bounds
.rows
[i
])
9105 xfree (font
->bounds
.rows
[i
]);
9106 xfree (font
->bounds
.rows
);
9107 ATSUDisposeStyle (font
->mac_style
);
9111 if (font
->bounds
.per_char
)
9112 xfree (font
->bounds
.per_char
);
9113 #if USE_CG_TEXT_DRAWING
9115 CGFontRelease (font
->cg_font
);
9116 if (font
->cg_glyphs
)
9117 xfree (font
->cg_glyphs
);
9123 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9124 pointer to the structure font_info while allocating it dynamically.
9125 If SIZE is 0, load any size of font.
9126 If loading is failed, return NULL. */
9129 x_load_font (f
, fontname
, size
)
9131 register char *fontname
;
9134 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9135 Lisp_Object font_names
;
9137 /* Get a list of all the fonts that match this name. Once we
9138 have a list of matching fonts, we compare them against the fonts
9139 we already have by comparing names. */
9140 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9142 if (!NILP (font_names
))
9147 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9148 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9149 if (dpyinfo
->font_table
[i
].name
9150 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9151 SDATA (XCAR (tail
)))
9152 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9153 SDATA (XCAR (tail
)))))
9154 return (dpyinfo
->font_table
+ i
);
9159 /* Load the font and add it to the table. */
9161 struct MacFontStruct
*font
;
9162 struct font_info
*fontp
;
9165 fontname
= (char *) SDATA (XCAR (font_names
));
9168 font
= mac_load_query_font (f
, fontname
);
9173 /* Find a free slot in the font table. */
9174 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9175 if (dpyinfo
->font_table
[i
].name
== NULL
)
9178 /* If no free slot found, maybe enlarge the font table. */
9179 if (i
== dpyinfo
->n_fonts
9180 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9183 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9184 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9186 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9189 fontp
= dpyinfo
->font_table
+ i
;
9190 if (i
== dpyinfo
->n_fonts
)
9193 /* Now fill in the slots of *FONTP. */
9195 bzero (fontp
, sizeof (*fontp
));
9197 fontp
->font_idx
= i
;
9198 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9199 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9201 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9203 /* Fixed width font. */
9204 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9211 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9212 pcm
= mac_per_char_metric (font
, &char2b
, 0);
9214 fontp
->space_width
= pcm
->width
;
9216 fontp
->space_width
= FONT_WIDTH (font
);
9220 int width
= pcm
->width
;
9221 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9222 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
9223 width
+= pcm
->width
;
9224 fontp
->average_width
= width
/ 95;
9227 fontp
->average_width
= FONT_WIDTH (font
);
9230 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
9231 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
9233 fontp
->size
= font
->max_bounds
.width
;
9234 fontp
->height
= FONT_HEIGHT (font
);
9236 /* For some font, ascent and descent in max_bounds field is
9237 larger than the above value. */
9238 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
9239 if (max_height
> fontp
->height
)
9240 fontp
->height
= max_height
;
9243 /* The slot `encoding' specifies how to map a character
9244 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9245 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9246 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9247 2:0xA020..0xFF7F). For the moment, we don't know which charset
9248 uses this font. So, we set information in fontp->encoding[1]
9249 which is never used by any charset. If mapping can't be
9250 decided, set FONT_ENCODING_NOT_DECIDED. */
9251 if (font
->mac_scriptcode
== smJapanese
)
9252 fontp
->encoding
[1] = 4;
9256 = (font
->max_byte1
== 0
9258 ? (font
->min_char_or_byte2
< 0x80
9259 ? (font
->max_char_or_byte2
< 0x80
9260 ? 0 /* 0x20..0x7F */
9261 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9262 : 1) /* 0xA0..0xFF */
9264 : (font
->min_byte1
< 0x80
9265 ? (font
->max_byte1
< 0x80
9266 ? (font
->min_char_or_byte2
< 0x80
9267 ? (font
->max_char_or_byte2
< 0x80
9268 ? 0 /* 0x2020..0x7F7F */
9269 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9270 : 3) /* 0x20A0..0x7FFF */
9271 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9272 : (font
->min_char_or_byte2
< 0x80
9273 ? (font
->max_char_or_byte2
< 0x80
9274 ? 2 /* 0xA020..0xFF7F */
9275 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9276 : 1))); /* 0xA0A0..0xFFFF */
9279 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9280 fontp
->baseline_offset
9281 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9282 ? (long) value
: 0);
9283 fontp
->relative_compose
9284 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9285 ? (long) value
: 0);
9286 fontp
->default_ascent
9287 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9288 ? (long) value
: 0);
9290 fontp
->baseline_offset
= 0;
9291 fontp
->relative_compose
= 0;
9292 fontp
->default_ascent
= 0;
9295 /* Set global flag fonts_changed_p to non-zero if the font loaded
9296 has a character with a smaller width than any other character
9297 before, or if the font loaded has a smaller height than any
9298 other font loaded before. If this happens, it will make a
9299 glyph matrix reallocation necessary. */
9300 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9307 /* Return a pointer to struct font_info of a font named FONTNAME for
9308 frame F. If no such font is loaded, return NULL. */
9311 x_query_font (f
, fontname
)
9313 register char *fontname
;
9315 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9318 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9319 if (dpyinfo
->font_table
[i
].name
9320 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
9321 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9322 return (dpyinfo
->font_table
+ i
);
9327 /* Find a CCL program for a font specified by FONTP, and set the member
9328 `encoder' of the structure. */
9331 x_find_ccl_program (fontp
)
9332 struct font_info
*fontp
;
9334 Lisp_Object list
, elt
;
9336 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9340 && STRINGP (XCAR (elt
))
9341 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9347 struct ccl_program
*ccl
9348 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9350 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9353 fontp
->font_encoder
= ccl
;
9357 #if USE_MAC_FONT_PANEL
9358 /* Whether Font Panel has been shown before. The first call to font
9359 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9360 slow. This variable is used for deferring such a call as much as
9362 static int font_panel_shown_p
= 0;
9364 extern Lisp_Object Qfont
;
9365 static Lisp_Object Qpanel_closed
, Qselection
;
9367 static OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
9371 const EventParamName
*,
9372 const EventParamType
*));
9375 mac_font_panel_visible_p ()
9377 return font_panel_shown_p
&& FPIsFontPanelVisible ();
9380 static pascal OSStatus
9381 mac_handle_font_event (next_handler
, event
, data
)
9382 EventHandlerCallRef next_handler
;
9386 OSStatus result
, err
;
9389 const EventParamName
*names
;
9390 const EventParamType
*types
;
9391 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9392 kEventParamATSUFontSize
,
9393 kEventParamFMFontFamily
,
9394 kEventParamFMFontSize
,
9395 kEventParamFontColor
};
9396 static const EventParamType types_sel
[] = {typeATSUFontID
,
9402 result
= CallNextEventHandler (next_handler
, event
);
9403 if (result
!= eventNotHandledErr
)
9406 switch (GetEventKind (event
))
9408 case kEventFontPanelClosed
:
9409 id_key
= Qpanel_closed
;
9415 case kEventFontSelection
:
9416 id_key
= Qselection
;
9417 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9423 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9433 mac_show_hide_font_panel ()
9435 if (!font_panel_shown_p
)
9439 static const EventTypeSpec specs
[] =
9440 {{kEventClassFont
, kEventFontPanelClosed
},
9441 {kEventClassFont
, kEventFontSelection
}};
9443 err
= InstallApplicationEventHandler (mac_handle_font_event
,
9444 GetEventTypeCount (specs
),
9449 font_panel_shown_p
= 1;
9452 return FPShowHideFontPanel ();
9456 mac_set_font_info_for_selection (f
, face_id
, c
)
9461 EventTargetRef target
= NULL
;
9462 XFontStruct
*font
= NULL
;
9464 if (!mac_font_panel_visible_p ())
9469 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
9471 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
9475 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
9476 face
= FACE_FROM_ID (f
, face_id
);
9482 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
9485 if (font
->mac_fontnum
!= -1)
9487 FontSelectionQDStyle qd_style
;
9489 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
9490 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
9491 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
9492 qd_style
.size
= font
->mac_fontsize
;
9493 qd_style
.hasColor
= false;
9495 err
= SetFontInfoForSelection (kFontSelectionQDType
,
9496 1, &qd_style
, target
);
9499 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
9500 1, &font
->mac_style
, target
);
9508 /* The Mac Event loop code */
9510 #if !TARGET_API_MAC_CARBON
9512 #include <Quickdraw.h>
9513 #include <Balloons.h>
9514 #include <Devices.h>
9516 #include <Gestalt.h>
9518 #include <Processes.h>
9520 #include <ToolUtils.h>
9521 #include <TextUtils.h>
9522 #include <Dialogs.h>
9525 #include <Resources.h>
9530 #endif /* ! TARGET_API_MAC_CARBON */
9535 #define DEFAULT_NUM_COLS 80
9537 #define MIN_DOC_SIZE 64
9538 #define MAX_DOC_SIZE 32767
9540 #define EXTRA_STACK_ALLOC (256 * 1024)
9542 #define ARGV_STRING_LIST_ID 129
9543 #define ABOUT_ALERT_ID 128
9544 #define RAM_TOO_LARGE_ALERT_ID 129
9546 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9547 Lisp_Object Qreverse
;
9550 /* Modifier associated with the control key, or nil to ignore. */
9551 Lisp_Object Vmac_control_modifier
;
9553 /* Modifier associated with the option key, or nil to ignore. */
9554 Lisp_Object Vmac_option_modifier
;
9556 /* Modifier associated with the command key, or nil to ignore. */
9557 Lisp_Object Vmac_command_modifier
;
9559 /* Modifier associated with the function key, or nil to ignore. */
9560 Lisp_Object Vmac_function_modifier
;
9562 /* True if the option and command modifiers should be used to emulate
9563 a three button mouse */
9564 Lisp_Object Vmac_emulate_three_button_mouse
;
9566 #if TARGET_API_MAC_CARBON
9567 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9568 mouse-2, instead of mouse-3. */
9569 int mac_wheel_button_is_mouse_2
;
9571 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9572 for processing before Emacs sees it. */
9573 int mac_pass_command_to_system
;
9575 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9576 for processing before Emacs sees it. */
9577 int mac_pass_control_to_system
;
9580 /* Points to the variable `inev' in the function XTread_socket. It is
9581 used for passing an input event to the function back from
9582 Carbon/Apple event handlers. */
9583 static struct input_event
*read_socket_inev
= NULL
;
9585 /* Whether or not the screen configuration has changed. */
9586 static int mac_screen_config_changed
= 0;
9588 Point saved_menu_event_location
;
9591 #if TARGET_API_MAC_CARBON
9592 static Lisp_Object Qhi_command
;
9594 extern Lisp_Object Qwindow
;
9595 static Lisp_Object Qtoolbar_switch_mode
;
9598 static TSMDocumentID tsm_document_id
;
9599 static Lisp_Object Qtext_input
;
9600 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
9601 static Lisp_Object Vmac_ts_active_input_overlay
;
9602 extern Lisp_Object Qbefore_string
;
9603 static Lisp_Object Vmac_ts_script_language_on_focus
;
9604 static Lisp_Object saved_ts_script_language_on_focus
;
9605 static ScriptLanguageRecord saved_ts_language
;
9606 static Component saved_ts_component
;
9608 #endif /* TARGET_API_MAC_CARBON */
9609 extern int mac_ready_for_apple_events
;
9610 extern Lisp_Object Qundefined
;
9611 extern void init_apple_event_handler
P_ ((void));
9612 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
9613 Lisp_Object
*, Lisp_Object
*,
9615 extern OSErr init_coercion_handler
P_ ((void));
9618 extern OSErr install_drag_handler
P_ ((WindowRef
));
9619 extern void remove_drag_handler
P_ ((WindowRef
));
9621 #if TARGET_API_MAC_CARBON
9622 /* Showing help echo string during menu tracking */
9623 extern OSStatus install_menu_target_item_handler
P_ ((void));
9626 extern OSStatus
install_service_handler ();
9627 static Lisp_Object Qservice
, Qpaste
, Qperform
;
9631 extern void init_emacs_passwd_dir ();
9632 extern int emacs_main (int, char **, char **);
9634 extern void initialize_applescript();
9635 extern void terminate_applescript();
9637 /* Table for translating Mac keycode to X keysym values. Contributed
9639 Mapping for special keys is now identical to that in Apple X11
9640 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9641 on the right of the Cmd key on laptops, and fn + `enter' (->
9643 static const unsigned char keycode_to_xkeysym_table
[] = {
9644 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9645 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9646 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9648 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9649 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9650 /*0x38*/ 0, 0, 0, 0,
9651 /*0x3C*/ 0, 0, 0, 0,
9653 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9654 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9655 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9656 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9658 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9659 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9660 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9661 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9663 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9664 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9665 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9666 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9668 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9669 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9670 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9671 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9675 /* Table for translating Mac keycode with the laptop `fn' key to that
9676 without it. Destination symbols in comments are keys on US
9677 keyboard, and they may not be the same on other types of keyboards.
9678 If the destination is identical to the source (f1 ... f12), it
9679 doesn't map `fn' key to a modifier. */
9680 static const unsigned char fn_keycode_to_keycode_table
[] = {
9681 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9682 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9683 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9685 /*0x30*/ 0, 0, 0, 0,
9686 /*0x34*/ 0, 0, 0, 0,
9687 /*0x38*/ 0, 0, 0, 0,
9688 /*0x3C*/ 0, 0, 0, 0,
9690 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9691 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9692 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9693 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9695 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9696 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9697 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9698 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9700 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9701 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9702 /*0x68*/ 0, 0, 0, 0,
9703 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9705 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9706 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9707 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9710 #endif /* MAC_OSX */
9713 #if TARGET_API_MAC_CARBON
9714 mac_to_emacs_modifiers (UInt32 mods
)
9716 mac_to_emacs_modifiers (EventModifiers mods
)
9719 unsigned int result
= 0;
9720 if (mods
& shiftKey
)
9721 result
|= shift_modifier
;
9723 /* Deactivated to simplify configuration:
9724 if Vmac_option_modifier is non-NIL, we fully process the Option
9725 key. Otherwise, we only process it if an additional Ctrl or Command
9726 is pressed. That way the system may convert the character to a
9728 if ((mods & optionKey) &&
9729 (( !NILP(Vmac_option_modifier) ||
9730 ((mods & cmdKey) || (mods & controlKey))))) */
9732 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
9733 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
9735 result
|= XUINT(val
);
9737 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
9738 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
9740 result
|= XUINT(val
);
9742 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
9743 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
9745 result
|= XUINT(val
);
9749 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
9750 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
9752 result
|= XUINT(val
);
9760 mac_mapped_modifiers (modifiers
)
9763 UInt32 mapped_modifiers_all
=
9764 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9765 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9766 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9769 mapped_modifiers_all
|=
9770 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9773 return mapped_modifiers_all
& modifiers
;
9777 mac_get_emulated_btn ( UInt32 modifiers
)
9780 if (!NILP (Vmac_emulate_three_button_mouse
)) {
9781 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
9782 if (modifiers
& cmdKey
)
9783 result
= cmdIs3
? 2 : 1;
9784 else if (modifiers
& optionKey
)
9785 result
= cmdIs3
? 1 : 2;
9790 #if TARGET_API_MAC_CARBON
9791 /***** Code to handle C-g testing *****/
9792 extern int quit_char
;
9793 extern int make_ctrl_char
P_ ((int));
9796 mac_quit_char_key_p (modifiers
, key_code
)
9797 UInt32 modifiers
, key_code
;
9800 unsigned long some_state
= 0;
9801 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9802 int c
, emacs_modifiers
;
9804 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9805 key_code
|= (modifiers
& ~(mac_mapped_modifiers (modifiers
)));
9806 char_code
= KeyTranslate (kchr_ptr
, key_code
, &some_state
);
9807 if (char_code
& ~0xff)
9810 emacs_modifiers
= mac_to_emacs_modifiers (modifiers
);
9811 if (emacs_modifiers
& ctrl_modifier
)
9812 c
= make_ctrl_char (char_code
);
9814 c
|= (emacs_modifiers
9815 & (meta_modifier
| alt_modifier
9816 | hyper_modifier
| super_modifier
));
9818 return c
== quit_char
;
9822 #if TARGET_API_MAC_CARBON
9823 /* Obtains the event modifiers from the event ref and then calls
9824 mac_to_emacs_modifiers. */
9826 mac_event_to_emacs_modifiers (EventRef eventRef
)
9828 UInt32 mods
= 0, class;
9830 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9831 sizeof (UInt32
), NULL
, &mods
);
9832 class = GetEventClass (eventRef
);
9833 if (!NILP (Vmac_emulate_three_button_mouse
) &&
9834 (class == kEventClassMouse
|| class == kEventClassCommand
))
9836 mods
&= ~(optionKey
| cmdKey
);
9838 return mac_to_emacs_modifiers (mods
);
9841 /* Given an event ref, return the code to use for the mouse button
9842 code in the emacs input_event. */
9844 mac_get_mouse_btn (EventRef ref
)
9846 EventMouseButton result
= kEventMouseButtonPrimary
;
9847 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9848 sizeof (EventMouseButton
), NULL
, &result
);
9851 case kEventMouseButtonPrimary
:
9852 if (NILP (Vmac_emulate_three_button_mouse
))
9856 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9857 sizeof (UInt32
), NULL
, &mods
);
9858 return mac_get_emulated_btn(mods
);
9860 case kEventMouseButtonSecondary
:
9861 return mac_wheel_button_is_mouse_2
? 2 : 1;
9862 case kEventMouseButtonTertiary
:
9863 case 4: /* 4 is the number for the mouse wheel button */
9864 return mac_wheel_button_is_mouse_2
? 1 : 2;
9870 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9871 events. However the click of the mouse wheel is not converted to a
9872 mouseDown or mouseUp event. Likewise for dead key events. This
9873 calls ConvertEventRefToEventRecord, but then checks to see if it is
9874 a mouse up/down, or a dead key Carbon event that has not been
9875 converted, and if so, converts it by hand (to be picked up in the
9876 XTread_socket loop). */
9877 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9880 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9886 switch (GetEventClass (eventRef
))
9888 case kEventClassMouse
:
9889 switch (GetEventKind (eventRef
))
9891 case kEventMouseDown
:
9892 eventRec
->what
= mouseDown
;
9897 eventRec
->what
= mouseUp
;
9906 case kEventClassKeyboard
:
9907 switch (GetEventKind (eventRef
))
9909 case kEventRawKeyDown
:
9911 goto keystroke_common
;
9912 case kEventRawKeyRepeat
:
9914 goto keystroke_common
;
9915 case kEventRawKeyUp
:
9919 unsigned char char_codes
;
9922 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
9923 typeChar
, NULL
, sizeof (char),
9926 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
9927 typeUInt32
, NULL
, sizeof (UInt32
),
9931 eventRec
->what
= action
;
9932 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
9949 /* Need where and when. */
9952 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
9953 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
9954 /* Use two step process because new event modifiers are 32-bit
9955 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9956 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9957 NULL
, sizeof (UInt32
), NULL
, &mods
);
9958 eventRec
->modifiers
= mods
;
9960 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9972 Handle menubar_handle
;
9975 menubar_handle
= GetNewMBar (128);
9976 if(menubar_handle
== NULL
)
9978 SetMenuBar (menubar_handle
);
9981 #if !TARGET_API_MAC_CARBON
9982 menu
= GetMenuRef (M_APPLE
);
9984 AppendResMenu (menu
, 'DRVR');
9992 do_init_managers (void)
9994 #if !TARGET_API_MAC_CARBON
9995 InitGraf (&qd
.thePort
);
9997 FlushEvents (everyEvent
, 0);
10001 InitDialogs (NULL
);
10002 #endif /* !TARGET_API_MAC_CARBON */
10005 #if !TARGET_API_MAC_CARBON
10006 /* set up some extra stack space for use by emacs */
10007 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
10009 /* MaxApplZone must be called for AppleScript to execute more
10010 complicated scripts */
10013 #endif /* !TARGET_API_MAC_CARBON */
10017 do_check_ram_size (void)
10019 SInt32 physical_ram_size
, logical_ram_size
;
10021 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
10022 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
10023 || physical_ram_size
> (1 << VALBITS
)
10024 || logical_ram_size
> (1 << VALBITS
))
10026 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
10030 #endif /* MAC_OS8 */
10033 do_window_update (WindowRef win
)
10035 struct frame
*f
= mac_window_to_frame (win
);
10039 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10041 if (win
!= tip_window
)
10043 if (f
->async_visible
== 0)
10045 /* Update events may occur when a frame gets iconified. */
10047 f
->async_visible
= 1;
10048 f
->async_iconified
= 0;
10049 SET_FRAME_GARBAGED (f
);
10055 #if TARGET_API_MAC_CARBON
10056 RgnHandle region
= NewRgn ();
10058 GetPortVisibleRegion (GetWindowPort (win
), region
);
10059 GetRegionBounds (region
, &r
);
10060 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10062 mac_prepare_for_quickdraw (f
);
10064 UpdateControls (win
, region
);
10065 DisposeRgn (region
);
10067 r
= (*win
->visRgn
)->rgnBBox
;
10068 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
10069 UpdateControls (win
, win
->visRgn
);
10078 is_emacs_window (WindowRef win
)
10080 Lisp_Object tail
, frame
;
10085 FOR_EACH_FRAME (tail
, frame
)
10086 if (FRAME_MAC_P (XFRAME (frame
)))
10087 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
10098 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10100 err
= ActivateTSMDocument (tsm_document_id
);
10104 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
10105 && EQ (saved_ts_script_language_on_focus
, Qt
))
10106 slptr
= &saved_ts_language
;
10107 else if (CONSP (Vmac_ts_script_language_on_focus
)
10108 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10109 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
10110 && CONSP (saved_ts_script_language_on_focus
)
10111 && EQ (XCAR (saved_ts_script_language_on_focus
),
10112 XCAR (Vmac_ts_script_language_on_focus
))
10113 && EQ (XCDR (saved_ts_script_language_on_focus
),
10114 XCDR (Vmac_ts_script_language_on_focus
)))
10116 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10117 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10124 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10125 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
10126 kKeyboardInputMethodClass
);
10128 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
10131 err
= SetTextServiceLanguage (slptr
);
10133 /* Seems to be needed on Mac OS X 10.2. */
10135 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
10145 ScriptLanguageRecord slrec
, *slptr
= NULL
;
10147 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
10149 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
10151 err
= GetTextServiceLanguage (&saved_ts_language
);
10153 slptr
= &saved_ts_language
;
10155 else if (CONSP (Vmac_ts_script_language_on_focus
)
10156 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
10157 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
10159 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
10160 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
10166 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10167 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
10168 kKeyboardInputMethodClass
);
10170 GetDefaultInputMethod (&saved_ts_component
, slptr
);
10174 err
= DeactivateTSMDocument (tsm_document_id
);
10180 #if !TARGET_API_MAC_CARBON
10182 do_apple_menu (SInt16 menu_item
)
10185 SInt16 da_driver_refnum
;
10187 if (menu_item
== I_ABOUT
)
10188 NoteAlert (ABOUT_ALERT_ID
, NULL
);
10191 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
10192 da_driver_refnum
= OpenDeskAcc (item_name
);
10195 #endif /* !TARGET_API_MAC_CARBON */
10197 /* Handle drags in size box. Based on code contributed by Ben
10198 Mesander and IM - Window Manager A. */
10201 do_grow_window (w
, e
)
10203 const EventRecord
*e
;
10206 int rows
, columns
, width
, height
;
10207 struct frame
*f
= mac_window_to_frame (w
);
10208 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
10209 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
10210 #if TARGET_API_MAC_CARBON
10216 if (size_hints
->flags
& PMinSize
)
10218 min_width
= size_hints
->min_width
;
10219 min_height
= size_hints
->min_height
;
10221 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
10223 #if TARGET_API_MAC_CARBON
10224 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
10226 height
= new_rect
.bottom
- new_rect
.top
;
10227 width
= new_rect
.right
- new_rect
.left
;
10229 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
10230 /* see if it really changed size */
10231 if (grow_size
== 0)
10233 height
= HiWord (grow_size
);
10234 width
= LoWord (grow_size
);
10237 if (width
!= FRAME_PIXEL_WIDTH (f
)
10238 || height
!= FRAME_PIXEL_HEIGHT (f
))
10240 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10241 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10243 x_set_window_size (f
, 0, columns
, rows
);
10248 #if TARGET_API_MAC_CARBON
10250 mac_get_ideal_size (f
)
10253 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10254 WindowRef w
= FRAME_MAC_WINDOW (f
);
10256 Rect standard_rect
;
10257 int height
, width
, columns
, rows
;
10259 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10260 ideal_size
.v
= dpyinfo
->height
;
10261 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
10262 /* Adjust the standard size according to character boundaries. */
10263 width
= standard_rect
.right
- standard_rect
.left
;
10264 height
= standard_rect
.bottom
- standard_rect
.top
;
10265 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
10266 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
10267 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
10268 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10274 /* Handle clicks in zoom box. Calculation of "standard state" based
10275 on code in IM - Window Manager A and code contributed by Ben
10276 Mesander. The standard state of an Emacs window is 80-characters
10277 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10280 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
10282 Rect zoom_rect
, port_rect
;
10284 struct frame
*f
= mac_window_to_frame (w
);
10285 #if TARGET_API_MAC_CARBON
10286 Point ideal_size
= mac_get_ideal_size (f
);
10288 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
10289 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
10290 && port_rect
.left
== zoom_rect
.left
10291 && port_rect
.top
== zoom_rect
.top
)
10292 zoom_in_or_out
= inZoomIn
;
10294 zoom_in_or_out
= inZoomOut
;
10297 mac_clear_window (f
);
10299 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
10300 #else /* not TARGET_API_MAC_CARBON */
10303 int w_title_height
, rows
;
10304 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10306 GetPort (&save_port
);
10308 SetPortWindowPort (w
);
10310 /* Clear window to avoid flicker. */
10311 EraseRect (&(w
->portRect
));
10312 if (zoom_in_or_out
== inZoomOut
)
10314 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
10315 LocalToGlobal (&top_left
);
10317 /* calculate height of window's title bar */
10318 w_title_height
= top_left
.v
- 1
10319 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
10321 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10322 zoom_rect
= qd
.screenBits
.bounds
;
10323 zoom_rect
.top
+= w_title_height
;
10324 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
10326 zoom_rect
.right
= zoom_rect
.left
10327 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
10329 /* Adjust the standard size according to character boundaries. */
10330 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
10332 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
10334 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
10338 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
10340 SetPort (save_port
);
10341 #endif /* not TARGET_API_MAC_CARBON */
10343 #if !TARGET_API_MAC_CARBON
10344 /* retrieve window size and update application values */
10345 port_rect
= w
->portRect
;
10346 height
= port_rect
.bottom
- port_rect
.top
;
10347 width
= port_rect
.right
- port_rect
.left
;
10349 mac_handle_size_change (f
, width
, height
);
10350 mac_handle_origin_change (f
);
10355 mac_set_unicode_keystroke_event (code
, buf
)
10357 struct input_event
*buf
;
10359 int charset_id
, c1
, c2
;
10363 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10366 else if (code
< 0x100)
10369 charset_id
= CHARSET_8_BIT_CONTROL
;
10371 charset_id
= charset_latin_iso8859_1
;
10372 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10373 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10378 charset_id
= charset_mule_unicode_0100_24ff
,
10380 else if (code
< 0x33FF)
10381 charset_id
= charset_mule_unicode_2500_33ff
,
10383 else if (code
>= 0xE000)
10384 charset_id
= charset_mule_unicode_e000_ffff
,
10386 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10387 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10388 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10393 do_keystroke (action
, char_code
, key_code
, modifiers
, timestamp
, buf
)
10395 unsigned char char_code
;
10396 UInt32 key_code
, modifiers
;
10397 unsigned long timestamp
;
10398 struct input_event
*buf
;
10400 static SInt16 last_key_script
= -1;
10401 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10402 UInt32 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10405 if (mapped_modifiers
& kEventKeyModifierFnMask
10406 && key_code
<= 0x7f
10407 && fn_keycode_to_keycode_table
[key_code
])
10408 key_code
= fn_keycode_to_keycode_table
[key_code
];
10411 if (key_code
<= 0x7f && keycode_to_xkeysym_table
[key_code
])
10413 buf
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10414 buf
->code
= 0xff00 | keycode_to_xkeysym_table
[key_code
];
10416 if (modifiers
& kEventKeyModifierFnMask
10417 && key_code
<= 0x7f
10418 && fn_keycode_to_keycode_table
[key_code
] == key_code
)
10419 modifiers
&= ~kEventKeyModifierFnMask
;
10422 else if (mapped_modifiers
)
10424 /* translate the keycode back to determine the original key */
10426 UCKeyboardLayout
*uchr_ptr
= NULL
;
10427 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10429 KeyboardLayoutRef layout
;
10431 err
= KLGetCurrentKeyboardLayout (&layout
);
10433 err
= KLGetKeyboardLayoutProperty (layout
, kKLuchrData
,
10434 (const void **) &uchr_ptr
);
10436 static SInt16 last_key_layout_id
= 0;
10437 static Handle uchr_handle
= (Handle
)-1;
10438 SInt16 current_key_layout_id
=
10439 GetScriptVariable (current_key_script
, smScriptKeys
);
10441 if (uchr_handle
== (Handle
)-1
10442 || last_key_layout_id
!= current_key_layout_id
)
10444 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10445 last_key_layout_id
= current_key_layout_id
;
10448 uchr_ptr
= (UCKeyboardLayout
*)*uchr_handle
;
10454 UInt16 key_action
= action
- keyDown
;
10455 UInt32 modifier_key_state
= (modifiers
& ~mapped_modifiers
) >> 8;
10456 UInt32 keyboard_type
= LMGetKbdType ();
10457 SInt32 dead_key_state
= 0;
10459 UniCharCount actual_length
;
10461 status
= UCKeyTranslate (uchr_ptr
, key_code
, key_action
,
10462 modifier_key_state
, keyboard_type
,
10463 kUCKeyTranslateNoDeadKeysMask
,
10465 1, &actual_length
, &code
);
10466 if (status
== noErr
&& actual_length
== 1)
10467 mac_set_unicode_keystroke_event (code
, buf
);
10469 #endif /* MAC_OSX */
10471 if (buf
->kind
== NO_EVENT
)
10473 /* This code comes from Keyboard Resource, Appendix C of IM
10474 - Text. This is necessary since shift is ignored in KCHR
10475 table translation when option or command is pressed. It
10476 also does not translate correctly control-shift chars
10477 like C-% so mask off shift here also. */
10478 /* Mask off modifier keys that are mapped to some Emacs
10480 int new_modifiers
= modifiers
& ~mapped_modifiers
;
10481 /* set high byte of keycode to modifier high byte*/
10482 int new_key_code
= key_code
| new_modifiers
;
10483 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10484 unsigned long some_state
= 0;
10485 UInt32 new_char_code
;
10487 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
, &some_state
);
10488 if (new_char_code
== 0)
10489 /* Seems like a dead key. Append up-stroke. */
10490 new_char_code
= KeyTranslate (kchr_ptr
, new_key_code
| 0x80,
10494 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10495 buf
->code
= new_char_code
& 0xff;
10500 if (buf
->kind
== NO_EVENT
)
10502 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10503 buf
->code
= char_code
;
10506 buf
->modifiers
= mac_to_emacs_modifiers (modifiers
);
10507 buf
->modifiers
|= (extra_keyboard_modifiers
10508 & (meta_modifier
| alt_modifier
10509 | hyper_modifier
| super_modifier
));
10511 #if TARGET_API_MAC_CARBON
10512 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10513 && buf
->code
>= 0x80 && buf
->modifiers
)
10516 TextEncoding encoding
= kTextEncodingMacRoman
;
10517 TextToUnicodeInfo ttu_info
;
10519 UpgradeScriptInfoToTextEncoding (current_key_script
,
10520 kTextLanguageDontCare
,
10521 kTextRegionDontCare
,
10523 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10528 ByteCount unicode_len
;
10531 pstr
[1] = buf
->code
;
10532 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10534 &unicode_len
, &code
);
10535 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10536 mac_set_unicode_keystroke_event (code
, buf
);
10537 DisposeTextToUnicodeInfo (&ttu_info
);
10542 if (buf
->kind
== ASCII_KEYSTROKE_EVENT
10543 && buf
->code
>= 0x80
10544 && last_key_script
!= current_key_script
)
10546 struct input_event event
;
10548 EVENT_INIT (event
);
10549 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10551 event
.code
= current_key_script
;
10552 event
.timestamp
= timestamp
;
10553 kbd_buffer_store_event (&event
);
10554 last_key_script
= current_key_script
;
10559 mac_store_apple_event (class, id
, desc
)
10560 Lisp_Object
class, id
;
10561 const AEDesc
*desc
;
10563 struct input_event buf
;
10567 buf
.kind
= MAC_APPLE_EVENT
;
10570 XSETFRAME (buf
.frame_or_window
,
10571 mac_focus_frame (&one_mac_display_info
));
10572 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10573 is safe to use them during read_socket_hook. */
10574 buf
.arg
= mac_aedesc_to_lisp (desc
);
10575 kbd_buffer_store_event (&buf
);
10578 #if TARGET_API_MAC_CARBON
10580 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
10581 event
, num_params
, names
, types
)
10582 AEEventClass
class;
10584 Lisp_Object class_key
, id_key
;
10587 const EventParamName
*names
;
10588 const EventParamType
*types
;
10590 OSStatus err
= eventNotHandledErr
;
10591 Lisp_Object binding
;
10593 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
10594 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
10596 if (INTEGERP (binding
))
10597 err
= XINT (binding
);
10600 AppleEvent apple_event
;
10601 err
= create_apple_event_from_event_ref (event
, num_params
,
10606 mac_store_apple_event (class_key
, id_key
, &apple_event
);
10607 AEDisposeDesc (&apple_event
);
10608 mac_wakeup_from_rne ();
10617 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
10621 const AEDesc
*desc
;
10623 struct input_event buf
;
10627 buf
.kind
= DRAG_N_DROP_EVENT
;
10628 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10629 buf
.timestamp
= TickCount () * (1000 / 60);
10630 XSETINT (buf
.x
, mouse_pos
.h
);
10631 XSETINT (buf
.y
, mouse_pos
.v
);
10632 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
10633 buf
.arg
= mac_aedesc_to_lisp (desc
);
10634 kbd_buffer_store_event (&buf
);
10639 mac_store_service_event (event
)
10643 Lisp_Object id_key
;
10645 const EventParamName
*names
;
10646 const EventParamType
*types
;
10647 static const EventParamName names_pfm
[] =
10648 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
10649 static const EventParamType types_pfm
[] =
10650 {typeCFStringRef
, typeCFStringRef
};
10652 switch (GetEventKind (event
))
10654 case kEventServicePaste
:
10661 case kEventServicePerform
:
10663 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
10672 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
10678 #endif /* MAC_OSX */
10680 static pascal OSStatus
10681 mac_handle_window_event (next_handler
, event
, data
)
10682 EventHandlerCallRef next_handler
;
10687 OSStatus err
, result
= eventNotHandledErr
;
10690 XSizeHints
*size_hints
;
10692 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
10693 NULL
, sizeof (WindowRef
), NULL
, &wp
);
10695 return eventNotHandledErr
;
10697 f
= mac_window_to_frame (wp
);
10698 switch (GetEventKind (event
))
10700 /* -- window refresh events -- */
10702 case kEventWindowUpdate
:
10703 result
= CallNextEventHandler (next_handler
, event
);
10704 if (result
!= eventNotHandledErr
)
10707 do_window_update (wp
);
10711 /* -- window state change events -- */
10713 case kEventWindowShowing
:
10714 size_hints
= FRAME_SIZE_HINTS (f
);
10715 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
10717 struct frame
*sf
= SELECTED_FRAME ();
10719 if (!(FRAME_MAC_P (sf
)))
10720 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
10723 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
10724 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10725 kWindowCascadeStartAtParentWindowScreen
10727 kWindowCascadeOnParentWindowScreen
10730 #if USE_MAC_TOOLBAR
10731 /* This is a workaround. RepositionWindow fails to put
10732 a window at the cascading position when its parent
10733 window has a Carbon HIToolbar. */
10734 if (f
->top_pos
== sf
->top_pos
&& f
->left_pos
== sf
->left_pos
)
10735 MoveWindowStructure (wp
, f
->left_pos
+ 10, f
->top_pos
+ 32);
10742 case kEventWindowHiding
:
10743 /* Before unmapping the window, update the WM_SIZE_HINTS
10744 property to claim that the current position of the window is
10745 user-specified, rather than program-specified, so that when
10746 the window is mapped again, it will be placed at the same
10747 location, without forcing the user to position it by hand
10748 again (they have already done that once for this window.) */
10749 x_wm_set_size_hint (f
, (long) 0, 1);
10753 case kEventWindowShown
:
10754 case kEventWindowHidden
:
10755 case kEventWindowCollapsed
:
10756 case kEventWindowExpanded
:
10757 mac_handle_visibility_change (f
);
10761 case kEventWindowBoundsChanging
:
10762 result
= CallNextEventHandler (next_handler
, event
);
10763 if (result
!= eventNotHandledErr
)
10766 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10767 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10771 size_hints
= FRAME_SIZE_HINTS (f
);
10772 if ((attributes
& kWindowBoundsChangeUserResize
)
10773 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
10774 == (PResizeInc
| PBaseSize
| PMinSize
)))
10779 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10780 typeQDRectangle
, NULL
, sizeof (Rect
),
10785 width
= bounds
.right
- bounds
.left
;
10786 height
= bounds
.bottom
- bounds
.top
;
10788 if (width
< size_hints
->min_width
)
10789 width
= size_hints
->min_width
;
10791 width
= size_hints
->base_width
10792 + (int) ((width
- size_hints
->base_width
)
10793 / (float) size_hints
->width_inc
+ .5)
10794 * size_hints
->width_inc
;
10796 if (height
< size_hints
->min_height
)
10797 height
= size_hints
->min_height
;
10799 height
= size_hints
->base_height
10800 + (int) ((height
- size_hints
->base_height
)
10801 / (float) size_hints
->height_inc
+ .5)
10802 * size_hints
->height_inc
;
10804 bounds
.right
= bounds
.left
+ width
;
10805 bounds
.bottom
= bounds
.top
+ height
;
10806 SetEventParameter (event
, kEventParamCurrentBounds
,
10807 typeQDRectangle
, sizeof (Rect
), &bounds
);
10812 case kEventWindowBoundsChanged
:
10813 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
10814 NULL
, sizeof (UInt32
), NULL
, &attributes
);
10818 if (attributes
& kWindowBoundsChangeSizeChanged
)
10822 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
10823 typeQDRectangle
, NULL
, sizeof (Rect
),
10829 width
= bounds
.right
- bounds
.left
;
10830 height
= bounds
.bottom
- bounds
.top
;
10831 mac_handle_size_change (f
, width
, height
);
10832 mac_wakeup_from_rne ();
10836 if (attributes
& kWindowBoundsChangeOriginChanged
)
10837 mac_handle_origin_change (f
);
10842 /* -- window action events -- */
10844 case kEventWindowClose
:
10846 struct input_event buf
;
10849 buf
.kind
= DELETE_WINDOW_EVENT
;
10850 XSETFRAME (buf
.frame_or_window
, f
);
10852 kbd_buffer_store_event (&buf
);
10857 case kEventWindowGetIdealSize
:
10858 result
= CallNextEventHandler (next_handler
, event
);
10859 if (result
!= eventNotHandledErr
)
10863 Point ideal_size
= mac_get_ideal_size (f
);
10865 err
= SetEventParameter (event
, kEventParamDimensions
,
10866 typeQDPoint
, sizeof (Point
), &ideal_size
);
10873 case kEventWindowToolbarSwitchMode
:
10875 static const EventParamName names
[] = {kEventParamDirectObject
,
10876 kEventParamWindowMouseLocation
,
10877 kEventParamKeyModifiers
,
10878 kEventParamMouseButton
,
10879 kEventParamClickCount
,
10880 kEventParamMouseChord
};
10881 static const EventParamType types
[] = {typeWindowRef
,
10887 int num_params
= sizeof (names
) / sizeof (names
[0]);
10889 err
= mac_store_event_ref_as_apple_event (0, 0,
10891 Qtoolbar_switch_mode
,
10901 /* -- window focus events -- */
10903 case kEventWindowFocusAcquired
:
10904 err
= mac_tsm_resume ();
10909 case kEventWindowFocusRelinquish
:
10910 err
= mac_tsm_suspend ();
10923 static pascal OSStatus
10924 mac_handle_application_event (next_handler
, event
, data
)
10925 EventHandlerCallRef next_handler
;
10929 OSStatus err
, result
= eventNotHandledErr
;
10931 switch (GetEventKind (event
))
10934 case kEventAppActivated
:
10935 err
= mac_tsm_resume ();
10938 case kEventAppDeactivated
:
10939 err
= mac_tsm_suspend ();
10953 static pascal OSStatus
10954 mac_handle_keyboard_event (next_handler
, event
, data
)
10955 EventHandlerCallRef next_handler
;
10959 OSStatus err
, result
= eventNotHandledErr
;
10960 UInt32 event_kind
, key_code
, modifiers
, mapped_modifiers
;
10961 unsigned char char_code
;
10963 event_kind
= GetEventKind (event
);
10964 switch (event_kind
)
10966 case kEventRawKeyDown
:
10967 case kEventRawKeyRepeat
:
10968 case kEventRawKeyUp
:
10969 if (read_socket_inev
== NULL
)
10971 result
= CallNextEventHandler (next_handler
, event
);
10975 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
10977 sizeof (UInt32
), NULL
, &modifiers
);
10981 mapped_modifiers
= mac_mapped_modifiers (modifiers
);
10983 /* When using Carbon Events, we need to pass raw keyboard events
10984 to the TSM ourselves. If TSM handles it, it will pass back
10985 noErr, otherwise it will pass back "eventNotHandledErr" and
10986 we can process it normally. */
10987 if (!(mapped_modifiers
10988 & ~(mac_pass_command_to_system
? cmdKey
: 0)
10989 & ~(mac_pass_control_to_system
? controlKey
: 0)))
10991 result
= CallNextEventHandler (next_handler
, event
);
10992 if (result
!= eventNotHandledErr
)
10997 if (read_socket_inev
->kind
!= NO_EVENT
)
11004 if (event_kind
== kEventRawKeyUp
)
11007 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
11009 sizeof (char), NULL
, &char_code
);
11013 err
= GetEventParameter (event
, kEventParamKeyCode
,
11015 sizeof (UInt32
), NULL
, &key_code
);
11019 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
11020 char_code
, key_code
, modifiers
,
11022 (GetEventTime (event
) / kEventDurationMillisecond
)),
11034 static pascal OSStatus
11035 mac_handle_command_event (next_handler
, event
, data
)
11036 EventHandlerCallRef next_handler
;
11040 OSStatus err
, result
= eventNotHandledErr
;
11042 static const EventParamName names
[] =
11043 {kEventParamDirectObject
, kEventParamKeyModifiers
};
11044 static const EventParamType types
[] =
11045 {typeHICommand
, typeUInt32
};
11046 int num_params
= sizeof (names
) / sizeof (names
[0]);
11048 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
11049 NULL
, sizeof (HICommand
), NULL
, &command
);
11051 return eventNotHandledErr
;
11053 switch (GetEventKind (event
))
11055 case kEventCommandProcess
:
11056 result
= CallNextEventHandler (next_handler
, event
);
11057 if (result
!= eventNotHandledErr
)
11060 err
= GetEventParameter (event
, kEventParamDirectObject
,
11061 typeHICommand
, NULL
,
11062 sizeof (HICommand
), NULL
, &command
);
11064 if (err
!= noErr
|| command
.commandID
== 0)
11067 /* A HI command event is mapped to an Apple event whose event
11068 class symbol is `hi-command' and event ID is its command
11070 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
11085 static pascal OSStatus
11086 mac_handle_mouse_event (next_handler
, event
, data
)
11087 EventHandlerCallRef next_handler
;
11091 OSStatus err
, result
= eventNotHandledErr
;
11093 switch (GetEventKind (event
))
11095 case kEventMouseWheelMoved
:
11099 EventMouseWheelAxis axis
;
11103 result
= CallNextEventHandler (next_handler
, event
);
11104 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
11107 f
= mac_focus_frame (&one_mac_display_info
);
11109 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
11110 NULL
, sizeof (WindowRef
), NULL
, &wp
);
11112 || wp
!= FRAME_MAC_WINDOW (f
))
11115 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
11116 typeMouseWheelAxis
, NULL
,
11117 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
11118 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
11121 err
= GetEventParameter (event
, kEventParamMouseLocation
,
11122 typeQDPoint
, NULL
, sizeof (Point
),
11127 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
11128 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
11129 if (point
.h
< 0 || point
.v
< 0
11130 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
11131 f
->tool_bar_window
))
11134 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
11135 typeSInt32
, NULL
, sizeof (SInt32
),
11140 read_socket_inev
->kind
= WHEEL_EVENT
;
11141 read_socket_inev
->code
= 0;
11142 read_socket_inev
->modifiers
=
11143 (mac_event_to_emacs_modifiers (event
)
11144 | ((delta
< 0) ? down_modifier
: up_modifier
));
11145 XSETINT (read_socket_inev
->x
, point
.h
);
11146 XSETINT (read_socket_inev
->y
, point
.v
);
11147 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11161 static pascal OSStatus
11162 mac_handle_text_input_event (next_handler
, event
, data
)
11163 EventHandlerCallRef next_handler
;
11167 OSStatus err
, result
;
11168 Lisp_Object id_key
= Qnil
;
11170 const EventParamName
*names
;
11171 const EventParamType
*types
;
11172 static UInt32 seqno_uaia
= 0;
11173 static const EventParamName names_uaia
[] =
11174 {kEventParamTextInputSendComponentInstance
,
11175 kEventParamTextInputSendRefCon
,
11176 kEventParamTextInputSendSLRec
,
11177 kEventParamTextInputSendFixLen
,
11178 kEventParamTextInputSendText
,
11179 kEventParamTextInputSendUpdateRng
,
11180 kEventParamTextInputSendHiliteRng
,
11181 kEventParamTextInputSendClauseRng
,
11182 kEventParamTextInputSendPinRng
,
11183 kEventParamTextInputSendTextServiceEncoding
,
11184 kEventParamTextInputSendTextServiceMacEncoding
,
11185 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
11186 static const EventParamType types_uaia
[] =
11187 {typeComponentInstance
,
11189 typeIntlWritingCode
,
11196 typeTextRangeArray
,
11197 typeTextRangeArray
,
11203 static const EventParamName names_ufke
[] =
11204 {kEventParamTextInputSendComponentInstance
,
11205 kEventParamTextInputSendRefCon
,
11206 kEventParamTextInputSendSLRec
,
11207 kEventParamTextInputSendText
};
11208 static const EventParamType types_ufke
[] =
11209 {typeComponentInstance
,
11211 typeIntlWritingCode
,
11214 result
= CallNextEventHandler (next_handler
, event
);
11215 if (result
!= eventNotHandledErr
)
11218 switch (GetEventKind (event
))
11220 case kEventTextInputUpdateActiveInputArea
:
11221 id_key
= Qupdate_active_input_area
;
11222 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
11223 names
= names_uaia
;
11224 types
= types_uaia
;
11225 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
11226 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
11231 case kEventTextInputUnicodeForKeyEvent
:
11233 EventRef kbd_event
;
11234 UInt32 actual_size
, modifiers
;
11236 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
11237 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
11240 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
11242 sizeof (UInt32
), NULL
, &modifiers
);
11243 if (err
== noErr
&& mac_mapped_modifiers (modifiers
))
11244 /* There're mapped modifier keys. Process it in
11248 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11249 typeUnicodeText
, NULL
, 0, &actual_size
,
11251 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
11255 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
11256 typeUnicodeText
, NULL
,
11257 sizeof (UniChar
), NULL
, &code
);
11258 if (err
== noErr
&& code
< 0x80)
11260 /* ASCII character. Process it in do_keystroke. */
11261 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
11265 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
11266 typeUInt32
, NULL
, sizeof (UInt32
),
11268 if (!(err
== noErr
&& key_code
<= 0x7f
11269 && keycode_to_xkeysym_table
[key_code
]))
11272 mac_focus_frame (&one_mac_display_info
);
11274 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
11275 read_socket_inev
->code
= code
;
11276 read_socket_inev
->modifiers
=
11277 mac_to_emacs_modifiers (modifiers
);
11278 read_socket_inev
->modifiers
|=
11279 (extra_keyboard_modifiers
11280 & (meta_modifier
| alt_modifier
11281 | hyper_modifier
| super_modifier
));
11282 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
11290 /* Non-ASCII keystrokes without mapped modifiers are
11291 processed at the Lisp level. */
11292 id_key
= Qunicode_for_key_event
;
11293 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
11294 names
= names_ufke
;
11295 types
= types_ufke
;
11301 case kEventTextInputOffsetToPos
:
11307 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
11310 /* Strictly speaking, this is not always correct because
11311 previous events may change some states about display. */
11312 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
11314 /* Active input area is displayed around the current point. */
11315 f
= SELECTED_FRAME ();
11316 w
= XWINDOW (f
->selected_window
);
11318 else if (WINDOWP (echo_area_window
))
11320 /* Active input area is displayed in the echo area. */
11321 w
= XWINDOW (echo_area_window
);
11322 f
= WINDOW_XFRAME (w
);
11327 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
11328 + WINDOW_LEFT_FRINGE_WIDTH (w
)
11329 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
11330 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
11331 + FONT_BASE (FRAME_FONT (f
))
11332 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
11333 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
11334 typeQDPoint
, sizeof (typeQDPoint
), &p
);
11344 if (!NILP (id_key
))
11345 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
11351 #endif /* TARGET_API_MAC_CARBON */
11355 install_window_handler (window
)
11358 OSStatus err
= noErr
;
11360 #if TARGET_API_MAC_CARBON
11363 static const EventTypeSpec specs
[] =
11365 /* -- window refresh events -- */
11366 {kEventClassWindow
, kEventWindowUpdate
},
11367 /* -- window state change events -- */
11368 {kEventClassWindow
, kEventWindowShowing
},
11369 {kEventClassWindow
, kEventWindowHiding
},
11370 {kEventClassWindow
, kEventWindowShown
},
11371 {kEventClassWindow
, kEventWindowHidden
},
11372 {kEventClassWindow
, kEventWindowCollapsed
},
11373 {kEventClassWindow
, kEventWindowExpanded
},
11374 {kEventClassWindow
, kEventWindowBoundsChanging
},
11375 {kEventClassWindow
, kEventWindowBoundsChanged
},
11376 /* -- window action events -- */
11377 {kEventClassWindow
, kEventWindowClose
},
11378 {kEventClassWindow
, kEventWindowGetIdealSize
},
11380 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
11383 /* -- window focus events -- */
11384 {kEventClassWindow
, kEventWindowFocusAcquired
},
11385 {kEventClassWindow
, kEventWindowFocusRelinquish
},
11388 static EventHandlerUPP handle_window_eventUPP
= NULL
;
11390 if (handle_window_eventUPP
== NULL
)
11391 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
11393 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
11394 GetEventTypeCount (specs
),
11395 specs
, NULL
, NULL
);
11400 err
= install_drag_handler (window
);
11406 remove_window_handler (window
)
11409 remove_drag_handler (window
);
11412 #if TARGET_API_MAC_CARBON
11414 install_application_handler ()
11416 OSStatus err
= noErr
;
11420 static const EventTypeSpec specs
[] = {
11422 {kEventClassApplication
, kEventAppActivated
},
11423 {kEventClassApplication
, kEventAppDeactivated
},
11427 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11428 (mac_handle_application_event
),
11429 GetEventTypeCount (specs
),
11430 specs
, NULL
, NULL
);
11435 static const EventTypeSpec specs
[] =
11436 {{kEventClassKeyboard
, kEventRawKeyDown
},
11437 {kEventClassKeyboard
, kEventRawKeyRepeat
},
11438 {kEventClassKeyboard
, kEventRawKeyUp
}};
11440 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11441 (mac_handle_keyboard_event
),
11442 GetEventTypeCount (specs
),
11443 specs
, NULL
, NULL
);
11448 static const EventTypeSpec specs
[] =
11449 {{kEventClassCommand
, kEventCommandProcess
}};
11451 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11452 (mac_handle_command_event
),
11453 GetEventTypeCount (specs
),
11454 specs
, NULL
, NULL
);
11459 static const EventTypeSpec specs
[] =
11460 {{kEventClassMouse
, kEventMouseWheelMoved
}};
11462 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11463 (mac_handle_mouse_event
),
11464 GetEventTypeCount (specs
),
11465 specs
, NULL
, NULL
);
11471 static const EventTypeSpec spec
[] =
11472 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
11473 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
11474 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
11476 err
= InstallApplicationEventHandler (NewEventHandlerUPP
11477 (mac_handle_text_input_event
),
11478 GetEventTypeCount (spec
),
11484 err
= install_menu_target_item_handler ();
11488 err
= install_service_handler ();
11496 mac_handle_dm_notification (event
)
11499 mac_screen_config_changed
= 1;
11502 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11504 mac_handle_cg_display_reconfig (display
, flags
, user_info
)
11505 CGDirectDisplayID display
;
11506 CGDisplayChangeSummaryFlags flags
;
11509 mac_screen_config_changed
= 1;
11514 init_dm_notification_handler ()
11518 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11519 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11520 if (CGDisplayRegisterReconfigurationCallback
!= NULL
)
11523 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig
,
11526 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11527 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11529 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11530 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11532 static DMNotificationUPP handle_dm_notificationUPP
= NULL
;
11533 ProcessSerialNumber psn
;
11535 if (handle_dm_notificationUPP
== NULL
)
11536 handle_dm_notificationUPP
=
11537 NewDMNotificationUPP (mac_handle_dm_notification
);
11539 err
= GetCurrentProcess (&psn
);
11541 err
= DMRegisterNotifyProc (handle_dm_notificationUPP
, &psn
);
11549 mac_get_screen_info (dpyinfo
)
11550 struct mac_display_info
*dpyinfo
;
11553 /* HasDepth returns true if it is possible to have a 32 bit display,
11554 but this may not be what is actually used. Mac OSX can do better. */
11555 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11556 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11559 CGDisplayCount ndisps
;
11560 CGDirectDisplayID
*displays
;
11562 err
= CGGetActiveDisplayList (0, NULL
, &ndisps
);
11565 displays
= alloca (sizeof (CGDirectDisplayID
) * ndisps
);
11566 err
= CGGetActiveDisplayList (ndisps
, displays
, &ndisps
);
11570 CGRect bounds
= CGRectZero
;
11572 while (ndisps
-- > 0)
11573 bounds
= CGRectUnion (bounds
, CGDisplayBounds (displays
[ndisps
]));
11574 dpyinfo
->height
= CGRectGetHeight (bounds
);
11575 dpyinfo
->width
= CGRectGetWidth (bounds
);
11579 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11580 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11583 #else /* !MAC_OSX */
11585 GDHandle gdh
= GetMainDevice ();
11586 Rect rect
= (**gdh
).gdRect
;
11588 dpyinfo
->color_p
= TestDeviceAttribute (gdh
, gdDevType
);
11589 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11590 if (HasDepth (gdh
, dpyinfo
->n_planes
, gdDevType
, dpyinfo
->color_p
))
11593 for (gdh
= DMGetFirstScreenDevice (dmOnlyActiveDisplays
); gdh
;
11594 gdh
= DMGetNextScreenDevice (gdh
, dmOnlyActiveDisplays
))
11595 UnionRect (&rect
, &(**gdh
).gdRect
, &rect
);
11597 dpyinfo
->height
= rect
.bottom
- rect
.top
;
11598 dpyinfo
->width
= rect
.right
- rect
.left
;
11600 #endif /* !MAC_OSX */
11606 profiler_exit_proc ()
11608 ProfilerDump ("\pEmacs.prof");
11613 /* These few functions implement Emacs as a normal Mac application
11614 (almost): set up the heap and the Toolbox, handle necessary system
11615 events plus a few simple menu events. They also set up Emacs's
11616 access to functions defined in the rest of this file. Emacs uses
11617 function hooks to perform all its terminal I/O. A complete list of
11618 these functions appear in termhooks.h. For what they do, read the
11619 comments there and see also w32term.c and xterm.c. What's
11620 noticeably missing here is the event loop, which is normally
11621 present in most Mac application. After performing the necessary
11622 Mac initializations, main passes off control to emacs_main
11623 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11624 (defined further below) to read input. This is where
11625 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11632 #if __profile__ /* is the profiler on? */
11633 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
11638 /* set creator and type for files created by MSL */
11639 _fcreator
= MAC_EMACS_CREATOR_CODE
;
11643 do_init_managers ();
11647 #ifndef USE_LSB_TAG
11648 do_check_ram_size ();
11651 init_emacs_passwd_dir ();
11655 init_coercion_handler ();
11657 initialize_applescript ();
11659 init_apple_event_handler ();
11661 init_dm_notification_handler ();
11667 /* set up argv array from STR# resource */
11668 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
11672 /* free up AppleScript resources on exit */
11673 atexit (terminate_applescript
);
11675 #if __profile__ /* is the profiler on? */
11676 atexit (profiler_exit_proc
);
11679 /* 3rd param "envp" never used in emacs_main */
11680 (void) emacs_main (argc
, argv
, 0);
11683 /* Never reached - real exit in Fkill_emacs */
11688 #if !TARGET_API_MAC_CARBON
11689 static RgnHandle mouse_region
= NULL
;
11692 mac_wait_next_event (er
, sleep_time
, dequeue
)
11697 static EventRecord er_buf
= {nullEvent
};
11698 UInt32 target_tick
, current_tick
;
11699 EventMask event_mask
;
11701 if (mouse_region
== NULL
)
11702 mouse_region
= NewRgn ();
11704 event_mask
= everyEvent
;
11705 if (!mac_ready_for_apple_events
)
11706 event_mask
-= highLevelEventMask
;
11708 current_tick
= TickCount ();
11709 target_tick
= current_tick
+ sleep_time
;
11711 if (er_buf
.what
== nullEvent
)
11712 while (!WaitNextEvent (event_mask
, &er_buf
,
11713 target_tick
- current_tick
, mouse_region
))
11715 current_tick
= TickCount ();
11716 if (target_tick
<= current_tick
)
11722 er_buf
.what
= nullEvent
;
11725 #endif /* not TARGET_API_MAC_CARBON */
11727 #if TARGET_API_MAC_CARBON
11729 mac_post_mouse_moved_event ()
11731 EventRef event
= NULL
;
11734 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
11735 kEventAttributeNone
, &event
);
11740 GetGlobalMouse (&mouse_pos
);
11741 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
11742 sizeof (Point
), &mouse_pos
);
11746 UInt32 modifiers
= GetCurrentKeyModifiers ();
11748 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
11749 sizeof (UInt32
), &modifiers
);
11752 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
11753 kEventPriorityStandard
);
11755 ReleaseEvent (event
);
11761 /* Emacs calls this whenever it wants to read an input event from the
11764 XTread_socket (sd
, expected
, hold_quit
)
11766 struct input_event
*hold_quit
;
11768 struct input_event inev
;
11770 #if TARGET_API_MAC_CARBON
11772 EventTargetRef toolbox_dispatcher
;
11775 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11777 if (interrupt_input_blocked
)
11779 interrupt_input_pending
= 1;
11783 interrupt_input_pending
= 0;
11786 /* So people can tell when we have read the available input. */
11787 input_signal_count
++;
11791 #if TARGET_API_MAC_CARBON
11792 toolbox_dispatcher
= GetEventDispatcherTarget ();
11796 mac_prepare_for_quickdraw (NULL
),
11798 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
11799 kEventRemoveFromQueue
, &eventRef
))
11800 #else /* !TARGET_API_MAC_CARBON */
11801 while (mac_wait_next_event (&er
, 0, true))
11802 #endif /* !TARGET_API_MAC_CARBON */
11806 unsigned long timestamp
;
11809 inev
.kind
= NO_EVENT
;
11812 #if TARGET_API_MAC_CARBON
11813 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
11815 if (!mac_convert_event_ref (eventRef
, &er
))
11817 #else /* !TARGET_API_MAC_CARBON */
11818 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
11819 #endif /* !TARGET_API_MAC_CARBON */
11826 WindowRef window_ptr
;
11827 ControlPartCode part_code
;
11828 int tool_bar_p
= 0;
11830 #if TARGET_API_MAC_CARBON
11833 /* This is needed to send mouse events like aqua window
11834 buttons to the correct handler. */
11835 read_socket_inev
= &inev
;
11836 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
11837 read_socket_inev
= NULL
;
11838 if (err
!= eventNotHandledErr
)
11841 last_mouse_glyph_frame
= 0;
11843 if (dpyinfo
->grabbed
&& last_mouse_frame
11844 && FRAME_LIVE_P (last_mouse_frame
))
11846 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
11847 part_code
= inContent
;
11851 part_code
= FindWindow (er
.where
, &window_ptr
);
11852 if (tip_window
&& window_ptr
== tip_window
)
11854 HideWindow (tip_window
);
11855 part_code
= FindWindow (er
.where
, &window_ptr
);
11859 if (er
.what
!= mouseDown
&&
11860 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
11866 f
= mac_focus_frame (dpyinfo
);
11867 saved_menu_event_location
= er
.where
;
11868 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
11869 XSETFRAME (inev
.frame_or_window
, f
);
11874 #if TARGET_API_MAC_CARBON
11875 FrontNonFloatingWindow ()
11880 || (mac_window_to_frame (window_ptr
)
11881 != dpyinfo
->x_focus_frame
))
11882 SelectWindow (window_ptr
);
11885 ControlPartCode control_part_code
;
11889 ControlKind control_kind
;
11892 f
= mac_window_to_frame (window_ptr
);
11893 /* convert to local coordinates of new window */
11894 mouse_loc
.h
= (er
.where
.h
11896 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
11897 mouse_loc
.v
= (er
.where
.v
11899 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
11900 #if TARGET_API_MAC_CARBON
11901 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
11902 &control_part_code
);
11905 GetControlKind (ch
, &control_kind
);
11908 control_part_code
= FindControl (mouse_loc
, window_ptr
,
11912 #if TARGET_API_MAC_CARBON
11913 inev
.code
= mac_get_mouse_btn (eventRef
);
11914 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
11916 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
11917 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
11919 XSETINT (inev
.x
, mouse_loc
.h
);
11920 XSETINT (inev
.y
, mouse_loc
.v
);
11922 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
11924 #ifndef USE_TOOLKIT_SCROLL_BARS
11925 /* control_part_code becomes kControlNoPart if
11926 a progress indicator is clicked. */
11927 && control_part_code
!= kControlNoPart
11928 #else /* USE_TOOLKIT_SCROLL_BARS */
11930 && control_kind
.kind
== kControlKindScrollBar
11931 #endif /* MAC_OSX */
11932 #endif /* USE_TOOLKIT_SCROLL_BARS */
11935 struct scroll_bar
*bar
;
11937 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
11939 bar
= tracked_scroll_bar
;
11940 #ifndef USE_TOOLKIT_SCROLL_BARS
11941 control_part_code
= kControlIndicatorPart
;
11945 bar
= (struct scroll_bar
*) GetControlReference (ch
);
11946 #ifdef USE_TOOLKIT_SCROLL_BARS
11947 /* Make the "Ctrl-Mouse-2 splits window" work
11948 for toolkit scroll bars. */
11949 if (inev
.modifiers
& ctrl_modifier
)
11950 x_scroll_bar_handle_click (bar
, control_part_code
,
11952 else if (er
.what
== mouseDown
)
11953 x_scroll_bar_handle_press (bar
, control_part_code
,
11956 x_scroll_bar_handle_release (bar
, &inev
);
11957 #else /* not USE_TOOLKIT_SCROLL_BARS */
11958 x_scroll_bar_handle_click (bar
, control_part_code
,
11960 if (er
.what
== mouseDown
11961 && control_part_code
== kControlIndicatorPart
)
11962 tracked_scroll_bar
= bar
;
11964 tracked_scroll_bar
= NULL
;
11965 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11969 Lisp_Object window
;
11970 int x
= mouse_loc
.h
;
11971 int y
= mouse_loc
.v
;
11973 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
11974 if (EQ (window
, f
->tool_bar_window
))
11976 if (er
.what
== mouseDown
)
11977 handle_tool_bar_click (f
, x
, y
, 1, 0);
11979 handle_tool_bar_click (f
, x
, y
, 0,
11985 XSETFRAME (inev
.frame_or_window
, f
);
11986 inev
.kind
= MOUSE_CLICK_EVENT
;
11990 if (er
.what
== mouseDown
)
11992 dpyinfo
->grabbed
|= (1 << inev
.code
);
11993 last_mouse_frame
= f
;
11996 last_tool_bar_item
= -1;
12000 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
12001 /* If a button is released though it was not
12002 previously pressed, that would be because
12003 of multi-button emulation. */
12004 dpyinfo
->grabbed
= 0;
12006 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
12009 /* Ignore any mouse motion that happened before
12010 this event; any subsequent mouse-movement Emacs
12011 events should reflect only motion after the
12014 f
->mouse_moved
= 0;
12016 #ifdef USE_TOOLKIT_SCROLL_BARS
12017 if (inev
.kind
== MOUSE_CLICK_EVENT
12018 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
12019 && (inev
.modifiers
& ctrl_modifier
)))
12024 inev
.modifiers
|= down_modifier
;
12027 inev
.modifiers
|= up_modifier
;
12034 #if TARGET_API_MAC_CARBON
12036 if (IsWindowPathSelectClick (window_ptr
, &er
))
12038 WindowPathSelect (window_ptr
, NULL
, NULL
);
12041 if (part_code
== inProxyIcon
12042 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
12043 != errUserWantsToDragWindow
))
12045 DragWindow (window_ptr
, er
.where
, NULL
);
12046 #else /* not TARGET_API_MAC_CARBON */
12047 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12048 /* Update the frame parameters. */
12050 struct frame
*f
= mac_window_to_frame (window_ptr
);
12052 if (f
&& !f
->async_iconified
)
12053 mac_handle_origin_change (f
);
12055 #endif /* not TARGET_API_MAC_CARBON */
12059 if (TrackGoAway (window_ptr
, er
.where
))
12061 inev
.kind
= DELETE_WINDOW_EVENT
;
12062 XSETFRAME (inev
.frame_or_window
,
12063 mac_window_to_frame (window_ptr
));
12067 /* window resize handling added --ben */
12069 do_grow_window (window_ptr
, &er
);
12072 /* window zoom handling added --ben */
12075 if (TrackBox (window_ptr
, er
.where
, part_code
))
12076 do_zoom_window (window_ptr
, part_code
);
12079 #if USE_MAC_TOOLBAR
12085 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
12087 /* This doesn't work on Mac OS X 10.2. */
12089 HIViewClick (ch
, eventRef
);
12092 #endif /* USE_MAC_TOOLBAR */
12100 #if !TARGET_API_MAC_CARBON
12102 do_window_update ((WindowRef
) er
.message
);
12107 switch ((er
.message
>> 24) & 0x000000FF)
12109 case mouseMovedMessage
:
12110 #if !TARGET_API_MAC_CARBON
12111 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
12112 er
.where
.h
+ 1, er
.where
.v
+ 1);
12114 previous_help_echo_string
= help_echo_string
;
12115 help_echo_string
= Qnil
;
12117 if (dpyinfo
->grabbed
&& last_mouse_frame
12118 && FRAME_LIVE_P (last_mouse_frame
))
12119 f
= last_mouse_frame
;
12121 f
= dpyinfo
->x_focus_frame
;
12123 if (dpyinfo
->mouse_face_hidden
)
12125 dpyinfo
->mouse_face_hidden
= 0;
12126 clear_mouse_face (dpyinfo
);
12131 WindowRef wp
= FRAME_MAC_WINDOW (f
);
12134 mouse_pos
.h
= (er
.where
.h
12136 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12137 mouse_pos
.v
= (er
.where
.v
12139 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12140 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12141 #ifdef USE_TOOLKIT_SCROLL_BARS
12142 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
12144 #else /* not USE_TOOLKIT_SCROLL_BARS */
12145 x_scroll_bar_note_movement (tracked_scroll_bar
,
12147 - XINT (tracked_scroll_bar
->top
),
12148 er
.when
* (1000 / 60));
12149 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12152 /* Generate SELECT_WINDOW_EVENTs when needed. */
12153 if (!NILP (Vmouse_autoselect_window
))
12155 Lisp_Object window
;
12157 window
= window_from_coordinates (f
,
12162 /* Window will be selected only when it is
12163 not selected now and last mouse movement
12164 event was not in it. Minibuffer window
12165 will be selected iff it is active. */
12166 if (WINDOWP (window
)
12167 && !EQ (window
, last_window
)
12168 && !EQ (window
, selected_window
))
12170 inev
.kind
= SELECT_WINDOW_EVENT
;
12171 inev
.frame_or_window
= window
;
12174 last_window
=window
;
12176 if (!note_mouse_movement (f
, &mouse_pos
))
12177 help_echo_string
= previous_help_echo_string
;
12178 #if USE_MAC_TOOLBAR
12180 mac_tool_bar_note_mouse_movement (f
, eventRef
);
12185 /* If the contents of the global variable
12186 help_echo_string has changed, generate a
12188 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
12199 WindowRef window_ptr
= (WindowRef
) er
.message
;
12201 if (window_ptr
== tip_window
)
12203 HideWindow (tip_window
);
12207 if (!is_emacs_window (window_ptr
))
12210 f
= mac_window_to_frame (window_ptr
);
12212 if ((er
.modifiers
& activeFlag
) != 0)
12214 /* A window has been activated */
12217 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12219 mouse_loc
.h
= (er
.where
.h
12221 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
12222 mouse_loc
.v
= (er
.where
.v
12224 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
12225 /* Window-activated event counts as mouse movement,
12226 so update things that depend on mouse position. */
12227 note_mouse_movement (f
, &mouse_loc
);
12231 /* A window has been deactivated */
12232 #ifdef USE_TOOLKIT_SCROLL_BARS
12233 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
12235 struct input_event event
;
12237 EVENT_INIT (event
);
12238 event
.kind
= NO_EVENT
;
12239 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
12240 if (event
.kind
!= NO_EVENT
)
12242 event
.timestamp
= timestamp
;
12243 kbd_buffer_store_event_hold (&event
, hold_quit
);
12248 dpyinfo
->grabbed
= 0;
12250 x_detect_focus_change (dpyinfo
, &er
, &inev
);
12252 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12254 /* If we move outside the frame, then we're
12255 certainly no longer on any text in the
12257 clear_mouse_face (dpyinfo
);
12258 dpyinfo
->mouse_face_mouse_frame
= 0;
12261 /* Generate a nil HELP_EVENT to cancel a help-echo.
12262 Do it only if there's something to cancel.
12263 Otherwise, the startup message is cleared when the
12264 mouse leaves the frame. */
12265 if (any_help_event_p
)
12276 f
= mac_focus_frame (dpyinfo
);
12277 XSETFRAME (inev
.frame_or_window
, f
);
12279 /* If mouse-highlight is an integer, input clears out mouse
12281 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
12282 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
12284 clear_mouse_face (dpyinfo
);
12285 dpyinfo
->mouse_face_hidden
= 1;
12287 #if TARGET_API_MAC_CARBON
12290 do_keystroke (er
.what
, er
.message
& charCodeMask
,
12291 (er
.message
& keyCodeMask
) >> 8,
12292 er
.modifiers
, timestamp
, &inev
);
12296 case kHighLevelEvent
:
12297 AEProcessAppleEvent (&er
);
12302 #if TARGET_API_MAC_CARBON
12306 read_socket_inev
= &inev
;
12307 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
12308 read_socket_inev
= NULL
;
12313 #if TARGET_API_MAC_CARBON
12314 ReleaseEvent (eventRef
);
12317 if (inev
.kind
!= NO_EVENT
)
12319 inev
.timestamp
= timestamp
;
12320 kbd_buffer_store_event_hold (&inev
, hold_quit
);
12325 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
12330 XSETFRAME (frame
, f
);
12336 any_help_event_p
= 1;
12337 gen_help_event (help_echo_string
, frame
, help_echo_window
,
12338 help_echo_object
, help_echo_pos
);
12342 help_echo_string
= Qnil
;
12343 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
12350 /* If the focus was just given to an autoraising frame,
12352 /* ??? This ought to be able to handle more than one such frame. */
12353 if (pending_autoraise_frame
)
12355 x_raise_frame (pending_autoraise_frame
);
12356 pending_autoraise_frame
= 0;
12359 if (mac_screen_config_changed
)
12361 mac_get_screen_info (dpyinfo
);
12362 mac_screen_config_changed
= 0;
12365 #if !TARGET_API_MAC_CARBON
12366 /* Check which frames are still visible. We do this here because
12367 there doesn't seem to be any direct notification from the Window
12368 Manager that the visibility of a window has changed (at least,
12369 not in all cases). */
12371 Lisp_Object tail
, frame
;
12373 FOR_EACH_FRAME (tail
, frame
)
12375 struct frame
*f
= XFRAME (frame
);
12377 /* The tooltip has been drawn already. Avoid the
12378 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12379 if (EQ (frame
, tip_frame
))
12382 if (FRAME_MAC_P (f
))
12383 mac_handle_visibility_change (f
);
12394 /* Need to override CodeWarrior's input function so no conversion is
12395 done on newlines Otherwise compiled functions in .elc files will be
12396 read incorrectly. Defined in ...:MSL C:MSL
12397 Common:Source:buffer_io.c. */
12400 __convert_to_newlines (unsigned char * p
, size_t * n
)
12402 #pragma unused(p,n)
12406 __convert_from_newlines (unsigned char * p
, size_t * n
)
12408 #pragma unused(p,n)
12414 make_mac_terminal_frame (struct frame
*f
)
12419 XSETFRAME (frame
, f
);
12421 f
->output_method
= output_mac
;
12422 f
->output_data
.mac
= (struct mac_output
*)
12423 xmalloc (sizeof (struct mac_output
));
12424 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
12426 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
12428 FRAME_COLS (f
) = 96;
12429 FRAME_LINES (f
) = 4;
12431 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
12432 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
12434 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
12436 f
->output_data
.mac
->cursor_pixel
= 0;
12437 f
->output_data
.mac
->border_pixel
= 0x00ff00;
12438 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
12439 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
12441 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
12442 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
12443 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
12444 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
12445 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
12446 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
12448 FRAME_FONTSET (f
) = -1;
12449 f
->output_data
.mac
->explicit_parent
= 0;
12452 f
->border_width
= 0;
12454 f
->internal_border_width
= 0;
12459 f
->new_text_cols
= 0;
12460 f
->new_text_lines
= 0;
12462 SetRect (&r
, f
->left_pos
, f
->top_pos
,
12463 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
12464 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
12468 if (!(FRAME_MAC_WINDOW (f
) =
12469 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
12470 (WindowRef
) -1, 1, (long) f
->output_data
.mac
)))
12472 /* so that update events can find this mac_output struct */
12473 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
12479 /* Need to be initialized for unshow_buffer in window.c. */
12480 selected_window
= f
->selected_window
;
12482 Fmodify_frame_parameters (frame
,
12483 Fcons (Fcons (Qfont
,
12484 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
12485 Fmodify_frame_parameters (frame
,
12486 Fcons (Fcons (Qforeground_color
,
12487 build_string ("black")), Qnil
));
12488 Fmodify_frame_parameters (frame
,
12489 Fcons (Fcons (Qbackground_color
,
12490 build_string ("white")), Qnil
));
12495 /***********************************************************************
12497 ***********************************************************************/
12499 static int mac_initialized
= 0;
12502 mac_make_rdb (xrm_option
)
12503 const char *xrm_option
;
12505 XrmDatabase database
;
12507 database
= xrm_get_preference_database (NULL
);
12509 xrm_merge_string_database (database
, xrm_option
);
12514 struct mac_display_info
*
12515 mac_term_init (display_name
, xrm_option
, resource_name
)
12516 Lisp_Object display_name
;
12518 char *resource_name
;
12520 struct mac_display_info
*dpyinfo
;
12524 if (!mac_initialized
)
12527 mac_initialized
= 1;
12530 if (x_display_list
)
12531 error ("Sorry, this version can only handle one display");
12533 dpyinfo
= &one_mac_display_info
;
12534 bzero (dpyinfo
, sizeof (*dpyinfo
));
12537 dpyinfo
->mac_id_name
12538 = (char *) xmalloc (SCHARS (Vinvocation_name
)
12539 + SCHARS (Vsystem_name
)
12541 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
12542 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
12544 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
12545 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
12548 dpyinfo
->reference_count
= 0;
12549 dpyinfo
->resx
= 72.0;
12550 dpyinfo
->resy
= 72.0;
12552 mac_get_screen_info (dpyinfo
);
12554 dpyinfo
->grabbed
= 0;
12555 dpyinfo
->root_window
= NULL
;
12556 dpyinfo
->image_cache
= make_image_cache ();
12558 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12559 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12560 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12561 dpyinfo
->mouse_face_window
= Qnil
;
12562 dpyinfo
->mouse_face_overlay
= Qnil
;
12563 dpyinfo
->mouse_face_hidden
= 0;
12565 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
12567 /* Put this display on the chain. */
12568 dpyinfo
->next
= x_display_list
;
12569 x_display_list
= dpyinfo
;
12571 /* Put it on x_display_name_list. */
12572 x_display_name_list
= Fcons (Fcons (display_name
,
12573 Fcons (Qnil
, dpyinfo
->xrdb
)),
12574 x_display_name_list
);
12575 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12582 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12585 x_delete_display (dpyinfo
)
12586 struct mac_display_info
*dpyinfo
;
12590 /* Discard this display from x_display_name_list and x_display_list.
12591 We can't use Fdelq because that can quit. */
12592 if (! NILP (x_display_name_list
)
12593 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12594 x_display_name_list
= XCDR (x_display_name_list
);
12599 tail
= x_display_name_list
;
12600 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12602 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
12604 XSETCDR (tail
, XCDR (XCDR (tail
)));
12607 tail
= XCDR (tail
);
12611 if (x_display_list
== dpyinfo
)
12612 x_display_list
= dpyinfo
->next
;
12615 struct x_display_info
*tail
;
12617 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12618 if (tail
->next
== dpyinfo
)
12619 tail
->next
= tail
->next
->next
;
12622 /* Free the font names in the font table. */
12623 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12624 if (dpyinfo
->font_table
[i
].name
)
12626 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
12627 xfree (dpyinfo
->font_table
[i
].full_name
);
12628 xfree (dpyinfo
->font_table
[i
].name
);
12631 if (dpyinfo
->font_table
)
12633 if (dpyinfo
->font_table
->font_encoder
)
12634 xfree (dpyinfo
->font_table
->font_encoder
);
12635 xfree (dpyinfo
->font_table
);
12637 if (dpyinfo
->mac_id_name
)
12638 xfree (dpyinfo
->mac_id_name
);
12640 if (x_display_list
== 0)
12642 mac_clear_font_name_table ();
12643 bzero (dpyinfo
, sizeof (*dpyinfo
));
12654 MenuItemIndex menu_index
;
12656 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
12657 &menu
, &menu_index
);
12659 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12660 EnableMenuCommand (NULL
, kHICommandPreferences
);
12661 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
12662 &menu
, &menu_index
);
12665 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
12666 InsertMenuItemTextWithCFString (menu
, NULL
,
12667 0, kMenuItemAttrSeparator
, 0);
12668 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
12669 0, 0, kHICommandAbout
);
12671 #else /* !MAC_OSX */
12672 #if TARGET_API_MAC_CARBON
12673 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
12683 static InterfaceTypeList types
= {kUnicodeDocument
};
12685 static InterfaceTypeList types
= {kTextService
};
12688 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
12689 &tsm_document_id
, 0);
12693 /* Set up use of X before we make the first connection. */
12695 extern frame_parm_handler mac_frame_parm_handlers
[];
12697 static struct redisplay_interface x_redisplay_interface
=
12699 mac_frame_parm_handlers
,
12703 x_clear_end_of_line
,
12705 x_after_update_window_line
,
12706 x_update_window_begin
,
12707 x_update_window_end
,
12711 mac_flush_display_optional
,
12713 0, /* flush_display_optional */
12715 x_clear_window_mouse_face
,
12716 x_get_glyph_overhangs
,
12717 x_fix_overlapping_area
,
12718 x_draw_fringe_bitmap
,
12720 mac_define_fringe_bitmap
,
12721 mac_destroy_fringe_bitmap
,
12723 0, /* define_fringe_bitmap */
12724 0, /* destroy_fringe_bitmap */
12726 mac_per_char_metric
,
12728 mac_compute_glyph_string_overhangs
,
12729 x_draw_glyph_string
,
12730 mac_define_frame_cursor
,
12731 mac_clear_frame_area
,
12732 mac_draw_window_cursor
,
12733 mac_draw_vertical_window_border
,
12734 mac_shift_glyphs_for_insert
12740 rif
= &x_redisplay_interface
;
12742 clear_frame_hook
= x_clear_frame
;
12743 ins_del_lines_hook
= x_ins_del_lines
;
12744 delete_glyphs_hook
= x_delete_glyphs
;
12745 ring_bell_hook
= XTring_bell
;
12746 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12747 set_terminal_modes_hook
= XTset_terminal_modes
;
12748 update_begin_hook
= x_update_begin
;
12749 update_end_hook
= x_update_end
;
12750 set_terminal_window_hook
= XTset_terminal_window
;
12751 read_socket_hook
= XTread_socket
;
12752 frame_up_to_date_hook
= XTframe_up_to_date
;
12753 mouse_position_hook
= XTmouse_position
;
12754 frame_rehighlight_hook
= XTframe_rehighlight
;
12755 frame_raise_lower_hook
= XTframe_raise_lower
;
12757 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12758 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12759 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12760 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12762 scroll_region_ok
= 1; /* we'll scroll partial frames */
12763 char_ins_del_ok
= 1;
12764 line_ins_del_ok
= 1; /* we'll just blt 'em */
12765 fast_clear_end_of_line
= 1; /* X does this well */
12766 memory_below_frame
= 0; /* we don't remember what scrolls
12770 last_tool_bar_item
= -1;
12771 any_help_event_p
= 0;
12773 /* Try to use interrupt input; if we can't, then start polling. */
12774 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
12778 #if TARGET_API_MAC_CARBON
12780 install_application_handler ();
12789 init_coercion_handler ();
12791 init_apple_event_handler ();
12793 init_dm_notification_handler ();
12795 if (!inhibit_window_system
)
12797 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
12799 SetFrontProcess (&psn
);
12807 mac_init_fringe ();
12818 staticpro (&x_error_message_string
);
12819 x_error_message_string
= Qnil
;
12822 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
12823 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
12824 Qalt
= intern ("alt"); staticpro (&Qalt
);
12825 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
12826 Qsuper
= intern ("super"); staticpro (&Qsuper
);
12827 Qmodifier_value
= intern ("modifier-value");
12828 staticpro (&Qmodifier_value
);
12830 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
12831 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12832 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12833 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12834 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12836 #if TARGET_API_MAC_CARBON
12837 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
12839 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
12840 staticpro (&Qtoolbar_switch_mode
);
12841 #if USE_MAC_FONT_PANEL
12842 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
12843 Qselection
= intern ("selection"); staticpro (&Qselection
);
12846 Qservice
= intern ("service"); staticpro (&Qservice
);
12847 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
12848 Qperform
= intern ("perform"); staticpro (&Qperform
);
12851 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
12852 Qupdate_active_input_area
= intern ("update-active-input-area");
12853 staticpro (&Qupdate_active_input_area
);
12854 Qunicode_for_key_event
= intern ("unicode-for-key-event");
12855 staticpro (&Qunicode_for_key_event
);
12860 Fprovide (intern ("mac-carbon"), Qnil
);
12863 staticpro (&Qreverse
);
12864 Qreverse
= intern ("reverse");
12866 staticpro (&x_display_name_list
);
12867 x_display_name_list
= Qnil
;
12869 staticpro (&last_mouse_scroll_bar
);
12870 last_mouse_scroll_bar
= Qnil
;
12872 staticpro (&fm_font_family_alist
);
12873 fm_font_family_alist
= Qnil
;
12876 staticpro (&atsu_font_id_hash
);
12877 atsu_font_id_hash
= Qnil
;
12879 staticpro (&fm_style_face_attributes_alist
);
12880 fm_style_face_attributes_alist
= Qnil
;
12884 staticpro (&saved_ts_script_language_on_focus
);
12885 saved_ts_script_language_on_focus
= Qnil
;
12888 /* We don't yet support this, but defining this here avoids whining
12889 from cus-start.el and other places, like "M-x set-variable". */
12890 DEFVAR_BOOL ("x-use-underline-position-properties",
12891 &x_use_underline_position_properties
,
12892 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12893 A value of nil means ignore them. If you encounter fonts with bogus
12894 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12895 to 4.1, set this to nil.
12897 NOTE: Not supported on Mac yet. */);
12898 x_use_underline_position_properties
= 0;
12900 DEFVAR_BOOL ("x-underline-at-descent-line",
12901 &x_underline_at_descent_line
,
12902 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
12903 A value of nil means to draw the underline according to the value of the
12904 variable `x-use-underline-position-properties', which is usually at the
12905 baseline level. The default value is nil. */);
12906 x_underline_at_descent_line
= 0;
12908 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
12909 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
12910 #ifdef USE_TOOLKIT_SCROLL_BARS
12911 Vx_toolkit_scroll_bars
= Qt
;
12913 Vx_toolkit_scroll_bars
= Qnil
;
12916 staticpro (&last_mouse_motion_frame
);
12917 last_mouse_motion_frame
= Qnil
;
12919 /* Variables to configure modifier key assignment. */
12921 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
12922 doc
: /* *Modifier key assumed when the Mac control key is pressed.
12923 The value can be `control', `meta', `alt', `hyper', or `super' for the
12924 respective modifier. The default is `control'. */);
12925 Vmac_control_modifier
= Qcontrol
;
12927 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
12928 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
12929 The value can be `control', `meta', `alt', `hyper', or `super' for the
12930 respective modifier. If the value is nil then the key will act as the
12931 normal Mac control modifier, and the option key can be used to compose
12932 characters depending on the chosen Mac keyboard setting. */);
12933 Vmac_option_modifier
= Qnil
;
12935 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
12936 doc
: /* *Modifier key assumed when the Mac command key is pressed.
12937 The value can be `control', `meta', `alt', `hyper', or `super' for the
12938 respective modifier. The default is `meta'. */);
12939 Vmac_command_modifier
= Qmeta
;
12941 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
12942 doc
: /* *Modifier key assumed when the Mac function key is pressed.
12943 The value can be `control', `meta', `alt', `hyper', or `super' for the
12944 respective modifier. Note that remapping the function key may lead to
12945 unexpected results for some keys on non-US/GB keyboards. */);
12946 Vmac_function_modifier
= Qnil
;
12948 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12949 &Vmac_emulate_three_button_mouse
,
12950 doc
: /* *Specify a way of three button mouse emulation.
12951 The value can be nil, t, or the symbol `reverse'.
12952 A value of nil means that no emulation should be done and the modifiers
12953 should be placed on the mouse-1 event.
12954 t means that when the option-key is held down while pressing the mouse
12955 button, the click will register as mouse-2 and while the command-key
12956 is held down, the click will register as mouse-3.
12957 The symbol `reverse' means that the option-key will register for
12958 mouse-3 and the command-key will register for mouse-2. */);
12959 Vmac_emulate_three_button_mouse
= Qnil
;
12961 #if TARGET_API_MAC_CARBON
12962 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
12963 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12964 Otherwise, the right click will be treated as mouse-2 and the wheel
12965 button will be mouse-3. */);
12966 mac_wheel_button_is_mouse_2
= 1;
12968 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
12969 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12970 mac_pass_command_to_system
= 1;
12972 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
12973 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12974 mac_pass_control_to_system
= 1;
12978 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
12979 doc
: /* *If non-nil, allow anti-aliasing.
12980 The text will be rendered using Core Graphics text rendering which
12981 may anti-alias the text. */);
12983 mac_use_core_graphics
= 1;
12985 mac_use_core_graphics
= 0;
12988 /* Register an entry for `mac-roman' so that it can be used when
12989 creating the terminal frame on Mac OS 9 before loading
12990 term/mac-win.elc. */
12991 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
12992 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
12993 Each entry should be of the form:
12995 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12997 where CHARSET-NAME is a string used in font names to identify the
12998 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12999 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13000 Vmac_charset_info_alist
=
13001 Fcons (list3 (build_string ("mac-roman"),
13002 make_number (smRoman
), Qnil
), Qnil
);
13005 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
13006 doc
: /* Overlay used to display Mac TSM active input area. */);
13007 Vmac_ts_active_input_overlay
= Qnil
;
13009 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
13010 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
13011 If the value is t, the input script and language are restored to those
13012 used in the last focus frame. If the value is a pair of integers, the
13013 input script and language codes, which are defined in the Script
13014 Manager, are set to its car and cdr parts, respectively. Otherwise,
13015 Emacs doesn't set them and thus follows the system default behavior. */);
13016 Vmac_ts_script_language_on_focus
= Qnil
;
13020 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13021 (do not change this comment) */