1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
62 #endif /* not TARGET_API_MAC_CARBON */
75 #include "dispextern.h"
77 #include "termhooks.h"
84 #include "intervals.h"
90 /* Non-nil means Emacs uses toolkit scroll bars. */
92 Lisp_Object Vx_toolkit_scroll_bars
;
94 /* If non-zero, the text will be rendered using Core Graphics text
95 rendering which may anti-alias the text. */
96 int mac_use_core_graphics
;
99 /* Non-zero means that a HELP_EVENT has been generated since Emacs
102 static int any_help_event_p
;
104 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
105 static Lisp_Object last_window
;
107 /* Non-zero means make use of UNDERLINE_POSITION font properties.
108 (Not yet supported.) */
109 int x_use_underline_position_properties
;
111 /* Non-zero means to draw the underline at the same place as the descent line. */
113 int x_underline_at_descent_line
;
115 /* This is a chain of structures for all the X displays currently in
118 struct x_display_info
*x_display_list
;
120 /* This is a list of cons cells, each of the form (NAME
121 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
122 x_display_list and in the same order. NAME is the name of the
123 frame. FONT-LIST-CACHE records previous values returned by
124 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
125 equivalent, which is implemented with a Lisp object, for the
128 Lisp_Object x_display_name_list
;
130 /* This is display since Mac does not support multiple ones. */
131 struct mac_display_info one_mac_display_info
;
133 /* Frame being updated by update_frame. This is declared in term.c.
134 This is set by update_begin and looked at by all the XT functions.
135 It is zero while not inside an update. In that case, the XT
136 functions assume that `selected_frame' is the frame to apply to. */
138 extern struct frame
*updating_frame
;
140 /* This is a frame waiting to be auto-raised, within XTread_socket. */
142 struct frame
*pending_autoraise_frame
;
146 Formerly, we used PointerMotionHintMask (in standard_event_mask)
147 so that we would have to call XQueryPointer after each MotionNotify
148 event to ask for another such event. However, this made mouse tracking
149 slow, and there was a bug that made it eventually stop.
151 Simply asking for MotionNotify all the time seems to work better.
153 In order to avoid asking for motion events and then throwing most
154 of them away or busy-polling the server for mouse positions, we ask
155 the server for pointer motion hints. This means that we get only
156 one event per group of mouse movements. "Groups" are delimited by
157 other kinds of events (focus changes and button clicks, for
158 example), or by XQueryPointer calls; when one of these happens, we
159 get another MotionNotify event the next time the mouse moves. This
160 is at least as efficient as getting motion events when mouse
161 tracking is on, and I suspect only negligibly worse when tracking
164 /* Where the mouse was last time we reported a mouse event. */
166 static Rect last_mouse_glyph
;
167 static FRAME_PTR last_mouse_glyph_frame
;
169 /* The scroll bar in which the last X motion event occurred.
171 If the last X motion event occurred in a scroll bar, we set this so
172 XTmouse_position can know whether to report a scroll bar motion or
175 If the last X motion event didn't occur in a scroll bar, we set
176 this to Qnil, to tell XTmouse_position to return an ordinary motion
179 static Lisp_Object last_mouse_scroll_bar
;
181 /* This is a hack. We would really prefer that XTmouse_position would
182 return the time associated with the position it returns, but there
183 doesn't seem to be any way to wrest the time-stamp from the server
184 along with the position query. So, we just keep track of the time
185 of the last movement we received, and return that in hopes that
186 it's somewhat accurate. */
188 static Time last_mouse_movement_time
;
190 struct scroll_bar
*tracked_scroll_bar
= NULL
;
192 /* Incremented by XTread_socket whenever it really tries to read
196 static int volatile input_signal_count
;
198 static int input_signal_count
;
201 extern Lisp_Object Vsystem_name
;
203 extern Lisp_Object Qeql
;
205 /* A mask of extra modifier bits to put into every keyboard char. */
207 extern EMACS_INT extra_keyboard_modifiers
;
209 /* The keysyms to use for the various modifiers. */
211 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
213 extern int inhibit_window_system
;
215 #if __MRC__ && !TARGET_API_MAC_CARBON
216 QDGlobals qd
; /* QuickDraw global information structure. */
219 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
221 struct mac_display_info
*mac_display_info_for_display (Display
*);
222 static void x_update_window_end
P_ ((struct window
*, int, int));
223 int x_catch_errors
P_ ((Display
*));
224 void x_uncatch_errors
P_ ((Display
*, int));
225 void x_lower_frame
P_ ((struct frame
*));
226 void x_scroll_bar_clear
P_ ((struct frame
*));
227 int x_had_errors_p
P_ ((Display
*));
228 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
229 void x_raise_frame
P_ ((struct frame
*));
230 void x_set_window_size
P_ ((struct frame
*, int, int, int));
231 void x_wm_set_window_state
P_ ((struct frame
*, int));
232 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
233 void mac_initialize
P_ ((void));
234 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
235 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
236 static void x_update_end
P_ ((struct frame
*));
237 static void XTframe_up_to_date
P_ ((struct frame
*));
238 static void XTset_terminal_modes
P_ ((void));
239 static void XTreset_terminal_modes
P_ ((void));
240 static void x_clear_frame
P_ ((void));
241 static void frame_highlight
P_ ((struct frame
*));
242 static void frame_unhighlight
P_ ((struct frame
*));
243 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
244 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
245 struct frame
*, struct input_event
*));
246 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
248 struct input_event
*));
249 static void XTframe_rehighlight
P_ ((struct frame
*));
250 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
251 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
252 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
253 enum text_cursor_kinds
));
255 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
256 static void x_flush
P_ ((struct frame
*f
));
257 static void x_update_begin
P_ ((struct frame
*));
258 static void x_update_window_begin
P_ ((struct window
*));
259 static void x_after_update_window_line
P_ ((struct glyph_row
*));
260 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
261 enum scroll_bar_part
*,
262 Lisp_Object
*, Lisp_Object
*,
265 static int is_emacs_window
P_ ((WindowPtr
));
266 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
267 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
269 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
270 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
271 #define GC_FONT(gc) ((gc)->xgcv.font)
272 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
273 #define CG_SET_FILL_COLOR(context, color) \
274 CGContextSetRGBFillColor (context, \
275 RED_FROM_ULONG (color) / 255.0f, \
276 GREEN_FROM_ULONG (color) / 255.0f, \
277 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
278 #define CG_SET_STROKE_COLOR(context, color) \
279 CGContextSetRGBStrokeColor (context, \
280 RED_FROM_ULONG (color) / 255.0f, \
281 GREEN_FROM_ULONG (color) / 255.0f, \
282 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
284 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
286 /* Fringe bitmaps. */
288 static int max_fringe_bmp
= 0;
289 static CGImageRef
*fringe_bmp
= 0;
292 mac_begin_cg_clip (f
, gc
)
296 CGContextRef context
= FRAME_CG_CONTEXT (f
);
300 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
301 FRAME_CG_CONTEXT (f
) = context
;
304 CGContextSaveGState (context
);
305 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
306 CGContextScaleCTM (context
, 1, -1);
307 if (gc
&& gc
->n_clip_rects
)
308 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
317 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
321 mac_prepare_for_quickdraw (f
)
326 Lisp_Object rest
, frame
;
327 FOR_EACH_FRAME (rest
, frame
)
328 if (FRAME_MAC_P (XFRAME (frame
)))
329 mac_prepare_for_quickdraw (XFRAME (frame
));
333 CGContextRef context
= FRAME_CG_CONTEXT (f
);
337 CGContextSynchronize (context
);
338 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
339 &FRAME_CG_CONTEXT (f
));
345 static RgnHandle saved_port_clip_region
= NULL
;
351 static RgnHandle new_region
= NULL
;
353 if (saved_port_clip_region
== NULL
)
354 saved_port_clip_region
= NewRgn ();
355 if (new_region
== NULL
)
356 new_region
= NewRgn ();
358 if (gc
->n_clip_rects
)
360 GetClip (saved_port_clip_region
);
361 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
362 SetClip (new_region
);
370 if (gc
->n_clip_rects
)
371 SetClip (saved_port_clip_region
);
375 /* X display function emulation */
378 XFreePixmap (display
, pixmap
)
379 Display
*display
; /* not used */
382 DisposeGWorld (pixmap
);
386 /* Mac version of XDrawLine. */
389 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
395 CGContextRef context
;
396 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
399 gx1
+= 0.5f
, gx2
+= 0.5f
;
401 gy1
+= 0.5f
, gy2
+= 0.5f
;
403 context
= mac_begin_cg_clip (f
, gc
);
404 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
405 CGContextBeginPath (context
);
406 CGContextMoveToPoint (context
, gx1
, gy1
);
407 CGContextAddLineToPoint (context
, gx2
, gy2
);
408 CGContextClosePath (context
);
409 CGContextStrokePath (context
);
427 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
429 RGBForeColor (GC_FORE_COLOR (gc
));
439 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
463 GetGWorld (&old_port
, &old_gdh
);
466 RGBForeColor (GC_FORE_COLOR (gc
));
468 LockPixels (GetGWorldPixMap (p
));
471 UnlockPixels (GetGWorldPixMap (p
));
473 SetGWorld (old_port
, old_gdh
);
478 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
482 unsigned int width
, height
;
485 CGContextRef context
;
487 context
= mac_begin_cg_clip (f
, gc
);
488 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
489 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
494 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
496 RGBBackColor (GC_BACK_COLOR (gc
));
497 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
503 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
508 /* Mac version of XClearArea. */
511 mac_clear_area (f
, x
, y
, width
, height
)
514 unsigned int width
, height
;
516 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
519 /* Mac version of XClearWindow. */
526 CGContextRef context
;
527 GC gc
= FRAME_NORMAL_GC (f
);
529 context
= mac_begin_cg_clip (f
, NULL
);
530 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
531 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
532 FRAME_PIXEL_HEIGHT (f
)));
535 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
537 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
539 #if TARGET_API_MAC_CARBON
543 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
546 #else /* not TARGET_API_MAC_CARBON */
547 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
548 #endif /* not TARGET_API_MAC_CARBON */
553 /* Mac replacement for XCopyArea. */
557 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
558 dest_x
, dest_y
, overlay_p
)
563 unsigned int width
, height
;
564 int dest_x
, dest_y
, overlay_p
;
566 CGContextRef context
;
567 float port_height
= FRAME_PIXEL_HEIGHT (f
);
568 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
570 context
= mac_begin_cg_clip (f
, gc
);
573 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
574 CGContextFillRect (context
, dest_rect
);
576 CGContextClipToRect (context
, dest_rect
);
577 CGContextScaleCTM (context
, 1, -1);
578 CGContextTranslateCTM (context
, 0, -port_height
);
579 if (CGImageIsMask (image
))
580 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
581 CGContextDrawImage (context
,
582 CGRectMake (dest_x
- src_x
,
583 port_height
- (dest_y
- src_y
584 + CGImageGetHeight (image
)),
585 CGImageGetWidth (image
),
586 CGImageGetHeight (image
)),
591 #else /* !USE_CG_DRAWING */
594 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
597 int x
, y
, width
, height
;
598 unsigned short *bits
;
604 bitmap
.rowBytes
= sizeof(unsigned short);
605 bitmap
.baseAddr
= (char *)bits
;
606 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
608 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
610 RGBForeColor (GC_FORE_COLOR (gc
));
611 RGBBackColor (GC_BACK_COLOR (gc
));
612 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
615 #if TARGET_API_MAC_CARBON
621 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
622 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
623 UnlockPortBits (port
);
625 #else /* not TARGET_API_MAC_CARBON */
626 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
627 overlay_p
? srcOr
: srcCopy
, 0);
628 #endif /* not TARGET_API_MAC_CARBON */
631 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
633 #endif /* !USE_CG_DRAWING */
636 /* Mac replacement for XCreateBitmapFromBitmapData. */
639 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
644 static const unsigned char swap_nibble
[16]
645 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
646 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
647 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
648 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
652 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
653 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
654 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
655 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
656 for (i
= 0; i
< h
; i
++)
658 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
659 for (j
= 0; j
< w1
; j
++)
661 /* Bitswap XBM bytes to match how Mac does things. */
662 unsigned char c
= *bits
++;
663 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
664 | (swap_nibble
[(c
>>4) & 0xf]));;
668 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
673 mac_free_bitmap (bitmap
)
676 xfree (bitmap
->baseAddr
);
681 XCreatePixmap (display
, w
, width
, height
, depth
)
682 Display
*display
; /* not used */
684 unsigned int width
, height
;
691 SetPortWindowPort (w
);
693 SetRect (&r
, 0, 0, width
, height
);
694 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
697 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
698 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
700 /* CreateCGImageFromPixMaps requires ARGB format. */
701 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
710 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
711 Display
*display
; /* not used */
714 unsigned int width
, height
;
715 unsigned long fg
, bg
;
722 static GC gc
= NULL
; /* not reentrant */
725 gc
= XCreateGC (display
, w
, 0, NULL
);
727 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
731 GetGWorld (&old_port
, &old_gdh
);
732 SetGWorld (pixmap
, NULL
);
733 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
734 XSetForeground (display
, gc
, fg
);
735 XSetBackground (display
, gc
, bg
);
736 RGBForeColor (GC_FORE_COLOR (gc
));
737 RGBBackColor (GC_BACK_COLOR (gc
));
738 LockPixels (GetGWorldPixMap (pixmap
));
739 #if TARGET_API_MAC_CARBON
740 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
741 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
742 #else /* not TARGET_API_MAC_CARBON */
743 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
744 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
745 #endif /* not TARGET_API_MAC_CARBON */
746 UnlockPixels (GetGWorldPixMap (pixmap
));
747 SetGWorld (old_port
, old_gdh
);
748 mac_free_bitmap (&bitmap
);
754 /* Mac replacement for XFillRectangle. */
757 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
761 unsigned int width
, height
;
764 CGContextRef context
;
766 context
= mac_begin_cg_clip (f
, gc
);
767 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
768 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
773 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
775 RGBForeColor (GC_FORE_COLOR (gc
));
776 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
779 PaintRect (&r
); /* using foreground color of gc */
785 /* Mac replacement for XDrawRectangle: dest is a window. */
788 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
792 unsigned int width
, height
;
795 CGContextRef context
;
797 context
= mac_begin_cg_clip (f
, gc
);
798 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
799 CGContextStrokeRect (context
,
800 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
805 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
807 RGBForeColor (GC_FORE_COLOR (gc
));
808 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
811 FrameRect (&r
); /* using foreground color of gc */
819 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
820 ConstUniCharArrayPtr text
;
821 UniCharCount text_length
;
823 ATSUTextLayout
*text_layout
;
826 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
828 if (saved_text_layout
== NULL
)
830 static const UniCharCount lengths
[] = {kATSUToTextEnd
};
831 static const ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
832 static const ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
833 static ATSLineLayoutOptions line_layout
=
834 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
835 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
836 | kATSLineUseQDRendering
838 kATSLineIsDisplayOnly
| kATSLineFractDisable
841 static const ATSUAttributeValuePtr values
[] = {&line_layout
};
843 err
= ATSUCreateTextLayoutWithTextPtr (text
,
844 kATSUFromTextBeginning
,
850 err
= ATSUSetLayoutControls (saved_text_layout
,
851 sizeof (tags
) / sizeof (tags
[0]),
852 tags
, sizes
, values
);
853 /* XXX: Should we do this? */
855 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
859 err
= ATSUSetRunStyle (saved_text_layout
, style
,
860 kATSUFromTextBeginning
, kATSUToTextEnd
);
862 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
863 kATSUFromTextBeginning
,
869 *text_layout
= saved_text_layout
;
876 mac_invert_rectangle (f
, x
, y
, width
, height
)
879 unsigned int width
, height
;
884 mac_prepare_for_quickdraw (f
);
886 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
888 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
895 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
896 overstrike_p
, bytes_per_char
)
901 int nchars
, bg_width
, overstrike_p
, bytes_per_char
;
903 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
906 if (GC_FONT (gc
)->mac_style
)
909 ATSUTextLayout text_layout
;
911 xassert (bytes_per_char
== 2);
913 #ifndef WORDS_BIG_ENDIAN
916 UniChar
*text
= (UniChar
*)buf
;
918 for (i
= 0; i
< nchars
; i
++)
919 text
[i
] = EndianU16_BtoN (text
[i
]);
922 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
924 GC_FONT (gc
)->mac_style
,
929 if (!mac_use_core_graphics
)
933 mac_prepare_for_quickdraw (f
);
936 RGBForeColor (GC_FORE_COLOR (gc
));
941 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
942 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
943 RGBBackColor (GC_BACK_COLOR (gc
));
945 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
948 ATSUDrawText (text_layout
,
949 kATSUFromTextBeginning
, kATSUToTextEnd
,
950 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
954 ATSUDrawText (text_layout
,
955 kATSUFromTextBeginning
, kATSUToTextEnd
,
956 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
964 static CGContextRef context
;
965 float port_height
= FRAME_PIXEL_HEIGHT (f
);
966 static const ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
967 static const ByteCount sizes
[] = {sizeof (CGContextRef
)};
968 static const ATSUAttributeValuePtr values
[] = {&context
};
971 context
= mac_begin_cg_clip (f
, gc
);
974 QDBeginCGContext (port
, &context
);
975 if (gc
->n_clip_rects
|| bg_width
)
977 CGContextTranslateCTM (context
, 0, port_height
);
978 CGContextScaleCTM (context
, 1, -1);
979 if (gc
->n_clip_rects
)
980 CGContextClipToRects (context
, gc
->clip_rects
,
985 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
988 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
989 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
991 CGContextScaleCTM (context
, 1, -1);
992 CGContextTranslateCTM (context
, 0, -port_height
);
996 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
997 err
= ATSUSetLayoutControls (text_layout
,
998 sizeof (tags
) / sizeof (tags
[0]),
999 tags
, sizes
, values
);
1002 ATSUDrawText (text_layout
,
1003 kATSUFromTextBeginning
, kATSUToTextEnd
,
1004 Long2Fix (x
), Long2Fix (port_height
- y
));
1006 ATSUDrawText (text_layout
,
1007 kATSUFromTextBeginning
, kATSUToTextEnd
,
1008 Long2Fix (x
+ 1), Long2Fix (port_height
- y
));
1011 mac_end_cg_clip (f
);
1014 CGContextSynchronize (context
);
1015 QDEndCGContext (port
, &context
);
1018 /* This doesn't work on Mac OS X 10.1. */
1019 ATSUClearLayoutControls (text_layout
,
1020 sizeof (tags
) / sizeof (tags
[0]), tags
);
1022 ATSUSetLayoutControls (text_layout
,
1023 sizeof (tags
) / sizeof (tags
[0]),
1024 tags
, sizes
, values
);
1027 #endif /* MAC_OSX */
1030 #endif /* USE_ATSUI */
1032 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1035 if (mac_use_core_graphics
)
1036 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1039 mac_prepare_for_quickdraw (f
);
1041 mac_begin_clip (gc
);
1042 RGBForeColor (GC_FORE_COLOR (gc
));
1046 RGBBackColor (GC_BACK_COLOR (gc
));
1052 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1054 - Screen is double-buffered. (In srcCopy mode, a text is
1055 drawn into an offscreen graphics world first. So
1056 performance gain cannot be expected.)
1057 - It lowers rendering quality.
1058 - Some fonts leave garbage on cursor movement. */
1063 RGBBackColor (GC_BACK_COLOR (gc
));
1064 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1065 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1070 TextFont (GC_FONT (gc
)->mac_fontnum
);
1071 TextSize (GC_FONT (gc
)->mac_fontsize
);
1072 TextFace (GC_FONT (gc
)->mac_fontface
);
1074 DrawText (buf
, 0, nchars
* bytes_per_char
);
1079 DrawText (buf
, 0, nchars
* bytes_per_char
);
1082 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1085 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1086 if (mac_use_core_graphics
)
1087 SwapQDTextFlags(savedFlags
);
1093 /* Mac replacement for XDrawImageString. */
1096 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1101 int nchars
, bg_width
, overstrike_p
;
1103 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
,
1108 /* Mac replacement for XDrawImageString16. */
1111 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1116 int nchars
, bg_width
, overstrike_p
;
1118 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
,
1123 /* Mac replacement for XQueryTextExtents, but takes a character. If
1124 STYLE is NULL, measurement is done by QuickDraw Text routines for
1125 the font of the current graphics port. If CG_GLYPH is not NULL,
1126 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1129 mac_query_char_extents (style
, c
,
1130 font_ascent_return
, font_descent_return
,
1131 overall_return
, cg_glyph
)
1138 int *font_ascent_return
, *font_descent_return
;
1139 XCharStruct
*overall_return
;
1140 #if USE_CG_TEXT_DRAWING
1146 OSStatus err
= noErr
;
1153 ATSUTextLayout text_layout
;
1156 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1159 ATSTrapezoid glyph_bounds
;
1161 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1162 kATSUFromTextBeginning
, kATSUToTextEnd
,
1163 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1164 kATSUseFractionalOrigins
,
1166 kATSUseDeviceOrigins
,
1168 1, &glyph_bounds
, NULL
);
1171 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1172 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1174 width
= Fix2Long (glyph_bounds
.upperRight
.x
1175 - glyph_bounds
.upperLeft
.x
);
1176 if (font_ascent_return
)
1177 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1178 if (font_descent_return
)
1179 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1182 if (err
== noErr
&& overall_return
)
1184 err
= ATSUMeasureTextImage (text_layout
,
1185 kATSUFromTextBeginning
, kATSUToTextEnd
,
1186 0, 0, &char_bounds
);
1188 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1189 #if USE_CG_TEXT_DRAWING
1190 if (err
== noErr
&& cg_glyph
)
1193 ATSUGlyphInfoArray glyph_info_array
;
1194 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1196 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1197 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1199 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1200 kATSUToTextEnd
, &count
,
1203 /* Make sure that we don't have to make layout
1205 && glyph_info_array
.glyphs
[0].deltaY
== 0.0f
1206 && glyph_info_array
.glyphs
[0].idealX
== 0.0f
1207 && glyph_info_array
.glyphs
[0].screenX
== 0)
1209 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1210 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1221 if (font_ascent_return
|| font_descent_return
)
1225 GetFontInfo (&font_info
);
1226 if (font_ascent_return
)
1227 *font_ascent_return
= font_info
.ascent
;
1228 if (font_descent_return
)
1229 *font_descent_return
= font_info
.descent
;
1235 width
= CharWidth (ch
);
1236 QDTextBounds (1, &ch
, &char_bounds
);
1237 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1245 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1248 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1249 XFontStruct
*font_struct
;
1252 XCharStruct
*overall_return
;
1255 short width
= 0, lbearing
= 0, rbearing
= 0;
1258 for (i
= 0; i
< nchars
; i
++)
1260 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1262 width
+= FONT_WIDTH (font_struct
);
1265 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1266 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1267 width
+= pcm
->width
;
1272 overall_return
->lbearing
= lbearing
;
1273 overall_return
->rbearing
= rbearing
;
1274 overall_return
->width
= width
;
1276 /* What's the meaning of the return value of XTextExtents16? */
1280 #if USE_CG_TEXT_DRAWING
1281 static int cg_text_anti_aliasing_threshold
= 8;
1284 init_cg_text_anti_aliasing_threshold ()
1290 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1291 kCFPreferencesCurrentApplication
,
1294 cg_text_anti_aliasing_threshold
= threshold
;
1298 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
, overstrike_p
)
1303 int nchars
, bg_width
, overstrike_p
;
1306 float port_height
, gx
, gy
;
1308 CGContextRef context
;
1312 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1315 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1316 port_height
= FRAME_PIXEL_HEIGHT (f
);
1318 gy
= port_height
- y
;
1319 glyphs
= (CGGlyph
*)buf
;
1320 advances
= alloca (sizeof (CGSize
) * nchars
);
1321 if (advances
== NULL
)
1323 for (i
= 0; i
< nchars
; i
++)
1325 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1327 advances
[i
].width
= pcm
->width
;
1328 advances
[i
].height
= 0;
1329 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1334 context
= mac_begin_cg_clip (f
, gc
);
1336 QDBeginCGContext (port
, &context
);
1337 if (gc
->n_clip_rects
|| bg_width
)
1339 CGContextTranslateCTM (context
, 0, port_height
);
1340 CGContextScaleCTM (context
, 1, -1);
1341 if (gc
->n_clip_rects
)
1342 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1346 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
1349 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1350 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1352 CGContextScaleCTM (context
, 1, -1);
1353 CGContextTranslateCTM (context
, 0, -port_height
);
1357 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
1358 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1359 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1360 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1361 CGContextSetShouldAntialias (context
, false);
1362 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1363 CGContextSetTextPosition (context
, gx
, gy
);
1364 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1367 CGContextSetTextPosition (context
, gx
+ 1.0f
, gy
);
1368 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1371 for (i
= 0; i
< nchars
; i
++)
1373 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1375 CGContextShowGlyphsAtPoint (context
, gx
+ 1.0f
, gy
, glyphs
+ i
, 1);
1376 gx
+= advances
[i
].width
;
1380 mac_end_cg_clip (f
);
1382 CGContextSynchronize (context
);
1383 QDEndCGContext (port
, &context
);
1392 /* Mac replacement for XCopyArea: dest must be window. */
1395 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1400 unsigned int width
, height
;
1405 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1407 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1408 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1410 ForeColor (blackColor
);
1411 BackColor (whiteColor
);
1413 mac_begin_clip (gc
);
1414 LockPixels (GetGWorldPixMap (src
));
1415 #if TARGET_API_MAC_CARBON
1420 LockPortBits (port
);
1421 CopyBits (GetPortBitMapForCopyBits (src
),
1422 GetPortBitMapForCopyBits (port
),
1423 &src_r
, &dest_r
, srcCopy
, 0);
1424 UnlockPortBits (port
);
1426 #else /* not TARGET_API_MAC_CARBON */
1427 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1428 &src_r
, &dest_r
, srcCopy
, 0);
1429 #endif /* not TARGET_API_MAC_CARBON */
1430 UnlockPixels (GetGWorldPixMap (src
));
1433 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1438 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1439 width
, height
, dest_x
, dest_y
)
1444 unsigned int width
, height
;
1449 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1451 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1452 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1454 ForeColor (blackColor
);
1455 BackColor (whiteColor
);
1457 mac_begin_clip (gc
);
1458 LockPixels (GetGWorldPixMap (src
));
1459 LockPixels (GetGWorldPixMap (mask
));
1460 #if TARGET_API_MAC_CARBON
1465 LockPortBits (port
);
1466 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1467 GetPortBitMapForCopyBits (port
),
1468 &src_r
, &src_r
, &dest_r
);
1469 UnlockPortBits (port
);
1471 #else /* not TARGET_API_MAC_CARBON */
1472 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1473 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1474 #endif /* not TARGET_API_MAC_CARBON */
1475 UnlockPixels (GetGWorldPixMap (mask
));
1476 UnlockPixels (GetGWorldPixMap (src
));
1479 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1481 #endif /* !USE_CG_DRAWING */
1484 /* Mac replacement for XCopyArea: used only for scrolling. */
1487 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1491 unsigned int width
, height
;
1494 #if TARGET_API_MAC_CARBON
1496 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1498 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1500 mac_prepare_for_quickdraw (f
);
1502 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1503 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1504 kScrollWindowNoOptions
, dummy
);
1506 #else /* not TARGET_API_MAC_CARBON */
1508 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1512 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1513 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1515 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1516 color mapping in CopyBits. Otherwise, it will be slow. */
1517 ForeColor (blackColor
);
1518 BackColor (whiteColor
);
1519 mac_begin_clip (gc
);
1520 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1523 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1524 #endif /* not TARGET_API_MAC_CARBON */
1528 /* Mac replacement for XChangeGC. */
1531 XChangeGC (display
, gc
, mask
, xgcv
)
1537 if (mask
& GCForeground
)
1538 XSetForeground (display
, gc
, xgcv
->foreground
);
1539 if (mask
& GCBackground
)
1540 XSetBackground (display
, gc
, xgcv
->background
);
1542 XSetFont (display
, gc
, xgcv
->font
);
1546 /* Mac replacement for XCreateGC. */
1549 XCreateGC (display
, window
, mask
, xgcv
)
1555 GC gc
= xmalloc (sizeof (*gc
));
1557 bzero (gc
, sizeof (*gc
));
1558 XChangeGC (display
, gc
, mask
, xgcv
);
1564 /* Used in xfaces.c. */
1567 XFreeGC (display
, gc
)
1571 if (gc
->clip_region
)
1572 DisposeRgn (gc
->clip_region
);
1577 /* Mac replacement for XGetGCValues. */
1580 XGetGCValues (display
, gc
, mask
, xgcv
)
1586 if (mask
& GCForeground
)
1587 xgcv
->foreground
= gc
->xgcv
.foreground
;
1588 if (mask
& GCBackground
)
1589 xgcv
->background
= gc
->xgcv
.background
;
1591 xgcv
->font
= gc
->xgcv
.font
;
1595 /* Mac replacement for XSetForeground. */
1598 XSetForeground (display
, gc
, color
)
1601 unsigned long color
;
1603 if (gc
->xgcv
.foreground
!= color
)
1605 gc
->xgcv
.foreground
= color
;
1606 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1607 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1608 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1613 /* Mac replacement for XSetBackground. */
1616 XSetBackground (display
, gc
, color
)
1619 unsigned long color
;
1621 if (gc
->xgcv
.background
!= color
)
1623 gc
->xgcv
.background
= color
;
1624 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1625 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1626 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1631 /* Mac replacement for XSetFont. */
1634 XSetFont (display
, gc
, font
)
1639 gc
->xgcv
.font
= font
;
1643 /* Mac replacement for XSetClipRectangles. */
1646 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1654 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1656 gc
->n_clip_rects
= n
;
1659 if (gc
->clip_region
== NULL
)
1660 gc
->clip_region
= NewRgn ();
1661 RectRgn (gc
->clip_region
, rectangles
);
1664 RgnHandle region
= NewRgn ();
1666 for (i
= 1; i
< n
; i
++)
1668 RectRgn (region
, rectangles
+ i
);
1669 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1671 DisposeRgn (region
);
1674 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1675 for (i
= 0; i
< n
; i
++)
1677 Rect
*rect
= rectangles
+ i
;
1679 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1680 rect
->right
- rect
->left
,
1681 rect
->bottom
- rect
->top
);
1687 /* Mac replacement for XSetClipMask. */
1690 mac_reset_clip_rectangles (display
, gc
)
1694 gc
->n_clip_rects
= 0;
1698 /* Mac replacement for XSetWindowBackground. */
1701 XSetWindowBackground (display
, w
, color
)
1704 unsigned long color
;
1706 #if !TARGET_API_MAC_CARBON
1707 AuxWinHandle aw_handle
;
1708 CTabHandle ctab_handle
;
1709 ColorSpecPtr ct_table
;
1714 bg_color
.red
= RED16_FROM_ULONG (color
);
1715 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1716 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1718 #if TARGET_API_MAC_CARBON
1719 SetWindowContentColor (w
, &bg_color
);
1721 if (GetAuxWin (w
, &aw_handle
))
1723 ctab_handle
= (*aw_handle
)->awCTable
;
1724 HandToHand ((Handle
*) &ctab_handle
);
1725 ct_table
= (*ctab_handle
)->ctTable
;
1726 ct_size
= (*ctab_handle
)->ctSize
;
1727 while (ct_size
> -1)
1729 if (ct_table
->value
== 0)
1731 ct_table
->rgb
= bg_color
;
1732 CTabChanged (ctab_handle
);
1733 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1741 /* Flush display of frame F, or of all frames if F is null. */
1747 #if TARGET_API_MAC_CARBON
1750 mac_prepare_for_quickdraw (f
);
1753 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1755 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1761 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1762 Calls to XFlush should be unnecessary because the X output buffer
1763 is flushed automatically as needed by calls to XPending,
1764 XNextEvent, or XWindowEvent according to the XFlush man page.
1765 XTread_socket calls XPending. Removing XFlush improves
1768 #define XFlush(DISPLAY) (void) 0
1771 /* Return the struct mac_display_info corresponding to DPY. There's
1774 struct mac_display_info
*
1775 mac_display_info_for_display (dpy
)
1778 return &one_mac_display_info
;
1783 /***********************************************************************
1784 Starting and ending an update
1785 ***********************************************************************/
1787 /* Start an update of frame F. This function is installed as a hook
1788 for update_begin, i.e. it is called when update_begin is called.
1789 This function is called prior to calls to x_update_window_begin for
1790 each window being updated. */
1796 #if TARGET_API_MAC_CARBON
1797 /* During update of a frame, availability of input events is
1798 periodically checked with ReceiveNextEvent if
1799 redisplay-dont-pause is nil. That normally flushes window buffer
1800 changes for every check, and thus screen update looks waving even
1801 if no input is available. So we disable screen updates during
1802 update of a frame. */
1804 DisableScreenUpdates ();
1810 /* Start update of window W. Set the global variable updated_window
1811 to the window being updated and set output_cursor to the cursor
1815 x_update_window_begin (w
)
1818 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1819 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1822 set_output_cursor (&w
->cursor
);
1826 if (f
== display_info
->mouse_face_mouse_frame
)
1828 /* Don't do highlighting for mouse motion during the update. */
1829 display_info
->mouse_face_defer
= 1;
1831 /* If F needs to be redrawn, simply forget about any prior mouse
1833 if (FRAME_GARBAGED_P (f
))
1834 display_info
->mouse_face_window
= Qnil
;
1836 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1837 their mouse_face_p flag set, which means that they are always
1838 unequal to rows in a desired matrix which never have that
1839 flag set. So, rows containing mouse-face glyphs are never
1840 scrolled, and we don't have to switch the mouse highlight off
1841 here to prevent it from being scrolled. */
1843 /* Can we tell that this update does not affect the window
1844 where the mouse highlight is? If so, no need to turn off.
1845 Likewise, don't do anything if the frame is garbaged;
1846 in that case, the frame's current matrix that we would use
1847 is all wrong, and we will redisplay that line anyway. */
1848 if (!NILP (display_info
->mouse_face_window
)
1849 && w
== XWINDOW (display_info
->mouse_face_window
))
1853 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1854 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1857 if (i
< w
->desired_matrix
->nrows
)
1858 clear_mouse_face (display_info
);
1867 /* Draw a vertical window border from (x,y0) to (x,y1) */
1870 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1874 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1877 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1879 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1882 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1885 /* End update of window W (which is equal to updated_window).
1887 Draw vertical borders between horizontally adjacent windows, and
1888 display W's cursor if CURSOR_ON_P is non-zero.
1890 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1891 glyphs in mouse-face were overwritten. In that case we have to
1892 make sure that the mouse-highlight is properly redrawn.
1894 W may be a menu bar pseudo-window in case we don't have X toolkit
1895 support. Such windows don't have a cursor, so don't display it
1899 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1901 int cursor_on_p
, mouse_face_overwritten_p
;
1903 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1905 if (!w
->pseudo_window_p
)
1910 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1912 output_cursor
.x
, output_cursor
.y
);
1914 if (draw_window_fringes (w
, 1))
1915 x_draw_vertical_border (w
);
1920 /* If a row with mouse-face was overwritten, arrange for
1921 XTframe_up_to_date to redisplay the mouse highlight. */
1922 if (mouse_face_overwritten_p
)
1924 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1925 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1926 dpyinfo
->mouse_face_window
= Qnil
;
1929 updated_window
= NULL
;
1933 /* End update of frame F. This function is installed as a hook in
1940 /* Mouse highlight may be displayed again. */
1941 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1944 #if TARGET_API_MAC_CARBON
1945 EnableScreenUpdates ();
1947 XFlush (FRAME_MAC_DISPLAY (f
));
1952 /* This function is called from various places in xdisp.c whenever a
1953 complete update has been performed. The global variable
1954 updated_window is not available here. */
1957 XTframe_up_to_date (f
)
1960 if (FRAME_MAC_P (f
))
1962 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1964 if (dpyinfo
->mouse_face_deferred_gc
1965 || f
== dpyinfo
->mouse_face_mouse_frame
)
1968 if (dpyinfo
->mouse_face_mouse_frame
)
1969 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1970 dpyinfo
->mouse_face_mouse_x
,
1971 dpyinfo
->mouse_face_mouse_y
);
1972 dpyinfo
->mouse_face_deferred_gc
= 0;
1979 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1980 arrow bitmaps, or clear the fringes if no bitmaps are required
1981 before DESIRED_ROW is made current. The window being updated is
1982 found in updated_window. This function is called from
1983 update_window_line only if it is known that there are differences
1984 between bitmaps to be drawn between current row and DESIRED_ROW. */
1987 x_after_update_window_line (desired_row
)
1988 struct glyph_row
*desired_row
;
1990 struct window
*w
= updated_window
;
1996 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1997 desired_row
->redraw_fringe_bitmaps_p
= 1;
1999 /* When a window has disappeared, make sure that no rest of
2000 full-width rows stays visible in the internal border. Could
2001 check here if updated_window is the leftmost/rightmost window,
2002 but I guess it's not worth doing since vertically split windows
2003 are almost never used, internal border is rarely set, and the
2004 overhead is very small. */
2005 if (windows_or_buffers_changed
2006 && desired_row
->full_width_p
2007 && (f
= XFRAME (w
->frame
),
2008 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2010 && (height
= desired_row
->visible_height
,
2013 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2015 /* Internal border is drawn below the tool bar. */
2016 if (WINDOWP (f
->tool_bar_window
)
2017 && w
== XWINDOW (f
->tool_bar_window
))
2021 mac_clear_area (f
, 0, y
, width
, height
);
2022 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2028 /* Draw the bitmap WHICH in one of the left or right fringes of
2029 window W. ROW is the glyph row for which to display the bitmap; it
2030 determines the vertical position at which the bitmap has to be
2034 x_draw_fringe_bitmap (w
, row
, p
)
2036 struct glyph_row
*row
;
2037 struct draw_fringe_bitmap_params
*p
;
2039 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2040 Display
*display
= FRAME_MAC_DISPLAY (f
);
2041 struct face
*face
= p
->face
;
2044 /* Must clip because of partially visible lines. */
2045 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2048 /* Adjust position of "bottom aligned" bitmap on partially
2049 visible last row. */
2051 int oldVH
= row
->visible_height
;
2052 row
->visible_height
= p
->h
;
2053 row
->y
-= rowY
- p
->y
;
2054 x_clip_to_row (w
, row
, -1, face
->gc
);
2056 row
->visible_height
= oldVH
;
2059 x_clip_to_row (w
, row
, -1, face
->gc
);
2061 if (p
->bx
>= 0 && !p
->overlay_p
)
2063 #if 0 /* MAC_TODO: stipple */
2064 /* In case the same realized face is used for fringes and
2065 for something displayed in the text (e.g. face `region' on
2066 mono-displays, the fill style may have been changed to
2067 FillSolid in x_draw_glyph_string_background. */
2069 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2071 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2074 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2076 #if 0 /* MAC_TODO: stipple */
2078 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2084 && p
->which
< max_fringe_bmp
2090 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2091 XSetForeground (display
, face
->gc
,
2093 ? (p
->overlay_p
? face
->background
2094 : f
->output_data
.mac
->cursor_pixel
)
2095 : face
->foreground
));
2097 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2098 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
2100 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2101 p
->wd
, p
->h
, p
->bits
+ p
->dh
, p
->overlay_p
);
2103 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2106 mac_reset_clip_rectangles (display
, face
->gc
);
2111 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2113 unsigned short *bits
;
2117 CGDataProviderRef provider
;
2119 if (which
>= max_fringe_bmp
)
2122 max_fringe_bmp
= which
+ 20;
2123 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2124 while (i
< max_fringe_bmp
)
2125 fringe_bmp
[i
++] = 0;
2128 for (i
= 0; i
< h
; i
++)
2130 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2131 sizeof (unsigned short) * h
, NULL
);
2134 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2135 sizeof (unsigned short),
2137 CGDataProviderRelease (provider
);
2142 mac_destroy_fringe_bitmap (which
)
2145 if (which
>= max_fringe_bmp
)
2148 if (fringe_bmp
[which
])
2149 CGImageRelease (fringe_bmp
[which
]);
2150 fringe_bmp
[which
] = 0;
2155 /* This is called when starting Emacs and when restarting after
2156 suspend. When starting Emacs, no window is mapped. And nothing
2157 must be done to Emacs's own window if it is suspended (though that
2161 XTset_terminal_modes ()
2165 /* This is called when exiting or suspending Emacs. Exiting will make
2166 the windows go away, and suspending requires no action. */
2169 XTreset_terminal_modes ()
2175 /***********************************************************************
2177 ***********************************************************************/
2179 /* Function prototypes of this page. */
2181 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2182 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2186 pcm_init (pcm
, count
)
2190 bzero (pcm
, sizeof (XCharStruct
) * count
);
2191 while (--count
>= 0)
2193 pcm
->descent
= PCM_INVALID
;
2198 static enum pcm_status
2199 pcm_get_status (pcm
)
2200 const XCharStruct
*pcm
;
2202 int height
= pcm
->ascent
+ pcm
->descent
;
2204 /* Negative height means some special status. */
2205 return height
>= 0 ? PCM_VALID
: height
;
2208 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2209 is not contained in the font. */
2211 static INLINE XCharStruct
*
2212 x_per_char_metric (font
, char2b
)
2216 /* The result metric information. */
2217 XCharStruct
*pcm
= NULL
;
2219 xassert (font
&& char2b
);
2222 if (font
->mac_style
)
2224 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2228 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2229 pcm_init (*row
, 0x100);
2231 pcm
= *row
+ char2b
->byte2
;
2232 if (pcm_get_status (pcm
) != PCM_VALID
)
2235 mac_query_char_extents (font
->mac_style
,
2236 (char2b
->byte1
<< 8) + char2b
->byte2
,
2237 NULL
, NULL
, pcm
, NULL
);
2244 if (font
->bounds
.per_char
!= NULL
)
2246 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2248 /* min_char_or_byte2 specifies the linear character index
2249 corresponding to the first element of the per_char array,
2250 max_char_or_byte2 is the index of the last character. A
2251 character with non-zero CHAR2B->byte1 is not in the font.
2252 A character with byte2 less than min_char_or_byte2 or
2253 greater max_char_or_byte2 is not in the font. */
2254 if (char2b
->byte1
== 0
2255 && char2b
->byte2
>= font
->min_char_or_byte2
2256 && char2b
->byte2
<= font
->max_char_or_byte2
)
2257 pcm
= font
->bounds
.per_char
2258 + (char2b
->byte2
- font
->min_char_or_byte2
);
2262 /* If either min_byte1 or max_byte1 are nonzero, both
2263 min_char_or_byte2 and max_char_or_byte2 are less than
2264 256, and the 2-byte character index values corresponding
2265 to the per_char array element N (counting from 0) are:
2267 byte1 = N/D + min_byte1
2268 byte2 = N\D + min_char_or_byte2
2272 D = max_char_or_byte2 - min_char_or_byte2 + 1
2273 / = integer division
2274 \ = integer modulus */
2275 if (char2b
->byte1
>= font
->min_byte1
2276 && char2b
->byte1
<= font
->max_byte1
2277 && char2b
->byte2
>= font
->min_char_or_byte2
2278 && char2b
->byte2
<= font
->max_char_or_byte2
)
2280 pcm
= (font
->bounds
.per_char
2281 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2282 * (char2b
->byte1
- font
->min_byte1
))
2283 + (char2b
->byte2
- font
->min_char_or_byte2
));
2289 /* If the per_char pointer is null, all glyphs between the first
2290 and last character indexes inclusive have the same
2291 information, as given by both min_bounds and max_bounds. */
2292 if (char2b
->byte2
>= font
->min_char_or_byte2
2293 && char2b
->byte2
<= font
->max_char_or_byte2
)
2294 pcm
= &font
->max_bounds
;
2300 return ((pcm
== NULL
2302 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2303 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2312 static XCharStruct
*
2313 mac_per_char_metric (font
, char2b
, font_type
)
2318 return x_per_char_metric (font
, char2b
);
2322 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2323 the two-byte form of C. Encoding is returned in *CHAR2B. */
2326 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2329 struct font_info
*font_info
;
2332 int charset
= CHAR_CHARSET (c
);
2333 XFontStruct
*font
= font_info
->font
;
2335 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2336 This may be either a program in a special encoder language or a
2338 if (font_info
->font_encoder
)
2340 /* It's a program. */
2341 struct ccl_program
*ccl
= font_info
->font_encoder
;
2343 check_ccl_update (ccl
);
2344 if (CHARSET_DIMENSION (charset
) == 1)
2346 ccl
->reg
[0] = charset
;
2347 ccl
->reg
[1] = char2b
->byte2
;
2352 ccl
->reg
[0] = charset
;
2353 ccl
->reg
[1] = char2b
->byte1
;
2354 ccl
->reg
[2] = char2b
->byte2
;
2357 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2359 /* We assume that MSBs are appropriately set/reset by CCL
2361 if (font
->max_byte1
== 0) /* 1-byte font */
2362 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2364 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2366 else if (font_info
->encoding
[charset
])
2368 /* Fixed encoding scheme. See fontset.h for the meaning of the
2369 encoding numbers. */
2370 int enc
= font_info
->encoding
[charset
];
2372 if ((enc
== 1 || enc
== 2)
2373 && CHARSET_DIMENSION (charset
) == 2)
2374 char2b
->byte1
|= 0x80;
2376 if (enc
== 1 || enc
== 3)
2377 char2b
->byte2
|= 0x80;
2383 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2384 char2b
->byte1
= sjis1
;
2385 char2b
->byte2
= sjis2
;
2390 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2392 return FONT_TYPE_UNKNOWN
;
2397 /***********************************************************************
2399 ***********************************************************************/
2403 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2404 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2405 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2407 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2408 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2409 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2410 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2411 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2412 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2413 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2414 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2415 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2416 unsigned long *, double, int));*/
2417 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2418 double, int, unsigned long));
2419 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2420 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2421 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2422 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2423 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2425 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2426 int, int, int, int, int, int,
2428 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2429 int, int, int, Rect
*));
2432 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2436 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2441 struct glyph_string
*s
;
2443 if (s
->font
== FRAME_FONT (s
->f
)
2444 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2445 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2447 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2450 /* Cursor on non-default face: must merge. */
2454 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2455 xgcv
.foreground
= s
->face
->background
;
2457 /* If the glyph would be invisible, try a different foreground. */
2458 if (xgcv
.foreground
== xgcv
.background
)
2459 xgcv
.foreground
= s
->face
->foreground
;
2460 if (xgcv
.foreground
== xgcv
.background
)
2461 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2462 if (xgcv
.foreground
== xgcv
.background
)
2463 xgcv
.foreground
= s
->face
->foreground
;
2465 /* Make sure the cursor is distinct from text in this face. */
2466 if (xgcv
.background
== s
->face
->background
2467 && xgcv
.foreground
== s
->face
->foreground
)
2469 xgcv
.background
= s
->face
->foreground
;
2470 xgcv
.foreground
= s
->face
->background
;
2473 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2474 xgcv
.font
= s
->font
;
2475 mask
= GCForeground
| GCBackground
| GCFont
;
2477 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2478 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2481 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2482 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2484 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2489 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2492 x_set_mouse_face_gc (s
)
2493 struct glyph_string
*s
;
2498 /* What face has to be used last for the mouse face? */
2499 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2500 face
= FACE_FROM_ID (s
->f
, face_id
);
2502 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2504 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2505 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2507 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2508 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2509 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2511 /* If font in this face is same as S->font, use it. */
2512 if (s
->font
== s
->face
->font
)
2513 s
->gc
= s
->face
->gc
;
2516 /* Otherwise construct scratch_cursor_gc with values from FACE
2521 xgcv
.background
= s
->face
->background
;
2522 xgcv
.foreground
= s
->face
->foreground
;
2523 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2524 xgcv
.font
= s
->font
;
2525 mask
= GCForeground
| GCBackground
| GCFont
;
2527 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2528 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2531 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2532 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2534 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2537 xassert (s
->gc
!= 0);
2541 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2542 Faces to use in the mode line have already been computed when the
2543 matrix was built, so there isn't much to do, here. */
2546 x_set_mode_line_face_gc (s
)
2547 struct glyph_string
*s
;
2549 s
->gc
= s
->face
->gc
;
2553 /* Set S->gc of glyph string S for drawing that glyph string. Set
2554 S->stippled_p to a non-zero value if the face of S has a stipple
2558 x_set_glyph_string_gc (s
)
2559 struct glyph_string
*s
;
2561 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2563 if (s
->hl
== DRAW_NORMAL_TEXT
)
2565 s
->gc
= s
->face
->gc
;
2566 s
->stippled_p
= s
->face
->stipple
!= 0;
2568 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2570 x_set_mode_line_face_gc (s
);
2571 s
->stippled_p
= s
->face
->stipple
!= 0;
2573 else if (s
->hl
== DRAW_CURSOR
)
2575 x_set_cursor_gc (s
);
2578 else if (s
->hl
== DRAW_MOUSE_FACE
)
2580 x_set_mouse_face_gc (s
);
2581 s
->stippled_p
= s
->face
->stipple
!= 0;
2583 else if (s
->hl
== DRAW_IMAGE_RAISED
2584 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2586 s
->gc
= s
->face
->gc
;
2587 s
->stippled_p
= s
->face
->stipple
!= 0;
2591 s
->gc
= s
->face
->gc
;
2592 s
->stippled_p
= s
->face
->stipple
!= 0;
2595 /* GC must have been set. */
2596 xassert (s
->gc
!= 0);
2600 /* Set clipping for output of glyph string S. S may be part of a mode
2601 line or menu if we don't have X toolkit support. */
2604 x_set_glyph_string_clipping (s
)
2605 struct glyph_string
*s
;
2607 Rect rects
[MAX_CLIP_RECTS
];
2610 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2611 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2616 Compute left and right overhang of glyph string S. If S is a glyph
2617 string for a composition, assume overhangs don't exist. */
2620 mac_compute_glyph_string_overhangs (s
)
2621 struct glyph_string
*s
;
2623 if (!(s
->cmp
== NULL
2624 && s
->first_glyph
->type
== CHAR_GLYPH
))
2629 || s
->font
->mac_style
2635 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2636 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2637 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2642 MacFontStruct
*font
= s
->font
;
2645 mac_prepare_for_quickdraw (s
->f
);
2647 SetPortWindowPort (FRAME_MAC_WINDOW (s
->f
));
2649 TextFont (font
->mac_fontnum
);
2650 TextSize (font
->mac_fontsize
);
2651 TextFace (font
->mac_fontface
);
2653 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2655 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2656 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2661 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2664 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2665 struct glyph_string
*s
;
2668 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2672 /* Draw the background of glyph_string S. If S->background_filled_p
2673 is non-zero don't draw it. FORCE_P non-zero means draw the
2674 background even if it wouldn't be drawn normally. This is used
2675 when a string preceding S draws into the background of S, or S
2676 contains the first component of a composition. */
2679 x_draw_glyph_string_background (s
, force_p
)
2680 struct glyph_string
*s
;
2683 /* Nothing to do if background has already been drawn or if it
2684 shouldn't be drawn in the first place. */
2685 if (!s
->background_filled_p
)
2687 int box_line_width
= max (s
->face
->box_line_width
, 0);
2689 #if 0 /* MAC_TODO: stipple */
2692 /* Fill background with a stipple pattern. */
2693 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2694 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2695 s
->y
+ box_line_width
,
2696 s
->background_width
,
2697 s
->height
- 2 * box_line_width
);
2698 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2699 s
->background_filled_p
= 1;
2703 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2704 || s
->font_not_found_p
2705 || s
->extends_to_end_of_line_p
2708 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2709 s
->background_width
,
2710 s
->height
- 2 * box_line_width
);
2711 s
->background_filled_p
= 1;
2717 /* Draw the foreground of glyph string S. */
2720 x_draw_glyph_string_foreground (s
)
2721 struct glyph_string
*s
;
2725 /* If first glyph of S has a left box line, start drawing the text
2726 of S to the right of that box line. */
2727 if (s
->face
->box
!= FACE_NO_BOX
2728 && s
->first_glyph
->left_box_line_p
)
2729 x
= s
->x
+ abs (s
->face
->box_line_width
);
2733 /* Draw characters of S as rectangles if S's font could not be
2735 if (s
->font_not_found_p
)
2737 for (i
= 0; i
< s
->nchars
; ++i
)
2739 struct glyph
*g
= s
->first_glyph
+ i
;
2740 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2741 g
->pixel_width
- 1, s
->height
- 1);
2742 x
+= g
->pixel_width
;
2747 char *char1b
= (char *) s
->char2b
;
2748 int boff
= s
->font_info
->baseline_offset
;
2750 if (s
->font_info
->vertical_centering
)
2751 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2753 /* If we can use 8-bit functions, condense S->char2b. */
2756 && GC_FONT (s
->gc
)->mac_style
== NULL
2759 for (i
= 0; i
< s
->nchars
; ++i
)
2760 char1b
[i
] = s
->char2b
[i
].byte2
;
2762 /* Draw text with XDrawString if background has already been
2763 filled. Otherwise, use XDrawImageString. (Note that
2764 XDrawImageString is usually faster than XDrawString.) Always
2765 use XDrawImageString when drawing the cursor so that there is
2766 no chance that characters under a box cursor are invisible. */
2768 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2769 bg_width
= 0; /* Corresponds to XDrawString. */
2771 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2775 || GC_FONT (s
->gc
)->mac_style
2778 #if USE_CG_TEXT_DRAWING
2780 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2781 s
->char2b
, s
->nchars
, bg_width
,
2782 s
->face
->overstrike
))
2786 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2787 s
->char2b
, s
->nchars
, bg_width
,
2788 s
->face
->overstrike
);
2790 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2791 char1b
, s
->nchars
, bg_width
,
2792 s
->face
->overstrike
);
2796 /* Draw the foreground of composite glyph string S. */
2799 x_draw_composite_glyph_string_foreground (s
)
2800 struct glyph_string
*s
;
2804 /* If first glyph of S has a left box line, start drawing the text
2805 of S to the right of that box line. */
2806 if (s
->face
->box
!= FACE_NO_BOX
2807 && s
->first_glyph
->left_box_line_p
)
2808 x
= s
->x
+ abs (s
->face
->box_line_width
);
2812 /* S is a glyph string for a composition. S->gidx is the index of
2813 the first character drawn for glyphs of this composition.
2814 S->gidx == 0 means we are drawing the very first character of
2815 this composition. */
2817 /* Draw a rectangle for the composition if the font for the very
2818 first character of the composition could not be loaded. */
2819 if (s
->font_not_found_p
)
2822 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2823 s
->width
- 1, s
->height
- 1);
2827 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2828 mac_draw_image_string_16 (s
->f
, s
->gc
,
2829 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2830 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2831 s
->char2b
+ i
, 1, 0, s
->face
->overstrike
);
2836 #ifdef USE_X_TOOLKIT
2838 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2841 /* Return the frame on which widget WIDGET is used.. Abort if frame
2842 cannot be determined. */
2844 static struct frame
*
2845 x_frame_of_widget (widget
)
2848 struct x_display_info
*dpyinfo
;
2852 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2854 /* Find the top-level shell of the widget. Note that this function
2855 can be called when the widget is not yet realized, so XtWindow
2856 (widget) == 0. That's the reason we can't simply use
2857 x_any_window_to_frame. */
2858 while (!XtIsTopLevelShell (widget
))
2859 widget
= XtParent (widget
);
2861 /* Look for a frame with that top-level widget. Allocate the color
2862 on that frame to get the right gamma correction value. */
2863 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2864 if (GC_FRAMEP (XCAR (tail
))
2865 && (f
= XFRAME (XCAR (tail
)),
2866 (f
->output_data
.nothing
!= 1
2867 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2868 && f
->output_data
.x
->widget
== widget
)
2875 /* Allocate the color COLOR->pixel on the screen and display of
2876 widget WIDGET in colormap CMAP. If an exact match cannot be
2877 allocated, try the nearest color available. Value is non-zero
2878 if successful. This is called from lwlib. */
2881 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2886 struct frame
*f
= x_frame_of_widget (widget
);
2887 return x_alloc_nearest_color (f
, cmap
, color
);
2891 #endif /* USE_X_TOOLKIT */
2893 #if 0 /* MAC_TODO */
2895 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2896 CMAP. If an exact match can't be allocated, try the nearest color
2897 available. Value is non-zero if successful. Set *COLOR to the
2901 x_alloc_nearest_color (f
, cmap
, color
)
2906 Display
*display
= FRAME_X_DISPLAY (f
);
2907 Screen
*screen
= FRAME_X_SCREEN (f
);
2910 gamma_correct (f
, color
);
2911 rc
= XAllocColor (display
, cmap
, color
);
2914 /* If we got to this point, the colormap is full, so we're going
2915 to try to get the next closest color. The algorithm used is
2916 a least-squares matching, which is what X uses for closest
2917 color matching with StaticColor visuals. */
2919 unsigned long nearest_delta
= ~0;
2920 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2921 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2923 for (i
= 0; i
< ncells
; ++i
)
2925 XQueryColors (display
, cmap
, cells
, ncells
);
2927 for (nearest
= i
= 0; i
< ncells
; ++i
)
2929 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2930 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2931 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2932 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2934 if (delta
< nearest_delta
)
2937 nearest_delta
= delta
;
2941 color
->red
= cells
[nearest
].red
;
2942 color
->green
= cells
[nearest
].green
;
2943 color
->blue
= cells
[nearest
].blue
;
2944 rc
= XAllocColor (display
, cmap
, color
);
2947 #ifdef DEBUG_X_COLORS
2949 register_color (color
->pixel
);
2950 #endif /* DEBUG_X_COLORS */
2956 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2957 It's necessary to do this instead of just using PIXEL directly to
2958 get color reference counts right. */
2961 x_copy_color (f
, pixel
)
2963 unsigned long pixel
;
2967 color
.pixel
= pixel
;
2969 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2970 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2972 #ifdef DEBUG_X_COLORS
2973 register_color (pixel
);
2979 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2980 It's necessary to do this instead of just using PIXEL directly to
2981 get color reference counts right. */
2984 x_copy_dpy_color (dpy
, cmap
, pixel
)
2987 unsigned long pixel
;
2991 color
.pixel
= pixel
;
2993 XQueryColor (dpy
, cmap
, &color
);
2994 XAllocColor (dpy
, cmap
, &color
);
2996 #ifdef DEBUG_X_COLORS
2997 register_color (pixel
);
3002 #endif /* MAC_TODO */
3005 /* Brightness beyond which a color won't have its highlight brightness
3008 Nominally, highlight colors for `3d' faces are calculated by
3009 brightening an object's color by a constant scale factor, but this
3010 doesn't yield good results for dark colors, so for colors who's
3011 brightness is less than this value (on a scale of 0-255) have to
3012 use an additional additive factor.
3014 The value here is set so that the default menu-bar/mode-line color
3015 (grey75) will not have its highlights changed at all. */
3016 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3019 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3020 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3021 If this produces the same color as COLOR, try a color where all RGB
3022 values have DELTA added. Return the allocated color in *COLOR.
3023 DISPLAY is the X display, CMAP is the colormap to operate on.
3024 Value is non-zero if successful. */
3027 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3029 unsigned long *color
;
3036 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3039 /* Change RGB values by specified FACTOR. Avoid overflow! */
3040 xassert (factor
>= 0);
3041 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3042 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3043 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3045 /* Calculate brightness of COLOR. */
3046 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3047 + BLUE_FROM_ULONG (*color
)) / 6;
3049 /* We only boost colors that are darker than
3050 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3051 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3052 /* Make an additive adjustment to NEW, because it's dark enough so
3053 that scaling by FACTOR alone isn't enough. */
3055 /* How far below the limit this color is (0 - 1, 1 being darker). */
3056 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3057 /* The additive adjustment. */
3058 int min_delta
= delta
* dimness
* factor
/ 2;
3061 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3062 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3063 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3065 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3066 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3067 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3071 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3072 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3073 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3075 /* MAC_TODO: Map to palette and retry with delta if same? */
3076 /* MAC_TODO: Free colors (if using palette)? */
3087 /* Set up the foreground color for drawing relief lines of glyph
3088 string S. RELIEF is a pointer to a struct relief containing the GC
3089 with which lines will be drawn. Use a color that is FACTOR or
3090 DELTA lighter or darker than the relief's background which is found
3091 in S->f->output_data.x->relief_background. If such a color cannot
3092 be allocated, use DEFAULT_PIXEL, instead. */
3095 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3097 struct relief
*relief
;
3100 unsigned long default_pixel
;
3103 struct mac_output
*di
= f
->output_data
.mac
;
3104 unsigned long mask
= GCForeground
;
3105 unsigned long pixel
;
3106 unsigned long background
= di
->relief_background
;
3107 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3109 /* MAC_TODO: Free colors (if using palette)? */
3111 /* Allocate new color. */
3112 xgcv
.foreground
= default_pixel
;
3114 if (dpyinfo
->n_planes
!= 1
3115 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3117 relief
->allocated_p
= 1;
3118 xgcv
.foreground
= relief
->pixel
= pixel
;
3121 if (relief
->gc
== 0)
3123 #if 0 /* MAC_TODO: stipple */
3124 xgcv
.stipple
= dpyinfo
->gray
;
3127 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3130 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3134 /* Set up colors for the relief lines around glyph string S. */
3137 x_setup_relief_colors (s
)
3138 struct glyph_string
*s
;
3140 struct mac_output
*di
= s
->f
->output_data
.mac
;
3141 unsigned long color
;
3143 if (s
->face
->use_box_color_for_shadows_p
)
3144 color
= s
->face
->box_color
;
3145 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3147 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3148 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3153 /* Get the background color of the face. */
3154 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3155 color
= xgcv
.background
;
3158 if (di
->white_relief
.gc
== 0
3159 || color
!= di
->relief_background
)
3161 di
->relief_background
= color
;
3162 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3163 WHITE_PIX_DEFAULT (s
->f
));
3164 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3165 BLACK_PIX_DEFAULT (s
->f
));
3170 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3171 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3172 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3173 relief. LEFT_P non-zero means draw a relief on the left side of
3174 the rectangle. RIGHT_P non-zero means draw a relief on the right
3175 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3179 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3180 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3182 int left_x
, top_y
, right_x
, bottom_y
, width
;
3183 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3186 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3191 gc
= f
->output_data
.mac
->white_relief
.gc
;
3193 gc
= f
->output_data
.mac
->black_relief
.gc
;
3194 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3198 for (i
= 0; i
< width
; ++i
)
3199 mac_draw_line (f
, gc
,
3200 left_x
+ i
* left_p
, top_y
+ i
,
3201 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3205 for (i
= 0; i
< width
; ++i
)
3206 mac_draw_line (f
, gc
,
3207 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3209 mac_reset_clip_rectangles (dpy
, gc
);
3211 gc
= f
->output_data
.mac
->black_relief
.gc
;
3213 gc
= f
->output_data
.mac
->white_relief
.gc
;
3214 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3218 for (i
= 0; i
< width
; ++i
)
3219 mac_draw_line (f
, gc
,
3220 left_x
+ i
* left_p
, bottom_y
- i
,
3221 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3225 for (i
= 0; i
< width
; ++i
)
3226 mac_draw_line (f
, gc
,
3227 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3229 mac_reset_clip_rectangles (dpy
, gc
);
3233 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3234 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3235 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3236 left side of the rectangle. RIGHT_P non-zero means draw a line
3237 on the right side of the rectangle. CLIP_RECT is the clipping
3238 rectangle to use when drawing. */
3241 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3242 left_p
, right_p
, clip_rect
)
3243 struct glyph_string
*s
;
3244 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3249 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3250 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3251 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3254 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3255 right_x
- left_x
+ 1, width
);
3259 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3260 width
, bottom_y
- top_y
+ 1);
3263 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3264 right_x
- left_x
+ 1, width
);
3268 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3269 top_y
, width
, bottom_y
- top_y
+ 1);
3271 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3272 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3276 /* Draw a box around glyph string S. */
3279 x_draw_glyph_string_box (s
)
3280 struct glyph_string
*s
;
3282 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3283 int left_p
, right_p
;
3284 struct glyph
*last_glyph
;
3287 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3288 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3289 : window_box_right (s
->w
, s
->area
));
3291 /* The glyph that may have a right box line. */
3292 last_glyph
= (s
->cmp
|| s
->img
3294 : s
->first_glyph
+ s
->nchars
- 1);
3296 width
= abs (s
->face
->box_line_width
);
3297 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3299 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3301 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3303 bottom_y
= top_y
+ s
->height
- 1;
3305 left_p
= (s
->first_glyph
->left_box_line_p
3306 || (s
->hl
== DRAW_MOUSE_FACE
3308 || s
->prev
->hl
!= s
->hl
)));
3309 right_p
= (last_glyph
->right_box_line_p
3310 || (s
->hl
== DRAW_MOUSE_FACE
3312 || s
->next
->hl
!= s
->hl
)));
3314 get_glyph_string_clip_rect (s
, &clip_rect
);
3316 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3317 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3318 left_p
, right_p
, &clip_rect
);
3321 x_setup_relief_colors (s
);
3322 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3323 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3328 /* Draw foreground of image glyph string S. */
3331 x_draw_image_foreground (s
)
3332 struct glyph_string
*s
;
3335 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3337 /* If first glyph of S has a left box line, start drawing it to the
3338 right of that line. */
3339 if (s
->face
->box
!= FACE_NO_BOX
3340 && s
->first_glyph
->left_box_line_p
3342 x
+= abs (s
->face
->box_line_width
);
3344 /* If there is a margin around the image, adjust x- and y-position
3346 if (s
->slice
.x
== 0)
3347 x
+= s
->img
->hmargin
;
3348 if (s
->slice
.y
== 0)
3349 y
+= s
->img
->vmargin
;
3353 x_set_glyph_string_clipping (s
);
3356 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3357 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3358 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3362 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3363 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3364 s
->slice
.width
, s
->slice
.height
, x
, y
);
3371 mac_copy_area (s
->img
->pixmap
,
3372 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3373 s
->slice
.width
, s
->slice
.height
, x
, y
);
3376 /* When the image has a mask, we can expect that at
3377 least part of a mouse highlight or a block cursor will
3378 be visible. If the image doesn't have a mask, make
3379 a block cursor visible by drawing a rectangle around
3380 the image. I believe it's looking better if we do
3381 nothing here for mouse-face. */
3382 if (s
->hl
== DRAW_CURSOR
)
3384 int r
= s
->img
->relief
;
3386 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3387 s
->slice
.width
+ r
*2 - 1,
3388 s
->slice
.height
+ r
*2 - 1);
3393 /* Draw a rectangle if image could not be loaded. */
3394 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3395 s
->slice
.width
- 1, s
->slice
.height
- 1);
3399 /* Draw a relief around the image glyph string S. */
3402 x_draw_image_relief (s
)
3403 struct glyph_string
*s
;
3405 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3408 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3410 /* If first glyph of S has a left box line, start drawing it to the
3411 right of that line. */
3412 if (s
->face
->box
!= FACE_NO_BOX
3413 && s
->first_glyph
->left_box_line_p
3415 x
+= abs (s
->face
->box_line_width
);
3417 /* If there is a margin around the image, adjust x- and y-position
3419 if (s
->slice
.x
== 0)
3420 x
+= s
->img
->hmargin
;
3421 if (s
->slice
.y
== 0)
3422 y
+= s
->img
->vmargin
;
3424 if (s
->hl
== DRAW_IMAGE_SUNKEN
3425 || s
->hl
== DRAW_IMAGE_RAISED
)
3427 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3428 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3432 thick
= abs (s
->img
->relief
);
3433 raised_p
= s
->img
->relief
> 0;
3438 x1
= x
+ s
->slice
.width
+ thick
- 1;
3439 y1
= y
+ s
->slice
.height
+ thick
- 1;
3441 x_setup_relief_colors (s
);
3442 get_glyph_string_clip_rect (s
, &r
);
3443 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3445 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3447 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3452 /* Draw part of the background of glyph string S. X, Y, W, and H
3453 give the rectangle to draw. */
3456 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3457 struct glyph_string
*s
;
3460 #if 0 /* MAC_TODO: stipple */
3463 /* Fill background with a stipple pattern. */
3464 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3465 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3466 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3469 #endif /* MAC_TODO */
3470 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3474 /* Draw image glyph string S.
3477 s->x +-------------------------
3480 | +-------------------------
3483 | | +-------------------
3489 x_draw_image_glyph_string (s
)
3490 struct glyph_string
*s
;
3493 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3494 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3497 height
= s
->height
- 2 * box_line_vwidth
;
3500 /* Fill background with face under the image. Do it only if row is
3501 taller than image or if image has a clip mask to reduce
3503 s
->stippled_p
= s
->face
->stipple
!= 0;
3504 if (height
> s
->slice
.height
3508 || s
->img
->pixmap
== 0
3509 || s
->width
!= s
->background_width
)
3512 if (s
->first_glyph
->left_box_line_p
3514 x
+= box_line_hwidth
;
3517 if (s
->slice
.y
== 0)
3518 y
+= box_line_vwidth
;
3520 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3522 s
->background_filled_p
= 1;
3525 /* Draw the foreground. */
3526 x_draw_image_foreground (s
);
3528 /* If we must draw a relief around the image, do it. */
3530 || s
->hl
== DRAW_IMAGE_RAISED
3531 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3532 x_draw_image_relief (s
);
3536 /* Draw stretch glyph string S. */
3539 x_draw_stretch_glyph_string (s
)
3540 struct glyph_string
*s
;
3542 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3543 s
->stippled_p
= s
->face
->stipple
!= 0;
3545 if (s
->hl
== DRAW_CURSOR
3546 && !x_stretch_cursor_p
)
3548 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3549 as wide as the stretch glyph. */
3550 int width
, background_width
= s
->background_width
;
3551 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3555 background_width
-= left_x
- x
;
3558 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3561 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3563 /* Clear rest using the GC of the original non-cursor face. */
3564 if (width
< background_width
)
3567 int w
= background_width
- width
, h
= s
->height
;
3572 if (s
->row
->mouse_face_p
3573 && cursor_in_mouse_face_p (s
->w
))
3575 x_set_mouse_face_gc (s
);
3581 get_glyph_string_clip_rect (s
, &r
);
3582 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3584 #if 0 /* MAC_TODO: stipple */
3585 if (s
->face
->stipple
)
3587 /* Fill background with a stipple pattern. */
3588 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3589 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3590 XSetFillStyle (s
->display
, gc
, FillSolid
);
3593 #endif /* MAC_TODO */
3594 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3597 else if (!s
->background_filled_p
)
3599 int background_width
= s
->background_width
;
3600 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3602 /* Don't draw into left margin, fringe or scrollbar area
3603 except for header line and mode line. */
3604 if (x
< left_x
&& !s
->row
->mode_line_p
)
3606 background_width
-= left_x
- x
;
3609 if (background_width
> 0)
3610 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3613 s
->background_filled_p
= 1;
3617 /* Draw glyph string S. */
3620 x_draw_glyph_string (s
)
3621 struct glyph_string
*s
;
3623 int relief_drawn_p
= 0;
3625 /* If S draws into the background of its successor that does not
3626 draw a cursor, draw the background of the successor first so that
3627 S can draw into it. This makes S->next use XDrawString instead
3628 of XDrawImageString. */
3629 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3630 && s
->next
->hl
!= DRAW_CURSOR
)
3632 xassert (s
->next
->img
== NULL
);
3633 x_set_glyph_string_gc (s
->next
);
3634 x_set_glyph_string_clipping (s
->next
);
3635 x_draw_glyph_string_background (s
->next
, 1);
3638 /* Set up S->gc, set clipping and draw S. */
3639 x_set_glyph_string_gc (s
);
3641 /* Draw relief (if any) in advance for char/composition so that the
3642 glyph string can be drawn over it. */
3643 if (!s
->for_overlaps
3644 && s
->face
->box
!= FACE_NO_BOX
3645 && (s
->first_glyph
->type
== CHAR_GLYPH
3646 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3649 x_set_glyph_string_clipping (s
);
3650 x_draw_glyph_string_background (s
, 1);
3651 x_draw_glyph_string_box (s
);
3652 x_set_glyph_string_clipping (s
);
3656 x_set_glyph_string_clipping (s
);
3658 switch (s
->first_glyph
->type
)
3661 x_draw_image_glyph_string (s
);
3665 x_draw_stretch_glyph_string (s
);
3669 if (s
->for_overlaps
)
3670 s
->background_filled_p
= 1;
3672 x_draw_glyph_string_background (s
, 0);
3673 x_draw_glyph_string_foreground (s
);
3676 case COMPOSITE_GLYPH
:
3677 if (s
->for_overlaps
|| s
->gidx
> 0)
3678 s
->background_filled_p
= 1;
3680 x_draw_glyph_string_background (s
, 1);
3681 x_draw_composite_glyph_string_foreground (s
);
3688 if (!s
->for_overlaps
)
3690 /* Draw underline. */
3691 if (s
->face
->underline_p
)
3693 unsigned long tem
, h
;
3697 /* Get the underline thickness. Default is 1 pixel. */
3698 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3702 y
= s
->y
+ s
->height
- h
;
3703 if (!x_underline_at_descent_line
)
3705 /* Get the underline position. This is the recommended
3706 vertical offset in pixels from the baseline to the top of
3707 the underline. This is a signed value according to the
3708 specs, and its default is
3710 ROUND ((maximum descent) / 2), with
3711 ROUND(x) = floor (x + 0.5) */
3714 if (x_use_underline_position_properties
3715 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3716 y
= s
->ybase
+ (long) tem
;
3720 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3723 if (s
->face
->underline_defaulted_p
)
3724 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3725 s
->background_width
, h
);
3729 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3730 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3731 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3732 s
->background_width
, h
);
3733 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3737 /* Draw overline. */
3738 if (s
->face
->overline_p
)
3740 unsigned long dy
= 0, h
= 1;
3742 if (s
->face
->overline_color_defaulted_p
)
3743 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3744 s
->background_width
, h
);
3748 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3749 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3750 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3751 s
->background_width
, h
);
3752 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3756 /* Draw strike-through. */
3757 if (s
->face
->strike_through_p
)
3759 unsigned long h
= 1;
3760 unsigned long dy
= (s
->height
- h
) / 2;
3762 if (s
->face
->strike_through_color_defaulted_p
)
3763 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3768 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3769 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3770 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3772 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3776 /* Draw relief if not yet drawn. */
3777 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3778 x_draw_glyph_string_box (s
);
3781 /* Reset clipping. */
3782 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3785 /* Shift display to make room for inserted glyphs. */
3788 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3790 int x
, y
, width
, height
, shift_by
;
3792 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3793 x
, y
, width
, height
,
3797 /* Delete N glyphs at the nominal cursor position. Not implemented
3808 /* Clear entire frame. If updating_frame is non-null, clear that
3809 frame. Otherwise clear the selected frame. */
3819 f
= SELECTED_FRAME ();
3821 /* Clearing the frame will erase any cursor, so mark them all as no
3823 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3824 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3825 output_cursor
.x
= -1;
3827 /* We don't set the output cursor here because there will always
3828 follow an explicit cursor_to. */
3830 mac_clear_window (f
);
3832 /* We have to clear the scroll bars, too. If we have changed
3833 colors or something like that, then they should be notified. */
3834 x_scroll_bar_clear (f
);
3836 XFlush (FRAME_MAC_DISPLAY (f
));
3842 /* Invert the middle quarter of the frame for .15 sec. */
3844 /* We use the select system call to do the waiting, so we have to make
3845 sure it's available. If it isn't, we just won't do visual bells. */
3847 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3850 /* Subtract the `struct timeval' values X and Y, storing the result in
3851 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3854 timeval_subtract (result
, x
, y
)
3855 struct timeval
*result
, x
, y
;
3857 /* Perform the carry for the later subtraction by updating y. This
3858 is safer because on some systems the tv_sec member is unsigned. */
3859 if (x
.tv_usec
< y
.tv_usec
)
3861 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3862 y
.tv_usec
-= 1000000 * nsec
;
3866 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3868 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3869 y
.tv_usec
+= 1000000 * nsec
;
3873 /* Compute the time remaining to wait. tv_usec is certainly
3875 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3876 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3878 /* Return indication of whether the result should be considered
3880 return x
.tv_sec
< y
.tv_sec
;
3887 /* Get the height not including a menu bar widget. */
3888 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3889 /* Height of each line to flash. */
3890 int flash_height
= FRAME_LINE_HEIGHT (f
);
3891 /* These will be the left and right margins of the rectangles. */
3892 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3893 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3897 /* Don't flash the area between a scroll bar and the frame
3898 edge it is next to. */
3899 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3901 case vertical_scroll_bar_left
:
3902 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3905 case vertical_scroll_bar_right
:
3906 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3913 width
= flash_right
- flash_left
;
3917 /* If window is tall, flash top and bottom line. */
3918 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3920 mac_invert_rectangle (f
, flash_left
,
3921 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3922 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3923 width
, flash_height
);
3924 mac_invert_rectangle (f
, flash_left
,
3925 (height
- flash_height
3926 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3927 width
, flash_height
);
3930 /* If it is short, flash it all. */
3931 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3932 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3937 struct timeval wakeup
;
3939 EMACS_GET_TIME (wakeup
);
3941 /* Compute time to wait until, propagating carry from usecs. */
3942 wakeup
.tv_usec
+= 150000;
3943 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3944 wakeup
.tv_usec
%= 1000000;
3946 /* Keep waiting until past the time wakeup or any input gets
3948 while (! detect_input_pending ())
3950 struct timeval current
;
3951 struct timeval timeout
;
3953 EMACS_GET_TIME (current
);
3955 /* Break if result would be negative. */
3956 if (timeval_subtract (¤t
, wakeup
, current
))
3959 /* How long `select' should wait. */
3961 timeout
.tv_usec
= 10000;
3963 /* Try to wait that long--but we might wake up sooner. */
3964 select (0, NULL
, NULL
, NULL
, &timeout
);
3968 /* If window is tall, flash top and bottom line. */
3969 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3971 mac_invert_rectangle (f
, flash_left
,
3972 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3973 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3974 width
, flash_height
);
3975 mac_invert_rectangle (f
, flash_left
,
3976 (height
- flash_height
3977 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3978 width
, flash_height
);
3981 /* If it is short, flash it all. */
3982 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3983 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3990 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3993 /* Make audible bell. */
3998 struct frame
*f
= SELECTED_FRAME ();
4000 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4008 XFlush (FRAME_MAC_DISPLAY (f
));
4014 /* Specify how many text lines, from the top of the window,
4015 should be affected by insert-lines and delete-lines operations.
4016 This, and those operations, are used only within an update
4017 that is bounded by calls to x_update_begin and x_update_end. */
4020 XTset_terminal_window (n
)
4023 /* This function intentionally left blank. */
4028 /***********************************************************************
4030 ***********************************************************************/
4032 /* Perform an insert-lines or delete-lines operation, inserting N
4033 lines or deleting -N lines at vertical position VPOS. */
4036 x_ins_del_lines (vpos
, n
)
4043 /* Scroll part of the display as described by RUN. */
4046 x_scroll_run (w
, run
)
4050 struct frame
*f
= XFRAME (w
->frame
);
4051 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4053 /* Get frame-relative bounding box of the text display area of W,
4054 without mode lines. Include in this box the left and right
4056 window_box (w
, -1, &x
, &y
, &width
, &height
);
4058 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4059 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4060 bottom_y
= y
+ height
;
4064 /* Scrolling up. Make sure we don't copy part of the mode
4065 line at the bottom. */
4066 if (from_y
+ run
->height
> bottom_y
)
4067 height
= bottom_y
- from_y
;
4069 height
= run
->height
;
4073 /* Scolling down. Make sure we don't copy over the mode line.
4075 if (to_y
+ run
->height
> bottom_y
)
4076 height
= bottom_y
- to_y
;
4078 height
= run
->height
;
4083 /* Cursor off. Will be switched on again in x_update_window_end. */
4087 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4097 /***********************************************************************
4099 ***********************************************************************/
4107 ControlRef root_control
;
4110 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4112 ActivateControl (root_control
);
4114 x_update_cursor (f
, 1);
4118 frame_unhighlight (f
)
4122 ControlRef root_control
;
4125 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4127 DeactivateControl (root_control
);
4129 x_update_cursor (f
, 1);
4132 /* The focus has changed. Update the frames as necessary to reflect
4133 the new situation. Note that we can't change the selected frame
4134 here, because the Lisp code we are interrupting might become confused.
4135 Each event gets marked with the frame in which it occurred, so the
4136 Lisp code can tell when the switch took place by examining the events. */
4139 x_new_focus_frame (dpyinfo
, frame
)
4140 struct x_display_info
*dpyinfo
;
4141 struct frame
*frame
;
4143 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4145 if (frame
!= dpyinfo
->x_focus_frame
)
4147 /* Set this before calling other routines, so that they see
4148 the correct value of x_focus_frame. */
4149 dpyinfo
->x_focus_frame
= frame
;
4151 if (old_focus
&& old_focus
->auto_lower
)
4152 x_lower_frame (old_focus
);
4155 selected_frame
= frame
;
4156 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4158 Fselect_window (selected_frame
->selected_window
, Qnil
);
4159 choose_minibuf_frame ();
4162 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4163 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4165 pending_autoraise_frame
= 0;
4167 #if USE_MAC_FONT_PANEL
4169 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4173 x_frame_rehighlight (dpyinfo
);
4176 /* Handle FocusIn and FocusOut state changes for FRAME.
4177 If FRAME has focus and there exists more than one frame, puts
4178 a FOCUS_IN_EVENT into *BUFP. */
4181 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4183 struct mac_display_info
*dpyinfo
;
4184 struct frame
*frame
;
4185 struct input_event
*bufp
;
4187 if (type
== activeFlag
)
4189 if (dpyinfo
->x_focus_event_frame
!= frame
)
4191 x_new_focus_frame (dpyinfo
, frame
);
4192 dpyinfo
->x_focus_event_frame
= frame
;
4194 /* Don't stop displaying the initial startup message
4195 for a switch-frame event we don't need. */
4196 if (GC_NILP (Vterminal_frame
)
4197 && GC_CONSP (Vframe_list
)
4198 && !GC_NILP (XCDR (Vframe_list
)))
4200 bufp
->kind
= FOCUS_IN_EVENT
;
4201 XSETFRAME (bufp
->frame_or_window
, frame
);
4207 if (dpyinfo
->x_focus_event_frame
== frame
)
4209 dpyinfo
->x_focus_event_frame
= 0;
4210 x_new_focus_frame (dpyinfo
, 0);
4215 /* The focus may have changed. Figure out if it is a real focus change,
4216 by checking both FocusIn/Out and Enter/LeaveNotify events.
4218 Returns FOCUS_IN_EVENT event in *BUFP. */
4221 x_detect_focus_change (dpyinfo
, event
, bufp
)
4222 struct mac_display_info
*dpyinfo
;
4223 const EventRecord
*event
;
4224 struct input_event
*bufp
;
4226 struct frame
*frame
;
4228 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4232 /* On Mac, this is only called from focus events, so no switch needed. */
4233 mac_focus_changed ((event
->modifiers
& activeFlag
),
4234 dpyinfo
, frame
, bufp
);
4238 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4241 x_mouse_leave (dpyinfo
)
4242 struct x_display_info
*dpyinfo
;
4244 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4247 /* The focus has changed, or we have redirected a frame's focus to
4248 another frame (this happens when a frame uses a surrogate
4249 mini-buffer frame). Shift the highlight as appropriate.
4251 The FRAME argument doesn't necessarily have anything to do with which
4252 frame is being highlighted or un-highlighted; we only use it to find
4253 the appropriate X display info. */
4256 XTframe_rehighlight (frame
)
4257 struct frame
*frame
;
4259 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4263 x_frame_rehighlight (dpyinfo
)
4264 struct x_display_info
*dpyinfo
;
4266 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4268 if (dpyinfo
->x_focus_frame
)
4270 dpyinfo
->x_highlight_frame
4271 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4272 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4273 : dpyinfo
->x_focus_frame
);
4274 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4276 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4277 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4281 dpyinfo
->x_highlight_frame
= 0;
4283 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4286 frame_unhighlight (old_highlight
);
4287 if (dpyinfo
->x_highlight_frame
)
4288 frame_highlight (dpyinfo
->x_highlight_frame
);
4294 /* Convert a keysym to its name. */
4297 x_get_keysym_name (keysym
)
4304 value
= XKeysymToString (keysym
);
4315 /* Function to report a mouse movement to the mainstream Emacs code.
4316 The input handler calls this.
4318 We have received a mouse movement event, which is given in *event.
4319 If the mouse is over a different glyph than it was last time, tell
4320 the mainstream emacs code by setting mouse_moved. If not, ask for
4321 another motion event, so we can check again the next time it moves. */
4323 static Point last_mouse_motion_position
;
4324 static Lisp_Object last_mouse_motion_frame
;
4327 note_mouse_movement (frame
, pos
)
4331 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4332 #if TARGET_API_MAC_CARBON
4336 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4337 last_mouse_motion_position
= *pos
;
4338 XSETFRAME (last_mouse_motion_frame
, frame
);
4340 #if TARGET_API_MAC_CARBON
4341 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4343 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4346 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4347 /* This case corresponds to LeaveNotify in X11. */
4349 /* If we move outside the frame, then we're certainly no
4350 longer on any text in the frame. */
4351 clear_mouse_face (dpyinfo
);
4352 dpyinfo
->mouse_face_mouse_frame
= 0;
4353 if (!dpyinfo
->grabbed
)
4354 rif
->define_frame_cursor (frame
,
4355 frame
->output_data
.mac
->nontext_cursor
);
4359 /* Has the mouse moved off the glyph it was on at the last sighting? */
4360 if (frame
!= last_mouse_glyph_frame
4361 || !PtInRect (*pos
, &last_mouse_glyph
))
4363 frame
->mouse_moved
= 1;
4364 last_mouse_scroll_bar
= Qnil
;
4365 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4366 /* Remember which glyph we're now on. */
4367 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4368 last_mouse_glyph_frame
= frame
;
4376 /************************************************************************
4378 ************************************************************************/
4380 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4383 redo_mouse_highlight ()
4385 if (!NILP (last_mouse_motion_frame
)
4386 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4387 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4388 last_mouse_motion_position
.h
,
4389 last_mouse_motion_position
.v
);
4393 static struct frame
*
4394 mac_focus_frame (dpyinfo
)
4395 struct mac_display_info
*dpyinfo
;
4397 if (dpyinfo
->x_focus_frame
)
4398 return dpyinfo
->x_focus_frame
;
4400 /* Mac version may get events, such as a menu bar click, even when
4401 all the frames are invisible. In this case, we regard the
4402 event came to the selected frame. */
4403 return SELECTED_FRAME ();
4407 /* Return the current position of the mouse.
4408 *FP should be a frame which indicates which display to ask about.
4410 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4411 and *PART to the frame, window, and scroll bar part that the mouse
4412 is over. Set *X and *Y to the portion and whole of the mouse's
4413 position on the scroll bar.
4415 If the mouse movement started elsewhere, set *FP to the frame the
4416 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4419 Set *TIME to the server time-stamp for the time at which the mouse
4420 was at this position.
4422 Don't store anything if we don't have a valid set of values to report.
4424 This clears the mouse_moved flag, so we can wait for the next mouse
4428 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4431 Lisp_Object
*bar_window
;
4432 enum scroll_bar_part
*part
;
4434 unsigned long *time
;
4440 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4441 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4444 Lisp_Object frame
, tail
;
4446 /* Clear the mouse-moved flag for every frame on this display. */
4447 FOR_EACH_FRAME (tail
, frame
)
4448 XFRAME (frame
)->mouse_moved
= 0;
4450 last_mouse_scroll_bar
= Qnil
;
4452 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4453 && FRAME_LIVE_P (last_mouse_frame
))
4454 f1
= last_mouse_frame
;
4456 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4460 /* Ok, we found a frame. Store all the values.
4461 last_mouse_glyph is a rectangle used to reduce the
4462 generation of mouse events. To not miss any motion
4463 events, we must divide the frame into rectangles of the
4464 size of the smallest character that could be displayed
4465 on it, i.e. into the same rectangles that matrices on
4466 the frame are divided into. */
4469 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4470 GetMouse (&mouse_pos
);
4471 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4473 last_mouse_glyph_frame
= f1
;
4478 XSETINT (*x
, mouse_pos
.h
);
4479 XSETINT (*y
, mouse_pos
.v
);
4480 *time
= last_mouse_movement_time
;
4488 /************************************************************************
4490 ************************************************************************/
4492 #ifdef USE_TOOLKIT_SCROLL_BARS
4494 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4495 static OSStatus install_scroll_bar_timer
P_ ((void));
4496 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4497 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4498 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4499 struct input_event
*));
4500 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4502 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4504 struct input_event
*));
4505 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4506 struct input_event
*));
4507 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4508 Point
, struct input_event
*));
4509 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4512 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4514 static int last_scroll_bar_part
;
4516 static EventLoopTimerRef scroll_bar_timer
;
4518 static int scroll_bar_timer_event_posted_p
;
4520 #define SCROLL_BAR_FIRST_DELAY 0.5
4521 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4524 scroll_bar_timer_callback (timer
, data
)
4525 EventLoopTimerRef timer
;
4530 err
= mac_post_mouse_moved_event ();
4532 scroll_bar_timer_event_posted_p
= 1;
4536 install_scroll_bar_timer ()
4538 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4540 if (scroll_bar_timer_callbackUPP
== NULL
)
4541 scroll_bar_timer_callbackUPP
=
4542 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4544 if (scroll_bar_timer
== NULL
)
4545 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4546 kEventDurationForever as delays. */
4548 InstallEventLoopTimer (GetCurrentEventLoop (),
4549 kEventDurationForever
, kEventDurationForever
,
4550 scroll_bar_timer_callbackUPP
, NULL
,
4555 set_scroll_bar_timer (delay
)
4556 EventTimerInterval delay
;
4558 if (scroll_bar_timer
== NULL
)
4559 install_scroll_bar_timer ();
4561 scroll_bar_timer_event_posted_p
= 0;
4563 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4567 control_part_code_to_scroll_bar_part (part_code
)
4568 ControlPartCode part_code
;
4572 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4573 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4574 case kControlPageUpPart
: return scroll_bar_above_handle
;
4575 case kControlPageDownPart
: return scroll_bar_below_handle
;
4576 case kControlIndicatorPart
: return scroll_bar_handle
;
4583 construct_scroll_bar_click (bar
, part
, bufp
)
4584 struct scroll_bar
*bar
;
4586 struct input_event
*bufp
;
4588 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4589 bufp
->frame_or_window
= bar
->window
;
4593 XSETINT (bufp
->x
, 0);
4594 XSETINT (bufp
->y
, 0);
4595 bufp
->modifiers
= 0;
4599 get_control_part_bounds (ch
, part_code
, rect
)
4601 ControlPartCode part_code
;
4604 RgnHandle region
= NewRgn ();
4607 err
= GetControlRegion (ch
, part_code
, region
);
4609 GetRegionBounds (region
, rect
);
4610 DisposeRgn (region
);
4616 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4617 struct scroll_bar
*bar
;
4618 ControlPartCode part_code
;
4619 struct input_event
*bufp
;
4621 int part
= control_part_code_to_scroll_bar_part (part_code
);
4626 if (part
!= scroll_bar_handle
)
4628 construct_scroll_bar_click (bar
, part
, bufp
);
4629 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4630 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4633 last_scroll_bar_part
= part
;
4634 bar
->dragging
= Qnil
;
4635 tracked_scroll_bar
= bar
;
4639 x_scroll_bar_handle_release (bar
, bufp
)
4640 struct scroll_bar
*bar
;
4641 struct input_event
*bufp
;
4643 if (last_scroll_bar_part
!= scroll_bar_handle
4644 || !GC_NILP (bar
->dragging
))
4645 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4647 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4648 set_scroll_bar_timer (kEventDurationForever
);
4650 last_scroll_bar_part
= -1;
4651 bar
->dragging
= Qnil
;
4652 tracked_scroll_bar
= NULL
;
4656 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4658 struct scroll_bar
*bar
;
4660 struct input_event
*bufp
;
4662 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4664 if (last_scroll_bar_part
== scroll_bar_handle
)
4669 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4670 kControlIndicatorPart
, &r
);
4672 if (GC_NILP (bar
->dragging
))
4673 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4675 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4676 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4677 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4682 if (top
> top_range
)
4685 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4686 XSETINT (bufp
->x
, top
);
4687 XSETINT (bufp
->y
, top_range
);
4691 ControlPartCode part_code
;
4692 int unhilite_p
= 0, part
;
4694 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4698 part
= control_part_code_to_scroll_bar_part (part_code
);
4700 switch (last_scroll_bar_part
)
4702 case scroll_bar_above_handle
:
4703 case scroll_bar_below_handle
:
4704 if (part
!= scroll_bar_above_handle
4705 && part
!= scroll_bar_below_handle
)
4709 case scroll_bar_up_arrow
:
4710 case scroll_bar_down_arrow
:
4711 if (part
!= scroll_bar_up_arrow
4712 && part
!= scroll_bar_down_arrow
)
4719 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4720 else if (part
!= last_scroll_bar_part
4721 || scroll_bar_timer_event_posted_p
)
4723 construct_scroll_bar_click (bar
, part
, bufp
);
4724 last_scroll_bar_part
= part
;
4725 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4726 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4731 /* Set the thumb size and position of scroll bar BAR. We are currently
4732 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4735 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4736 struct scroll_bar
*bar
;
4737 int portion
, position
, whole
;
4739 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4740 int value
, viewsize
, maximum
;
4742 if (XINT (bar
->track_height
) == 0)
4746 value
= 0, viewsize
= 1, maximum
= 0;
4751 maximum
= max (0, whole
- portion
);
4756 if (GetControlViewSize (ch
) != viewsize
4757 || GetControl32BitValue (ch
) != value
4758 || GetControl32BitMaximum (ch
) != maximum
)
4760 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4761 SetControlVisibility (ch
, false, false);
4763 SetControl32BitMaximum (ch
, maximum
);
4764 SetControl32BitValue (ch
, value
);
4765 SetControlViewSize (ch
, viewsize
);
4767 SetControlVisibility (ch
, true, true);
4773 #endif /* USE_TOOLKIT_SCROLL_BARS */
4777 /************************************************************************
4778 Scroll bars, general
4779 ************************************************************************/
4781 /* Create a scroll bar and return the scroll bar vector for it. W is
4782 the Emacs window on which to create the scroll bar. TOP, LEFT,
4783 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4786 static struct scroll_bar
*
4787 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4789 int top
, left
, width
, height
, disp_top
, disp_height
;
4791 struct frame
*f
= XFRAME (w
->frame
);
4792 struct scroll_bar
*bar
4793 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4801 r
.right
= left
+ width
;
4802 r
.bottom
= disp_top
+ disp_height
;
4805 mac_prepare_for_quickdraw (f
);
4807 #if TARGET_API_MAC_CARBON
4808 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4809 #if USE_TOOLKIT_SCROLL_BARS
4812 width
< disp_height
,
4814 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4816 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4817 0, 0, 0, scrollBarProc
, (long) bar
);
4819 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4821 XSETWINDOW (bar
->window
, w
);
4822 XSETINT (bar
->top
, top
);
4823 XSETINT (bar
->left
, left
);
4824 XSETINT (bar
->width
, width
);
4825 XSETINT (bar
->height
, height
);
4826 XSETINT (bar
->start
, 0);
4827 XSETINT (bar
->end
, 0);
4828 bar
->dragging
= Qnil
;
4829 #ifdef USE_TOOLKIT_SCROLL_BARS
4830 bar
->track_top
= Qnil
;
4831 bar
->track_height
= Qnil
;
4834 /* Add bar to its frame's list of scroll bars. */
4835 bar
->next
= FRAME_SCROLL_BARS (f
);
4837 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4838 if (!NILP (bar
->next
))
4839 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4846 /* Draw BAR's handle in the proper position.
4848 If the handle is already drawn from START to END, don't bother
4849 redrawing it, unless REBUILD is non-zero; in that case, always
4850 redraw it. (REBUILD is handy for drawing the handle after expose
4853 Normally, we want to constrain the start and end of the handle to
4854 fit inside its rectangle, but if the user is dragging the scroll
4855 bar handle, we want to let them drag it down all the way, so that
4856 the bar's top is as far down as it goes; otherwise, there's no way
4857 to move to the very end of the buffer. */
4859 #ifndef USE_TOOLKIT_SCROLL_BARS
4862 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4863 struct scroll_bar
*bar
;
4867 int dragging
= ! NILP (bar
->dragging
);
4868 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4869 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4870 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4871 int length
= end
- start
;
4873 /* If the display is already accurate, do nothing. */
4875 && start
== XINT (bar
->start
)
4876 && end
== XINT (bar
->end
))
4881 /* Make sure the values are reasonable, and try to preserve the
4882 distance between start and end. */
4885 else if (start
> top_range
)
4887 end
= start
+ length
;
4891 else if (end
> top_range
&& ! dragging
)
4894 /* Store the adjusted setting in the scroll bar. */
4895 XSETINT (bar
->start
, start
);
4896 XSETINT (bar
->end
, end
);
4898 /* Clip the end position, just for display. */
4899 if (end
> top_range
)
4902 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4903 top positions, to make sure the handle is always at least that
4904 many pixels tall. */
4905 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4907 SetControlMinimum (ch
, 0);
4908 /* Don't inadvertently activate deactivated scroll bars */
4909 if (GetControlMaximum (ch
) != -1)
4910 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4912 SetControlValue (ch
, start
);
4913 #if TARGET_API_MAC_CARBON
4914 SetControlViewSize (ch
, end
- start
);
4920 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4922 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4926 x_scroll_bar_remove (bar
)
4927 struct scroll_bar
*bar
;
4929 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4934 mac_prepare_for_quickdraw (f
);
4936 /* Destroy the Mac scroll bar control */
4937 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4939 /* Disassociate this scroll bar from its window. */
4940 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4946 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4947 that we are displaying PORTION characters out of a total of WHOLE
4948 characters, starting at POSITION. If WINDOW has no scroll bar,
4952 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4954 int portion
, whole
, position
;
4956 struct frame
*f
= XFRAME (w
->frame
);
4957 struct scroll_bar
*bar
;
4958 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4959 int window_y
, window_height
;
4961 /* Get window dimensions. */
4962 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4964 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4965 height
= window_height
;
4967 /* Compute the left edge of the scroll bar area. */
4968 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4970 /* Compute the width of the scroll bar which might be less than
4971 the width of the area reserved for the scroll bar. */
4972 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4973 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4977 /* Compute the left edge of the scroll bar. */
4978 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4981 sb_left
= left
+ width
- sb_width
;
4983 /* Adjustments according to Inside Macintosh to make it look nice */
4985 disp_height
= height
;
4992 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4998 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
5002 /* Does the scroll bar exist yet? */
5003 if (NILP (w
->vertical_scroll_bar
))
5006 mac_clear_area (f
, left
, top
, width
, height
);
5008 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
5010 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5014 /* It may just need to be moved and resized. */
5017 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5018 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5022 /* If already correctly positioned, do nothing. */
5023 if (!(XINT (bar
->left
) == sb_left
5024 && XINT (bar
->top
) == top
5025 && XINT (bar
->width
) == sb_width
5026 && XINT (bar
->height
) == height
))
5028 /* Since toolkit scroll bars are smaller than the space reserved
5029 for them on the frame, we have to clear "under" them. */
5030 mac_clear_area (f
, left
, top
, width
, height
);
5033 mac_prepare_for_quickdraw (f
);
5036 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5037 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5039 #ifndef USE_TOOLKIT_SCROLL_BARS
5040 if (sb_width
< disp_height
)
5044 /* Remember new settings. */
5045 XSETINT (bar
->left
, sb_left
);
5046 XSETINT (bar
->top
, top
);
5047 XSETINT (bar
->width
, sb_width
);
5048 XSETINT (bar
->height
, height
);
5049 #ifdef USE_TOOLKIT_SCROLL_BARS
5050 bar
->track_top
= Qnil
;
5051 bar
->track_height
= Qnil
;
5058 #ifdef USE_TOOLKIT_SCROLL_BARS
5059 if (NILP (bar
->track_top
))
5061 if (sb_width
>= disp_height
)
5063 XSETINT (bar
->track_top
, 0);
5064 XSETINT (bar
->track_height
, 0);
5068 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5073 SetControl32BitMinimum (ch
, 0);
5074 SetControl32BitMaximum (ch
, 1);
5075 SetControlViewSize (ch
, 1);
5077 /* Move the scroll bar thumb to the top. */
5078 SetControl32BitValue (ch
, 0);
5079 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5081 /* Move the scroll bar thumb to the bottom. */
5082 SetControl32BitValue (ch
, 1);
5083 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5085 UnionRect (&r0
, &r1
, &r0
);
5086 XSETINT (bar
->track_top
, r0
.top
);
5087 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5089 /* Don't show the scroll bar if its height is not enough to
5090 display the scroll bar thumb. */
5091 if (r0
.bottom
- r0
.top
> 0)
5098 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5099 #else /* not USE_TOOLKIT_SCROLL_BARS */
5100 /* Set the scroll bar's current state, unless we're currently being
5102 if (NILP (bar
->dragging
))
5104 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5107 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5110 int start
= ((double) position
* top_range
) / whole
;
5111 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5112 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5115 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5119 /* The following three hooks are used when we're doing a thorough
5120 redisplay of the frame. We don't explicitly know which scroll bars
5121 are going to be deleted, because keeping track of when windows go
5122 away is a real pain - "Can you say set-window-configuration, boys
5123 and girls?" Instead, we just assert at the beginning of redisplay
5124 that *all* scroll bars are to be removed, and then save a scroll bar
5125 from the fiery pit when we actually redisplay its window. */
5127 /* Arrange for all scroll bars on FRAME to be removed at the next call
5128 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5129 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5132 XTcondemn_scroll_bars (frame
)
5135 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5136 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5139 bar
= FRAME_SCROLL_BARS (frame
);
5140 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5141 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5142 XSCROLL_BAR (bar
)->prev
= Qnil
;
5143 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5144 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5145 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5150 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5151 Note that WINDOW isn't necessarily condemned at all. */
5154 XTredeem_scroll_bar (window
)
5155 struct window
*window
;
5157 struct scroll_bar
*bar
;
5160 /* We can't redeem this window's scroll bar if it doesn't have one. */
5161 if (NILP (window
->vertical_scroll_bar
))
5164 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5166 /* Unlink it from the condemned list. */
5167 f
= XFRAME (WINDOW_FRAME (window
));
5168 if (NILP (bar
->prev
))
5170 /* If the prev pointer is nil, it must be the first in one of
5172 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5173 /* It's not condemned. Everything's fine. */
5175 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5176 window
->vertical_scroll_bar
))
5177 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5179 /* If its prev pointer is nil, it must be at the front of
5180 one or the other! */
5184 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5186 if (! NILP (bar
->next
))
5187 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5189 bar
->next
= FRAME_SCROLL_BARS (f
);
5191 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5192 if (! NILP (bar
->next
))
5193 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5196 /* Remove all scroll bars on FRAME that haven't been saved since the
5197 last call to `*condemn_scroll_bars_hook'. */
5200 XTjudge_scroll_bars (f
)
5203 Lisp_Object bar
, next
;
5205 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5207 /* Clear out the condemned list now so we won't try to process any
5208 more events on the hapless scroll bars. */
5209 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5211 for (; ! NILP (bar
); bar
= next
)
5213 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5215 x_scroll_bar_remove (b
);
5218 b
->next
= b
->prev
= Qnil
;
5221 /* Now there should be no references to the condemned scroll bars,
5222 and they should get garbage-collected. */
5226 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5227 is set to something other than NO_EVENT, it is enqueued.
5229 This may be called from a signal handler, so we have to ignore GC
5233 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5234 struct scroll_bar
*bar
;
5235 ControlPartCode part_code
;
5236 const EventRecord
*er
;
5237 struct input_event
*bufp
;
5239 int win_y
, top_range
;
5241 if (! GC_WINDOWP (bar
->window
))
5244 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5245 bufp
->frame_or_window
= bar
->window
;
5248 bar
->dragging
= Qnil
;
5252 case kControlUpButtonPart
:
5253 bufp
->part
= scroll_bar_up_arrow
;
5255 case kControlDownButtonPart
:
5256 bufp
->part
= scroll_bar_down_arrow
;
5258 case kControlPageUpPart
:
5259 bufp
->part
= scroll_bar_above_handle
;
5261 case kControlPageDownPart
:
5262 bufp
->part
= scroll_bar_below_handle
;
5264 #if TARGET_API_MAC_CARBON
5267 case kControlIndicatorPart
:
5269 if (er
->what
== mouseDown
)
5270 bar
->dragging
= make_number (0);
5271 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5272 bufp
->part
= scroll_bar_handle
;
5276 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5277 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5279 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5283 if (! NILP (bar
->dragging
))
5284 win_y
-= XINT (bar
->dragging
);
5288 if (win_y
> top_range
)
5291 XSETINT (bufp
->x
, win_y
);
5292 XSETINT (bufp
->y
, top_range
);
5295 #ifndef USE_TOOLKIT_SCROLL_BARS
5297 /* Handle some mouse motion while someone is dragging the scroll bar.
5299 This may be called from a signal handler, so we have to ignore GC
5303 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5304 struct scroll_bar
*bar
;
5308 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5310 last_mouse_movement_time
= t
;
5313 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5315 /* If we're dragging the bar, display it. */
5316 if (! GC_NILP (bar
->dragging
))
5318 /* Where should the handle be now? */
5319 int new_start
= y_pos
- 24;
5321 if (new_start
!= XINT (bar
->start
))
5323 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5325 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5330 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5332 /* Return information to the user about the current position of the mouse
5333 on the scroll bar. */
5336 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5338 Lisp_Object
*bar_window
;
5339 enum scroll_bar_part
*part
;
5341 unsigned long *time
;
5343 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5344 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5345 #if TARGET_API_MAC_CARBON
5346 WindowPtr wp
= GetControlOwner (ch
);
5348 WindowPtr wp
= (*ch
)->contrlOwner
;
5351 struct frame
*f
= mac_window_to_frame (wp
);
5352 int win_y
, top_range
;
5354 SetPortWindowPort (wp
);
5356 GetMouse (&mouse_pos
);
5358 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5359 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5361 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5365 if (! NILP (bar
->dragging
))
5366 win_y
-= XINT (bar
->dragging
);
5370 if (win_y
> top_range
)
5374 *bar_window
= bar
->window
;
5376 if (! NILP (bar
->dragging
))
5377 *part
= scroll_bar_handle
;
5378 else if (win_y
< XINT (bar
->start
))
5379 *part
= scroll_bar_above_handle
;
5380 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5381 *part
= scroll_bar_handle
;
5383 *part
= scroll_bar_below_handle
;
5385 XSETINT (*x
, win_y
);
5386 XSETINT (*y
, top_range
);
5389 last_mouse_scroll_bar
= Qnil
;
5391 *time
= last_mouse_movement_time
;
5395 /* The screen has been cleared so we may have changed foreground or
5396 background colors, and the scroll bars may need to be redrawn.
5397 Clear out the scroll bars, and ask for expose events, so we can
5401 x_scroll_bar_clear (f
)
5404 XTcondemn_scroll_bars (f
);
5405 XTjudge_scroll_bars (f
);
5409 /***********************************************************************
5411 ***********************************************************************/
5413 /* Set clipping for output in glyph row ROW. W is the window in which
5414 we operate. GC is the graphics context to set clipping in.
5416 ROW may be a text row or, e.g., a mode line. Text rows must be
5417 clipped to the interior of the window dedicated to text display,
5418 mode lines must be clipped to the whole window. */
5421 x_clip_to_row (w
, row
, area
, gc
)
5423 struct glyph_row
*row
;
5427 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5429 int window_x
, window_y
, window_width
;
5431 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5433 clip_rect
.left
= window_x
;
5434 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5435 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5436 clip_rect
.right
= clip_rect
.left
+ window_width
;
5437 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5439 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5443 /* Draw a hollow box cursor on window W in glyph row ROW. */
5446 x_draw_hollow_cursor (w
, row
)
5448 struct glyph_row
*row
;
5450 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5451 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5452 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5455 struct glyph
*cursor_glyph
;
5458 /* Get the glyph the cursor is on. If we can't tell because
5459 the current matrix is invalid or such, give up. */
5460 cursor_glyph
= get_phys_cursor_glyph (w
);
5461 if (cursor_glyph
== NULL
)
5464 /* Compute frame-relative coordinates for phys cursor. */
5465 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5466 wd
= w
->phys_cursor_width
;
5468 /* The foreground of cursor_gc is typically the same as the normal
5469 background color, which can cause the cursor box to be invisible. */
5470 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5471 if (dpyinfo
->scratch_cursor_gc
)
5472 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5474 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5475 GCForeground
, &xgcv
);
5476 gc
= dpyinfo
->scratch_cursor_gc
;
5478 /* Set clipping, draw the rectangle, and reset clipping again. */
5479 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5480 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5481 mac_reset_clip_rectangles (dpy
, gc
);
5485 /* Draw a bar cursor on window W in glyph row ROW.
5487 Implementation note: One would like to draw a bar cursor with an
5488 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5489 Unfortunately, I didn't find a font yet that has this property set.
5493 x_draw_bar_cursor (w
, row
, width
, kind
)
5495 struct glyph_row
*row
;
5497 enum text_cursor_kinds kind
;
5499 struct frame
*f
= XFRAME (w
->frame
);
5500 struct glyph
*cursor_glyph
;
5502 /* If cursor is out of bounds, don't draw garbage. This can happen
5503 in mini-buffer windows when switching between echo area glyphs
5505 cursor_glyph
= get_phys_cursor_glyph (w
);
5506 if (cursor_glyph
== NULL
)
5509 /* If on an image, draw like a normal cursor. That's usually better
5510 visible than drawing a bar, esp. if the image is large so that
5511 the bar might not be in the window. */
5512 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5514 struct glyph_row
*row
;
5515 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5516 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5520 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5521 Window window
= FRAME_MAC_WINDOW (f
);
5522 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5523 unsigned long mask
= GCForeground
| GCBackground
;
5524 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5527 /* If the glyph's background equals the color we normally draw
5528 the bar cursor in, the bar cursor in its normal color is
5529 invisible. Use the glyph's foreground color instead in this
5530 case, on the assumption that the glyph's colors are chosen so
5531 that the glyph is legible. */
5532 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5533 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5535 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5538 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5541 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5542 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5546 width
= FRAME_CURSOR_WIDTH (f
);
5547 width
= min (cursor_glyph
->pixel_width
, width
);
5549 w
->phys_cursor_width
= width
;
5550 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5552 if (kind
== BAR_CURSOR
)
5553 mac_fill_rectangle (f
, gc
,
5554 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5555 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5556 width
, row
->height
);
5558 mac_fill_rectangle (f
, gc
,
5559 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5560 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5561 row
->height
- width
),
5562 cursor_glyph
->pixel_width
,
5565 mac_reset_clip_rectangles (dpy
, gc
);
5570 /* RIF: Define cursor CURSOR on frame F. */
5573 mac_define_frame_cursor (f
, cursor
)
5577 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5579 if (dpyinfo
->x_focus_frame
== f
)
5580 SetThemeCursor (cursor
);
5584 /* RIF: Clear area on frame F. */
5587 mac_clear_frame_area (f
, x
, y
, width
, height
)
5589 int x
, y
, width
, height
;
5591 mac_clear_area (f
, x
, y
, width
, height
);
5595 /* RIF: Draw cursor on window W. */
5598 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5600 struct glyph_row
*glyph_row
;
5602 int cursor_type
, cursor_width
;
5607 w
->phys_cursor_type
= cursor_type
;
5608 w
->phys_cursor_on_p
= 1;
5610 if (glyph_row
->exact_window_width_line_p
5611 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5613 glyph_row
->cursor_in_fringe_p
= 1;
5614 draw_fringe_bitmap (w
, glyph_row
, 0);
5617 switch (cursor_type
)
5619 case HOLLOW_BOX_CURSOR
:
5620 x_draw_hollow_cursor (w
, glyph_row
);
5623 case FILLED_BOX_CURSOR
:
5624 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5628 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5632 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5636 w
->phys_cursor_width
= 0;
5648 #if 0 /* MAC_TODO: no icon support yet. */
5650 x_bitmap_icon (f
, icon
)
5656 if (FRAME_W32_WINDOW (f
) == 0)
5660 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5661 else if (STRINGP (icon
))
5662 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5663 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5664 else if (SYMBOLP (icon
))
5668 if (EQ (icon
, intern ("application")))
5669 name
= (LPCTSTR
) IDI_APPLICATION
;
5670 else if (EQ (icon
, intern ("hand")))
5671 name
= (LPCTSTR
) IDI_HAND
;
5672 else if (EQ (icon
, intern ("question")))
5673 name
= (LPCTSTR
) IDI_QUESTION
;
5674 else if (EQ (icon
, intern ("exclamation")))
5675 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5676 else if (EQ (icon
, intern ("asterisk")))
5677 name
= (LPCTSTR
) IDI_ASTERISK
;
5678 else if (EQ (icon
, intern ("winlogo")))
5679 name
= (LPCTSTR
) IDI_WINLOGO
;
5683 hicon
= LoadIcon (NULL
, name
);
5691 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5696 #endif /* MAC_TODO */
5698 /************************************************************************
5700 ************************************************************************/
5702 /* Display Error Handling functions not used on W32. Listing them here
5703 helps diff stay in step when comparing w32term.c with xterm.c.
5705 x_error_catcher (display, error)
5706 x_catch_errors (dpy)
5707 x_catch_errors_unwind (old_val)
5708 x_check_errors (dpy, format)
5709 x_had_errors_p (dpy)
5710 x_clear_errors (dpy)
5711 x_uncatch_errors (dpy, count)
5713 x_connection_signal (signalnum)
5714 x_connection_closed (dpy, error_message)
5715 x_error_quitter (display, error)
5716 x_error_handler (display, error)
5717 x_io_error_quitter (display)
5722 /* Changing the font of the frame. */
5724 /* Give frame F the font named FONTNAME as its default font, and
5725 return the full name of that font. FONTNAME may be a wildcard
5726 pattern; in that case, we choose some font that fits the pattern.
5727 The return value shows which font we chose. */
5730 x_new_font (f
, fontname
)
5732 register char *fontname
;
5734 struct font_info
*fontp
5735 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5740 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5741 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5742 FRAME_FONTSET (f
) = -1;
5744 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5745 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5746 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5748 compute_fringe_widths (f
, 1);
5750 /* Compute the scroll bar width in character columns. */
5751 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5753 int wid
= FRAME_COLUMN_WIDTH (f
);
5754 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5755 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5759 int wid
= FRAME_COLUMN_WIDTH (f
);
5760 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5763 /* Now make the frame display the given font. */
5764 if (FRAME_MAC_WINDOW (f
) != 0)
5766 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5768 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5770 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5773 /* Don't change the size of a tip frame; there's no point in
5774 doing it because it's done in Fx_show_tip, and it leads to
5775 problems because the tip frame has no widget. */
5776 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5777 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5780 return build_string (fontp
->full_name
);
5783 /* Give frame F the fontset named FONTSETNAME as its default font, and
5784 return the full name of that fontset. FONTSETNAME may be a wildcard
5785 pattern; in that case, we choose some fontset that fits the pattern.
5786 The return value shows which fontset we chose. */
5789 x_new_fontset (f
, fontsetname
)
5793 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5799 if (FRAME_FONTSET (f
) == fontset
)
5800 /* This fontset is already set in frame F. There's nothing more
5802 return fontset_name (fontset
);
5804 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5806 if (!STRINGP (result
))
5807 /* Can't load ASCII font. */
5810 /* Since x_new_font doesn't update any fontset information, do it now. */
5811 FRAME_FONTSET (f
) = fontset
;
5813 return build_string (fontsetname
);
5817 /***********************************************************************
5818 TODO: W32 Input Methods
5819 ***********************************************************************/
5820 /* Listing missing functions from xterm.c helps diff stay in step.
5822 xim_destroy_callback (xim, client_data, call_data)
5823 xim_open_dpy (dpyinfo, resource_name)
5825 xim_instantiate_callback (display, client_data, call_data)
5826 xim_initialize (dpyinfo, resource_name)
5827 xim_close_dpy (dpyinfo)
5833 mac_get_window_bounds (f
, inner
, outer
)
5835 Rect
*inner
, *outer
;
5837 #if TARGET_API_MAC_CARBON
5838 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5839 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5840 #else /* not TARGET_API_MAC_CARBON */
5841 RgnHandle region
= NewRgn ();
5843 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5844 *inner
= (*region
)->rgnBBox
;
5845 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5846 *outer
= (*region
)->rgnBBox
;
5847 DisposeRgn (region
);
5848 #endif /* not TARGET_API_MAC_CARBON */
5852 mac_handle_origin_change (f
)
5855 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5859 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
5861 int pixelwidth
, pixelheight
;
5865 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
5866 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
5868 if (cols
!= FRAME_COLS (f
)
5869 || rows
!= FRAME_LINES (f
)
5870 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
5871 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
5873 /* We pass 1 for DELAY since we can't run Lisp code inside of
5875 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5876 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5877 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5878 SET_FRAME_GARBAGED (f
);
5880 /* If cursor was outside the new size, mark it as off. */
5881 mark_window_cursors_off (XWINDOW (f
->root_window
));
5883 /* Clear out any recollection of where the mouse highlighting
5884 was, since it might be in a place that's outside the new
5885 frame size. Actually checking whether it is outside is a
5886 pain in the neck, so don't try--just let the highlighting be
5887 done afresh with new size. */
5888 cancel_mouse_face (f
);
5890 #if TARGET_API_MAC_CARBON
5891 if (f
->output_data
.mac
->hourglass_control
)
5894 mac_prepare_for_quickdraw (f
);
5896 MoveControl (f
->output_data
.mac
->hourglass_control
,
5897 pixelwidth
- HOURGLASS_WIDTH
, 0);
5904 /* Calculate the absolute position in frame F
5905 from its current recorded position values and gravity. */
5908 x_calc_absolute_position (f
)
5911 int width_diff
= 0, height_diff
= 0;
5912 int flags
= f
->size_hint_flags
;
5915 /* We have nothing to do if the current position
5916 is already for the top-left corner. */
5917 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5920 /* Find the offsets of the outside upper-left corner of
5921 the inner window, with respect to the outer window. */
5922 mac_get_window_bounds (f
, &inner
, &outer
);
5924 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5925 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5927 /* Treat negative positions as relative to the leftmost bottommost
5928 position that fits on the screen. */
5929 if (flags
& XNegative
)
5930 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5932 - FRAME_PIXEL_WIDTH (f
)
5935 if (flags
& YNegative
)
5936 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5938 - FRAME_PIXEL_HEIGHT (f
)
5941 /* The left_pos and top_pos
5942 are now relative to the top and left screen edges,
5943 so the flags should correspond. */
5944 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5947 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5948 to really change the position, and 0 when calling from
5949 x_make_frame_visible (in that case, XOFF and YOFF are the current
5950 position values). It is -1 when calling from x_set_frame_parameters,
5951 which means, do adjust for borders but don't change the gravity. */
5954 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5956 register int xoff
, yoff
;
5959 if (change_gravity
> 0)
5963 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5965 f
->size_hint_flags
|= XNegative
;
5967 f
->size_hint_flags
|= YNegative
;
5968 f
->win_gravity
= NorthWestGravity
;
5970 x_calc_absolute_position (f
);
5973 x_wm_set_size_hint (f
, (long) 0, 0);
5975 #if TARGET_API_MAC_CARBON
5976 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5977 /* If the title bar is completely outside the screen, adjust the
5979 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5980 kWindowConstrainMoveRegardlessOfFit
5981 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5982 #if USE_CARBON_EVENTS
5983 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
5985 mac_handle_origin_change (f
);
5988 Rect inner
, outer
, screen_rect
, dummy
;
5989 RgnHandle region
= NewRgn ();
5991 mac_get_window_bounds (f
, &inner
, &outer
);
5992 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5993 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5994 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5995 f
->top_pos
+ f
->y_pixels_diff
, false);
5997 /* If the title bar is completely outside the screen, adjust the
5998 position. The variable `outer' holds the title bar rectangle.
5999 The variable `inner' holds slightly smaller one than `outer',
6000 so that the calculation of overlapping may not become too
6002 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
6003 outer
= (*region
)->rgnBBox
;
6004 DisposeRgn (region
);
6006 InsetRect (&inner
, 8, 8);
6007 screen_rect
= qd
.screenBits
.bounds
;
6008 screen_rect
.top
+= GetMBarHeight ();
6010 if (!SectRect (&inner
, &screen_rect
, &dummy
))
6012 if (inner
.right
<= screen_rect
.left
)
6013 f
->left_pos
= screen_rect
.left
;
6014 else if (inner
.left
>= screen_rect
.right
)
6015 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6017 if (inner
.bottom
<= screen_rect
.top
)
6018 f
->top_pos
= screen_rect
.top
;
6019 else if (inner
.top
>= screen_rect
.bottom
)
6020 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6022 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6023 f
->top_pos
+ f
->y_pixels_diff
, false);
6031 /* Call this to change the size of frame F's x-window.
6032 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6033 for this size change and subsequent size changes.
6034 Otherwise we leave the window gravity unchanged. */
6037 x_set_window_size (f
, change_gravity
, cols
, rows
)
6042 int pixelwidth
, pixelheight
;
6046 check_frame_size (f
, &rows
, &cols
);
6047 f
->scroll_bar_actual_width
6048 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6050 compute_fringe_widths (f
, 0);
6052 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6053 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6055 f
->win_gravity
= NorthWestGravity
;
6056 x_wm_set_size_hint (f
, (long) 0, 0);
6058 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6060 #if USE_CARBON_EVENTS
6061 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6063 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6068 /* Mouse warping. */
6070 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6073 x_set_mouse_position (f
, x
, y
)
6079 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6080 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6082 if (pix_x
< 0) pix_x
= 0;
6083 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6085 if (pix_y
< 0) pix_y
= 0;
6086 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6088 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6092 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6101 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
6107 CGWarpMouseCursorPosition (point
);
6110 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6113 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6114 0, 0, 0, 0, pix_x
, pix_y
);
6120 /* focus shifting, raising and lowering. */
6123 x_focus_on_frame (f
)
6126 #if 0 /* This proves to be unpleasant. */
6130 /* I don't think that the ICCCM allows programs to do things like this
6131 without the interaction of the window manager. Whatever you end up
6132 doing with this code, do it to x_unfocus_frame too. */
6133 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6134 RevertToPointerRoot
, CurrentTime
);
6144 /* Raise frame F. */
6150 if (f
->async_visible
)
6153 BringToFront (FRAME_MAC_WINDOW (f
));
6158 /* Lower frame F. */
6164 if (f
->async_visible
)
6167 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6173 XTframe_raise_lower (f
, raise_flag
)
6183 /* Change of visibility. */
6186 mac_handle_visibility_change (f
)
6189 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6190 int visible
= 0, iconified
= 0;
6191 struct input_event buf
;
6193 if (IsWindowVisible (wp
))
6195 if (IsWindowCollapsed (wp
))
6201 if (!f
->async_visible
&& visible
)
6205 /* wait_reading_process_output will notice this and update
6206 the frame's display structures. If we were made
6207 invisible, we should not set garbaged, because that stops
6208 redrawing on Update events. */
6209 SET_FRAME_GARBAGED (f
);
6212 buf
.kind
= DEICONIFY_EVENT
;
6213 XSETFRAME (buf
.frame_or_window
, f
);
6215 kbd_buffer_store_event (&buf
);
6217 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6218 /* Force a redisplay sooner or later to update the
6219 frame titles in case this is the second frame. */
6220 record_asynch_buffer_change ();
6222 else if (f
->async_visible
&& !visible
)
6226 buf
.kind
= ICONIFY_EVENT
;
6227 XSETFRAME (buf
.frame_or_window
, f
);
6229 kbd_buffer_store_event (&buf
);
6232 f
->async_visible
= visible
;
6233 f
->async_iconified
= iconified
;
6236 /* This tries to wait until the frame is really visible.
6237 However, if the window manager asks the user where to position
6238 the frame, this will return before the user finishes doing that.
6239 The frame will not actually be visible at that time,
6240 but it will become visible later when the window manager
6241 finishes with it. */
6244 x_make_frame_visible (f
)
6249 if (! FRAME_VISIBLE_P (f
))
6251 /* We test FRAME_GARBAGED_P here to make sure we don't
6252 call x_set_offset a second time
6253 if we get to x_make_frame_visible a second time
6254 before the window gets really visible. */
6255 if (! FRAME_ICONIFIED_P (f
)
6256 && ! f
->output_data
.mac
->asked_for_visible
)
6258 #if TARGET_API_MAC_CARBON
6259 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6261 struct frame
*sf
= SELECTED_FRAME ();
6262 if (!FRAME_MAC_P (sf
))
6263 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6264 kWindowCenterOnMainScreen
);
6266 RepositionWindow (FRAME_MAC_WINDOW (f
),
6267 FRAME_MAC_WINDOW (sf
),
6268 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6269 kWindowCascadeStartAtParentWindowScreen
6271 kWindowCascadeOnParentWindowScreen
6274 #if USE_CARBON_EVENTS
6275 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6277 mac_handle_origin_change (f
);
6281 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6284 f
->output_data
.mac
->asked_for_visible
= 1;
6286 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6287 ShowWindow (FRAME_MAC_WINDOW (f
));
6290 XFlush (FRAME_MAC_DISPLAY (f
));
6292 /* Synchronize to ensure Emacs knows the frame is visible
6293 before we do anything else. We do this loop with input not blocked
6294 so that incoming events are handled. */
6299 /* This must come after we set COUNT. */
6302 XSETFRAME (frame
, f
);
6304 /* Wait until the frame is visible. Process X events until a
6305 MapNotify event has been seen, or until we think we won't get a
6306 MapNotify at all.. */
6307 for (count
= input_signal_count
+ 10;
6308 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6310 /* Force processing of queued events. */
6313 /* Machines that do polling rather than SIGIO have been
6314 observed to go into a busy-wait here. So we'll fake an
6315 alarm signal to let the handler know that there's something
6316 to be read. We used to raise a real alarm, but it seems
6317 that the handler isn't always enabled here. This is
6319 if (input_polling_used ())
6321 /* It could be confusing if a real alarm arrives while
6322 processing the fake one. Turn it off and let the
6323 handler reset it. */
6324 extern void poll_for_input_1
P_ ((void));
6325 int old_poll_suppress_count
= poll_suppress_count
;
6326 poll_suppress_count
= 1;
6327 poll_for_input_1 ();
6328 poll_suppress_count
= old_poll_suppress_count
;
6331 /* See if a MapNotify event has been processed. */
6332 FRAME_SAMPLE_VISIBILITY (f
);
6337 /* Change from mapped state to withdrawn state. */
6339 /* Make the frame visible (mapped and not iconified). */
6342 x_make_frame_invisible (f
)
6345 /* A deactivate event does not occur when the last visible frame is
6346 made invisible. So if we clear the highlight here, it will not
6347 be rehighlighted when it is made visible. */
6349 /* Don't keep the highlight on an invisible frame. */
6350 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6351 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6356 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6357 that the current position of the window is user-specified, rather than
6358 program-specified, so that when the window is mapped again, it will be
6359 placed at the same location, without forcing the user to position it
6360 by hand again (they have already done that once for this window.) */
6361 x_wm_set_size_hint (f
, (long) 0, 1);
6363 HideWindow (FRAME_MAC_WINDOW (f
));
6367 #if !USE_CARBON_EVENTS
6368 mac_handle_visibility_change (f
);
6372 /* Change window state from mapped to iconified. */
6380 /* A deactivate event does not occur when the last visible frame is
6381 iconified. So if we clear the highlight here, it will not be
6382 rehighlighted when it is deiconified. */
6384 /* Don't keep the highlight on an invisible frame. */
6385 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6386 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6389 if (f
->async_iconified
)
6394 FRAME_SAMPLE_VISIBILITY (f
);
6396 if (! FRAME_VISIBLE_P (f
))
6397 ShowWindow (FRAME_MAC_WINDOW (f
));
6399 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6404 error ("Can't notify window manager of iconification");
6406 #if !USE_CARBON_EVENTS
6407 mac_handle_visibility_change (f
);
6412 /* Free X resources of frame F. */
6415 x_free_frame_resources (f
)
6418 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6419 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6423 if (wp
!= tip_window
)
6424 remove_window_handler (wp
);
6427 if (wp
== tip_window
)
6428 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6429 closed' event. So we reset tip_window here. */
6432 free_frame_menubar (f
);
6434 if (FRAME_FACE_CACHE (f
))
6435 free_frame_faces (f
);
6439 if (FRAME_SIZE_HINTS (f
))
6440 xfree (FRAME_SIZE_HINTS (f
));
6442 xfree (f
->output_data
.mac
);
6443 f
->output_data
.mac
= NULL
;
6445 if (f
== dpyinfo
->x_focus_frame
)
6447 dpyinfo
->x_focus_frame
= 0;
6448 #if USE_MAC_FONT_PANEL
6449 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6452 if (f
== dpyinfo
->x_focus_event_frame
)
6453 dpyinfo
->x_focus_event_frame
= 0;
6454 if (f
== dpyinfo
->x_highlight_frame
)
6455 dpyinfo
->x_highlight_frame
= 0;
6457 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6459 dpyinfo
->mouse_face_beg_row
6460 = dpyinfo
->mouse_face_beg_col
= -1;
6461 dpyinfo
->mouse_face_end_row
6462 = dpyinfo
->mouse_face_end_col
= -1;
6463 dpyinfo
->mouse_face_window
= Qnil
;
6464 dpyinfo
->mouse_face_deferred_gc
= 0;
6465 dpyinfo
->mouse_face_mouse_frame
= 0;
6472 /* Destroy the X window of frame F. */
6475 x_destroy_window (f
)
6478 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6480 x_free_frame_resources (f
);
6482 dpyinfo
->reference_count
--;
6486 /* Setting window manager hints. */
6488 /* Set the normal size hints for the window manager, for frame F.
6489 FLAGS is the flags word to use--or 0 meaning preserve the flags
6490 that the window now has.
6491 If USER_POSITION is nonzero, we set the USPosition
6492 flag (this is useful when FLAGS is 0). */
6494 x_wm_set_size_hint (f
, flags
, user_position
)
6499 int base_width
, base_height
, width_inc
, height_inc
;
6500 int min_rows
= 0, min_cols
= 0;
6501 XSizeHints
*size_hints
;
6503 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6504 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6505 width_inc
= FRAME_COLUMN_WIDTH (f
);
6506 height_inc
= FRAME_LINE_HEIGHT (f
);
6508 check_frame_size (f
, &min_rows
, &min_cols
);
6510 size_hints
= FRAME_SIZE_HINTS (f
);
6511 if (size_hints
== NULL
)
6513 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6514 bzero (size_hints
, sizeof (XSizeHints
));
6517 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6518 size_hints
->width_inc
= width_inc
;
6519 size_hints
->height_inc
= height_inc
;
6520 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6521 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6522 size_hints
->base_width
= base_width
;
6523 size_hints
->base_height
= base_height
;
6526 size_hints
->flags
= flags
;
6527 else if (user_position
)
6529 size_hints
->flags
&= ~ PPosition
;
6530 size_hints
->flags
|= USPosition
;
6534 #if 0 /* MAC_TODO: hide application instead of iconify? */
6535 /* Used for IconicState or NormalState */
6538 x_wm_set_window_state (f
, state
)
6542 #ifdef USE_X_TOOLKIT
6545 XtSetArg (al
[0], XtNinitialState
, state
);
6546 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6547 #else /* not USE_X_TOOLKIT */
6548 Window window
= FRAME_X_WINDOW (f
);
6550 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6551 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6553 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6554 #endif /* not USE_X_TOOLKIT */
6558 x_wm_set_icon_pixmap (f
, pixmap_id
)
6564 #ifndef USE_X_TOOLKIT
6565 Window window
= FRAME_X_WINDOW (f
);
6570 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6571 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6575 /* It seems there is no way to turn off use of an icon pixmap.
6576 The following line does it, only if no icon has yet been created,
6577 for some window managers. But with mwm it crashes.
6578 Some people say it should clear the IconPixmapHint bit in this case,
6579 but that doesn't work, and the X consortium said it isn't the
6580 right thing at all. Since there is no way to win,
6581 best to explicitly give up. */
6583 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6589 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6593 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6594 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6597 #else /* not USE_X_TOOLKIT */
6599 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6600 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6602 #endif /* not USE_X_TOOLKIT */
6605 #endif /* MAC_TODO */
6608 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6612 #if 0 /* MAC_TODO: no icons on Mac */
6613 #ifdef USE_X_TOOLKIT
6614 Window window
= XtWindow (f
->output_data
.x
->widget
);
6616 Window window
= FRAME_X_WINDOW (f
);
6619 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6620 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6621 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6623 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6624 #endif /* MAC_TODO */
6628 /***********************************************************************
6630 ***********************************************************************/
6632 /* An XLFD pattern is divided into blocks delimited by '*'. This
6633 structure holds information for each block. */
6634 struct xlfdpat_block
6636 /* Length of the pattern string in this block. Non-zero except for
6637 the first and the last blocks. */
6640 /* Pattern string except the last character in this block. The last
6641 character is replaced with NUL in order to use it as a
6643 unsigned char *pattern
;
6645 /* Last character of the pattern string. Must not be '?'. */
6646 unsigned char last_char
;
6648 /* One of the tables for the Boyer-Moore string search. It
6649 specifies the number of positions to proceed for each character
6650 with which the match fails. */
6653 /* The skip value for the last character in the above `skip' is
6654 assigned to `infinity' in order to simplify a loop condition.
6655 The original value is saved here. */
6661 /* Normalized pattern string. "Normalized" means that capital
6662 letters are lowered, blocks are not empty except the first and
6663 the last ones, and trailing '?'s in a block that is not the last
6664 one are moved to the next one. The last character in each block
6665 is replaced with NUL. */
6668 /* Number of characters except '*'s and trailing '?'s in the
6669 normalized pattern string. */
6672 /* Number of trailing '?'s in the normalized pattern string. */
6673 int trailing_anychars
;
6675 /* Number of blocks and information for each block. The latter is
6676 NULL if the pattern is exact (no '*' or '?' in it). */
6678 struct xlfdpat_block
*blocks
;
6682 xlfdpat_destroy (pat
)
6683 struct xlfdpat
*pat
;
6690 xfree (pat
->blocks
);
6697 static struct xlfdpat
*
6698 xlfdpat_create (pattern
)
6699 const char *pattern
;
6701 struct xlfdpat
*pat
;
6702 int nblocks
, i
, skip
;
6703 unsigned char last_char
, *p
, *q
, *anychar_head
;
6704 const unsigned char *ptr
;
6705 struct xlfdpat_block
*blk
;
6707 pat
= xmalloc (sizeof (struct xlfdpat
));
6708 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6710 /* Normalize the pattern string and store it to `pat->buf'. */
6712 anychar_head
= NULL
;
6715 for (ptr
= pattern
; *ptr
; ptr
++)
6717 unsigned char c
= *ptr
;
6720 if (last_char
== '*')
6721 /* ...a** -> ...a* */
6725 if (last_char
== '?')
6727 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6728 /* ...*??* -> ...*?? */
6731 /* ...a??* -> ...a*?? */
6733 *anychar_head
++ = '*';
6741 if (last_char
!= '?')
6745 /* On Mac OS X 10.3, tolower also converts non-ASCII
6746 characters for some locales. */
6750 *q
++ = last_char
= c
;
6754 pat
->nblocks
= nblocks
;
6755 if (last_char
!= '?')
6756 pat
->trailing_anychars
= 0;
6759 pat
->trailing_anychars
= q
- anychar_head
;
6762 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6764 if (anychar_head
== NULL
&& nblocks
== 1)
6766 /* The pattern is exact. */
6771 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6773 /* Divide the normalized pattern into blocks. */
6775 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6780 blk
->len
= p
- blk
->pattern
;
6784 blk
->len
= q
- blk
->pattern
;
6786 /* Setup a table for the Boyer-Moore string search. */
6787 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6790 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6791 blk
->pattern
[blk
->len
- 1] = '\0';
6793 for (skip
= 1; skip
< blk
->len
; skip
++)
6794 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6797 for (i
= 0; i
< 256; i
++)
6798 blk
->skip
[i
] = skip
;
6800 p
= blk
->pattern
+ (blk
->len
- skip
);
6802 blk
->skip
[*p
++] = skip
;
6804 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6811 xlfdpat_exact_p (pat
)
6812 struct xlfdpat
*pat
;
6814 return pat
->blocks
== NULL
;
6817 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6818 that the pattern in *BLK matches with its prefix. Return NULL
6819 there is no such strings. STRING must be lowered in advance. */
6822 xlfdpat_block_match_1 (blk
, string
, start_max
)
6823 struct xlfdpat_block
*blk
;
6824 const unsigned char *string
;
6827 int start
, infinity
;
6829 const unsigned char *s
;
6831 xassert (blk
->len
> 0);
6832 xassert (start_max
+ blk
->len
<= strlen (string
));
6833 xassert (blk
->last_char
!= '?');
6835 /* See the comments in the function `boyer_moore' (search.c) for the
6836 use of `infinity'. */
6837 infinity
= start_max
+ blk
->len
+ 1;
6838 blk
->skip
[blk
->last_char
] = infinity
;
6843 /* Check the last character of the pattern. */
6844 s
= string
+ blk
->len
- 1;
6847 start
+= blk
->skip
[*(s
+ start
)];
6849 while (start
<= start_max
);
6851 if (start
< infinity
)
6852 /* Couldn't find the last character. */
6855 /* No less than `infinity' means we could find the last
6856 character at `s[start - infinity]'. */
6859 /* Check the remaining characters. We prefer making no-'?'
6860 cases faster because the use of '?' is really rare. */
6865 while (*p
++ == *s
++)
6868 while (*(p
- 1) == '?');
6870 if (*(p
- 1) == '\0')
6872 return string
+ start
;
6875 start
+= blk
->last_char_skip
;
6877 while (start
<= start_max
);
6882 #define xlfdpat_block_match(b, s, m) \
6883 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6884 : xlfdpat_block_match_1 (b, s, m))
6886 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
6887 matches with STRING. STRING must be lowered in advance. */
6890 xlfdpat_match (pat
, string
)
6891 struct xlfdpat
*pat
;
6892 const unsigned char *string
;
6894 int str_len
, nblocks
, i
, start_max
;
6895 struct xlfdpat_block
*blk
;
6896 const unsigned char *s
;
6898 xassert (pat
->nblocks
> 0);
6900 if (xlfdpat_exact_p (pat
))
6901 return strcmp (pat
->buf
, string
) == 0;
6903 /* The number of the characters in the string must not be smaller
6904 than that in the pattern. */
6905 str_len
= strlen (string
);
6906 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6909 /* Chop off the trailing '?'s. */
6910 str_len
-= pat
->trailing_anychars
;
6912 /* The last block. When it is non-empty, it must match at the end
6914 nblocks
= pat
->nblocks
;
6915 blk
= pat
->blocks
+ (nblocks
- 1);
6917 /* The last block is also the first one. */
6918 return (str_len
== blk
->len
6919 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6920 else if (blk
->len
!= 0)
6921 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6924 /* The first block. When it is non-empty, it must match at the
6925 beginning of the string. */
6929 s
= xlfdpat_block_match (blk
, string
, 0);
6932 string
= s
+ blk
->len
;
6935 /* The rest of the blocks. */
6936 start_max
= str_len
- pat
->nchars
;
6937 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6939 s
= xlfdpat_block_match (blk
, string
, start_max
);
6942 start_max
-= s
- string
;
6943 string
= s
+ blk
->len
;
6950 /***********************************************************************
6952 ***********************************************************************/
6954 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6957 x_get_font_info (f
, font_idx
)
6961 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6964 /* the global font name table */
6965 static char **font_name_table
= NULL
;
6966 static int font_name_table_size
= 0;
6967 static int font_name_count
= 0;
6969 /* Alist linking font family names to Font Manager font family
6970 references (which can also be used as QuickDraw font IDs). We use
6971 an alist because hash tables are not ready when the terminal frame
6972 for Mac OS Classic is created. */
6973 static Lisp_Object fm_font_family_alist
;
6975 /* Hash table linking font family names to ATSU font IDs. */
6976 static Lisp_Object atsu_font_id_hash
;
6977 /* Alist linking Font Manager style to face attributes. */
6978 static Lisp_Object fm_style_face_attributes_alist
;
6979 static Lisp_Object Vmac_atsu_font_table
;
6980 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
6983 /* Alist linking character set strings to Mac text encoding and Emacs
6985 static Lisp_Object Vmac_charset_info_alist
;
6988 create_text_encoding_info_alist ()
6990 Lisp_Object result
= Qnil
, rest
;
6992 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6994 Lisp_Object charset_info
= XCAR (rest
);
6995 Lisp_Object charset
, coding_system
, text_encoding
;
6996 Lisp_Object existing_info
;
6998 if (!(CONSP (charset_info
)
6999 && STRINGP (charset
= XCAR (charset_info
))
7000 && CONSP (XCDR (charset_info
))
7001 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
7002 && CONSP (XCDR (XCDR (charset_info
)))
7003 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
7006 existing_info
= assq_no_quit (text_encoding
, result
);
7007 if (NILP (existing_info
))
7008 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
7011 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
7012 XSETCDR (XCDR (existing_info
),
7013 Fcons (charset
, XCDR (XCDR (existing_info
))));
7021 decode_mac_font_name (name
, size
, coding_system
)
7024 Lisp_Object coding_system
;
7026 struct coding_system coding
;
7029 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7031 for (p
= name
; *p
; p
++)
7032 if (!isascii (*p
) || iscntrl (*p
))
7037 setup_coding_system (coding_system
, &coding
);
7038 coding
.src_multibyte
= 0;
7039 coding
.dst_multibyte
= 1;
7040 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7041 coding
.composing
= COMPOSITION_DISABLED
;
7042 buf
= (char *) alloca (size
);
7044 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7045 bcopy (buf
, name
, coding
.produced
);
7046 name
[coding
.produced
] = '\0';
7050 /* If there's just one occurrence of '-' in the family name, it is
7051 replaced with '_'. (More than one occurrence of '-' means a
7052 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7053 p
= strchr (name
, '-');
7054 if (p
&& strchr (p
+ 1, '-') == NULL
)
7057 for (p
= name
; *p
; p
++)
7058 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7059 for some locales. */
7066 mac_to_x_fontname (name
, size
, style
, charset
)
7074 char xf
[256], *result
;
7077 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7081 strcpy(foundry
, "Apple");
7082 strcpy(family
, name
);
7085 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7086 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7087 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7089 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7090 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7091 for (p
= result
; *p
; p
++)
7092 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7093 for some locales. */
7100 /* Parse fully-specified and instantiated X11 font spec XF, and store
7101 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7102 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7103 caller must allocate at least 256 and 32 bytes respectively. For
7104 ordinary Mac fonts, the value stored to FAMILY should just be their
7105 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7106 intlfonts collection contain their charset designation in their
7107 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7108 types of font names are handled accordingly. */
7110 const int kDefaultFontSize
= 12;
7113 parse_x_font_name (xf
, family
, size
, style
, charset
)
7120 Str31 foundry
, weight
;
7121 int point_size
, avgwidth
;
7124 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7125 foundry
, family
, weight
, slant
, size
,
7126 &point_size
, &avgwidth
, charset
) != 8
7127 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7128 foundry
, family
, weight
, slant
, size
,
7129 &point_size
, &avgwidth
, charset
) != 8)
7135 *size
= point_size
/ 10;
7136 else if (avgwidth
> 0)
7137 *size
= avgwidth
/ 10;
7140 *size
= kDefaultFontSize
;
7143 if (strcmp (weight
, "bold") == 0)
7148 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7150 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7152 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7154 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7155 but take overlap into account. */
7156 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7157 memcpy (family
, foundry
, foundry_len
);
7158 family
[foundry_len
] = '-';
7159 family
[foundry_len
+ 1 + family_len
] = '-';
7160 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7166 for (p
= family
; *p
; p
++)
7167 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7168 for some locales. */
7177 add_font_name_table_entry (char *font_name
)
7179 if (font_name_table_size
== 0)
7181 font_name_table_size
= 256;
7182 font_name_table
= (char **)
7183 xmalloc (font_name_table_size
* sizeof (char *));
7185 else if (font_name_count
+ 1 >= font_name_table_size
)
7187 font_name_table_size
*= 2;
7188 font_name_table
= (char **)
7189 xrealloc (font_name_table
,
7190 font_name_table_size
* sizeof (char *));
7193 font_name_table
[font_name_count
++] = font_name
;
7197 add_mac_font_name (name
, size
, style
, charset
)
7201 const char *charset
;
7204 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7207 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7208 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7209 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7210 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7217 fm_style_to_face_attributes (fm_style
)
7218 FMFontStyle fm_style
;
7222 fm_style
&= (bold
| italic
);
7223 tem
= assq_no_quit (make_number (fm_style
),
7224 fm_style_face_attributes_alist
);
7228 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
7229 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
7230 fm_style_face_attributes_alist
=
7231 Fcons (Fcons (make_number (fm_style
), tem
),
7232 fm_style_face_attributes_alist
);
7238 /* Sets up the table font_name_table to contain the list of all fonts
7239 in the system the first time the table is used so that the Resource
7240 Manager need not be accessed every time this information is
7244 init_font_name_table ()
7246 #if TARGET_API_MAC_CARBON
7247 FMFontFamilyIterator ffi
;
7248 FMFontFamilyInstanceIterator ffii
;
7250 Lisp_Object text_encoding_info_alist
;
7251 struct gcpro gcpro1
;
7253 text_encoding_info_alist
= create_text_encoding_info_alist ();
7256 #if USE_CG_TEXT_DRAWING
7257 init_cg_text_anti_aliasing_threshold ();
7259 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7260 text_encoding_info_alist
)))
7263 struct Lisp_Hash_Table
*h
;
7265 ItemCount nfonts
, i
;
7266 ATSUFontID
*font_ids
= NULL
;
7272 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7273 make_float (DEFAULT_REHASH_SIZE
),
7274 make_float (DEFAULT_REHASH_THRESHOLD
),
7276 h
= XHASH_TABLE (atsu_font_id_hash
);
7278 err
= ATSUFontCount (&nfonts
);
7281 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7282 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7285 for (i
= 0; i
< nfonts
; i
++)
7287 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7288 kFontMacintoshPlatform
, kFontNoScript
,
7289 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
7292 name
= xmalloc (name_len
+ 1);
7293 name
[name_len
] = '\0';
7294 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7295 kFontMacintoshPlatform
, kFontNoScript
,
7296 kFontNoLanguage
, name_len
, name
,
7301 FMFontStyle style
= normal
;
7303 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
7304 family
= make_unibyte_string (name
, name_len
);
7305 FMGetFontFamilyInstanceFromFont (font_ids
[i
], &ff
, &style
);
7306 Fputhash ((font_ids
[i
] > MOST_POSITIVE_FIXNUM
7307 ? make_float (font_ids
[i
])
7308 : make_number (font_ids
[i
])),
7311 fm_style_to_face_attributes (style
))),
7312 Vmac_atsu_font_table
);
7314 && hash_lookup (h
, family
, &hash_code
) < 0)
7316 add_mac_font_name (name
, 0, normal
, "iso10646-1");
7317 hash_put (h
, family
, long_to_cons (font_ids
[i
]),
7328 /* Create a dummy instance iterator here to avoid creating and
7329 destroying it in the loop. */
7330 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7332 /* Create an iterator to enumerate the font families. */
7333 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7336 FMDisposeFontFamilyInstanceIterator (&ffii
);
7340 GCPRO1 (text_encoding_info_alist
);
7342 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7348 TextEncoding encoding
;
7349 TextEncodingBase sc
;
7350 Lisp_Object text_encoding_info
, family
;
7352 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7358 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7360 sc
= GetTextEncodingBase (encoding
);
7361 text_encoding_info
= assq_no_quit (make_number (sc
),
7362 text_encoding_info_alist
);
7363 if (NILP (text_encoding_info
))
7364 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7365 text_encoding_info_alist
);
7366 decode_mac_font_name (name
, sizeof (name
),
7367 XCAR (XCDR (text_encoding_info
)));
7368 family
= build_string (name
);
7369 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7371 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7372 fm_font_family_alist
);
7374 /* Point the instance iterator at the current font family. */
7375 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7378 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7381 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7383 if (size
> 0 || style
== normal
)
7384 for (; !NILP (rest
); rest
= XCDR (rest
))
7385 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7391 /* Dispose of the iterators. */
7392 FMDisposeFontFamilyIterator (&ffi
);
7393 FMDisposeFontFamilyInstanceIterator (&ffii
);
7394 #else /* !TARGET_API_MAC_CARBON */
7396 SInt16 fontnum
, old_fontnum
;
7397 int num_mac_fonts
= CountResources('FOND');
7399 Handle font_handle
, font_handle_2
;
7400 short id
, scriptcode
;
7403 struct FontAssoc
*fat
;
7404 struct AsscEntry
*assc_entry
;
7405 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7406 struct gcpro gcpro1
;
7408 GetPort (&port
); /* save the current font number used */
7409 old_fontnum
= port
->txFont
;
7411 text_encoding_info_alist
= create_text_encoding_info_alist ();
7413 GCPRO1 (text_encoding_info_alist
);
7415 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7417 font_handle
= GetIndResource ('FOND', i
);
7421 GetResInfo (font_handle
, &id
, &type
, name
);
7422 GetFNum (name
, &fontnum
);
7424 if (fontnum
== 0 || *name
== '.')
7428 scriptcode
= FontToScript (fontnum
);
7429 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7430 text_encoding_info_alist
);
7431 if (NILP (text_encoding_info
))
7432 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7433 text_encoding_info_alist
);
7434 decode_mac_font_name (name
, sizeof (name
),
7435 XCAR (XCDR (text_encoding_info
)));
7436 family
= build_string (name
);
7437 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7439 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7440 fm_font_family_alist
);
7443 HLock (font_handle
);
7445 if (GetResourceSizeOnDisk (font_handle
)
7446 >= sizeof (struct FamRec
))
7448 fat
= (struct FontAssoc
*) (*font_handle
7449 + sizeof (struct FamRec
));
7451 = (struct AsscEntry
*) (*font_handle
7452 + sizeof (struct FamRec
)
7453 + sizeof (struct FontAssoc
));
7455 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7457 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7459 for (; !NILP (rest
); rest
= XCDR (rest
))
7460 add_mac_font_name (name
, assc_entry
->fontSize
,
7461 assc_entry
->fontStyle
,
7462 SDATA (XCAR (rest
)));
7466 HUnlock (font_handle
);
7467 font_handle_2
= GetNextFOND (font_handle
);
7468 ReleaseResource (font_handle
);
7469 font_handle
= font_handle_2
;
7471 while (ResError () == noErr
&& font_handle
);
7476 TextFont (old_fontnum
);
7477 #endif /* !TARGET_API_MAC_CARBON */
7482 mac_clear_font_name_table ()
7486 for (i
= 0; i
< font_name_count
; i
++)
7487 xfree (font_name_table
[i
]);
7488 xfree (font_name_table
);
7489 font_name_table
= NULL
;
7490 font_name_table_size
= font_name_count
= 0;
7491 fm_font_family_alist
= Qnil
;
7495 enum xlfd_scalable_field_index
7497 XLFD_SCL_PIXEL_SIZE
,
7498 XLFD_SCL_POINT_SIZE
,
7503 static const int xlfd_scalable_fields
[] =
7512 mac_do_list_fonts (pattern
, maxnames
)
7513 const char *pattern
;
7517 Lisp_Object font_list
= Qnil
;
7518 struct xlfdpat
*pat
;
7521 int scl_val
[XLFD_SCL_LAST
], *val
;
7525 if (font_name_table
== NULL
) /* Initialize when first used. */
7526 init_font_name_table ();
7528 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7531 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7532 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7533 fonts are scaled according to the specified size. */
7536 field
= xlfd_scalable_fields
;
7544 if ('0' <= *ptr
&& *ptr
<= '9')
7546 *val
= *ptr
++ - '0';
7547 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7548 *val
= *val
* 10 + *ptr
++ - '0';
7555 ptr
= strchr (ptr
, '-');
7558 while (ptr
&& i
< 14);
7560 if (i
== 14 && ptr
== NULL
)
7562 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7563 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7564 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7565 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7567 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7568 scl_val
[XLFD_SCL_POINT_SIZE
] =
7569 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7570 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7572 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7573 scl_val
[XLFD_SCL_AVGWIDTH
] =
7574 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7575 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7579 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7581 pat
= xlfdpat_create (pattern
);
7585 exact
= xlfdpat_exact_p (pat
);
7587 for (i
= 0; i
< font_name_count
; i
++)
7589 if (xlfdpat_match (pat
, font_name_table
[i
]))
7591 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7592 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7595 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7596 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7598 int former_len
= ptr
- font_name_table
[i
];
7600 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7601 memcpy (scaled
, font_name_table
[i
], former_len
);
7602 sprintf (scaled
+ former_len
,
7603 "-%d-%d-72-72-m-%d-%s",
7604 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7605 scl_val
[XLFD_SCL_POINT_SIZE
],
7606 scl_val
[XLFD_SCL_AVGWIDTH
],
7607 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7609 if (xlfdpat_match (pat
, scaled
))
7611 font_list
= Fcons (build_string (scaled
), font_list
);
7613 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7621 xlfdpat_destroy (pat
);
7626 /* Return a list of names of available fonts matching PATTERN on frame F.
7628 Frame F null means we have not yet created any frame on Mac, and
7629 consult the first display in x_display_list. MAXNAMES sets a limit
7630 on how many fonts to match. */
7633 x_list_fonts (f
, pattern
, size
, maxnames
)
7635 Lisp_Object pattern
;
7638 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7639 struct mac_display_info
*dpyinfo
7640 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7642 xassert (size
<= 0);
7644 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7645 if (NILP (patterns
))
7646 patterns
= Fcons (pattern
, Qnil
);
7648 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7650 pattern
= XCAR (patterns
);
7652 if (!STRINGP (pattern
))
7655 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7656 key
= Fcons (pattern
, make_number (maxnames
));
7658 list
= Fassoc (key
, tem
);
7661 list
= Fcdr_safe (list
);
7662 /* We have a cashed list. Don't have to get the list again. */
7667 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7670 /* MAC_TODO: add code for matching outline fonts here */
7672 /* Now store the result in the cache. */
7673 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7674 Fcons (Fcons (key
, list
),
7675 XCAR (XCDR (dpyinfo
->name_list_element
))));
7678 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7687 /* Check that FONT is valid on frame F. It is if it can be found in F's
7691 x_check_font (f
, font
)
7696 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7698 xassert (font
!= NULL
);
7700 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7701 if (dpyinfo
->font_table
[i
].name
7702 && font
== dpyinfo
->font_table
[i
].font
)
7705 xassert (i
< dpyinfo
->n_fonts
);
7708 #endif /* GLYPH_DEBUG != 0 */
7710 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7711 Note: There are (broken) X fonts out there with invalid XFontStruct
7712 min_bounds contents. For example, handa@etl.go.jp reports that
7713 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7714 have font->min_bounds.width == 0. */
7717 x_font_min_bounds (font
, w
, h
)
7718 MacFontStruct
*font
;
7721 *h
= FONT_HEIGHT (font
);
7722 *w
= font
->min_bounds
.width
;
7726 /* Compute the smallest character width and smallest font height over
7727 all fonts available on frame F. Set the members smallest_char_width
7728 and smallest_font_height in F's x_display_info structure to
7729 the values computed. Value is non-zero if smallest_font_height or
7730 smallest_char_width become smaller than they were before. */
7733 x_compute_min_glyph_bounds (f
)
7737 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7738 MacFontStruct
*font
;
7739 int old_width
= dpyinfo
->smallest_char_width
;
7740 int old_height
= dpyinfo
->smallest_font_height
;
7742 dpyinfo
->smallest_font_height
= 100000;
7743 dpyinfo
->smallest_char_width
= 100000;
7745 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7746 if (dpyinfo
->font_table
[i
].name
)
7748 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7751 font
= (MacFontStruct
*) fontp
->font
;
7752 xassert (font
!= (MacFontStruct
*) ~0);
7753 x_font_min_bounds (font
, &w
, &h
);
7755 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7756 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7759 xassert (dpyinfo
->smallest_char_width
> 0
7760 && dpyinfo
->smallest_font_height
> 0);
7762 return (dpyinfo
->n_fonts
== 1
7763 || dpyinfo
->smallest_char_width
< old_width
7764 || dpyinfo
->smallest_font_height
< old_height
);
7768 /* Determine whether given string is a fully-specified XLFD: all 14
7769 fields are present, none is '*'. */
7772 is_fully_specified_xlfd (p
)
7781 for (i
= 0; i
< 13; i
++)
7783 q
= strchr (p
+ 1, '-');
7786 if (q
- p
== 2 && *(p
+ 1) == '*')
7791 if (strchr (p
+ 1, '-') != NULL
)
7794 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7801 /* mac_load_query_font creates and returns an internal representation
7802 for a font in a MacFontStruct struct. There is really no concept
7803 corresponding to "loading" a font on the Mac. But we check its
7804 existence and find the font number and all other information for it
7805 and store them in the returned MacFontStruct. */
7807 static MacFontStruct
*
7808 mac_load_query_font (f
, fontname
)
7818 static ATSUFontID font_id
;
7819 ATSUStyle mac_style
= NULL
;
7822 #if TARGET_API_MAC_CARBON
7823 TextEncoding encoding
;
7828 MacFontStruct
*font
;
7829 XCharStruct
*space_bounds
= NULL
, *pcm
;
7831 if (is_fully_specified_xlfd (fontname
))
7835 Lisp_Object matched_fonts
;
7837 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7838 if (NILP (matched_fonts
))
7840 name
= SDATA (XCAR (matched_fonts
));
7843 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7847 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7850 static const ATSUAttributeTag tags
[] =
7851 {kATSUFontTag
, kATSUSizeTag
,
7852 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7853 static const ByteCount sizes
[] =
7854 {sizeof (ATSUFontID
), sizeof (Fixed
),
7855 sizeof (Boolean
), sizeof (Boolean
)};
7856 static Fixed size_fixed
;
7857 static Boolean bold_p
, italic_p
;
7858 static const ATSUAttributeValuePtr values
[] =
7859 {&font_id
, &size_fixed
,
7860 &bold_p
, &italic_p
};
7861 static const ATSUFontFeatureType types
[] =
7862 {kAllTypographicFeaturesType
, kDiacriticsType
};
7863 static const ATSUFontFeatureSelector selectors
[] =
7864 {kAllTypeFeaturesOffSelector
, kDecomposeDiacriticsSelector
};
7865 Lisp_Object font_id_cons
;
7868 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7869 atsu_font_id_hash
, Qnil
);
7870 if (NILP (font_id_cons
))
7872 font_id
= cons_to_long (font_id_cons
);
7873 size_fixed
= Long2Fix (size
);
7874 bold_p
= (fontface
& bold
) != 0;
7875 italic_p
= (fontface
& italic
) != 0;
7876 err
= ATSUCreateStyle (&mac_style
);
7879 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7883 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7884 tags
, sizes
, values
);
7887 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
7890 scriptcode
= kTextEncodingMacUnicode
;
7895 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7899 fontnum
= XINT (XCDR (tmp
));
7900 #if TARGET_API_MAC_CARBON
7901 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7903 scriptcode
= GetTextEncodingBase (encoding
);
7905 scriptcode
= FontToScript (fontnum
);
7909 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7911 font
->mac_fontnum
= fontnum
;
7912 font
->mac_fontsize
= size
;
7913 font
->mac_fontface
= fontface
;
7914 font
->mac_scriptcode
= scriptcode
;
7916 font
->mac_style
= mac_style
;
7917 #if USE_CG_TEXT_DRAWING
7918 font
->cg_font
= NULL
;
7919 font
->cg_glyphs
= NULL
;
7923 /* Apple Japanese (SJIS) font is listed as both
7924 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7925 (Roman script) in init_font_name_table (). The latter should be
7926 treated as a one-byte font. */
7927 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7928 font
->mac_scriptcode
= smRoman
;
7930 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7933 if (font
->mac_style
)
7938 font
->min_byte1
= 0;
7939 font
->max_byte1
= 0xff;
7940 font
->min_char_or_byte2
= 0;
7941 font
->max_char_or_byte2
= 0xff;
7943 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
7944 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
7945 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
7946 pcm_init (font
->bounds
.rows
[0], 0x100);
7948 #if USE_CG_TEXT_DRAWING
7952 ATSFontRef ats_font
;
7954 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
7956 /* Use CG text drawing if italic/bold is not synthesized. */
7957 if (err
== noErr
&& style
== fontface
)
7959 ats_font
= FMGetATSFontRefFromFont (font_id
);
7960 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7966 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7967 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7970 space_bounds
= font
->bounds
.rows
[0] + 0x20;
7971 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7972 &font
->ascent
, &font
->descent
,
7974 #if USE_CG_TEXT_DRAWING
7975 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7982 || space_bounds
->width
<= 0 || FONT_HEIGHT (font
) <= 0)
7984 mac_unload_font (&one_mac_display_info
, font
);
7988 pcm
= font
->bounds
.rows
[0];
7989 for (c
= 0x21; c
<= 0xff; c
++)
7992 /* Soft hyphen is not supported in ATSUI. */
8000 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
8001 #if USE_CG_TEXT_DRAWING
8002 (font
->cg_glyphs
? font
->cg_glyphs
+ c
8009 #if USE_CG_TEXT_DRAWING
8010 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
8012 /* Don't use CG text drawing if font substitution occurs in
8013 ASCII or Latin-1 characters. */
8014 CGFontRelease (font
->cg_font
);
8015 font
->cg_font
= NULL
;
8016 xfree (font
->cg_glyphs
);
8017 font
->cg_glyphs
= NULL
;
8025 FontInfo the_fontinfo
;
8026 int is_two_byte_font
;
8029 mac_prepare_for_quickdraw (f
);
8031 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
8035 TextFace (fontface
);
8037 GetFontInfo (&the_fontinfo
);
8039 font
->ascent
= the_fontinfo
.ascent
;
8040 font
->descent
= the_fontinfo
.descent
;
8042 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8043 || font
->mac_scriptcode
== smTradChinese
8044 || font
->mac_scriptcode
== smSimpChinese
8045 || font
->mac_scriptcode
== smKorean
);
8047 if (is_two_byte_font
)
8051 font
->min_byte1
= 0xa1;
8052 font
->max_byte1
= 0xfe;
8053 font
->min_char_or_byte2
= 0xa1;
8054 font
->max_char_or_byte2
= 0xfe;
8056 /* Use the width of an "ideographic space" of that font
8057 because the_fontinfo.widMax returns the wrong width for
8059 switch (font
->mac_scriptcode
)
8062 font
->min_byte1
= 0x81;
8063 font
->max_byte1
= 0xfc;
8064 font
->min_char_or_byte2
= 0x40;
8065 font
->max_char_or_byte2
= 0xfc;
8066 char_width
= StringWidth("\p\x81\x40");
8069 font
->min_char_or_byte2
= 0x40;
8070 char_width
= StringWidth("\p\xa1\x40");
8073 char_width
= StringWidth("\p\xa1\xa1");
8076 char_width
= StringWidth("\p\xa1\xa1");
8080 font
->bounds
.per_char
= NULL
;
8082 if (fontface
& italic
)
8083 font
->max_bounds
.rbearing
= char_width
+ 1;
8085 font
->max_bounds
.rbearing
= char_width
;
8086 font
->max_bounds
.lbearing
= 0;
8087 font
->max_bounds
.width
= char_width
;
8088 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8089 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8091 font
->min_bounds
= font
->max_bounds
;
8097 font
->min_byte1
= font
->max_byte1
= 0;
8098 font
->min_char_or_byte2
= 0x20;
8099 font
->max_char_or_byte2
= 0xff;
8101 font
->bounds
.per_char
=
8102 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8103 bzero (font
->bounds
.per_char
,
8104 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8106 space_bounds
= font
->bounds
.per_char
;
8107 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
8108 space_bounds
, NULL
);
8110 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8111 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8119 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8120 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8123 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8125 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8127 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8129 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8131 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
8134 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8136 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8138 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8140 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8142 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
8147 font
->mac_style
== NULL
&&
8149 font
->max_bounds
.width
== font
->min_bounds
.width
8150 && font
->min_bounds
.lbearing
>= 0
8151 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8153 /* Fixed width and no overhangs. */
8154 xfree (font
->bounds
.per_char
);
8155 font
->bounds
.per_char
= NULL
;
8159 #if !defined (MAC_OS8) || USE_ATSUI
8160 /* AppKit and WebKit do some adjustment to the heights of Courier,
8161 Helvetica, and Times. This only works on the environments where
8162 srcCopy text transfer mode is never used. */
8164 #ifdef MAC_OS8 /* implies USE_ATSUI */
8167 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8168 || strcmp (family
, "times") == 0))
8169 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8177 mac_unload_font (dpyinfo
, font
)
8178 struct mac_display_info
*dpyinfo
;
8181 xfree (font
->full_name
);
8183 if (font
->mac_style
)
8187 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8188 if (font
->bounds
.rows
[i
])
8189 xfree (font
->bounds
.rows
[i
]);
8190 xfree (font
->bounds
.rows
);
8191 ATSUDisposeStyle (font
->mac_style
);
8195 if (font
->bounds
.per_char
)
8196 xfree (font
->bounds
.per_char
);
8197 #if USE_CG_TEXT_DRAWING
8199 CGFontRelease (font
->cg_font
);
8200 if (font
->cg_glyphs
)
8201 xfree (font
->cg_glyphs
);
8207 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8208 pointer to the structure font_info while allocating it dynamically.
8209 If SIZE is 0, load any size of font.
8210 If loading is failed, return NULL. */
8213 x_load_font (f
, fontname
, size
)
8215 register char *fontname
;
8218 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8219 Lisp_Object font_names
;
8221 /* Get a list of all the fonts that match this name. Once we
8222 have a list of matching fonts, we compare them against the fonts
8223 we already have by comparing names. */
8224 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8226 if (!NILP (font_names
))
8231 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8232 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8233 if (dpyinfo
->font_table
[i
].name
8234 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8235 SDATA (XCAR (tail
)))
8236 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8237 SDATA (XCAR (tail
)))))
8238 return (dpyinfo
->font_table
+ i
);
8243 /* Load the font and add it to the table. */
8245 struct MacFontStruct
*font
;
8246 struct font_info
*fontp
;
8249 fontname
= (char *) SDATA (XCAR (font_names
));
8252 font
= mac_load_query_font (f
, fontname
);
8257 /* Find a free slot in the font table. */
8258 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8259 if (dpyinfo
->font_table
[i
].name
== NULL
)
8262 /* If no free slot found, maybe enlarge the font table. */
8263 if (i
== dpyinfo
->n_fonts
8264 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8267 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8268 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8270 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8273 fontp
= dpyinfo
->font_table
+ i
;
8274 if (i
== dpyinfo
->n_fonts
)
8277 /* Now fill in the slots of *FONTP. */
8279 bzero (fontp
, sizeof (*fontp
));
8281 fontp
->font_idx
= i
;
8282 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8283 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8285 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8287 /* Fixed width font. */
8288 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8295 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8296 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8298 fontp
->space_width
= pcm
->width
;
8300 fontp
->space_width
= FONT_WIDTH (font
);
8304 int width
= pcm
->width
;
8305 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8306 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8307 width
+= pcm
->width
;
8308 fontp
->average_width
= width
/ 95;
8311 fontp
->average_width
= FONT_WIDTH (font
);
8314 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8315 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8317 fontp
->size
= font
->max_bounds
.width
;
8318 fontp
->height
= FONT_HEIGHT (font
);
8320 /* For some font, ascent and descent in max_bounds field is
8321 larger than the above value. */
8322 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8323 if (max_height
> fontp
->height
)
8324 fontp
->height
= max_height
;
8327 /* The slot `encoding' specifies how to map a character
8328 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8329 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8330 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8331 2:0xA020..0xFF7F). For the moment, we don't know which charset
8332 uses this font. So, we set information in fontp->encoding[1]
8333 which is never used by any charset. If mapping can't be
8334 decided, set FONT_ENCODING_NOT_DECIDED. */
8335 if (font
->mac_scriptcode
== smJapanese
)
8336 fontp
->encoding
[1] = 4;
8340 = (font
->max_byte1
== 0
8342 ? (font
->min_char_or_byte2
< 0x80
8343 ? (font
->max_char_or_byte2
< 0x80
8344 ? 0 /* 0x20..0x7F */
8345 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8346 : 1) /* 0xA0..0xFF */
8348 : (font
->min_byte1
< 0x80
8349 ? (font
->max_byte1
< 0x80
8350 ? (font
->min_char_or_byte2
< 0x80
8351 ? (font
->max_char_or_byte2
< 0x80
8352 ? 0 /* 0x2020..0x7F7F */
8353 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8354 : 3) /* 0x20A0..0x7FFF */
8355 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8356 : (font
->min_char_or_byte2
< 0x80
8357 ? (font
->max_char_or_byte2
< 0x80
8358 ? 2 /* 0xA020..0xFF7F */
8359 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8360 : 1))); /* 0xA0A0..0xFFFF */
8363 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8364 fontp
->baseline_offset
8365 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8366 ? (long) value
: 0);
8367 fontp
->relative_compose
8368 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8369 ? (long) value
: 0);
8370 fontp
->default_ascent
8371 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8372 ? (long) value
: 0);
8374 fontp
->baseline_offset
= 0;
8375 fontp
->relative_compose
= 0;
8376 fontp
->default_ascent
= 0;
8379 /* Set global flag fonts_changed_p to non-zero if the font loaded
8380 has a character with a smaller width than any other character
8381 before, or if the font loaded has a smaller height than any
8382 other font loaded before. If this happens, it will make a
8383 glyph matrix reallocation necessary. */
8384 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8391 /* Return a pointer to struct font_info of a font named FONTNAME for
8392 frame F. If no such font is loaded, return NULL. */
8395 x_query_font (f
, fontname
)
8397 register char *fontname
;
8399 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8402 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8403 if (dpyinfo
->font_table
[i
].name
8404 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8405 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8406 return (dpyinfo
->font_table
+ i
);
8411 /* Find a CCL program for a font specified by FONTP, and set the member
8412 `encoder' of the structure. */
8415 x_find_ccl_program (fontp
)
8416 struct font_info
*fontp
;
8418 Lisp_Object list
, elt
;
8420 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8424 && STRINGP (XCAR (elt
))
8425 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8431 struct ccl_program
*ccl
8432 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8434 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8437 fontp
->font_encoder
= ccl
;
8441 #if USE_MAC_FONT_PANEL
8442 /* Whether Font Panel has been shown before. The first call to font
8443 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8444 slow. This variable is used for deferring such a call as much as
8446 static int font_panel_shown_p
= 0;
8449 mac_font_panel_visible_p ()
8451 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8455 mac_show_hide_font_panel ()
8457 font_panel_shown_p
= 1;
8459 return FPShowHideFontPanel ();
8463 mac_set_font_info_for_selection (f
, face_id
, c
)
8468 EventTargetRef target
= NULL
;
8469 XFontStruct
*font
= NULL
;
8471 if (!mac_font_panel_visible_p ())
8476 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8478 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8482 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8483 face
= FACE_FROM_ID (f
, face_id
);
8489 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8492 if (font
->mac_fontnum
!= -1)
8494 FontSelectionQDStyle qd_style
;
8496 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8497 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8498 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8499 qd_style
.size
= font
->mac_fontsize
;
8500 qd_style
.hasColor
= false;
8502 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8503 1, &qd_style
, target
);
8506 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8507 1, &font
->mac_style
, target
);
8515 /* The Mac Event loop code */
8517 #if !TARGET_API_MAC_CARBON
8519 #include <Quickdraw.h>
8520 #include <Balloons.h>
8521 #include <Devices.h>
8523 #include <Gestalt.h>
8525 #include <Processes.h>
8527 #include <ToolUtils.h>
8528 #include <TextUtils.h>
8529 #include <Dialogs.h>
8532 #include <Resources.h>
8537 #endif /* ! TARGET_API_MAC_CARBON */
8542 #define WINDOW_RESOURCE 128
8543 #define TERM_WINDOW_RESOURCE 129
8545 #define DEFAULT_NUM_COLS 80
8547 #define MIN_DOC_SIZE 64
8548 #define MAX_DOC_SIZE 32767
8550 #define EXTRA_STACK_ALLOC (256 * 1024)
8552 #define ARGV_STRING_LIST_ID 129
8553 #define ABOUT_ALERT_ID 128
8554 #define RAM_TOO_LARGE_ALERT_ID 129
8556 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8557 Lisp_Object Qreverse
;
8560 /* Modifier associated with the control key, or nil to ignore. */
8561 Lisp_Object Vmac_control_modifier
;
8563 /* Modifier associated with the option key, or nil to ignore. */
8564 Lisp_Object Vmac_option_modifier
;
8566 /* Modifier associated with the command key, or nil to ignore. */
8567 Lisp_Object Vmac_command_modifier
;
8569 /* Modifier associated with the function key, or nil to ignore. */
8570 Lisp_Object Vmac_function_modifier
;
8572 /* True if the option and command modifiers should be used to emulate
8573 a three button mouse */
8574 Lisp_Object Vmac_emulate_three_button_mouse
;
8576 #if USE_CARBON_EVENTS
8577 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8578 mouse-2, instead of mouse-3. */
8579 int mac_wheel_button_is_mouse_2
;
8581 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8582 for processing before Emacs sees it. */
8583 int mac_pass_command_to_system
;
8585 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8586 for processing before Emacs sees it. */
8587 int mac_pass_control_to_system
;
8590 /* Points to the variable `inev' in the function XTread_socket. It is
8591 used for passing an input event to the function back from
8592 Carbon/Apple event handlers. */
8593 static struct input_event
*read_socket_inev
= NULL
;
8595 Point saved_menu_event_location
;
8598 #if USE_CARBON_EVENTS
8599 static Lisp_Object Qhi_command
;
8601 extern Lisp_Object Qwindow
;
8602 static Lisp_Object Qtoolbar_switch_mode
;
8604 #if USE_MAC_FONT_PANEL
8605 extern Lisp_Object Qfont
;
8606 static Lisp_Object Qpanel_closed
, Qselection
;
8609 static TSMDocumentID tsm_document_id
;
8610 static Lisp_Object Qtext_input
;
8611 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8612 static Lisp_Object Vmac_ts_active_input_overlay
;
8613 extern Lisp_Object Qbefore_string
;
8614 static Lisp_Object Vmac_ts_script_language_on_focus
;
8615 static Lisp_Object saved_ts_script_language_on_focus
;
8616 static ScriptLanguageRecord saved_ts_language
;
8617 static Component saved_ts_component
;
8620 extern int mac_ready_for_apple_events
;
8621 extern Lisp_Object Qundefined
;
8622 extern void init_apple_event_handler
P_ ((void));
8623 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8624 Lisp_Object
*, Lisp_Object
*,
8626 extern OSErr init_coercion_handler
P_ ((void));
8629 OSErr install_drag_handler
P_ ((WindowRef
));
8630 void remove_drag_handler
P_ ((WindowRef
));
8632 #if USE_CARBON_EVENTS
8634 extern void init_service_handler ();
8635 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8637 /* Window Event Handler */
8638 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8641 OSStatus
install_window_handler (WindowPtr
);
8643 extern void init_emacs_passwd_dir ();
8644 extern int emacs_main (int, char **, char **);
8646 extern void initialize_applescript();
8647 extern void terminate_applescript();
8649 /* Table for translating Mac keycode to X keysym values. Contributed
8651 Mapping for special keys is now identical to that in Apple X11
8652 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8653 on the right of the Cmd key on laptops, and fn + `enter' (->
8655 static const unsigned char keycode_to_xkeysym_table
[] = {
8656 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8657 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8658 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8660 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8661 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8662 /*0x38*/ 0, 0, 0, 0,
8663 /*0x3C*/ 0, 0, 0, 0,
8665 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8666 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8667 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8668 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8670 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8671 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8672 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8673 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8675 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8676 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8677 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8678 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8680 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8681 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8682 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8683 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8687 /* Table for translating Mac keycode with the laptop `fn' key to that
8688 without it. Destination symbols in comments are keys on US
8689 keyboard, and they may not be the same on other types of keyboards.
8690 If the destination is identical to the source (f1 ... f12), it
8691 doesn't map `fn' key to a modifier. */
8692 static const unsigned char fn_keycode_to_keycode_table
[] = {
8693 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8694 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8695 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8697 /*0x30*/ 0, 0, 0, 0,
8698 /*0x34*/ 0, 0, 0, 0,
8699 /*0x38*/ 0, 0, 0, 0,
8700 /*0x3C*/ 0, 0, 0, 0,
8702 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8703 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8704 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8705 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8707 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8708 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8709 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8710 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8712 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8713 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8714 /*0x68*/ 0, 0, 0, 0,
8715 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8717 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
8718 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8719 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
8722 #endif /* MAC_OSX */
8725 #if USE_CARBON_EVENTS
8726 mac_to_emacs_modifiers (UInt32 mods
)
8728 mac_to_emacs_modifiers (EventModifiers mods
)
8731 unsigned int result
= 0;
8732 if (mods
& shiftKey
)
8733 result
|= shift_modifier
;
8735 /* Deactivated to simplify configuration:
8736 if Vmac_option_modifier is non-NIL, we fully process the Option
8737 key. Otherwise, we only process it if an additional Ctrl or Command
8738 is pressed. That way the system may convert the character to a
8740 if ((mods & optionKey) &&
8741 (( !NILP(Vmac_option_modifier) ||
8742 ((mods & cmdKey) || (mods & controlKey))))) */
8744 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8745 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8747 result
|= XUINT(val
);
8749 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8750 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8752 result
|= XUINT(val
);
8754 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8755 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8757 result
|= XUINT(val
);
8761 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8762 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8764 result
|= XUINT(val
);
8772 mac_get_emulated_btn ( UInt32 modifiers
)
8775 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8776 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8777 if (modifiers
& cmdKey
)
8778 result
= cmdIs3
? 2 : 1;
8779 else if (modifiers
& optionKey
)
8780 result
= cmdIs3
? 1 : 2;
8785 #if USE_CARBON_EVENTS
8786 /* Obtains the event modifiers from the event ref and then calls
8787 mac_to_emacs_modifiers. */
8789 mac_event_to_emacs_modifiers (EventRef eventRef
)
8792 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8793 sizeof (UInt32
), NULL
, &mods
);
8794 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8795 GetEventClass(eventRef
) == kEventClassMouse
)
8797 mods
&= ~(optionKey
| cmdKey
);
8799 return mac_to_emacs_modifiers (mods
);
8802 /* Given an event ref, return the code to use for the mouse button
8803 code in the emacs input_event. */
8805 mac_get_mouse_btn (EventRef ref
)
8807 EventMouseButton result
= kEventMouseButtonPrimary
;
8808 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8809 sizeof (EventMouseButton
), NULL
, &result
);
8812 case kEventMouseButtonPrimary
:
8813 if (NILP (Vmac_emulate_three_button_mouse
))
8817 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8818 sizeof (UInt32
), NULL
, &mods
);
8819 return mac_get_emulated_btn(mods
);
8821 case kEventMouseButtonSecondary
:
8822 return mac_wheel_button_is_mouse_2
? 2 : 1;
8823 case kEventMouseButtonTertiary
:
8824 case 4: /* 4 is the number for the mouse wheel button */
8825 return mac_wheel_button_is_mouse_2
? 1 : 2;
8831 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8832 events. However the click of the mouse wheel is not converted to a
8833 mouseDown or mouseUp event. Likewise for dead key down events.
8834 This calls ConvertEventRef, but then checks to see if it is a mouse
8835 up/down, or a dead key down carbon event that has not been
8836 converted, and if so, converts it by hand (to be picked up in the
8837 XTread_socket loop). */
8838 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8841 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8846 switch (GetEventClass (eventRef
))
8848 case kEventClassMouse
:
8849 switch (GetEventKind (eventRef
))
8851 case kEventMouseDown
:
8852 eventRec
->what
= mouseDown
;
8857 eventRec
->what
= mouseUp
;
8866 case kEventClassKeyboard
:
8867 switch (GetEventKind (eventRef
))
8869 case kEventRawKeyDown
:
8871 unsigned char char_codes
;
8874 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
8875 typeChar
, NULL
, sizeof (char),
8878 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
8879 typeUInt32
, NULL
, sizeof (UInt32
),
8883 eventRec
->what
= keyDown
;
8884 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8901 /* Need where and when. */
8904 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8905 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8906 /* Use two step process because new event modifiers are 32-bit
8907 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8908 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8909 NULL
, sizeof (UInt32
), NULL
, &mods
);
8910 eventRec
->modifiers
= mods
;
8912 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8924 Handle menubar_handle
;
8925 MenuHandle menu_handle
;
8927 menubar_handle
= GetNewMBar (128);
8928 if(menubar_handle
== NULL
)
8930 SetMenuBar (menubar_handle
);
8933 #if !TARGET_API_MAC_CARBON
8934 menu_handle
= GetMenuHandle (M_APPLE
);
8935 if(menu_handle
!= NULL
)
8936 AppendResMenu (menu_handle
,'DRVR');
8944 do_init_managers (void)
8946 #if !TARGET_API_MAC_CARBON
8947 InitGraf (&qd
.thePort
);
8949 FlushEvents (everyEvent
, 0);
8954 #endif /* !TARGET_API_MAC_CARBON */
8957 #if !TARGET_API_MAC_CARBON
8958 /* set up some extra stack space for use by emacs */
8959 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8961 /* MaxApplZone must be called for AppleScript to execute more
8962 complicated scripts */
8965 #endif /* !TARGET_API_MAC_CARBON */
8969 do_check_ram_size (void)
8971 SInt32 physical_ram_size
, logical_ram_size
;
8973 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8974 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8975 || physical_ram_size
> (1 << VALBITS
)
8976 || logical_ram_size
> (1 << VALBITS
))
8978 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8982 #endif /* MAC_OS8 */
8985 do_window_update (WindowPtr win
)
8987 struct frame
*f
= mac_window_to_frame (win
);
8991 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8993 if (win
!= tip_window
)
8995 if (f
->async_visible
== 0)
8997 /* Update events may occur when a frame gets iconified. */
8999 f
->async_visible
= 1;
9000 f
->async_iconified
= 0;
9001 SET_FRAME_GARBAGED (f
);
9007 #if TARGET_API_MAC_CARBON
9008 RgnHandle region
= NewRgn ();
9010 GetPortVisibleRegion (GetWindowPort (win
), region
);
9011 GetRegionBounds (region
, &r
);
9012 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9013 UpdateControls (win
, region
);
9014 DisposeRgn (region
);
9016 r
= (*win
->visRgn
)->rgnBBox
;
9017 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9018 UpdateControls (win
, win
->visRgn
);
9027 is_emacs_window (WindowPtr win
)
9029 Lisp_Object tail
, frame
;
9034 FOR_EACH_FRAME (tail
, frame
)
9035 if (FRAME_MAC_P (XFRAME (frame
)))
9036 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9047 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9049 err
= ActivateTSMDocument (tsm_document_id
);
9053 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9054 && EQ (saved_ts_script_language_on_focus
, Qt
))
9055 slptr
= &saved_ts_language
;
9056 else if (CONSP (Vmac_ts_script_language_on_focus
)
9057 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9058 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9059 && CONSP (saved_ts_script_language_on_focus
)
9060 && EQ (XCAR (saved_ts_script_language_on_focus
),
9061 XCAR (Vmac_ts_script_language_on_focus
))
9062 && EQ (XCDR (saved_ts_script_language_on_focus
),
9063 XCDR (Vmac_ts_script_language_on_focus
)))
9065 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9066 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9073 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9074 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
9075 kKeyboardInputMethodClass
);
9077 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
9080 err
= SetTextServiceLanguage (slptr
);
9082 /* Seems to be needed on Mac OS X 10.2. */
9084 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
9094 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9096 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
9098 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
9100 err
= GetTextServiceLanguage (&saved_ts_language
);
9102 slptr
= &saved_ts_language
;
9104 else if (CONSP (Vmac_ts_script_language_on_focus
)
9105 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9106 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
9108 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9109 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9115 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9116 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
9117 kKeyboardInputMethodClass
);
9119 GetDefaultInputMethod (&saved_ts_component
, slptr
);
9123 err
= DeactivateTSMDocument (tsm_document_id
);
9129 #if !TARGET_API_MAC_CARBON
9131 do_apple_menu (SInt16 menu_item
)
9134 SInt16 da_driver_refnum
;
9136 if (menu_item
== I_ABOUT
)
9137 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9140 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9141 da_driver_refnum
= OpenDeskAcc (item_name
);
9144 #endif /* !TARGET_API_MAC_CARBON */
9146 /* Handle drags in size box. Based on code contributed by Ben
9147 Mesander and IM - Window Manager A. */
9150 do_grow_window (w
, e
)
9152 const EventRecord
*e
;
9155 int rows
, columns
, width
, height
;
9156 struct frame
*f
= mac_window_to_frame (w
);
9157 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
9158 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
9159 #if TARGET_API_MAC_CARBON
9165 if (size_hints
->flags
& PMinSize
)
9167 min_width
= size_hints
->min_width
;
9168 min_height
= size_hints
->min_height
;
9170 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9172 #if TARGET_API_MAC_CARBON
9173 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
9175 height
= new_rect
.bottom
- new_rect
.top
;
9176 width
= new_rect
.right
- new_rect
.left
;
9178 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9179 /* see if it really changed size */
9182 height
= HiWord (grow_size
);
9183 width
= LoWord (grow_size
);
9186 if (width
!= FRAME_PIXEL_WIDTH (f
)
9187 || height
!= FRAME_PIXEL_HEIGHT (f
))
9189 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9190 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9192 x_set_window_size (f
, 0, columns
, rows
);
9197 #if TARGET_API_MAC_CARBON
9199 mac_get_ideal_size (f
)
9202 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9203 WindowPtr w
= FRAME_MAC_WINDOW (f
);
9206 int height
, width
, columns
, rows
;
9208 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9209 ideal_size
.v
= dpyinfo
->height
;
9210 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
9211 /* Adjust the standard size according to character boundaries. */
9212 width
= standard_rect
.right
- standard_rect
.left
;
9213 height
= standard_rect
.bottom
- standard_rect
.top
;
9214 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9215 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9216 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9217 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9223 /* Handle clicks in zoom box. Calculation of "standard state" based
9224 on code in IM - Window Manager A and code contributed by Ben
9225 Mesander. The standard state of an Emacs window is 80-characters
9226 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9229 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9231 Rect zoom_rect
, port_rect
;
9233 struct frame
*f
= mac_window_to_frame (w
);
9234 #if TARGET_API_MAC_CARBON
9235 Point ideal_size
= mac_get_ideal_size (f
);
9237 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9238 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
9239 && port_rect
.left
== zoom_rect
.left
9240 && port_rect
.top
== zoom_rect
.top
)
9241 zoom_in_or_out
= inZoomIn
;
9243 zoom_in_or_out
= inZoomOut
;
9246 mac_clear_window (f
);
9248 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
9249 #else /* not TARGET_API_MAC_CARBON */
9252 int w_title_height
, rows
;
9253 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9255 GetPort (&save_port
);
9257 SetPortWindowPort (w
);
9259 /* Clear window to avoid flicker. */
9260 EraseRect (&(w
->portRect
));
9261 if (zoom_in_or_out
== inZoomOut
)
9263 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9264 LocalToGlobal (&top_left
);
9266 /* calculate height of window's title bar */
9267 w_title_height
= top_left
.v
- 1
9268 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9270 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9271 zoom_rect
= qd
.screenBits
.bounds
;
9272 zoom_rect
.top
+= w_title_height
;
9273 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9275 zoom_rect
.right
= zoom_rect
.left
9276 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9278 /* Adjust the standard size according to character boundaries. */
9279 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9281 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9283 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9287 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9289 SetPort (save_port
);
9290 #endif /* not TARGET_API_MAC_CARBON */
9292 #if !USE_CARBON_EVENTS
9293 /* retrieve window size and update application values */
9294 #if TARGET_API_MAC_CARBON
9295 GetWindowPortBounds (w
, &port_rect
);
9297 port_rect
= w
->portRect
;
9299 height
= port_rect
.bottom
- port_rect
.top
;
9300 width
= port_rect
.right
- port_rect
.left
;
9302 mac_handle_size_change (f
, width
, height
);
9303 mac_handle_origin_change (f
);
9308 mac_store_apple_event (class, id
, desc
)
9309 Lisp_Object
class, id
;
9312 struct input_event buf
;
9316 buf
.kind
= MAC_APPLE_EVENT
;
9319 XSETFRAME (buf
.frame_or_window
,
9320 mac_focus_frame (&one_mac_display_info
));
9321 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9322 is safe to use them during read_socket_hook. */
9323 buf
.arg
= mac_aedesc_to_lisp (desc
);
9324 kbd_buffer_store_event (&buf
);
9327 #if TARGET_API_MAC_CARBON
9329 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9330 event
, num_params
, names
, types
)
9333 Lisp_Object class_key
, id_key
;
9336 const EventParamName
*names
;
9337 const EventParamType
*types
;
9339 OSStatus err
= eventNotHandledErr
;
9340 Lisp_Object binding
;
9342 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9343 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9345 if (INTEGERP (binding
))
9346 err
= XINT (binding
);
9349 AppleEvent apple_event
;
9350 err
= create_apple_event_from_event_ref (event
, num_params
,
9355 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9356 AEDisposeDesc (&apple_event
);
9357 /* Post a harmless event so as to wake up from
9358 ReceiveNextEvent. */
9359 mac_post_mouse_moved_event ();
9368 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9374 struct input_event buf
;
9378 buf
.kind
= DRAG_N_DROP_EVENT
;
9379 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9380 buf
.timestamp
= TickCount () * (1000 / 60);
9381 XSETINT (buf
.x
, mouse_pos
.h
);
9382 XSETINT (buf
.y
, mouse_pos
.v
);
9383 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9384 buf
.arg
= mac_aedesc_to_lisp (desc
);
9385 kbd_buffer_store_event (&buf
);
9389 #if USE_CARBON_EVENTS
9390 static pascal OSStatus
9391 mac_handle_command_event (next_handler
, event
, data
)
9392 EventHandlerCallRef next_handler
;
9396 OSStatus result
, err
;
9398 static const EventParamName names
[] =
9399 {kEventParamDirectObject
, kEventParamKeyModifiers
};
9400 static const EventParamType types
[] =
9401 {typeHICommand
, typeUInt32
};
9402 int num_params
= sizeof (names
) / sizeof (names
[0]);
9404 result
= CallNextEventHandler (next_handler
, event
);
9405 if (result
!= eventNotHandledErr
)
9408 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9409 NULL
, sizeof (HICommand
), NULL
, &command
);
9411 if (err
!= noErr
|| command
.commandID
== 0)
9412 return eventNotHandledErr
;
9414 /* A HI command event is mapped to an Apple event whose event class
9415 symbol is `hi-command' and event ID is its command ID. */
9416 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9418 event
, num_params
, names
, types
);
9419 return err
== noErr
? noErr
: eventNotHandledErr
;
9423 init_command_handler ()
9425 static const EventTypeSpec specs
[] =
9426 {{kEventClassCommand
, kEventCommandProcess
}};
9427 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9429 if (handle_command_eventUPP
== NULL
)
9430 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9431 return InstallApplicationEventHandler (handle_command_eventUPP
,
9432 GetEventTypeCount (specs
), specs
,
9436 static pascal OSStatus
9437 mac_handle_window_event (next_handler
, event
, data
)
9438 EventHandlerCallRef next_handler
;
9443 OSStatus result
, err
;
9446 XSizeHints
*size_hints
;
9448 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9449 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9451 return eventNotHandledErr
;
9453 f
= mac_window_to_frame (wp
);
9454 switch (GetEventKind (event
))
9456 case kEventWindowUpdate
:
9457 result
= CallNextEventHandler (next_handler
, event
);
9458 if (result
!= eventNotHandledErr
)
9461 do_window_update (wp
);
9464 case kEventWindowGetIdealSize
:
9465 result
= CallNextEventHandler (next_handler
, event
);
9466 if (result
!= eventNotHandledErr
)
9470 Point ideal_size
= mac_get_ideal_size (f
);
9472 err
= SetEventParameter (event
, kEventParamDimensions
,
9473 typeQDPoint
, sizeof (Point
), &ideal_size
);
9479 case kEventWindowBoundsChanging
:
9480 result
= CallNextEventHandler (next_handler
, event
);
9481 if (result
!= eventNotHandledErr
)
9484 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9485 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9489 size_hints
= FRAME_SIZE_HINTS (f
);
9490 if ((attributes
& kWindowBoundsChangeUserResize
)
9491 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9492 == (PResizeInc
| PBaseSize
| PMinSize
)))
9497 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9498 typeQDRectangle
, NULL
, sizeof (Rect
),
9503 width
= bounds
.right
- bounds
.left
;
9504 height
= bounds
.bottom
- bounds
.top
;
9506 if (width
< size_hints
->min_width
)
9507 width
= size_hints
->min_width
;
9509 width
= size_hints
->base_width
9510 + (int) ((width
- size_hints
->base_width
)
9511 / (float) size_hints
->width_inc
+ .5)
9512 * size_hints
->width_inc
;
9514 if (height
< size_hints
->min_height
)
9515 height
= size_hints
->min_height
;
9517 height
= size_hints
->base_height
9518 + (int) ((height
- size_hints
->base_height
)
9519 / (float) size_hints
->height_inc
+ .5)
9520 * size_hints
->height_inc
;
9522 bounds
.right
= bounds
.left
+ width
;
9523 bounds
.bottom
= bounds
.top
+ height
;
9524 SetEventParameter (event
, kEventParamCurrentBounds
,
9525 typeQDRectangle
, sizeof (Rect
), &bounds
);
9530 case kEventWindowBoundsChanged
:
9531 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9532 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9536 if (attributes
& kWindowBoundsChangeSizeChanged
)
9540 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9541 typeQDRectangle
, NULL
, sizeof (Rect
),
9547 width
= bounds
.right
- bounds
.left
;
9548 height
= bounds
.bottom
- bounds
.top
;
9549 mac_handle_size_change (f
, width
, height
);
9553 if (attributes
& kWindowBoundsChangeOriginChanged
)
9554 mac_handle_origin_change (f
);
9558 case kEventWindowShown
:
9559 case kEventWindowHidden
:
9560 case kEventWindowExpanded
:
9561 case kEventWindowCollapsed
:
9562 result
= CallNextEventHandler (next_handler
, event
);
9564 mac_handle_visibility_change (f
);
9569 case kEventWindowClose
:
9570 result
= CallNextEventHandler (next_handler
, event
);
9572 struct input_event buf
;
9575 buf
.kind
= DELETE_WINDOW_EVENT
;
9576 XSETFRAME (buf
.frame_or_window
, f
);
9578 kbd_buffer_store_event (&buf
);
9583 case kEventWindowToolbarSwitchMode
:
9584 result
= CallNextEventHandler (next_handler
, event
);
9586 static const EventParamName names
[] = {kEventParamDirectObject
,
9587 kEventParamWindowMouseLocation
,
9588 kEventParamKeyModifiers
,
9589 kEventParamMouseButton
,
9590 kEventParamClickCount
,
9591 kEventParamMouseChord
};
9592 static const EventParamType types
[] = {typeWindowRef
,
9598 int num_params
= sizeof (names
) / sizeof (names
[0]);
9600 err
= mac_store_event_ref_as_apple_event (0, 0,
9602 Qtoolbar_switch_mode
,
9606 return err
== noErr
? noErr
: result
;
9610 case kEventWindowFocusAcquired
:
9611 result
= CallNextEventHandler (next_handler
, event
);
9612 err
= mac_tsm_resume ();
9613 return err
== noErr
? noErr
: result
;
9615 case kEventWindowFocusRelinquish
:
9616 result
= CallNextEventHandler (next_handler
, event
);
9617 err
= mac_tsm_suspend ();
9618 return err
== noErr
? noErr
: result
;
9622 return eventNotHandledErr
;
9625 static pascal OSStatus
9626 mac_handle_mouse_event (next_handler
, event
, data
)
9627 EventHandlerCallRef next_handler
;
9631 OSStatus result
, err
;
9633 switch (GetEventKind (event
))
9635 case kEventMouseWheelMoved
:
9639 EventMouseWheelAxis axis
;
9643 result
= CallNextEventHandler (next_handler
, event
);
9644 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9647 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9648 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9652 f
= mac_window_to_frame (wp
);
9653 if (f
!= mac_focus_frame (&one_mac_display_info
))
9656 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
9657 typeMouseWheelAxis
, NULL
,
9658 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9659 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
9662 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
9663 typeSInt32
, NULL
, sizeof (SInt32
),
9667 err
= GetEventParameter (event
, kEventParamMouseLocation
,
9668 typeQDPoint
, NULL
, sizeof (Point
),
9672 read_socket_inev
->kind
= WHEEL_EVENT
;
9673 read_socket_inev
->code
= 0;
9674 read_socket_inev
->modifiers
=
9675 (mac_event_to_emacs_modifiers (event
)
9676 | ((delta
< 0) ? down_modifier
: up_modifier
));
9677 SetPortWindowPort (wp
);
9678 GlobalToLocal (&point
);
9679 XSETINT (read_socket_inev
->x
, point
.h
);
9680 XSETINT (read_socket_inev
->y
, point
.v
);
9681 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9691 return eventNotHandledErr
;
9694 #if USE_MAC_FONT_PANEL
9695 static pascal OSStatus
9696 mac_handle_font_event (next_handler
, event
, data
)
9697 EventHandlerCallRef next_handler
;
9701 OSStatus result
, err
;
9704 const EventParamName
*names
;
9705 const EventParamType
*types
;
9706 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
9707 kEventParamATSUFontSize
,
9708 kEventParamFMFontFamily
,
9709 kEventParamFMFontSize
,
9710 kEventParamFontColor
};
9711 static const EventParamType types_sel
[] = {typeATSUFontID
,
9717 result
= CallNextEventHandler (next_handler
, event
);
9718 if (result
!= eventNotHandledErr
)
9721 switch (GetEventKind (event
))
9723 case kEventFontPanelClosed
:
9724 id_key
= Qpanel_closed
;
9730 case kEventFontSelection
:
9731 id_key
= Qselection
;
9732 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9738 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9742 return err
== noErr
? noErr
: eventNotHandledErr
;
9747 static pascal OSStatus
9748 mac_handle_text_input_event (next_handler
, event
, data
)
9749 EventHandlerCallRef next_handler
;
9753 OSStatus result
, err
= noErr
;
9754 Lisp_Object id_key
= Qnil
;
9756 const EventParamName
*names
;
9757 const EventParamType
*types
;
9758 static UInt32 seqno_uaia
= 0;
9759 static const EventParamName names_uaia
[] =
9760 {kEventParamTextInputSendComponentInstance
,
9761 kEventParamTextInputSendRefCon
,
9762 kEventParamTextInputSendSLRec
,
9763 kEventParamTextInputSendFixLen
,
9764 kEventParamTextInputSendText
,
9765 kEventParamTextInputSendUpdateRng
,
9766 kEventParamTextInputSendHiliteRng
,
9767 kEventParamTextInputSendClauseRng
,
9768 kEventParamTextInputSendPinRng
,
9769 kEventParamTextInputSendTextServiceEncoding
,
9770 kEventParamTextInputSendTextServiceMacEncoding
,
9771 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
9772 static const EventParamType types_uaia
[] =
9773 {typeComponentInstance
,
9775 typeIntlWritingCode
,
9789 static const EventParamName names_ufke
[] =
9790 {kEventParamTextInputSendComponentInstance
,
9791 kEventParamTextInputSendRefCon
,
9792 kEventParamTextInputSendSLRec
,
9793 kEventParamTextInputSendText
};
9794 static const EventParamType types_ufke
[] =
9795 {typeComponentInstance
,
9797 typeIntlWritingCode
,
9800 result
= CallNextEventHandler (next_handler
, event
);
9802 switch (GetEventKind (event
))
9804 case kEventTextInputUpdateActiveInputArea
:
9805 id_key
= Qupdate_active_input_area
;
9806 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
9809 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
9810 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
9814 case kEventTextInputUnicodeForKeyEvent
:
9817 UInt32 actual_size
, modifiers
, mapped_modifiers
;
9819 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
9820 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
9823 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
9825 sizeof (UInt32
), NULL
, &modifiers
);
9829 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9830 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9831 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9834 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9836 if (modifiers
& mapped_modifiers
)
9837 /* There're mapped modifier keys. Process it in
9839 return eventNotHandledErr
;
9842 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
9843 typeUnicodeText
, NULL
, 0, &actual_size
,
9845 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
9849 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
9850 typeUnicodeText
, NULL
,
9851 sizeof (UniChar
), NULL
, &code
);
9852 if (err
== noErr
&& code
< 0x80)
9854 /* ASCII character. Process it in XTread_socket. */
9855 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
9859 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
9860 typeUInt32
, NULL
, sizeof (UInt32
),
9862 if (!(err
== noErr
&& key_code
<= 0x7f
9863 && keycode_to_xkeysym_table
[key_code
]))
9866 mac_focus_frame (&one_mac_display_info
);
9868 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
9869 read_socket_inev
->code
= code
;
9870 read_socket_inev
->modifiers
=
9871 mac_to_emacs_modifiers (modifiers
);
9872 read_socket_inev
->modifiers
|=
9873 (extra_keyboard_modifiers
9874 & (meta_modifier
| alt_modifier
9875 | hyper_modifier
| super_modifier
));
9876 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9879 return eventNotHandledErr
;
9883 /* Non-ASCII keystrokes without mapped modifiers are processed
9884 at the Lisp level. */
9885 id_key
= Qunicode_for_key_event
;
9886 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
9891 case kEventTextInputOffsetToPos
:
9897 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
9898 return eventNotHandledErr
;
9900 /* Strictly speaking, this is not always correct because
9901 previous events may change some states about display. */
9902 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
9904 /* Active input area is displayed in the echo area. */
9905 w
= XWINDOW (echo_area_window
);
9906 f
= WINDOW_XFRAME (w
);
9910 /* Active input area is displayed around the current point. */
9911 f
= SELECTED_FRAME ();
9912 w
= XWINDOW (f
->selected_window
);
9915 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
9916 + WINDOW_LEFT_FRINGE_WIDTH (w
));
9917 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
9918 + FONT_BASE (FRAME_FONT (f
)));
9919 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
9921 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
9922 typeQDPoint
, sizeof (typeQDPoint
), &p
);
9931 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
9935 return err
== noErr
? noErr
: result
;
9941 mac_store_service_event (event
)
9947 const EventParamName
*names
;
9948 const EventParamType
*types
;
9949 static const EventParamName names_pfm
[] =
9950 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
9951 static const EventParamType types_pfm
[] =
9952 {typeCFStringRef
, typeCFStringRef
};
9954 switch (GetEventKind (event
))
9956 case kEventServicePaste
:
9963 case kEventServicePerform
:
9965 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
9974 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
9980 #endif /* MAC_OSX */
9981 #endif /* USE_CARBON_EVENTS */
9985 install_window_handler (window
)
9988 OSStatus err
= noErr
;
9989 #if USE_CARBON_EVENTS
9990 static const EventTypeSpec specs_window
[] =
9991 {{kEventClassWindow
, kEventWindowUpdate
},
9992 {kEventClassWindow
, kEventWindowGetIdealSize
},
9993 {kEventClassWindow
, kEventWindowBoundsChanging
},
9994 {kEventClassWindow
, kEventWindowBoundsChanged
},
9995 {kEventClassWindow
, kEventWindowShown
},
9996 {kEventClassWindow
, kEventWindowHidden
},
9997 {kEventClassWindow
, kEventWindowExpanded
},
9998 {kEventClassWindow
, kEventWindowCollapsed
},
9999 {kEventClassWindow
, kEventWindowClose
},
10001 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
10004 {kEventClassWindow
, kEventWindowFocusAcquired
},
10005 {kEventClassWindow
, kEventWindowFocusRelinquish
},
10008 static const EventTypeSpec specs_mouse
[] =
10009 {{kEventClassMouse
, kEventMouseWheelMoved
}};
10010 static EventHandlerUPP handle_window_eventUPP
= NULL
;
10011 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
10012 #if USE_MAC_FONT_PANEL
10013 static const EventTypeSpec specs_font
[] =
10014 {{kEventClassFont
, kEventFontPanelClosed
},
10015 {kEventClassFont
, kEventFontSelection
}};
10016 static EventHandlerUPP handle_font_eventUPP
= NULL
;
10019 static const EventTypeSpec specs_text_input
[] =
10020 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
10021 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
10022 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
10023 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
10026 if (handle_window_eventUPP
== NULL
)
10027 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
10028 if (handle_mouse_eventUPP
== NULL
)
10029 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
10030 #if USE_MAC_FONT_PANEL
10031 if (handle_font_eventUPP
== NULL
)
10032 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
10035 if (handle_text_input_eventUPP
== NULL
)
10036 handle_text_input_eventUPP
=
10037 NewEventHandlerUPP (mac_handle_text_input_event
);
10039 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
10040 GetEventTypeCount (specs_window
),
10041 specs_window
, NULL
, NULL
);
10043 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
10044 GetEventTypeCount (specs_mouse
),
10045 specs_mouse
, NULL
, NULL
);
10046 #if USE_MAC_FONT_PANEL
10048 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
10049 GetEventTypeCount (specs_font
),
10050 specs_font
, NULL
, NULL
);
10054 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
10055 GetEventTypeCount (specs_text_input
),
10056 specs_text_input
, window
, NULL
);
10060 err
= install_drag_handler (window
);
10066 remove_window_handler (window
)
10069 remove_drag_handler (window
);
10075 profiler_exit_proc ()
10077 ProfilerDump ("\pEmacs.prof");
10082 /* These few functions implement Emacs as a normal Mac application
10083 (almost): set up the heap and the Toolbox, handle necessary system
10084 events plus a few simple menu events. They also set up Emacs's
10085 access to functions defined in the rest of this file. Emacs uses
10086 function hooks to perform all its terminal I/O. A complete list of
10087 these functions appear in termhooks.h. For what they do, read the
10088 comments there and see also w32term.c and xterm.c. What's
10089 noticeably missing here is the event loop, which is normally
10090 present in most Mac application. After performing the necessary
10091 Mac initializations, main passes off control to emacs_main
10092 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10093 (defined further below) to read input. This is where
10094 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10101 #if __profile__ /* is the profiler on? */
10102 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10107 /* set creator and type for files created by MSL */
10108 _fcreator
= 'EMAx';
10112 do_init_managers ();
10116 #ifndef USE_LSB_TAG
10117 do_check_ram_size ();
10120 init_emacs_passwd_dir ();
10124 init_coercion_handler ();
10126 initialize_applescript ();
10128 init_apple_event_handler ();
10134 /* set up argv array from STR# resource */
10135 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10139 /* free up AppleScript resources on exit */
10140 atexit (terminate_applescript
);
10142 #if __profile__ /* is the profiler on? */
10143 atexit (profiler_exit_proc
);
10146 /* 3rd param "envp" never used in emacs_main */
10147 (void) emacs_main (argc
, argv
, 0);
10150 /* Never reached - real exit in Fkill_emacs */
10155 #if !USE_CARBON_EVENTS
10156 static RgnHandle mouse_region
= NULL
;
10159 mac_wait_next_event (er
, sleep_time
, dequeue
)
10164 static EventRecord er_buf
= {nullEvent
};
10165 UInt32 target_tick
, current_tick
;
10166 EventMask event_mask
;
10168 if (mouse_region
== NULL
)
10169 mouse_region
= NewRgn ();
10171 event_mask
= everyEvent
;
10172 if (!mac_ready_for_apple_events
)
10173 event_mask
-= highLevelEventMask
;
10175 current_tick
= TickCount ();
10176 target_tick
= current_tick
+ sleep_time
;
10178 if (er_buf
.what
== nullEvent
)
10179 while (!WaitNextEvent (event_mask
, &er_buf
,
10180 target_tick
- current_tick
, mouse_region
))
10182 current_tick
= TickCount ();
10183 if (target_tick
<= current_tick
)
10189 er_buf
.what
= nullEvent
;
10192 #endif /* not USE_CARBON_EVENTS */
10194 #if TARGET_API_MAC_CARBON
10196 mac_post_mouse_moved_event ()
10198 EventRef event
= NULL
;
10201 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
10202 kEventAttributeNone
, &event
);
10207 GetMouse (&mouse_pos
);
10208 LocalToGlobal (&mouse_pos
);
10209 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
10210 sizeof (Point
), &mouse_pos
);
10214 UInt32 modifiers
= GetCurrentKeyModifiers ();
10216 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10217 sizeof (UInt32
), &modifiers
);
10220 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10221 kEventPriorityStandard
);
10223 ReleaseEvent (event
);
10229 mac_set_unicode_keystroke_event (code
, buf
)
10231 struct input_event
*buf
;
10233 int charset_id
, c1
, c2
;
10237 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10240 else if (code
< 0x100)
10243 charset_id
= CHARSET_8_BIT_CONTROL
;
10245 charset_id
= charset_latin_iso8859_1
;
10246 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10247 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10252 charset_id
= charset_mule_unicode_0100_24ff
,
10254 else if (code
< 0x33FF)
10255 charset_id
= charset_mule_unicode_2500_33ff
,
10257 else if (code
>= 0xE000)
10258 charset_id
= charset_mule_unicode_e000_ffff
,
10260 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10261 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10262 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10267 /* Emacs calls this whenever it wants to read an input event from the
10270 XTread_socket (sd
, expected
, hold_quit
)
10272 struct input_event
*hold_quit
;
10274 struct input_event inev
;
10276 #if USE_CARBON_EVENTS
10278 EventTargetRef toolbox_dispatcher
;
10281 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10283 if (interrupt_input_blocked
)
10285 interrupt_input_pending
= 1;
10289 interrupt_input_pending
= 0;
10292 /* So people can tell when we have read the available input. */
10293 input_signal_count
++;
10297 #if USE_CARBON_EVENTS
10298 toolbox_dispatcher
= GetEventDispatcherTarget ();
10302 mac_prepare_for_quickdraw (NULL
),
10304 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10305 kEventRemoveFromQueue
, &eventRef
))
10306 #else /* !USE_CARBON_EVENTS */
10307 while (mac_wait_next_event (&er
, 0, true))
10308 #endif /* !USE_CARBON_EVENTS */
10312 unsigned long timestamp
;
10315 inev
.kind
= NO_EVENT
;
10318 #if USE_CARBON_EVENTS
10319 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10321 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10324 #if USE_CARBON_EVENTS
10325 /* Handle new events */
10326 if (!mac_convert_event_ref (eventRef
, &er
))
10328 /* There used to be a handler for the kEventMouseWheelMoved
10329 event here. But as of Mac OS X 10.4, this kind of event
10330 is not directly posted to the main event queue by
10331 two-finger scrolling on the trackpad. Instead, some
10332 private event is posted and it is converted to a wheel
10333 event by the default handler for the application target.
10334 The converted one can be received by a Carbon event
10335 handler installed on a window target. */
10336 read_socket_inev
= &inev
;
10337 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10338 read_socket_inev
= NULL
;
10341 #endif /* USE_CARBON_EVENTS */
10347 WindowPtr window_ptr
;
10348 ControlPartCode part_code
;
10349 int tool_bar_p
= 0;
10351 #if USE_CARBON_EVENTS
10352 /* This is needed to send mouse events like aqua window
10353 buttons to the correct handler. */
10354 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10355 != eventNotHandledErr
)
10358 last_mouse_glyph_frame
= 0;
10360 if (dpyinfo
->grabbed
&& last_mouse_frame
10361 && FRAME_LIVE_P (last_mouse_frame
))
10363 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10364 part_code
= inContent
;
10368 part_code
= FindWindow (er
.where
, &window_ptr
);
10369 if (tip_window
&& window_ptr
== tip_window
)
10371 HideWindow (tip_window
);
10372 part_code
= FindWindow (er
.where
, &window_ptr
);
10376 if (er
.what
!= mouseDown
&&
10377 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10383 f
= mac_focus_frame (dpyinfo
);
10384 saved_menu_event_location
= er
.where
;
10385 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10386 XSETFRAME (inev
.frame_or_window
, f
);
10391 #if TARGET_API_MAC_CARBON
10392 FrontNonFloatingWindow ()
10397 SelectWindow (window_ptr
);
10400 ControlPartCode control_part_code
;
10402 Point mouse_loc
= er
.where
;
10404 ControlKind control_kind
;
10407 f
= mac_window_to_frame (window_ptr
);
10408 /* convert to local coordinates of new window */
10409 SetPortWindowPort (window_ptr
);
10411 GlobalToLocal (&mouse_loc
);
10412 #if TARGET_API_MAC_CARBON
10413 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10414 &control_part_code
);
10417 GetControlKind (ch
, &control_kind
);
10420 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10424 #if USE_CARBON_EVENTS
10425 inev
.code
= mac_get_mouse_btn (eventRef
);
10426 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10428 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10429 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10431 XSETINT (inev
.x
, mouse_loc
.h
);
10432 XSETINT (inev
.y
, mouse_loc
.v
);
10434 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10436 #ifndef USE_TOOLKIT_SCROLL_BARS
10437 /* control_part_code becomes kControlNoPart if
10438 a progress indicator is clicked. */
10439 && control_part_code
!= kControlNoPart
10440 #else /* USE_TOOLKIT_SCROLL_BARS */
10442 && control_kind
.kind
== kControlKindScrollBar
10443 #endif /* MAC_OSX */
10444 #endif /* USE_TOOLKIT_SCROLL_BARS */
10447 struct scroll_bar
*bar
;
10449 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10451 bar
= tracked_scroll_bar
;
10452 #ifndef USE_TOOLKIT_SCROLL_BARS
10453 control_part_code
= kControlIndicatorPart
;
10457 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10458 #ifdef USE_TOOLKIT_SCROLL_BARS
10459 /* Make the "Ctrl-Mouse-2 splits window" work
10460 for toolkit scroll bars. */
10461 if (er
.modifiers
& controlKey
)
10462 x_scroll_bar_handle_click (bar
, control_part_code
,
10464 else if (er
.what
== mouseDown
)
10465 x_scroll_bar_handle_press (bar
, control_part_code
,
10468 x_scroll_bar_handle_release (bar
, &inev
);
10469 #else /* not USE_TOOLKIT_SCROLL_BARS */
10470 x_scroll_bar_handle_click (bar
, control_part_code
,
10472 if (er
.what
== mouseDown
10473 && control_part_code
== kControlIndicatorPart
)
10474 tracked_scroll_bar
= bar
;
10476 tracked_scroll_bar
= NULL
;
10477 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10481 Lisp_Object window
;
10482 int x
= mouse_loc
.h
;
10483 int y
= mouse_loc
.v
;
10485 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10486 if (EQ (window
, f
->tool_bar_window
))
10488 if (er
.what
== mouseDown
)
10489 handle_tool_bar_click (f
, x
, y
, 1, 0);
10491 handle_tool_bar_click (f
, x
, y
, 0,
10497 XSETFRAME (inev
.frame_or_window
, f
);
10498 inev
.kind
= MOUSE_CLICK_EVENT
;
10502 if (er
.what
== mouseDown
)
10504 dpyinfo
->grabbed
|= (1 << inev
.code
);
10505 last_mouse_frame
= f
;
10508 last_tool_bar_item
= -1;
10512 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10513 /* If a button is released though it was not
10514 previously pressed, that would be because
10515 of multi-button emulation. */
10516 dpyinfo
->grabbed
= 0;
10518 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10521 /* Ignore any mouse motion that happened before
10522 this event; any subsequent mouse-movement Emacs
10523 events should reflect only motion after the
10526 f
->mouse_moved
= 0;
10528 #ifdef USE_TOOLKIT_SCROLL_BARS
10529 if (inev
.kind
== MOUSE_CLICK_EVENT
)
10534 inev
.modifiers
|= down_modifier
;
10537 inev
.modifiers
|= up_modifier
;
10544 #if TARGET_API_MAC_CARBON
10546 if (IsWindowPathSelectClick (window_ptr
, &er
))
10548 WindowPathSelect (window_ptr
, NULL
, NULL
);
10551 if (part_code
== inProxyIcon
10552 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
10553 != errUserWantsToDragWindow
))
10555 DragWindow (window_ptr
, er
.where
, NULL
);
10556 #else /* not TARGET_API_MAC_CARBON */
10557 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10558 #endif /* not TARGET_API_MAC_CARBON */
10559 /* Update the frame parameters. */
10560 #if !USE_CARBON_EVENTS
10562 struct frame
*f
= mac_window_to_frame (window_ptr
);
10564 if (f
&& !f
->async_iconified
)
10565 mac_handle_origin_change (f
);
10571 if (TrackGoAway (window_ptr
, er
.where
))
10573 inev
.kind
= DELETE_WINDOW_EVENT
;
10574 XSETFRAME (inev
.frame_or_window
,
10575 mac_window_to_frame (window_ptr
));
10579 /* window resize handling added --ben */
10581 do_grow_window (window_ptr
, &er
);
10584 /* window zoom handling added --ben */
10587 if (TrackBox (window_ptr
, er
.where
, part_code
))
10588 do_zoom_window (window_ptr
, part_code
);
10598 #if USE_CARBON_EVENTS
10599 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10600 != eventNotHandledErr
)
10603 do_window_update ((WindowPtr
) er
.message
);
10608 #if USE_CARBON_EVENTS
10609 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10610 != eventNotHandledErr
)
10613 switch ((er
.message
>> 24) & 0x000000FF)
10615 case suspendResumeMessage
:
10617 if (er
.message
& resumeFlag
)
10620 mac_tsm_suspend ();
10624 case mouseMovedMessage
:
10625 #if !USE_CARBON_EVENTS
10626 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
10627 er
.where
.h
+ 1, er
.where
.v
+ 1);
10629 previous_help_echo_string
= help_echo_string
;
10630 help_echo_string
= Qnil
;
10632 if (dpyinfo
->grabbed
&& last_mouse_frame
10633 && FRAME_LIVE_P (last_mouse_frame
))
10634 f
= last_mouse_frame
;
10636 f
= dpyinfo
->x_focus_frame
;
10638 if (dpyinfo
->mouse_face_hidden
)
10640 dpyinfo
->mouse_face_hidden
= 0;
10641 clear_mouse_face (dpyinfo
);
10646 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
10647 Point mouse_pos
= er
.where
;
10649 SetPortWindowPort (wp
);
10651 GlobalToLocal (&mouse_pos
);
10653 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10654 #ifdef USE_TOOLKIT_SCROLL_BARS
10655 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
10657 #else /* not USE_TOOLKIT_SCROLL_BARS */
10658 x_scroll_bar_note_movement (tracked_scroll_bar
,
10660 - XINT (tracked_scroll_bar
->top
),
10661 er
.when
* (1000 / 60));
10662 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10665 /* Generate SELECT_WINDOW_EVENTs when needed. */
10666 if (!NILP (Vmouse_autoselect_window
))
10668 Lisp_Object window
;
10670 window
= window_from_coordinates (f
,
10675 /* Window will be selected only when it is
10676 not selected now and last mouse movement
10677 event was not in it. Minibuffer window
10678 will be selected iff it is active. */
10679 if (WINDOWP (window
)
10680 && !EQ (window
, last_window
)
10681 && !EQ (window
, selected_window
))
10683 inev
.kind
= SELECT_WINDOW_EVENT
;
10684 inev
.frame_or_window
= window
;
10687 last_window
=window
;
10689 if (!note_mouse_movement (f
, &mouse_pos
))
10690 help_echo_string
= previous_help_echo_string
;
10694 /* If the contents of the global variable
10695 help_echo_string has changed, generate a
10697 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10705 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10707 #if USE_CARBON_EVENTS
10708 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10709 != eventNotHandledErr
)
10712 if (window_ptr
== tip_window
)
10714 HideWindow (tip_window
);
10718 if (!is_emacs_window (window_ptr
))
10721 if ((er
.modifiers
& activeFlag
) != 0)
10723 /* A window has been activated */
10724 Point mouse_loc
= er
.where
;
10726 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10728 SetPortWindowPort (window_ptr
);
10729 GlobalToLocal (&mouse_loc
);
10730 /* Window-activated event counts as mouse movement,
10731 so update things that depend on mouse position. */
10732 note_mouse_movement (mac_window_to_frame (window_ptr
),
10737 /* A window has been deactivated */
10738 #if USE_TOOLKIT_SCROLL_BARS
10739 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10741 struct input_event event
;
10743 EVENT_INIT (event
);
10744 event
.kind
= NO_EVENT
;
10745 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10746 if (event
.kind
!= NO_EVENT
)
10748 event
.timestamp
= timestamp
;
10749 kbd_buffer_store_event_hold (&event
, hold_quit
);
10754 dpyinfo
->grabbed
= 0;
10756 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10758 f
= mac_window_to_frame (window_ptr
);
10759 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10761 /* If we move outside the frame, then we're
10762 certainly no longer on any text in the
10764 clear_mouse_face (dpyinfo
);
10765 dpyinfo
->mouse_face_mouse_frame
= 0;
10768 /* Generate a nil HELP_EVENT to cancel a help-echo.
10769 Do it only if there's something to cancel.
10770 Otherwise, the startup message is cleared when the
10771 mouse leaves the frame. */
10772 if (any_help_event_p
)
10782 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10783 static SInt16 last_key_script
= -1;
10784 SInt16 current_key_script
;
10785 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
10788 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
10789 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
10790 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
10792 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10793 mapped_modifiers
|=
10794 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
10796 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
10798 sizeof (UInt32
), NULL
, &modifiers
);
10800 mapped_modifiers
&= modifiers
;
10802 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
10803 /* When using Carbon Events, we need to pass raw keyboard
10804 events to the TSM ourselves. If TSM handles it, it
10805 will pass back noErr, otherwise it will pass back
10806 "eventNotHandledErr" and we can process it
10808 if (!(mapped_modifiers
10809 & ~(mac_pass_command_to_system
? cmdKey
: 0)
10810 & ~(mac_pass_control_to_system
? controlKey
: 0)))
10814 read_socket_inev
= &inev
;
10815 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10816 read_socket_inev
= NULL
;
10817 if (err
!= eventNotHandledErr
)
10821 if (er
.what
== keyUp
)
10826 f
= mac_focus_frame (dpyinfo
);
10828 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
10829 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
10831 clear_mouse_face (dpyinfo
);
10832 dpyinfo
->mouse_face_hidden
= 1;
10835 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10836 if (last_key_script
!= current_key_script
)
10838 struct input_event event
;
10840 EVENT_INIT (event
);
10841 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10843 event
.code
= current_key_script
;
10844 event
.timestamp
= timestamp
;
10845 kbd_buffer_store_event (&event
);
10847 last_key_script
= current_key_script
;
10851 if (inev
.kind
!= NO_EVENT
)
10856 if (mapped_modifiers
& kEventKeyModifierFnMask
10858 && fn_keycode_to_keycode_table
[keycode
])
10859 keycode
= fn_keycode_to_keycode_table
[keycode
];
10861 if (keycode
<= 0x7f && keycode_to_xkeysym_table
[keycode
])
10863 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10864 inev
.code
= 0xff00 | keycode_to_xkeysym_table
[keycode
];
10866 if (modifiers
& kEventKeyModifierFnMask
10868 && fn_keycode_to_keycode_table
[keycode
] == keycode
)
10869 modifiers
&= ~kEventKeyModifierFnMask
;
10872 else if (mapped_modifiers
)
10874 /* translate the keycode back to determine the
10877 static SInt16 last_key_layout_id
= 0;
10878 static Handle uchr_handle
= (Handle
)-1;
10879 SInt16 current_key_layout_id
=
10880 GetScriptVariable (current_key_script
, smScriptKeys
);
10882 if (uchr_handle
== (Handle
)-1
10883 || last_key_layout_id
!= current_key_layout_id
)
10885 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10886 last_key_layout_id
= current_key_layout_id
;
10892 UInt16 key_action
= er
.what
- keyDown
;
10893 UInt32 modifier_key_state
=
10894 (modifiers
& ~mapped_modifiers
) >> 8;
10895 UInt32 keyboard_type
= LMGetKbdType ();
10896 SInt32 dead_key_state
= 0;
10898 UniCharCount actual_length
;
10900 status
= UCKeyTranslate ((UCKeyboardLayout
*)*uchr_handle
,
10901 keycode
, key_action
,
10902 modifier_key_state
,
10904 kUCKeyTranslateNoDeadKeysMask
,
10906 1, &actual_length
, &code
);
10907 if (status
== noErr
&& actual_length
== 1)
10908 mac_set_unicode_keystroke_event (code
, &inev
);
10910 #endif /* MAC_OSX */
10912 if (inev
.kind
== NO_EVENT
)
10914 /* This code comes from Keyboard Resource,
10915 Appendix C of IM - Text. This is necessary
10916 since shift is ignored in KCHR table
10917 translation when option or command is pressed.
10918 It also does not translate correctly
10919 control-shift chars like C-% so mask off shift
10921 /* Mask off modifier keys that are mapped to some
10922 Emacs modifiers. */
10923 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
10924 /* set high byte of keycode to modifier high byte*/
10925 int new_keycode
= keycode
| new_modifiers
;
10926 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10927 unsigned long some_state
= 0;
10928 UInt32 new_char_code
;
10930 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
10932 if (new_char_code
== 0)
10933 /* Seems like a dead key. Append up-stroke. */
10934 new_char_code
= KeyTranslate (kchr_ptr
,
10935 new_keycode
| 0x80,
10939 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10940 inev
.code
= new_char_code
& 0xff;
10945 if (inev
.kind
== NO_EVENT
)
10947 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10948 inev
.code
= er
.message
& charCodeMask
;
10951 inev
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10952 inev
.modifiers
|= (extra_keyboard_modifiers
10953 & (meta_modifier
| alt_modifier
10954 | hyper_modifier
| super_modifier
));
10955 XSETFRAME (inev
.frame_or_window
, f
);
10957 #if TARGET_API_MAC_CARBON
10958 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
10959 && inev
.code
>= 0x80 && inev
.modifiers
)
10962 TextEncoding encoding
= kTextEncodingMacRoman
;
10963 TextToUnicodeInfo ttu_info
;
10965 UpgradeScriptInfoToTextEncoding (current_key_script
,
10966 kTextLanguageDontCare
,
10967 kTextRegionDontCare
,
10969 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10974 ByteCount unicode_len
;
10977 pstr
[1] = inev
.code
;
10978 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10980 &unicode_len
, &code
);
10981 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10982 mac_set_unicode_keystroke_event (code
, &inev
);
10983 DisposeTextToUnicodeInfo (&ttu_info
);
10990 case kHighLevelEvent
:
10991 AEProcessAppleEvent (&er
);
10997 #if USE_CARBON_EVENTS
10998 ReleaseEvent (eventRef
);
11001 if (inev
.kind
!= NO_EVENT
)
11003 inev
.timestamp
= timestamp
;
11004 kbd_buffer_store_event_hold (&inev
, hold_quit
);
11009 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
11014 XSETFRAME (frame
, f
);
11020 any_help_event_p
= 1;
11021 gen_help_event (help_echo_string
, frame
, help_echo_window
,
11022 help_echo_object
, help_echo_pos
);
11026 help_echo_string
= Qnil
;
11027 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
11034 /* If the focus was just given to an autoraising frame,
11036 /* ??? This ought to be able to handle more than one such frame. */
11037 if (pending_autoraise_frame
)
11039 x_raise_frame (pending_autoraise_frame
);
11040 pending_autoraise_frame
= 0;
11043 #if !USE_CARBON_EVENTS
11044 /* Check which frames are still visible. We do this here because
11045 there doesn't seem to be any direct notification from the Window
11046 Manager that the visibility of a window has changed (at least,
11047 not in all cases). */
11049 Lisp_Object tail
, frame
;
11051 FOR_EACH_FRAME (tail
, frame
)
11053 struct frame
*f
= XFRAME (frame
);
11055 /* The tooltip has been drawn already. Avoid the
11056 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11057 if (EQ (frame
, tip_frame
))
11060 if (FRAME_MAC_P (f
))
11061 mac_handle_visibility_change (f
);
11072 /* Need to override CodeWarrior's input function so no conversion is
11073 done on newlines Otherwise compiled functions in .elc files will be
11074 read incorrectly. Defined in ...:MSL C:MSL
11075 Common:Source:buffer_io.c. */
11078 __convert_to_newlines (unsigned char * p
, size_t * n
)
11080 #pragma unused(p,n)
11084 __convert_from_newlines (unsigned char * p
, size_t * n
)
11086 #pragma unused(p,n)
11092 make_mac_terminal_frame (struct frame
*f
)
11097 XSETFRAME (frame
, f
);
11099 f
->output_method
= output_mac
;
11100 f
->output_data
.mac
= (struct mac_output
*)
11101 xmalloc (sizeof (struct mac_output
));
11102 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
11104 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
11106 FRAME_COLS (f
) = 96;
11107 FRAME_LINES (f
) = 4;
11109 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
11110 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
11112 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
11114 f
->output_data
.mac
->cursor_pixel
= 0;
11115 f
->output_data
.mac
->border_pixel
= 0x00ff00;
11116 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
11117 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
11119 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
11120 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
11121 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
11122 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
11123 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
11124 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
11126 FRAME_FONTSET (f
) = -1;
11127 f
->output_data
.mac
->explicit_parent
= 0;
11130 f
->border_width
= 0;
11132 f
->internal_border_width
= 0;
11137 f
->new_text_cols
= 0;
11138 f
->new_text_lines
= 0;
11140 SetRect (&r
, f
->left_pos
, f
->top_pos
,
11141 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
11142 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
11146 if (!(FRAME_MAC_WINDOW (f
) =
11147 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
11148 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
11150 /* so that update events can find this mac_output struct */
11151 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
11157 /* Need to be initialized for unshow_buffer in window.c. */
11158 selected_window
= f
->selected_window
;
11160 Fmodify_frame_parameters (frame
,
11161 Fcons (Fcons (Qfont
,
11162 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
11163 Fmodify_frame_parameters (frame
,
11164 Fcons (Fcons (Qforeground_color
,
11165 build_string ("black")), Qnil
));
11166 Fmodify_frame_parameters (frame
,
11167 Fcons (Fcons (Qbackground_color
,
11168 build_string ("white")), Qnil
));
11173 /***********************************************************************
11175 ***********************************************************************/
11177 int mac_initialized
= 0;
11180 mac_initialize_display_info ()
11182 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11184 bzero (dpyinfo
, sizeof (*dpyinfo
));
11187 dpyinfo
->mac_id_name
11188 = (char *) xmalloc (SCHARS (Vinvocation_name
)
11189 + SCHARS (Vsystem_name
)
11191 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
11192 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11194 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
11195 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
11198 dpyinfo
->reference_count
= 0;
11199 dpyinfo
->resx
= 72.0;
11200 dpyinfo
->resy
= 72.0;
11202 /* HasDepth returns true if it is possible to have a 32 bit display,
11203 but this may not be what is actually used. Mac OSX can do better. */
11204 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11205 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11206 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11207 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11210 GDHandle main_device_handle
= LMGetMainDevice();
11212 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
11213 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11214 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
11215 gdDevType
, dpyinfo
->color_p
))
11217 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
11218 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
11221 dpyinfo
->grabbed
= 0;
11222 dpyinfo
->root_window
= NULL
;
11223 dpyinfo
->image_cache
= make_image_cache ();
11225 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11226 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11227 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11228 dpyinfo
->mouse_face_window
= Qnil
;
11229 dpyinfo
->mouse_face_overlay
= Qnil
;
11230 dpyinfo
->mouse_face_hidden
= 0;
11235 mac_make_rdb (xrm_option
)
11236 const char *xrm_option
;
11238 XrmDatabase database
;
11240 database
= xrm_get_preference_database (NULL
);
11242 xrm_merge_string_database (database
, xrm_option
);
11247 struct mac_display_info
*
11248 mac_term_init (display_name
, xrm_option
, resource_name
)
11249 Lisp_Object display_name
;
11251 char *resource_name
;
11253 struct mac_display_info
*dpyinfo
;
11257 if (!mac_initialized
)
11260 mac_initialized
= 1;
11263 if (x_display_list
)
11264 error ("Sorry, this version can only handle one display");
11266 mac_initialize_display_info ();
11268 dpyinfo
= &one_mac_display_info
;
11270 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11272 /* Put this display on the chain. */
11273 dpyinfo
->next
= x_display_list
;
11274 x_display_list
= dpyinfo
;
11276 /* Put it on x_display_name_list. */
11277 x_display_name_list
= Fcons (Fcons (display_name
,
11278 Fcons (Qnil
, dpyinfo
->xrdb
)),
11279 x_display_name_list
);
11280 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11286 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11289 x_delete_display (dpyinfo
)
11290 struct mac_display_info
*dpyinfo
;
11294 /* Discard this display from x_display_name_list and x_display_list.
11295 We can't use Fdelq because that can quit. */
11296 if (! NILP (x_display_name_list
)
11297 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11298 x_display_name_list
= XCDR (x_display_name_list
);
11303 tail
= x_display_name_list
;
11304 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11306 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11308 XSETCDR (tail
, XCDR (XCDR (tail
)));
11311 tail
= XCDR (tail
);
11315 if (x_display_list
== dpyinfo
)
11316 x_display_list
= dpyinfo
->next
;
11319 struct x_display_info
*tail
;
11321 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11322 if (tail
->next
== dpyinfo
)
11323 tail
->next
= tail
->next
->next
;
11326 /* Free the font names in the font table. */
11327 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11328 if (dpyinfo
->font_table
[i
].name
)
11330 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11331 xfree (dpyinfo
->font_table
[i
].full_name
);
11332 xfree (dpyinfo
->font_table
[i
].name
);
11335 if (dpyinfo
->font_table
)
11337 if (dpyinfo
->font_table
->font_encoder
)
11338 xfree (dpyinfo
->font_table
->font_encoder
);
11339 xfree (dpyinfo
->font_table
);
11341 if (dpyinfo
->mac_id_name
)
11342 xfree (dpyinfo
->mac_id_name
);
11344 if (x_display_list
== 0)
11346 mac_clear_font_name_table ();
11347 bzero (dpyinfo
, sizeof (*dpyinfo
));
11356 extern int inhibit_window_system
;
11357 extern int noninteractive
;
11358 CFBundleRef appsBundle
;
11360 /* No need to test if already -nw*/
11361 if (inhibit_window_system
|| noninteractive
)
11364 appsBundle
= CFBundleGetMainBundle();
11365 if (appsBundle
!= NULL
)
11367 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
11368 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
11369 /* We found the bundle identifier, now we know we are valid. */
11376 /* MAC_TODO: Have this start the bundled executable */
11378 /* For now, prevent the fatal error by bringing it up in the terminal */
11379 inhibit_window_system
= 1;
11383 MakeMeTheFrontProcess ()
11385 ProcessSerialNumber psn
;
11388 err
= GetCurrentProcess (&psn
);
11390 (void) SetFrontProcess (&psn
);
11393 /***** Code to handle C-g testing *****/
11395 /* Contains the Mac modifier formed from quit_char */
11396 int mac_quit_char_modifiers
= 0;
11397 int mac_quit_char_keycode
;
11398 extern int quit_char
;
11401 mac_determine_quit_char_modifiers()
11403 /* Todo: Determine modifiers from quit_char. */
11404 UInt32 qc_modifiers
= ctrl_modifier
;
11406 /* Map modifiers */
11407 mac_quit_char_modifiers
= 0;
11408 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
11409 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
11410 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
11414 init_quit_char_handler ()
11416 /* TODO: Let this support keys other the 'g' */
11417 mac_quit_char_keycode
= 5;
11418 /* Look at <architecture/adb_kb_map.h> for details */
11419 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
11421 mac_determine_quit_char_modifiers();
11423 #endif /* MAC_OSX */
11431 MenuItemIndex menu_index
;
11433 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11434 &menu
, &menu_index
);
11436 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11437 #if USE_CARBON_EVENTS
11438 EnableMenuCommand (NULL
, kHICommandPreferences
);
11439 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11440 &menu
, &menu_index
);
11443 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11444 InsertMenuItemTextWithCFString (menu
, NULL
,
11445 0, kMenuItemAttrSeparator
, 0);
11446 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11447 0, 0, kHICommandAbout
);
11449 #endif /* USE_CARBON_EVENTS */
11450 #else /* !MAC_OSX */
11451 #if USE_CARBON_EVENTS
11452 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11462 static InterfaceTypeList types
= {kUnicodeDocument
};
11464 static InterfaceTypeList types
= {kTextService
};
11467 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11468 &tsm_document_id
, 0);
11472 /* Set up use of X before we make the first connection. */
11474 extern frame_parm_handler mac_frame_parm_handlers
[];
11476 static struct redisplay_interface x_redisplay_interface
=
11478 mac_frame_parm_handlers
,
11482 x_clear_end_of_line
,
11484 x_after_update_window_line
,
11485 x_update_window_begin
,
11486 x_update_window_end
,
11489 0, /* flush_display_optional */
11490 x_clear_window_mouse_face
,
11491 x_get_glyph_overhangs
,
11492 x_fix_overlapping_area
,
11493 x_draw_fringe_bitmap
,
11495 mac_define_fringe_bitmap
,
11496 mac_destroy_fringe_bitmap
,
11498 0, /* define_fringe_bitmap */
11499 0, /* destroy_fringe_bitmap */
11501 mac_per_char_metric
,
11503 mac_compute_glyph_string_overhangs
,
11504 x_draw_glyph_string
,
11505 mac_define_frame_cursor
,
11506 mac_clear_frame_area
,
11507 mac_draw_window_cursor
,
11508 mac_draw_vertical_window_border
,
11509 mac_shift_glyphs_for_insert
11515 rif
= &x_redisplay_interface
;
11517 clear_frame_hook
= x_clear_frame
;
11518 ins_del_lines_hook
= x_ins_del_lines
;
11519 delete_glyphs_hook
= x_delete_glyphs
;
11520 ring_bell_hook
= XTring_bell
;
11521 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11522 set_terminal_modes_hook
= XTset_terminal_modes
;
11523 update_begin_hook
= x_update_begin
;
11524 update_end_hook
= x_update_end
;
11525 set_terminal_window_hook
= XTset_terminal_window
;
11526 read_socket_hook
= XTread_socket
;
11527 frame_up_to_date_hook
= XTframe_up_to_date
;
11528 mouse_position_hook
= XTmouse_position
;
11529 frame_rehighlight_hook
= XTframe_rehighlight
;
11530 frame_raise_lower_hook
= XTframe_raise_lower
;
11532 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11533 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11534 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11535 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11537 scroll_region_ok
= 1; /* we'll scroll partial frames */
11538 char_ins_del_ok
= 1;
11539 line_ins_del_ok
= 1; /* we'll just blt 'em */
11540 fast_clear_end_of_line
= 1; /* X does this well */
11541 memory_below_frame
= 0; /* we don't remember what scrolls
11545 last_tool_bar_item
= -1;
11546 any_help_event_p
= 0;
11548 /* Try to use interrupt input; if we can't, then start polling. */
11549 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11553 #if TARGET_API_MAC_CARBON
11555 #if USE_CARBON_EVENTS
11557 init_service_handler ();
11559 init_quit_char_handler ();
11560 #endif /* MAC_OSX */
11562 init_command_handler ();
11569 #endif /* USE_CARBON_EVENTS */
11572 init_coercion_handler ();
11574 init_apple_event_handler ();
11576 if (!inhibit_window_system
)
11577 MakeMeTheFrontProcess ();
11582 mac_init_fringe ();
11593 staticpro (&x_error_message_string
);
11594 x_error_message_string
= Qnil
;
11597 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11598 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11599 Qalt
= intern ("alt"); staticpro (&Qalt
);
11600 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
11601 Qsuper
= intern ("super"); staticpro (&Qsuper
);
11602 Qmodifier_value
= intern ("modifier-value");
11603 staticpro (&Qmodifier_value
);
11605 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
11606 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11607 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11608 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11609 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11611 #if USE_CARBON_EVENTS
11612 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
11614 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
11615 staticpro (&Qtoolbar_switch_mode
);
11616 #if USE_MAC_FONT_PANEL
11617 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
11618 Qselection
= intern ("selection"); staticpro (&Qselection
);
11621 Qservice
= intern ("service"); staticpro (&Qservice
);
11622 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
11623 Qperform
= intern ("perform"); staticpro (&Qperform
);
11626 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
11627 Qupdate_active_input_area
= intern ("update-active-input-area");
11628 staticpro (&Qupdate_active_input_area
);
11629 Qunicode_for_key_event
= intern ("unicode-for-key-event");
11630 staticpro (&Qunicode_for_key_event
);
11635 Fprovide (intern ("mac-carbon"), Qnil
);
11638 staticpro (&Qreverse
);
11639 Qreverse
= intern ("reverse");
11641 staticpro (&x_display_name_list
);
11642 x_display_name_list
= Qnil
;
11644 staticpro (&last_mouse_scroll_bar
);
11645 last_mouse_scroll_bar
= Qnil
;
11647 staticpro (&fm_font_family_alist
);
11648 fm_font_family_alist
= Qnil
;
11651 staticpro (&atsu_font_id_hash
);
11652 atsu_font_id_hash
= Qnil
;
11654 staticpro (&fm_style_face_attributes_alist
);
11655 fm_style_face_attributes_alist
= Qnil
;
11659 staticpro (&saved_ts_script_language_on_focus
);
11660 saved_ts_script_language_on_focus
= Qnil
;
11663 /* We don't yet support this, but defining this here avoids whining
11664 from cus-start.el and other places, like "M-x set-variable". */
11665 DEFVAR_BOOL ("x-use-underline-position-properties",
11666 &x_use_underline_position_properties
,
11667 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11668 nil means ignore them. If you encounter fonts with bogus
11669 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11670 to 4.1, set this to nil.
11672 NOTE: Not supported on Mac yet. */);
11673 x_use_underline_position_properties
= 0;
11675 DEFVAR_BOOL ("x-underline-at-descent-line",
11676 &x_underline_at_descent_line
,
11677 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
11678 nil means to draw the underline according to the value of the variable
11679 `x-use-underline-position-properties', which is usually at the baseline
11680 level. The default value is nil. */);
11681 x_underline_at_descent_line
= 0;
11683 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
11684 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
11685 #ifdef USE_TOOLKIT_SCROLL_BARS
11686 Vx_toolkit_scroll_bars
= Qt
;
11688 Vx_toolkit_scroll_bars
= Qnil
;
11691 staticpro (&last_mouse_motion_frame
);
11692 last_mouse_motion_frame
= Qnil
;
11694 /* Variables to configure modifier key assignment. */
11696 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
11697 doc
: /* *Modifier key assumed when the Mac control key is pressed.
11698 The value can be `control', `meta', `alt', `hyper', or `super' for the
11699 respective modifier. The default is `control'. */);
11700 Vmac_control_modifier
= Qcontrol
;
11702 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
11703 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
11704 The value can be `control', `meta', `alt', `hyper', or `super' for the
11705 respective modifier. If the value is nil then the key will act as the
11706 normal Mac control modifier, and the option key can be used to compose
11707 characters depending on the chosen Mac keyboard setting. */);
11708 Vmac_option_modifier
= Qnil
;
11710 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
11711 doc
: /* *Modifier key assumed when the Mac command key is pressed.
11712 The value can be `control', `meta', `alt', `hyper', or `super' for the
11713 respective modifier. The default is `meta'. */);
11714 Vmac_command_modifier
= Qmeta
;
11716 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
11717 doc
: /* *Modifier key assumed when the Mac function key is pressed.
11718 The value can be `control', `meta', `alt', `hyper', or `super' for the
11719 respective modifier. Note that remapping the function key may lead to
11720 unexpected results for some keys on non-US/GB keyboards. */);
11721 Vmac_function_modifier
= Qnil
;
11723 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11724 &Vmac_emulate_three_button_mouse
,
11725 doc
: /* *Specify a way of three button mouse emulation.
11726 The value can be nil, t, or the symbol `reverse'.
11727 nil means that no emulation should be done and the modifiers should be
11728 placed on the mouse-1 event.
11729 t means that when the option-key is held down while pressing the mouse
11730 button, the click will register as mouse-2 and while the command-key
11731 is held down, the click will register as mouse-3.
11732 The symbol `reverse' means that the option-key will register for
11733 mouse-3 and the command-key will register for mouse-2. */);
11734 Vmac_emulate_three_button_mouse
= Qnil
;
11736 #if USE_CARBON_EVENTS
11737 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
11738 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11739 Otherwise, the right click will be treated as mouse-2 and the wheel
11740 button will be mouse-3. */);
11741 mac_wheel_button_is_mouse_2
= 1;
11743 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
11744 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
11745 mac_pass_command_to_system
= 1;
11747 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
11748 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
11749 mac_pass_control_to_system
= 1;
11753 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
11754 doc
: /* *If non-nil, allow anti-aliasing.
11755 The text will be rendered using Core Graphics text rendering which
11756 may anti-alias the text. */);
11758 mac_use_core_graphics
= 1;
11760 mac_use_core_graphics
= 0;
11763 /* Register an entry for `mac-roman' so that it can be used when
11764 creating the terminal frame on Mac OS 9 before loading
11765 term/mac-win.elc. */
11766 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
11767 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
11768 Each entry should be of the form:
11770 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
11772 where CHARSET-NAME is a string used in font names to identify the
11773 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
11774 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
11775 Vmac_charset_info_alist
=
11776 Fcons (list3 (build_string ("mac-roman"),
11777 make_number (smRoman
), Qnil
), Qnil
);
11780 DEFVAR_LISP ("mac-atsu-font-table", &Vmac_atsu_font_table
,
11781 doc
: /* Hash table of ATSU font IDs vs plist of attributes and values. */);
11782 Vmac_atsu_font_table
=
11783 make_hash_table (Qeql
, make_number (DEFAULT_HASH_SIZE
),
11784 make_float (DEFAULT_REHASH_SIZE
),
11785 make_float (DEFAULT_REHASH_THRESHOLD
),
11789 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
11790 doc
: /* Overlay used to display Mac TSM active input area. */);
11791 Vmac_ts_active_input_overlay
= Qnil
;
11793 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
11794 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
11795 If the value is t, the input script and language are restored to those
11796 used in the last focus frame. If the value is a pair of integers, the
11797 input script and language codes, which are defined in the Script
11798 Manager, are set to its car and cdr parts, respectively. Otherwise,
11799 Emacs doesn't set them and thus follows the system default behavior. */);
11800 Vmac_ts_script_language_on_focus
= Qnil
;
11804 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
11805 (do not change this comment) */