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
*,
247 EventRecord
*, struct input_event
*));
248 static void XTframe_rehighlight
P_ ((struct frame
*));
249 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
250 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
251 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
252 enum text_cursor_kinds
));
254 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
255 static void x_flush
P_ ((struct frame
*f
));
256 static void x_update_begin
P_ ((struct frame
*));
257 static void x_update_window_begin
P_ ((struct window
*));
258 static void x_after_update_window_line
P_ ((struct glyph_row
*));
259 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
260 enum scroll_bar_part
*,
261 Lisp_Object
*, Lisp_Object
*,
264 static int is_emacs_window
P_ ((WindowPtr
));
265 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
266 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
268 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
269 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
270 #define GC_FONT(gc) ((gc)->xgcv.font)
271 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
272 #define CG_SET_FILL_COLOR(context, color) \
273 CGContextSetRGBFillColor (context, \
274 RED_FROM_ULONG (color) / 255.0f, \
275 GREEN_FROM_ULONG (color) / 255.0f, \
276 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
277 #define CG_SET_STROKE_COLOR(context, color) \
278 CGContextSetRGBStrokeColor (context, \
279 RED_FROM_ULONG (color) / 255.0f, \
280 GREEN_FROM_ULONG (color) / 255.0f, \
281 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
283 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
285 /* Fringe bitmaps. */
287 static int max_fringe_bmp
= 0;
288 static CGImageRef
*fringe_bmp
= 0;
291 mac_begin_cg_clip (f
, gc
)
295 CGContextRef context
= FRAME_CG_CONTEXT (f
);
299 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
300 FRAME_CG_CONTEXT (f
) = context
;
303 CGContextSaveGState (context
);
304 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
305 CGContextScaleCTM (context
, 1, -1);
306 if (gc
&& gc
->n_clip_rects
)
307 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
316 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
320 mac_prepare_for_quickdraw (f
)
325 Lisp_Object rest
, frame
;
326 FOR_EACH_FRAME (rest
, frame
)
327 if (FRAME_MAC_P (XFRAME (frame
)))
328 mac_prepare_for_quickdraw (XFRAME (frame
));
332 CGContextRef context
= FRAME_CG_CONTEXT (f
);
336 CGContextSynchronize (context
);
337 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
338 &FRAME_CG_CONTEXT (f
));
344 static RgnHandle saved_port_clip_region
= NULL
;
350 static RgnHandle new_region
= NULL
;
352 if (saved_port_clip_region
== NULL
)
353 saved_port_clip_region
= NewRgn ();
354 if (new_region
== NULL
)
355 new_region
= NewRgn ();
357 if (gc
->n_clip_rects
)
359 GetClip (saved_port_clip_region
);
360 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
361 SetClip (new_region
);
369 if (gc
->n_clip_rects
)
370 SetClip (saved_port_clip_region
);
374 /* X display function emulation */
377 XFreePixmap (display
, pixmap
)
378 Display
*display
; /* not used */
381 DisposeGWorld (pixmap
);
385 /* Mac version of XDrawLine. */
388 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
394 CGContextRef context
;
395 float gx1
= x1
, gy1
= y1
, gx2
= x2
, gy2
= y2
;
398 gx1
+= 0.5f
, gx2
+= 0.5f
;
400 gy1
+= 0.5f
, gy2
+= 0.5f
;
402 context
= mac_begin_cg_clip (f
, gc
);
403 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
404 CGContextBeginPath (context
);
405 CGContextMoveToPoint (context
, gx1
, gy1
);
406 CGContextAddLineToPoint (context
, gx2
, gy2
);
407 CGContextClosePath (context
);
408 CGContextStrokePath (context
);
426 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
428 RGBForeColor (GC_FORE_COLOR (gc
));
438 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
462 GetGWorld (&old_port
, &old_gdh
);
465 RGBForeColor (GC_FORE_COLOR (gc
));
467 LockPixels (GetGWorldPixMap (p
));
470 UnlockPixels (GetGWorldPixMap (p
));
472 SetGWorld (old_port
, old_gdh
);
477 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
481 unsigned int width
, height
;
484 CGContextRef context
;
486 context
= mac_begin_cg_clip (f
, gc
);
487 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
488 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
493 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
495 RGBBackColor (GC_BACK_COLOR (gc
));
496 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
502 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
507 /* Mac version of XClearArea. */
510 mac_clear_area (f
, x
, y
, width
, height
)
513 unsigned int width
, height
;
515 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
518 /* Mac version of XClearWindow. */
525 CGContextRef context
;
526 GC gc
= FRAME_NORMAL_GC (f
);
528 context
= mac_begin_cg_clip (f
, NULL
);
529 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
530 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
531 FRAME_PIXEL_HEIGHT (f
)));
534 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
536 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
538 #if TARGET_API_MAC_CARBON
542 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
545 #else /* not TARGET_API_MAC_CARBON */
546 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
547 #endif /* not TARGET_API_MAC_CARBON */
552 /* Mac replacement for XCopyArea. */
556 mac_draw_cg_image (image
, f
, gc
, src_x
, src_y
, width
, height
,
557 dest_x
, dest_y
, overlay_p
)
562 unsigned int width
, height
;
563 int dest_x
, dest_y
, overlay_p
;
565 CGContextRef context
;
566 float port_height
= FRAME_PIXEL_HEIGHT (f
);
567 CGRect dest_rect
= CGRectMake (dest_x
, dest_y
, width
, height
);
569 context
= mac_begin_cg_clip (f
, gc
);
572 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
573 CGContextFillRect (context
, dest_rect
);
575 CGContextClipToRect (context
, dest_rect
);
576 CGContextScaleCTM (context
, 1, -1);
577 CGContextTranslateCTM (context
, 0, -port_height
);
578 if (CGImageIsMask (image
))
579 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
580 CGContextDrawImage (context
,
581 CGRectMake (dest_x
- src_x
,
582 port_height
- (dest_y
- src_y
583 + CGImageGetHeight (image
)),
584 CGImageGetWidth (image
),
585 CGImageGetHeight (image
)),
590 #else /* !USE_CG_DRAWING */
593 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
596 int x
, y
, width
, height
;
597 unsigned short *bits
;
603 bitmap
.rowBytes
= sizeof(unsigned short);
604 bitmap
.baseAddr
= (char *)bits
;
605 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
607 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
609 RGBForeColor (GC_FORE_COLOR (gc
));
610 RGBBackColor (GC_BACK_COLOR (gc
));
611 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
614 #if TARGET_API_MAC_CARBON
620 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
621 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
622 UnlockPortBits (port
);
624 #else /* not TARGET_API_MAC_CARBON */
625 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
626 overlay_p
? srcOr
: srcCopy
, 0);
627 #endif /* not TARGET_API_MAC_CARBON */
630 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
632 #endif /* !USE_CG_DRAWING */
635 /* Mac replacement for XCreateBitmapFromBitmapData. */
638 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
643 static unsigned char swap_nibble
[16]
644 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
645 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
646 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
647 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
651 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
652 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
653 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
654 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
655 for (i
= 0; i
< h
; i
++)
657 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
658 for (j
= 0; j
< w1
; j
++)
660 /* Bitswap XBM bytes to match how Mac does things. */
661 unsigned char c
= *bits
++;
662 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
663 | (swap_nibble
[(c
>>4) & 0xf]));;
667 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
672 mac_free_bitmap (bitmap
)
675 xfree (bitmap
->baseAddr
);
680 XCreatePixmap (display
, w
, width
, height
, depth
)
681 Display
*display
; /* not used */
683 unsigned int width
, height
;
690 SetPortWindowPort (w
);
692 SetRect (&r
, 0, 0, width
, height
);
693 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
696 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
697 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
699 /* CreateCGImageFromPixMaps requires ARGB format. */
700 err
= QTNewGWorld (&pixmap
, k32ARGBPixelFormat
, &r
, NULL
, NULL
, 0);
709 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
710 Display
*display
; /* not used */
713 unsigned int width
, height
;
714 unsigned long fg
, bg
;
721 static GC gc
= NULL
; /* not reentrant */
724 gc
= XCreateGC (display
, w
, 0, NULL
);
726 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
730 GetGWorld (&old_port
, &old_gdh
);
731 SetGWorld (pixmap
, NULL
);
732 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
733 XSetForeground (display
, gc
, fg
);
734 XSetBackground (display
, gc
, bg
);
735 RGBForeColor (GC_FORE_COLOR (gc
));
736 RGBBackColor (GC_BACK_COLOR (gc
));
737 LockPixels (GetGWorldPixMap (pixmap
));
738 #if TARGET_API_MAC_CARBON
739 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
740 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
741 #else /* not TARGET_API_MAC_CARBON */
742 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
743 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
744 #endif /* not TARGET_API_MAC_CARBON */
745 UnlockPixels (GetGWorldPixMap (pixmap
));
746 SetGWorld (old_port
, old_gdh
);
747 mac_free_bitmap (&bitmap
);
753 /* Mac replacement for XFillRectangle. */
756 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
760 unsigned int width
, height
;
763 CGContextRef context
;
765 context
= mac_begin_cg_clip (f
, gc
);
766 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
767 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
772 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
774 RGBForeColor (GC_FORE_COLOR (gc
));
775 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
778 PaintRect (&r
); /* using foreground color of gc */
784 /* Mac replacement for XDrawRectangle: dest is a window. */
787 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
791 unsigned int width
, height
;
794 CGContextRef context
;
796 context
= mac_begin_cg_clip (f
, gc
);
797 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
798 CGContextStrokeRect (context
,
799 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
804 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
806 RGBForeColor (GC_FORE_COLOR (gc
));
807 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
810 FrameRect (&r
); /* using foreground color of gc */
818 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
819 ConstUniCharArrayPtr text
;
820 UniCharCount text_length
;
822 ATSUTextLayout
*text_layout
;
825 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
827 if (saved_text_layout
== NULL
)
829 UniCharCount lengths
[] = {kATSUToTextEnd
};
830 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
831 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
832 static ATSLineLayoutOptions line_layout
=
833 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
834 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
835 | kATSLineUseQDRendering
837 kATSLineIsDisplayOnly
| kATSLineFractDisable
840 ATSUAttributeValuePtr values
[] = {&line_layout
};
842 err
= ATSUCreateTextLayoutWithTextPtr (text
,
843 kATSUFromTextBeginning
,
849 err
= ATSUSetLayoutControls (saved_text_layout
,
850 sizeof (tags
) / sizeof (tags
[0]),
851 tags
, sizes
, values
);
852 /* XXX: Should we do this? */
854 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
858 err
= ATSUSetRunStyle (saved_text_layout
, style
,
859 kATSUFromTextBeginning
, kATSUToTextEnd
);
861 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
862 kATSUFromTextBeginning
,
868 *text_layout
= saved_text_layout
;
875 mac_invert_rectangle (f
, x
, y
, width
, height
)
878 unsigned int width
, height
;
883 mac_prepare_for_quickdraw (f
);
885 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
887 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
894 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, bytes_per_char
)
899 int nchars
, bg_width
, bytes_per_char
;
901 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
904 if (GC_FONT (gc
)->mac_style
)
907 ATSUTextLayout text_layout
;
909 xassert (bytes_per_char
== 2);
911 #ifndef WORDS_BIG_ENDIAN
914 UniChar
*text
= (UniChar
*)buf
;
916 for (i
= 0; i
< nchars
; i
++)
917 text
[i
] = EndianU16_BtoN (text
[i
]);
920 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
922 GC_FONT (gc
)->mac_style
,
927 if (!mac_use_core_graphics
)
931 mac_prepare_for_quickdraw (f
);
934 RGBForeColor (GC_FORE_COLOR (gc
));
939 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
940 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
941 RGBBackColor (GC_BACK_COLOR (gc
));
943 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
946 ATSUDrawText (text_layout
,
947 kATSUFromTextBeginning
, kATSUToTextEnd
,
948 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
955 CGContextRef context
;
956 float port_height
= FRAME_PIXEL_HEIGHT (f
);
957 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
958 ByteCount sizes
[] = {sizeof (CGContextRef
)};
959 ATSUAttributeValuePtr values
[] = {&context
};
962 context
= mac_begin_cg_clip (f
, gc
);
965 QDBeginCGContext (port
, &context
);
966 if (gc
->n_clip_rects
|| bg_width
)
968 CGContextTranslateCTM (context
, 0, port_height
);
969 CGContextScaleCTM (context
, 1, -1);
970 if (gc
->n_clip_rects
)
971 CGContextClipToRects (context
, gc
->clip_rects
,
976 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
979 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
980 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
982 CGContextScaleCTM (context
, 1, -1);
983 CGContextTranslateCTM (context
, 0, -port_height
);
987 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
988 err
= ATSUSetLayoutControls (text_layout
,
989 sizeof (tags
) / sizeof (tags
[0]),
990 tags
, sizes
, values
);
992 ATSUDrawText (text_layout
,
993 kATSUFromTextBeginning
, kATSUToTextEnd
,
994 Long2Fix (x
), Long2Fix (port_height
- y
));
999 CGContextSynchronize (context
);
1000 QDEndCGContext (port
, &context
);
1003 /* This doesn't work on Mac OS X 10.1. */
1004 ATSUClearLayoutControls (text_layout
,
1005 sizeof (tags
) / sizeof (tags
[0]), tags
);
1007 ATSUSetLayoutControls (text_layout
,
1008 sizeof (tags
) / sizeof (tags
[0]),
1009 tags
, sizes
, values
);
1012 #endif /* MAC_OSX */
1015 #endif /* USE_ATSUI */
1017 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1020 if (mac_use_core_graphics
)
1021 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
1024 mac_prepare_for_quickdraw (f
);
1026 mac_begin_clip (gc
);
1027 RGBForeColor (GC_FORE_COLOR (gc
));
1031 RGBBackColor (GC_BACK_COLOR (gc
));
1037 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1039 - Screen is double-buffered. (In srcCopy mode, a text is
1040 drawn into an offscreen graphics world first. So
1041 performance gain cannot be expected.)
1042 - It lowers rendering quality.
1043 - Some fonts leave garbage on cursor movement. */
1048 RGBBackColor (GC_BACK_COLOR (gc
));
1049 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
1050 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
1055 TextFont (GC_FONT (gc
)->mac_fontnum
);
1056 TextSize (GC_FONT (gc
)->mac_fontsize
);
1057 TextFace (GC_FONT (gc
)->mac_fontface
);
1059 DrawText (buf
, 0, nchars
* bytes_per_char
);
1061 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1064 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1065 if (mac_use_core_graphics
)
1066 SwapQDTextFlags(savedFlags
);
1072 /* Mac replacement for XDrawString. */
1075 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
1082 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, 0, 1);
1086 /* Mac replacement for XDrawString16. */
1089 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
1096 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, 0, 2);
1100 /* Mac replacement for XDrawImageString. */
1103 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1108 int nchars
, bg_width
;
1110 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, 1);
1114 /* Mac replacement for XDrawString16. */
1117 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1122 int nchars
, bg_width
;
1124 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
, 2);
1128 /* Mac replacement for XQueryTextExtents, but takes a character. If
1129 STYLE is NULL, measurement is done by QuickDraw Text routines for
1130 the font of the current graphics port. If CG_GLYPH is not NULL,
1131 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1134 mac_query_char_extents (style
, c
,
1135 font_ascent_return
, font_descent_return
,
1136 overall_return
, cg_glyph
)
1143 int *font_ascent_return
, *font_descent_return
;
1144 XCharStruct
*overall_return
;
1145 #if USE_CG_TEXT_DRAWING
1151 OSStatus err
= noErr
;
1158 ATSUTextLayout text_layout
;
1161 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1164 ATSTrapezoid glyph_bounds
;
1166 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1167 kATSUFromTextBeginning
, kATSUToTextEnd
,
1168 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1169 kATSUseFractionalOrigins
,
1171 kATSUseDeviceOrigins
,
1173 1, &glyph_bounds
, NULL
);
1176 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1177 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1179 width
= Fix2Long (glyph_bounds
.upperRight
.x
1180 - glyph_bounds
.upperLeft
.x
);
1181 if (font_ascent_return
)
1182 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1183 if (font_descent_return
)
1184 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1187 if (err
== noErr
&& overall_return
)
1189 err
= ATSUMeasureTextImage (text_layout
,
1190 kATSUFromTextBeginning
, kATSUToTextEnd
,
1191 0, 0, &char_bounds
);
1193 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1194 #if USE_CG_TEXT_DRAWING
1195 if (err
== noErr
&& cg_glyph
)
1198 ATSUGlyphInfoArray glyph_info_array
;
1199 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1201 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1202 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1204 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1205 kATSUToTextEnd
, &count
,
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
)
1303 int nchars
, bg_width
;
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
);
1366 for (i
= 0; i
< nchars
; i
++)
1368 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1369 gx
+= advances
[i
].width
;
1373 mac_end_cg_clip (f
);
1375 CGContextSynchronize (context
);
1376 QDEndCGContext (port
, &context
);
1385 /* Mac replacement for XCopyArea: dest must be window. */
1388 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1393 unsigned int width
, height
;
1398 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1400 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1401 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1403 ForeColor (blackColor
);
1404 BackColor (whiteColor
);
1406 mac_begin_clip (gc
);
1407 LockPixels (GetGWorldPixMap (src
));
1408 #if TARGET_API_MAC_CARBON
1413 LockPortBits (port
);
1414 CopyBits (GetPortBitMapForCopyBits (src
),
1415 GetPortBitMapForCopyBits (port
),
1416 &src_r
, &dest_r
, srcCopy
, 0);
1417 UnlockPortBits (port
);
1419 #else /* not TARGET_API_MAC_CARBON */
1420 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1421 &src_r
, &dest_r
, srcCopy
, 0);
1422 #endif /* not TARGET_API_MAC_CARBON */
1423 UnlockPixels (GetGWorldPixMap (src
));
1426 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1431 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1432 width
, height
, dest_x
, dest_y
)
1437 unsigned int width
, height
;
1442 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1444 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1445 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1447 ForeColor (blackColor
);
1448 BackColor (whiteColor
);
1450 mac_begin_clip (gc
);
1451 LockPixels (GetGWorldPixMap (src
));
1452 LockPixels (GetGWorldPixMap (mask
));
1453 #if TARGET_API_MAC_CARBON
1458 LockPortBits (port
);
1459 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1460 GetPortBitMapForCopyBits (port
),
1461 &src_r
, &src_r
, &dest_r
);
1462 UnlockPortBits (port
);
1464 #else /* not TARGET_API_MAC_CARBON */
1465 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1466 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1467 #endif /* not TARGET_API_MAC_CARBON */
1468 UnlockPixels (GetGWorldPixMap (mask
));
1469 UnlockPixels (GetGWorldPixMap (src
));
1472 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1474 #endif /* !USE_CG_DRAWING */
1477 /* Mac replacement for XCopyArea: used only for scrolling. */
1480 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1484 unsigned int width
, height
;
1487 #if TARGET_API_MAC_CARBON
1489 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1491 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1493 mac_prepare_for_quickdraw (f
);
1495 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1496 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1497 kScrollWindowNoOptions
, dummy
);
1499 #else /* not TARGET_API_MAC_CARBON */
1501 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1505 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1506 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1508 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1509 color mapping in CopyBits. Otherwise, it will be slow. */
1510 ForeColor (blackColor
);
1511 BackColor (whiteColor
);
1512 mac_begin_clip (gc
);
1513 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1516 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1517 #endif /* not TARGET_API_MAC_CARBON */
1521 /* Mac replacement for XChangeGC. */
1524 XChangeGC (display
, gc
, mask
, xgcv
)
1530 if (mask
& GCForeground
)
1531 XSetForeground (display
, gc
, xgcv
->foreground
);
1532 if (mask
& GCBackground
)
1533 XSetBackground (display
, gc
, xgcv
->background
);
1535 XSetFont (display
, gc
, xgcv
->font
);
1539 /* Mac replacement for XCreateGC. */
1542 XCreateGC (display
, window
, mask
, xgcv
)
1548 GC gc
= xmalloc (sizeof (*gc
));
1550 bzero (gc
, sizeof (*gc
));
1551 XChangeGC (display
, gc
, mask
, xgcv
);
1557 /* Used in xfaces.c. */
1560 XFreeGC (display
, gc
)
1564 if (gc
->clip_region
)
1565 DisposeRgn (gc
->clip_region
);
1570 /* Mac replacement for XGetGCValues. */
1573 XGetGCValues (display
, gc
, mask
, xgcv
)
1579 if (mask
& GCForeground
)
1580 xgcv
->foreground
= gc
->xgcv
.foreground
;
1581 if (mask
& GCBackground
)
1582 xgcv
->background
= gc
->xgcv
.background
;
1584 xgcv
->font
= gc
->xgcv
.font
;
1588 /* Mac replacement for XSetForeground. */
1591 XSetForeground (display
, gc
, color
)
1594 unsigned long color
;
1596 if (gc
->xgcv
.foreground
!= color
)
1598 gc
->xgcv
.foreground
= color
;
1599 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1600 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1601 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1606 /* Mac replacement for XSetBackground. */
1609 XSetBackground (display
, gc
, color
)
1612 unsigned long color
;
1614 if (gc
->xgcv
.background
!= color
)
1616 gc
->xgcv
.background
= color
;
1617 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1618 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1619 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1624 /* Mac replacement for XSetFont. */
1627 XSetFont (display
, gc
, font
)
1632 gc
->xgcv
.font
= font
;
1636 /* Mac replacement for XSetClipRectangles. */
1639 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1647 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1649 gc
->n_clip_rects
= n
;
1652 if (gc
->clip_region
== NULL
)
1653 gc
->clip_region
= NewRgn ();
1654 RectRgn (gc
->clip_region
, rectangles
);
1657 RgnHandle region
= NewRgn ();
1659 for (i
= 1; i
< n
; i
++)
1661 RectRgn (region
, rectangles
+ i
);
1662 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1664 DisposeRgn (region
);
1667 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1668 for (i
= 0; i
< n
; i
++)
1670 Rect
*rect
= rectangles
+ i
;
1672 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1673 rect
->right
- rect
->left
,
1674 rect
->bottom
- rect
->top
);
1680 /* Mac replacement for XSetClipMask. */
1683 mac_reset_clip_rectangles (display
, gc
)
1687 gc
->n_clip_rects
= 0;
1691 /* Mac replacement for XSetWindowBackground. */
1694 XSetWindowBackground (display
, w
, color
)
1697 unsigned long color
;
1699 #if !TARGET_API_MAC_CARBON
1700 AuxWinHandle aw_handle
;
1701 CTabHandle ctab_handle
;
1702 ColorSpecPtr ct_table
;
1707 bg_color
.red
= RED16_FROM_ULONG (color
);
1708 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1709 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1711 #if TARGET_API_MAC_CARBON
1712 SetWindowContentColor (w
, &bg_color
);
1714 if (GetAuxWin (w
, &aw_handle
))
1716 ctab_handle
= (*aw_handle
)->awCTable
;
1717 HandToHand ((Handle
*) &ctab_handle
);
1718 ct_table
= (*ctab_handle
)->ctTable
;
1719 ct_size
= (*ctab_handle
)->ctSize
;
1720 while (ct_size
> -1)
1722 if (ct_table
->value
== 0)
1724 ct_table
->rgb
= bg_color
;
1725 CTabChanged (ctab_handle
);
1726 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1734 /* Flush display of frame F, or of all frames if F is null. */
1740 #if TARGET_API_MAC_CARBON
1743 mac_prepare_for_quickdraw (f
);
1746 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1748 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1754 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1755 Calls to XFlush should be unnecessary because the X output buffer
1756 is flushed automatically as needed by calls to XPending,
1757 XNextEvent, or XWindowEvent according to the XFlush man page.
1758 XTread_socket calls XPending. Removing XFlush improves
1761 #define XFlush(DISPLAY) (void) 0
1764 /* Return the struct mac_display_info corresponding to DPY. There's
1767 struct mac_display_info
*
1768 mac_display_info_for_display (dpy
)
1771 return &one_mac_display_info
;
1776 /***********************************************************************
1777 Starting and ending an update
1778 ***********************************************************************/
1780 /* Start an update of frame F. This function is installed as a hook
1781 for update_begin, i.e. it is called when update_begin is called.
1782 This function is called prior to calls to x_update_window_begin for
1783 each window being updated. */
1789 #if TARGET_API_MAC_CARBON
1790 /* During update of a frame, availability of input events is
1791 periodically checked with ReceiveNextEvent if
1792 redisplay-dont-pause is nil. That normally flushes window buffer
1793 changes for every check, and thus screen update looks waving even
1794 if no input is available. So we disable screen updates during
1795 update of a frame. */
1797 DisableScreenUpdates ();
1803 /* Start update of window W. Set the global variable updated_window
1804 to the window being updated and set output_cursor to the cursor
1808 x_update_window_begin (w
)
1811 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1812 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1815 set_output_cursor (&w
->cursor
);
1819 if (f
== display_info
->mouse_face_mouse_frame
)
1821 /* Don't do highlighting for mouse motion during the update. */
1822 display_info
->mouse_face_defer
= 1;
1824 /* If F needs to be redrawn, simply forget about any prior mouse
1826 if (FRAME_GARBAGED_P (f
))
1827 display_info
->mouse_face_window
= Qnil
;
1829 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1830 their mouse_face_p flag set, which means that they are always
1831 unequal to rows in a desired matrix which never have that
1832 flag set. So, rows containing mouse-face glyphs are never
1833 scrolled, and we don't have to switch the mouse highlight off
1834 here to prevent it from being scrolled. */
1836 /* Can we tell that this update does not affect the window
1837 where the mouse highlight is? If so, no need to turn off.
1838 Likewise, don't do anything if the frame is garbaged;
1839 in that case, the frame's current matrix that we would use
1840 is all wrong, and we will redisplay that line anyway. */
1841 if (!NILP (display_info
->mouse_face_window
)
1842 && w
== XWINDOW (display_info
->mouse_face_window
))
1846 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1847 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1850 if (i
< w
->desired_matrix
->nrows
)
1851 clear_mouse_face (display_info
);
1860 /* Draw a vertical window border from (x,y0) to (x,y1) */
1863 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1867 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1870 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1872 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1875 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1878 /* End update of window W (which is equal to updated_window).
1880 Draw vertical borders between horizontally adjacent windows, and
1881 display W's cursor if CURSOR_ON_P is non-zero.
1883 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1884 glyphs in mouse-face were overwritten. In that case we have to
1885 make sure that the mouse-highlight is properly redrawn.
1887 W may be a menu bar pseudo-window in case we don't have X toolkit
1888 support. Such windows don't have a cursor, so don't display it
1892 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1894 int cursor_on_p
, mouse_face_overwritten_p
;
1896 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1898 if (!w
->pseudo_window_p
)
1903 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1905 output_cursor
.x
, output_cursor
.y
);
1907 if (draw_window_fringes (w
, 1))
1908 x_draw_vertical_border (w
);
1913 /* If a row with mouse-face was overwritten, arrange for
1914 XTframe_up_to_date to redisplay the mouse highlight. */
1915 if (mouse_face_overwritten_p
)
1917 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1918 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1919 dpyinfo
->mouse_face_window
= Qnil
;
1922 updated_window
= NULL
;
1926 /* End update of frame F. This function is installed as a hook in
1933 /* Mouse highlight may be displayed again. */
1934 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1937 #if TARGET_API_MAC_CARBON
1938 EnableScreenUpdates ();
1940 XFlush (FRAME_MAC_DISPLAY (f
));
1945 /* This function is called from various places in xdisp.c whenever a
1946 complete update has been performed. The global variable
1947 updated_window is not available here. */
1950 XTframe_up_to_date (f
)
1953 if (FRAME_MAC_P (f
))
1955 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1957 if (dpyinfo
->mouse_face_deferred_gc
1958 || f
== dpyinfo
->mouse_face_mouse_frame
)
1961 if (dpyinfo
->mouse_face_mouse_frame
)
1962 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1963 dpyinfo
->mouse_face_mouse_x
,
1964 dpyinfo
->mouse_face_mouse_y
);
1965 dpyinfo
->mouse_face_deferred_gc
= 0;
1972 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1973 arrow bitmaps, or clear the fringes if no bitmaps are required
1974 before DESIRED_ROW is made current. The window being updated is
1975 found in updated_window. This function is called from
1976 update_window_line only if it is known that there are differences
1977 between bitmaps to be drawn between current row and DESIRED_ROW. */
1980 x_after_update_window_line (desired_row
)
1981 struct glyph_row
*desired_row
;
1983 struct window
*w
= updated_window
;
1989 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1990 desired_row
->redraw_fringe_bitmaps_p
= 1;
1992 /* When a window has disappeared, make sure that no rest of
1993 full-width rows stays visible in the internal border. Could
1994 check here if updated_window is the leftmost/rightmost window,
1995 but I guess it's not worth doing since vertically split windows
1996 are almost never used, internal border is rarely set, and the
1997 overhead is very small. */
1998 if (windows_or_buffers_changed
1999 && desired_row
->full_width_p
2000 && (f
= XFRAME (w
->frame
),
2001 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
2003 && (height
= desired_row
->visible_height
,
2006 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
2008 /* Internal border is drawn below the tool bar. */
2009 if (WINDOWP (f
->tool_bar_window
)
2010 && w
== XWINDOW (f
->tool_bar_window
))
2014 mac_clear_area (f
, 0, y
, width
, height
);
2015 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
2021 /* Draw the bitmap WHICH in one of the left or right fringes of
2022 window W. ROW is the glyph row for which to display the bitmap; it
2023 determines the vertical position at which the bitmap has to be
2027 x_draw_fringe_bitmap (w
, row
, p
)
2029 struct glyph_row
*row
;
2030 struct draw_fringe_bitmap_params
*p
;
2032 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2033 Display
*display
= FRAME_MAC_DISPLAY (f
);
2034 struct face
*face
= p
->face
;
2037 /* Must clip because of partially visible lines. */
2038 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
2041 /* Adjust position of "bottom aligned" bitmap on partially
2042 visible last row. */
2044 int oldVH
= row
->visible_height
;
2045 row
->visible_height
= p
->h
;
2046 row
->y
-= rowY
- p
->y
;
2047 x_clip_to_row (w
, row
, -1, face
->gc
);
2049 row
->visible_height
= oldVH
;
2052 x_clip_to_row (w
, row
, -1, face
->gc
);
2054 if (p
->bx
>= 0 && !p
->overlay_p
)
2056 #if 0 /* MAC_TODO: stipple */
2057 /* In case the same realized face is used for fringes and
2058 for something displayed in the text (e.g. face `region' on
2059 mono-displays, the fill style may have been changed to
2060 FillSolid in x_draw_glyph_string_background. */
2062 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
2064 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
2067 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
2069 #if 0 /* MAC_TODO: stipple */
2071 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2077 && p
->which
< max_fringe_bmp
2083 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2084 XSetForeground (display
, face
->gc
,
2086 ? (p
->overlay_p
? face
->background
2087 : f
->output_data
.mac
->cursor_pixel
)
2088 : face
->foreground
));
2090 mac_draw_cg_image (fringe_bmp
[p
->which
], f
, face
->gc
, 0, p
->dh
,
2091 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
2093 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2094 p
->wd
, p
->h
, p
->bits
+ p
->dh
, p
->overlay_p
);
2096 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2099 mac_reset_clip_rectangles (display
, face
->gc
);
2104 mac_define_fringe_bitmap (which
, bits
, h
, wd
)
2106 unsigned short *bits
;
2110 CGDataProviderRef provider
;
2112 if (which
>= max_fringe_bmp
)
2115 max_fringe_bmp
= which
+ 20;
2116 fringe_bmp
= (CGImageRef
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (CGImageRef
));
2117 while (i
< max_fringe_bmp
)
2118 fringe_bmp
[i
++] = 0;
2121 for (i
= 0; i
< h
; i
++)
2123 provider
= CGDataProviderCreateWithData (NULL
, bits
,
2124 sizeof (unsigned short) * h
, NULL
);
2127 fringe_bmp
[which
] = CGImageMaskCreate (wd
, h
, 1, 1,
2128 sizeof (unsigned short),
2130 CGDataProviderRelease (provider
);
2135 mac_destroy_fringe_bitmap (which
)
2138 if (which
>= max_fringe_bmp
)
2141 if (fringe_bmp
[which
])
2142 CGImageRelease (fringe_bmp
[which
]);
2143 fringe_bmp
[which
] = 0;
2148 /* This is called when starting Emacs and when restarting after
2149 suspend. When starting Emacs, no window is mapped. And nothing
2150 must be done to Emacs's own window if it is suspended (though that
2154 XTset_terminal_modes ()
2158 /* This is called when exiting or suspending Emacs. Exiting will make
2159 the windows go away, and suspending requires no action. */
2162 XTreset_terminal_modes ()
2168 /***********************************************************************
2170 ***********************************************************************/
2172 /* Function prototypes of this page. */
2174 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2175 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2179 pcm_init (pcm
, count
)
2183 bzero (pcm
, sizeof (XCharStruct
) * count
);
2184 while (--count
>= 0)
2186 pcm
->descent
= PCM_INVALID
;
2191 static enum pcm_status
2192 pcm_get_status (pcm
)
2195 int height
= pcm
->ascent
+ pcm
->descent
;
2197 /* Negative height means some special status. */
2198 return height
>= 0 ? PCM_VALID
: height
;
2201 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2202 is not contained in the font. */
2204 static INLINE XCharStruct
*
2205 x_per_char_metric (font
, char2b
)
2209 /* The result metric information. */
2210 XCharStruct
*pcm
= NULL
;
2212 xassert (font
&& char2b
);
2215 if (font
->mac_style
)
2217 XCharStruct
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2221 *row
= xmalloc (sizeof (XCharStruct
) * 0x100);
2222 pcm_init (*row
, 0x100);
2224 pcm
= *row
+ char2b
->byte2
;
2225 if (pcm_get_status (pcm
) != PCM_VALID
)
2228 mac_query_char_extents (font
->mac_style
,
2229 (char2b
->byte1
<< 8) + char2b
->byte2
,
2230 NULL
, NULL
, pcm
, NULL
);
2237 if (font
->bounds
.per_char
!= NULL
)
2239 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2241 /* min_char_or_byte2 specifies the linear character index
2242 corresponding to the first element of the per_char array,
2243 max_char_or_byte2 is the index of the last character. A
2244 character with non-zero CHAR2B->byte1 is not in the font.
2245 A character with byte2 less than min_char_or_byte2 or
2246 greater max_char_or_byte2 is not in the font. */
2247 if (char2b
->byte1
== 0
2248 && char2b
->byte2
>= font
->min_char_or_byte2
2249 && char2b
->byte2
<= font
->max_char_or_byte2
)
2250 pcm
= font
->bounds
.per_char
2251 + (char2b
->byte2
- font
->min_char_or_byte2
);
2255 /* If either min_byte1 or max_byte1 are nonzero, both
2256 min_char_or_byte2 and max_char_or_byte2 are less than
2257 256, and the 2-byte character index values corresponding
2258 to the per_char array element N (counting from 0) are:
2260 byte1 = N/D + min_byte1
2261 byte2 = N\D + min_char_or_byte2
2265 D = max_char_or_byte2 - min_char_or_byte2 + 1
2266 / = integer division
2267 \ = integer modulus */
2268 if (char2b
->byte1
>= font
->min_byte1
2269 && char2b
->byte1
<= font
->max_byte1
2270 && char2b
->byte2
>= font
->min_char_or_byte2
2271 && char2b
->byte2
<= font
->max_char_or_byte2
)
2273 pcm
= (font
->bounds
.per_char
2274 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2275 * (char2b
->byte1
- font
->min_byte1
))
2276 + (char2b
->byte2
- font
->min_char_or_byte2
));
2282 /* If the per_char pointer is null, all glyphs between the first
2283 and last character indexes inclusive have the same
2284 information, as given by both min_bounds and max_bounds. */
2285 if (char2b
->byte2
>= font
->min_char_or_byte2
2286 && char2b
->byte2
<= font
->max_char_or_byte2
)
2287 pcm
= &font
->max_bounds
;
2293 return ((pcm
== NULL
2295 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2296 && (pcm
->rbearing
- pcm
->lbearing
) == 0
2305 static XCharStruct
*
2306 mac_per_char_metric (font
, char2b
, font_type
)
2311 return x_per_char_metric (font
, char2b
);
2315 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2316 the two-byte form of C. Encoding is returned in *CHAR2B. */
2319 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2322 struct font_info
*font_info
;
2325 int charset
= CHAR_CHARSET (c
);
2326 XFontStruct
*font
= font_info
->font
;
2328 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2329 This may be either a program in a special encoder language or a
2331 if (font_info
->font_encoder
)
2333 /* It's a program. */
2334 struct ccl_program
*ccl
= font_info
->font_encoder
;
2336 check_ccl_update (ccl
);
2337 if (CHARSET_DIMENSION (charset
) == 1)
2339 ccl
->reg
[0] = charset
;
2340 ccl
->reg
[1] = char2b
->byte2
;
2345 ccl
->reg
[0] = charset
;
2346 ccl
->reg
[1] = char2b
->byte1
;
2347 ccl
->reg
[2] = char2b
->byte2
;
2350 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2352 /* We assume that MSBs are appropriately set/reset by CCL
2354 if (font
->max_byte1
== 0) /* 1-byte font */
2355 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2357 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2359 else if (font_info
->encoding
[charset
])
2361 /* Fixed encoding scheme. See fontset.h for the meaning of the
2362 encoding numbers. */
2363 int enc
= font_info
->encoding
[charset
];
2365 if ((enc
== 1 || enc
== 2)
2366 && CHARSET_DIMENSION (charset
) == 2)
2367 char2b
->byte1
|= 0x80;
2369 if (enc
== 1 || enc
== 3)
2370 char2b
->byte2
|= 0x80;
2376 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2377 char2b
->byte1
= sjis1
;
2378 char2b
->byte2
= sjis2
;
2383 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2385 return FONT_TYPE_UNKNOWN
;
2390 /***********************************************************************
2392 ***********************************************************************/
2396 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2397 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2398 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2400 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2401 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2402 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2403 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2404 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2405 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2406 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2407 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2408 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2409 unsigned long *, double, int));*/
2410 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2411 double, int, unsigned long));
2412 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2413 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2414 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2415 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2416 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2418 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2419 int, int, int, int, int, int,
2421 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2422 int, int, int, Rect
*));
2425 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2429 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2434 struct glyph_string
*s
;
2436 if (s
->font
== FRAME_FONT (s
->f
)
2437 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2438 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2440 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2443 /* Cursor on non-default face: must merge. */
2447 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2448 xgcv
.foreground
= s
->face
->background
;
2450 /* If the glyph would be invisible, try a different foreground. */
2451 if (xgcv
.foreground
== xgcv
.background
)
2452 xgcv
.foreground
= s
->face
->foreground
;
2453 if (xgcv
.foreground
== xgcv
.background
)
2454 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2455 if (xgcv
.foreground
== xgcv
.background
)
2456 xgcv
.foreground
= s
->face
->foreground
;
2458 /* Make sure the cursor is distinct from text in this face. */
2459 if (xgcv
.background
== s
->face
->background
2460 && xgcv
.foreground
== s
->face
->foreground
)
2462 xgcv
.background
= s
->face
->foreground
;
2463 xgcv
.foreground
= s
->face
->background
;
2466 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2467 xgcv
.font
= s
->font
;
2468 mask
= GCForeground
| GCBackground
| GCFont
;
2470 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2471 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2474 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2475 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2477 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2482 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2485 x_set_mouse_face_gc (s
)
2486 struct glyph_string
*s
;
2491 /* What face has to be used last for the mouse face? */
2492 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2493 face
= FACE_FROM_ID (s
->f
, face_id
);
2495 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2497 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2498 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2500 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2501 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2502 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2504 /* If font in this face is same as S->font, use it. */
2505 if (s
->font
== s
->face
->font
)
2506 s
->gc
= s
->face
->gc
;
2509 /* Otherwise construct scratch_cursor_gc with values from FACE
2514 xgcv
.background
= s
->face
->background
;
2515 xgcv
.foreground
= s
->face
->foreground
;
2516 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2517 xgcv
.font
= s
->font
;
2518 mask
= GCForeground
| GCBackground
| GCFont
;
2520 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2521 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2524 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2525 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2527 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2530 xassert (s
->gc
!= 0);
2534 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2535 Faces to use in the mode line have already been computed when the
2536 matrix was built, so there isn't much to do, here. */
2539 x_set_mode_line_face_gc (s
)
2540 struct glyph_string
*s
;
2542 s
->gc
= s
->face
->gc
;
2546 /* Set S->gc of glyph string S for drawing that glyph string. Set
2547 S->stippled_p to a non-zero value if the face of S has a stipple
2551 x_set_glyph_string_gc (s
)
2552 struct glyph_string
*s
;
2554 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2556 if (s
->hl
== DRAW_NORMAL_TEXT
)
2558 s
->gc
= s
->face
->gc
;
2559 s
->stippled_p
= s
->face
->stipple
!= 0;
2561 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2563 x_set_mode_line_face_gc (s
);
2564 s
->stippled_p
= s
->face
->stipple
!= 0;
2566 else if (s
->hl
== DRAW_CURSOR
)
2568 x_set_cursor_gc (s
);
2571 else if (s
->hl
== DRAW_MOUSE_FACE
)
2573 x_set_mouse_face_gc (s
);
2574 s
->stippled_p
= s
->face
->stipple
!= 0;
2576 else if (s
->hl
== DRAW_IMAGE_RAISED
2577 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2579 s
->gc
= s
->face
->gc
;
2580 s
->stippled_p
= s
->face
->stipple
!= 0;
2584 s
->gc
= s
->face
->gc
;
2585 s
->stippled_p
= s
->face
->stipple
!= 0;
2588 /* GC must have been set. */
2589 xassert (s
->gc
!= 0);
2593 /* Set clipping for output of glyph string S. S may be part of a mode
2594 line or menu if we don't have X toolkit support. */
2597 x_set_glyph_string_clipping (s
)
2598 struct glyph_string
*s
;
2600 Rect rects
[MAX_CLIP_RECTS
];
2603 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2604 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2609 Compute left and right overhang of glyph string S. If S is a glyph
2610 string for a composition, assume overhangs don't exist. */
2613 mac_compute_glyph_string_overhangs (s
)
2614 struct glyph_string
*s
;
2616 if (!(s
->cmp
== NULL
2617 && s
->first_glyph
->type
== CHAR_GLYPH
))
2622 || s
->font
->mac_style
2628 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2629 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2630 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2635 MacFontStruct
*font
= s
->font
;
2637 TextFont (font
->mac_fontnum
);
2638 TextSize (font
->mac_fontsize
);
2639 TextFace (font
->mac_fontface
);
2641 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2643 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2644 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2649 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2652 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2653 struct glyph_string
*s
;
2656 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2660 /* Draw the background of glyph_string S. If S->background_filled_p
2661 is non-zero don't draw it. FORCE_P non-zero means draw the
2662 background even if it wouldn't be drawn normally. This is used
2663 when a string preceding S draws into the background of S, or S
2664 contains the first component of a composition. */
2667 x_draw_glyph_string_background (s
, force_p
)
2668 struct glyph_string
*s
;
2671 /* Nothing to do if background has already been drawn or if it
2672 shouldn't be drawn in the first place. */
2673 if (!s
->background_filled_p
)
2675 int box_line_width
= max (s
->face
->box_line_width
, 0);
2677 #if 0 /* MAC_TODO: stipple */
2680 /* Fill background with a stipple pattern. */
2681 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2682 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2683 s
->y
+ box_line_width
,
2684 s
->background_width
,
2685 s
->height
- 2 * box_line_width
);
2686 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2687 s
->background_filled_p
= 1;
2691 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2692 || s
->font_not_found_p
2693 || s
->extends_to_end_of_line_p
2696 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2697 s
->background_width
,
2698 s
->height
- 2 * box_line_width
);
2699 s
->background_filled_p
= 1;
2705 /* Draw the foreground of glyph string S. */
2708 x_draw_glyph_string_foreground (s
)
2709 struct glyph_string
*s
;
2713 /* If first glyph of S has a left box line, start drawing the text
2714 of S to the right of that box line. */
2715 if (s
->face
->box
!= FACE_NO_BOX
2716 && s
->first_glyph
->left_box_line_p
)
2717 x
= s
->x
+ abs (s
->face
->box_line_width
);
2721 /* Draw characters of S as rectangles if S's font could not be
2723 if (s
->font_not_found_p
)
2725 for (i
= 0; i
< s
->nchars
; ++i
)
2727 struct glyph
*g
= s
->first_glyph
+ i
;
2728 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2729 g
->pixel_width
- 1, s
->height
- 1);
2730 x
+= g
->pixel_width
;
2735 char *char1b
= (char *) s
->char2b
;
2736 int boff
= s
->font_info
->baseline_offset
;
2738 if (s
->font_info
->vertical_centering
)
2739 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2741 /* If we can use 8-bit functions, condense S->char2b. */
2744 && GC_FONT (s
->gc
)->mac_style
== NULL
2747 for (i
= 0; i
< s
->nchars
; ++i
)
2748 char1b
[i
] = s
->char2b
[i
].byte2
;
2750 /* Draw text with XDrawString if background has already been
2751 filled. Otherwise, use XDrawImageString. (Note that
2752 XDrawImageString is usually faster than XDrawString.) Always
2753 use XDrawImageString when drawing the cursor so that there is
2754 no chance that characters under a box cursor are invisible. */
2756 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2757 bg_width
= 0; /* Corresponds to XDrawString. */
2759 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2763 || GC_FONT (s
->gc
)->mac_style
2766 #if USE_CG_TEXT_DRAWING
2768 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2769 s
->char2b
, s
->nchars
, bg_width
))
2773 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2774 s
->char2b
, s
->nchars
, bg_width
);
2776 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2777 char1b
, s
->nchars
, bg_width
);
2781 /* Draw the foreground of composite glyph string S. */
2784 x_draw_composite_glyph_string_foreground (s
)
2785 struct glyph_string
*s
;
2789 /* If first glyph of S has a left box line, start drawing the text
2790 of S to the right of that box line. */
2791 if (s
->face
->box
!= FACE_NO_BOX
2792 && s
->first_glyph
->left_box_line_p
)
2793 x
= s
->x
+ abs (s
->face
->box_line_width
);
2797 /* S is a glyph string for a composition. S->gidx is the index of
2798 the first character drawn for glyphs of this composition.
2799 S->gidx == 0 means we are drawing the very first character of
2800 this composition. */
2802 /* Draw a rectangle for the composition if the font for the very
2803 first character of the composition could not be loaded. */
2804 if (s
->font_not_found_p
)
2807 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2808 s
->width
- 1, s
->height
- 1);
2812 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2813 mac_draw_string_16 (s
->f
, s
->gc
,
2814 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2815 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2821 #ifdef USE_X_TOOLKIT
2823 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2826 /* Return the frame on which widget WIDGET is used.. Abort if frame
2827 cannot be determined. */
2829 static struct frame
*
2830 x_frame_of_widget (widget
)
2833 struct x_display_info
*dpyinfo
;
2837 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2839 /* Find the top-level shell of the widget. Note that this function
2840 can be called when the widget is not yet realized, so XtWindow
2841 (widget) == 0. That's the reason we can't simply use
2842 x_any_window_to_frame. */
2843 while (!XtIsTopLevelShell (widget
))
2844 widget
= XtParent (widget
);
2846 /* Look for a frame with that top-level widget. Allocate the color
2847 on that frame to get the right gamma correction value. */
2848 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2849 if (GC_FRAMEP (XCAR (tail
))
2850 && (f
= XFRAME (XCAR (tail
)),
2851 (f
->output_data
.nothing
!= 1
2852 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2853 && f
->output_data
.x
->widget
== widget
)
2860 /* Allocate the color COLOR->pixel on the screen and display of
2861 widget WIDGET in colormap CMAP. If an exact match cannot be
2862 allocated, try the nearest color available. Value is non-zero
2863 if successful. This is called from lwlib. */
2866 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2871 struct frame
*f
= x_frame_of_widget (widget
);
2872 return x_alloc_nearest_color (f
, cmap
, color
);
2876 #endif /* USE_X_TOOLKIT */
2878 #if 0 /* MAC_TODO */
2880 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2881 CMAP. If an exact match can't be allocated, try the nearest color
2882 available. Value is non-zero if successful. Set *COLOR to the
2886 x_alloc_nearest_color (f
, cmap
, color
)
2891 Display
*display
= FRAME_X_DISPLAY (f
);
2892 Screen
*screen
= FRAME_X_SCREEN (f
);
2895 gamma_correct (f
, color
);
2896 rc
= XAllocColor (display
, cmap
, color
);
2899 /* If we got to this point, the colormap is full, so we're going
2900 to try to get the next closest color. The algorithm used is
2901 a least-squares matching, which is what X uses for closest
2902 color matching with StaticColor visuals. */
2904 unsigned long nearest_delta
= ~0;
2905 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2906 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2908 for (i
= 0; i
< ncells
; ++i
)
2910 XQueryColors (display
, cmap
, cells
, ncells
);
2912 for (nearest
= i
= 0; i
< ncells
; ++i
)
2914 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2915 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2916 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2917 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2919 if (delta
< nearest_delta
)
2922 nearest_delta
= delta
;
2926 color
->red
= cells
[nearest
].red
;
2927 color
->green
= cells
[nearest
].green
;
2928 color
->blue
= cells
[nearest
].blue
;
2929 rc
= XAllocColor (display
, cmap
, color
);
2932 #ifdef DEBUG_X_COLORS
2934 register_color (color
->pixel
);
2935 #endif /* DEBUG_X_COLORS */
2941 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2942 It's necessary to do this instead of just using PIXEL directly to
2943 get color reference counts right. */
2946 x_copy_color (f
, pixel
)
2948 unsigned long pixel
;
2952 color
.pixel
= pixel
;
2954 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2955 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2957 #ifdef DEBUG_X_COLORS
2958 register_color (pixel
);
2964 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2965 It's necessary to do this instead of just using PIXEL directly to
2966 get color reference counts right. */
2969 x_copy_dpy_color (dpy
, cmap
, pixel
)
2972 unsigned long pixel
;
2976 color
.pixel
= pixel
;
2978 XQueryColor (dpy
, cmap
, &color
);
2979 XAllocColor (dpy
, cmap
, &color
);
2981 #ifdef DEBUG_X_COLORS
2982 register_color (pixel
);
2987 #endif /* MAC_TODO */
2990 /* Brightness beyond which a color won't have its highlight brightness
2993 Nominally, highlight colors for `3d' faces are calculated by
2994 brightening an object's color by a constant scale factor, but this
2995 doesn't yield good results for dark colors, so for colors who's
2996 brightness is less than this value (on a scale of 0-255) have to
2997 use an additional additive factor.
2999 The value here is set so that the default menu-bar/mode-line color
3000 (grey75) will not have its highlights changed at all. */
3001 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3004 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3005 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3006 If this produces the same color as COLOR, try a color where all RGB
3007 values have DELTA added. Return the allocated color in *COLOR.
3008 DISPLAY is the X display, CMAP is the colormap to operate on.
3009 Value is non-zero if successful. */
3012 mac_alloc_lighter_color (f
, color
, factor
, delta
)
3014 unsigned long *color
;
3021 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3024 /* Change RGB values by specified FACTOR. Avoid overflow! */
3025 xassert (factor
>= 0);
3026 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
3027 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
3028 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
3030 /* Calculate brightness of COLOR. */
3031 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
3032 + BLUE_FROM_ULONG (*color
)) / 6;
3034 /* We only boost colors that are darker than
3035 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3036 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3037 /* Make an additive adjustment to NEW, because it's dark enough so
3038 that scaling by FACTOR alone isn't enough. */
3040 /* How far below the limit this color is (0 - 1, 1 being darker). */
3041 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3042 /* The additive adjustment. */
3043 int min_delta
= delta
* dimness
* factor
/ 2;
3046 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
3047 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
3048 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
3050 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
3051 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
3052 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
3056 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
3057 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
3058 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
3060 /* MAC_TODO: Map to palette and retry with delta if same? */
3061 /* MAC_TODO: Free colors (if using palette)? */
3072 /* Set up the foreground color for drawing relief lines of glyph
3073 string S. RELIEF is a pointer to a struct relief containing the GC
3074 with which lines will be drawn. Use a color that is FACTOR or
3075 DELTA lighter or darker than the relief's background which is found
3076 in S->f->output_data.x->relief_background. If such a color cannot
3077 be allocated, use DEFAULT_PIXEL, instead. */
3080 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3082 struct relief
*relief
;
3085 unsigned long default_pixel
;
3088 struct mac_output
*di
= f
->output_data
.mac
;
3089 unsigned long mask
= GCForeground
;
3090 unsigned long pixel
;
3091 unsigned long background
= di
->relief_background
;
3092 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3094 /* MAC_TODO: Free colors (if using palette)? */
3096 /* Allocate new color. */
3097 xgcv
.foreground
= default_pixel
;
3099 if (dpyinfo
->n_planes
!= 1
3100 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
3102 relief
->allocated_p
= 1;
3103 xgcv
.foreground
= relief
->pixel
= pixel
;
3106 if (relief
->gc
== 0)
3108 #if 0 /* MAC_TODO: stipple */
3109 xgcv
.stipple
= dpyinfo
->gray
;
3112 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
3115 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
3119 /* Set up colors for the relief lines around glyph string S. */
3122 x_setup_relief_colors (s
)
3123 struct glyph_string
*s
;
3125 struct mac_output
*di
= s
->f
->output_data
.mac
;
3126 unsigned long color
;
3128 if (s
->face
->use_box_color_for_shadows_p
)
3129 color
= s
->face
->box_color
;
3130 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3132 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3133 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3138 /* Get the background color of the face. */
3139 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3140 color
= xgcv
.background
;
3143 if (di
->white_relief
.gc
== 0
3144 || color
!= di
->relief_background
)
3146 di
->relief_background
= color
;
3147 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3148 WHITE_PIX_DEFAULT (s
->f
));
3149 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3150 BLACK_PIX_DEFAULT (s
->f
));
3155 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3156 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3157 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3158 relief. LEFT_P non-zero means draw a relief on the left side of
3159 the rectangle. RIGHT_P non-zero means draw a relief on the right
3160 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3164 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3165 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3167 int left_x
, top_y
, right_x
, bottom_y
, width
;
3168 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3171 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3176 gc
= f
->output_data
.mac
->white_relief
.gc
;
3178 gc
= f
->output_data
.mac
->black_relief
.gc
;
3179 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3183 for (i
= 0; i
< width
; ++i
)
3184 mac_draw_line (f
, gc
,
3185 left_x
+ i
* left_p
, top_y
+ i
,
3186 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3190 for (i
= 0; i
< width
; ++i
)
3191 mac_draw_line (f
, gc
,
3192 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3194 mac_reset_clip_rectangles (dpy
, gc
);
3196 gc
= f
->output_data
.mac
->black_relief
.gc
;
3198 gc
= f
->output_data
.mac
->white_relief
.gc
;
3199 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3203 for (i
= 0; i
< width
; ++i
)
3204 mac_draw_line (f
, gc
,
3205 left_x
+ i
* left_p
, bottom_y
- i
,
3206 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3210 for (i
= 0; i
< width
; ++i
)
3211 mac_draw_line (f
, gc
,
3212 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3214 mac_reset_clip_rectangles (dpy
, gc
);
3218 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3219 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3220 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3221 left side of the rectangle. RIGHT_P non-zero means draw a line
3222 on the right side of the rectangle. CLIP_RECT is the clipping
3223 rectangle to use when drawing. */
3226 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3227 left_p
, right_p
, clip_rect
)
3228 struct glyph_string
*s
;
3229 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3234 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3235 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3236 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3239 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3240 right_x
- left_x
+ 1, width
);
3244 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3245 width
, bottom_y
- top_y
+ 1);
3248 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3249 right_x
- left_x
+ 1, width
);
3253 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3254 top_y
, width
, bottom_y
- top_y
+ 1);
3256 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3257 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3261 /* Draw a box around glyph string S. */
3264 x_draw_glyph_string_box (s
)
3265 struct glyph_string
*s
;
3267 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3268 int left_p
, right_p
;
3269 struct glyph
*last_glyph
;
3272 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3273 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3274 : window_box_right (s
->w
, s
->area
));
3276 /* The glyph that may have a right box line. */
3277 last_glyph
= (s
->cmp
|| s
->img
3279 : s
->first_glyph
+ s
->nchars
- 1);
3281 width
= abs (s
->face
->box_line_width
);
3282 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3284 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3286 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3288 bottom_y
= top_y
+ s
->height
- 1;
3290 left_p
= (s
->first_glyph
->left_box_line_p
3291 || (s
->hl
== DRAW_MOUSE_FACE
3293 || s
->prev
->hl
!= s
->hl
)));
3294 right_p
= (last_glyph
->right_box_line_p
3295 || (s
->hl
== DRAW_MOUSE_FACE
3297 || s
->next
->hl
!= s
->hl
)));
3299 get_glyph_string_clip_rect (s
, &clip_rect
);
3301 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3302 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3303 left_p
, right_p
, &clip_rect
);
3306 x_setup_relief_colors (s
);
3307 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3308 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3313 /* Draw foreground of image glyph string S. */
3316 x_draw_image_foreground (s
)
3317 struct glyph_string
*s
;
3320 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3322 /* If first glyph of S has a left box line, start drawing it to the
3323 right of that line. */
3324 if (s
->face
->box
!= FACE_NO_BOX
3325 && s
->first_glyph
->left_box_line_p
3327 x
+= abs (s
->face
->box_line_width
);
3329 /* If there is a margin around the image, adjust x- and y-position
3331 if (s
->slice
.x
== 0)
3332 x
+= s
->img
->hmargin
;
3333 if (s
->slice
.y
== 0)
3334 y
+= s
->img
->vmargin
;
3338 x_set_glyph_string_clipping (s
);
3341 mac_draw_cg_image (s
->img
->data
.ptr_val
,
3342 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3343 s
->slice
.width
, s
->slice
.height
, x
, y
, 1);
3347 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3348 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3349 s
->slice
.width
, s
->slice
.height
, x
, y
);
3356 mac_copy_area (s
->img
->pixmap
,
3357 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3358 s
->slice
.width
, s
->slice
.height
, x
, y
);
3361 /* When the image has a mask, we can expect that at
3362 least part of a mouse highlight or a block cursor will
3363 be visible. If the image doesn't have a mask, make
3364 a block cursor visible by drawing a rectangle around
3365 the image. I believe it's looking better if we do
3366 nothing here for mouse-face. */
3367 if (s
->hl
== DRAW_CURSOR
)
3369 int r
= s
->img
->relief
;
3371 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3372 s
->slice
.width
+ r
*2 - 1,
3373 s
->slice
.height
+ r
*2 - 1);
3378 /* Draw a rectangle if image could not be loaded. */
3379 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3380 s
->slice
.width
- 1, s
->slice
.height
- 1);
3384 /* Draw a relief around the image glyph string S. */
3387 x_draw_image_relief (s
)
3388 struct glyph_string
*s
;
3390 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3393 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3395 /* If first glyph of S has a left box line, start drawing it to the
3396 right of that line. */
3397 if (s
->face
->box
!= FACE_NO_BOX
3398 && s
->first_glyph
->left_box_line_p
3400 x
+= abs (s
->face
->box_line_width
);
3402 /* If there is a margin around the image, adjust x- and y-position
3404 if (s
->slice
.x
== 0)
3405 x
+= s
->img
->hmargin
;
3406 if (s
->slice
.y
== 0)
3407 y
+= s
->img
->vmargin
;
3409 if (s
->hl
== DRAW_IMAGE_SUNKEN
3410 || s
->hl
== DRAW_IMAGE_RAISED
)
3412 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3413 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3417 thick
= abs (s
->img
->relief
);
3418 raised_p
= s
->img
->relief
> 0;
3423 x1
= x
+ s
->slice
.width
+ thick
- 1;
3424 y1
= y
+ s
->slice
.height
+ thick
- 1;
3426 x_setup_relief_colors (s
);
3427 get_glyph_string_clip_rect (s
, &r
);
3428 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3430 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3432 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3437 /* Draw part of the background of glyph string S. X, Y, W, and H
3438 give the rectangle to draw. */
3441 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3442 struct glyph_string
*s
;
3445 #if 0 /* MAC_TODO: stipple */
3448 /* Fill background with a stipple pattern. */
3449 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3450 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3451 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3454 #endif /* MAC_TODO */
3455 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3459 /* Draw image glyph string S.
3462 s->x +-------------------------
3465 | +-------------------------
3468 | | +-------------------
3474 x_draw_image_glyph_string (s
)
3475 struct glyph_string
*s
;
3478 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3479 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3482 height
= s
->height
- 2 * box_line_vwidth
;
3485 /* Fill background with face under the image. Do it only if row is
3486 taller than image or if image has a clip mask to reduce
3488 s
->stippled_p
= s
->face
->stipple
!= 0;
3489 if (height
> s
->slice
.height
3493 || s
->img
->pixmap
== 0
3494 || s
->width
!= s
->background_width
)
3497 if (s
->first_glyph
->left_box_line_p
3499 x
+= box_line_hwidth
;
3502 if (s
->slice
.y
== 0)
3503 y
+= box_line_vwidth
;
3505 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3507 s
->background_filled_p
= 1;
3510 /* Draw the foreground. */
3511 x_draw_image_foreground (s
);
3513 /* If we must draw a relief around the image, do it. */
3515 || s
->hl
== DRAW_IMAGE_RAISED
3516 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3517 x_draw_image_relief (s
);
3521 /* Draw stretch glyph string S. */
3524 x_draw_stretch_glyph_string (s
)
3525 struct glyph_string
*s
;
3527 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3528 s
->stippled_p
= s
->face
->stipple
!= 0;
3530 if (s
->hl
== DRAW_CURSOR
3531 && !x_stretch_cursor_p
)
3533 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3534 as wide as the stretch glyph. */
3535 int width
, background_width
= s
->background_width
;
3536 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3540 background_width
-= left_x
- x
;
3543 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3546 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3548 /* Clear rest using the GC of the original non-cursor face. */
3549 if (width
< background_width
)
3552 int w
= background_width
- width
, h
= s
->height
;
3557 if (s
->row
->mouse_face_p
3558 && cursor_in_mouse_face_p (s
->w
))
3560 x_set_mouse_face_gc (s
);
3566 get_glyph_string_clip_rect (s
, &r
);
3567 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3569 #if 0 /* MAC_TODO: stipple */
3570 if (s
->face
->stipple
)
3572 /* Fill background with a stipple pattern. */
3573 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3574 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3575 XSetFillStyle (s
->display
, gc
, FillSolid
);
3578 #endif /* MAC_TODO */
3579 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3582 else if (!s
->background_filled_p
)
3584 int background_width
= s
->background_width
;
3585 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3587 /* Don't draw into left margin, fringe or scrollbar area
3588 except for header line and mode line. */
3589 if (x
< left_x
&& !s
->row
->mode_line_p
)
3591 background_width
-= left_x
- x
;
3594 if (background_width
> 0)
3595 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3598 s
->background_filled_p
= 1;
3602 /* Draw glyph string S. */
3605 x_draw_glyph_string (s
)
3606 struct glyph_string
*s
;
3608 int relief_drawn_p
= 0;
3610 /* If S draws into the background of its successor that does not
3611 draw a cursor, draw the background of the successor first so that
3612 S can draw into it. This makes S->next use XDrawString instead
3613 of XDrawImageString. */
3614 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3615 && s
->next
->hl
!= DRAW_CURSOR
)
3617 xassert (s
->next
->img
== NULL
);
3618 x_set_glyph_string_gc (s
->next
);
3619 x_set_glyph_string_clipping (s
->next
);
3620 x_draw_glyph_string_background (s
->next
, 1);
3623 /* Set up S->gc, set clipping and draw S. */
3624 x_set_glyph_string_gc (s
);
3626 /* Draw relief (if any) in advance for char/composition so that the
3627 glyph string can be drawn over it. */
3628 if (!s
->for_overlaps
3629 && s
->face
->box
!= FACE_NO_BOX
3630 && (s
->first_glyph
->type
== CHAR_GLYPH
3631 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3634 x_set_glyph_string_clipping (s
);
3635 x_draw_glyph_string_background (s
, 1);
3636 x_draw_glyph_string_box (s
);
3637 x_set_glyph_string_clipping (s
);
3641 x_set_glyph_string_clipping (s
);
3643 switch (s
->first_glyph
->type
)
3646 x_draw_image_glyph_string (s
);
3650 x_draw_stretch_glyph_string (s
);
3654 if (s
->for_overlaps
)
3655 s
->background_filled_p
= 1;
3657 x_draw_glyph_string_background (s
, 0);
3658 x_draw_glyph_string_foreground (s
);
3661 case COMPOSITE_GLYPH
:
3662 if (s
->for_overlaps
|| s
->gidx
> 0)
3663 s
->background_filled_p
= 1;
3665 x_draw_glyph_string_background (s
, 1);
3666 x_draw_composite_glyph_string_foreground (s
);
3673 if (!s
->for_overlaps
)
3675 /* Draw underline. */
3676 if (s
->face
->underline_p
)
3678 unsigned long tem
, h
;
3682 /* Get the underline thickness. Default is 1 pixel. */
3683 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3687 y
= s
->y
+ s
->height
- h
;
3688 if (!x_underline_at_descent_line
)
3690 /* Get the underline position. This is the recommended
3691 vertical offset in pixels from the baseline to the top of
3692 the underline. This is a signed value according to the
3693 specs, and its default is
3695 ROUND ((maximum descent) / 2), with
3696 ROUND(x) = floor (x + 0.5) */
3699 if (x_use_underline_position_properties
3700 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
3701 y
= s
->ybase
+ (long) tem
;
3705 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
3708 if (s
->face
->underline_defaulted_p
)
3709 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3710 s
->background_width
, h
);
3714 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3715 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3716 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, y
,
3717 s
->background_width
, h
);
3718 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3722 /* Draw overline. */
3723 if (s
->face
->overline_p
)
3725 unsigned long dy
= 0, h
= 1;
3727 if (s
->face
->overline_color_defaulted_p
)
3728 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3729 s
->background_width
, h
);
3733 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3734 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3735 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3736 s
->background_width
, h
);
3737 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3741 /* Draw strike-through. */
3742 if (s
->face
->strike_through_p
)
3744 unsigned long h
= 1;
3745 unsigned long dy
= (s
->height
- h
) / 2;
3747 if (s
->face
->strike_through_color_defaulted_p
)
3748 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3753 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3754 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3755 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3757 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3761 /* Draw relief if not yet drawn. */
3762 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3763 x_draw_glyph_string_box (s
);
3766 /* Reset clipping. */
3767 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3770 /* Shift display to make room for inserted glyphs. */
3773 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3775 int x
, y
, width
, height
, shift_by
;
3777 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3778 x
, y
, width
, height
,
3782 /* Delete N glyphs at the nominal cursor position. Not implemented
3793 /* Clear entire frame. If updating_frame is non-null, clear that
3794 frame. Otherwise clear the selected frame. */
3804 f
= SELECTED_FRAME ();
3806 /* Clearing the frame will erase any cursor, so mark them all as no
3808 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3809 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3810 output_cursor
.x
= -1;
3812 /* We don't set the output cursor here because there will always
3813 follow an explicit cursor_to. */
3815 mac_clear_window (f
);
3817 /* We have to clear the scroll bars, too. If we have changed
3818 colors or something like that, then they should be notified. */
3819 x_scroll_bar_clear (f
);
3821 XFlush (FRAME_MAC_DISPLAY (f
));
3827 /* Invert the middle quarter of the frame for .15 sec. */
3829 /* We use the select system call to do the waiting, so we have to make
3830 sure it's available. If it isn't, we just won't do visual bells. */
3832 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3835 /* Subtract the `struct timeval' values X and Y, storing the result in
3836 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3839 timeval_subtract (result
, x
, y
)
3840 struct timeval
*result
, x
, y
;
3842 /* Perform the carry for the later subtraction by updating y. This
3843 is safer because on some systems the tv_sec member is unsigned. */
3844 if (x
.tv_usec
< y
.tv_usec
)
3846 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3847 y
.tv_usec
-= 1000000 * nsec
;
3851 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3853 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3854 y
.tv_usec
+= 1000000 * nsec
;
3858 /* Compute the time remaining to wait. tv_usec is certainly
3860 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3861 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3863 /* Return indication of whether the result should be considered
3865 return x
.tv_sec
< y
.tv_sec
;
3872 /* Get the height not including a menu bar widget. */
3873 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3874 /* Height of each line to flash. */
3875 int flash_height
= FRAME_LINE_HEIGHT (f
);
3876 /* These will be the left and right margins of the rectangles. */
3877 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3878 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3882 /* Don't flash the area between a scroll bar and the frame
3883 edge it is next to. */
3884 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3886 case vertical_scroll_bar_left
:
3887 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3890 case vertical_scroll_bar_right
:
3891 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3898 width
= flash_right
- flash_left
;
3902 /* If window is tall, flash top and bottom line. */
3903 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3905 mac_invert_rectangle (f
, flash_left
,
3906 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3907 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3908 width
, flash_height
);
3909 mac_invert_rectangle (f
, flash_left
,
3910 (height
- flash_height
3911 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3912 width
, flash_height
);
3915 /* If it is short, flash it all. */
3916 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3917 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3922 struct timeval wakeup
;
3924 EMACS_GET_TIME (wakeup
);
3926 /* Compute time to wait until, propagating carry from usecs. */
3927 wakeup
.tv_usec
+= 150000;
3928 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3929 wakeup
.tv_usec
%= 1000000;
3931 /* Keep waiting until past the time wakeup or any input gets
3933 while (! detect_input_pending ())
3935 struct timeval current
;
3936 struct timeval timeout
;
3938 EMACS_GET_TIME (current
);
3940 /* Break if result would be negative. */
3941 if (timeval_subtract (¤t
, wakeup
, current
))
3944 /* How long `select' should wait. */
3946 timeout
.tv_usec
= 10000;
3948 /* Try to wait that long--but we might wake up sooner. */
3949 select (0, NULL
, NULL
, NULL
, &timeout
);
3953 /* If window is tall, flash top and bottom line. */
3954 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3956 mac_invert_rectangle (f
, flash_left
,
3957 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3958 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3959 width
, flash_height
);
3960 mac_invert_rectangle (f
, flash_left
,
3961 (height
- flash_height
3962 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3963 width
, flash_height
);
3966 /* If it is short, flash it all. */
3967 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3968 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3975 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3978 /* Make audible bell. */
3983 struct frame
*f
= SELECTED_FRAME ();
3985 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3993 XFlush (FRAME_MAC_DISPLAY (f
));
3999 /* Specify how many text lines, from the top of the window,
4000 should be affected by insert-lines and delete-lines operations.
4001 This, and those operations, are used only within an update
4002 that is bounded by calls to x_update_begin and x_update_end. */
4005 XTset_terminal_window (n
)
4008 /* This function intentionally left blank. */
4013 /***********************************************************************
4015 ***********************************************************************/
4017 /* Perform an insert-lines or delete-lines operation, inserting N
4018 lines or deleting -N lines at vertical position VPOS. */
4021 x_ins_del_lines (vpos
, n
)
4028 /* Scroll part of the display as described by RUN. */
4031 x_scroll_run (w
, run
)
4035 struct frame
*f
= XFRAME (w
->frame
);
4036 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4038 /* Get frame-relative bounding box of the text display area of W,
4039 without mode lines. Include in this box the left and right
4041 window_box (w
, -1, &x
, &y
, &width
, &height
);
4043 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4044 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4045 bottom_y
= y
+ height
;
4049 /* Scrolling up. Make sure we don't copy part of the mode
4050 line at the bottom. */
4051 if (from_y
+ run
->height
> bottom_y
)
4052 height
= bottom_y
- from_y
;
4054 height
= run
->height
;
4058 /* Scolling down. Make sure we don't copy over the mode line.
4060 if (to_y
+ run
->height
> bottom_y
)
4061 height
= bottom_y
- to_y
;
4063 height
= run
->height
;
4068 /* Cursor off. Will be switched on again in x_update_window_end. */
4072 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
4082 /***********************************************************************
4084 ***********************************************************************/
4092 ControlRef root_control
;
4095 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4097 ActivateControl (root_control
);
4099 x_update_cursor (f
, 1);
4103 frame_unhighlight (f
)
4107 ControlRef root_control
;
4110 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
4112 DeactivateControl (root_control
);
4114 x_update_cursor (f
, 1);
4117 /* The focus has changed. Update the frames as necessary to reflect
4118 the new situation. Note that we can't change the selected frame
4119 here, because the Lisp code we are interrupting might become confused.
4120 Each event gets marked with the frame in which it occurred, so the
4121 Lisp code can tell when the switch took place by examining the events. */
4124 x_new_focus_frame (dpyinfo
, frame
)
4125 struct x_display_info
*dpyinfo
;
4126 struct frame
*frame
;
4128 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4130 if (frame
!= dpyinfo
->x_focus_frame
)
4132 /* Set this before calling other routines, so that they see
4133 the correct value of x_focus_frame. */
4134 dpyinfo
->x_focus_frame
= frame
;
4136 if (old_focus
&& old_focus
->auto_lower
)
4137 x_lower_frame (old_focus
);
4140 selected_frame
= frame
;
4141 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4143 Fselect_window (selected_frame
->selected_window
, Qnil
);
4144 choose_minibuf_frame ();
4147 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4148 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4150 pending_autoraise_frame
= 0;
4152 #if USE_MAC_FONT_PANEL
4154 mac_set_font_info_for_selection (frame
, DEFAULT_FACE_ID
, 0);
4158 x_frame_rehighlight (dpyinfo
);
4161 /* Handle FocusIn and FocusOut state changes for FRAME.
4162 If FRAME has focus and there exists more than one frame, puts
4163 a FOCUS_IN_EVENT into *BUFP. */
4166 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
4168 struct mac_display_info
*dpyinfo
;
4169 struct frame
*frame
;
4170 struct input_event
*bufp
;
4172 if (type
== activeFlag
)
4174 if (dpyinfo
->x_focus_event_frame
!= frame
)
4176 x_new_focus_frame (dpyinfo
, frame
);
4177 dpyinfo
->x_focus_event_frame
= frame
;
4179 /* Don't stop displaying the initial startup message
4180 for a switch-frame event we don't need. */
4181 if (GC_NILP (Vterminal_frame
)
4182 && GC_CONSP (Vframe_list
)
4183 && !GC_NILP (XCDR (Vframe_list
)))
4185 bufp
->kind
= FOCUS_IN_EVENT
;
4186 XSETFRAME (bufp
->frame_or_window
, frame
);
4192 if (dpyinfo
->x_focus_event_frame
== frame
)
4194 dpyinfo
->x_focus_event_frame
= 0;
4195 x_new_focus_frame (dpyinfo
, 0);
4200 /* The focus may have changed. Figure out if it is a real focus change,
4201 by checking both FocusIn/Out and Enter/LeaveNotify events.
4203 Returns FOCUS_IN_EVENT event in *BUFP. */
4206 x_detect_focus_change (dpyinfo
, event
, bufp
)
4207 struct mac_display_info
*dpyinfo
;
4209 struct input_event
*bufp
;
4211 struct frame
*frame
;
4213 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4217 /* On Mac, this is only called from focus events, so no switch needed. */
4218 mac_focus_changed ((event
->modifiers
& activeFlag
),
4219 dpyinfo
, frame
, bufp
);
4223 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4226 x_mouse_leave (dpyinfo
)
4227 struct x_display_info
*dpyinfo
;
4229 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4232 /* The focus has changed, or we have redirected a frame's focus to
4233 another frame (this happens when a frame uses a surrogate
4234 mini-buffer frame). Shift the highlight as appropriate.
4236 The FRAME argument doesn't necessarily have anything to do with which
4237 frame is being highlighted or un-highlighted; we only use it to find
4238 the appropriate X display info. */
4241 XTframe_rehighlight (frame
)
4242 struct frame
*frame
;
4244 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4248 x_frame_rehighlight (dpyinfo
)
4249 struct x_display_info
*dpyinfo
;
4251 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4253 if (dpyinfo
->x_focus_frame
)
4255 dpyinfo
->x_highlight_frame
4256 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4257 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4258 : dpyinfo
->x_focus_frame
);
4259 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4261 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4262 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4266 dpyinfo
->x_highlight_frame
= 0;
4268 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4271 frame_unhighlight (old_highlight
);
4272 if (dpyinfo
->x_highlight_frame
)
4273 frame_highlight (dpyinfo
->x_highlight_frame
);
4279 /* Convert a keysym to its name. */
4282 x_get_keysym_name (keysym
)
4289 value
= XKeysymToString (keysym
);
4300 /* Function to report a mouse movement to the mainstream Emacs code.
4301 The input handler calls this.
4303 We have received a mouse movement event, which is given in *event.
4304 If the mouse is over a different glyph than it was last time, tell
4305 the mainstream emacs code by setting mouse_moved. If not, ask for
4306 another motion event, so we can check again the next time it moves. */
4308 static Point last_mouse_motion_position
;
4309 static Lisp_Object last_mouse_motion_frame
;
4312 note_mouse_movement (frame
, pos
)
4316 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4317 #if TARGET_API_MAC_CARBON
4321 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4322 last_mouse_motion_position
= *pos
;
4323 XSETFRAME (last_mouse_motion_frame
, frame
);
4325 #if TARGET_API_MAC_CARBON
4326 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4328 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4331 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4332 /* This case corresponds to LeaveNotify in X11. */
4334 /* If we move outside the frame, then we're certainly no
4335 longer on any text in the frame. */
4336 clear_mouse_face (dpyinfo
);
4337 dpyinfo
->mouse_face_mouse_frame
= 0;
4338 if (!dpyinfo
->grabbed
)
4339 rif
->define_frame_cursor (frame
,
4340 frame
->output_data
.mac
->nontext_cursor
);
4344 /* Has the mouse moved off the glyph it was on at the last sighting? */
4345 if (frame
!= last_mouse_glyph_frame
4346 || !PtInRect (*pos
, &last_mouse_glyph
))
4348 frame
->mouse_moved
= 1;
4349 last_mouse_scroll_bar
= Qnil
;
4350 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4351 /* Remember which glyph we're now on. */
4352 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4353 last_mouse_glyph_frame
= frame
;
4361 /************************************************************************
4363 ************************************************************************/
4365 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4368 redo_mouse_highlight ()
4370 if (!NILP (last_mouse_motion_frame
)
4371 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4372 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4373 last_mouse_motion_position
.h
,
4374 last_mouse_motion_position
.v
);
4378 static struct frame
*
4379 mac_focus_frame (dpyinfo
)
4380 struct mac_display_info
*dpyinfo
;
4382 if (dpyinfo
->x_focus_frame
)
4383 return dpyinfo
->x_focus_frame
;
4385 /* Mac version may get events, such as a menu bar click, even when
4386 all the frames are invisible. In this case, we regard the
4387 event came to the selected frame. */
4388 return SELECTED_FRAME ();
4392 /* Return the current position of the mouse.
4393 *FP should be a frame which indicates which display to ask about.
4395 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4396 and *PART to the frame, window, and scroll bar part that the mouse
4397 is over. Set *X and *Y to the portion and whole of the mouse's
4398 position on the scroll bar.
4400 If the mouse movement started elsewhere, set *FP to the frame the
4401 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4404 Set *TIME to the server time-stamp for the time at which the mouse
4405 was at this position.
4407 Don't store anything if we don't have a valid set of values to report.
4409 This clears the mouse_moved flag, so we can wait for the next mouse
4413 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4416 Lisp_Object
*bar_window
;
4417 enum scroll_bar_part
*part
;
4419 unsigned long *time
;
4425 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4426 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4429 Lisp_Object frame
, tail
;
4431 /* Clear the mouse-moved flag for every frame on this display. */
4432 FOR_EACH_FRAME (tail
, frame
)
4433 XFRAME (frame
)->mouse_moved
= 0;
4435 last_mouse_scroll_bar
= Qnil
;
4437 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4438 && FRAME_LIVE_P (last_mouse_frame
))
4439 f1
= last_mouse_frame
;
4441 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4445 /* Ok, we found a frame. Store all the values.
4446 last_mouse_glyph is a rectangle used to reduce the
4447 generation of mouse events. To not miss any motion
4448 events, we must divide the frame into rectangles of the
4449 size of the smallest character that could be displayed
4450 on it, i.e. into the same rectangles that matrices on
4451 the frame are divided into. */
4454 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4455 GetMouse (&mouse_pos
);
4456 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4458 last_mouse_glyph_frame
= f1
;
4463 XSETINT (*x
, mouse_pos
.h
);
4464 XSETINT (*y
, mouse_pos
.v
);
4465 *time
= last_mouse_movement_time
;
4473 /************************************************************************
4475 ************************************************************************/
4477 #ifdef USE_TOOLKIT_SCROLL_BARS
4479 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4480 static OSStatus install_scroll_bar_timer
P_ ((void));
4481 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4482 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4483 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4484 struct input_event
*));
4485 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4487 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4489 struct input_event
*));
4490 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4491 struct input_event
*));
4492 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4493 Point
, struct input_event
*));
4494 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4497 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4499 static int last_scroll_bar_part
;
4501 static EventLoopTimerRef scroll_bar_timer
;
4503 static int scroll_bar_timer_event_posted_p
;
4505 #define SCROLL_BAR_FIRST_DELAY 0.5
4506 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4509 scroll_bar_timer_callback (timer
, data
)
4510 EventLoopTimerRef timer
;
4515 err
= mac_post_mouse_moved_event ();
4517 scroll_bar_timer_event_posted_p
= 1;
4521 install_scroll_bar_timer ()
4523 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4525 if (scroll_bar_timer_callbackUPP
== NULL
)
4526 scroll_bar_timer_callbackUPP
=
4527 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4529 if (scroll_bar_timer
== NULL
)
4530 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4531 kEventDurationForever as delays. */
4533 InstallEventLoopTimer (GetCurrentEventLoop (),
4534 kEventDurationForever
, kEventDurationForever
,
4535 scroll_bar_timer_callbackUPP
, NULL
,
4540 set_scroll_bar_timer (delay
)
4541 EventTimerInterval delay
;
4543 if (scroll_bar_timer
== NULL
)
4544 install_scroll_bar_timer ();
4546 scroll_bar_timer_event_posted_p
= 0;
4548 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4552 control_part_code_to_scroll_bar_part (part_code
)
4553 ControlPartCode part_code
;
4557 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4558 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4559 case kControlPageUpPart
: return scroll_bar_above_handle
;
4560 case kControlPageDownPart
: return scroll_bar_below_handle
;
4561 case kControlIndicatorPart
: return scroll_bar_handle
;
4568 construct_scroll_bar_click (bar
, part
, bufp
)
4569 struct scroll_bar
*bar
;
4571 struct input_event
*bufp
;
4573 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4574 bufp
->frame_or_window
= bar
->window
;
4578 XSETINT (bufp
->x
, 0);
4579 XSETINT (bufp
->y
, 0);
4580 bufp
->modifiers
= 0;
4584 get_control_part_bounds (ch
, part_code
, rect
)
4586 ControlPartCode part_code
;
4589 RgnHandle region
= NewRgn ();
4592 err
= GetControlRegion (ch
, part_code
, region
);
4594 GetRegionBounds (region
, rect
);
4595 DisposeRgn (region
);
4601 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4602 struct scroll_bar
*bar
;
4603 ControlPartCode part_code
;
4604 struct input_event
*bufp
;
4606 int part
= control_part_code_to_scroll_bar_part (part_code
);
4611 if (part
!= scroll_bar_handle
)
4613 construct_scroll_bar_click (bar
, part
, bufp
);
4614 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4615 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4618 last_scroll_bar_part
= part
;
4619 bar
->dragging
= Qnil
;
4620 tracked_scroll_bar
= bar
;
4624 x_scroll_bar_handle_release (bar
, bufp
)
4625 struct scroll_bar
*bar
;
4626 struct input_event
*bufp
;
4628 if (last_scroll_bar_part
!= scroll_bar_handle
4629 || !GC_NILP (bar
->dragging
))
4630 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4632 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4633 set_scroll_bar_timer (kEventDurationForever
);
4635 last_scroll_bar_part
= -1;
4636 bar
->dragging
= Qnil
;
4637 tracked_scroll_bar
= NULL
;
4641 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4643 struct scroll_bar
*bar
;
4645 struct input_event
*bufp
;
4647 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4649 if (last_scroll_bar_part
== scroll_bar_handle
)
4654 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4655 kControlIndicatorPart
, &r
);
4657 if (GC_NILP (bar
->dragging
))
4658 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4660 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4661 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4662 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4667 if (top
> top_range
)
4670 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4671 XSETINT (bufp
->x
, top
);
4672 XSETINT (bufp
->y
, top_range
);
4676 ControlPartCode part_code
;
4677 int unhilite_p
= 0, part
;
4679 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4683 part
= control_part_code_to_scroll_bar_part (part_code
);
4685 switch (last_scroll_bar_part
)
4687 case scroll_bar_above_handle
:
4688 case scroll_bar_below_handle
:
4689 if (part
!= scroll_bar_above_handle
4690 && part
!= scroll_bar_below_handle
)
4694 case scroll_bar_up_arrow
:
4695 case scroll_bar_down_arrow
:
4696 if (part
!= scroll_bar_up_arrow
4697 && part
!= scroll_bar_down_arrow
)
4704 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4705 else if (part
!= last_scroll_bar_part
4706 || scroll_bar_timer_event_posted_p
)
4708 construct_scroll_bar_click (bar
, part
, bufp
);
4709 last_scroll_bar_part
= part
;
4710 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4711 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4716 /* Set the thumb size and position of scroll bar BAR. We are currently
4717 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4720 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4721 struct scroll_bar
*bar
;
4722 int portion
, position
, whole
;
4724 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4725 int value
, viewsize
, maximum
;
4727 if (XINT (bar
->track_height
) == 0)
4731 value
= 0, viewsize
= 1, maximum
= 0;
4736 maximum
= max (0, whole
- portion
);
4741 if (GetControlViewSize (ch
) != viewsize
4742 || GetControl32BitValue (ch
) != value
4743 || GetControl32BitMaximum (ch
) != maximum
)
4745 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4746 SetControlVisibility (ch
, false, false);
4748 SetControl32BitMaximum (ch
, maximum
);
4749 SetControl32BitValue (ch
, value
);
4750 SetControlViewSize (ch
, viewsize
);
4752 SetControlVisibility (ch
, true, true);
4758 #endif /* USE_TOOLKIT_SCROLL_BARS */
4762 /************************************************************************
4763 Scroll bars, general
4764 ************************************************************************/
4766 /* Create a scroll bar and return the scroll bar vector for it. W is
4767 the Emacs window on which to create the scroll bar. TOP, LEFT,
4768 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4771 static struct scroll_bar
*
4772 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4774 int top
, left
, width
, height
, disp_top
, disp_height
;
4776 struct frame
*f
= XFRAME (w
->frame
);
4777 struct scroll_bar
*bar
4778 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4786 r
.right
= left
+ width
;
4787 r
.bottom
= disp_top
+ disp_height
;
4790 mac_prepare_for_quickdraw (f
);
4792 #if TARGET_API_MAC_CARBON
4793 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4794 #if USE_TOOLKIT_SCROLL_BARS
4797 width
< disp_height
,
4799 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4801 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4802 0, 0, 0, scrollBarProc
, (long) bar
);
4804 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4806 XSETWINDOW (bar
->window
, w
);
4807 XSETINT (bar
->top
, top
);
4808 XSETINT (bar
->left
, left
);
4809 XSETINT (bar
->width
, width
);
4810 XSETINT (bar
->height
, height
);
4811 XSETINT (bar
->start
, 0);
4812 XSETINT (bar
->end
, 0);
4813 bar
->dragging
= Qnil
;
4814 #ifdef USE_TOOLKIT_SCROLL_BARS
4815 bar
->track_top
= Qnil
;
4816 bar
->track_height
= Qnil
;
4819 /* Add bar to its frame's list of scroll bars. */
4820 bar
->next
= FRAME_SCROLL_BARS (f
);
4822 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4823 if (!NILP (bar
->next
))
4824 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4831 /* Draw BAR's handle in the proper position.
4833 If the handle is already drawn from START to END, don't bother
4834 redrawing it, unless REBUILD is non-zero; in that case, always
4835 redraw it. (REBUILD is handy for drawing the handle after expose
4838 Normally, we want to constrain the start and end of the handle to
4839 fit inside its rectangle, but if the user is dragging the scroll
4840 bar handle, we want to let them drag it down all the way, so that
4841 the bar's top is as far down as it goes; otherwise, there's no way
4842 to move to the very end of the buffer. */
4844 #ifndef USE_TOOLKIT_SCROLL_BARS
4847 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4848 struct scroll_bar
*bar
;
4852 int dragging
= ! NILP (bar
->dragging
);
4853 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4854 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4855 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4856 int length
= end
- start
;
4858 /* If the display is already accurate, do nothing. */
4860 && start
== XINT (bar
->start
)
4861 && end
== XINT (bar
->end
))
4866 /* Make sure the values are reasonable, and try to preserve the
4867 distance between start and end. */
4870 else if (start
> top_range
)
4872 end
= start
+ length
;
4876 else if (end
> top_range
&& ! dragging
)
4879 /* Store the adjusted setting in the scroll bar. */
4880 XSETINT (bar
->start
, start
);
4881 XSETINT (bar
->end
, end
);
4883 /* Clip the end position, just for display. */
4884 if (end
> top_range
)
4887 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4888 top positions, to make sure the handle is always at least that
4889 many pixels tall. */
4890 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4892 SetControlMinimum (ch
, 0);
4893 /* Don't inadvertently activate deactivated scroll bars */
4894 if (GetControlMaximum (ch
) != -1)
4895 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4897 SetControlValue (ch
, start
);
4898 #if TARGET_API_MAC_CARBON
4899 SetControlViewSize (ch
, end
- start
);
4905 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4907 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4911 x_scroll_bar_remove (bar
)
4912 struct scroll_bar
*bar
;
4914 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4919 mac_prepare_for_quickdraw (f
);
4921 /* Destroy the Mac scroll bar control */
4922 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4924 /* Disassociate this scroll bar from its window. */
4925 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4931 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4932 that we are displaying PORTION characters out of a total of WHOLE
4933 characters, starting at POSITION. If WINDOW has no scroll bar,
4937 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4939 int portion
, whole
, position
;
4941 struct frame
*f
= XFRAME (w
->frame
);
4942 struct scroll_bar
*bar
;
4943 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4944 int window_y
, window_height
;
4946 /* Get window dimensions. */
4947 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4949 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4950 height
= window_height
;
4952 /* Compute the left edge of the scroll bar area. */
4953 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4955 /* Compute the width of the scroll bar which might be less than
4956 the width of the area reserved for the scroll bar. */
4957 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4958 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4962 /* Compute the left edge of the scroll bar. */
4963 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4966 sb_left
= left
+ width
- sb_width
;
4968 /* Adjustments according to Inside Macintosh to make it look nice */
4970 disp_height
= height
;
4977 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4983 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4987 /* Does the scroll bar exist yet? */
4988 if (NILP (w
->vertical_scroll_bar
))
4991 mac_clear_area (f
, left
, top
, width
, height
);
4993 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4995 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4999 /* It may just need to be moved and resized. */
5002 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5003 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5007 /* If already correctly positioned, do nothing. */
5008 if (!(XINT (bar
->left
) == sb_left
5009 && XINT (bar
->top
) == top
5010 && XINT (bar
->width
) == sb_width
5011 && XINT (bar
->height
) == height
))
5013 /* Since toolkit scroll bars are smaller than the space reserved
5014 for them on the frame, we have to clear "under" them. */
5015 mac_clear_area (f
, left
, top
, width
, height
);
5018 mac_prepare_for_quickdraw (f
);
5021 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
5022 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5024 #ifndef USE_TOOLKIT_SCROLL_BARS
5025 if (sb_width
< disp_height
)
5029 /* Remember new settings. */
5030 XSETINT (bar
->left
, sb_left
);
5031 XSETINT (bar
->top
, top
);
5032 XSETINT (bar
->width
, sb_width
);
5033 XSETINT (bar
->height
, height
);
5034 #ifdef USE_TOOLKIT_SCROLL_BARS
5035 bar
->track_top
= Qnil
;
5036 bar
->track_height
= Qnil
;
5043 #ifdef USE_TOOLKIT_SCROLL_BARS
5044 if (NILP (bar
->track_top
))
5046 if (sb_width
>= disp_height
)
5048 XSETINT (bar
->track_top
, 0);
5049 XSETINT (bar
->track_height
, 0);
5053 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5058 SetControl32BitMinimum (ch
, 0);
5059 SetControl32BitMaximum (ch
, 1);
5060 SetControlViewSize (ch
, 1);
5062 /* Move the scroll bar thumb to the top. */
5063 SetControl32BitValue (ch
, 0);
5064 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5066 /* Move the scroll bar thumb to the bottom. */
5067 SetControl32BitValue (ch
, 1);
5068 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5070 UnionRect (&r0
, &r1
, &r0
);
5071 XSETINT (bar
->track_top
, r0
.top
);
5072 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5074 /* Don't show the scroll bar if its height is not enough to
5075 display the scroll bar thumb. */
5076 if (r0
.bottom
- r0
.top
> 0)
5083 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5084 #else /* not USE_TOOLKIT_SCROLL_BARS */
5085 /* Set the scroll bar's current state, unless we're currently being
5087 if (NILP (bar
->dragging
))
5089 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5092 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5095 int start
= ((double) position
* top_range
) / whole
;
5096 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5097 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5100 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5104 /* The following three hooks are used when we're doing a thorough
5105 redisplay of the frame. We don't explicitly know which scroll bars
5106 are going to be deleted, because keeping track of when windows go
5107 away is a real pain - "Can you say set-window-configuration, boys
5108 and girls?" Instead, we just assert at the beginning of redisplay
5109 that *all* scroll bars are to be removed, and then save a scroll bar
5110 from the fiery pit when we actually redisplay its window. */
5112 /* Arrange for all scroll bars on FRAME to be removed at the next call
5113 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5114 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5117 XTcondemn_scroll_bars (frame
)
5120 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5121 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5124 bar
= FRAME_SCROLL_BARS (frame
);
5125 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5126 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5127 XSCROLL_BAR (bar
)->prev
= Qnil
;
5128 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5129 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5130 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5135 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5136 Note that WINDOW isn't necessarily condemned at all. */
5139 XTredeem_scroll_bar (window
)
5140 struct window
*window
;
5142 struct scroll_bar
*bar
;
5145 /* We can't redeem this window's scroll bar if it doesn't have one. */
5146 if (NILP (window
->vertical_scroll_bar
))
5149 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5151 /* Unlink it from the condemned list. */
5152 f
= XFRAME (WINDOW_FRAME (window
));
5153 if (NILP (bar
->prev
))
5155 /* If the prev pointer is nil, it must be the first in one of
5157 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5158 /* It's not condemned. Everything's fine. */
5160 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5161 window
->vertical_scroll_bar
))
5162 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5164 /* If its prev pointer is nil, it must be at the front of
5165 one or the other! */
5169 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5171 if (! NILP (bar
->next
))
5172 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5174 bar
->next
= FRAME_SCROLL_BARS (f
);
5176 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5177 if (! NILP (bar
->next
))
5178 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5181 /* Remove all scroll bars on FRAME that haven't been saved since the
5182 last call to `*condemn_scroll_bars_hook'. */
5185 XTjudge_scroll_bars (f
)
5188 Lisp_Object bar
, next
;
5190 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5192 /* Clear out the condemned list now so we won't try to process any
5193 more events on the hapless scroll bars. */
5194 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5196 for (; ! NILP (bar
); bar
= next
)
5198 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5200 x_scroll_bar_remove (b
);
5203 b
->next
= b
->prev
= Qnil
;
5206 /* Now there should be no references to the condemned scroll bars,
5207 and they should get garbage-collected. */
5211 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5212 is set to something other than NO_EVENT, it is enqueued.
5214 This may be called from a signal handler, so we have to ignore GC
5218 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5219 struct scroll_bar
*bar
;
5220 ControlPartCode part_code
;
5222 struct input_event
*bufp
;
5224 int win_y
, top_range
;
5226 if (! GC_WINDOWP (bar
->window
))
5229 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5230 bufp
->frame_or_window
= bar
->window
;
5233 bar
->dragging
= Qnil
;
5237 case kControlUpButtonPart
:
5238 bufp
->part
= scroll_bar_up_arrow
;
5240 case kControlDownButtonPart
:
5241 bufp
->part
= scroll_bar_down_arrow
;
5243 case kControlPageUpPart
:
5244 bufp
->part
= scroll_bar_above_handle
;
5246 case kControlPageDownPart
:
5247 bufp
->part
= scroll_bar_below_handle
;
5249 #if TARGET_API_MAC_CARBON
5252 case kControlIndicatorPart
:
5254 if (er
->what
== mouseDown
)
5255 bar
->dragging
= make_number (0);
5256 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5257 bufp
->part
= scroll_bar_handle
;
5261 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5262 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5264 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5268 if (! NILP (bar
->dragging
))
5269 win_y
-= XINT (bar
->dragging
);
5273 if (win_y
> top_range
)
5276 XSETINT (bufp
->x
, win_y
);
5277 XSETINT (bufp
->y
, top_range
);
5280 #ifndef USE_TOOLKIT_SCROLL_BARS
5282 /* Handle some mouse motion while someone is dragging the scroll bar.
5284 This may be called from a signal handler, so we have to ignore GC
5288 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5289 struct scroll_bar
*bar
;
5293 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5295 last_mouse_movement_time
= t
;
5298 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5300 /* If we're dragging the bar, display it. */
5301 if (! GC_NILP (bar
->dragging
))
5303 /* Where should the handle be now? */
5304 int new_start
= y_pos
- 24;
5306 if (new_start
!= XINT (bar
->start
))
5308 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5310 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5315 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5317 /* Return information to the user about the current position of the mouse
5318 on the scroll bar. */
5321 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5323 Lisp_Object
*bar_window
;
5324 enum scroll_bar_part
*part
;
5326 unsigned long *time
;
5328 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5329 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5330 #if TARGET_API_MAC_CARBON
5331 WindowPtr wp
= GetControlOwner (ch
);
5333 WindowPtr wp
= (*ch
)->contrlOwner
;
5336 struct frame
*f
= mac_window_to_frame (wp
);
5337 int win_y
, top_range
;
5339 SetPortWindowPort (wp
);
5341 GetMouse (&mouse_pos
);
5343 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5344 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5346 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5350 if (! NILP (bar
->dragging
))
5351 win_y
-= XINT (bar
->dragging
);
5355 if (win_y
> top_range
)
5359 *bar_window
= bar
->window
;
5361 if (! NILP (bar
->dragging
))
5362 *part
= scroll_bar_handle
;
5363 else if (win_y
< XINT (bar
->start
))
5364 *part
= scroll_bar_above_handle
;
5365 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5366 *part
= scroll_bar_handle
;
5368 *part
= scroll_bar_below_handle
;
5370 XSETINT (*x
, win_y
);
5371 XSETINT (*y
, top_range
);
5374 last_mouse_scroll_bar
= Qnil
;
5376 *time
= last_mouse_movement_time
;
5380 /* The screen has been cleared so we may have changed foreground or
5381 background colors, and the scroll bars may need to be redrawn.
5382 Clear out the scroll bars, and ask for expose events, so we can
5386 x_scroll_bar_clear (f
)
5389 XTcondemn_scroll_bars (f
);
5390 XTjudge_scroll_bars (f
);
5394 /***********************************************************************
5396 ***********************************************************************/
5398 /* Set clipping for output in glyph row ROW. W is the window in which
5399 we operate. GC is the graphics context to set clipping in.
5401 ROW may be a text row or, e.g., a mode line. Text rows must be
5402 clipped to the interior of the window dedicated to text display,
5403 mode lines must be clipped to the whole window. */
5406 x_clip_to_row (w
, row
, area
, gc
)
5408 struct glyph_row
*row
;
5412 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5414 int window_x
, window_y
, window_width
;
5416 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5418 clip_rect
.left
= window_x
;
5419 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5420 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5421 clip_rect
.right
= clip_rect
.left
+ window_width
;
5422 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5424 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5428 /* Draw a hollow box cursor on window W in glyph row ROW. */
5431 x_draw_hollow_cursor (w
, row
)
5433 struct glyph_row
*row
;
5435 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5436 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5437 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5440 struct glyph
*cursor_glyph
;
5443 /* Get the glyph the cursor is on. If we can't tell because
5444 the current matrix is invalid or such, give up. */
5445 cursor_glyph
= get_phys_cursor_glyph (w
);
5446 if (cursor_glyph
== NULL
)
5449 /* Compute frame-relative coordinates for phys cursor. */
5450 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
5451 wd
= w
->phys_cursor_width
;
5453 /* The foreground of cursor_gc is typically the same as the normal
5454 background color, which can cause the cursor box to be invisible. */
5455 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5456 if (dpyinfo
->scratch_cursor_gc
)
5457 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5459 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5460 GCForeground
, &xgcv
);
5461 gc
= dpyinfo
->scratch_cursor_gc
;
5463 /* Set clipping, draw the rectangle, and reset clipping again. */
5464 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5465 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5466 mac_reset_clip_rectangles (dpy
, gc
);
5470 /* Draw a bar cursor on window W in glyph row ROW.
5472 Implementation note: One would like to draw a bar cursor with an
5473 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5474 Unfortunately, I didn't find a font yet that has this property set.
5478 x_draw_bar_cursor (w
, row
, width
, kind
)
5480 struct glyph_row
*row
;
5482 enum text_cursor_kinds kind
;
5484 struct frame
*f
= XFRAME (w
->frame
);
5485 struct glyph
*cursor_glyph
;
5487 /* If cursor is out of bounds, don't draw garbage. This can happen
5488 in mini-buffer windows when switching between echo area glyphs
5490 cursor_glyph
= get_phys_cursor_glyph (w
);
5491 if (cursor_glyph
== NULL
)
5494 /* If on an image, draw like a normal cursor. That's usually better
5495 visible than drawing a bar, esp. if the image is large so that
5496 the bar might not be in the window. */
5497 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5499 struct glyph_row
*row
;
5500 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5501 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5505 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5506 Window window
= FRAME_MAC_WINDOW (f
);
5507 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5508 unsigned long mask
= GCForeground
| GCBackground
;
5509 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5512 /* If the glyph's background equals the color we normally draw
5513 the bar cursor in, the bar cursor in its normal color is
5514 invisible. Use the glyph's foreground color instead in this
5515 case, on the assumption that the glyph's colors are chosen so
5516 that the glyph is legible. */
5517 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5518 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5520 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5523 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5526 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5527 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5531 width
= FRAME_CURSOR_WIDTH (f
);
5532 width
= min (cursor_glyph
->pixel_width
, width
);
5534 w
->phys_cursor_width
= width
;
5535 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5537 if (kind
== BAR_CURSOR
)
5538 mac_fill_rectangle (f
, gc
,
5539 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5540 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5541 width
, row
->height
);
5543 mac_fill_rectangle (f
, gc
,
5544 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5545 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5546 row
->height
- width
),
5547 cursor_glyph
->pixel_width
,
5550 mac_reset_clip_rectangles (dpy
, gc
);
5555 /* RIF: Define cursor CURSOR on frame F. */
5558 mac_define_frame_cursor (f
, cursor
)
5562 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5564 if (dpyinfo
->x_focus_frame
== f
)
5565 SetThemeCursor (cursor
);
5569 /* RIF: Clear area on frame F. */
5572 mac_clear_frame_area (f
, x
, y
, width
, height
)
5574 int x
, y
, width
, height
;
5576 mac_clear_area (f
, x
, y
, width
, height
);
5580 /* RIF: Draw cursor on window W. */
5583 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5585 struct glyph_row
*glyph_row
;
5587 int cursor_type
, cursor_width
;
5592 w
->phys_cursor_type
= cursor_type
;
5593 w
->phys_cursor_on_p
= 1;
5595 if (glyph_row
->exact_window_width_line_p
5596 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5598 glyph_row
->cursor_in_fringe_p
= 1;
5599 draw_fringe_bitmap (w
, glyph_row
, 0);
5602 switch (cursor_type
)
5604 case HOLLOW_BOX_CURSOR
:
5605 x_draw_hollow_cursor (w
, glyph_row
);
5608 case FILLED_BOX_CURSOR
:
5609 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5613 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5617 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5621 w
->phys_cursor_width
= 0;
5633 #if 0 /* MAC_TODO: no icon support yet. */
5635 x_bitmap_icon (f
, icon
)
5641 if (FRAME_W32_WINDOW (f
) == 0)
5645 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5646 else if (STRINGP (icon
))
5647 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5648 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5649 else if (SYMBOLP (icon
))
5653 if (EQ (icon
, intern ("application")))
5654 name
= (LPCTSTR
) IDI_APPLICATION
;
5655 else if (EQ (icon
, intern ("hand")))
5656 name
= (LPCTSTR
) IDI_HAND
;
5657 else if (EQ (icon
, intern ("question")))
5658 name
= (LPCTSTR
) IDI_QUESTION
;
5659 else if (EQ (icon
, intern ("exclamation")))
5660 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5661 else if (EQ (icon
, intern ("asterisk")))
5662 name
= (LPCTSTR
) IDI_ASTERISK
;
5663 else if (EQ (icon
, intern ("winlogo")))
5664 name
= (LPCTSTR
) IDI_WINLOGO
;
5668 hicon
= LoadIcon (NULL
, name
);
5676 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5681 #endif /* MAC_TODO */
5683 /************************************************************************
5685 ************************************************************************/
5687 /* Display Error Handling functions not used on W32. Listing them here
5688 helps diff stay in step when comparing w32term.c with xterm.c.
5690 x_error_catcher (display, error)
5691 x_catch_errors (dpy)
5692 x_catch_errors_unwind (old_val)
5693 x_check_errors (dpy, format)
5694 x_had_errors_p (dpy)
5695 x_clear_errors (dpy)
5696 x_uncatch_errors (dpy, count)
5698 x_connection_signal (signalnum)
5699 x_connection_closed (dpy, error_message)
5700 x_error_quitter (display, error)
5701 x_error_handler (display, error)
5702 x_io_error_quitter (display)
5707 /* Changing the font of the frame. */
5709 /* Give frame F the font named FONTNAME as its default font, and
5710 return the full name of that font. FONTNAME may be a wildcard
5711 pattern; in that case, we choose some font that fits the pattern.
5712 The return value shows which font we chose. */
5715 x_new_font (f
, fontname
)
5717 register char *fontname
;
5719 struct font_info
*fontp
5720 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5725 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5726 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5727 FRAME_FONTSET (f
) = -1;
5729 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5730 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5731 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5733 compute_fringe_widths (f
, 1);
5735 /* Compute the scroll bar width in character columns. */
5736 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5738 int wid
= FRAME_COLUMN_WIDTH (f
);
5739 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5740 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5744 int wid
= FRAME_COLUMN_WIDTH (f
);
5745 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5748 /* Now make the frame display the given font. */
5749 if (FRAME_MAC_WINDOW (f
) != 0)
5751 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5753 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5755 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5758 /* Don't change the size of a tip frame; there's no point in
5759 doing it because it's done in Fx_show_tip, and it leads to
5760 problems because the tip frame has no widget. */
5761 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5762 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5765 return build_string (fontp
->full_name
);
5768 /* Give frame F the fontset named FONTSETNAME as its default font, and
5769 return the full name of that fontset. FONTSETNAME may be a wildcard
5770 pattern; in that case, we choose some fontset that fits the pattern.
5771 The return value shows which fontset we chose. */
5774 x_new_fontset (f
, fontsetname
)
5778 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5784 if (FRAME_FONTSET (f
) == fontset
)
5785 /* This fontset is already set in frame F. There's nothing more
5787 return fontset_name (fontset
);
5789 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5791 if (!STRINGP (result
))
5792 /* Can't load ASCII font. */
5795 /* Since x_new_font doesn't update any fontset information, do it now. */
5796 FRAME_FONTSET (f
) = fontset
;
5798 return build_string (fontsetname
);
5802 /***********************************************************************
5803 TODO: W32 Input Methods
5804 ***********************************************************************/
5805 /* Listing missing functions from xterm.c helps diff stay in step.
5807 xim_destroy_callback (xim, client_data, call_data)
5808 xim_open_dpy (dpyinfo, resource_name)
5810 xim_instantiate_callback (display, client_data, call_data)
5811 xim_initialize (dpyinfo, resource_name)
5812 xim_close_dpy (dpyinfo)
5818 mac_get_window_bounds (f
, inner
, outer
)
5820 Rect
*inner
, *outer
;
5822 #if TARGET_API_MAC_CARBON
5823 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5824 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5825 #else /* not TARGET_API_MAC_CARBON */
5826 RgnHandle region
= NewRgn ();
5828 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5829 *inner
= (*region
)->rgnBBox
;
5830 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5831 *outer
= (*region
)->rgnBBox
;
5832 DisposeRgn (region
);
5833 #endif /* not TARGET_API_MAC_CARBON */
5837 mac_handle_origin_change (f
)
5840 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5844 mac_handle_size_change (f
, pixelwidth
, pixelheight
)
5846 int pixelwidth
, pixelheight
;
5850 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
5851 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
5853 if (cols
!= FRAME_COLS (f
)
5854 || rows
!= FRAME_LINES (f
)
5855 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
5856 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
5858 /* We pass 1 for DELAY since we can't run Lisp code inside of
5860 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5861 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5862 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5863 SET_FRAME_GARBAGED (f
);
5865 /* If cursor was outside the new size, mark it as off. */
5866 mark_window_cursors_off (XWINDOW (f
->root_window
));
5868 /* Clear out any recollection of where the mouse highlighting
5869 was, since it might be in a place that's outside the new
5870 frame size. Actually checking whether it is outside is a
5871 pain in the neck, so don't try--just let the highlighting be
5872 done afresh with new size. */
5873 cancel_mouse_face (f
);
5875 #if TARGET_API_MAC_CARBON
5876 if (f
->output_data
.mac
->hourglass_control
)
5879 mac_prepare_for_quickdraw (f
);
5881 MoveControl (f
->output_data
.mac
->hourglass_control
,
5882 pixelwidth
- HOURGLASS_WIDTH
, 0);
5889 /* Calculate the absolute position in frame F
5890 from its current recorded position values and gravity. */
5893 x_calc_absolute_position (f
)
5896 int width_diff
= 0, height_diff
= 0;
5897 int flags
= f
->size_hint_flags
;
5900 /* We have nothing to do if the current position
5901 is already for the top-left corner. */
5902 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5905 /* Find the offsets of the outside upper-left corner of
5906 the inner window, with respect to the outer window. */
5907 mac_get_window_bounds (f
, &inner
, &outer
);
5909 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5910 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5912 /* Treat negative positions as relative to the leftmost bottommost
5913 position that fits on the screen. */
5914 if (flags
& XNegative
)
5915 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5917 - FRAME_PIXEL_WIDTH (f
)
5920 if (flags
& YNegative
)
5921 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5923 - FRAME_PIXEL_HEIGHT (f
)
5926 /* The left_pos and top_pos
5927 are now relative to the top and left screen edges,
5928 so the flags should correspond. */
5929 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5932 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5933 to really change the position, and 0 when calling from
5934 x_make_frame_visible (in that case, XOFF and YOFF are the current
5935 position values). It is -1 when calling from x_set_frame_parameters,
5936 which means, do adjust for borders but don't change the gravity. */
5939 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5941 register int xoff
, yoff
;
5944 if (change_gravity
> 0)
5948 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5950 f
->size_hint_flags
|= XNegative
;
5952 f
->size_hint_flags
|= YNegative
;
5953 f
->win_gravity
= NorthWestGravity
;
5955 x_calc_absolute_position (f
);
5958 x_wm_set_size_hint (f
, (long) 0, 0);
5960 #if TARGET_API_MAC_CARBON
5961 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5962 /* If the title bar is completely outside the screen, adjust the
5964 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5965 kWindowConstrainMoveRegardlessOfFit
5966 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5967 #if USE_CARBON_EVENTS
5968 if (!NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
5970 mac_handle_origin_change (f
);
5973 Rect inner
, outer
, screen_rect
, dummy
;
5974 RgnHandle region
= NewRgn ();
5976 mac_get_window_bounds (f
, &inner
, &outer
);
5977 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5978 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5979 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5980 f
->top_pos
+ f
->y_pixels_diff
, false);
5982 /* If the title bar is completely outside the screen, adjust the
5983 position. The variable `outer' holds the title bar rectangle.
5984 The variable `inner' holds slightly smaller one than `outer',
5985 so that the calculation of overlapping may not become too
5987 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5988 outer
= (*region
)->rgnBBox
;
5989 DisposeRgn (region
);
5991 InsetRect (&inner
, 8, 8);
5992 screen_rect
= qd
.screenBits
.bounds
;
5993 screen_rect
.top
+= GetMBarHeight ();
5995 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5997 if (inner
.right
<= screen_rect
.left
)
5998 f
->left_pos
= screen_rect
.left
;
5999 else if (inner
.left
>= screen_rect
.right
)
6000 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
6002 if (inner
.bottom
<= screen_rect
.top
)
6003 f
->top_pos
= screen_rect
.top
;
6004 else if (inner
.top
>= screen_rect
.bottom
)
6005 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
6007 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
6008 f
->top_pos
+ f
->y_pixels_diff
, false);
6016 /* Call this to change the size of frame F's x-window.
6017 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6018 for this size change and subsequent size changes.
6019 Otherwise we leave the window gravity unchanged. */
6022 x_set_window_size (f
, change_gravity
, cols
, rows
)
6027 int pixelwidth
, pixelheight
;
6031 check_frame_size (f
, &rows
, &cols
);
6032 f
->scroll_bar_actual_width
6033 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6035 compute_fringe_widths (f
, 0);
6037 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6038 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6040 f
->win_gravity
= NorthWestGravity
;
6041 x_wm_set_size_hint (f
, (long) 0, 0);
6043 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
6045 #if USE_CARBON_EVENTS
6046 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6048 mac_handle_size_change (f
, pixelwidth
, pixelheight
);
6053 /* Mouse warping. */
6055 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6058 x_set_mouse_position (f
, x
, y
)
6064 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6065 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6067 if (pix_x
< 0) pix_x
= 0;
6068 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6070 if (pix_y
< 0) pix_y
= 0;
6071 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6073 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6077 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6086 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
6092 CGWarpMouseCursorPosition (point
);
6095 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6098 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6099 0, 0, 0, 0, pix_x
, pix_y
);
6105 /* focus shifting, raising and lowering. */
6108 x_focus_on_frame (f
)
6111 #if 0 /* This proves to be unpleasant. */
6115 /* I don't think that the ICCCM allows programs to do things like this
6116 without the interaction of the window manager. Whatever you end up
6117 doing with this code, do it to x_unfocus_frame too. */
6118 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6119 RevertToPointerRoot
, CurrentTime
);
6129 /* Raise frame F. */
6135 if (f
->async_visible
)
6138 BringToFront (FRAME_MAC_WINDOW (f
));
6143 /* Lower frame F. */
6149 if (f
->async_visible
)
6152 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6158 XTframe_raise_lower (f
, raise_flag
)
6168 /* Change of visibility. */
6171 mac_handle_visibility_change (f
)
6174 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6175 int visible
= 0, iconified
= 0;
6176 struct input_event buf
;
6178 if (IsWindowVisible (wp
))
6180 if (IsWindowCollapsed (wp
))
6186 if (!f
->async_visible
&& visible
)
6190 /* wait_reading_process_output will notice this and update
6191 the frame's display structures. If we were made
6192 invisible, we should not set garbaged, because that stops
6193 redrawing on Update events. */
6194 SET_FRAME_GARBAGED (f
);
6197 buf
.kind
= DEICONIFY_EVENT
;
6198 XSETFRAME (buf
.frame_or_window
, f
);
6200 kbd_buffer_store_event (&buf
);
6202 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6203 /* Force a redisplay sooner or later to update the
6204 frame titles in case this is the second frame. */
6205 record_asynch_buffer_change ();
6207 else if (f
->async_visible
&& !visible
)
6211 buf
.kind
= ICONIFY_EVENT
;
6212 XSETFRAME (buf
.frame_or_window
, f
);
6214 kbd_buffer_store_event (&buf
);
6217 f
->async_visible
= visible
;
6218 f
->async_iconified
= iconified
;
6221 /* This tries to wait until the frame is really visible.
6222 However, if the window manager asks the user where to position
6223 the frame, this will return before the user finishes doing that.
6224 The frame will not actually be visible at that time,
6225 but it will become visible later when the window manager
6226 finishes with it. */
6229 x_make_frame_visible (f
)
6234 if (! FRAME_VISIBLE_P (f
))
6236 /* We test FRAME_GARBAGED_P here to make sure we don't
6237 call x_set_offset a second time
6238 if we get to x_make_frame_visible a second time
6239 before the window gets really visible. */
6240 if (! FRAME_ICONIFIED_P (f
)
6241 && ! f
->output_data
.mac
->asked_for_visible
)
6243 #if TARGET_API_MAC_CARBON
6244 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6246 struct frame
*sf
= SELECTED_FRAME ();
6247 if (!FRAME_MAC_P (sf
))
6248 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6249 kWindowCenterOnMainScreen
);
6251 RepositionWindow (FRAME_MAC_WINDOW (f
),
6252 FRAME_MAC_WINDOW (sf
),
6253 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6254 kWindowCascadeStartAtParentWindowScreen
6256 kWindowCascadeOnParentWindowScreen
6259 #if USE_CARBON_EVENTS
6260 if (!NILP (tip_frame
) && f
== XFRAME (tip_frame
))
6262 mac_handle_origin_change (f
);
6266 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6269 f
->output_data
.mac
->asked_for_visible
= 1;
6271 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6272 ShowWindow (FRAME_MAC_WINDOW (f
));
6275 XFlush (FRAME_MAC_DISPLAY (f
));
6277 /* Synchronize to ensure Emacs knows the frame is visible
6278 before we do anything else. We do this loop with input not blocked
6279 so that incoming events are handled. */
6284 /* This must come after we set COUNT. */
6287 XSETFRAME (frame
, f
);
6289 /* Wait until the frame is visible. Process X events until a
6290 MapNotify event has been seen, or until we think we won't get a
6291 MapNotify at all.. */
6292 for (count
= input_signal_count
+ 10;
6293 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6295 /* Force processing of queued events. */
6298 /* Machines that do polling rather than SIGIO have been
6299 observed to go into a busy-wait here. So we'll fake an
6300 alarm signal to let the handler know that there's something
6301 to be read. We used to raise a real alarm, but it seems
6302 that the handler isn't always enabled here. This is
6304 if (input_polling_used ())
6306 /* It could be confusing if a real alarm arrives while
6307 processing the fake one. Turn it off and let the
6308 handler reset it. */
6309 extern void poll_for_input_1
P_ ((void));
6310 int old_poll_suppress_count
= poll_suppress_count
;
6311 poll_suppress_count
= 1;
6312 poll_for_input_1 ();
6313 poll_suppress_count
= old_poll_suppress_count
;
6316 /* See if a MapNotify event has been processed. */
6317 FRAME_SAMPLE_VISIBILITY (f
);
6322 /* Change from mapped state to withdrawn state. */
6324 /* Make the frame visible (mapped and not iconified). */
6327 x_make_frame_invisible (f
)
6330 /* A deactivate event does not occur when the last visible frame is
6331 made invisible. So if we clear the highlight here, it will not
6332 be rehighlighted when it is made visible. */
6334 /* Don't keep the highlight on an invisible frame. */
6335 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6336 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6341 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6342 that the current position of the window is user-specified, rather than
6343 program-specified, so that when the window is mapped again, it will be
6344 placed at the same location, without forcing the user to position it
6345 by hand again (they have already done that once for this window.) */
6346 x_wm_set_size_hint (f
, (long) 0, 1);
6348 HideWindow (FRAME_MAC_WINDOW (f
));
6352 #if !USE_CARBON_EVENTS
6353 mac_handle_visibility_change (f
);
6357 /* Change window state from mapped to iconified. */
6365 /* A deactivate event does not occur when the last visible frame is
6366 iconified. So if we clear the highlight here, it will not be
6367 rehighlighted when it is deiconified. */
6369 /* Don't keep the highlight on an invisible frame. */
6370 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6371 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6374 if (f
->async_iconified
)
6379 FRAME_SAMPLE_VISIBILITY (f
);
6381 if (! FRAME_VISIBLE_P (f
))
6382 ShowWindow (FRAME_MAC_WINDOW (f
));
6384 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6389 error ("Can't notify window manager of iconification");
6391 #if !USE_CARBON_EVENTS
6392 mac_handle_visibility_change (f
);
6397 /* Free X resources of frame F. */
6400 x_free_frame_resources (f
)
6403 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6404 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6408 if (wp
!= tip_window
)
6409 remove_window_handler (wp
);
6412 if (wp
== tip_window
)
6413 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6414 closed' event. So we reset tip_window here. */
6417 free_frame_menubar (f
);
6419 if (FRAME_FACE_CACHE (f
))
6420 free_frame_faces (f
);
6424 if (FRAME_SIZE_HINTS (f
))
6425 xfree (FRAME_SIZE_HINTS (f
));
6427 xfree (f
->output_data
.mac
);
6428 f
->output_data
.mac
= NULL
;
6430 if (f
== dpyinfo
->x_focus_frame
)
6432 dpyinfo
->x_focus_frame
= 0;
6433 #if USE_MAC_FONT_PANEL
6434 mac_set_font_info_for_selection (NULL
, DEFAULT_FACE_ID
, 0);
6437 if (f
== dpyinfo
->x_focus_event_frame
)
6438 dpyinfo
->x_focus_event_frame
= 0;
6439 if (f
== dpyinfo
->x_highlight_frame
)
6440 dpyinfo
->x_highlight_frame
= 0;
6442 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6444 dpyinfo
->mouse_face_beg_row
6445 = dpyinfo
->mouse_face_beg_col
= -1;
6446 dpyinfo
->mouse_face_end_row
6447 = dpyinfo
->mouse_face_end_col
= -1;
6448 dpyinfo
->mouse_face_window
= Qnil
;
6449 dpyinfo
->mouse_face_deferred_gc
= 0;
6450 dpyinfo
->mouse_face_mouse_frame
= 0;
6457 /* Destroy the X window of frame F. */
6460 x_destroy_window (f
)
6463 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6465 x_free_frame_resources (f
);
6467 dpyinfo
->reference_count
--;
6471 /* Setting window manager hints. */
6473 /* Set the normal size hints for the window manager, for frame F.
6474 FLAGS is the flags word to use--or 0 meaning preserve the flags
6475 that the window now has.
6476 If USER_POSITION is nonzero, we set the USPosition
6477 flag (this is useful when FLAGS is 0). */
6479 x_wm_set_size_hint (f
, flags
, user_position
)
6484 int base_width
, base_height
, width_inc
, height_inc
;
6485 int min_rows
= 0, min_cols
= 0;
6486 XSizeHints
*size_hints
;
6488 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6489 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6490 width_inc
= FRAME_COLUMN_WIDTH (f
);
6491 height_inc
= FRAME_LINE_HEIGHT (f
);
6493 check_frame_size (f
, &min_rows
, &min_cols
);
6495 size_hints
= FRAME_SIZE_HINTS (f
);
6496 if (size_hints
== NULL
)
6498 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6499 bzero (size_hints
, sizeof (XSizeHints
));
6502 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6503 size_hints
->width_inc
= width_inc
;
6504 size_hints
->height_inc
= height_inc
;
6505 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6506 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6507 size_hints
->base_width
= base_width
;
6508 size_hints
->base_height
= base_height
;
6511 size_hints
->flags
= flags
;
6512 else if (user_position
)
6514 size_hints
->flags
&= ~ PPosition
;
6515 size_hints
->flags
|= USPosition
;
6519 #if 0 /* MAC_TODO: hide application instead of iconify? */
6520 /* Used for IconicState or NormalState */
6523 x_wm_set_window_state (f
, state
)
6527 #ifdef USE_X_TOOLKIT
6530 XtSetArg (al
[0], XtNinitialState
, state
);
6531 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6532 #else /* not USE_X_TOOLKIT */
6533 Window window
= FRAME_X_WINDOW (f
);
6535 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6536 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6538 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6539 #endif /* not USE_X_TOOLKIT */
6543 x_wm_set_icon_pixmap (f
, pixmap_id
)
6549 #ifndef USE_X_TOOLKIT
6550 Window window
= FRAME_X_WINDOW (f
);
6555 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6556 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6560 /* It seems there is no way to turn off use of an icon pixmap.
6561 The following line does it, only if no icon has yet been created,
6562 for some window managers. But with mwm it crashes.
6563 Some people say it should clear the IconPixmapHint bit in this case,
6564 but that doesn't work, and the X consortium said it isn't the
6565 right thing at all. Since there is no way to win,
6566 best to explicitly give up. */
6568 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6574 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6578 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6579 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6582 #else /* not USE_X_TOOLKIT */
6584 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6585 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6587 #endif /* not USE_X_TOOLKIT */
6590 #endif /* MAC_TODO */
6593 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6597 #if 0 /* MAC_TODO: no icons on Mac */
6598 #ifdef USE_X_TOOLKIT
6599 Window window
= XtWindow (f
->output_data
.x
->widget
);
6601 Window window
= FRAME_X_WINDOW (f
);
6604 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6605 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6606 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6608 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6609 #endif /* MAC_TODO */
6613 /***********************************************************************
6615 ***********************************************************************/
6617 /* An XLFD pattern is divided into blocks delimited by '*'. This
6618 structure holds information for each block. */
6619 struct xlfdpat_block
6621 /* Length of the pattern string in this block. Non-zero except for
6622 the first and the last blocks. */
6625 /* Pattern string except the last character in this block. The last
6626 character is replaced with NUL in order to use it as a
6628 unsigned char *pattern
;
6630 /* Last character of the pattern string. Must not be '?'. */
6631 unsigned char last_char
;
6633 /* One of the tables for the Boyer-Moore string search. It
6634 specifies the number of positions to proceed for each character
6635 with which the match fails. */
6638 /* The skip value for the last character in the above `skip' is
6639 assigned to `infinity' in order to simplify a loop condition.
6640 The original value is saved here. */
6646 /* Normalized pattern string. "Normalized" means that capital
6647 letters are lowered, blocks are not empty except the first and
6648 the last ones, and trailing '?'s in a block that is not the last
6649 one are moved to the next one. The last character in each block
6650 is replaced with NUL. */
6653 /* Number of characters except '*'s and trailing '?'s in the
6654 normalized pattern string. */
6657 /* Number of trailing '?'s in the normalized pattern string. */
6658 int trailing_anychars
;
6660 /* Number of blocks and information for each block. The latter is
6661 NULL if the pattern is exact (no '*' or '?' in it). */
6663 struct xlfdpat_block
*blocks
;
6667 xlfdpat_destroy (pat
)
6668 struct xlfdpat
*pat
;
6675 xfree (pat
->blocks
);
6682 static struct xlfdpat
*
6683 xlfdpat_create (pattern
)
6686 struct xlfdpat
*pat
;
6687 int nblocks
, i
, skip
;
6688 unsigned char last_char
, *p
, *q
, *anychar_head
;
6689 struct xlfdpat_block
*blk
;
6691 pat
= xmalloc (sizeof (struct xlfdpat
));
6692 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6694 /* Normalize the pattern string and store it to `pat->buf'. */
6696 anychar_head
= NULL
;
6699 for (p
= pattern
; *p
; p
++)
6701 unsigned char c
= *p
;
6704 if (last_char
== '*')
6705 /* ...a** -> ...a* */
6709 if (last_char
== '?')
6711 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6712 /* ...*??* -> ...*?? */
6715 /* ...a??* -> ...a*?? */
6717 *anychar_head
++ = '*';
6725 if (last_char
!= '?')
6729 /* On Mac OS X 10.3, tolower also converts non-ASCII
6730 characters for some locales. */
6734 *q
++ = last_char
= c
;
6738 pat
->nblocks
= nblocks
;
6739 if (last_char
!= '?')
6740 pat
->trailing_anychars
= 0;
6743 pat
->trailing_anychars
= q
- anychar_head
;
6746 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6748 if (anychar_head
== NULL
&& nblocks
== 1)
6750 /* The pattern is exact. */
6755 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6757 /* Divide the normalized pattern into blocks. */
6759 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6764 blk
->len
= p
- blk
->pattern
;
6768 blk
->len
= q
- blk
->pattern
;
6770 /* Setup a table for the Boyer-Moore string search. */
6771 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6774 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6775 blk
->pattern
[blk
->len
- 1] = '\0';
6777 for (skip
= 1; skip
< blk
->len
; skip
++)
6778 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6781 for (i
= 0; i
< 256; i
++)
6782 blk
->skip
[i
] = skip
;
6784 p
= blk
->pattern
+ (blk
->len
- skip
);
6786 blk
->skip
[*p
++] = skip
;
6788 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6795 xlfdpat_exact_p (pat
)
6796 struct xlfdpat
*pat
;
6798 return pat
->blocks
== NULL
;
6801 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6802 that the pattern in *BLK matches with its prefix. Return NULL
6803 there is no such strings. STRING must be lowered in advance. */
6806 xlfdpat_block_match_1 (blk
, string
, start_max
)
6807 struct xlfdpat_block
*blk
;
6808 unsigned char *string
;
6811 int start
, infinity
;
6812 unsigned char *p
, *s
;
6814 xassert (blk
->len
> 0);
6815 xassert (start_max
+ blk
->len
<= strlen (string
));
6816 xassert (blk
->last_char
!= '?');
6818 /* See the comments in the function `boyer_moore' (search.c) for the
6819 use of `infinity'. */
6820 infinity
= start_max
+ blk
->len
+ 1;
6821 blk
->skip
[blk
->last_char
] = infinity
;
6826 /* Check the last character of the pattern. */
6827 s
= string
+ blk
->len
- 1;
6830 start
+= blk
->skip
[*(s
+ start
)];
6832 while (start
<= start_max
);
6834 if (start
< infinity
)
6835 /* Couldn't find the last character. */
6838 /* No less than `infinity' means we could find the last
6839 character at `s[start - infinity]'. */
6842 /* Check the remaining characters. We prefer making no-'?'
6843 cases faster because the use of '?' is really rare. */
6848 while (*p
++ == *s
++)
6851 while (*(p
- 1) == '?');
6853 if (*(p
- 1) == '\0')
6855 return string
+ start
;
6858 start
+= blk
->last_char_skip
;
6860 while (start
<= start_max
);
6865 #define xlfdpat_block_match(b, s, m) \
6866 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6867 : xlfdpat_block_match_1 (b, s, m))
6869 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6870 matches with STRING. STRING must be lowered in advance. */
6873 xlfdpat_match (pat
, string
)
6874 struct xlfdpat
*pat
;
6875 unsigned char *string
;
6877 int str_len
, nblocks
, i
, start_max
;
6878 struct xlfdpat_block
*blk
;
6881 xassert (pat
->nblocks
> 0);
6883 if (xlfdpat_exact_p (pat
))
6884 return strcmp (pat
->buf
, string
) == 0;
6886 /* The number of the characters in the string must not be smaller
6887 than that in the pattern. */
6888 str_len
= strlen (string
);
6889 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6892 /* Chop off the trailing '?'s. */
6893 str_len
-= pat
->trailing_anychars
;
6895 /* The last block. When it is non-empty, it must match at the end
6897 nblocks
= pat
->nblocks
;
6898 blk
= pat
->blocks
+ (nblocks
- 1);
6900 /* The last block is also the first one. */
6901 return (str_len
== blk
->len
6902 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6903 else if (blk
->len
!= 0)
6904 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6907 /* The first block. When it is non-empty, it must match at the
6908 beginning of the string. */
6912 s
= xlfdpat_block_match (blk
, string
, 0);
6915 string
= s
+ blk
->len
;
6918 /* The rest of the blocks. */
6919 start_max
= str_len
- pat
->nchars
;
6920 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6922 s
= xlfdpat_block_match (blk
, string
, start_max
);
6925 start_max
-= s
- string
;
6926 string
= s
+ blk
->len
;
6933 /***********************************************************************
6935 ***********************************************************************/
6937 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6940 x_get_font_info (f
, font_idx
)
6944 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6947 /* the global font name table */
6948 static char **font_name_table
= NULL
;
6949 static int font_name_table_size
= 0;
6950 static int font_name_count
= 0;
6952 /* Alist linking font family names to Font Manager font family
6953 references (which can also be used as QuickDraw font IDs). We use
6954 an alist because hash tables are not ready when the terminal frame
6955 for Mac OS Classic is created. */
6956 static Lisp_Object fm_font_family_alist
;
6958 /* Hash table linking font family names to ATSU font IDs. */
6959 static Lisp_Object atsu_font_id_hash
;
6960 /* Alist linking Font Manager style to face attributes. */
6961 static Lisp_Object fm_style_face_attributes_alist
;
6962 static Lisp_Object Vmac_atsu_font_table
;
6963 extern Lisp_Object QCfamily
, QCweight
, QCslant
, Qnormal
, Qbold
, Qitalic
;
6966 /* Alist linking character set strings to Mac text encoding and Emacs
6968 static Lisp_Object Vmac_charset_info_alist
;
6971 create_text_encoding_info_alist ()
6973 Lisp_Object result
= Qnil
, rest
;
6975 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6977 Lisp_Object charset_info
= XCAR (rest
);
6978 Lisp_Object charset
, coding_system
, text_encoding
;
6979 Lisp_Object existing_info
;
6981 if (!(CONSP (charset_info
)
6982 && STRINGP (charset
= XCAR (charset_info
))
6983 && CONSP (XCDR (charset_info
))
6984 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6985 && CONSP (XCDR (XCDR (charset_info
)))
6986 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6989 existing_info
= assq_no_quit (text_encoding
, result
);
6990 if (NILP (existing_info
))
6991 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6994 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6995 XSETCDR (XCDR (existing_info
),
6996 Fcons (charset
, XCDR (XCDR (existing_info
))));
7004 decode_mac_font_name (name
, size
, coding_system
)
7007 Lisp_Object coding_system
;
7009 struct coding_system coding
;
7012 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
7014 for (p
= name
; *p
; p
++)
7015 if (!isascii (*p
) || iscntrl (*p
))
7020 setup_coding_system (coding_system
, &coding
);
7021 coding
.src_multibyte
= 0;
7022 coding
.dst_multibyte
= 1;
7023 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
7024 coding
.composing
= COMPOSITION_DISABLED
;
7025 buf
= (char *) alloca (size
);
7027 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
7028 bcopy (buf
, name
, coding
.produced
);
7029 name
[coding
.produced
] = '\0';
7033 /* If there's just one occurrence of '-' in the family name, it is
7034 replaced with '_'. (More than one occurrence of '-' means a
7035 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7036 p
= strchr (name
, '-');
7037 if (p
&& strchr (p
+ 1, '-') == NULL
)
7040 for (p
= name
; *p
; p
++)
7041 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7042 for some locales. */
7049 mac_to_x_fontname (name
, size
, style
, charset
)
7057 char xf
[256], *result
;
7060 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
7064 strcpy(foundry
, "Apple");
7065 strcpy(family
, name
);
7068 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7069 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
7070 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
7072 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
7073 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
7074 for (p
= result
; *p
; p
++)
7075 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7076 for some locales. */
7083 /* Parse fully-specified and instantiated X11 font spec XF, and store
7084 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7085 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7086 caller must allocate at least 256 and 32 bytes respectively. For
7087 ordinary Mac fonts, the value stored to FAMILY should just be their
7088 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7089 intlfonts collection contain their charset designation in their
7090 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7091 types of font names are handled accordingly. */
7093 const int kDefaultFontSize
= 12;
7096 parse_x_font_name (xf
, family
, size
, style
, charset
)
7102 Str31 foundry
, weight
;
7103 int point_size
, avgwidth
;
7106 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7107 foundry
, family
, weight
, slant
, size
,
7108 &point_size
, &avgwidth
, charset
) != 8
7109 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7110 foundry
, family
, weight
, slant
, size
,
7111 &point_size
, &avgwidth
, charset
) != 8)
7117 *size
= point_size
/ 10;
7118 else if (avgwidth
> 0)
7119 *size
= avgwidth
/ 10;
7122 *size
= kDefaultFontSize
;
7125 if (strcmp (weight
, "bold") == 0)
7130 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7132 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7134 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7136 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7137 but take overlap into account. */
7138 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7139 memcpy (family
, foundry
, foundry_len
);
7140 family
[foundry_len
] = '-';
7141 family
[foundry_len
+ 1 + family_len
] = '-';
7142 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7148 for (p
= family
; *p
; p
++)
7149 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7150 for some locales. */
7159 add_font_name_table_entry (char *font_name
)
7161 if (font_name_table_size
== 0)
7163 font_name_table_size
= 256;
7164 font_name_table
= (char **)
7165 xmalloc (font_name_table_size
* sizeof (char *));
7167 else if (font_name_count
+ 1 >= font_name_table_size
)
7169 font_name_table_size
*= 2;
7170 font_name_table
= (char **)
7171 xrealloc (font_name_table
,
7172 font_name_table_size
* sizeof (char *));
7175 font_name_table
[font_name_count
++] = font_name
;
7179 add_mac_font_name (name
, size
, style
, charset
)
7186 add_font_name_table_entry (mac_to_x_fontname (name
, size
, style
, charset
));
7189 add_font_name_table_entry (mac_to_x_fontname (name
, 0, style
, charset
));
7190 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
, charset
));
7191 add_font_name_table_entry (mac_to_x_fontname (name
, 0, bold
, charset
));
7192 add_font_name_table_entry (mac_to_x_fontname (name
, 0, italic
| bold
,
7199 fm_style_to_face_attributes (fm_style
)
7200 FMFontStyle fm_style
;
7204 fm_style
&= (bold
| italic
);
7205 tem
= assq_no_quit (make_number (fm_style
),
7206 fm_style_face_attributes_alist
);
7210 tem
= list4 (QCweight
, fm_style
& bold
? Qbold
: Qnormal
,
7211 QCslant
, fm_style
& italic
? Qitalic
: Qnormal
);
7212 fm_style_face_attributes_alist
=
7213 Fcons (Fcons (make_number (fm_style
), tem
),
7214 fm_style_face_attributes_alist
);
7220 /* Sets up the table font_name_table to contain the list of all fonts
7221 in the system the first time the table is used so that the Resource
7222 Manager need not be accessed every time this information is
7226 init_font_name_table ()
7228 #if TARGET_API_MAC_CARBON
7229 FMFontFamilyIterator ffi
;
7230 FMFontFamilyInstanceIterator ffii
;
7232 Lisp_Object text_encoding_info_alist
;
7233 struct gcpro gcpro1
;
7235 text_encoding_info_alist
= create_text_encoding_info_alist ();
7238 #if USE_CG_TEXT_DRAWING
7239 init_cg_text_anti_aliasing_threshold ();
7241 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7242 text_encoding_info_alist
)))
7245 struct Lisp_Hash_Table
*h
;
7247 ItemCount nfonts
, i
;
7248 ATSUFontID
*font_ids
= NULL
;
7254 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7255 make_float (DEFAULT_REHASH_SIZE
),
7256 make_float (DEFAULT_REHASH_THRESHOLD
),
7258 h
= XHASH_TABLE (atsu_font_id_hash
);
7260 err
= ATSUFontCount (&nfonts
);
7263 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7264 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7267 for (i
= 0; i
< nfonts
; i
++)
7269 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7270 kFontMacintoshPlatform
, kFontNoScript
,
7271 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
7274 name
= xmalloc (name_len
+ 1);
7275 name
[name_len
] = '\0';
7276 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7277 kFontMacintoshPlatform
, kFontNoScript
,
7278 kFontNoLanguage
, name_len
, name
,
7283 FMFontStyle style
= normal
;
7285 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
7286 family
= make_unibyte_string (name
, name_len
);
7287 FMGetFontFamilyInstanceFromFont (font_ids
[i
], &ff
, &style
);
7288 Fputhash ((font_ids
[i
] > MOST_POSITIVE_FIXNUM
7289 ? make_float (font_ids
[i
])
7290 : make_number (font_ids
[i
])),
7293 fm_style_to_face_attributes (style
))),
7294 Vmac_atsu_font_table
);
7296 && hash_lookup (h
, family
, &hash_code
) < 0)
7298 add_mac_font_name (name
, 0, normal
, "iso10646-1");
7299 hash_put (h
, family
, long_to_cons (font_ids
[i
]),
7310 /* Create a dummy instance iterator here to avoid creating and
7311 destroying it in the loop. */
7312 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7314 /* Create an iterator to enumerate the font families. */
7315 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7318 FMDisposeFontFamilyInstanceIterator (&ffii
);
7322 GCPRO1 (text_encoding_info_alist
);
7324 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7330 TextEncoding encoding
;
7331 TextEncodingBase sc
;
7332 Lisp_Object text_encoding_info
, family
;
7334 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7340 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7342 sc
= GetTextEncodingBase (encoding
);
7343 text_encoding_info
= assq_no_quit (make_number (sc
),
7344 text_encoding_info_alist
);
7345 if (NILP (text_encoding_info
))
7346 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7347 text_encoding_info_alist
);
7348 decode_mac_font_name (name
, sizeof (name
),
7349 XCAR (XCDR (text_encoding_info
)));
7350 family
= build_string (name
);
7351 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7353 fm_font_family_alist
= Fcons (Fcons (family
, make_number (ff
)),
7354 fm_font_family_alist
);
7356 /* Point the instance iterator at the current font family. */
7357 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7360 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7363 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7365 if (size
> 0 || style
== normal
)
7366 for (; !NILP (rest
); rest
= XCDR (rest
))
7367 add_mac_font_name (name
, size
, style
, SDATA (XCAR (rest
)));
7373 /* Dispose of the iterators. */
7374 FMDisposeFontFamilyIterator (&ffi
);
7375 FMDisposeFontFamilyInstanceIterator (&ffii
);
7376 #else /* !TARGET_API_MAC_CARBON */
7378 SInt16 fontnum
, old_fontnum
;
7379 int num_mac_fonts
= CountResources('FOND');
7381 Handle font_handle
, font_handle_2
;
7382 short id
, scriptcode
;
7385 struct FontAssoc
*fat
;
7386 struct AsscEntry
*assc_entry
;
7387 Lisp_Object text_encoding_info_alist
, text_encoding_info
, family
;
7388 struct gcpro gcpro1
;
7390 GetPort (&port
); /* save the current font number used */
7391 old_fontnum
= port
->txFont
;
7393 text_encoding_info_alist
= create_text_encoding_info_alist ();
7395 GCPRO1 (text_encoding_info_alist
);
7397 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7399 font_handle
= GetIndResource ('FOND', i
);
7403 GetResInfo (font_handle
, &id
, &type
, name
);
7404 GetFNum (name
, &fontnum
);
7406 if (fontnum
== 0 || *name
== '.')
7410 scriptcode
= FontToScript (fontnum
);
7411 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7412 text_encoding_info_alist
);
7413 if (NILP (text_encoding_info
))
7414 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7415 text_encoding_info_alist
);
7416 decode_mac_font_name (name
, sizeof (name
),
7417 XCAR (XCDR (text_encoding_info
)));
7418 family
= build_string (name
);
7419 if (!NILP (Fassoc (family
, fm_font_family_alist
)))
7421 fm_font_family_alist
= Fcons (Fcons (family
, make_number (fontnum
)),
7422 fm_font_family_alist
);
7425 HLock (font_handle
);
7427 if (GetResourceSizeOnDisk (font_handle
)
7428 >= sizeof (struct FamRec
))
7430 fat
= (struct FontAssoc
*) (*font_handle
7431 + sizeof (struct FamRec
));
7433 = (struct AsscEntry
*) (*font_handle
7434 + sizeof (struct FamRec
)
7435 + sizeof (struct FontAssoc
));
7437 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7439 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7441 for (; !NILP (rest
); rest
= XCDR (rest
))
7442 add_mac_font_name (name
, assc_entry
->fontSize
,
7443 assc_entry
->fontStyle
,
7444 SDATA (XCAR (rest
)));
7448 HUnlock (font_handle
);
7449 font_handle_2
= GetNextFOND (font_handle
);
7450 ReleaseResource (font_handle
);
7451 font_handle
= font_handle_2
;
7453 while (ResError () == noErr
&& font_handle
);
7458 TextFont (old_fontnum
);
7459 #endif /* !TARGET_API_MAC_CARBON */
7464 mac_clear_font_name_table ()
7468 for (i
= 0; i
< font_name_count
; i
++)
7469 xfree (font_name_table
[i
]);
7470 xfree (font_name_table
);
7471 font_name_table
= NULL
;
7472 font_name_table_size
= font_name_count
= 0;
7473 fm_font_family_alist
= Qnil
;
7477 enum xlfd_scalable_field_index
7479 XLFD_SCL_PIXEL_SIZE
,
7480 XLFD_SCL_POINT_SIZE
,
7485 static int xlfd_scalable_fields
[] =
7494 mac_do_list_fonts (pattern
, maxnames
)
7499 Lisp_Object font_list
= Qnil
;
7500 struct xlfdpat
*pat
;
7502 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7505 if (font_name_table
== NULL
) /* Initialize when first used. */
7506 init_font_name_table ();
7508 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7511 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7512 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7513 fonts are scaled according to the specified size. */
7516 field
= xlfd_scalable_fields
;
7524 if ('0' <= *ptr
&& *ptr
<= '9')
7526 *val
= *ptr
++ - '0';
7527 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7528 *val
= *val
* 10 + *ptr
++ - '0';
7535 ptr
= strchr (ptr
, '-');
7538 while (ptr
&& i
< 14);
7540 if (i
== 14 && ptr
== NULL
)
7542 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7543 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7544 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7545 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7547 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7548 scl_val
[XLFD_SCL_POINT_SIZE
] =
7549 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7550 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7552 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7553 scl_val
[XLFD_SCL_AVGWIDTH
] =
7554 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7555 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7559 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7561 pat
= xlfdpat_create (pattern
);
7565 exact
= xlfdpat_exact_p (pat
);
7567 for (i
= 0; i
< font_name_count
; i
++)
7569 if (xlfdpat_match (pat
, font_name_table
[i
]))
7571 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7572 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7575 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7576 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7578 int former_len
= ptr
- font_name_table
[i
];
7580 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7581 memcpy (scaled
, font_name_table
[i
], former_len
);
7582 sprintf (scaled
+ former_len
,
7583 "-%d-%d-72-72-m-%d-%s",
7584 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7585 scl_val
[XLFD_SCL_POINT_SIZE
],
7586 scl_val
[XLFD_SCL_AVGWIDTH
],
7587 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7589 if (xlfdpat_match (pat
, scaled
))
7591 font_list
= Fcons (build_string (scaled
), font_list
);
7593 if (exact
|| (maxnames
> 0 && ++n_fonts
>= maxnames
))
7601 xlfdpat_destroy (pat
);
7606 /* Return a list of names of available fonts matching PATTERN on frame F.
7608 Frame F null means we have not yet created any frame on Mac, and
7609 consult the first display in x_display_list. MAXNAMES sets a limit
7610 on how many fonts to match. */
7613 x_list_fonts (f
, pattern
, size
, maxnames
)
7615 Lisp_Object pattern
;
7618 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7619 struct mac_display_info
*dpyinfo
7620 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7622 xassert (size
<= 0);
7624 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7625 if (NILP (patterns
))
7626 patterns
= Fcons (pattern
, Qnil
);
7628 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7630 pattern
= XCAR (patterns
);
7632 if (!STRINGP (pattern
))
7635 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7636 key
= Fcons (pattern
, make_number (maxnames
));
7638 list
= Fassoc (key
, tem
);
7641 list
= Fcdr_safe (list
);
7642 /* We have a cashed list. Don't have to get the list again. */
7647 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7650 /* MAC_TODO: add code for matching outline fonts here */
7652 /* Now store the result in the cache. */
7653 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7654 Fcons (Fcons (key
, list
),
7655 XCAR (XCDR (dpyinfo
->name_list_element
))));
7658 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7667 /* Check that FONT is valid on frame F. It is if it can be found in F's
7671 x_check_font (f
, font
)
7676 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7678 xassert (font
!= NULL
);
7680 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7681 if (dpyinfo
->font_table
[i
].name
7682 && font
== dpyinfo
->font_table
[i
].font
)
7685 xassert (i
< dpyinfo
->n_fonts
);
7688 #endif /* GLYPH_DEBUG != 0 */
7690 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7691 Note: There are (broken) X fonts out there with invalid XFontStruct
7692 min_bounds contents. For example, handa@etl.go.jp reports that
7693 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7694 have font->min_bounds.width == 0. */
7697 x_font_min_bounds (font
, w
, h
)
7698 MacFontStruct
*font
;
7701 *h
= FONT_HEIGHT (font
);
7702 *w
= font
->min_bounds
.width
;
7706 /* Compute the smallest character width and smallest font height over
7707 all fonts available on frame F. Set the members smallest_char_width
7708 and smallest_font_height in F's x_display_info structure to
7709 the values computed. Value is non-zero if smallest_font_height or
7710 smallest_char_width become smaller than they were before. */
7713 x_compute_min_glyph_bounds (f
)
7717 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7718 MacFontStruct
*font
;
7719 int old_width
= dpyinfo
->smallest_char_width
;
7720 int old_height
= dpyinfo
->smallest_font_height
;
7722 dpyinfo
->smallest_font_height
= 100000;
7723 dpyinfo
->smallest_char_width
= 100000;
7725 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7726 if (dpyinfo
->font_table
[i
].name
)
7728 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7731 font
= (MacFontStruct
*) fontp
->font
;
7732 xassert (font
!= (MacFontStruct
*) ~0);
7733 x_font_min_bounds (font
, &w
, &h
);
7735 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7736 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7739 xassert (dpyinfo
->smallest_char_width
> 0
7740 && dpyinfo
->smallest_font_height
> 0);
7742 return (dpyinfo
->n_fonts
== 1
7743 || dpyinfo
->smallest_char_width
< old_width
7744 || dpyinfo
->smallest_font_height
< old_height
);
7748 /* Determine whether given string is a fully-specified XLFD: all 14
7749 fields are present, none is '*'. */
7752 is_fully_specified_xlfd (char *p
)
7760 for (i
= 0; i
< 13; i
++)
7762 q
= strchr (p
+ 1, '-');
7765 if (q
- p
== 2 && *(p
+ 1) == '*')
7770 if (strchr (p
+ 1, '-') != NULL
)
7773 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7780 /* XLoadQueryFont creates and returns an internal representation for a
7781 font in a MacFontStruct struct. There is really no concept
7782 corresponding to "loading" a font on the Mac. But we check its
7783 existence and find the font number and all other information for it
7784 and store them in the returned MacFontStruct. */
7786 static MacFontStruct
*
7787 XLoadQueryFont (Display
*dpy
, char *fontname
)
7795 static ATSUFontID font_id
;
7796 ATSUStyle mac_style
= NULL
;
7799 #if TARGET_API_MAC_CARBON
7800 TextEncoding encoding
;
7805 MacFontStruct
*font
;
7806 XCharStruct
*space_bounds
= NULL
, *pcm
;
7808 if (is_fully_specified_xlfd (fontname
))
7812 Lisp_Object matched_fonts
;
7814 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7815 if (NILP (matched_fonts
))
7817 name
= SDATA (XCAR (matched_fonts
));
7820 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7824 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7827 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7828 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7829 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7830 sizeof (Boolean
), sizeof (Boolean
)};
7831 static Fixed size_fixed
;
7832 static Boolean bold_p
, italic_p
;
7833 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7834 &bold_p
, &italic_p
};
7835 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
,
7837 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
,
7838 kDecomposeDiacriticsSelector
};
7839 Lisp_Object font_id_cons
;
7842 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7843 atsu_font_id_hash
, Qnil
);
7844 if (NILP (font_id_cons
))
7846 font_id
= cons_to_long (font_id_cons
);
7847 size_fixed
= Long2Fix (size
);
7848 bold_p
= (fontface
& bold
) != 0;
7849 italic_p
= (fontface
& italic
) != 0;
7850 err
= ATSUCreateStyle (&mac_style
);
7853 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7857 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7858 tags
, sizes
, values
);
7861 err
= FMGetFontFamilyInstanceFromFont (font_id
, &fontnum
, &style
);
7864 scriptcode
= kTextEncodingMacUnicode
;
7869 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7873 fontnum
= XINT (XCDR (tmp
));
7874 #if TARGET_API_MAC_CARBON
7875 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7877 scriptcode
= GetTextEncodingBase (encoding
);
7879 scriptcode
= FontToScript (fontnum
);
7883 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7885 font
->mac_fontnum
= fontnum
;
7886 font
->mac_fontsize
= size
;
7887 font
->mac_fontface
= fontface
;
7888 font
->mac_scriptcode
= scriptcode
;
7890 font
->mac_style
= mac_style
;
7891 #if USE_CG_TEXT_DRAWING
7892 font
->cg_font
= NULL
;
7893 font
->cg_glyphs
= NULL
;
7897 /* Apple Japanese (SJIS) font is listed as both
7898 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7899 (Roman script) in init_font_name_table (). The latter should be
7900 treated as a one-byte font. */
7901 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7902 font
->mac_scriptcode
= smRoman
;
7904 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7907 if (font
->mac_style
)
7912 font
->min_byte1
= 0;
7913 font
->max_byte1
= 0xff;
7914 font
->min_char_or_byte2
= 0;
7915 font
->max_char_or_byte2
= 0xff;
7917 font
->bounds
.rows
= xmalloc (sizeof (XCharStruct
*) * 0x100);
7918 bzero (font
->bounds
.rows
, sizeof (XCharStruct
*) * 0x100);
7919 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStruct
) * 0x100);
7920 pcm_init (font
->bounds
.rows
[0], 0x100);
7922 #if USE_CG_TEXT_DRAWING
7926 ATSFontRef ats_font
;
7928 err
= FMGetFontFromFontFamilyInstance (fontnum
, fontface
,
7930 /* Use CG text drawing if italic/bold is not synthesized. */
7931 if (err
== noErr
&& style
== fontface
)
7933 ats_font
= FMGetATSFontRefFromFont (font_id
);
7934 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7940 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7941 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7944 space_bounds
= font
->bounds
.rows
[0] + 0x20;
7945 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7946 &font
->ascent
, &font
->descent
,
7948 #if USE_CG_TEXT_DRAWING
7949 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7957 mac_unload_font (&one_mac_display_info
, font
);
7961 pcm
= font
->bounds
.rows
[0];
7962 for (c
= 0x21; c
<= 0xff; c
++)
7965 /* Soft hyphen is not supported in ATSUI. */
7973 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7974 #if USE_CG_TEXT_DRAWING
7975 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7982 #if USE_CG_TEXT_DRAWING
7983 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7985 /* Don't use CG text drawing if font substitution occurs in
7986 ASCII or Latin-1 characters. */
7987 CGFontRelease (font
->cg_font
);
7988 font
->cg_font
= NULL
;
7989 xfree (font
->cg_glyphs
);
7990 font
->cg_glyphs
= NULL
;
7999 SInt16 old_fontnum
, old_fontsize
;
8001 FontInfo the_fontinfo
;
8002 int is_two_byte_font
;
8004 /* Save the current font number used. */
8006 #if TARGET_API_MAC_CARBON
8007 old_fontnum
= GetPortTextFont (port
);
8008 old_fontsize
= GetPortTextSize (port
);
8009 old_fontface
= GetPortTextFace (port
);
8011 old_fontnum
= port
->txFont
;
8012 old_fontsize
= port
->txSize
;
8013 old_fontface
= port
->txFace
;
8018 TextFace (fontface
);
8020 GetFontInfo (&the_fontinfo
);
8022 font
->ascent
= the_fontinfo
.ascent
;
8023 font
->descent
= the_fontinfo
.descent
;
8025 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
8026 || font
->mac_scriptcode
== smTradChinese
8027 || font
->mac_scriptcode
== smSimpChinese
8028 || font
->mac_scriptcode
== smKorean
);
8030 if (is_two_byte_font
)
8034 font
->min_byte1
= 0xa1;
8035 font
->max_byte1
= 0xfe;
8036 font
->min_char_or_byte2
= 0xa1;
8037 font
->max_char_or_byte2
= 0xfe;
8039 /* Use the width of an "ideographic space" of that font
8040 because the_fontinfo.widMax returns the wrong width for
8042 switch (font
->mac_scriptcode
)
8045 font
->min_byte1
= 0x81;
8046 font
->max_byte1
= 0xfc;
8047 font
->min_char_or_byte2
= 0x40;
8048 font
->max_char_or_byte2
= 0xfc;
8049 char_width
= StringWidth("\p\x81\x40");
8052 font
->min_char_or_byte2
= 0x40;
8053 char_width
= StringWidth("\p\xa1\x40");
8056 char_width
= StringWidth("\p\xa1\xa1");
8059 char_width
= StringWidth("\p\xa1\xa1");
8063 font
->bounds
.per_char
= NULL
;
8065 if (fontface
& italic
)
8066 font
->max_bounds
.rbearing
= char_width
+ 1;
8068 font
->max_bounds
.rbearing
= char_width
;
8069 font
->max_bounds
.lbearing
= 0;
8070 font
->max_bounds
.width
= char_width
;
8071 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8072 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8074 font
->min_bounds
= font
->max_bounds
;
8080 font
->min_byte1
= font
->max_byte1
= 0;
8081 font
->min_char_or_byte2
= 0x20;
8082 font
->max_char_or_byte2
= 0xff;
8084 font
->bounds
.per_char
=
8085 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8086 bzero (font
->bounds
.per_char
,
8087 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8089 space_bounds
= font
->bounds
.per_char
;
8090 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
8091 space_bounds
, NULL
);
8093 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8094 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8097 /* Restore previous font number, size and face. */
8098 TextFont (old_fontnum
);
8099 TextSize (old_fontsize
);
8100 TextFace (old_fontface
);
8107 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8108 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8111 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8113 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8115 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8117 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8119 font
->min_bounds
.descent
= min (font
->min_bounds
.descent
,
8122 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8124 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8126 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8128 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8130 font
->max_bounds
.descent
= max (font
->max_bounds
.descent
,
8135 font
->mac_style
== NULL
&&
8137 font
->max_bounds
.width
== font
->min_bounds
.width
8138 && font
->min_bounds
.lbearing
>= 0
8139 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8141 /* Fixed width and no overhangs. */
8142 xfree (font
->bounds
.per_char
);
8143 font
->bounds
.per_char
= NULL
;
8147 #if !defined (MAC_OS8) || USE_ATSUI
8148 /* AppKit and WebKit do some adjustment to the heights of Courier,
8149 Helvetica, and Times. This only works on the environments where
8150 srcCopy text transfer mode is never used. */
8152 #ifdef MAC_OS8 /* implies USE_ATSUI */
8155 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8156 || strcmp (family
, "times") == 0))
8157 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8165 mac_unload_font (dpyinfo
, font
)
8166 struct mac_display_info
*dpyinfo
;
8169 xfree (font
->full_name
);
8171 if (font
->mac_style
)
8175 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8176 if (font
->bounds
.rows
[i
])
8177 xfree (font
->bounds
.rows
[i
]);
8178 xfree (font
->bounds
.rows
);
8179 ATSUDisposeStyle (font
->mac_style
);
8183 if (font
->bounds
.per_char
)
8184 xfree (font
->bounds
.per_char
);
8185 #if USE_CG_TEXT_DRAWING
8187 CGFontRelease (font
->cg_font
);
8188 if (font
->cg_glyphs
)
8189 xfree (font
->cg_glyphs
);
8195 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8196 pointer to the structure font_info while allocating it dynamically.
8197 If SIZE is 0, load any size of font.
8198 If loading is failed, return NULL. */
8201 x_load_font (f
, fontname
, size
)
8203 register char *fontname
;
8206 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8207 Lisp_Object font_names
;
8209 /* Get a list of all the fonts that match this name. Once we
8210 have a list of matching fonts, we compare them against the fonts
8211 we already have by comparing names. */
8212 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8214 if (!NILP (font_names
))
8219 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8220 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8221 if (dpyinfo
->font_table
[i
].name
8222 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8223 SDATA (XCAR (tail
)))
8224 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8225 SDATA (XCAR (tail
)))))
8226 return (dpyinfo
->font_table
+ i
);
8231 /* Load the font and add it to the table. */
8233 struct MacFontStruct
*font
;
8234 struct font_info
*fontp
;
8237 fontname
= (char *) SDATA (XCAR (font_names
));
8240 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
8245 /* Find a free slot in the font table. */
8246 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8247 if (dpyinfo
->font_table
[i
].name
== NULL
)
8250 /* If no free slot found, maybe enlarge the font table. */
8251 if (i
== dpyinfo
->n_fonts
8252 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8255 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8256 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8258 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8261 fontp
= dpyinfo
->font_table
+ i
;
8262 if (i
== dpyinfo
->n_fonts
)
8265 /* Now fill in the slots of *FONTP. */
8267 bzero (fontp
, sizeof (*fontp
));
8269 fontp
->font_idx
= i
;
8270 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8271 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8273 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8275 /* Fixed width font. */
8276 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8283 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8284 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8286 fontp
->space_width
= pcm
->width
;
8288 fontp
->space_width
= FONT_WIDTH (font
);
8292 int width
= pcm
->width
;
8293 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8294 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8295 width
+= pcm
->width
;
8296 fontp
->average_width
= width
/ 95;
8299 fontp
->average_width
= FONT_WIDTH (font
);
8302 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8303 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8305 fontp
->size
= font
->max_bounds
.width
;
8306 fontp
->height
= FONT_HEIGHT (font
);
8308 /* For some font, ascent and descent in max_bounds field is
8309 larger than the above value. */
8310 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8311 if (max_height
> fontp
->height
)
8312 fontp
->height
= max_height
;
8315 /* The slot `encoding' specifies how to map a character
8316 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8317 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8318 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8319 2:0xA020..0xFF7F). For the moment, we don't know which charset
8320 uses this font. So, we set information in fontp->encoding[1]
8321 which is never used by any charset. If mapping can't be
8322 decided, set FONT_ENCODING_NOT_DECIDED. */
8323 if (font
->mac_scriptcode
== smJapanese
)
8324 fontp
->encoding
[1] = 4;
8328 = (font
->max_byte1
== 0
8330 ? (font
->min_char_or_byte2
< 0x80
8331 ? (font
->max_char_or_byte2
< 0x80
8332 ? 0 /* 0x20..0x7F */
8333 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8334 : 1) /* 0xA0..0xFF */
8336 : (font
->min_byte1
< 0x80
8337 ? (font
->max_byte1
< 0x80
8338 ? (font
->min_char_or_byte2
< 0x80
8339 ? (font
->max_char_or_byte2
< 0x80
8340 ? 0 /* 0x2020..0x7F7F */
8341 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8342 : 3) /* 0x20A0..0x7FFF */
8343 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8344 : (font
->min_char_or_byte2
< 0x80
8345 ? (font
->max_char_or_byte2
< 0x80
8346 ? 2 /* 0xA020..0xFF7F */
8347 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8348 : 1))); /* 0xA0A0..0xFFFF */
8351 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8352 fontp
->baseline_offset
8353 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8354 ? (long) value
: 0);
8355 fontp
->relative_compose
8356 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8357 ? (long) value
: 0);
8358 fontp
->default_ascent
8359 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8360 ? (long) value
: 0);
8362 fontp
->baseline_offset
= 0;
8363 fontp
->relative_compose
= 0;
8364 fontp
->default_ascent
= 0;
8367 /* Set global flag fonts_changed_p to non-zero if the font loaded
8368 has a character with a smaller width than any other character
8369 before, or if the font loaded has a smaller height than any
8370 other font loaded before. If this happens, it will make a
8371 glyph matrix reallocation necessary. */
8372 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8379 /* Return a pointer to struct font_info of a font named FONTNAME for
8380 frame F. If no such font is loaded, return NULL. */
8383 x_query_font (f
, fontname
)
8385 register char *fontname
;
8387 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8390 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8391 if (dpyinfo
->font_table
[i
].name
8392 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
8393 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8394 return (dpyinfo
->font_table
+ i
);
8399 /* Find a CCL program for a font specified by FONTP, and set the member
8400 `encoder' of the structure. */
8403 x_find_ccl_program (fontp
)
8404 struct font_info
*fontp
;
8406 Lisp_Object list
, elt
;
8408 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8412 && STRINGP (XCAR (elt
))
8413 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8419 struct ccl_program
*ccl
8420 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8422 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8425 fontp
->font_encoder
= ccl
;
8429 #if USE_MAC_FONT_PANEL
8430 /* Whether Font Panel has been shown before. The first call to font
8431 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8432 slow. This variable is used for deferring such a call as much as
8434 static int font_panel_shown_p
= 0;
8437 mac_font_panel_visible_p ()
8439 return font_panel_shown_p
&& FPIsFontPanelVisible ();
8443 mac_show_hide_font_panel ()
8445 font_panel_shown_p
= 1;
8447 return FPShowHideFontPanel ();
8451 mac_set_font_info_for_selection (f
, face_id
, c
)
8456 EventTargetRef target
= NULL
;
8457 XFontStruct
*font
= NULL
;
8459 if (!mac_font_panel_visible_p ())
8464 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
8466 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
8470 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
8471 face
= FACE_FROM_ID (f
, face_id
);
8477 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
8480 if (font
->mac_fontnum
!= -1)
8482 FontSelectionQDStyle qd_style
;
8484 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
8485 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
8486 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
8487 qd_style
.size
= font
->mac_fontsize
;
8488 qd_style
.hasColor
= false;
8490 err
= SetFontInfoForSelection (kFontSelectionQDType
,
8491 1, &qd_style
, target
);
8494 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
8495 1, &font
->mac_style
, target
);
8503 /* The Mac Event loop code */
8505 #if !TARGET_API_MAC_CARBON
8507 #include <Quickdraw.h>
8508 #include <Balloons.h>
8509 #include <Devices.h>
8511 #include <Gestalt.h>
8513 #include <Processes.h>
8515 #include <ToolUtils.h>
8516 #include <TextUtils.h>
8517 #include <Dialogs.h>
8520 #include <Resources.h>
8525 #endif /* ! TARGET_API_MAC_CARBON */
8530 #define WINDOW_RESOURCE 128
8531 #define TERM_WINDOW_RESOURCE 129
8533 #define DEFAULT_NUM_COLS 80
8535 #define MIN_DOC_SIZE 64
8536 #define MAX_DOC_SIZE 32767
8538 #define EXTRA_STACK_ALLOC (256 * 1024)
8540 #define ARGV_STRING_LIST_ID 129
8541 #define ABOUT_ALERT_ID 128
8542 #define RAM_TOO_LARGE_ALERT_ID 129
8544 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8545 Lisp_Object Qreverse
;
8548 /* Modifier associated with the control key, or nil to ignore. */
8549 Lisp_Object Vmac_control_modifier
;
8551 /* Modifier associated with the option key, or nil to ignore. */
8552 Lisp_Object Vmac_option_modifier
;
8554 /* Modifier associated with the command key, or nil to ignore. */
8555 Lisp_Object Vmac_command_modifier
;
8557 /* Modifier associated with the function key, or nil to ignore. */
8558 Lisp_Object Vmac_function_modifier
;
8560 /* True if the option and command modifiers should be used to emulate
8561 a three button mouse */
8562 Lisp_Object Vmac_emulate_three_button_mouse
;
8564 #if USE_CARBON_EVENTS
8565 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8566 mouse-2, instead of mouse-3. */
8567 int mac_wheel_button_is_mouse_2
;
8569 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8570 for processing before Emacs sees it. */
8571 int mac_pass_command_to_system
;
8573 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8574 for processing before Emacs sees it. */
8575 int mac_pass_control_to_system
;
8578 /* Points to the variable `inev' in the function XTread_socket. It is
8579 used for passing an input event to the function back from
8580 Carbon/Apple event handlers. */
8581 static struct input_event
*read_socket_inev
= NULL
;
8583 Point saved_menu_event_location
;
8586 #if USE_CARBON_EVENTS
8587 static Lisp_Object Qhi_command
;
8589 extern Lisp_Object Qwindow
;
8590 static Lisp_Object Qtoolbar_switch_mode
;
8592 #if USE_MAC_FONT_PANEL
8593 extern Lisp_Object Qfont
;
8594 static Lisp_Object Qpanel_closed
, Qselection
;
8597 static TSMDocumentID tsm_document_id
;
8598 static Lisp_Object Qtext_input
;
8599 static Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
8600 static Lisp_Object Vmac_ts_active_input_overlay
;
8601 extern Lisp_Object Qbefore_string
;
8602 static Lisp_Object Vmac_ts_script_language_on_focus
;
8603 static Lisp_Object saved_ts_script_language_on_focus
;
8604 static ScriptLanguageRecord saved_ts_language
;
8605 static Component saved_ts_component
;
8608 extern int mac_ready_for_apple_events
;
8609 extern Lisp_Object Qundefined
;
8610 extern void init_apple_event_handler
P_ ((void));
8611 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8612 Lisp_Object
*, Lisp_Object
*,
8614 extern OSErr init_coercion_handler
P_ ((void));
8617 OSErr install_drag_handler
P_ ((WindowRef
));
8618 void remove_drag_handler
P_ ((WindowRef
));
8620 #if USE_CARBON_EVENTS
8622 extern void init_service_handler ();
8623 static Lisp_Object Qservice
, Qpaste
, Qperform
;
8625 /* Window Event Handler */
8626 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8629 OSStatus
install_window_handler (WindowPtr
);
8631 extern void init_emacs_passwd_dir ();
8632 extern int emacs_main (int, char **, char **);
8634 extern void initialize_applescript();
8635 extern void terminate_applescript();
8637 /* Table for translating Mac keycode to X keysym values. Contributed
8639 Mapping for special keys is now identical to that in Apple X11
8640 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8641 on the right of the Cmd key on laptops, and fn + `enter' (->
8643 static unsigned char keycode_to_xkeysym_table
[] = {
8644 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8645 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8646 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8648 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8649 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8650 /*0x38*/ 0, 0, 0, 0,
8651 /*0x3C*/ 0, 0, 0, 0,
8653 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8654 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8655 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8656 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8658 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8659 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8660 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8661 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8663 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8664 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8665 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8666 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8668 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8669 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8670 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8671 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8675 /* Table for translating Mac keycode with the laptop `fn' key to that
8676 without it. Destination symbols in comments are keys on US
8677 keyboard, and they may not be the same on other types of keyboards.
8678 If the destination is identical to the source (f1 ... f12), it
8679 doesn't map `fn' key to a modifier. */
8680 static unsigned char fn_keycode_to_keycode_table
[] = {
8681 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8682 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8683 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8685 /*0x30*/ 0, 0, 0, 0,
8686 /*0x34*/ 0, 0, 0, 0,
8687 /*0x38*/ 0, 0, 0, 0,
8688 /*0x3C*/ 0, 0, 0, 0,
8690 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8691 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8692 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8693 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8695 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8696 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8697 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8698 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8700 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8701 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8702 /*0x68*/ 0, 0, 0, 0,
8703 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8705 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
8706 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8707 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
8710 #endif /* MAC_OSX */
8713 #if USE_CARBON_EVENTS
8714 mac_to_emacs_modifiers (UInt32 mods
)
8716 mac_to_emacs_modifiers (EventModifiers mods
)
8719 unsigned int result
= 0;
8720 if (mods
& shiftKey
)
8721 result
|= shift_modifier
;
8723 /* Deactivated to simplify configuration:
8724 if Vmac_option_modifier is non-NIL, we fully process the Option
8725 key. Otherwise, we only process it if an additional Ctrl or Command
8726 is pressed. That way the system may convert the character to a
8728 if ((mods & optionKey) &&
8729 (( !NILP(Vmac_option_modifier) ||
8730 ((mods & cmdKey) || (mods & controlKey))))) */
8732 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8733 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8735 result
|= XUINT(val
);
8737 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8738 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8740 result
|= XUINT(val
);
8742 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8743 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8745 result
|= XUINT(val
);
8749 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8750 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8752 result
|= XUINT(val
);
8760 mac_get_emulated_btn ( UInt32 modifiers
)
8763 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8764 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8765 if (modifiers
& cmdKey
)
8766 result
= cmdIs3
? 2 : 1;
8767 else if (modifiers
& optionKey
)
8768 result
= cmdIs3
? 1 : 2;
8773 #if USE_CARBON_EVENTS
8774 /* Obtains the event modifiers from the event ref and then calls
8775 mac_to_emacs_modifiers. */
8777 mac_event_to_emacs_modifiers (EventRef eventRef
)
8780 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8781 sizeof (UInt32
), NULL
, &mods
);
8782 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8783 GetEventClass(eventRef
) == kEventClassMouse
)
8785 mods
&= ~(optionKey
| cmdKey
);
8787 return mac_to_emacs_modifiers (mods
);
8790 /* Given an event ref, return the code to use for the mouse button
8791 code in the emacs input_event. */
8793 mac_get_mouse_btn (EventRef ref
)
8795 EventMouseButton result
= kEventMouseButtonPrimary
;
8796 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8797 sizeof (EventMouseButton
), NULL
, &result
);
8800 case kEventMouseButtonPrimary
:
8801 if (NILP (Vmac_emulate_three_button_mouse
))
8805 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8806 sizeof (UInt32
), NULL
, &mods
);
8807 return mac_get_emulated_btn(mods
);
8809 case kEventMouseButtonSecondary
:
8810 return mac_wheel_button_is_mouse_2
? 2 : 1;
8811 case kEventMouseButtonTertiary
:
8812 case 4: /* 4 is the number for the mouse wheel button */
8813 return mac_wheel_button_is_mouse_2
? 1 : 2;
8819 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8820 events. However the click of the mouse wheel is not converted to a
8821 mouseDown or mouseUp event. Likewise for dead key down events.
8822 This calls ConvertEventRef, but then checks to see if it is a mouse
8823 up/down, or a dead key down carbon event that has not been
8824 converted, and if so, converts it by hand (to be picked up in the
8825 XTread_socket loop). */
8826 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8829 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8834 switch (GetEventClass (eventRef
))
8836 case kEventClassMouse
:
8837 switch (GetEventKind (eventRef
))
8839 case kEventMouseDown
:
8840 eventRec
->what
= mouseDown
;
8845 eventRec
->what
= mouseUp
;
8854 case kEventClassKeyboard
:
8855 switch (GetEventKind (eventRef
))
8857 case kEventRawKeyDown
:
8859 unsigned char char_codes
;
8862 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
8863 typeChar
, NULL
, sizeof (char),
8866 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
8867 typeUInt32
, NULL
, sizeof (UInt32
),
8871 eventRec
->what
= keyDown
;
8872 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8889 /* Need where and when. */
8892 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8893 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8894 /* Use two step process because new event modifiers are 32-bit
8895 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8896 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8897 NULL
, sizeof (UInt32
), NULL
, &mods
);
8898 eventRec
->modifiers
= mods
;
8900 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8912 Handle menubar_handle
;
8913 MenuHandle menu_handle
;
8915 menubar_handle
= GetNewMBar (128);
8916 if(menubar_handle
== NULL
)
8918 SetMenuBar (menubar_handle
);
8921 #if !TARGET_API_MAC_CARBON
8922 menu_handle
= GetMenuHandle (M_APPLE
);
8923 if(menu_handle
!= NULL
)
8924 AppendResMenu (menu_handle
,'DRVR');
8932 do_init_managers (void)
8934 #if !TARGET_API_MAC_CARBON
8935 InitGraf (&qd
.thePort
);
8937 FlushEvents (everyEvent
, 0);
8942 #endif /* !TARGET_API_MAC_CARBON */
8945 #if !TARGET_API_MAC_CARBON
8946 /* set up some extra stack space for use by emacs */
8947 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8949 /* MaxApplZone must be called for AppleScript to execute more
8950 complicated scripts */
8953 #endif /* !TARGET_API_MAC_CARBON */
8957 do_check_ram_size (void)
8959 SInt32 physical_ram_size
, logical_ram_size
;
8961 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8962 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8963 || physical_ram_size
> (1 << VALBITS
)
8964 || logical_ram_size
> (1 << VALBITS
))
8966 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8970 #endif /* MAC_OS8 */
8973 do_window_update (WindowPtr win
)
8975 struct frame
*f
= mac_window_to_frame (win
);
8979 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8981 if (win
!= tip_window
)
8983 if (f
->async_visible
== 0)
8985 /* Update events may occur when a frame gets iconified. */
8987 f
->async_visible
= 1;
8988 f
->async_iconified
= 0;
8989 SET_FRAME_GARBAGED (f
);
8995 #if TARGET_API_MAC_CARBON
8996 RgnHandle region
= NewRgn ();
8998 GetPortVisibleRegion (GetWindowPort (win
), region
);
8999 GetRegionBounds (region
, &r
);
9000 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9001 UpdateControls (win
, region
);
9002 DisposeRgn (region
);
9004 r
= (*win
->visRgn
)->rgnBBox
;
9005 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
9006 UpdateControls (win
, win
->visRgn
);
9015 is_emacs_window (WindowPtr win
)
9017 Lisp_Object tail
, frame
;
9022 FOR_EACH_FRAME (tail
, frame
)
9023 if (FRAME_MAC_P (XFRAME (frame
)))
9024 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9035 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9037 err
= ActivateTSMDocument (tsm_document_id
);
9041 if (EQ (Vmac_ts_script_language_on_focus
, Qt
)
9042 && EQ (saved_ts_script_language_on_focus
, Qt
))
9043 slptr
= &saved_ts_language
;
9044 else if (CONSP (Vmac_ts_script_language_on_focus
)
9045 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9046 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
))
9047 && CONSP (saved_ts_script_language_on_focus
)
9048 && EQ (XCAR (saved_ts_script_language_on_focus
),
9049 XCAR (Vmac_ts_script_language_on_focus
))
9050 && EQ (XCDR (saved_ts_script_language_on_focus
),
9051 XCDR (Vmac_ts_script_language_on_focus
)))
9053 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9054 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9061 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9062 err
= SetDefaultInputMethodOfClass (saved_ts_component
, slptr
,
9063 kKeyboardInputMethodClass
);
9065 err
= SetDefaultInputMethod (saved_ts_component
, slptr
);
9068 err
= SetTextServiceLanguage (slptr
);
9070 /* Seems to be needed on Mac OS X 10.2. */
9072 KeyScript (slptr
->fScript
| smKeyForceKeyScriptMask
);
9082 ScriptLanguageRecord slrec
, *slptr
= NULL
;
9084 saved_ts_script_language_on_focus
= Vmac_ts_script_language_on_focus
;
9086 if (EQ (Vmac_ts_script_language_on_focus
, Qt
))
9088 err
= GetTextServiceLanguage (&saved_ts_language
);
9090 slptr
= &saved_ts_language
;
9092 else if (CONSP (Vmac_ts_script_language_on_focus
)
9093 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus
))
9094 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus
)))
9096 slrec
.fScript
= XINT (XCAR (Vmac_ts_script_language_on_focus
));
9097 slrec
.fLanguage
= XINT (XCDR (Vmac_ts_script_language_on_focus
));
9103 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9104 GetDefaultInputMethodOfClass (&saved_ts_component
, slptr
,
9105 kKeyboardInputMethodClass
);
9107 GetDefaultInputMethod (&saved_ts_component
, slptr
);
9111 err
= DeactivateTSMDocument (tsm_document_id
);
9117 #if !TARGET_API_MAC_CARBON
9119 do_apple_menu (SInt16 menu_item
)
9122 SInt16 da_driver_refnum
;
9124 if (menu_item
== I_ABOUT
)
9125 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9128 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9129 da_driver_refnum
= OpenDeskAcc (item_name
);
9132 #endif /* !TARGET_API_MAC_CARBON */
9134 /* Handle drags in size box. Based on code contributed by Ben
9135 Mesander and IM - Window Manager A. */
9138 do_grow_window (WindowPtr w
, EventRecord
*e
)
9141 int rows
, columns
, width
, height
;
9142 struct frame
*f
= mac_window_to_frame (w
);
9143 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
9144 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
9145 #if TARGET_API_MAC_CARBON
9151 if (size_hints
->flags
& PMinSize
)
9153 min_width
= size_hints
->min_width
;
9154 min_height
= size_hints
->min_height
;
9156 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9158 #if TARGET_API_MAC_CARBON
9159 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
9161 height
= new_rect
.bottom
- new_rect
.top
;
9162 width
= new_rect
.right
- new_rect
.left
;
9164 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9165 /* see if it really changed size */
9168 height
= HiWord (grow_size
);
9169 width
= LoWord (grow_size
);
9172 if (width
!= FRAME_PIXEL_WIDTH (f
)
9173 || height
!= FRAME_PIXEL_HEIGHT (f
))
9175 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9176 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9178 x_set_window_size (f
, 0, columns
, rows
);
9183 #if TARGET_API_MAC_CARBON
9185 mac_get_ideal_size (f
)
9188 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9189 WindowPtr w
= FRAME_MAC_WINDOW (f
);
9192 int height
, width
, columns
, rows
;
9194 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9195 ideal_size
.v
= dpyinfo
->height
;
9196 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
9197 /* Adjust the standard size according to character boundaries. */
9198 width
= standard_rect
.right
- standard_rect
.left
;
9199 height
= standard_rect
.bottom
- standard_rect
.top
;
9200 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
9201 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
9202 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
9203 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9209 /* Handle clicks in zoom box. Calculation of "standard state" based
9210 on code in IM - Window Manager A and code contributed by Ben
9211 Mesander. The standard state of an Emacs window is 80-characters
9212 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9215 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9217 Rect zoom_rect
, port_rect
;
9219 struct frame
*f
= mac_window_to_frame (w
);
9220 #if TARGET_API_MAC_CARBON
9221 Point ideal_size
= mac_get_ideal_size (f
);
9223 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
9224 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
9225 && port_rect
.left
== zoom_rect
.left
9226 && port_rect
.top
== zoom_rect
.top
)
9227 zoom_in_or_out
= inZoomIn
;
9229 zoom_in_or_out
= inZoomOut
;
9232 mac_clear_window (f
);
9234 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
9235 #else /* not TARGET_API_MAC_CARBON */
9238 int w_title_height
, rows
;
9239 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9241 GetPort (&save_port
);
9243 SetPortWindowPort (w
);
9245 /* Clear window to avoid flicker. */
9246 EraseRect (&(w
->portRect
));
9247 if (zoom_in_or_out
== inZoomOut
)
9249 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9250 LocalToGlobal (&top_left
);
9252 /* calculate height of window's title bar */
9253 w_title_height
= top_left
.v
- 1
9254 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9256 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9257 zoom_rect
= qd
.screenBits
.bounds
;
9258 zoom_rect
.top
+= w_title_height
;
9259 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9261 zoom_rect
.right
= zoom_rect
.left
9262 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9264 /* Adjust the standard size according to character boundaries. */
9265 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
9267 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
9269 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9273 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
9275 SetPort (save_port
);
9276 #endif /* not TARGET_API_MAC_CARBON */
9278 #if !USE_CARBON_EVENTS
9279 /* retrieve window size and update application values */
9280 #if TARGET_API_MAC_CARBON
9281 GetWindowPortBounds (w
, &port_rect
);
9283 port_rect
= w
->portRect
;
9285 height
= port_rect
.bottom
- port_rect
.top
;
9286 width
= port_rect
.right
- port_rect
.left
;
9288 mac_handle_size_change (f
, width
, height
);
9289 mac_handle_origin_change (f
);
9294 mac_store_apple_event (class, id
, desc
)
9295 Lisp_Object
class, id
;
9298 struct input_event buf
;
9302 buf
.kind
= MAC_APPLE_EVENT
;
9305 XSETFRAME (buf
.frame_or_window
,
9306 mac_focus_frame (&one_mac_display_info
));
9307 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9308 is safe to use them during read_socket_hook. */
9309 buf
.arg
= mac_aedesc_to_lisp (desc
);
9310 kbd_buffer_store_event (&buf
);
9313 #if TARGET_API_MAC_CARBON
9315 mac_store_event_ref_as_apple_event (class, id
, class_key
, id_key
,
9316 event
, num_params
, names
, types
)
9319 Lisp_Object class_key
, id_key
;
9322 EventParamName
*names
;
9323 EventParamType
*types
;
9325 OSStatus err
= eventNotHandledErr
;
9326 Lisp_Object binding
;
9328 mac_find_apple_event_spec (class, id
, &class_key
, &id_key
, &binding
);
9329 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9331 if (INTEGERP (binding
))
9332 err
= XINT (binding
);
9335 AppleEvent apple_event
;
9336 err
= create_apple_event_from_event_ref (event
, num_params
,
9341 mac_store_apple_event (class_key
, id_key
, &apple_event
);
9342 AEDisposeDesc (&apple_event
);
9343 /* Post a harmless event so as to wake up from
9344 ReceiveNextEvent. */
9345 mac_post_mouse_moved_event ();
9354 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
9360 struct input_event buf
;
9364 buf
.kind
= DRAG_N_DROP_EVENT
;
9365 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9366 buf
.timestamp
= TickCount () * (1000 / 60);
9367 XSETINT (buf
.x
, mouse_pos
.h
);
9368 XSETINT (buf
.y
, mouse_pos
.v
);
9369 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
9370 buf
.arg
= mac_aedesc_to_lisp (desc
);
9371 kbd_buffer_store_event (&buf
);
9375 #if USE_CARBON_EVENTS
9376 static pascal OSStatus
9377 mac_handle_command_event (next_handler
, event
, data
)
9378 EventHandlerCallRef next_handler
;
9382 OSStatus result
, err
;
9384 static EventParamName names
[] = {kEventParamDirectObject
,
9385 kEventParamKeyModifiers
};
9386 static EventParamType types
[] = {typeHICommand
,
9388 int num_params
= sizeof (names
) / sizeof (names
[0]);
9390 result
= CallNextEventHandler (next_handler
, event
);
9391 if (result
!= eventNotHandledErr
)
9394 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9395 NULL
, sizeof (HICommand
), NULL
, &command
);
9397 if (err
!= noErr
|| command
.commandID
== 0)
9398 return eventNotHandledErr
;
9400 /* A HI command event is mapped to an Apple event whose event class
9401 symbol is `hi-command' and event ID is its command ID. */
9402 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
9404 event
, num_params
, names
, types
);
9405 return err
== noErr
? noErr
: eventNotHandledErr
;
9409 init_command_handler ()
9411 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
9412 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9414 if (handle_command_eventUPP
== NULL
)
9415 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9416 return InstallApplicationEventHandler (handle_command_eventUPP
,
9417 GetEventTypeCount (specs
), specs
,
9421 static pascal OSStatus
9422 mac_handle_window_event (next_handler
, event
, data
)
9423 EventHandlerCallRef next_handler
;
9428 OSStatus result
, err
;
9431 XSizeHints
*size_hints
;
9433 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9434 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9436 return eventNotHandledErr
;
9438 f
= mac_window_to_frame (wp
);
9439 switch (GetEventKind (event
))
9441 case kEventWindowUpdate
:
9442 result
= CallNextEventHandler (next_handler
, event
);
9443 if (result
!= eventNotHandledErr
)
9446 do_window_update (wp
);
9449 case kEventWindowGetIdealSize
:
9450 result
= CallNextEventHandler (next_handler
, event
);
9451 if (result
!= eventNotHandledErr
)
9455 Point ideal_size
= mac_get_ideal_size (f
);
9457 err
= SetEventParameter (event
, kEventParamDimensions
,
9458 typeQDPoint
, sizeof (Point
), &ideal_size
);
9464 case kEventWindowBoundsChanging
:
9465 result
= CallNextEventHandler (next_handler
, event
);
9466 if (result
!= eventNotHandledErr
)
9469 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9470 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9474 size_hints
= FRAME_SIZE_HINTS (f
);
9475 if ((attributes
& kWindowBoundsChangeUserResize
)
9476 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9477 == (PResizeInc
| PBaseSize
| PMinSize
)))
9482 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9483 typeQDRectangle
, NULL
, sizeof (Rect
),
9488 width
= bounds
.right
- bounds
.left
;
9489 height
= bounds
.bottom
- bounds
.top
;
9491 if (width
< size_hints
->min_width
)
9492 width
= size_hints
->min_width
;
9494 width
= size_hints
->base_width
9495 + (int) ((width
- size_hints
->base_width
)
9496 / (float) size_hints
->width_inc
+ .5)
9497 * size_hints
->width_inc
;
9499 if (height
< size_hints
->min_height
)
9500 height
= size_hints
->min_height
;
9502 height
= size_hints
->base_height
9503 + (int) ((height
- size_hints
->base_height
)
9504 / (float) size_hints
->height_inc
+ .5)
9505 * size_hints
->height_inc
;
9507 bounds
.right
= bounds
.left
+ width
;
9508 bounds
.bottom
= bounds
.top
+ height
;
9509 SetEventParameter (event
, kEventParamCurrentBounds
,
9510 typeQDRectangle
, sizeof (Rect
), &bounds
);
9515 case kEventWindowBoundsChanged
:
9516 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9517 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9521 if (attributes
& kWindowBoundsChangeSizeChanged
)
9525 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9526 typeQDRectangle
, NULL
, sizeof (Rect
),
9532 width
= bounds
.right
- bounds
.left
;
9533 height
= bounds
.bottom
- bounds
.top
;
9534 mac_handle_size_change (f
, width
, height
);
9538 if (attributes
& kWindowBoundsChangeOriginChanged
)
9539 mac_handle_origin_change (f
);
9543 case kEventWindowShown
:
9544 case kEventWindowHidden
:
9545 case kEventWindowExpanded
:
9546 case kEventWindowCollapsed
:
9547 result
= CallNextEventHandler (next_handler
, event
);
9549 mac_handle_visibility_change (f
);
9554 case kEventWindowClose
:
9555 result
= CallNextEventHandler (next_handler
, event
);
9557 struct input_event buf
;
9560 buf
.kind
= DELETE_WINDOW_EVENT
;
9561 XSETFRAME (buf
.frame_or_window
, f
);
9563 kbd_buffer_store_event (&buf
);
9568 case kEventWindowToolbarSwitchMode
:
9569 result
= CallNextEventHandler (next_handler
, event
);
9571 static EventParamName names
[] = {kEventParamDirectObject
,
9572 kEventParamWindowMouseLocation
,
9573 kEventParamKeyModifiers
,
9574 kEventParamMouseButton
,
9575 kEventParamClickCount
,
9576 kEventParamMouseChord
};
9577 static EventParamType types
[] = {typeWindowRef
,
9583 int num_params
= sizeof (names
) / sizeof (names
[0]);
9585 err
= mac_store_event_ref_as_apple_event (0, 0,
9587 Qtoolbar_switch_mode
,
9591 return err
== noErr
? noErr
: result
;
9595 case kEventWindowFocusAcquired
:
9596 result
= CallNextEventHandler (next_handler
, event
);
9597 err
= mac_tsm_resume ();
9598 return err
== noErr
? noErr
: result
;
9600 case kEventWindowFocusRelinquish
:
9601 result
= CallNextEventHandler (next_handler
, event
);
9602 err
= mac_tsm_suspend ();
9603 return err
== noErr
? noErr
: result
;
9607 return eventNotHandledErr
;
9610 static pascal OSStatus
9611 mac_handle_mouse_event (next_handler
, event
, data
)
9612 EventHandlerCallRef next_handler
;
9616 OSStatus result
, err
;
9618 switch (GetEventKind (event
))
9620 case kEventMouseWheelMoved
:
9624 EventMouseWheelAxis axis
;
9628 result
= CallNextEventHandler (next_handler
, event
);
9629 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9632 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9633 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9637 f
= mac_window_to_frame (wp
);
9638 if (f
!= mac_focus_frame (&one_mac_display_info
))
9641 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
9642 typeMouseWheelAxis
, NULL
,
9643 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9644 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
9647 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
9648 typeSInt32
, NULL
, sizeof (SInt32
),
9652 err
= GetEventParameter (event
, kEventParamMouseLocation
,
9653 typeQDPoint
, NULL
, sizeof (Point
),
9657 read_socket_inev
->kind
= WHEEL_EVENT
;
9658 read_socket_inev
->code
= 0;
9659 read_socket_inev
->modifiers
=
9660 (mac_event_to_emacs_modifiers (event
)
9661 | ((delta
< 0) ? down_modifier
: up_modifier
));
9662 SetPortWindowPort (wp
);
9663 GlobalToLocal (&point
);
9664 XSETINT (read_socket_inev
->x
, point
.h
);
9665 XSETINT (read_socket_inev
->y
, point
.v
);
9666 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9676 return eventNotHandledErr
;
9679 #if USE_MAC_FONT_PANEL
9680 static pascal OSStatus
9681 mac_handle_font_event (next_handler
, event
, data
)
9682 EventHandlerCallRef next_handler
;
9686 OSStatus result
, err
;
9689 EventParamName
*names
;
9690 EventParamType
*types
;
9691 static EventParamName names_sel
[] = {kEventParamATSUFontID
,
9692 kEventParamATSUFontSize
,
9693 kEventParamFMFontFamily
,
9694 kEventParamFMFontSize
,
9695 kEventParamFontColor
};
9696 static EventParamType types_sel
[] = {typeATSUFontID
,
9702 result
= CallNextEventHandler (next_handler
, event
);
9703 if (result
!= eventNotHandledErr
)
9706 switch (GetEventKind (event
))
9708 case kEventFontPanelClosed
:
9709 id_key
= Qpanel_closed
;
9715 case kEventFontSelection
:
9716 id_key
= Qselection
;
9717 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
9723 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
9727 return err
== noErr
? noErr
: eventNotHandledErr
;
9732 static pascal OSStatus
9733 mac_handle_text_input_event (next_handler
, event
, data
)
9734 EventHandlerCallRef next_handler
;
9738 OSStatus result
, err
= noErr
;
9739 Lisp_Object id_key
= Qnil
;
9741 EventParamName
*names
;
9742 EventParamType
*types
;
9743 static UInt32 seqno_uaia
= 0;
9744 static EventParamName names_uaia
[] =
9745 {kEventParamTextInputSendComponentInstance
,
9746 kEventParamTextInputSendRefCon
,
9747 kEventParamTextInputSendSLRec
,
9748 kEventParamTextInputSendFixLen
,
9749 kEventParamTextInputSendText
,
9750 kEventParamTextInputSendUpdateRng
,
9751 kEventParamTextInputSendHiliteRng
,
9752 kEventParamTextInputSendClauseRng
,
9753 kEventParamTextInputSendPinRng
,
9754 kEventParamTextInputSendTextServiceEncoding
,
9755 kEventParamTextInputSendTextServiceMacEncoding
,
9756 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
9757 static EventParamType types_uaia
[] =
9758 {typeComponentInstance
,
9760 typeIntlWritingCode
,
9774 static EventParamName names_ufke
[] =
9775 {kEventParamTextInputSendComponentInstance
,
9776 kEventParamTextInputSendRefCon
,
9777 kEventParamTextInputSendSLRec
,
9778 kEventParamTextInputSendText
};
9779 static EventParamType types_ufke
[] =
9780 {typeComponentInstance
,
9782 typeIntlWritingCode
,
9785 result
= CallNextEventHandler (next_handler
, event
);
9787 switch (GetEventKind (event
))
9789 case kEventTextInputUpdateActiveInputArea
:
9790 id_key
= Qupdate_active_input_area
;
9791 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
9794 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
9795 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
9799 case kEventTextInputUnicodeForKeyEvent
:
9802 UInt32 actual_size
, modifiers
, mapped_modifiers
;
9804 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
9805 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
9808 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
9810 sizeof (UInt32
), NULL
, &modifiers
);
9814 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9815 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9816 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9819 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
9821 if (modifiers
& mapped_modifiers
)
9822 /* There're mapped modifier keys. Process it in
9824 return eventNotHandledErr
;
9827 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
9828 typeUnicodeText
, NULL
, 0, &actual_size
,
9830 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
9834 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
9835 typeUnicodeText
, NULL
,
9836 sizeof (UniChar
), NULL
, &code
);
9837 if (err
== noErr
&& code
< 0x80)
9839 /* ASCII character. Process it in XTread_socket. */
9840 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e)
9844 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
9845 typeUInt32
, NULL
, sizeof (UInt32
),
9847 if (!(err
== noErr
&& key_code
<= 0x7f
9848 && keycode_to_xkeysym_table
[key_code
]))
9851 mac_focus_frame (&one_mac_display_info
);
9853 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
9854 read_socket_inev
->code
= code
;
9855 read_socket_inev
->modifiers
=
9856 mac_to_emacs_modifiers (modifiers
);
9857 read_socket_inev
->modifiers
|=
9858 (extra_keyboard_modifiers
9859 & (meta_modifier
| alt_modifier
9860 | hyper_modifier
| super_modifier
));
9861 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9864 return eventNotHandledErr
;
9868 /* Non-ASCII keystrokes without mapped modifiers are processed
9869 at the Lisp level. */
9870 id_key
= Qunicode_for_key_event
;
9871 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
9876 case kEventTextInputOffsetToPos
:
9882 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
9883 return eventNotHandledErr
;
9885 /* Strictly speaking, this is not always correct because
9886 previous events may change some states about display. */
9887 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
9889 /* Active input area is displayed in the echo area. */
9890 w
= XWINDOW (echo_area_window
);
9891 f
= WINDOW_XFRAME (w
);
9895 /* Active input area is displayed around the current point. */
9896 f
= SELECTED_FRAME ();
9897 w
= XWINDOW (f
->selected_window
);
9900 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
9901 + WINDOW_LEFT_FRINGE_WIDTH (w
));
9902 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
9903 + FONT_BASE (FRAME_FONT (f
)));
9904 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
9906 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
9907 typeQDPoint
, sizeof (typeQDPoint
), &p
);
9916 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
9920 return err
== noErr
? noErr
: result
;
9926 mac_store_service_event (event
)
9932 EventParamName
*names
;
9933 EventParamType
*types
;
9934 static EventParamName names_pfm
[] = {kEventParamServiceMessageName
,
9935 kEventParamServiceUserData
};
9936 static EventParamType types_pfm
[] = {typeCFStringRef
,
9939 switch (GetEventKind (event
))
9941 case kEventServicePaste
:
9948 case kEventServicePerform
:
9950 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
9959 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
9965 #endif /* MAC_OSX */
9966 #endif /* USE_CARBON_EVENTS */
9970 install_window_handler (window
)
9973 OSStatus err
= noErr
;
9974 #if USE_CARBON_EVENTS
9975 EventTypeSpec specs_window
[] =
9976 {{kEventClassWindow
, kEventWindowUpdate
},
9977 {kEventClassWindow
, kEventWindowGetIdealSize
},
9978 {kEventClassWindow
, kEventWindowBoundsChanging
},
9979 {kEventClassWindow
, kEventWindowBoundsChanged
},
9980 {kEventClassWindow
, kEventWindowShown
},
9981 {kEventClassWindow
, kEventWindowHidden
},
9982 {kEventClassWindow
, kEventWindowExpanded
},
9983 {kEventClassWindow
, kEventWindowCollapsed
},
9984 {kEventClassWindow
, kEventWindowClose
},
9986 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
9989 {kEventClassWindow
, kEventWindowFocusAcquired
},
9990 {kEventClassWindow
, kEventWindowFocusRelinquish
},
9993 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9994 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9995 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9996 #if USE_MAC_FONT_PANEL
9997 EventTypeSpec specs_font
[] = {{kEventClassFont
, kEventFontPanelClosed
},
9998 {kEventClassFont
, kEventFontSelection
}};
9999 static EventHandlerUPP handle_font_eventUPP
= NULL
;
10002 EventTypeSpec specs_text_input
[] =
10003 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
10004 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
10005 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
10006 static EventHandlerUPP handle_text_input_eventUPP
= NULL
;
10009 if (handle_window_eventUPP
== NULL
)
10010 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
10011 if (handle_mouse_eventUPP
== NULL
)
10012 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
10013 #if USE_MAC_FONT_PANEL
10014 if (handle_font_eventUPP
== NULL
)
10015 handle_font_eventUPP
= NewEventHandlerUPP (mac_handle_font_event
);
10018 if (handle_text_input_eventUPP
== NULL
)
10019 handle_text_input_eventUPP
=
10020 NewEventHandlerUPP (mac_handle_text_input_event
);
10022 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
10023 GetEventTypeCount (specs_window
),
10024 specs_window
, NULL
, NULL
);
10026 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
10027 GetEventTypeCount (specs_mouse
),
10028 specs_mouse
, NULL
, NULL
);
10029 #if USE_MAC_FONT_PANEL
10031 err
= InstallWindowEventHandler (window
, handle_font_eventUPP
,
10032 GetEventTypeCount (specs_font
),
10033 specs_font
, NULL
, NULL
);
10037 err
= InstallWindowEventHandler (window
, handle_text_input_eventUPP
,
10038 GetEventTypeCount (specs_text_input
),
10039 specs_text_input
, window
, NULL
);
10043 err
= install_drag_handler (window
);
10049 remove_window_handler (window
)
10052 remove_drag_handler (window
);
10058 profiler_exit_proc ()
10060 ProfilerDump ("\pEmacs.prof");
10065 /* These few functions implement Emacs as a normal Mac application
10066 (almost): set up the heap and the Toolbox, handle necessary system
10067 events plus a few simple menu events. They also set up Emacs's
10068 access to functions defined in the rest of this file. Emacs uses
10069 function hooks to perform all its terminal I/O. A complete list of
10070 these functions appear in termhooks.h. For what they do, read the
10071 comments there and see also w32term.c and xterm.c. What's
10072 noticeably missing here is the event loop, which is normally
10073 present in most Mac application. After performing the necessary
10074 Mac initializations, main passes off control to emacs_main
10075 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10076 (defined further below) to read input. This is where
10077 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10084 #if __profile__ /* is the profiler on? */
10085 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10090 /* set creator and type for files created by MSL */
10091 _fcreator
= 'EMAx';
10095 do_init_managers ();
10099 #ifndef USE_LSB_TAG
10100 do_check_ram_size ();
10103 init_emacs_passwd_dir ();
10107 init_coercion_handler ();
10109 initialize_applescript ();
10111 init_apple_event_handler ();
10117 /* set up argv array from STR# resource */
10118 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10122 /* free up AppleScript resources on exit */
10123 atexit (terminate_applescript
);
10125 #if __profile__ /* is the profiler on? */
10126 atexit (profiler_exit_proc
);
10129 /* 3rd param "envp" never used in emacs_main */
10130 (void) emacs_main (argc
, argv
, 0);
10133 /* Never reached - real exit in Fkill_emacs */
10138 #if !USE_CARBON_EVENTS
10139 static RgnHandle mouse_region
= NULL
;
10142 mac_wait_next_event (er
, sleep_time
, dequeue
)
10147 static EventRecord er_buf
= {nullEvent
};
10148 UInt32 target_tick
, current_tick
;
10149 EventMask event_mask
;
10151 if (mouse_region
== NULL
)
10152 mouse_region
= NewRgn ();
10154 event_mask
= everyEvent
;
10155 if (!mac_ready_for_apple_events
)
10156 event_mask
-= highLevelEventMask
;
10158 current_tick
= TickCount ();
10159 target_tick
= current_tick
+ sleep_time
;
10161 if (er_buf
.what
== nullEvent
)
10162 while (!WaitNextEvent (event_mask
, &er_buf
,
10163 target_tick
- current_tick
, mouse_region
))
10165 current_tick
= TickCount ();
10166 if (target_tick
<= current_tick
)
10172 er_buf
.what
= nullEvent
;
10175 #endif /* not USE_CARBON_EVENTS */
10177 #if TARGET_API_MAC_CARBON
10179 mac_post_mouse_moved_event ()
10181 EventRef event
= NULL
;
10184 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
10185 kEventAttributeNone
, &event
);
10190 GetMouse (&mouse_pos
);
10191 LocalToGlobal (&mouse_pos
);
10192 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
10193 sizeof (Point
), &mouse_pos
);
10197 UInt32 modifiers
= GetCurrentKeyModifiers ();
10199 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
10200 sizeof (UInt32
), &modifiers
);
10203 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
10204 kEventPriorityStandard
);
10206 ReleaseEvent (event
);
10212 mac_set_unicode_keystroke_event (code
, buf
)
10214 struct input_event
*buf
;
10216 int charset_id
, c1
, c2
;
10220 buf
->kind
= ASCII_KEYSTROKE_EVENT
;
10223 else if (code
< 0x100)
10226 charset_id
= CHARSET_8_BIT_CONTROL
;
10228 charset_id
= charset_latin_iso8859_1
;
10229 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10230 buf
->code
= MAKE_CHAR (charset_id
, code
, 0);
10235 charset_id
= charset_mule_unicode_0100_24ff
,
10237 else if (code
< 0x33FF)
10238 charset_id
= charset_mule_unicode_2500_33ff
,
10240 else if (code
>= 0xE000)
10241 charset_id
= charset_mule_unicode_e000_ffff
,
10243 c1
= (code
/ 96) + 32, c2
= (code
% 96) + 32;
10244 buf
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
10245 buf
->code
= MAKE_CHAR (charset_id
, c1
, c2
);
10250 /* Emacs calls this whenever it wants to read an input event from the
10253 XTread_socket (sd
, expected
, hold_quit
)
10255 struct input_event
*hold_quit
;
10257 struct input_event inev
;
10259 #if USE_CARBON_EVENTS
10261 EventTargetRef toolbox_dispatcher
;
10264 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10266 if (interrupt_input_blocked
)
10268 interrupt_input_pending
= 1;
10272 interrupt_input_pending
= 0;
10275 /* So people can tell when we have read the available input. */
10276 input_signal_count
++;
10280 #if USE_CARBON_EVENTS
10281 toolbox_dispatcher
= GetEventDispatcherTarget ();
10285 mac_prepare_for_quickdraw (NULL
),
10287 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
10288 kEventRemoveFromQueue
, &eventRef
))
10289 #else /* !USE_CARBON_EVENTS */
10290 while (mac_wait_next_event (&er
, 0, true))
10291 #endif /* !USE_CARBON_EVENTS */
10295 unsigned long timestamp
;
10298 inev
.kind
= NO_EVENT
;
10301 #if USE_CARBON_EVENTS
10302 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
10304 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10307 #if USE_CARBON_EVENTS
10308 /* Handle new events */
10309 if (!mac_convert_event_ref (eventRef
, &er
))
10311 /* There used to be a handler for the kEventMouseWheelMoved
10312 event here. But as of Mac OS X 10.4, this kind of event
10313 is not directly posted to the main event queue by
10314 two-finger scrolling on the trackpad. Instead, some
10315 private event is posted and it is converted to a wheel
10316 event by the default handler for the application target.
10317 The converted one can be received by a Carbon event
10318 handler installed on a window target. */
10319 read_socket_inev
= &inev
;
10320 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10321 read_socket_inev
= NULL
;
10324 #endif /* USE_CARBON_EVENTS */
10330 WindowPtr window_ptr
;
10331 ControlPartCode part_code
;
10332 int tool_bar_p
= 0;
10334 #if USE_CARBON_EVENTS
10335 /* This is needed to send mouse events like aqua window
10336 buttons to the correct handler. */
10337 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10338 != eventNotHandledErr
)
10341 last_mouse_glyph_frame
= 0;
10343 if (dpyinfo
->grabbed
&& last_mouse_frame
10344 && FRAME_LIVE_P (last_mouse_frame
))
10346 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
10347 part_code
= inContent
;
10351 part_code
= FindWindow (er
.where
, &window_ptr
);
10352 if (tip_window
&& window_ptr
== tip_window
)
10354 HideWindow (tip_window
);
10355 part_code
= FindWindow (er
.where
, &window_ptr
);
10359 if (er
.what
!= mouseDown
&&
10360 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
10366 f
= mac_focus_frame (dpyinfo
);
10367 saved_menu_event_location
= er
.where
;
10368 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
10369 XSETFRAME (inev
.frame_or_window
, f
);
10374 #if TARGET_API_MAC_CARBON
10375 FrontNonFloatingWindow ()
10380 SelectWindow (window_ptr
);
10383 ControlPartCode control_part_code
;
10385 Point mouse_loc
= er
.where
;
10387 ControlKind control_kind
;
10390 f
= mac_window_to_frame (window_ptr
);
10391 /* convert to local coordinates of new window */
10392 SetPortWindowPort (window_ptr
);
10394 GlobalToLocal (&mouse_loc
);
10395 #if TARGET_API_MAC_CARBON
10396 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10397 &control_part_code
);
10400 GetControlKind (ch
, &control_kind
);
10403 control_part_code
= FindControl (mouse_loc
, window_ptr
,
10407 #if USE_CARBON_EVENTS
10408 inev
.code
= mac_get_mouse_btn (eventRef
);
10409 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10411 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
10412 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10414 XSETINT (inev
.x
, mouse_loc
.h
);
10415 XSETINT (inev
.y
, mouse_loc
.v
);
10417 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
10419 #ifndef USE_TOOLKIT_SCROLL_BARS
10420 /* control_part_code becomes kControlNoPart if
10421 a progress indicator is clicked. */
10422 && control_part_code
!= kControlNoPart
10423 #else /* USE_TOOLKIT_SCROLL_BARS */
10425 && control_kind
.kind
== kControlKindScrollBar
10426 #endif /* MAC_OSX */
10427 #endif /* USE_TOOLKIT_SCROLL_BARS */
10430 struct scroll_bar
*bar
;
10432 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10434 bar
= tracked_scroll_bar
;
10435 #ifndef USE_TOOLKIT_SCROLL_BARS
10436 control_part_code
= kControlIndicatorPart
;
10440 bar
= (struct scroll_bar
*) GetControlReference (ch
);
10441 #ifdef USE_TOOLKIT_SCROLL_BARS
10442 /* Make the "Ctrl-Mouse-2 splits window" work
10443 for toolkit scroll bars. */
10444 if (er
.modifiers
& controlKey
)
10445 x_scroll_bar_handle_click (bar
, control_part_code
,
10447 else if (er
.what
== mouseDown
)
10448 x_scroll_bar_handle_press (bar
, control_part_code
,
10451 x_scroll_bar_handle_release (bar
, &inev
);
10452 #else /* not USE_TOOLKIT_SCROLL_BARS */
10453 x_scroll_bar_handle_click (bar
, control_part_code
,
10455 if (er
.what
== mouseDown
10456 && control_part_code
== kControlIndicatorPart
)
10457 tracked_scroll_bar
= bar
;
10459 tracked_scroll_bar
= NULL
;
10460 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10464 Lisp_Object window
;
10465 int x
= mouse_loc
.h
;
10466 int y
= mouse_loc
.v
;
10468 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10469 if (EQ (window
, f
->tool_bar_window
))
10471 if (er
.what
== mouseDown
)
10472 handle_tool_bar_click (f
, x
, y
, 1, 0);
10474 handle_tool_bar_click (f
, x
, y
, 0,
10480 XSETFRAME (inev
.frame_or_window
, f
);
10481 inev
.kind
= MOUSE_CLICK_EVENT
;
10485 if (er
.what
== mouseDown
)
10487 dpyinfo
->grabbed
|= (1 << inev
.code
);
10488 last_mouse_frame
= f
;
10491 last_tool_bar_item
= -1;
10495 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10496 /* If a button is released though it was not
10497 previously pressed, that would be because
10498 of multi-button emulation. */
10499 dpyinfo
->grabbed
= 0;
10501 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10504 /* Ignore any mouse motion that happened before
10505 this event; any subsequent mouse-movement Emacs
10506 events should reflect only motion after the
10509 f
->mouse_moved
= 0;
10511 #ifdef USE_TOOLKIT_SCROLL_BARS
10512 if (inev
.kind
== MOUSE_CLICK_EVENT
)
10517 inev
.modifiers
|= down_modifier
;
10520 inev
.modifiers
|= up_modifier
;
10527 #if TARGET_API_MAC_CARBON
10529 if (IsWindowPathSelectClick (window_ptr
, &er
))
10531 WindowPathSelect (window_ptr
, NULL
, NULL
);
10534 if (part_code
== inProxyIcon
10535 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
10536 != errUserWantsToDragWindow
))
10538 DragWindow (window_ptr
, er
.where
, NULL
);
10539 #else /* not TARGET_API_MAC_CARBON */
10540 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10541 #endif /* not TARGET_API_MAC_CARBON */
10542 /* Update the frame parameters. */
10543 #if !USE_CARBON_EVENTS
10545 struct frame
*f
= mac_window_to_frame (window_ptr
);
10547 if (f
&& !f
->async_iconified
)
10548 mac_handle_origin_change (f
);
10554 if (TrackGoAway (window_ptr
, er
.where
))
10556 inev
.kind
= DELETE_WINDOW_EVENT
;
10557 XSETFRAME (inev
.frame_or_window
,
10558 mac_window_to_frame (window_ptr
));
10562 /* window resize handling added --ben */
10564 do_grow_window (window_ptr
, &er
);
10567 /* window zoom handling added --ben */
10570 if (TrackBox (window_ptr
, er
.where
, part_code
))
10571 do_zoom_window (window_ptr
, part_code
);
10581 #if USE_CARBON_EVENTS
10582 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10583 != eventNotHandledErr
)
10586 do_window_update ((WindowPtr
) er
.message
);
10591 #if USE_CARBON_EVENTS
10592 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10593 != eventNotHandledErr
)
10596 switch ((er
.message
>> 24) & 0x000000FF)
10598 case suspendResumeMessage
:
10600 if (er
.message
& resumeFlag
)
10603 mac_tsm_suspend ();
10607 case mouseMovedMessage
:
10608 #if !USE_CARBON_EVENTS
10609 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
10610 er
.where
.h
+ 1, er
.where
.v
+ 1);
10612 previous_help_echo_string
= help_echo_string
;
10613 help_echo_string
= Qnil
;
10615 if (dpyinfo
->grabbed
&& last_mouse_frame
10616 && FRAME_LIVE_P (last_mouse_frame
))
10617 f
= last_mouse_frame
;
10619 f
= dpyinfo
->x_focus_frame
;
10621 if (dpyinfo
->mouse_face_hidden
)
10623 dpyinfo
->mouse_face_hidden
= 0;
10624 clear_mouse_face (dpyinfo
);
10629 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
10630 Point mouse_pos
= er
.where
;
10632 SetPortWindowPort (wp
);
10634 GlobalToLocal (&mouse_pos
);
10636 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10637 #ifdef USE_TOOLKIT_SCROLL_BARS
10638 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
10640 #else /* not USE_TOOLKIT_SCROLL_BARS */
10641 x_scroll_bar_note_movement (tracked_scroll_bar
,
10643 - XINT (tracked_scroll_bar
->top
),
10644 er
.when
* (1000 / 60));
10645 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10648 /* Generate SELECT_WINDOW_EVENTs when needed. */
10649 if (!NILP (Vmouse_autoselect_window
))
10651 Lisp_Object window
;
10653 window
= window_from_coordinates (f
,
10658 /* Window will be selected only when it is
10659 not selected now and last mouse movement
10660 event was not in it. Minibuffer window
10661 will be selected iff it is active. */
10662 if (WINDOWP (window
)
10663 && !EQ (window
, last_window
)
10664 && !EQ (window
, selected_window
))
10666 inev
.kind
= SELECT_WINDOW_EVENT
;
10667 inev
.frame_or_window
= window
;
10670 last_window
=window
;
10672 if (!note_mouse_movement (f
, &mouse_pos
))
10673 help_echo_string
= previous_help_echo_string
;
10677 /* If the contents of the global variable
10678 help_echo_string has changed, generate a
10680 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10688 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10690 #if USE_CARBON_EVENTS
10691 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10692 != eventNotHandledErr
)
10695 if (window_ptr
== tip_window
)
10697 HideWindow (tip_window
);
10701 if (!is_emacs_window (window_ptr
))
10704 if ((er
.modifiers
& activeFlag
) != 0)
10706 /* A window has been activated */
10707 Point mouse_loc
= er
.where
;
10709 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10711 SetPortWindowPort (window_ptr
);
10712 GlobalToLocal (&mouse_loc
);
10713 /* Window-activated event counts as mouse movement,
10714 so update things that depend on mouse position. */
10715 note_mouse_movement (mac_window_to_frame (window_ptr
),
10720 /* A window has been deactivated */
10721 #if USE_TOOLKIT_SCROLL_BARS
10722 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10724 struct input_event event
;
10726 EVENT_INIT (event
);
10727 event
.kind
= NO_EVENT
;
10728 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10729 if (event
.kind
!= NO_EVENT
)
10731 event
.timestamp
= timestamp
;
10732 kbd_buffer_store_event_hold (&event
, hold_quit
);
10737 dpyinfo
->grabbed
= 0;
10739 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10741 f
= mac_window_to_frame (window_ptr
);
10742 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10744 /* If we move outside the frame, then we're
10745 certainly no longer on any text in the
10747 clear_mouse_face (dpyinfo
);
10748 dpyinfo
->mouse_face_mouse_frame
= 0;
10751 /* Generate a nil HELP_EVENT to cancel a help-echo.
10752 Do it only if there's something to cancel.
10753 Otherwise, the startup message is cleared when the
10754 mouse leaves the frame. */
10755 if (any_help_event_p
)
10765 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10766 static SInt16 last_key_script
= -1;
10767 SInt16 current_key_script
;
10768 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
10771 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
10772 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
10773 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
10775 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10776 mapped_modifiers
|=
10777 (NILP (Vmac_function_modifier
) ? 0 : kEventKeyModifierFnMask
);
10779 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
10781 sizeof (UInt32
), NULL
, &modifiers
);
10783 mapped_modifiers
&= modifiers
;
10785 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
10786 /* When using Carbon Events, we need to pass raw keyboard
10787 events to the TSM ourselves. If TSM handles it, it
10788 will pass back noErr, otherwise it will pass back
10789 "eventNotHandledErr" and we can process it
10791 if (!(mapped_modifiers
10792 & ~(mac_pass_command_to_system
? cmdKey
: 0)
10793 & ~(mac_pass_control_to_system
? controlKey
: 0)))
10797 read_socket_inev
= &inev
;
10798 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
10799 read_socket_inev
= NULL
;
10800 if (err
!= eventNotHandledErr
)
10804 if (er
.what
== keyUp
)
10809 f
= mac_focus_frame (dpyinfo
);
10811 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
10812 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
10814 clear_mouse_face (dpyinfo
);
10815 dpyinfo
->mouse_face_hidden
= 1;
10818 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10819 if (last_key_script
!= current_key_script
)
10821 struct input_event event
;
10823 EVENT_INIT (event
);
10824 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10826 event
.code
= current_key_script
;
10827 event
.timestamp
= timestamp
;
10828 kbd_buffer_store_event (&event
);
10830 last_key_script
= current_key_script
;
10834 if (inev
.kind
!= NO_EVENT
)
10839 if (mapped_modifiers
& kEventKeyModifierFnMask
10841 && fn_keycode_to_keycode_table
[keycode
])
10842 keycode
= fn_keycode_to_keycode_table
[keycode
];
10844 if (keycode
<= 0x7f && keycode_to_xkeysym_table
[keycode
])
10846 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10847 inev
.code
= 0xff00 | keycode_to_xkeysym_table
[keycode
];
10849 if (modifiers
& kEventKeyModifierFnMask
10851 && fn_keycode_to_keycode_table
[keycode
] == keycode
)
10852 modifiers
&= ~kEventKeyModifierFnMask
;
10855 else if (mapped_modifiers
)
10857 /* translate the keycode back to determine the
10860 static SInt16 last_key_layout_id
= 0;
10861 static Handle uchr_handle
= (Handle
)-1;
10862 SInt16 current_key_layout_id
=
10863 GetScriptVariable (current_key_script
, smScriptKeys
);
10865 if (uchr_handle
== (Handle
)-1
10866 || last_key_layout_id
!= current_key_layout_id
)
10868 uchr_handle
= GetResource ('uchr', current_key_layout_id
);
10869 last_key_layout_id
= current_key_layout_id
;
10875 UInt16 key_action
= er
.what
- keyDown
;
10876 UInt32 modifier_key_state
=
10877 (modifiers
& ~mapped_modifiers
) >> 8;
10878 UInt32 keyboard_type
= LMGetKbdType ();
10879 SInt32 dead_key_state
= 0;
10881 UniCharCount actual_length
;
10883 status
= UCKeyTranslate ((UCKeyboardLayout
*)*uchr_handle
,
10884 keycode
, key_action
,
10885 modifier_key_state
,
10887 kUCKeyTranslateNoDeadKeysMask
,
10889 1, &actual_length
, &code
);
10890 if (status
== noErr
&& actual_length
== 1)
10891 mac_set_unicode_keystroke_event (code
, &inev
);
10893 #endif /* MAC_OSX */
10895 if (inev
.kind
== NO_EVENT
)
10897 /* This code comes from Keyboard Resource,
10898 Appendix C of IM - Text. This is necessary
10899 since shift is ignored in KCHR table
10900 translation when option or command is pressed.
10901 It also does not translate correctly
10902 control-shift chars like C-% so mask off shift
10904 /* Mask off modifier keys that are mapped to some
10905 Emacs modifiers. */
10906 int new_modifiers
= er
.modifiers
& ~mapped_modifiers
;
10907 /* set high byte of keycode to modifier high byte*/
10908 int new_keycode
= keycode
| new_modifiers
;
10909 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10910 unsigned long some_state
= 0;
10911 UInt32 new_char_code
;
10913 new_char_code
= KeyTranslate (kchr_ptr
, new_keycode
,
10915 if (new_char_code
== 0)
10916 /* Seems like a dead key. Append up-stroke. */
10917 new_char_code
= KeyTranslate (kchr_ptr
,
10918 new_keycode
| 0x80,
10922 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10923 inev
.code
= new_char_code
& 0xff;
10928 if (inev
.kind
== NO_EVENT
)
10930 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10931 inev
.code
= er
.message
& charCodeMask
;
10934 inev
.modifiers
= mac_to_emacs_modifiers (modifiers
);
10935 inev
.modifiers
|= (extra_keyboard_modifiers
10936 & (meta_modifier
| alt_modifier
10937 | hyper_modifier
| super_modifier
));
10938 XSETFRAME (inev
.frame_or_window
, f
);
10940 #if TARGET_API_MAC_CARBON
10941 if (inev
.kind
== ASCII_KEYSTROKE_EVENT
10942 && inev
.code
>= 0x80 && inev
.modifiers
)
10945 TextEncoding encoding
= kTextEncodingMacRoman
;
10946 TextToUnicodeInfo ttu_info
;
10948 UpgradeScriptInfoToTextEncoding (current_key_script
,
10949 kTextLanguageDontCare
,
10950 kTextRegionDontCare
,
10952 err
= CreateTextToUnicodeInfoByEncoding (encoding
, &ttu_info
);
10957 ByteCount unicode_len
;
10960 pstr
[1] = inev
.code
;
10961 err
= ConvertFromPStringToUnicode (ttu_info
, pstr
,
10963 &unicode_len
, &code
);
10964 if (err
== noErr
&& unicode_len
== sizeof (UniChar
))
10965 mac_set_unicode_keystroke_event (code
, &inev
);
10966 DisposeTextToUnicodeInfo (&ttu_info
);
10973 case kHighLevelEvent
:
10974 AEProcessAppleEvent (&er
);
10980 #if USE_CARBON_EVENTS
10981 ReleaseEvent (eventRef
);
10984 if (inev
.kind
!= NO_EVENT
)
10986 inev
.timestamp
= timestamp
;
10987 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10992 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10997 XSETFRAME (frame
, f
);
11003 any_help_event_p
= 1;
11004 gen_help_event (help_echo_string
, frame
, help_echo_window
,
11005 help_echo_object
, help_echo_pos
);
11009 help_echo_string
= Qnil
;
11010 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
11017 /* If the focus was just given to an autoraising frame,
11019 /* ??? This ought to be able to handle more than one such frame. */
11020 if (pending_autoraise_frame
)
11022 x_raise_frame (pending_autoraise_frame
);
11023 pending_autoraise_frame
= 0;
11026 #if !USE_CARBON_EVENTS
11027 /* Check which frames are still visible. We do this here because
11028 there doesn't seem to be any direct notification from the Window
11029 Manager that the visibility of a window has changed (at least,
11030 not in all cases). */
11032 Lisp_Object tail
, frame
;
11034 FOR_EACH_FRAME (tail
, frame
)
11036 struct frame
*f
= XFRAME (frame
);
11038 /* The tooltip has been drawn already. Avoid the
11039 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11040 if (EQ (frame
, tip_frame
))
11043 if (FRAME_MAC_P (f
))
11044 mac_handle_visibility_change (f
);
11055 /* Need to override CodeWarrior's input function so no conversion is
11056 done on newlines Otherwise compiled functions in .elc files will be
11057 read incorrectly. Defined in ...:MSL C:MSL
11058 Common:Source:buffer_io.c. */
11061 __convert_to_newlines (unsigned char * p
, size_t * n
)
11063 #pragma unused(p,n)
11067 __convert_from_newlines (unsigned char * p
, size_t * n
)
11069 #pragma unused(p,n)
11075 make_mac_terminal_frame (struct frame
*f
)
11080 XSETFRAME (frame
, f
);
11082 f
->output_method
= output_mac
;
11083 f
->output_data
.mac
= (struct mac_output
*)
11084 xmalloc (sizeof (struct mac_output
));
11085 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
11087 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
11089 FRAME_COLS (f
) = 96;
11090 FRAME_LINES (f
) = 4;
11092 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
11093 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
11095 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
11097 f
->output_data
.mac
->cursor_pixel
= 0;
11098 f
->output_data
.mac
->border_pixel
= 0x00ff00;
11099 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
11100 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
11102 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
11103 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
11104 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
11105 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
11106 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
11107 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
11109 FRAME_FONTSET (f
) = -1;
11110 f
->output_data
.mac
->explicit_parent
= 0;
11113 f
->border_width
= 0;
11115 f
->internal_border_width
= 0;
11120 f
->new_text_cols
= 0;
11121 f
->new_text_lines
= 0;
11123 SetRect (&r
, f
->left_pos
, f
->top_pos
,
11124 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
11125 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
11129 if (!(FRAME_MAC_WINDOW (f
) =
11130 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
11131 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
11133 /* so that update events can find this mac_output struct */
11134 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
11140 /* Need to be initialized for unshow_buffer in window.c. */
11141 selected_window
= f
->selected_window
;
11143 Fmodify_frame_parameters (frame
,
11144 Fcons (Fcons (Qfont
,
11145 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
11146 Fmodify_frame_parameters (frame
,
11147 Fcons (Fcons (Qforeground_color
,
11148 build_string ("black")), Qnil
));
11149 Fmodify_frame_parameters (frame
,
11150 Fcons (Fcons (Qbackground_color
,
11151 build_string ("white")), Qnil
));
11156 /***********************************************************************
11158 ***********************************************************************/
11160 int mac_initialized
= 0;
11163 mac_initialize_display_info ()
11165 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
11167 bzero (dpyinfo
, sizeof (*dpyinfo
));
11170 dpyinfo
->mac_id_name
11171 = (char *) xmalloc (SCHARS (Vinvocation_name
)
11172 + SCHARS (Vsystem_name
)
11174 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
11175 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11177 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
11178 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
11181 dpyinfo
->reference_count
= 0;
11182 dpyinfo
->resx
= 72.0;
11183 dpyinfo
->resy
= 72.0;
11185 /* HasDepth returns true if it is possible to have a 32 bit display,
11186 but this may not be what is actually used. Mac OSX can do better. */
11187 dpyinfo
->color_p
= CGDisplaySamplesPerPixel (kCGDirectMainDisplay
) > 1;
11188 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (kCGDirectMainDisplay
);
11189 dpyinfo
->height
= CGDisplayPixelsHigh (kCGDirectMainDisplay
);
11190 dpyinfo
->width
= CGDisplayPixelsWide (kCGDirectMainDisplay
);
11193 GDHandle main_device_handle
= LMGetMainDevice();
11195 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
11196 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
11197 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
11198 gdDevType
, dpyinfo
->color_p
))
11200 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
11201 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
11204 dpyinfo
->grabbed
= 0;
11205 dpyinfo
->root_window
= NULL
;
11206 dpyinfo
->image_cache
= make_image_cache ();
11208 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11209 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11210 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11211 dpyinfo
->mouse_face_window
= Qnil
;
11212 dpyinfo
->mouse_face_overlay
= Qnil
;
11213 dpyinfo
->mouse_face_hidden
= 0;
11218 mac_make_rdb (xrm_option
)
11221 XrmDatabase database
;
11223 database
= xrm_get_preference_database (NULL
);
11225 xrm_merge_string_database (database
, xrm_option
);
11230 struct mac_display_info
*
11231 mac_term_init (display_name
, xrm_option
, resource_name
)
11232 Lisp_Object display_name
;
11234 char *resource_name
;
11236 struct mac_display_info
*dpyinfo
;
11240 if (!mac_initialized
)
11243 mac_initialized
= 1;
11246 if (x_display_list
)
11247 error ("Sorry, this version can only handle one display");
11249 mac_initialize_display_info ();
11251 dpyinfo
= &one_mac_display_info
;
11253 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
11255 /* Put this display on the chain. */
11256 dpyinfo
->next
= x_display_list
;
11257 x_display_list
= dpyinfo
;
11259 /* Put it on x_display_name_list. */
11260 x_display_name_list
= Fcons (Fcons (display_name
,
11261 Fcons (Qnil
, dpyinfo
->xrdb
)),
11262 x_display_name_list
);
11263 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11269 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11272 x_delete_display (dpyinfo
)
11273 struct mac_display_info
*dpyinfo
;
11277 /* Discard this display from x_display_name_list and x_display_list.
11278 We can't use Fdelq because that can quit. */
11279 if (! NILP (x_display_name_list
)
11280 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11281 x_display_name_list
= XCDR (x_display_name_list
);
11286 tail
= x_display_name_list
;
11287 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11289 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11291 XSETCDR (tail
, XCDR (XCDR (tail
)));
11294 tail
= XCDR (tail
);
11298 if (x_display_list
== dpyinfo
)
11299 x_display_list
= dpyinfo
->next
;
11302 struct x_display_info
*tail
;
11304 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11305 if (tail
->next
== dpyinfo
)
11306 tail
->next
= tail
->next
->next
;
11309 /* Free the font names in the font table. */
11310 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11311 if (dpyinfo
->font_table
[i
].name
)
11313 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11314 xfree (dpyinfo
->font_table
[i
].full_name
);
11315 xfree (dpyinfo
->font_table
[i
].name
);
11318 if (dpyinfo
->font_table
)
11320 if (dpyinfo
->font_table
->font_encoder
)
11321 xfree (dpyinfo
->font_table
->font_encoder
);
11322 xfree (dpyinfo
->font_table
);
11324 if (dpyinfo
->mac_id_name
)
11325 xfree (dpyinfo
->mac_id_name
);
11327 if (x_display_list
== 0)
11329 mac_clear_font_name_table ();
11330 bzero (dpyinfo
, sizeof (*dpyinfo
));
11339 extern int inhibit_window_system
;
11340 extern int noninteractive
;
11341 CFBundleRef appsBundle
;
11343 /* No need to test if already -nw*/
11344 if (inhibit_window_system
|| noninteractive
)
11347 appsBundle
= CFBundleGetMainBundle();
11348 if (appsBundle
!= NULL
)
11350 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
11351 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
11352 /* We found the bundle identifier, now we know we are valid. */
11359 /* MAC_TODO: Have this start the bundled executable */
11361 /* For now, prevent the fatal error by bringing it up in the terminal */
11362 inhibit_window_system
= 1;
11366 MakeMeTheFrontProcess ()
11368 ProcessSerialNumber psn
;
11371 err
= GetCurrentProcess (&psn
);
11373 (void) SetFrontProcess (&psn
);
11376 /***** Code to handle C-g testing *****/
11378 /* Contains the Mac modifier formed from quit_char */
11379 int mac_quit_char_modifiers
= 0;
11380 int mac_quit_char_keycode
;
11381 extern int quit_char
;
11384 mac_determine_quit_char_modifiers()
11386 /* Todo: Determine modifiers from quit_char. */
11387 UInt32 qc_modifiers
= ctrl_modifier
;
11389 /* Map modifiers */
11390 mac_quit_char_modifiers
= 0;
11391 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
11392 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
11393 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
11397 init_quit_char_handler ()
11399 /* TODO: Let this support keys other the 'g' */
11400 mac_quit_char_keycode
= 5;
11401 /* Look at <architecture/adb_kb_map.h> for details */
11402 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
11404 mac_determine_quit_char_modifiers();
11406 #endif /* MAC_OSX */
11414 MenuItemIndex menu_index
;
11416 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
11417 &menu
, &menu_index
);
11419 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11420 #if USE_CARBON_EVENTS
11421 EnableMenuCommand (NULL
, kHICommandPreferences
);
11422 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
11423 &menu
, &menu_index
);
11426 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
11427 InsertMenuItemTextWithCFString (menu
, NULL
,
11428 0, kMenuItemAttrSeparator
, 0);
11429 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
11430 0, 0, kHICommandAbout
);
11432 #endif /* USE_CARBON_EVENTS */
11433 #else /* !MAC_OSX */
11434 #if USE_CARBON_EVENTS
11435 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
11445 static InterfaceTypeList types
= {kUnicodeDocument
};
11447 static InterfaceTypeList types
= {kTextService
};
11450 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
11451 &tsm_document_id
, 0);
11455 /* Set up use of X before we make the first connection. */
11457 extern frame_parm_handler mac_frame_parm_handlers
[];
11459 static struct redisplay_interface x_redisplay_interface
=
11461 mac_frame_parm_handlers
,
11465 x_clear_end_of_line
,
11467 x_after_update_window_line
,
11468 x_update_window_begin
,
11469 x_update_window_end
,
11472 0, /* flush_display_optional */
11473 x_clear_window_mouse_face
,
11474 x_get_glyph_overhangs
,
11475 x_fix_overlapping_area
,
11476 x_draw_fringe_bitmap
,
11478 mac_define_fringe_bitmap
,
11479 mac_destroy_fringe_bitmap
,
11481 0, /* define_fringe_bitmap */
11482 0, /* destroy_fringe_bitmap */
11484 mac_per_char_metric
,
11486 mac_compute_glyph_string_overhangs
,
11487 x_draw_glyph_string
,
11488 mac_define_frame_cursor
,
11489 mac_clear_frame_area
,
11490 mac_draw_window_cursor
,
11491 mac_draw_vertical_window_border
,
11492 mac_shift_glyphs_for_insert
11498 rif
= &x_redisplay_interface
;
11500 clear_frame_hook
= x_clear_frame
;
11501 ins_del_lines_hook
= x_ins_del_lines
;
11502 delete_glyphs_hook
= x_delete_glyphs
;
11503 ring_bell_hook
= XTring_bell
;
11504 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11505 set_terminal_modes_hook
= XTset_terminal_modes
;
11506 update_begin_hook
= x_update_begin
;
11507 update_end_hook
= x_update_end
;
11508 set_terminal_window_hook
= XTset_terminal_window
;
11509 read_socket_hook
= XTread_socket
;
11510 frame_up_to_date_hook
= XTframe_up_to_date
;
11511 mouse_position_hook
= XTmouse_position
;
11512 frame_rehighlight_hook
= XTframe_rehighlight
;
11513 frame_raise_lower_hook
= XTframe_raise_lower
;
11515 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11516 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11517 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11518 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11520 scroll_region_ok
= 1; /* we'll scroll partial frames */
11521 char_ins_del_ok
= 1;
11522 line_ins_del_ok
= 1; /* we'll just blt 'em */
11523 fast_clear_end_of_line
= 1; /* X does this well */
11524 memory_below_frame
= 0; /* we don't remember what scrolls
11528 last_tool_bar_item
= -1;
11529 any_help_event_p
= 0;
11531 /* Try to use interrupt input; if we can't, then start polling. */
11532 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11536 #if TARGET_API_MAC_CARBON
11538 #if USE_CARBON_EVENTS
11540 init_service_handler ();
11542 init_quit_char_handler ();
11543 #endif /* MAC_OSX */
11545 init_command_handler ();
11552 #endif /* USE_CARBON_EVENTS */
11555 init_coercion_handler ();
11557 init_apple_event_handler ();
11559 if (!inhibit_window_system
)
11560 MakeMeTheFrontProcess ();
11565 mac_init_fringe ();
11576 staticpro (&x_error_message_string
);
11577 x_error_message_string
= Qnil
;
11580 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
11581 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
11582 Qalt
= intern ("alt"); staticpro (&Qalt
);
11583 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
11584 Qsuper
= intern ("super"); staticpro (&Qsuper
);
11585 Qmodifier_value
= intern ("modifier-value");
11586 staticpro (&Qmodifier_value
);
11588 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
11589 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11590 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11591 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11592 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11594 #if USE_CARBON_EVENTS
11595 Qhi_command
= intern ("hi-command"); staticpro (&Qhi_command
);
11597 Qtoolbar_switch_mode
= intern ("toolbar-switch-mode");
11598 staticpro (&Qtoolbar_switch_mode
);
11599 #if USE_MAC_FONT_PANEL
11600 Qpanel_closed
= intern ("panel-closed"); staticpro (&Qpanel_closed
);
11601 Qselection
= intern ("selection"); staticpro (&Qselection
);
11604 Qservice
= intern ("service"); staticpro (&Qservice
);
11605 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
11606 Qperform
= intern ("perform"); staticpro (&Qperform
);
11609 Qtext_input
= intern ("text-input"); staticpro (&Qtext_input
);
11610 Qupdate_active_input_area
= intern ("update-active-input-area");
11611 staticpro (&Qupdate_active_input_area
);
11612 Qunicode_for_key_event
= intern ("unicode-for-key-event");
11613 staticpro (&Qunicode_for_key_event
);
11618 Fprovide (intern ("mac-carbon"), Qnil
);
11621 staticpro (&Qreverse
);
11622 Qreverse
= intern ("reverse");
11624 staticpro (&x_display_name_list
);
11625 x_display_name_list
= Qnil
;
11627 staticpro (&last_mouse_scroll_bar
);
11628 last_mouse_scroll_bar
= Qnil
;
11630 staticpro (&fm_font_family_alist
);
11631 fm_font_family_alist
= Qnil
;
11634 staticpro (&atsu_font_id_hash
);
11635 atsu_font_id_hash
= Qnil
;
11637 staticpro (&fm_style_face_attributes_alist
);
11638 fm_style_face_attributes_alist
= Qnil
;
11642 staticpro (&saved_ts_script_language_on_focus
);
11643 saved_ts_script_language_on_focus
= Qnil
;
11646 /* We don't yet support this, but defining this here avoids whining
11647 from cus-start.el and other places, like "M-x set-variable". */
11648 DEFVAR_BOOL ("x-use-underline-position-properties",
11649 &x_use_underline_position_properties
,
11650 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11651 nil means ignore them. If you encounter fonts with bogus
11652 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11653 to 4.1, set this to nil.
11655 NOTE: Not supported on Mac yet. */);
11656 x_use_underline_position_properties
= 0;
11658 DEFVAR_BOOL ("x-underline-at-descent-line",
11659 &x_underline_at_descent_line
,
11660 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
11661 nil means to draw the underline according to the value of the variable
11662 `x-use-underline-position-properties', which is usually at the baseline
11663 level. The default value is nil. */);
11664 x_underline_at_descent_line
= 0;
11666 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
11667 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
11668 #ifdef USE_TOOLKIT_SCROLL_BARS
11669 Vx_toolkit_scroll_bars
= Qt
;
11671 Vx_toolkit_scroll_bars
= Qnil
;
11674 staticpro (&last_mouse_motion_frame
);
11675 last_mouse_motion_frame
= Qnil
;
11677 /* Variables to configure modifier key assignment. */
11679 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
11680 doc
: /* *Modifier key assumed when the Mac control key is pressed.
11681 The value can be `control', `meta', `alt', `hyper', or `super' for the
11682 respective modifier. The default is `control'. */);
11683 Vmac_control_modifier
= Qcontrol
;
11685 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
11686 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
11687 The value can be `control', `meta', `alt', `hyper', or `super' for the
11688 respective modifier. If the value is nil then the key will act as the
11689 normal Mac control modifier, and the option key can be used to compose
11690 characters depending on the chosen Mac keyboard setting. */);
11691 Vmac_option_modifier
= Qnil
;
11693 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
11694 doc
: /* *Modifier key assumed when the Mac command key is pressed.
11695 The value can be `control', `meta', `alt', `hyper', or `super' for the
11696 respective modifier. The default is `meta'. */);
11697 Vmac_command_modifier
= Qmeta
;
11699 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
11700 doc
: /* *Modifier key assumed when the Mac function key is pressed.
11701 The value can be `control', `meta', `alt', `hyper', or `super' for the
11702 respective modifier. Note that remapping the function key may lead to
11703 unexpected results for some keys on non-US/GB keyboards. */);
11704 Vmac_function_modifier
= Qnil
;
11706 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11707 &Vmac_emulate_three_button_mouse
,
11708 doc
: /* *Specify a way of three button mouse emulation.
11709 The value can be nil, t, or the symbol `reverse'.
11710 nil means that no emulation should be done and the modifiers should be
11711 placed on the mouse-1 event.
11712 t means that when the option-key is held down while pressing the mouse
11713 button, the click will register as mouse-2 and while the command-key
11714 is held down, the click will register as mouse-3.
11715 The symbol `reverse' means that the option-key will register for
11716 mouse-3 and the command-key will register for mouse-2. */);
11717 Vmac_emulate_three_button_mouse
= Qnil
;
11719 #if USE_CARBON_EVENTS
11720 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
11721 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11722 Otherwise, the right click will be treated as mouse-2 and the wheel
11723 button will be mouse-3. */);
11724 mac_wheel_button_is_mouse_2
= 1;
11726 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
11727 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
11728 mac_pass_command_to_system
= 1;
11730 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
11731 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
11732 mac_pass_control_to_system
= 1;
11736 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
11737 doc
: /* *If non-nil, allow anti-aliasing.
11738 The text will be rendered using Core Graphics text rendering which
11739 may anti-alias the text. */);
11741 mac_use_core_graphics
= 1;
11743 mac_use_core_graphics
= 0;
11746 /* Register an entry for `mac-roman' so that it can be used when
11747 creating the terminal frame on Mac OS 9 before loading
11748 term/mac-win.elc. */
11749 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
11750 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
11751 Each entry should be of the form:
11753 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
11755 where CHARSET-NAME is a string used in font names to identify the
11756 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
11757 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
11758 Vmac_charset_info_alist
=
11759 Fcons (list3 (build_string ("mac-roman"),
11760 make_number (smRoman
), Qnil
), Qnil
);
11763 DEFVAR_LISP ("mac-atsu-font-table", &Vmac_atsu_font_table
,
11764 doc
: /* Hash table of ATSU font IDs vs plist of attributes and values. */);
11765 Vmac_atsu_font_table
=
11766 make_hash_table (Qeql
, make_number (DEFAULT_HASH_SIZE
),
11767 make_float (DEFAULT_REHASH_SIZE
),
11768 make_float (DEFAULT_REHASH_THRESHOLD
),
11772 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay
,
11773 doc
: /* Overlay used to display Mac TSM active input area. */);
11774 Vmac_ts_active_input_overlay
= Qnil
;
11776 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus
,
11777 doc
: /* *How to change Mac TSM script/language when a frame gets focus.
11778 If the value is t, the input script and language are restored to those
11779 used in the last focus frame. If the value is a pair of integers, the
11780 input script and language codes, which are defined in the Script
11781 Manager, are set to its car and cdr parts, respectively. Otherwise,
11782 Emacs doesn't set them and thus follows the system default behavior. */);
11783 Vmac_ts_script_language_on_focus
= Qnil
;
11787 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
11788 (do not change this comment) */