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"
85 #include "intervals.h"
91 /* Non-nil means Emacs uses toolkit scroll bars. */
93 Lisp_Object Vx_toolkit_scroll_bars
;
95 /* If non-zero, the text will be rendered using Core Graphics text
96 rendering which may anti-alias the text. */
97 int mac_use_core_graphics
;
100 /* Non-zero means that a HELP_EVENT has been generated since Emacs
103 static int any_help_event_p
;
105 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
106 static Lisp_Object last_window
;
108 /* Non-zero means make use of UNDERLINE_POSITION font properties.
109 (Not yet supported.) */
110 int x_use_underline_position_properties
;
112 /* This is a chain of structures for all the X displays currently in
115 struct x_display_info
*x_display_list
;
117 /* This is a list of cons cells, each of the form (NAME
118 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
119 x_display_list and in the same order. NAME is the name of the
120 frame. FONT-LIST-CACHE records previous values returned by
121 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
122 equivalent, which is implemented with a Lisp object, for the
125 Lisp_Object x_display_name_list
;
127 /* This is display since Mac does not support multiple ones. */
128 struct mac_display_info one_mac_display_info
;
130 /* Frame being updated by update_frame. This is declared in term.c.
131 This is set by update_begin and looked at by all the XT functions.
132 It is zero while not inside an update. In that case, the XT
133 functions assume that `selected_frame' is the frame to apply to. */
135 extern struct frame
*updating_frame
;
137 /* This is a frame waiting to be auto-raised, within XTread_socket. */
139 struct frame
*pending_autoraise_frame
;
143 Formerly, we used PointerMotionHintMask (in standard_event_mask)
144 so that we would have to call XQueryPointer after each MotionNotify
145 event to ask for another such event. However, this made mouse tracking
146 slow, and there was a bug that made it eventually stop.
148 Simply asking for MotionNotify all the time seems to work better.
150 In order to avoid asking for motion events and then throwing most
151 of them away or busy-polling the server for mouse positions, we ask
152 the server for pointer motion hints. This means that we get only
153 one event per group of mouse movements. "Groups" are delimited by
154 other kinds of events (focus changes and button clicks, for
155 example), or by XQueryPointer calls; when one of these happens, we
156 get another MotionNotify event the next time the mouse moves. This
157 is at least as efficient as getting motion events when mouse
158 tracking is on, and I suspect only negligibly worse when tracking
161 /* Where the mouse was last time we reported a mouse event. */
163 static Rect last_mouse_glyph
;
164 static FRAME_PTR last_mouse_glyph_frame
;
166 /* The scroll bar in which the last X motion event occurred.
168 If the last X motion event occurred in a scroll bar, we set this so
169 XTmouse_position can know whether to report a scroll bar motion or
172 If the last X motion event didn't occur in a scroll bar, we set
173 this to Qnil, to tell XTmouse_position to return an ordinary motion
176 static Lisp_Object last_mouse_scroll_bar
;
178 /* This is a hack. We would really prefer that XTmouse_position would
179 return the time associated with the position it returns, but there
180 doesn't seem to be any way to wrest the time-stamp from the server
181 along with the position query. So, we just keep track of the time
182 of the last movement we received, and return that in hopes that
183 it's somewhat accurate. */
185 static Time last_mouse_movement_time
;
187 struct scroll_bar
*tracked_scroll_bar
= NULL
;
189 /* Incremented by XTread_socket whenever it really tries to read
193 static int volatile input_signal_count
;
195 static int input_signal_count
;
198 extern Lisp_Object Vsystem_name
;
200 /* A mask of extra modifier bits to put into every keyboard char. */
202 extern EMACS_INT extra_keyboard_modifiers
;
204 /* The keysyms to use for the various modifiers. */
206 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
208 extern int inhibit_window_system
;
210 #if __MRC__ && !TARGET_API_MAC_CARBON
211 QDGlobals qd
; /* QuickDraw global information structure. */
214 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
216 struct mac_display_info
*mac_display_info_for_display (Display
*);
217 static void x_update_window_end
P_ ((struct window
*, int, int));
218 static int x_io_error_quitter
P_ ((Display
*));
219 int x_catch_errors
P_ ((Display
*));
220 void x_uncatch_errors
P_ ((Display
*, int));
221 void x_lower_frame
P_ ((struct frame
*));
222 void x_scroll_bar_clear
P_ ((struct frame
*));
223 int x_had_errors_p
P_ ((Display
*));
224 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
225 void x_raise_frame
P_ ((struct frame
*));
226 void x_set_window_size
P_ ((struct frame
*, int, int, int));
227 void x_wm_set_window_state
P_ ((struct frame
*, int));
228 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
229 void mac_initialize
P_ ((void));
230 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
231 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
232 static void x_update_end
P_ ((struct frame
*));
233 static void XTframe_up_to_date
P_ ((struct frame
*));
234 static void XTset_terminal_modes
P_ ((void));
235 static void XTreset_terminal_modes
P_ ((void));
236 static void x_clear_frame
P_ ((void));
237 static void frame_highlight
P_ ((struct frame
*));
238 static void frame_unhighlight
P_ ((struct frame
*));
239 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
240 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
241 struct frame
*, struct input_event
*));
242 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
243 EventRecord
*, struct input_event
*));
244 static void XTframe_rehighlight
P_ ((struct frame
*));
245 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
246 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
247 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
248 enum text_cursor_kinds
));
250 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
251 static void x_flush
P_ ((struct frame
*f
));
252 static void x_update_begin
P_ ((struct frame
*));
253 static void x_update_window_begin
P_ ((struct window
*));
254 static void x_after_update_window_line
P_ ((struct glyph_row
*));
255 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
256 enum scroll_bar_part
*,
257 Lisp_Object
*, Lisp_Object
*,
260 static int is_emacs_window
P_ ((WindowPtr
));
261 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
262 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
264 /* Defined in macmenu.h. */
265 extern void menubar_selection_callback (FRAME_PTR
, int);
267 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
268 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
269 #define GC_FONT(gc) ((gc)->xgcv.font)
270 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
271 #define CG_SET_FILL_COLOR(context, color) \
272 CGContextSetRGBFillColor (context, \
273 RED_FROM_ULONG (color) / 255.0f, \
274 GREEN_FROM_ULONG (color) / 255.0f, \
275 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
276 #define CG_SET_STROKE_COLOR(context, color) \
277 CGContextSetRGBStrokeColor (context, \
278 RED_FROM_ULONG (color) / 255.0f, \
279 GREEN_FROM_ULONG (color) / 255.0f, \
280 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
282 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
285 mac_begin_cg_clip (f
, gc
)
289 CGContextRef context
= FRAME_CG_CONTEXT (f
);
293 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
294 FRAME_CG_CONTEXT (f
) = context
;
297 CGContextSaveGState (context
);
298 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
299 CGContextScaleCTM (context
, 1, -1);
300 if (gc
&& gc
->n_clip_rects
)
301 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
310 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
314 mac_prepare_for_quickdraw (f
)
319 Lisp_Object rest
, frame
;
320 FOR_EACH_FRAME (rest
, frame
)
321 if (FRAME_MAC_P (XFRAME (frame
)))
322 mac_prepare_for_quickdraw (XFRAME (frame
));
326 CGContextRef context
= FRAME_CG_CONTEXT (f
);
330 CGContextSynchronize (context
);
331 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
332 &FRAME_CG_CONTEXT (f
));
338 static RgnHandle saved_port_clip_region
= NULL
;
344 static RgnHandle new_region
= NULL
;
346 if (saved_port_clip_region
== NULL
)
347 saved_port_clip_region
= NewRgn ();
348 if (new_region
== NULL
)
349 new_region
= NewRgn ();
351 if (gc
->n_clip_rects
)
353 GetClip (saved_port_clip_region
);
354 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
355 SetClip (new_region
);
363 if (gc
->n_clip_rects
)
364 SetClip (saved_port_clip_region
);
368 /* X display function emulation */
371 XFreePixmap (display
, pixmap
)
372 Display
*display
; /* not used */
375 DisposeGWorld (pixmap
);
379 /* Mac version of XDrawLine. */
382 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
388 CGContextRef context
;
390 context
= mac_begin_cg_clip (f
, gc
);
391 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
392 CGContextBeginPath (context
);
393 CGContextMoveToPoint (context
, x1
+ 0.5f
, y1
+ 0.5f
);
394 CGContextAddLineToPoint (context
, x2
+ 0.5f
, y2
+ 0.5f
);
395 CGContextClosePath (context
);
396 CGContextStrokePath (context
);
399 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
401 RGBForeColor (GC_FORE_COLOR (gc
));
411 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
420 GetGWorld (&old_port
, &old_gdh
);
423 RGBForeColor (GC_FORE_COLOR (gc
));
425 LockPixels (GetGWorldPixMap (p
));
428 UnlockPixels (GetGWorldPixMap (p
));
430 SetGWorld (old_port
, old_gdh
);
435 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
439 unsigned int width
, height
;
442 CGContextRef context
;
444 context
= mac_begin_cg_clip (f
, gc
);
445 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
446 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
451 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
453 RGBBackColor (GC_BACK_COLOR (gc
));
454 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
460 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
465 /* Mac version of XClearArea. */
468 mac_clear_area (f
, x
, y
, width
, height
)
471 unsigned int width
, height
;
473 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
476 /* Mac version of XClearWindow. */
483 CGContextRef context
;
484 GC gc
= FRAME_NORMAL_GC (f
);
486 context
= mac_begin_cg_clip (f
, NULL
);
487 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
488 CGContextFillRect (context
, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f
),
489 FRAME_PIXEL_HEIGHT (f
)));
492 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
494 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
496 #if TARGET_API_MAC_CARBON
500 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
503 #else /* not TARGET_API_MAC_CARBON */
504 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
505 #endif /* not TARGET_API_MAC_CARBON */
510 /* Mac replacement for XCopyArea. */
513 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
516 int x
, y
, width
, height
;
517 unsigned short *bits
;
523 bitmap
.rowBytes
= sizeof(unsigned short);
524 bitmap
.baseAddr
= (char *)bits
;
525 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
528 mac_prepare_for_quickdraw (f
);
530 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
532 RGBForeColor (GC_FORE_COLOR (gc
));
533 RGBBackColor (GC_BACK_COLOR (gc
));
534 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
537 #if TARGET_API_MAC_CARBON
543 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
544 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
545 UnlockPortBits (port
);
547 #else /* not TARGET_API_MAC_CARBON */
548 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
549 overlay_p
? srcOr
: srcCopy
, 0);
550 #endif /* not TARGET_API_MAC_CARBON */
553 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
557 /* Mac replacement for XCreateBitmapFromBitmapData. */
560 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
565 static unsigned char swap_nibble
[16]
566 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
567 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
568 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
569 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
573 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
574 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
575 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
576 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
577 for (i
= 0; i
< h
; i
++)
579 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
580 for (j
= 0; j
< w1
; j
++)
582 /* Bitswap XBM bytes to match how Mac does things. */
583 unsigned char c
= *bits
++;
584 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
585 | (swap_nibble
[(c
>>4) & 0xf]));;
589 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
594 mac_free_bitmap (bitmap
)
597 xfree (bitmap
->baseAddr
);
602 XCreatePixmap (display
, w
, width
, height
, depth
)
603 Display
*display
; /* not used */
605 unsigned int width
, height
;
612 SetPortWindowPort (w
);
614 SetRect (&r
, 0, 0, width
, height
);
615 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
623 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
624 Display
*display
; /* not used */
627 unsigned int width
, height
;
628 unsigned long fg
, bg
;
635 static GC gc
= NULL
; /* not reentrant */
638 gc
= XCreateGC (display
, w
, 0, NULL
);
640 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
644 GetGWorld (&old_port
, &old_gdh
);
645 SetGWorld (pixmap
, NULL
);
646 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
647 XSetForeground (display
, gc
, fg
);
648 XSetBackground (display
, gc
, bg
);
649 RGBForeColor (GC_FORE_COLOR (gc
));
650 RGBBackColor (GC_BACK_COLOR (gc
));
651 LockPixels (GetGWorldPixMap (pixmap
));
652 #if TARGET_API_MAC_CARBON
653 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
654 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
655 #else /* not TARGET_API_MAC_CARBON */
656 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
657 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
658 #endif /* not TARGET_API_MAC_CARBON */
659 UnlockPixels (GetGWorldPixMap (pixmap
));
660 SetGWorld (old_port
, old_gdh
);
661 mac_free_bitmap (&bitmap
);
667 /* Mac replacement for XFillRectangle. */
670 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
674 unsigned int width
, height
;
677 CGContextRef context
;
679 context
= mac_begin_cg_clip (f
, gc
);
680 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
681 CGContextFillRect (context
, CGRectMake (x
, y
, width
, height
));
686 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
688 RGBForeColor (GC_FORE_COLOR (gc
));
689 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
692 PaintRect (&r
); /* using foreground color of gc */
698 /* Mac replacement for XDrawRectangle: dest is a window. */
701 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
705 unsigned int width
, height
;
708 CGContextRef context
;
710 context
= mac_begin_cg_clip (f
, gc
);
711 CG_SET_STROKE_COLOR (context
, gc
->xgcv
.foreground
);
712 CGContextStrokeRect (context
,
713 CGRectMake (x
+ 0.5f
, y
+ 0.5f
, width
, height
));
718 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
720 RGBForeColor (GC_FORE_COLOR (gc
));
721 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
724 FrameRect (&r
); /* using foreground color of gc */
732 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
733 ConstUniCharArrayPtr text
;
734 UniCharCount text_length
;
736 ATSUTextLayout
*text_layout
;
739 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
741 if (saved_text_layout
== NULL
)
743 UniCharCount lengths
[] = {kATSUToTextEnd
};
744 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
745 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
746 static ATSLineLayoutOptions line_layout
=
747 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
748 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
749 | kATSLineUseQDRendering
751 kATSLineIsDisplayOnly
| kATSLineFractDisable
754 ATSUAttributeValuePtr values
[] = {&line_layout
};
756 err
= ATSUCreateTextLayoutWithTextPtr (text
,
757 kATSUFromTextBeginning
,
763 err
= ATSUSetLayoutControls (saved_text_layout
,
764 sizeof (tags
) / sizeof (tags
[0]),
765 tags
, sizes
, values
);
766 /* XXX: Should we do this? */
768 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
772 err
= ATSUSetRunStyle (saved_text_layout
, style
,
773 kATSUFromTextBeginning
, kATSUToTextEnd
);
775 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
776 kATSUFromTextBeginning
,
782 *text_layout
= saved_text_layout
;
789 mac_invert_rectangle (f
, x
, y
, width
, height
)
792 unsigned int width
, height
;
797 mac_prepare_for_quickdraw (f
);
799 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
801 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
808 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, bytes_per_char
)
813 int nchars
, bg_width
, bytes_per_char
;
815 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
818 if (GC_FONT (gc
)->mac_style
)
821 ATSUTextLayout text_layout
;
823 xassert (bytes_per_char
== 2);
825 #ifndef WORDS_BIG_ENDIAN
828 UniChar
*text
= (UniChar
*)buf
;
830 for (i
= 0; i
< nchars
; i
++)
831 text
[i
] = EndianU16_BtoN (text
[i
]);
834 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
836 GC_FONT (gc
)->mac_style
,
841 if (!mac_use_core_graphics
)
845 mac_prepare_for_quickdraw (f
);
848 RGBForeColor (GC_FORE_COLOR (gc
));
853 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
854 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
855 RGBBackColor (GC_BACK_COLOR (gc
));
857 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
860 ATSUDrawText (text_layout
,
861 kATSUFromTextBeginning
, kATSUToTextEnd
,
862 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
869 CGContextRef context
;
870 float port_height
= FRAME_PIXEL_HEIGHT (f
);
871 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
872 ByteCount sizes
[] = {sizeof (CGContextRef
)};
873 ATSUAttributeValuePtr values
[] = {&context
};
876 context
= mac_begin_cg_clip (f
, gc
);
879 QDBeginCGContext (port
, &context
);
880 if (gc
->n_clip_rects
|| bg_width
)
882 CGContextTranslateCTM (context
, 0, port_height
);
883 CGContextScaleCTM (context
, 1, -1);
884 if (gc
->n_clip_rects
)
885 CGContextClipToRects (context
, gc
->clip_rects
,
890 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
893 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
894 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
896 CGContextScaleCTM (context
, 1, -1);
897 CGContextTranslateCTM (context
, 0, -port_height
);
901 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
902 err
= ATSUSetLayoutControls (text_layout
,
903 sizeof (tags
) / sizeof (tags
[0]),
904 tags
, sizes
, values
);
906 ATSUDrawText (text_layout
,
907 kATSUFromTextBeginning
, kATSUToTextEnd
,
908 Long2Fix (x
), Long2Fix (port_height
- y
));
913 CGContextSynchronize (context
);
914 QDEndCGContext (port
, &context
);
917 /* This doesn't work on Mac OS X 10.1. */
918 ATSUClearLayoutControls (text_layout
,
919 sizeof (tags
) / sizeof (tags
[0]), tags
);
921 ATSUSetLayoutControls (text_layout
,
922 sizeof (tags
) / sizeof (tags
[0]),
923 tags
, sizes
, values
);
929 #endif /* USE_ATSUI */
931 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
934 if (mac_use_core_graphics
)
935 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
938 mac_prepare_for_quickdraw (f
);
941 RGBForeColor (GC_FORE_COLOR (gc
));
945 RGBBackColor (GC_BACK_COLOR (gc
));
951 /* We prefer not to use srcCopy text transfer mode on Mac OS X
953 - Screen is double-buffered. (In srcCopy mode, a text is
954 drawn into an offscreen graphics world first. So
955 performance gain cannot be expected.)
956 - It lowers rendering quality.
957 - Some fonts leave garbage on cursor movement. */
962 RGBBackColor (GC_BACK_COLOR (gc
));
963 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
964 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
969 TextFont (GC_FONT (gc
)->mac_fontnum
);
970 TextSize (GC_FONT (gc
)->mac_fontsize
);
971 TextFace (GC_FONT (gc
)->mac_fontface
);
973 DrawText (buf
, 0, nchars
* bytes_per_char
);
975 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
978 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
979 if (mac_use_core_graphics
)
980 SwapQDTextFlags(savedFlags
);
986 /* Mac replacement for XDrawString. */
989 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
996 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, 0, 1);
1000 /* Mac replacement for XDrawString16. */
1003 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
1010 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, 0, 2);
1014 /* Mac replacement for XDrawImageString. */
1017 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1022 int nchars
, bg_width
;
1024 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, 1);
1028 /* Mac replacement for XDrawString16. */
1031 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1036 int nchars
, bg_width
;
1038 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
, 2);
1042 /* Mac replacement for XQueryTextExtents, but takes a character. If
1043 STYLE is NULL, measurement is done by QuickDraw Text routines for
1044 the font of the current graphics port. If CG_GLYPH is not NULL,
1045 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1048 mac_query_char_extents (style
, c
,
1049 font_ascent_return
, font_descent_return
,
1050 overall_return
, cg_glyph
)
1057 int *font_ascent_return
, *font_descent_return
;
1058 XCharStruct
*overall_return
;
1059 #if USE_CG_TEXT_DRAWING
1072 ATSUTextLayout text_layout
;
1075 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
1078 ATSTrapezoid glyph_bounds
;
1080 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1081 kATSUFromTextBeginning
, kATSUToTextEnd
,
1082 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1083 kATSUseFractionalOrigins
,
1085 kATSUseDeviceOrigins
,
1087 1, &glyph_bounds
, NULL
);
1090 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1091 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1093 width
= Fix2Long (glyph_bounds
.upperRight
.x
1094 - glyph_bounds
.upperLeft
.x
);
1095 if (font_ascent_return
)
1096 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
1097 if (font_descent_return
)
1098 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
1101 if (err
== noErr
&& overall_return
)
1103 err
= ATSUMeasureTextImage (text_layout
,
1104 kATSUFromTextBeginning
, kATSUToTextEnd
,
1105 0, 0, &char_bounds
);
1107 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1108 #if USE_CG_TEXT_DRAWING
1109 if (err
== noErr
&& cg_glyph
)
1112 ATSUGlyphInfoArray glyph_info_array
;
1113 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
1115 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
1116 kATSUToTextEnd
, NULL
, NULL
, NULL
);
1118 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
1119 kATSUToTextEnd
, &count
,
1123 xassert (glyph_info_array
.glyphs
[0].glyphID
);
1124 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1135 if (font_ascent_return
|| font_descent_return
)
1139 GetFontInfo (&font_info
);
1140 if (font_ascent_return
)
1141 *font_ascent_return
= font_info
.ascent
;
1142 if (font_descent_return
)
1143 *font_descent_return
= font_info
.descent
;
1149 width
= CharWidth (ch
);
1150 QDTextBounds (1, &ch
, &char_bounds
);
1151 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1159 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1162 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1163 XFontStruct
*font_struct
;
1166 XCharStruct
*overall_return
;
1169 short width
= 0, lbearing
= 0, rbearing
= 0;
1172 for (i
= 0; i
< nchars
; i
++)
1174 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1176 width
+= FONT_WIDTH (font_struct
);
1179 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1180 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1181 width
+= pcm
->width
;
1186 overall_return
->lbearing
= lbearing
;
1187 overall_return
->rbearing
= rbearing
;
1188 overall_return
->width
= width
;
1190 /* What's the meaning of the return value of XTextExtents16? */
1194 #if USE_CG_TEXT_DRAWING
1195 static int cg_text_anti_aliasing_threshold
= 8;
1198 init_cg_text_anti_aliasing_threshold ()
1204 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1205 kCFPreferencesCurrentApplication
,
1208 cg_text_anti_aliasing_threshold
= threshold
;
1212 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1217 int nchars
, bg_width
;
1220 float port_height
, gx
, gy
;
1222 CGContextRef context
;
1226 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1229 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1230 port_height
= FRAME_PIXEL_HEIGHT (f
);
1232 gy
= port_height
- y
;
1233 glyphs
= (CGGlyph
*)buf
;
1234 advances
= alloca (sizeof (CGSize
) * nchars
);
1235 if (advances
== NULL
)
1237 for (i
= 0; i
< nchars
; i
++)
1239 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1241 advances
[i
].width
= pcm
->width
;
1242 advances
[i
].height
= 0;
1243 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1248 context
= mac_begin_cg_clip (f
, gc
);
1250 QDBeginCGContext (port
, &context
);
1251 if (gc
->n_clip_rects
|| bg_width
)
1253 CGContextTranslateCTM (context
, 0, port_height
);
1254 CGContextScaleCTM (context
, 1, -1);
1255 if (gc
->n_clip_rects
)
1256 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1260 CG_SET_FILL_COLOR (context
, gc
->xgcv
.background
);
1263 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1264 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1266 CGContextScaleCTM (context
, 1, -1);
1267 CGContextTranslateCTM (context
, 0, -port_height
);
1271 CG_SET_FILL_COLOR (context
, gc
->xgcv
.foreground
);
1272 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1273 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1274 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1275 CGContextSetShouldAntialias (context
, false);
1276 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1277 CGContextSetTextPosition (context
, gx
, gy
);
1278 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1280 for (i
= 0; i
< nchars
; i
++)
1282 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1283 gx
+= advances
[i
].width
;
1287 mac_end_cg_clip (f
);
1289 CGContextSynchronize (context
);
1290 QDEndCGContext (port
, &context
);
1298 /* Mac replacement for XCopyArea: dest must be window. */
1301 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1306 unsigned int width
, height
;
1312 mac_prepare_for_quickdraw (f
);
1314 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1316 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1317 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1319 ForeColor (blackColor
);
1320 BackColor (whiteColor
);
1322 mac_begin_clip (gc
);
1323 LockPixels (GetGWorldPixMap (src
));
1324 #if TARGET_API_MAC_CARBON
1329 LockPortBits (port
);
1330 CopyBits (GetPortBitMapForCopyBits (src
),
1331 GetPortBitMapForCopyBits (port
),
1332 &src_r
, &dest_r
, srcCopy
, 0);
1333 UnlockPortBits (port
);
1335 #else /* not TARGET_API_MAC_CARBON */
1336 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1337 &src_r
, &dest_r
, srcCopy
, 0);
1338 #endif /* not TARGET_API_MAC_CARBON */
1339 UnlockPixels (GetGWorldPixMap (src
));
1342 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1347 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1348 width
, height
, dest_x
, dest_y
)
1353 unsigned int width
, height
;
1359 mac_prepare_for_quickdraw (f
);
1361 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1363 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1364 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1366 ForeColor (blackColor
);
1367 BackColor (whiteColor
);
1369 mac_begin_clip (gc
);
1370 LockPixels (GetGWorldPixMap (src
));
1371 LockPixels (GetGWorldPixMap (mask
));
1372 #if TARGET_API_MAC_CARBON
1377 LockPortBits (port
);
1378 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1379 GetPortBitMapForCopyBits (port
),
1380 &src_r
, &src_r
, &dest_r
);
1381 UnlockPortBits (port
);
1383 #else /* not TARGET_API_MAC_CARBON */
1384 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1385 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1386 #endif /* not TARGET_API_MAC_CARBON */
1387 UnlockPixels (GetGWorldPixMap (mask
));
1388 UnlockPixels (GetGWorldPixMap (src
));
1391 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1395 /* Mac replacement for XCopyArea: used only for scrolling. */
1398 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1402 unsigned int width
, height
;
1405 #if TARGET_API_MAC_CARBON
1407 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1409 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1411 mac_prepare_for_quickdraw (f
);
1413 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1414 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1415 kScrollWindowNoOptions
, dummy
);
1417 #else /* not TARGET_API_MAC_CARBON */
1419 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1423 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1424 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1426 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1427 color mapping in CopyBits. Otherwise, it will be slow. */
1428 ForeColor (blackColor
);
1429 BackColor (whiteColor
);
1430 mac_begin_clip (gc
);
1431 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1434 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1435 #endif /* not TARGET_API_MAC_CARBON */
1439 /* Mac replacement for XChangeGC. */
1442 XChangeGC (display
, gc
, mask
, xgcv
)
1448 if (mask
& GCForeground
)
1449 XSetForeground (display
, gc
, xgcv
->foreground
);
1450 if (mask
& GCBackground
)
1451 XSetBackground (display
, gc
, xgcv
->background
);
1453 XSetFont (display
, gc
, xgcv
->font
);
1457 /* Mac replacement for XCreateGC. */
1460 XCreateGC (display
, window
, mask
, xgcv
)
1466 GC gc
= xmalloc (sizeof (*gc
));
1470 bzero (gc
, sizeof (*gc
));
1471 XChangeGC (display
, gc
, mask
, xgcv
);
1478 /* Used in xfaces.c. */
1481 XFreeGC (display
, gc
)
1485 if (gc
->clip_region
)
1486 DisposeRgn (gc
->clip_region
);
1491 /* Mac replacement for XGetGCValues. */
1494 XGetGCValues (display
, gc
, mask
, xgcv
)
1500 if (mask
& GCForeground
)
1501 xgcv
->foreground
= gc
->xgcv
.foreground
;
1502 if (mask
& GCBackground
)
1503 xgcv
->background
= gc
->xgcv
.background
;
1505 xgcv
->font
= gc
->xgcv
.font
;
1509 /* Mac replacement for XSetForeground. */
1512 XSetForeground (display
, gc
, color
)
1515 unsigned long color
;
1517 if (gc
->xgcv
.foreground
!= color
)
1519 gc
->xgcv
.foreground
= color
;
1520 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1521 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1522 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1527 /* Mac replacement for XSetBackground. */
1530 XSetBackground (display
, gc
, color
)
1533 unsigned long color
;
1535 if (gc
->xgcv
.background
!= color
)
1537 gc
->xgcv
.background
= color
;
1538 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1539 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1540 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1545 /* Mac replacement for XSetFont. */
1548 XSetFont (display
, gc
, font
)
1553 gc
->xgcv
.font
= font
;
1557 /* Mac replacement for XSetClipRectangles. */
1560 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1568 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1570 gc
->n_clip_rects
= n
;
1573 if (gc
->clip_region
== NULL
)
1574 gc
->clip_region
= NewRgn ();
1575 RectRgn (gc
->clip_region
, rectangles
);
1578 RgnHandle region
= NewRgn ();
1580 for (i
= 1; i
< n
; i
++)
1582 RectRgn (region
, rectangles
+ i
);
1583 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1585 DisposeRgn (region
);
1588 #if defined (MAC_OSX) && USE_ATSUI
1589 for (i
= 0; i
< n
; i
++)
1591 Rect
*rect
= rectangles
+ i
;
1593 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1594 rect
->right
- rect
->left
,
1595 rect
->bottom
- rect
->top
);
1601 /* Mac replacement for XSetClipMask. */
1604 mac_reset_clip_rectangles (display
, gc
)
1608 gc
->n_clip_rects
= 0;
1612 /* Mac replacement for XSetWindowBackground. */
1615 XSetWindowBackground (display
, w
, color
)
1618 unsigned long color
;
1620 #if !TARGET_API_MAC_CARBON
1621 AuxWinHandle aw_handle
;
1622 CTabHandle ctab_handle
;
1623 ColorSpecPtr ct_table
;
1628 bg_color
.red
= RED16_FROM_ULONG (color
);
1629 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1630 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1632 #if TARGET_API_MAC_CARBON
1633 SetWindowContentColor (w
, &bg_color
);
1635 if (GetAuxWin (w
, &aw_handle
))
1637 ctab_handle
= (*aw_handle
)->awCTable
;
1638 HandToHand ((Handle
*) &ctab_handle
);
1639 ct_table
= (*ctab_handle
)->ctTable
;
1640 ct_size
= (*ctab_handle
)->ctSize
;
1641 while (ct_size
> -1)
1643 if (ct_table
->value
== 0)
1645 ct_table
->rgb
= bg_color
;
1646 CTabChanged (ctab_handle
);
1647 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1655 /* x_sync is a no-op on Mac. */
1663 /* Flush display of frame F, or of all frames if F is null. */
1669 #if TARGET_API_MAC_CARBON
1672 mac_prepare_for_quickdraw (f
);
1675 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1677 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1683 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1684 Calls to XFlush should be unnecessary because the X output buffer
1685 is flushed automatically as needed by calls to XPending,
1686 XNextEvent, or XWindowEvent according to the XFlush man page.
1687 XTread_socket calls XPending. Removing XFlush improves
1690 #define XFlush(DISPLAY) (void) 0
1693 /* Return the struct mac_display_info corresponding to DPY. There's
1696 struct mac_display_info
*
1697 mac_display_info_for_display (dpy
)
1700 return &one_mac_display_info
;
1705 /***********************************************************************
1706 Starting and ending an update
1707 ***********************************************************************/
1709 /* Start an update of frame F. This function is installed as a hook
1710 for update_begin, i.e. it is called when update_begin is called.
1711 This function is called prior to calls to x_update_window_begin for
1712 each window being updated. */
1718 #if TARGET_API_MAC_CARBON
1719 /* During update of a frame, availability of input events is
1720 periodically checked with ReceiveNextEvent if
1721 redisplay-dont-pause is nil. That normally flushes window buffer
1722 changes for every check, and thus screen update looks waving even
1723 if no input is available. So we disable screen updates during
1724 update of a frame. */
1726 DisableScreenUpdates ();
1732 /* Start update of window W. Set the global variable updated_window
1733 to the window being updated and set output_cursor to the cursor
1737 x_update_window_begin (w
)
1740 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1741 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1744 set_output_cursor (&w
->cursor
);
1748 if (f
== display_info
->mouse_face_mouse_frame
)
1750 /* Don't do highlighting for mouse motion during the update. */
1751 display_info
->mouse_face_defer
= 1;
1753 /* If F needs to be redrawn, simply forget about any prior mouse
1755 if (FRAME_GARBAGED_P (f
))
1756 display_info
->mouse_face_window
= Qnil
;
1758 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1759 their mouse_face_p flag set, which means that they are always
1760 unequal to rows in a desired matrix which never have that
1761 flag set. So, rows containing mouse-face glyphs are never
1762 scrolled, and we don't have to switch the mouse highlight off
1763 here to prevent it from being scrolled. */
1765 /* Can we tell that this update does not affect the window
1766 where the mouse highlight is? If so, no need to turn off.
1767 Likewise, don't do anything if the frame is garbaged;
1768 in that case, the frame's current matrix that we would use
1769 is all wrong, and we will redisplay that line anyway. */
1770 if (!NILP (display_info
->mouse_face_window
)
1771 && w
== XWINDOW (display_info
->mouse_face_window
))
1775 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1776 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1779 if (i
< w
->desired_matrix
->nrows
)
1780 clear_mouse_face (display_info
);
1789 /* Draw a vertical window border from (x,y0) to (x,y1) */
1792 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1796 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1799 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1801 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1804 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1807 /* End update of window W (which is equal to updated_window).
1809 Draw vertical borders between horizontally adjacent windows, and
1810 display W's cursor if CURSOR_ON_P is non-zero.
1812 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1813 glyphs in mouse-face were overwritten. In that case we have to
1814 make sure that the mouse-highlight is properly redrawn.
1816 W may be a menu bar pseudo-window in case we don't have X toolkit
1817 support. Such windows don't have a cursor, so don't display it
1821 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1823 int cursor_on_p
, mouse_face_overwritten_p
;
1825 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1827 if (!w
->pseudo_window_p
)
1832 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1834 output_cursor
.x
, output_cursor
.y
);
1836 if (draw_window_fringes (w
, 1))
1837 x_draw_vertical_border (w
);
1842 /* If a row with mouse-face was overwritten, arrange for
1843 XTframe_up_to_date to redisplay the mouse highlight. */
1844 if (mouse_face_overwritten_p
)
1846 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1847 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1848 dpyinfo
->mouse_face_window
= Qnil
;
1851 updated_window
= NULL
;
1855 /* End update of frame F. This function is installed as a hook in
1862 /* Mouse highlight may be displayed again. */
1863 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1866 #if TARGET_API_MAC_CARBON
1867 EnableScreenUpdates ();
1869 XFlush (FRAME_MAC_DISPLAY (f
));
1874 /* This function is called from various places in xdisp.c whenever a
1875 complete update has been performed. The global variable
1876 updated_window is not available here. */
1879 XTframe_up_to_date (f
)
1882 if (FRAME_MAC_P (f
))
1884 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1886 if (dpyinfo
->mouse_face_deferred_gc
1887 || f
== dpyinfo
->mouse_face_mouse_frame
)
1890 if (dpyinfo
->mouse_face_mouse_frame
)
1891 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1892 dpyinfo
->mouse_face_mouse_x
,
1893 dpyinfo
->mouse_face_mouse_y
);
1894 dpyinfo
->mouse_face_deferred_gc
= 0;
1901 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1902 arrow bitmaps, or clear the fringes if no bitmaps are required
1903 before DESIRED_ROW is made current. The window being updated is
1904 found in updated_window. This function is called from
1905 update_window_line only if it is known that there are differences
1906 between bitmaps to be drawn between current row and DESIRED_ROW. */
1909 x_after_update_window_line (desired_row
)
1910 struct glyph_row
*desired_row
;
1912 struct window
*w
= updated_window
;
1918 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1919 desired_row
->redraw_fringe_bitmaps_p
= 1;
1921 /* When a window has disappeared, make sure that no rest of
1922 full-width rows stays visible in the internal border. Could
1923 check here if updated_window is the leftmost/rightmost window,
1924 but I guess it's not worth doing since vertically split windows
1925 are almost never used, internal border is rarely set, and the
1926 overhead is very small. */
1927 if (windows_or_buffers_changed
1928 && desired_row
->full_width_p
1929 && (f
= XFRAME (w
->frame
),
1930 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1932 && (height
= desired_row
->visible_height
,
1935 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1937 /* Internal border is drawn below the tool bar. */
1938 if (WINDOWP (f
->tool_bar_window
)
1939 && w
== XWINDOW (f
->tool_bar_window
))
1943 mac_clear_area (f
, 0, y
, width
, height
);
1944 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1950 /* Draw the bitmap WHICH in one of the left or right fringes of
1951 window W. ROW is the glyph row for which to display the bitmap; it
1952 determines the vertical position at which the bitmap has to be
1956 x_draw_fringe_bitmap (w
, row
, p
)
1958 struct glyph_row
*row
;
1959 struct draw_fringe_bitmap_params
*p
;
1961 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1962 Display
*display
= FRAME_MAC_DISPLAY (f
);
1963 struct face
*face
= p
->face
;
1966 /* Must clip because of partially visible lines. */
1967 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1970 /* Adjust position of "bottom aligned" bitmap on partially
1971 visible last row. */
1973 int oldVH
= row
->visible_height
;
1974 row
->visible_height
= p
->h
;
1975 row
->y
-= rowY
- p
->y
;
1976 x_clip_to_row (w
, row
, -1, face
->gc
);
1978 row
->visible_height
= oldVH
;
1981 x_clip_to_row (w
, row
, -1, face
->gc
);
1983 if (p
->bx
>= 0 && !p
->overlay_p
)
1985 #if 0 /* MAC_TODO: stipple */
1986 /* In case the same realized face is used for fringes and
1987 for something displayed in the text (e.g. face `region' on
1988 mono-displays, the fill style may have been changed to
1989 FillSolid in x_draw_glyph_string_background. */
1991 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1993 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1996 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1998 #if 0 /* MAC_TODO: stipple */
2000 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
2006 unsigned short *bits
= p
->bits
+ p
->dh
;
2009 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
2010 XSetForeground (display
, face
->gc
,
2012 ? (p
->overlay_p
? face
->background
2013 : f
->output_data
.mac
->cursor_pixel
)
2014 : face
->foreground
));
2015 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
2016 p
->wd
, p
->h
, bits
, p
->overlay_p
);
2017 XSetForeground (display
, face
->gc
, gcv
.foreground
);
2020 mac_reset_clip_rectangles (display
, face
->gc
);
2025 /* This is called when starting Emacs and when restarting after
2026 suspend. When starting Emacs, no window is mapped. And nothing
2027 must be done to Emacs's own window if it is suspended (though that
2031 XTset_terminal_modes ()
2035 /* This is called when exiting or suspending Emacs. Exiting will make
2036 the windows go away, and suspending requires no action. */
2039 XTreset_terminal_modes ()
2045 /***********************************************************************
2047 ***********************************************************************/
2049 /* Function prototypes of this page. */
2051 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
2052 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
2055 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2056 is not contained in the font. */
2058 static INLINE XCharStruct
*
2059 x_per_char_metric (font
, char2b
)
2063 /* The result metric information. */
2064 XCharStruct
*pcm
= NULL
;
2066 xassert (font
&& char2b
);
2069 if (font
->mac_style
)
2071 XCharStructRow
**row
= font
->bounds
.rows
+ char2b
->byte1
;
2075 *row
= xmalloc (sizeof (XCharStructRow
));
2077 bzero (*row
, sizeof (XCharStructRow
));
2081 pcm
= (*row
)->per_char
+ char2b
->byte2
;
2082 if (!XCHARSTRUCTROW_CHAR_VALID_P (*row
, char2b
->byte2
))
2085 mac_query_char_extents (font
->mac_style
,
2086 (char2b
->byte1
<< 8) + char2b
->byte2
,
2087 NULL
, NULL
, pcm
, NULL
);
2089 XCHARSTRUCTROW_SET_CHAR_VALID (*row
, char2b
->byte2
);
2096 if (font
->bounds
.per_char
!= NULL
)
2098 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
2100 /* min_char_or_byte2 specifies the linear character index
2101 corresponding to the first element of the per_char array,
2102 max_char_or_byte2 is the index of the last character. A
2103 character with non-zero CHAR2B->byte1 is not in the font.
2104 A character with byte2 less than min_char_or_byte2 or
2105 greater max_char_or_byte2 is not in the font. */
2106 if (char2b
->byte1
== 0
2107 && char2b
->byte2
>= font
->min_char_or_byte2
2108 && char2b
->byte2
<= font
->max_char_or_byte2
)
2109 pcm
= font
->bounds
.per_char
2110 + (char2b
->byte2
- font
->min_char_or_byte2
);
2114 /* If either min_byte1 or max_byte1 are nonzero, both
2115 min_char_or_byte2 and max_char_or_byte2 are less than
2116 256, and the 2-byte character index values corresponding
2117 to the per_char array element N (counting from 0) are:
2119 byte1 = N/D + min_byte1
2120 byte2 = N\D + min_char_or_byte2
2124 D = max_char_or_byte2 - min_char_or_byte2 + 1
2125 / = integer division
2126 \ = integer modulus */
2127 if (char2b
->byte1
>= font
->min_byte1
2128 && char2b
->byte1
<= font
->max_byte1
2129 && char2b
->byte2
>= font
->min_char_or_byte2
2130 && char2b
->byte2
<= font
->max_char_or_byte2
)
2132 pcm
= (font
->bounds
.per_char
2133 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
2134 * (char2b
->byte1
- font
->min_byte1
))
2135 + (char2b
->byte2
- font
->min_char_or_byte2
));
2141 /* If the per_char pointer is null, all glyphs between the first
2142 and last character indexes inclusive have the same
2143 information, as given by both min_bounds and max_bounds. */
2144 if (char2b
->byte2
>= font
->min_char_or_byte2
2145 && char2b
->byte2
<= font
->max_char_or_byte2
)
2146 pcm
= &font
->max_bounds
;
2152 return ((pcm
== NULL
2153 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
2160 static XCharStruct
*
2161 mac_per_char_metric (font
, char2b
, font_type
)
2166 return x_per_char_metric (font
, char2b
);
2170 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2171 the two-byte form of C. Encoding is returned in *CHAR2B. */
2174 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2177 struct font_info
*font_info
;
2180 int charset
= CHAR_CHARSET (c
);
2181 XFontStruct
*font
= font_info
->font
;
2183 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2184 This may be either a program in a special encoder language or a
2186 if (font_info
->font_encoder
)
2188 /* It's a program. */
2189 struct ccl_program
*ccl
= font_info
->font_encoder
;
2191 check_ccl_update (ccl
);
2192 if (CHARSET_DIMENSION (charset
) == 1)
2194 ccl
->reg
[0] = charset
;
2195 ccl
->reg
[1] = char2b
->byte2
;
2200 ccl
->reg
[0] = charset
;
2201 ccl
->reg
[1] = char2b
->byte1
;
2202 ccl
->reg
[2] = char2b
->byte2
;
2205 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2207 /* We assume that MSBs are appropriately set/reset by CCL
2209 if (font
->max_byte1
== 0) /* 1-byte font */
2210 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2212 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2214 else if (font_info
->encoding
[charset
])
2216 /* Fixed encoding scheme. See fontset.h for the meaning of the
2217 encoding numbers. */
2218 int enc
= font_info
->encoding
[charset
];
2220 if ((enc
== 1 || enc
== 2)
2221 && CHARSET_DIMENSION (charset
) == 2)
2222 char2b
->byte1
|= 0x80;
2224 if (enc
== 1 || enc
== 3)
2225 char2b
->byte2
|= 0x80;
2231 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2232 char2b
->byte1
= sjis1
;
2233 char2b
->byte2
= sjis2
;
2238 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2240 return FONT_TYPE_UNKNOWN
;
2245 /***********************************************************************
2247 ***********************************************************************/
2251 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2252 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2253 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2255 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2256 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2257 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2258 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2259 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2260 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2261 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2262 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2263 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2264 unsigned long *, double, int));*/
2265 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2266 double, int, unsigned long));
2267 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2268 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2269 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2270 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2271 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2272 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2274 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2275 int, int, int, int, int, int,
2277 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2278 int, int, int, Rect
*));
2281 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2285 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2290 struct glyph_string
*s
;
2292 if (s
->font
== FRAME_FONT (s
->f
)
2293 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2294 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2296 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2299 /* Cursor on non-default face: must merge. */
2303 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2304 xgcv
.foreground
= s
->face
->background
;
2306 /* If the glyph would be invisible, try a different foreground. */
2307 if (xgcv
.foreground
== xgcv
.background
)
2308 xgcv
.foreground
= s
->face
->foreground
;
2309 if (xgcv
.foreground
== xgcv
.background
)
2310 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2311 if (xgcv
.foreground
== xgcv
.background
)
2312 xgcv
.foreground
= s
->face
->foreground
;
2314 /* Make sure the cursor is distinct from text in this face. */
2315 if (xgcv
.background
== s
->face
->background
2316 && xgcv
.foreground
== s
->face
->foreground
)
2318 xgcv
.background
= s
->face
->foreground
;
2319 xgcv
.foreground
= s
->face
->background
;
2322 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2323 xgcv
.font
= s
->font
;
2324 mask
= GCForeground
| GCBackground
| GCFont
;
2326 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2327 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2330 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2331 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2333 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2338 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2341 x_set_mouse_face_gc (s
)
2342 struct glyph_string
*s
;
2347 /* What face has to be used last for the mouse face? */
2348 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2349 face
= FACE_FROM_ID (s
->f
, face_id
);
2351 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2353 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2354 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2356 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2357 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2358 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2360 /* If font in this face is same as S->font, use it. */
2361 if (s
->font
== s
->face
->font
)
2362 s
->gc
= s
->face
->gc
;
2365 /* Otherwise construct scratch_cursor_gc with values from FACE
2370 xgcv
.background
= s
->face
->background
;
2371 xgcv
.foreground
= s
->face
->foreground
;
2372 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2373 xgcv
.font
= s
->font
;
2374 mask
= GCForeground
| GCBackground
| GCFont
;
2376 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2377 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2380 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2381 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2383 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2386 xassert (s
->gc
!= 0);
2390 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2391 Faces to use in the mode line have already been computed when the
2392 matrix was built, so there isn't much to do, here. */
2395 x_set_mode_line_face_gc (s
)
2396 struct glyph_string
*s
;
2398 s
->gc
= s
->face
->gc
;
2402 /* Set S->gc of glyph string S for drawing that glyph string. Set
2403 S->stippled_p to a non-zero value if the face of S has a stipple
2407 x_set_glyph_string_gc (s
)
2408 struct glyph_string
*s
;
2410 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2412 if (s
->hl
== DRAW_NORMAL_TEXT
)
2414 s
->gc
= s
->face
->gc
;
2415 s
->stippled_p
= s
->face
->stipple
!= 0;
2417 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2419 x_set_mode_line_face_gc (s
);
2420 s
->stippled_p
= s
->face
->stipple
!= 0;
2422 else if (s
->hl
== DRAW_CURSOR
)
2424 x_set_cursor_gc (s
);
2427 else if (s
->hl
== DRAW_MOUSE_FACE
)
2429 x_set_mouse_face_gc (s
);
2430 s
->stippled_p
= s
->face
->stipple
!= 0;
2432 else if (s
->hl
== DRAW_IMAGE_RAISED
2433 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2435 s
->gc
= s
->face
->gc
;
2436 s
->stippled_p
= s
->face
->stipple
!= 0;
2440 s
->gc
= s
->face
->gc
;
2441 s
->stippled_p
= s
->face
->stipple
!= 0;
2444 /* GC must have been set. */
2445 xassert (s
->gc
!= 0);
2449 /* Set clipping for output of glyph string S. S may be part of a mode
2450 line or menu if we don't have X toolkit support. */
2453 x_set_glyph_string_clipping (s
)
2454 struct glyph_string
*s
;
2456 Rect rects
[MAX_CLIP_RECTS
];
2459 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2460 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2465 Compute left and right overhang of glyph string S. If S is a glyph
2466 string for a composition, assume overhangs don't exist. */
2469 mac_compute_glyph_string_overhangs (s
)
2470 struct glyph_string
*s
;
2473 && s
->first_glyph
->type
== CHAR_GLYPH
)
2476 || s
->font
->mac_style
2482 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2483 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2484 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2489 MacFontStruct
*font
= s
->font
;
2491 TextFont (font
->mac_fontnum
);
2492 TextSize (font
->mac_fontsize
);
2493 TextFace (font
->mac_fontface
);
2495 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2497 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2498 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2503 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2506 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2507 struct glyph_string
*s
;
2510 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2514 /* Draw the background of glyph_string S. If S->background_filled_p
2515 is non-zero don't draw it. FORCE_P non-zero means draw the
2516 background even if it wouldn't be drawn normally. This is used
2517 when a string preceding S draws into the background of S, or S
2518 contains the first component of a composition. */
2521 x_draw_glyph_string_background (s
, force_p
)
2522 struct glyph_string
*s
;
2525 /* Nothing to do if background has already been drawn or if it
2526 shouldn't be drawn in the first place. */
2527 if (!s
->background_filled_p
)
2529 int box_line_width
= max (s
->face
->box_line_width
, 0);
2531 #if 0 /* MAC_TODO: stipple */
2534 /* Fill background with a stipple pattern. */
2535 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2536 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2537 s
->y
+ box_line_width
,
2538 s
->background_width
,
2539 s
->height
- 2 * box_line_width
);
2540 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2541 s
->background_filled_p
= 1;
2545 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2546 || s
->font_not_found_p
2547 || s
->extends_to_end_of_line_p
2550 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2551 s
->background_width
,
2552 s
->height
- 2 * box_line_width
);
2553 s
->background_filled_p
= 1;
2559 /* Draw the foreground of glyph string S. */
2562 x_draw_glyph_string_foreground (s
)
2563 struct glyph_string
*s
;
2567 /* If first glyph of S has a left box line, start drawing the text
2568 of S to the right of that box line. */
2569 if (s
->face
->box
!= FACE_NO_BOX
2570 && s
->first_glyph
->left_box_line_p
)
2571 x
= s
->x
+ abs (s
->face
->box_line_width
);
2575 /* Draw characters of S as rectangles if S's font could not be
2577 if (s
->font_not_found_p
)
2579 for (i
= 0; i
< s
->nchars
; ++i
)
2581 struct glyph
*g
= s
->first_glyph
+ i
;
2582 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2583 g
->pixel_width
- 1, s
->height
- 1);
2584 x
+= g
->pixel_width
;
2589 char *char1b
= (char *) s
->char2b
;
2590 int boff
= s
->font_info
->baseline_offset
;
2592 if (s
->font_info
->vertical_centering
)
2593 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2595 /* If we can use 8-bit functions, condense S->char2b. */
2598 && GC_FONT (s
->gc
)->mac_style
== NULL
2601 for (i
= 0; i
< s
->nchars
; ++i
)
2602 char1b
[i
] = s
->char2b
[i
].byte2
;
2604 /* Draw text with XDrawString if background has already been
2605 filled. Otherwise, use XDrawImageString. (Note that
2606 XDrawImageString is usually faster than XDrawString.) Always
2607 use XDrawImageString when drawing the cursor so that there is
2608 no chance that characters under a box cursor are invisible. */
2610 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2611 bg_width
= 0; /* Corresponds to XDrawString. */
2613 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2617 || GC_FONT (s
->gc
)->mac_style
2620 #if USE_CG_TEXT_DRAWING
2622 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2623 s
->char2b
, s
->nchars
, bg_width
))
2627 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2628 s
->char2b
, s
->nchars
, bg_width
);
2630 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2631 char1b
, s
->nchars
, bg_width
);
2635 /* Draw the foreground of composite glyph string S. */
2638 x_draw_composite_glyph_string_foreground (s
)
2639 struct glyph_string
*s
;
2643 /* If first glyph of S has a left box line, start drawing the text
2644 of S to the right of that box line. */
2645 if (s
->face
->box
!= FACE_NO_BOX
2646 && s
->first_glyph
->left_box_line_p
)
2647 x
= s
->x
+ abs (s
->face
->box_line_width
);
2651 /* S is a glyph string for a composition. S->gidx is the index of
2652 the first character drawn for glyphs of this composition.
2653 S->gidx == 0 means we are drawing the very first character of
2654 this composition. */
2656 /* Draw a rectangle for the composition if the font for the very
2657 first character of the composition could not be loaded. */
2658 if (s
->font_not_found_p
)
2661 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2662 s
->width
- 1, s
->height
- 1);
2666 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2667 mac_draw_string_16 (s
->f
, s
->gc
,
2668 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2669 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2675 #ifdef USE_X_TOOLKIT
2677 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2680 /* Return the frame on which widget WIDGET is used.. Abort if frame
2681 cannot be determined. */
2683 static struct frame
*
2684 x_frame_of_widget (widget
)
2687 struct x_display_info
*dpyinfo
;
2691 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2693 /* Find the top-level shell of the widget. Note that this function
2694 can be called when the widget is not yet realized, so XtWindow
2695 (widget) == 0. That's the reason we can't simply use
2696 x_any_window_to_frame. */
2697 while (!XtIsTopLevelShell (widget
))
2698 widget
= XtParent (widget
);
2700 /* Look for a frame with that top-level widget. Allocate the color
2701 on that frame to get the right gamma correction value. */
2702 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2703 if (GC_FRAMEP (XCAR (tail
))
2704 && (f
= XFRAME (XCAR (tail
)),
2705 (f
->output_data
.nothing
!= 1
2706 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2707 && f
->output_data
.x
->widget
== widget
)
2714 /* Allocate the color COLOR->pixel on the screen and display of
2715 widget WIDGET in colormap CMAP. If an exact match cannot be
2716 allocated, try the nearest color available. Value is non-zero
2717 if successful. This is called from lwlib. */
2720 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2725 struct frame
*f
= x_frame_of_widget (widget
);
2726 return x_alloc_nearest_color (f
, cmap
, color
);
2730 #endif /* USE_X_TOOLKIT */
2732 #if 0 /* MAC_TODO */
2734 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2735 CMAP. If an exact match can't be allocated, try the nearest color
2736 available. Value is non-zero if successful. Set *COLOR to the
2740 x_alloc_nearest_color (f
, cmap
, color
)
2745 Display
*display
= FRAME_X_DISPLAY (f
);
2746 Screen
*screen
= FRAME_X_SCREEN (f
);
2749 gamma_correct (f
, color
);
2750 rc
= XAllocColor (display
, cmap
, color
);
2753 /* If we got to this point, the colormap is full, so we're going
2754 to try to get the next closest color. The algorithm used is
2755 a least-squares matching, which is what X uses for closest
2756 color matching with StaticColor visuals. */
2758 unsigned long nearest_delta
= ~0;
2759 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2760 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2762 for (i
= 0; i
< ncells
; ++i
)
2764 XQueryColors (display
, cmap
, cells
, ncells
);
2766 for (nearest
= i
= 0; i
< ncells
; ++i
)
2768 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2769 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2770 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2771 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2773 if (delta
< nearest_delta
)
2776 nearest_delta
= delta
;
2780 color
->red
= cells
[nearest
].red
;
2781 color
->green
= cells
[nearest
].green
;
2782 color
->blue
= cells
[nearest
].blue
;
2783 rc
= XAllocColor (display
, cmap
, color
);
2786 #ifdef DEBUG_X_COLORS
2788 register_color (color
->pixel
);
2789 #endif /* DEBUG_X_COLORS */
2795 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2796 It's necessary to do this instead of just using PIXEL directly to
2797 get color reference counts right. */
2800 x_copy_color (f
, pixel
)
2802 unsigned long pixel
;
2806 color
.pixel
= pixel
;
2808 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2809 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2811 #ifdef DEBUG_X_COLORS
2812 register_color (pixel
);
2818 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2819 It's necessary to do this instead of just using PIXEL directly to
2820 get color reference counts right. */
2823 x_copy_dpy_color (dpy
, cmap
, pixel
)
2826 unsigned long pixel
;
2830 color
.pixel
= pixel
;
2832 XQueryColor (dpy
, cmap
, &color
);
2833 XAllocColor (dpy
, cmap
, &color
);
2835 #ifdef DEBUG_X_COLORS
2836 register_color (pixel
);
2841 #endif /* MAC_TODO */
2844 /* Brightness beyond which a color won't have its highlight brightness
2847 Nominally, highlight colors for `3d' faces are calculated by
2848 brightening an object's color by a constant scale factor, but this
2849 doesn't yield good results for dark colors, so for colors who's
2850 brightness is less than this value (on a scale of 0-255) have to
2851 use an additional additive factor.
2853 The value here is set so that the default menu-bar/mode-line color
2854 (grey75) will not have its highlights changed at all. */
2855 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2858 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2859 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2860 If this produces the same color as COLOR, try a color where all RGB
2861 values have DELTA added. Return the allocated color in *COLOR.
2862 DISPLAY is the X display, CMAP is the colormap to operate on.
2863 Value is non-zero if successful. */
2866 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2868 unsigned long *color
;
2875 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2878 /* Change RGB values by specified FACTOR. Avoid overflow! */
2879 xassert (factor
>= 0);
2880 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2881 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2882 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2884 /* Calculate brightness of COLOR. */
2885 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2886 + BLUE_FROM_ULONG (*color
)) / 6;
2888 /* We only boost colors that are darker than
2889 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2890 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2891 /* Make an additive adjustment to NEW, because it's dark enough so
2892 that scaling by FACTOR alone isn't enough. */
2894 /* How far below the limit this color is (0 - 1, 1 being darker). */
2895 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2896 /* The additive adjustment. */
2897 int min_delta
= delta
* dimness
* factor
/ 2;
2900 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2901 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2902 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2904 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2905 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2906 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2910 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2911 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2912 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2914 /* MAC_TODO: Map to palette and retry with delta if same? */
2915 /* MAC_TODO: Free colors (if using palette)? */
2926 /* Set up the foreground color for drawing relief lines of glyph
2927 string S. RELIEF is a pointer to a struct relief containing the GC
2928 with which lines will be drawn. Use a color that is FACTOR or
2929 DELTA lighter or darker than the relief's background which is found
2930 in S->f->output_data.x->relief_background. If such a color cannot
2931 be allocated, use DEFAULT_PIXEL, instead. */
2934 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2936 struct relief
*relief
;
2939 unsigned long default_pixel
;
2942 struct mac_output
*di
= f
->output_data
.mac
;
2943 unsigned long mask
= GCForeground
;
2944 unsigned long pixel
;
2945 unsigned long background
= di
->relief_background
;
2946 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2948 /* MAC_TODO: Free colors (if using palette)? */
2950 /* Allocate new color. */
2951 xgcv
.foreground
= default_pixel
;
2953 if (dpyinfo
->n_planes
!= 1
2954 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2956 relief
->allocated_p
= 1;
2957 xgcv
.foreground
= relief
->pixel
= pixel
;
2960 if (relief
->gc
== 0)
2962 #if 0 /* MAC_TODO: stipple */
2963 xgcv
.stipple
= dpyinfo
->gray
;
2966 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2969 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2973 /* Set up colors for the relief lines around glyph string S. */
2976 x_setup_relief_colors (s
)
2977 struct glyph_string
*s
;
2979 struct mac_output
*di
= s
->f
->output_data
.mac
;
2980 unsigned long color
;
2982 if (s
->face
->use_box_color_for_shadows_p
)
2983 color
= s
->face
->box_color
;
2984 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2986 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2987 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2992 /* Get the background color of the face. */
2993 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2994 color
= xgcv
.background
;
2997 if (di
->white_relief
.gc
== 0
2998 || color
!= di
->relief_background
)
3000 di
->relief_background
= color
;
3001 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3002 WHITE_PIX_DEFAULT (s
->f
));
3003 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3004 BLACK_PIX_DEFAULT (s
->f
));
3009 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3010 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3011 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3012 relief. LEFT_P non-zero means draw a relief on the left side of
3013 the rectangle. RIGHT_P non-zero means draw a relief on the right
3014 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3018 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3019 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
3021 int left_x
, top_y
, right_x
, bottom_y
, width
;
3022 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
3025 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
3030 gc
= f
->output_data
.mac
->white_relief
.gc
;
3032 gc
= f
->output_data
.mac
->black_relief
.gc
;
3033 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3037 for (i
= 0; i
< width
; ++i
)
3038 mac_draw_line (f
, gc
,
3039 left_x
+ i
* left_p
, top_y
+ i
,
3040 right_x
- i
* right_p
, top_y
+ i
);
3044 for (i
= 0; i
< width
; ++i
)
3045 mac_draw_line (f
, gc
,
3046 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
3048 mac_reset_clip_rectangles (dpy
, gc
);
3050 gc
= f
->output_data
.mac
->black_relief
.gc
;
3052 gc
= f
->output_data
.mac
->white_relief
.gc
;
3053 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
3057 for (i
= 0; i
< width
; ++i
)
3058 mac_draw_line (f
, gc
,
3059 left_x
+ i
* left_p
, bottom_y
- i
,
3060 right_x
- i
* right_p
, bottom_y
- i
);
3064 for (i
= 0; i
< width
; ++i
)
3065 mac_draw_line (f
, gc
,
3066 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
3068 mac_reset_clip_rectangles (dpy
, gc
);
3072 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3073 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3074 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3075 left side of the rectangle. RIGHT_P non-zero means draw a line
3076 on the right side of the rectangle. CLIP_RECT is the clipping
3077 rectangle to use when drawing. */
3080 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3081 left_p
, right_p
, clip_rect
)
3082 struct glyph_string
*s
;
3083 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
3088 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3089 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3090 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
3093 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3094 right_x
- left_x
+ 1, width
);
3098 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
3099 width
, bottom_y
- top_y
+ 1);
3102 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
3103 right_x
- left_x
+ 1, width
);
3107 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
3108 top_y
, width
, bottom_y
- top_y
+ 1);
3110 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3111 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3115 /* Draw a box around glyph string S. */
3118 x_draw_glyph_string_box (s
)
3119 struct glyph_string
*s
;
3121 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3122 int left_p
, right_p
;
3123 struct glyph
*last_glyph
;
3126 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
3127 ? WINDOW_RIGHT_EDGE_X (s
->w
)
3128 : window_box_right (s
->w
, s
->area
));
3130 /* The glyph that may have a right box line. */
3131 last_glyph
= (s
->cmp
|| s
->img
3133 : s
->first_glyph
+ s
->nchars
- 1);
3135 width
= abs (s
->face
->box_line_width
);
3136 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3138 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3140 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3142 bottom_y
= top_y
+ s
->height
- 1;
3144 left_p
= (s
->first_glyph
->left_box_line_p
3145 || (s
->hl
== DRAW_MOUSE_FACE
3147 || s
->prev
->hl
!= s
->hl
)));
3148 right_p
= (last_glyph
->right_box_line_p
3149 || (s
->hl
== DRAW_MOUSE_FACE
3151 || s
->next
->hl
!= s
->hl
)));
3153 get_glyph_string_clip_rect (s
, &clip_rect
);
3155 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3156 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3157 left_p
, right_p
, &clip_rect
);
3160 x_setup_relief_colors (s
);
3161 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3162 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3167 /* Draw foreground of image glyph string S. */
3170 x_draw_image_foreground (s
)
3171 struct glyph_string
*s
;
3174 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3176 /* If first glyph of S has a left box line, start drawing it to the
3177 right of that line. */
3178 if (s
->face
->box
!= FACE_NO_BOX
3179 && s
->first_glyph
->left_box_line_p
3181 x
+= abs (s
->face
->box_line_width
);
3183 /* If there is a margin around the image, adjust x- and y-position
3185 if (s
->slice
.x
== 0)
3186 x
+= s
->img
->hmargin
;
3187 if (s
->slice
.y
== 0)
3188 y
+= s
->img
->vmargin
;
3192 x_set_glyph_string_clipping (s
);
3195 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3196 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3197 s
->slice
.width
, s
->slice
.height
, x
, y
);
3200 mac_copy_area (s
->img
->pixmap
,
3201 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3202 s
->slice
.width
, s
->slice
.height
, x
, y
);
3204 /* When the image has a mask, we can expect that at
3205 least part of a mouse highlight or a block cursor will
3206 be visible. If the image doesn't have a mask, make
3207 a block cursor visible by drawing a rectangle around
3208 the image. I believe it's looking better if we do
3209 nothing here for mouse-face. */
3210 if (s
->hl
== DRAW_CURSOR
)
3212 int r
= s
->img
->relief
;
3214 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3215 s
->slice
.width
+ r
*2 - 1,
3216 s
->slice
.height
+ r
*2 - 1);
3221 /* Draw a rectangle if image could not be loaded. */
3222 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3223 s
->slice
.width
- 1, s
->slice
.height
- 1);
3227 /* Draw a relief around the image glyph string S. */
3230 x_draw_image_relief (s
)
3231 struct glyph_string
*s
;
3233 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3236 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3238 /* If first glyph of S has a left box line, start drawing it to the
3239 right of that line. */
3240 if (s
->face
->box
!= FACE_NO_BOX
3241 && s
->first_glyph
->left_box_line_p
3243 x
+= abs (s
->face
->box_line_width
);
3245 /* If there is a margin around the image, adjust x- and y-position
3247 if (s
->slice
.x
== 0)
3248 x
+= s
->img
->hmargin
;
3249 if (s
->slice
.y
== 0)
3250 y
+= s
->img
->vmargin
;
3252 if (s
->hl
== DRAW_IMAGE_SUNKEN
3253 || s
->hl
== DRAW_IMAGE_RAISED
)
3255 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3256 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3260 thick
= abs (s
->img
->relief
);
3261 raised_p
= s
->img
->relief
> 0;
3266 x1
= x
+ s
->slice
.width
+ thick
- 1;
3267 y1
= y
+ s
->slice
.height
+ thick
- 1;
3269 x_setup_relief_colors (s
);
3270 get_glyph_string_clip_rect (s
, &r
);
3271 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3273 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3275 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3280 /* Draw part of the background of glyph string S. X, Y, W, and H
3281 give the rectangle to draw. */
3284 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3285 struct glyph_string
*s
;
3288 #if 0 /* MAC_TODO: stipple */
3291 /* Fill background with a stipple pattern. */
3292 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3293 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3294 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3297 #endif /* MAC_TODO */
3298 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3302 /* Draw image glyph string S.
3305 s->x +-------------------------
3308 | +-------------------------
3311 | | +-------------------
3317 x_draw_image_glyph_string (s
)
3318 struct glyph_string
*s
;
3321 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3322 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3326 height
= s
->height
- 2 * box_line_vwidth
;
3329 /* Fill background with face under the image. Do it only if row is
3330 taller than image or if image has a clip mask to reduce
3332 s
->stippled_p
= s
->face
->stipple
!= 0;
3333 if (height
> s
->slice
.height
3337 || s
->img
->pixmap
== 0
3338 || s
->width
!= s
->background_width
)
3341 if (s
->first_glyph
->left_box_line_p
3343 x
+= box_line_hwidth
;
3346 if (s
->slice
.y
== 0)
3347 y
+= box_line_vwidth
;
3349 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3351 s
->background_filled_p
= 1;
3354 /* Draw the foreground. */
3355 x_draw_image_foreground (s
);
3357 /* If we must draw a relief around the image, do it. */
3359 || s
->hl
== DRAW_IMAGE_RAISED
3360 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3361 x_draw_image_relief (s
);
3365 /* Draw stretch glyph string S. */
3368 x_draw_stretch_glyph_string (s
)
3369 struct glyph_string
*s
;
3371 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3372 s
->stippled_p
= s
->face
->stipple
!= 0;
3374 if (s
->hl
== DRAW_CURSOR
3375 && !x_stretch_cursor_p
)
3377 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3378 as wide as the stretch glyph. */
3379 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3382 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3384 /* Clear rest using the GC of the original non-cursor face. */
3385 if (width
< s
->background_width
)
3387 int x
= s
->x
+ width
, y
= s
->y
;
3388 int w
= s
->background_width
- width
, h
= s
->height
;
3392 if (s
->row
->mouse_face_p
3393 && cursor_in_mouse_face_p (s
->w
))
3395 x_set_mouse_face_gc (s
);
3401 get_glyph_string_clip_rect (s
, &r
);
3402 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3404 #if 0 /* MAC_TODO: stipple */
3405 if (s
->face
->stipple
)
3407 /* Fill background with a stipple pattern. */
3408 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3409 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3410 XSetFillStyle (s
->display
, gc
, FillSolid
);
3413 #endif /* MAC_TODO */
3414 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3417 else if (!s
->background_filled_p
)
3418 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3421 s
->background_filled_p
= 1;
3425 /* Draw glyph string S. */
3428 x_draw_glyph_string (s
)
3429 struct glyph_string
*s
;
3431 int relief_drawn_p
= 0;
3433 /* If S draws into the background of its successor that does not
3434 draw a cursor, draw the background of the successor first so that
3435 S can draw into it. This makes S->next use XDrawString instead
3436 of XDrawImageString. */
3437 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3438 && s
->next
->hl
!= DRAW_CURSOR
)
3440 xassert (s
->next
->img
== NULL
);
3441 x_set_glyph_string_gc (s
->next
);
3442 x_set_glyph_string_clipping (s
->next
);
3443 x_draw_glyph_string_background (s
->next
, 1);
3446 /* Set up S->gc, set clipping and draw S. */
3447 x_set_glyph_string_gc (s
);
3449 /* Draw relief (if any) in advance for char/composition so that the
3450 glyph string can be drawn over it. */
3451 if (!s
->for_overlaps
3452 && s
->face
->box
!= FACE_NO_BOX
3453 && (s
->first_glyph
->type
== CHAR_GLYPH
3454 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3457 x_set_glyph_string_clipping (s
);
3458 x_draw_glyph_string_background (s
, 1);
3459 x_draw_glyph_string_box (s
);
3460 x_set_glyph_string_clipping (s
);
3464 x_set_glyph_string_clipping (s
);
3466 switch (s
->first_glyph
->type
)
3469 x_draw_image_glyph_string (s
);
3473 x_draw_stretch_glyph_string (s
);
3477 if (s
->for_overlaps
)
3478 s
->background_filled_p
= 1;
3480 x_draw_glyph_string_background (s
, 0);
3481 x_draw_glyph_string_foreground (s
);
3484 case COMPOSITE_GLYPH
:
3485 if (s
->for_overlaps
|| s
->gidx
> 0)
3486 s
->background_filled_p
= 1;
3488 x_draw_glyph_string_background (s
, 1);
3489 x_draw_composite_glyph_string_foreground (s
);
3496 if (!s
->for_overlaps
)
3498 /* Draw underline. */
3499 if (s
->face
->underline_p
)
3501 unsigned long h
= 1;
3502 unsigned long dy
= s
->height
- h
;
3504 if (s
->face
->underline_defaulted_p
)
3505 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3510 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3511 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3512 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3514 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3518 /* Draw overline. */
3519 if (s
->face
->overline_p
)
3521 unsigned long dy
= 0, h
= 1;
3523 if (s
->face
->overline_color_defaulted_p
)
3524 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3529 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3530 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3531 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3533 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3537 /* Draw strike-through. */
3538 if (s
->face
->strike_through_p
)
3540 unsigned long h
= 1;
3541 unsigned long dy
= (s
->height
- h
) / 2;
3543 if (s
->face
->strike_through_color_defaulted_p
)
3544 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3549 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3550 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3551 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3553 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3557 /* Draw relief if not yet drawn. */
3558 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3559 x_draw_glyph_string_box (s
);
3562 /* Reset clipping. */
3563 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3566 /* Shift display to make room for inserted glyphs. */
3569 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3571 int x
, y
, width
, height
, shift_by
;
3573 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3574 x
, y
, width
, height
,
3578 /* Delete N glyphs at the nominal cursor position. Not implemented
3589 /* Clear entire frame. If updating_frame is non-null, clear that
3590 frame. Otherwise clear the selected frame. */
3600 f
= SELECTED_FRAME ();
3602 /* Clearing the frame will erase any cursor, so mark them all as no
3604 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3605 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3606 output_cursor
.x
= -1;
3608 /* We don't set the output cursor here because there will always
3609 follow an explicit cursor_to. */
3611 mac_clear_window (f
);
3613 /* We have to clear the scroll bars, too. If we have changed
3614 colors or something like that, then they should be notified. */
3615 x_scroll_bar_clear (f
);
3617 XFlush (FRAME_MAC_DISPLAY (f
));
3623 /* Invert the middle quarter of the frame for .15 sec. */
3625 /* We use the select system call to do the waiting, so we have to make
3626 sure it's available. If it isn't, we just won't do visual bells. */
3628 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3631 /* Subtract the `struct timeval' values X and Y, storing the result in
3632 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3635 timeval_subtract (result
, x
, y
)
3636 struct timeval
*result
, x
, y
;
3638 /* Perform the carry for the later subtraction by updating y. This
3639 is safer because on some systems the tv_sec member is unsigned. */
3640 if (x
.tv_usec
< y
.tv_usec
)
3642 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3643 y
.tv_usec
-= 1000000 * nsec
;
3647 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3649 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3650 y
.tv_usec
+= 1000000 * nsec
;
3654 /* Compute the time remaining to wait. tv_usec is certainly
3656 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3657 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3659 /* Return indication of whether the result should be considered
3661 return x
.tv_sec
< y
.tv_sec
;
3668 /* Get the height not including a menu bar widget. */
3669 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3670 /* Height of each line to flash. */
3671 int flash_height
= FRAME_LINE_HEIGHT (f
);
3672 /* These will be the left and right margins of the rectangles. */
3673 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3674 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3678 /* Don't flash the area between a scroll bar and the frame
3679 edge it is next to. */
3680 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3682 case vertical_scroll_bar_left
:
3683 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3686 case vertical_scroll_bar_right
:
3687 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3694 width
= flash_right
- flash_left
;
3698 /* If window is tall, flash top and bottom line. */
3699 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3701 mac_invert_rectangle (f
, flash_left
,
3702 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3703 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3704 width
, flash_height
);
3705 mac_invert_rectangle (f
, flash_left
,
3706 (height
- flash_height
3707 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3708 width
, flash_height
);
3711 /* If it is short, flash it all. */
3712 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3713 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3718 struct timeval wakeup
;
3720 EMACS_GET_TIME (wakeup
);
3722 /* Compute time to wait until, propagating carry from usecs. */
3723 wakeup
.tv_usec
+= 150000;
3724 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3725 wakeup
.tv_usec
%= 1000000;
3727 /* Keep waiting until past the time wakeup or any input gets
3729 while (! detect_input_pending ())
3731 struct timeval current
;
3732 struct timeval timeout
;
3734 EMACS_GET_TIME (current
);
3736 /* Break if result would be negative. */
3737 if (timeval_subtract (¤t
, wakeup
, current
))
3740 /* How long `select' should wait. */
3742 timeout
.tv_usec
= 10000;
3744 /* Try to wait that long--but we might wake up sooner. */
3745 select (0, NULL
, NULL
, NULL
, &timeout
);
3749 /* If window is tall, flash top and bottom line. */
3750 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3752 mac_invert_rectangle (f
, flash_left
,
3753 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3754 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3755 width
, flash_height
);
3756 mac_invert_rectangle (f
, flash_left
,
3757 (height
- flash_height
3758 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3759 width
, flash_height
);
3762 /* If it is short, flash it all. */
3763 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3764 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3771 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3774 /* Make audible bell. */
3779 struct frame
*f
= SELECTED_FRAME ();
3781 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3789 XFlush (FRAME_MAC_DISPLAY (f
));
3795 /* Specify how many text lines, from the top of the window,
3796 should be affected by insert-lines and delete-lines operations.
3797 This, and those operations, are used only within an update
3798 that is bounded by calls to x_update_begin and x_update_end. */
3801 XTset_terminal_window (n
)
3804 /* This function intentionally left blank. */
3809 /***********************************************************************
3811 ***********************************************************************/
3813 /* Perform an insert-lines or delete-lines operation, inserting N
3814 lines or deleting -N lines at vertical position VPOS. */
3817 x_ins_del_lines (vpos
, n
)
3824 /* Scroll part of the display as described by RUN. */
3827 x_scroll_run (w
, run
)
3831 struct frame
*f
= XFRAME (w
->frame
);
3832 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3834 /* Get frame-relative bounding box of the text display area of W,
3835 without mode lines. Include in this box the left and right
3837 window_box (w
, -1, &x
, &y
, &width
, &height
);
3839 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3840 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3841 bottom_y
= y
+ height
;
3845 /* Scrolling up. Make sure we don't copy part of the mode
3846 line at the bottom. */
3847 if (from_y
+ run
->height
> bottom_y
)
3848 height
= bottom_y
- from_y
;
3850 height
= run
->height
;
3854 /* Scolling down. Make sure we don't copy over the mode line.
3856 if (to_y
+ run
->height
> bottom_y
)
3857 height
= bottom_y
- to_y
;
3859 height
= run
->height
;
3864 /* Cursor off. Will be switched on again in x_update_window_end. */
3868 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3878 /***********************************************************************
3880 ***********************************************************************/
3888 ControlRef root_control
;
3891 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3893 ActivateControl (root_control
);
3895 x_update_cursor (f
, 1);
3899 frame_unhighlight (f
)
3903 ControlRef root_control
;
3906 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3908 DeactivateControl (root_control
);
3910 x_update_cursor (f
, 1);
3913 /* The focus has changed. Update the frames as necessary to reflect
3914 the new situation. Note that we can't change the selected frame
3915 here, because the Lisp code we are interrupting might become confused.
3916 Each event gets marked with the frame in which it occurred, so the
3917 Lisp code can tell when the switch took place by examining the events. */
3920 x_new_focus_frame (dpyinfo
, frame
)
3921 struct x_display_info
*dpyinfo
;
3922 struct frame
*frame
;
3924 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3926 if (frame
!= dpyinfo
->x_focus_frame
)
3928 /* Set this before calling other routines, so that they see
3929 the correct value of x_focus_frame. */
3930 dpyinfo
->x_focus_frame
= frame
;
3932 if (old_focus
&& old_focus
->auto_lower
)
3933 x_lower_frame (old_focus
);
3936 selected_frame
= frame
;
3937 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3939 Fselect_window (selected_frame
->selected_window
, Qnil
);
3940 choose_minibuf_frame ();
3943 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3944 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3946 pending_autoraise_frame
= 0;
3949 x_frame_rehighlight (dpyinfo
);
3952 /* Handle FocusIn and FocusOut state changes for FRAME.
3953 If FRAME has focus and there exists more than one frame, puts
3954 a FOCUS_IN_EVENT into *BUFP. */
3957 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3959 struct mac_display_info
*dpyinfo
;
3960 struct frame
*frame
;
3961 struct input_event
*bufp
;
3963 if (type
== activeFlag
)
3965 if (dpyinfo
->x_focus_event_frame
!= frame
)
3967 x_new_focus_frame (dpyinfo
, frame
);
3968 dpyinfo
->x_focus_event_frame
= frame
;
3970 /* Don't stop displaying the initial startup message
3971 for a switch-frame event we don't need. */
3972 if (GC_NILP (Vterminal_frame
)
3973 && GC_CONSP (Vframe_list
)
3974 && !GC_NILP (XCDR (Vframe_list
)))
3976 bufp
->kind
= FOCUS_IN_EVENT
;
3977 XSETFRAME (bufp
->frame_or_window
, frame
);
3983 if (dpyinfo
->x_focus_event_frame
== frame
)
3985 dpyinfo
->x_focus_event_frame
= 0;
3986 x_new_focus_frame (dpyinfo
, 0);
3991 /* The focus may have changed. Figure out if it is a real focus change,
3992 by checking both FocusIn/Out and Enter/LeaveNotify events.
3994 Returns FOCUS_IN_EVENT event in *BUFP. */
3997 x_detect_focus_change (dpyinfo
, event
, bufp
)
3998 struct mac_display_info
*dpyinfo
;
4000 struct input_event
*bufp
;
4002 struct frame
*frame
;
4004 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
4008 /* On Mac, this is only called from focus events, so no switch needed. */
4009 mac_focus_changed ((event
->modifiers
& activeFlag
),
4010 dpyinfo
, frame
, bufp
);
4014 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4017 x_mouse_leave (dpyinfo
)
4018 struct x_display_info
*dpyinfo
;
4020 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4023 /* The focus has changed, or we have redirected a frame's focus to
4024 another frame (this happens when a frame uses a surrogate
4025 mini-buffer frame). Shift the highlight as appropriate.
4027 The FRAME argument doesn't necessarily have anything to do with which
4028 frame is being highlighted or un-highlighted; we only use it to find
4029 the appropriate X display info. */
4032 XTframe_rehighlight (frame
)
4033 struct frame
*frame
;
4035 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4039 x_frame_rehighlight (dpyinfo
)
4040 struct x_display_info
*dpyinfo
;
4042 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4044 if (dpyinfo
->x_focus_frame
)
4046 dpyinfo
->x_highlight_frame
4047 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4048 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4049 : dpyinfo
->x_focus_frame
);
4050 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4052 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4053 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4057 dpyinfo
->x_highlight_frame
= 0;
4059 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4062 frame_unhighlight (old_highlight
);
4063 if (dpyinfo
->x_highlight_frame
)
4064 frame_highlight (dpyinfo
->x_highlight_frame
);
4070 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
4072 #if 0 /* MAC_TODO */
4073 /* Initialize mode_switch_bit and modifier_meaning. */
4075 x_find_modifier_meanings (dpyinfo
)
4076 struct x_display_info
*dpyinfo
;
4078 int min_code
, max_code
;
4081 XModifierKeymap
*mods
;
4083 dpyinfo
->meta_mod_mask
= 0;
4084 dpyinfo
->shift_lock_mask
= 0;
4085 dpyinfo
->alt_mod_mask
= 0;
4086 dpyinfo
->super_mod_mask
= 0;
4087 dpyinfo
->hyper_mod_mask
= 0;
4090 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
4092 min_code
= dpyinfo
->display
->min_keycode
;
4093 max_code
= dpyinfo
->display
->max_keycode
;
4096 syms
= XGetKeyboardMapping (dpyinfo
->display
,
4097 min_code
, max_code
- min_code
+ 1,
4099 mods
= XGetModifierMapping (dpyinfo
->display
);
4101 /* Scan the modifier table to see which modifier bits the Meta and
4102 Alt keysyms are on. */
4104 int row
, col
; /* The row and column in the modifier table. */
4106 for (row
= 3; row
< 8; row
++)
4107 for (col
= 0; col
< mods
->max_keypermod
; col
++)
4110 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
4112 /* Zeroes are used for filler. Skip them. */
4116 /* Are any of this keycode's keysyms a meta key? */
4120 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
4122 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
4128 dpyinfo
->meta_mod_mask
|= (1 << row
);
4133 dpyinfo
->alt_mod_mask
|= (1 << row
);
4138 dpyinfo
->hyper_mod_mask
|= (1 << row
);
4143 dpyinfo
->super_mod_mask
|= (1 << row
);
4147 /* Ignore this if it's not on the lock modifier. */
4148 if ((1 << row
) == LockMask
)
4149 dpyinfo
->shift_lock_mask
= LockMask
;
4157 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
4158 if (! dpyinfo
->meta_mod_mask
)
4160 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
4161 dpyinfo
->alt_mod_mask
= 0;
4164 /* If some keys are both alt and meta,
4165 make them just meta, not alt. */
4166 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
4168 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4171 XFree ((char *) syms
);
4172 XFreeModifiermap (mods
);
4175 #endif /* MAC_TODO */
4177 /* Convert between the modifier bits X uses and the modifier bits
4181 x_mac_to_emacs_modifiers (dpyinfo
, state
)
4182 struct x_display_info
*dpyinfo
;
4183 unsigned short state
;
4185 return (((state
& shiftKey
) ? shift_modifier
: 0)
4186 | ((state
& controlKey
) ? ctrl_modifier
: 0)
4187 | ((state
& cmdKey
) ? meta_modifier
: 0)
4188 | ((state
& optionKey
) ? alt_modifier
: 0));
4191 #if 0 /* MAC_TODO */
4192 static unsigned short
4193 x_emacs_to_x_modifiers (dpyinfo
, state
)
4194 struct x_display_info
*dpyinfo
;
4197 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
4198 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
4199 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
4200 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4201 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4202 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
4204 #endif /* MAC_TODO */
4206 /* Convert a keysym to its name. */
4209 x_get_keysym_name (keysym
)
4216 value
= XKeysymToString (keysym
);
4227 /* Function to report a mouse movement to the mainstream Emacs code.
4228 The input handler calls this.
4230 We have received a mouse movement event, which is given in *event.
4231 If the mouse is over a different glyph than it was last time, tell
4232 the mainstream emacs code by setting mouse_moved. If not, ask for
4233 another motion event, so we can check again the next time it moves. */
4235 static Point last_mouse_motion_position
;
4236 static Lisp_Object last_mouse_motion_frame
;
4239 note_mouse_movement (frame
, pos
)
4243 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4244 #if TARGET_API_MAC_CARBON
4248 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4249 last_mouse_motion_position
= *pos
;
4250 XSETFRAME (last_mouse_motion_frame
, frame
);
4252 #if TARGET_API_MAC_CARBON
4253 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4255 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4258 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4259 /* This case corresponds to LeaveNotify in X11. */
4261 /* If we move outside the frame, then we're certainly no
4262 longer on any text in the frame. */
4263 clear_mouse_face (dpyinfo
);
4264 dpyinfo
->mouse_face_mouse_frame
= 0;
4265 if (!dpyinfo
->grabbed
)
4266 rif
->define_frame_cursor (frame
,
4267 frame
->output_data
.mac
->nontext_cursor
);
4271 /* Has the mouse moved off the glyph it was on at the last sighting? */
4272 if (frame
!= last_mouse_glyph_frame
4273 || !PtInRect (*pos
, &last_mouse_glyph
))
4275 frame
->mouse_moved
= 1;
4276 last_mouse_scroll_bar
= Qnil
;
4277 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4278 /* Remember which glyph we're now on. */
4279 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4280 last_mouse_glyph_frame
= frame
;
4288 /************************************************************************
4290 ************************************************************************/
4292 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4295 redo_mouse_highlight ()
4297 if (!NILP (last_mouse_motion_frame
)
4298 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4299 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4300 last_mouse_motion_position
.h
,
4301 last_mouse_motion_position
.v
);
4305 static struct frame
*
4306 mac_focus_frame (dpyinfo
)
4307 struct mac_display_info
*dpyinfo
;
4309 if (dpyinfo
->x_focus_frame
)
4310 return dpyinfo
->x_focus_frame
;
4312 /* Mac version may get events, such as a menu bar click, even when
4313 all the frames are invisible. In this case, we regard the
4314 event came to the selected frame. */
4315 return SELECTED_FRAME ();
4319 /* Return the current position of the mouse.
4320 *FP should be a frame which indicates which display to ask about.
4322 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4323 and *PART to the frame, window, and scroll bar part that the mouse
4324 is over. Set *X and *Y to the portion and whole of the mouse's
4325 position on the scroll bar.
4327 If the mouse movement started elsewhere, set *FP to the frame the
4328 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4331 Set *TIME to the server time-stamp for the time at which the mouse
4332 was at this position.
4334 Don't store anything if we don't have a valid set of values to report.
4336 This clears the mouse_moved flag, so we can wait for the next mouse
4340 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4343 Lisp_Object
*bar_window
;
4344 enum scroll_bar_part
*part
;
4346 unsigned long *time
;
4352 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4353 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4356 Lisp_Object frame
, tail
;
4358 /* Clear the mouse-moved flag for every frame on this display. */
4359 FOR_EACH_FRAME (tail
, frame
)
4360 XFRAME (frame
)->mouse_moved
= 0;
4362 last_mouse_scroll_bar
= Qnil
;
4364 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4365 && FRAME_LIVE_P (last_mouse_frame
))
4366 f1
= last_mouse_frame
;
4368 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4372 /* Ok, we found a frame. Store all the values.
4373 last_mouse_glyph is a rectangle used to reduce the
4374 generation of mouse events. To not miss any motion
4375 events, we must divide the frame into rectangles of the
4376 size of the smallest character that could be displayed
4377 on it, i.e. into the same rectangles that matrices on
4378 the frame are divided into. */
4381 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4382 GetMouse (&mouse_pos
);
4383 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4385 last_mouse_glyph_frame
= f1
;
4390 XSETINT (*x
, mouse_pos
.h
);
4391 XSETINT (*y
, mouse_pos
.v
);
4392 *time
= last_mouse_movement_time
;
4400 /************************************************************************
4402 ************************************************************************/
4404 #ifdef USE_TOOLKIT_SCROLL_BARS
4406 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4407 static OSStatus install_scroll_bar_timer
P_ ((void));
4408 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4409 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4410 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4411 struct input_event
*));
4412 static OSStatus get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4414 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4416 struct input_event
*));
4417 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4418 struct input_event
*));
4419 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4420 Point
, struct input_event
*));
4421 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4424 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4426 static int last_scroll_bar_part
;
4428 static EventLoopTimerRef scroll_bar_timer
;
4430 static int scroll_bar_timer_event_posted_p
;
4432 #define SCROLL_BAR_FIRST_DELAY 0.5
4433 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4436 scroll_bar_timer_callback (timer
, data
)
4437 EventLoopTimerRef timer
;
4440 EventRef event
= NULL
;
4443 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4444 kEventAttributeNone
, &event
);
4449 GetMouse (&mouse_pos
);
4450 LocalToGlobal (&mouse_pos
);
4451 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4452 sizeof (Point
), &mouse_pos
);
4456 UInt32 modifiers
= GetCurrentKeyModifiers ();
4458 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4459 sizeof (UInt32
), &modifiers
);
4462 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4463 kEventPriorityStandard
);
4465 scroll_bar_timer_event_posted_p
= 1;
4468 ReleaseEvent (event
);
4472 install_scroll_bar_timer ()
4474 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4476 if (scroll_bar_timer_callbackUPP
== NULL
)
4477 scroll_bar_timer_callbackUPP
=
4478 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4480 if (scroll_bar_timer
== NULL
)
4481 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4482 kEventDurationForever as delays. */
4484 InstallEventLoopTimer (GetCurrentEventLoop (),
4485 kEventDurationForever
, kEventDurationForever
,
4486 scroll_bar_timer_callbackUPP
, NULL
,
4491 set_scroll_bar_timer (delay
)
4492 EventTimerInterval delay
;
4494 if (scroll_bar_timer
== NULL
)
4495 install_scroll_bar_timer ();
4497 scroll_bar_timer_event_posted_p
= 0;
4499 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4503 control_part_code_to_scroll_bar_part (part_code
)
4504 ControlPartCode part_code
;
4508 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4509 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4510 case kControlPageUpPart
: return scroll_bar_above_handle
;
4511 case kControlPageDownPart
: return scroll_bar_below_handle
;
4512 case kControlIndicatorPart
: return scroll_bar_handle
;
4519 construct_scroll_bar_click (bar
, part
, bufp
)
4520 struct scroll_bar
*bar
;
4522 struct input_event
*bufp
;
4524 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4525 bufp
->frame_or_window
= bar
->window
;
4529 XSETINT (bufp
->x
, 0);
4530 XSETINT (bufp
->y
, 0);
4531 bufp
->modifiers
= 0;
4535 get_control_part_bounds (ch
, part_code
, rect
)
4537 ControlPartCode part_code
;
4540 RgnHandle region
= NewRgn ();
4543 err
= GetControlRegion (ch
, part_code
, region
);
4545 GetRegionBounds (region
, rect
);
4546 DisposeRgn (region
);
4552 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4553 struct scroll_bar
*bar
;
4554 ControlPartCode part_code
;
4555 struct input_event
*bufp
;
4557 int part
= control_part_code_to_scroll_bar_part (part_code
);
4562 if (part
!= scroll_bar_handle
)
4564 construct_scroll_bar_click (bar
, part
, bufp
);
4565 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4566 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4569 last_scroll_bar_part
= part
;
4570 bar
->dragging
= Qnil
;
4571 tracked_scroll_bar
= bar
;
4575 x_scroll_bar_handle_release (bar
, bufp
)
4576 struct scroll_bar
*bar
;
4577 struct input_event
*bufp
;
4579 if (last_scroll_bar_part
!= scroll_bar_handle
4580 || !GC_NILP (bar
->dragging
))
4581 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4583 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4584 set_scroll_bar_timer (kEventDurationForever
);
4586 last_scroll_bar_part
= -1;
4587 bar
->dragging
= Qnil
;
4588 tracked_scroll_bar
= NULL
;
4592 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4594 struct scroll_bar
*bar
;
4596 struct input_event
*bufp
;
4598 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4600 if (last_scroll_bar_part
== scroll_bar_handle
)
4605 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4606 kControlIndicatorPart
, &r
);
4608 if (GC_NILP (bar
->dragging
))
4609 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4611 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4612 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4613 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4618 if (top
> top_range
)
4621 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4622 XSETINT (bufp
->x
, top
);
4623 XSETINT (bufp
->y
, top_range
);
4627 ControlPartCode part_code
;
4628 int unhilite_p
= 0, part
;
4630 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4634 part
= control_part_code_to_scroll_bar_part (part_code
);
4636 switch (last_scroll_bar_part
)
4638 case scroll_bar_above_handle
:
4639 case scroll_bar_below_handle
:
4640 if (part
!= scroll_bar_above_handle
4641 && part
!= scroll_bar_below_handle
)
4645 case scroll_bar_up_arrow
:
4646 case scroll_bar_down_arrow
:
4647 if (part
!= scroll_bar_up_arrow
4648 && part
!= scroll_bar_down_arrow
)
4655 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4656 else if (part
!= last_scroll_bar_part
4657 || scroll_bar_timer_event_posted_p
)
4659 construct_scroll_bar_click (bar
, part
, bufp
);
4660 last_scroll_bar_part
= part
;
4661 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4662 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4667 /* Set the thumb size and position of scroll bar BAR. We are currently
4668 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4671 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4672 struct scroll_bar
*bar
;
4673 int portion
, position
, whole
;
4675 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4676 int value
, viewsize
, maximum
;
4678 if (XINT (bar
->track_height
) == 0)
4682 value
= 0, viewsize
= 1, maximum
= 0;
4687 maximum
= max (0, whole
- portion
);
4692 if (GetControlViewSize (ch
) != viewsize
4693 || GetControl32BitValue (ch
) != value
4694 || GetControl32BitMaximum (ch
) != maximum
)
4696 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4697 SetControlVisibility (ch
, false, false);
4699 SetControl32BitMaximum (ch
, maximum
);
4700 SetControl32BitValue (ch
, value
);
4701 SetControlViewSize (ch
, viewsize
);
4703 SetControlVisibility (ch
, true, true);
4709 #endif /* USE_TOOLKIT_SCROLL_BARS */
4713 /************************************************************************
4714 Scroll bars, general
4715 ************************************************************************/
4717 /* Create a scroll bar and return the scroll bar vector for it. W is
4718 the Emacs window on which to create the scroll bar. TOP, LEFT,
4719 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4722 static struct scroll_bar
*
4723 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4725 int top
, left
, width
, height
, disp_top
, disp_height
;
4727 struct frame
*f
= XFRAME (w
->frame
);
4728 struct scroll_bar
*bar
4729 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4737 r
.right
= left
+ width
;
4738 r
.bottom
= disp_top
+ disp_height
;
4741 mac_prepare_for_quickdraw (f
);
4743 #if TARGET_API_MAC_CARBON
4744 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p",
4745 #if USE_TOOLKIT_SCROLL_BARS
4748 width
< disp_height
,
4750 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4752 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4753 0, 0, 0, scrollBarProc
, (long) bar
);
4755 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4757 XSETWINDOW (bar
->window
, w
);
4758 XSETINT (bar
->top
, top
);
4759 XSETINT (bar
->left
, left
);
4760 XSETINT (bar
->width
, width
);
4761 XSETINT (bar
->height
, height
);
4762 XSETINT (bar
->start
, 0);
4763 XSETINT (bar
->end
, 0);
4764 bar
->dragging
= Qnil
;
4765 #ifdef USE_TOOLKIT_SCROLL_BARS
4766 bar
->track_top
= Qnil
;
4767 bar
->track_height
= Qnil
;
4770 /* Add bar to its frame's list of scroll bars. */
4771 bar
->next
= FRAME_SCROLL_BARS (f
);
4773 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4774 if (!NILP (bar
->next
))
4775 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4782 /* Draw BAR's handle in the proper position.
4784 If the handle is already drawn from START to END, don't bother
4785 redrawing it, unless REBUILD is non-zero; in that case, always
4786 redraw it. (REBUILD is handy for drawing the handle after expose
4789 Normally, we want to constrain the start and end of the handle to
4790 fit inside its rectangle, but if the user is dragging the scroll
4791 bar handle, we want to let them drag it down all the way, so that
4792 the bar's top is as far down as it goes; otherwise, there's no way
4793 to move to the very end of the buffer. */
4795 #ifndef USE_TOOLKIT_SCROLL_BARS
4798 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4799 struct scroll_bar
*bar
;
4803 int dragging
= ! NILP (bar
->dragging
);
4804 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4805 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4806 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4807 int length
= end
- start
;
4809 /* If the display is already accurate, do nothing. */
4811 && start
== XINT (bar
->start
)
4812 && end
== XINT (bar
->end
))
4817 /* Make sure the values are reasonable, and try to preserve the
4818 distance between start and end. */
4821 else if (start
> top_range
)
4823 end
= start
+ length
;
4827 else if (end
> top_range
&& ! dragging
)
4830 /* Store the adjusted setting in the scroll bar. */
4831 XSETINT (bar
->start
, start
);
4832 XSETINT (bar
->end
, end
);
4834 /* Clip the end position, just for display. */
4835 if (end
> top_range
)
4838 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4839 top positions, to make sure the handle is always at least that
4840 many pixels tall. */
4841 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4843 SetControlMinimum (ch
, 0);
4844 /* Don't inadvertently activate deactivated scroll bars */
4845 if (GetControlMaximum (ch
) != -1)
4846 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4848 SetControlValue (ch
, start
);
4849 #if TARGET_API_MAC_CARBON
4850 SetControlViewSize (ch
, end
- start
);
4856 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4858 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4862 x_scroll_bar_remove (bar
)
4863 struct scroll_bar
*bar
;
4865 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4870 mac_prepare_for_quickdraw (f
);
4872 /* Destroy the Mac scroll bar control */
4873 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4875 /* Disassociate this scroll bar from its window. */
4876 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4882 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4883 that we are displaying PORTION characters out of a total of WHOLE
4884 characters, starting at POSITION. If WINDOW has no scroll bar,
4888 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4890 int portion
, whole
, position
;
4892 struct frame
*f
= XFRAME (w
->frame
);
4893 struct scroll_bar
*bar
;
4894 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4895 int window_y
, window_height
;
4897 /* Get window dimensions. */
4898 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4900 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4901 height
= window_height
;
4903 /* Compute the left edge of the scroll bar area. */
4904 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4906 /* Compute the width of the scroll bar which might be less than
4907 the width of the area reserved for the scroll bar. */
4908 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4909 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4913 /* Compute the left edge of the scroll bar. */
4914 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4917 sb_left
= left
+ width
- sb_width
;
4919 /* Adjustments according to Inside Macintosh to make it look nice */
4921 disp_height
= height
;
4928 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4934 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4938 /* Does the scroll bar exist yet? */
4939 if (NILP (w
->vertical_scroll_bar
))
4942 mac_clear_area (f
, left
, top
, width
, height
);
4944 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4946 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4950 /* It may just need to be moved and resized. */
4953 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4954 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4958 /* If already correctly positioned, do nothing. */
4959 if (!(XINT (bar
->left
) == sb_left
4960 && XINT (bar
->top
) == top
4961 && XINT (bar
->width
) == sb_width
4962 && XINT (bar
->height
) == height
))
4964 /* Since toolkit scroll bars are smaller than the space reserved
4965 for them on the frame, we have to clear "under" them. */
4966 mac_clear_area (f
, left
, top
, width
, height
);
4969 mac_prepare_for_quickdraw (f
);
4972 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4973 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4975 #ifndef USE_TOOLKIT_SCROLL_BARS
4976 if (sb_width
< disp_height
)
4980 /* Remember new settings. */
4981 XSETINT (bar
->left
, sb_left
);
4982 XSETINT (bar
->top
, top
);
4983 XSETINT (bar
->width
, sb_width
);
4984 XSETINT (bar
->height
, height
);
4985 #ifdef USE_TOOLKIT_SCROLL_BARS
4986 bar
->track_top
= Qnil
;
4987 bar
->track_height
= Qnil
;
4994 #ifdef USE_TOOLKIT_SCROLL_BARS
4995 if (NILP (bar
->track_top
))
4996 if (sb_width
>= disp_height
)
4998 XSETINT (bar
->track_top
, 0);
4999 XSETINT (bar
->track_height
, 0);
5003 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5008 SetControl32BitMinimum (ch
, 0);
5009 SetControl32BitMaximum (ch
, 1);
5010 SetControlViewSize (ch
, 1);
5012 /* Move the scroll bar thumb to the top. */
5013 SetControl32BitValue (ch
, 0);
5014 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
5016 /* Move the scroll bar thumb to the bottom. */
5017 SetControl32BitValue (ch
, 1);
5018 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
5020 UnionRect (&r0
, &r1
, &r0
);
5021 XSETINT (bar
->track_top
, r0
.top
);
5022 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
5024 /* Don't show the scroll bar if its height is not enough to
5025 display the scroll bar thumb. */
5026 if (r0
.bottom
- r0
.top
> 0)
5032 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5033 #else /* not USE_TOOLKIT_SCROLL_BARS */
5034 /* Set the scroll bar's current state, unless we're currently being
5036 if (NILP (bar
->dragging
))
5038 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5041 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5044 int start
= ((double) position
* top_range
) / whole
;
5045 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5046 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5049 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5053 /* The following three hooks are used when we're doing a thorough
5054 redisplay of the frame. We don't explicitly know which scroll bars
5055 are going to be deleted, because keeping track of when windows go
5056 away is a real pain - "Can you say set-window-configuration, boys
5057 and girls?" Instead, we just assert at the beginning of redisplay
5058 that *all* scroll bars are to be removed, and then save a scroll bar
5059 from the fiery pit when we actually redisplay its window. */
5061 /* Arrange for all scroll bars on FRAME to be removed at the next call
5062 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5063 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5066 XTcondemn_scroll_bars (frame
)
5069 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5070 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5073 bar
= FRAME_SCROLL_BARS (frame
);
5074 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5075 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5076 XSCROLL_BAR (bar
)->prev
= Qnil
;
5077 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5078 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5079 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5084 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5085 Note that WINDOW isn't necessarily condemned at all. */
5088 XTredeem_scroll_bar (window
)
5089 struct window
*window
;
5091 struct scroll_bar
*bar
;
5094 /* We can't redeem this window's scroll bar if it doesn't have one. */
5095 if (NILP (window
->vertical_scroll_bar
))
5098 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5100 /* Unlink it from the condemned list. */
5101 f
= XFRAME (WINDOW_FRAME (window
));
5102 if (NILP (bar
->prev
))
5104 /* If the prev pointer is nil, it must be the first in one of
5106 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5107 /* It's not condemned. Everything's fine. */
5109 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5110 window
->vertical_scroll_bar
))
5111 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5113 /* If its prev pointer is nil, it must be at the front of
5114 one or the other! */
5118 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5120 if (! NILP (bar
->next
))
5121 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5123 bar
->next
= FRAME_SCROLL_BARS (f
);
5125 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5126 if (! NILP (bar
->next
))
5127 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5130 /* Remove all scroll bars on FRAME that haven't been saved since the
5131 last call to `*condemn_scroll_bars_hook'. */
5134 XTjudge_scroll_bars (f
)
5137 Lisp_Object bar
, next
;
5139 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5141 /* Clear out the condemned list now so we won't try to process any
5142 more events on the hapless scroll bars. */
5143 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5145 for (; ! NILP (bar
); bar
= next
)
5147 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5149 x_scroll_bar_remove (b
);
5152 b
->next
= b
->prev
= Qnil
;
5155 /* Now there should be no references to the condemned scroll bars,
5156 and they should get garbage-collected. */
5160 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5161 is set to something other than NO_EVENT, it is enqueued.
5163 This may be called from a signal handler, so we have to ignore GC
5167 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5168 struct scroll_bar
*bar
;
5169 ControlPartCode part_code
;
5171 struct input_event
*bufp
;
5173 int win_y
, top_range
;
5175 if (! GC_WINDOWP (bar
->window
))
5178 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5179 bufp
->frame_or_window
= bar
->window
;
5182 bar
->dragging
= Qnil
;
5186 case kControlUpButtonPart
:
5187 bufp
->part
= scroll_bar_up_arrow
;
5189 case kControlDownButtonPart
:
5190 bufp
->part
= scroll_bar_down_arrow
;
5192 case kControlPageUpPart
:
5193 bufp
->part
= scroll_bar_above_handle
;
5195 case kControlPageDownPart
:
5196 bufp
->part
= scroll_bar_below_handle
;
5198 #if TARGET_API_MAC_CARBON
5201 case kControlIndicatorPart
:
5203 if (er
->what
== mouseDown
)
5204 bar
->dragging
= make_number (0);
5205 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5206 bufp
->part
= scroll_bar_handle
;
5210 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5211 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5213 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5217 if (! NILP (bar
->dragging
))
5218 win_y
-= XINT (bar
->dragging
);
5222 if (win_y
> top_range
)
5225 XSETINT (bufp
->x
, win_y
);
5226 XSETINT (bufp
->y
, top_range
);
5229 #ifndef USE_TOOLKIT_SCROLL_BARS
5231 /* Handle some mouse motion while someone is dragging the scroll bar.
5233 This may be called from a signal handler, so we have to ignore GC
5237 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5238 struct scroll_bar
*bar
;
5242 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5244 last_mouse_movement_time
= t
;
5247 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5249 /* If we're dragging the bar, display it. */
5250 if (! GC_NILP (bar
->dragging
))
5252 /* Where should the handle be now? */
5253 int new_start
= y_pos
- 24;
5255 if (new_start
!= XINT (bar
->start
))
5257 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5259 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5264 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5266 /* Return information to the user about the current position of the mouse
5267 on the scroll bar. */
5270 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5272 Lisp_Object
*bar_window
;
5273 enum scroll_bar_part
*part
;
5275 unsigned long *time
;
5277 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5278 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5279 #if TARGET_API_MAC_CARBON
5280 WindowPtr wp
= GetControlOwner (ch
);
5282 WindowPtr wp
= (*ch
)->contrlOwner
;
5285 struct frame
*f
= mac_window_to_frame (wp
);
5286 int win_y
, top_range
;
5288 SetPortWindowPort (wp
);
5290 GetMouse (&mouse_pos
);
5292 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5293 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5295 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5299 if (! NILP (bar
->dragging
))
5300 win_y
-= XINT (bar
->dragging
);
5304 if (win_y
> top_range
)
5308 *bar_window
= bar
->window
;
5310 if (! NILP (bar
->dragging
))
5311 *part
= scroll_bar_handle
;
5312 else if (win_y
< XINT (bar
->start
))
5313 *part
= scroll_bar_above_handle
;
5314 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5315 *part
= scroll_bar_handle
;
5317 *part
= scroll_bar_below_handle
;
5319 XSETINT (*x
, win_y
);
5320 XSETINT (*y
, top_range
);
5323 last_mouse_scroll_bar
= Qnil
;
5325 *time
= last_mouse_movement_time
;
5329 /* The screen has been cleared so we may have changed foreground or
5330 background colors, and the scroll bars may need to be redrawn.
5331 Clear out the scroll bars, and ask for expose events, so we can
5335 x_scroll_bar_clear (f
)
5338 XTcondemn_scroll_bars (f
);
5339 XTjudge_scroll_bars (f
);
5343 /***********************************************************************
5345 ***********************************************************************/
5347 /* Set clipping for output in glyph row ROW. W is the window in which
5348 we operate. GC is the graphics context to set clipping in.
5350 ROW may be a text row or, e.g., a mode line. Text rows must be
5351 clipped to the interior of the window dedicated to text display,
5352 mode lines must be clipped to the whole window. */
5355 x_clip_to_row (w
, row
, area
, gc
)
5357 struct glyph_row
*row
;
5361 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5363 int window_x
, window_y
, window_width
;
5365 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5367 clip_rect
.left
= window_x
;
5368 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5369 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5370 clip_rect
.right
= clip_rect
.left
+ window_width
;
5371 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5373 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5377 /* Draw a hollow box cursor on window W in glyph row ROW. */
5380 x_draw_hollow_cursor (w
, row
)
5382 struct glyph_row
*row
;
5384 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5385 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5386 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5389 struct glyph
*cursor_glyph
;
5392 /* Get the glyph the cursor is on. If we can't tell because
5393 the current matrix is invalid or such, give up. */
5394 cursor_glyph
= get_phys_cursor_glyph (w
);
5395 if (cursor_glyph
== NULL
)
5398 /* Compute frame-relative coordinates for phys cursor. */
5399 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5400 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5401 wd
= w
->phys_cursor_width
;
5403 /* The foreground of cursor_gc is typically the same as the normal
5404 background color, which can cause the cursor box to be invisible. */
5405 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5406 if (dpyinfo
->scratch_cursor_gc
)
5407 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5409 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5410 GCForeground
, &xgcv
);
5411 gc
= dpyinfo
->scratch_cursor_gc
;
5413 /* Set clipping, draw the rectangle, and reset clipping again. */
5414 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5415 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
5416 mac_reset_clip_rectangles (dpy
, gc
);
5420 /* Draw a bar cursor on window W in glyph row ROW.
5422 Implementation note: One would like to draw a bar cursor with an
5423 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5424 Unfortunately, I didn't find a font yet that has this property set.
5428 x_draw_bar_cursor (w
, row
, width
, kind
)
5430 struct glyph_row
*row
;
5432 enum text_cursor_kinds kind
;
5434 struct frame
*f
= XFRAME (w
->frame
);
5435 struct glyph
*cursor_glyph
;
5437 /* If cursor is out of bounds, don't draw garbage. This can happen
5438 in mini-buffer windows when switching between echo area glyphs
5440 cursor_glyph
= get_phys_cursor_glyph (w
);
5441 if (cursor_glyph
== NULL
)
5444 /* If on an image, draw like a normal cursor. That's usually better
5445 visible than drawing a bar, esp. if the image is large so that
5446 the bar might not be in the window. */
5447 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5449 struct glyph_row
*row
;
5450 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5451 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5455 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5456 Window window
= FRAME_MAC_WINDOW (f
);
5457 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5458 unsigned long mask
= GCForeground
| GCBackground
;
5459 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5462 /* If the glyph's background equals the color we normally draw
5463 the bar cursor in, the bar cursor in its normal color is
5464 invisible. Use the glyph's foreground color instead in this
5465 case, on the assumption that the glyph's colors are chosen so
5466 that the glyph is legible. */
5467 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5468 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5470 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5473 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5476 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5477 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5481 width
= FRAME_CURSOR_WIDTH (f
);
5482 width
= min (cursor_glyph
->pixel_width
, width
);
5484 w
->phys_cursor_width
= width
;
5485 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5487 if (kind
== BAR_CURSOR
)
5488 mac_fill_rectangle (f
, gc
,
5489 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5490 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5491 width
, row
->height
);
5493 mac_fill_rectangle (f
, gc
,
5494 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5495 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5496 row
->height
- width
),
5497 cursor_glyph
->pixel_width
,
5500 mac_reset_clip_rectangles (dpy
, gc
);
5505 /* RIF: Define cursor CURSOR on frame F. */
5508 mac_define_frame_cursor (f
, cursor
)
5512 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5514 if (dpyinfo
->x_focus_frame
== f
)
5515 SetThemeCursor (cursor
);
5519 /* RIF: Clear area on frame F. */
5522 mac_clear_frame_area (f
, x
, y
, width
, height
)
5524 int x
, y
, width
, height
;
5526 mac_clear_area (f
, x
, y
, width
, height
);
5530 /* RIF: Draw cursor on window W. */
5533 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5535 struct glyph_row
*glyph_row
;
5537 int cursor_type
, cursor_width
;
5542 w
->phys_cursor_type
= cursor_type
;
5543 w
->phys_cursor_on_p
= 1;
5545 if (glyph_row
->exact_window_width_line_p
5546 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5548 glyph_row
->cursor_in_fringe_p
= 1;
5549 draw_fringe_bitmap (w
, glyph_row
, 0);
5552 switch (cursor_type
)
5554 case HOLLOW_BOX_CURSOR
:
5555 x_draw_hollow_cursor (w
, glyph_row
);
5558 case FILLED_BOX_CURSOR
:
5559 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5563 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5567 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5571 w
->phys_cursor_width
= 0;
5583 #if 0 /* MAC_TODO: no icon support yet. */
5585 x_bitmap_icon (f
, icon
)
5591 if (FRAME_W32_WINDOW (f
) == 0)
5595 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5596 else if (STRINGP (icon
))
5597 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5598 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5599 else if (SYMBOLP (icon
))
5603 if (EQ (icon
, intern ("application")))
5604 name
= (LPCTSTR
) IDI_APPLICATION
;
5605 else if (EQ (icon
, intern ("hand")))
5606 name
= (LPCTSTR
) IDI_HAND
;
5607 else if (EQ (icon
, intern ("question")))
5608 name
= (LPCTSTR
) IDI_QUESTION
;
5609 else if (EQ (icon
, intern ("exclamation")))
5610 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5611 else if (EQ (icon
, intern ("asterisk")))
5612 name
= (LPCTSTR
) IDI_ASTERISK
;
5613 else if (EQ (icon
, intern ("winlogo")))
5614 name
= (LPCTSTR
) IDI_WINLOGO
;
5618 hicon
= LoadIcon (NULL
, name
);
5626 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5631 #endif /* MAC_TODO */
5633 /************************************************************************
5635 ************************************************************************/
5637 /* Display Error Handling functions not used on W32. Listing them here
5638 helps diff stay in step when comparing w32term.c with xterm.c.
5640 x_error_catcher (display, error)
5641 x_catch_errors (dpy)
5642 x_catch_errors_unwind (old_val)
5643 x_check_errors (dpy, format)
5644 x_had_errors_p (dpy)
5645 x_clear_errors (dpy)
5646 x_uncatch_errors (dpy, count)
5648 x_connection_signal (signalnum)
5649 x_connection_closed (dpy, error_message)
5650 x_error_quitter (display, error)
5651 x_error_handler (display, error)
5652 x_io_error_quitter (display)
5657 /* Changing the font of the frame. */
5659 /* Give frame F the font named FONTNAME as its default font, and
5660 return the full name of that font. FONTNAME may be a wildcard
5661 pattern; in that case, we choose some font that fits the pattern.
5662 The return value shows which font we chose. */
5665 x_new_font (f
, fontname
)
5667 register char *fontname
;
5669 struct font_info
*fontp
5670 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5675 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5676 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5677 FRAME_FONTSET (f
) = -1;
5679 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5680 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5681 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5683 compute_fringe_widths (f
, 1);
5685 /* Compute the scroll bar width in character columns. */
5686 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5688 int wid
= FRAME_COLUMN_WIDTH (f
);
5689 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5690 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5694 int wid
= FRAME_COLUMN_WIDTH (f
);
5695 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5698 /* Now make the frame display the given font. */
5699 if (FRAME_MAC_WINDOW (f
) != 0)
5701 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5703 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5705 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5708 /* Don't change the size of a tip frame; there's no point in
5709 doing it because it's done in Fx_show_tip, and it leads to
5710 problems because the tip frame has no widget. */
5711 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5712 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5715 return build_string (fontp
->full_name
);
5718 /* Give frame F the fontset named FONTSETNAME as its default font, and
5719 return the full name of that fontset. FONTSETNAME may be a wildcard
5720 pattern; in that case, we choose some fontset that fits the pattern.
5721 The return value shows which fontset we chose. */
5724 x_new_fontset (f
, fontsetname
)
5728 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5734 if (FRAME_FONTSET (f
) == fontset
)
5735 /* This fontset is already set in frame F. There's nothing more
5737 return fontset_name (fontset
);
5739 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5741 if (!STRINGP (result
))
5742 /* Can't load ASCII font. */
5745 /* Since x_new_font doesn't update any fontset information, do it now. */
5746 FRAME_FONTSET (f
) = fontset
;
5748 return build_string (fontsetname
);
5752 /***********************************************************************
5753 TODO: W32 Input Methods
5754 ***********************************************************************/
5755 /* Listing missing functions from xterm.c helps diff stay in step.
5757 xim_destroy_callback (xim, client_data, call_data)
5758 xim_open_dpy (dpyinfo, resource_name)
5760 xim_instantiate_callback (display, client_data, call_data)
5761 xim_initialize (dpyinfo, resource_name)
5762 xim_close_dpy (dpyinfo)
5768 mac_get_window_bounds (f
, inner
, outer
)
5770 Rect
*inner
, *outer
;
5772 #if TARGET_API_MAC_CARBON
5773 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5774 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5775 #else /* not TARGET_API_MAC_CARBON */
5776 RgnHandle region
= NewRgn ();
5778 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5779 *inner
= (*region
)->rgnBBox
;
5780 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5781 *outer
= (*region
)->rgnBBox
;
5782 DisposeRgn (region
);
5783 #endif /* not TARGET_API_MAC_CARBON */
5788 /* Calculate the absolute position in frame F
5789 from its current recorded position values and gravity. */
5792 x_calc_absolute_position (f
)
5795 int width_diff
= 0, height_diff
= 0;
5796 int flags
= f
->size_hint_flags
;
5799 /* We have nothing to do if the current position
5800 is already for the top-left corner. */
5801 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5804 /* Find the offsets of the outside upper-left corner of
5805 the inner window, with respect to the outer window. */
5806 mac_get_window_bounds (f
, &inner
, &outer
);
5808 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5809 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5811 /* Treat negative positions as relative to the leftmost bottommost
5812 position that fits on the screen. */
5813 if (flags
& XNegative
)
5814 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5816 - FRAME_PIXEL_WIDTH (f
)
5819 if (flags
& YNegative
)
5820 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5822 - FRAME_PIXEL_HEIGHT (f
)
5825 /* The left_pos and top_pos
5826 are now relative to the top and left screen edges,
5827 so the flags should correspond. */
5828 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5831 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5832 to really change the position, and 0 when calling from
5833 x_make_frame_visible (in that case, XOFF and YOFF are the current
5834 position values). It is -1 when calling from x_set_frame_parameters,
5835 which means, do adjust for borders but don't change the gravity. */
5838 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5840 register int xoff
, yoff
;
5843 if (change_gravity
> 0)
5847 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5849 f
->size_hint_flags
|= XNegative
;
5851 f
->size_hint_flags
|= YNegative
;
5852 f
->win_gravity
= NorthWestGravity
;
5854 x_calc_absolute_position (f
);
5857 x_wm_set_size_hint (f
, (long) 0, 0);
5859 #if TARGET_API_MAC_CARBON
5860 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5861 /* If the title bar is completely outside the screen, adjust the
5863 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5864 kWindowConstrainMoveRegardlessOfFit
5865 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5866 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5869 Rect inner
, outer
, screen_rect
, dummy
;
5870 RgnHandle region
= NewRgn ();
5872 mac_get_window_bounds (f
, &inner
, &outer
);
5873 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5874 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5875 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5876 f
->top_pos
+ f
->y_pixels_diff
, false);
5878 /* If the title bar is completely outside the screen, adjust the
5879 position. The variable `outer' holds the title bar rectangle.
5880 The variable `inner' holds slightly smaller one than `outer',
5881 so that the calculation of overlapping may not become too
5883 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5884 outer
= (*region
)->rgnBBox
;
5885 DisposeRgn (region
);
5887 InsetRect (&inner
, 8, 8);
5888 screen_rect
= qd
.screenBits
.bounds
;
5889 screen_rect
.top
+= GetMBarHeight ();
5891 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5893 if (inner
.right
<= screen_rect
.left
)
5894 f
->left_pos
= screen_rect
.left
;
5895 else if (inner
.left
>= screen_rect
.right
)
5896 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5898 if (inner
.bottom
<= screen_rect
.top
)
5899 f
->top_pos
= screen_rect
.top
;
5900 else if (inner
.top
>= screen_rect
.bottom
)
5901 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5903 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5904 f
->top_pos
+ f
->y_pixels_diff
, false);
5912 /* Call this to change the size of frame F's x-window.
5913 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5914 for this size change and subsequent size changes.
5915 Otherwise we leave the window gravity unchanged. */
5918 x_set_window_size (f
, change_gravity
, cols
, rows
)
5923 int pixelwidth
, pixelheight
;
5927 check_frame_size (f
, &rows
, &cols
);
5928 f
->scroll_bar_actual_width
5929 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5931 compute_fringe_widths (f
, 0);
5933 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5934 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5936 f
->win_gravity
= NorthWestGravity
;
5937 x_wm_set_size_hint (f
, (long) 0, 0);
5939 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5940 #if TARGET_API_MAC_CARBON
5941 if (f
->output_data
.mac
->hourglass_control
)
5944 mac_prepare_for_quickdraw (f
);
5946 MoveControl (f
->output_data
.mac
->hourglass_control
,
5947 pixelwidth
- HOURGLASS_WIDTH
, 0);
5951 /* Now, strictly speaking, we can't be sure that this is accurate,
5952 but the window manager will get around to dealing with the size
5953 change request eventually, and we'll hear how it went when the
5954 ConfigureNotify event gets here.
5956 We could just not bother storing any of this information here,
5957 and let the ConfigureNotify event set everything up, but that
5958 might be kind of confusing to the Lisp code, since size changes
5959 wouldn't be reported in the frame parameters until some random
5960 point in the future when the ConfigureNotify event arrives.
5962 We pass 1 for DELAY since we can't run Lisp code inside of
5964 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5965 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5966 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5968 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5969 receive in the ConfigureNotify event; if we get what we asked
5970 for, then the event won't cause the screen to become garbaged, so
5971 we have to make sure to do it here. */
5972 SET_FRAME_GARBAGED (f
);
5974 XFlush (FRAME_X_DISPLAY (f
));
5976 /* If cursor was outside the new size, mark it as off. */
5977 mark_window_cursors_off (XWINDOW (f
->root_window
));
5979 /* Clear out any recollection of where the mouse highlighting was,
5980 since it might be in a place that's outside the new frame size.
5981 Actually checking whether it is outside is a pain in the neck,
5982 so don't try--just let the highlighting be done afresh with new size. */
5983 cancel_mouse_face (f
);
5988 /* Mouse warping. */
5990 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5993 x_set_mouse_position (f
, x
, y
)
5999 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6000 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6002 if (pix_x
< 0) pix_x
= 0;
6003 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6005 if (pix_y
< 0) pix_y
= 0;
6006 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6008 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6012 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6016 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
6019 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
6020 0, 0, 0, 0, pix_x
, pix_y
);
6025 /* focus shifting, raising and lowering. */
6028 x_focus_on_frame (f
)
6031 #if 0 /* This proves to be unpleasant. */
6035 /* I don't think that the ICCCM allows programs to do things like this
6036 without the interaction of the window manager. Whatever you end up
6037 doing with this code, do it to x_unfocus_frame too. */
6038 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6039 RevertToPointerRoot
, CurrentTime
);
6049 /* Raise frame F. */
6055 if (f
->async_visible
)
6058 BringToFront (FRAME_MAC_WINDOW (f
));
6063 /* Lower frame F. */
6069 if (f
->async_visible
)
6072 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
6078 XTframe_raise_lower (f
, raise_flag
)
6088 /* Change of visibility. */
6091 mac_handle_visibility_change (f
)
6094 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6095 int visible
= 0, iconified
= 0;
6096 struct input_event buf
;
6098 if (IsWindowVisible (wp
))
6099 if (IsWindowCollapsed (wp
))
6104 if (!f
->async_visible
&& visible
)
6108 /* wait_reading_process_output will notice this and update
6109 the frame's display structures. If we were made
6110 invisible, we should not set garbaged, because that stops
6111 redrawing on Update events. */
6112 SET_FRAME_GARBAGED (f
);
6115 buf
.kind
= DEICONIFY_EVENT
;
6116 XSETFRAME (buf
.frame_or_window
, f
);
6117 kbd_buffer_store_event (&buf
);
6119 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6120 /* Force a redisplay sooner or later to update the
6121 frame titles in case this is the second frame. */
6122 record_asynch_buffer_change ();
6124 else if (f
->async_visible
&& !visible
)
6128 buf
.kind
= ICONIFY_EVENT
;
6129 XSETFRAME (buf
.frame_or_window
, f
);
6130 kbd_buffer_store_event (&buf
);
6133 f
->async_visible
= visible
;
6134 f
->async_iconified
= iconified
;
6137 /* This tries to wait until the frame is really visible.
6138 However, if the window manager asks the user where to position
6139 the frame, this will return before the user finishes doing that.
6140 The frame will not actually be visible at that time,
6141 but it will become visible later when the window manager
6142 finishes with it. */
6145 x_make_frame_visible (f
)
6149 int original_top
, original_left
;
6153 if (! FRAME_VISIBLE_P (f
))
6155 /* We test FRAME_GARBAGED_P here to make sure we don't
6156 call x_set_offset a second time
6157 if we get to x_make_frame_visible a second time
6158 before the window gets really visible. */
6159 if (! FRAME_ICONIFIED_P (f
)
6160 && ! f
->output_data
.mac
->asked_for_visible
)
6161 #if TARGET_API_MAC_CARBON
6162 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6164 struct frame
*sf
= SELECTED_FRAME ();
6165 if (!FRAME_MAC_P (sf
))
6166 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6167 kWindowCenterOnMainScreen
);
6169 RepositionWindow (FRAME_MAC_WINDOW (f
),
6170 FRAME_MAC_WINDOW (sf
),
6171 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6172 kWindowCascadeStartAtParentWindowScreen
6174 kWindowCascadeOnParentWindowScreen
6177 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6181 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6183 f
->output_data
.mac
->asked_for_visible
= 1;
6185 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6186 ShowWindow (FRAME_MAC_WINDOW (f
));
6189 XFlush (FRAME_MAC_DISPLAY (f
));
6191 /* Synchronize to ensure Emacs knows the frame is visible
6192 before we do anything else. We do this loop with input not blocked
6193 so that incoming events are handled. */
6198 /* This must come after we set COUNT. */
6201 XSETFRAME (frame
, f
);
6203 /* Wait until the frame is visible. Process X events until a
6204 MapNotify event has been seen, or until we think we won't get a
6205 MapNotify at all.. */
6206 for (count
= input_signal_count
+ 10;
6207 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6209 /* Force processing of queued events. */
6212 /* Machines that do polling rather than SIGIO have been
6213 observed to go into a busy-wait here. So we'll fake an
6214 alarm signal to let the handler know that there's something
6215 to be read. We used to raise a real alarm, but it seems
6216 that the handler isn't always enabled here. This is
6218 if (input_polling_used ())
6220 /* It could be confusing if a real alarm arrives while
6221 processing the fake one. Turn it off and let the
6222 handler reset it. */
6223 extern void poll_for_input_1
P_ ((void));
6224 int old_poll_suppress_count
= poll_suppress_count
;
6225 poll_suppress_count
= 1;
6226 poll_for_input_1 ();
6227 poll_suppress_count
= old_poll_suppress_count
;
6230 /* See if a MapNotify event has been processed. */
6231 FRAME_SAMPLE_VISIBILITY (f
);
6236 /* Change from mapped state to withdrawn state. */
6238 /* Make the frame visible (mapped and not iconified). */
6241 x_make_frame_invisible (f
)
6244 /* A deactivate event does not occur when the last visible frame is
6245 made invisible. So if we clear the highlight here, it will not
6246 be rehighlighted when it is made visible. */
6248 /* Don't keep the highlight on an invisible frame. */
6249 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6250 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6255 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6256 that the current position of the window is user-specified, rather than
6257 program-specified, so that when the window is mapped again, it will be
6258 placed at the same location, without forcing the user to position it
6259 by hand again (they have already done that once for this window.) */
6260 x_wm_set_size_hint (f
, (long) 0, 1);
6262 HideWindow (FRAME_MAC_WINDOW (f
));
6266 #if !USE_CARBON_EVENTS
6267 mac_handle_visibility_change (f
);
6271 /* Change window state from mapped to iconified. */
6279 /* A deactivate event does not occur when the last visible frame is
6280 iconified. So if we clear the highlight here, it will not be
6281 rehighlighted when it is deiconified. */
6283 /* Don't keep the highlight on an invisible frame. */
6284 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6285 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6288 if (f
->async_iconified
)
6293 FRAME_SAMPLE_VISIBILITY (f
);
6295 if (! FRAME_VISIBLE_P (f
))
6296 ShowWindow (FRAME_MAC_WINDOW (f
));
6298 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6303 error ("Can't notify window manager of iconification");
6305 #if !USE_CARBON_EVENTS
6306 mac_handle_visibility_change (f
);
6311 /* Free X resources of frame F. */
6314 x_free_frame_resources (f
)
6317 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6318 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6322 if (wp
!= tip_window
)
6323 remove_window_handler (wp
);
6326 if (wp
== tip_window
)
6327 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6328 closed' event. So we reset tip_window here. */
6331 free_frame_menubar (f
);
6333 if (FRAME_FACE_CACHE (f
))
6334 free_frame_faces (f
);
6338 if (FRAME_SIZE_HINTS (f
))
6339 xfree (FRAME_SIZE_HINTS (f
));
6341 xfree (f
->output_data
.mac
);
6342 f
->output_data
.mac
= NULL
;
6344 if (f
== dpyinfo
->x_focus_frame
)
6345 dpyinfo
->x_focus_frame
= 0;
6346 if (f
== dpyinfo
->x_focus_event_frame
)
6347 dpyinfo
->x_focus_event_frame
= 0;
6348 if (f
== dpyinfo
->x_highlight_frame
)
6349 dpyinfo
->x_highlight_frame
= 0;
6351 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6353 dpyinfo
->mouse_face_beg_row
6354 = dpyinfo
->mouse_face_beg_col
= -1;
6355 dpyinfo
->mouse_face_end_row
6356 = dpyinfo
->mouse_face_end_col
= -1;
6357 dpyinfo
->mouse_face_window
= Qnil
;
6358 dpyinfo
->mouse_face_deferred_gc
= 0;
6359 dpyinfo
->mouse_face_mouse_frame
= 0;
6366 /* Destroy the X window of frame F. */
6369 x_destroy_window (f
)
6372 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6374 x_free_frame_resources (f
);
6376 dpyinfo
->reference_count
--;
6380 /* Setting window manager hints. */
6382 /* Set the normal size hints for the window manager, for frame F.
6383 FLAGS is the flags word to use--or 0 meaning preserve the flags
6384 that the window now has.
6385 If USER_POSITION is nonzero, we set the USPosition
6386 flag (this is useful when FLAGS is 0). */
6388 x_wm_set_size_hint (f
, flags
, user_position
)
6393 int base_width
, base_height
, width_inc
, height_inc
;
6394 int min_rows
= 0, min_cols
= 0;
6395 XSizeHints
*size_hints
;
6397 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6398 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6399 width_inc
= FRAME_COLUMN_WIDTH (f
);
6400 height_inc
= FRAME_LINE_HEIGHT (f
);
6402 check_frame_size (f
, &min_rows
, &min_cols
);
6404 size_hints
= FRAME_SIZE_HINTS (f
);
6405 if (size_hints
== NULL
)
6407 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6408 bzero (size_hints
, sizeof (XSizeHints
));
6411 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6412 size_hints
->width_inc
= width_inc
;
6413 size_hints
->height_inc
= height_inc
;
6414 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6415 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6416 size_hints
->base_width
= base_width
;
6417 size_hints
->base_height
= base_height
;
6420 size_hints
->flags
= flags
;
6421 else if (user_position
)
6423 size_hints
->flags
&= ~ PPosition
;
6424 size_hints
->flags
|= USPosition
;
6428 #if 0 /* MAC_TODO: hide application instead of iconify? */
6429 /* Used for IconicState or NormalState */
6432 x_wm_set_window_state (f
, state
)
6436 #ifdef USE_X_TOOLKIT
6439 XtSetArg (al
[0], XtNinitialState
, state
);
6440 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6441 #else /* not USE_X_TOOLKIT */
6442 Window window
= FRAME_X_WINDOW (f
);
6444 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6445 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6447 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6448 #endif /* not USE_X_TOOLKIT */
6452 x_wm_set_icon_pixmap (f
, pixmap_id
)
6458 #ifndef USE_X_TOOLKIT
6459 Window window
= FRAME_X_WINDOW (f
);
6464 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6465 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6469 /* It seems there is no way to turn off use of an icon pixmap.
6470 The following line does it, only if no icon has yet been created,
6471 for some window managers. But with mwm it crashes.
6472 Some people say it should clear the IconPixmapHint bit in this case,
6473 but that doesn't work, and the X consortium said it isn't the
6474 right thing at all. Since there is no way to win,
6475 best to explicitly give up. */
6477 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6483 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6487 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6488 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6491 #else /* not USE_X_TOOLKIT */
6493 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6494 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6496 #endif /* not USE_X_TOOLKIT */
6499 #endif /* MAC_TODO */
6502 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6506 #if 0 /* MAC_TODO: no icons on Mac */
6507 #ifdef USE_X_TOOLKIT
6508 Window window
= XtWindow (f
->output_data
.x
->widget
);
6510 Window window
= FRAME_X_WINDOW (f
);
6513 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6514 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6515 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6517 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6518 #endif /* MAC_TODO */
6522 /***********************************************************************
6524 ***********************************************************************/
6526 /* An XLFD pattern is divided into blocks delimited by '*'. This
6527 structure holds information for each block. */
6528 struct xlfdpat_block
6530 /* Length of the pattern string in this block. Non-zero except for
6531 the first and the last blocks. */
6534 /* Pattern string except the last character in this block. The last
6535 character is replaced with NUL in order to use it as a
6537 unsigned char *pattern
;
6539 /* Last character of the pattern string. Must not be '?'. */
6540 unsigned char last_char
;
6542 /* One of the tables for the Boyer-Moore string search. It
6543 specifies the number of positions to proceed for each character
6544 with which the match fails. */
6547 /* The skip value for the last character in the above `skip' is
6548 assigned to `infinity' in order to simplify a loop condition.
6549 The original value is saved here. */
6555 /* Normalized pattern string. "Normalized" means that capital
6556 letters are lowered, blocks are not empty except the first and
6557 the last ones, and trailing '?'s in a block that is not the last
6558 one are moved to the next one. The last character in each block
6559 is replaced with NUL. */
6562 /* Number of characters except '*'s and trailing '?'s in the
6563 normalized pattern string. */
6566 /* Number of trailing '?'s in the normalized pattern string. */
6567 int trailing_anychars
;
6569 /* Number of blocks and information for each block. The latter is
6570 NULL if the pattern is exact (no '*' or '?' in it). */
6572 struct xlfdpat_block
*blocks
;
6576 xlfdpat_destroy (pat
)
6577 struct xlfdpat
*pat
;
6584 xfree (pat
->blocks
);
6591 static struct xlfdpat
*
6592 xlfdpat_create (pattern
)
6595 struct xlfdpat
*pat
;
6596 int nblocks
, i
, skip
;
6597 unsigned char last_char
, *p
, *q
, *anychar_head
;
6598 struct xlfdpat_block
*blk
;
6600 pat
= xmalloc (sizeof (struct xlfdpat
));
6604 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6605 if (pat
->buf
== NULL
)
6608 /* Normalize the pattern string and store it to `pat->buf'. */
6610 anychar_head
= NULL
;
6613 for (p
= pattern
; *p
; p
++)
6615 unsigned char c
= *p
;
6618 if (last_char
== '*')
6619 /* ...a** -> ...a* */
6623 if (last_char
== '?')
6624 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6625 /* ...*??* -> ...*?? */
6628 /* ...a??* -> ...a*?? */
6630 *anychar_head
++ = '*';
6637 if (last_char
!= '?')
6641 /* On Mac OS X 10.3, tolower also converts non-ASCII
6642 characters for some locales. */
6646 *q
++ = last_char
= c
;
6650 pat
->nblocks
= nblocks
;
6651 if (last_char
!= '?')
6652 pat
->trailing_anychars
= 0;
6655 pat
->trailing_anychars
= q
- anychar_head
;
6658 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6660 if (anychar_head
== NULL
&& nblocks
== 1)
6662 /* The pattern is exact. */
6667 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6668 if (pat
->blocks
== NULL
)
6671 /* Divide the normalized pattern into blocks. */
6673 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6678 blk
->len
= p
- blk
->pattern
;
6682 blk
->len
= q
- blk
->pattern
;
6684 /* Setup a table for the Boyer-Moore string search. */
6685 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6688 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6689 blk
->pattern
[blk
->len
- 1] = '\0';
6691 for (skip
= 1; skip
< blk
->len
; skip
++)
6692 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6695 for (i
= 0; i
< 256; i
++)
6696 blk
->skip
[i
] = skip
;
6698 p
= blk
->pattern
+ (blk
->len
- skip
);
6700 blk
->skip
[*p
++] = skip
;
6702 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6708 xlfdpat_destroy (pat
);
6713 xlfdpat_exact_p (pat
)
6714 struct xlfdpat
*pat
;
6716 return pat
->blocks
== NULL
;
6719 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6720 that the pattern in *BLK matches with its prefix. Return NULL
6721 there is no such strings. STRING must be lowered in advance. */
6724 xlfdpat_block_match_1 (blk
, string
, start_max
)
6725 struct xlfdpat_block
*blk
;
6726 unsigned char *string
;
6729 int start
, infinity
;
6730 unsigned char *p
, *s
;
6732 xassert (blk
->len
> 0);
6733 xassert (start_max
+ blk
->len
<= strlen (string
));
6734 xassert (blk
->last_char
!= '?');
6736 /* See the comments in the function `boyer_moore' (search.c) for the
6737 use of `infinity'. */
6738 infinity
= start_max
+ blk
->len
+ 1;
6739 blk
->skip
[blk
->last_char
] = infinity
;
6744 /* Check the last character of the pattern. */
6745 s
= string
+ blk
->len
- 1;
6748 start
+= blk
->skip
[*(s
+ start
)];
6750 while (start
<= start_max
);
6752 if (start
< infinity
)
6753 /* Couldn't find the last character. */
6756 /* No less than `infinity' means we could find the last
6757 character at `s[start - infinity]'. */
6760 /* Check the remaining characters. We prefer making no-'?'
6761 cases faster because the use of '?' is really rare. */
6766 while (*p
++ == *s
++)
6769 while (*(p
- 1) == '?');
6771 if (*(p
- 1) == '\0')
6773 return string
+ start
;
6776 start
+= blk
->last_char_skip
;
6778 while (start
<= start_max
);
6783 #define xlfdpat_block_match(b, s, m) \
6784 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6785 : xlfdpat_block_match_1 (b, s, m))
6787 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6788 matches with STRING. STRING must be lowered in advance. */
6791 xlfdpat_match (pat
, string
)
6792 struct xlfdpat
*pat
;
6793 unsigned char *string
;
6795 int str_len
, nblocks
, i
, start_max
;
6796 struct xlfdpat_block
*blk
;
6799 xassert (pat
->nblocks
> 0);
6801 if (xlfdpat_exact_p (pat
))
6802 return strcmp (pat
->buf
, string
) == 0;
6804 /* The number of the characters in the string must not be smaller
6805 than that in the pattern. */
6806 str_len
= strlen (string
);
6807 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6810 /* Chop off the trailing '?'s. */
6811 str_len
-= pat
->trailing_anychars
;
6813 /* The last block. When it is non-empty, it must match at the end
6815 nblocks
= pat
->nblocks
;
6816 blk
= pat
->blocks
+ (nblocks
- 1);
6818 /* The last block is also the first one. */
6819 return (str_len
== blk
->len
6820 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6821 else if (blk
->len
!= 0)
6822 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6825 /* The first block. When it is non-empty, it must match at the
6826 beginning of the string. */
6830 s
= xlfdpat_block_match (blk
, string
, 0);
6833 string
= s
+ blk
->len
;
6836 /* The rest of the blocks. */
6837 start_max
= str_len
- pat
->nchars
;
6838 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6840 s
= xlfdpat_block_match (blk
, string
, start_max
);
6843 start_max
-= s
- string
;
6844 string
= s
+ blk
->len
;
6851 /***********************************************************************
6853 ***********************************************************************/
6855 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6858 x_get_font_info (f
, font_idx
)
6862 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6865 /* the global font name table */
6866 static char **font_name_table
= NULL
;
6867 static int font_name_table_size
= 0;
6868 static int font_name_count
= 0;
6870 /* Alist linking font family names to Font Manager font family
6871 references (which can also be used as QuickDraw font IDs). We use
6872 an alist because hash tables are not ready when the terminal frame
6873 for Mac OS Classic is created. */
6874 static Lisp_Object fm_font_family_alist
;
6876 /* Hash table linking font family names to ATSU font IDs. */
6877 static Lisp_Object atsu_font_id_hash
;
6880 /* Alist linking character set strings to Mac text encoding and Emacs
6882 static Lisp_Object Vmac_charset_info_alist
;
6885 create_text_encoding_info_alist ()
6887 Lisp_Object result
= Qnil
, rest
;
6889 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6891 Lisp_Object charset_info
= XCAR (rest
);
6892 Lisp_Object charset
, coding_system
, text_encoding
;
6893 Lisp_Object existing_info
;
6895 if (!(CONSP (charset_info
)
6896 && STRINGP (charset
= XCAR (charset_info
))
6897 && CONSP (XCDR (charset_info
))
6898 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6899 && CONSP (XCDR (XCDR (charset_info
)))
6900 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6903 existing_info
= assq_no_quit (text_encoding
, result
);
6904 if (NILP (existing_info
))
6905 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6908 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6909 XSETCDR (XCDR (existing_info
),
6910 Fcons (charset
, XCDR (XCDR (existing_info
))));
6918 decode_mac_font_name (name
, size
, coding_system
)
6921 Lisp_Object coding_system
;
6923 struct coding_system coding
;
6926 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6928 for (p
= name
; *p
; p
++)
6929 if (!isascii (*p
) || iscntrl (*p
))
6934 setup_coding_system (coding_system
, &coding
);
6935 coding
.src_multibyte
= 0;
6936 coding
.dst_multibyte
= 1;
6937 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6938 coding
.composing
= COMPOSITION_DISABLED
;
6939 buf
= (char *) alloca (size
);
6941 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6942 bcopy (buf
, name
, coding
.produced
);
6943 name
[coding
.produced
] = '\0';
6947 /* If there's just one occurrence of '-' in the family name, it is
6948 replaced with '_'. (More than one occurrence of '-' means a
6949 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6950 p
= strchr (name
, '-');
6951 if (p
&& strchr (p
+ 1, '-') == NULL
)
6954 for (p
= name
; *p
; p
++)
6955 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6956 for some locales. */
6963 mac_to_x_fontname (name
, size
, style
, charset
)
6971 char xf
[256], *result
;
6974 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6978 strcpy(foundry
, "Apple");
6979 strcpy(family
, name
);
6982 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6983 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6984 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6986 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6987 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6988 for (p
= result
; *p
; p
++)
6989 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6990 for some locales. */
6997 /* Parse fully-specified and instantiated X11 font spec XF, and store
6998 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6999 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7000 caller must allocate at least 256 and 32 bytes respectively. For
7001 ordinary Mac fonts, the value stored to FAMILY should just be their
7002 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7003 intlfonts collection contain their charset designation in their
7004 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7005 types of font names are handled accordingly. */
7007 const int kDefaultFontSize
= 12;
7010 parse_x_font_name (xf
, family
, size
, style
, charset
)
7016 Str31 foundry
, weight
;
7017 int point_size
, avgwidth
;
7020 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7021 foundry
, family
, weight
, slant
, size
,
7022 &point_size
, &avgwidth
, charset
) != 8
7023 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7024 foundry
, family
, weight
, slant
, size
,
7025 &point_size
, &avgwidth
, charset
) != 8)
7031 *size
= point_size
/ 10;
7032 else if (avgwidth
> 0)
7033 *size
= avgwidth
/ 10;
7036 *size
= kDefaultFontSize
;
7039 if (strcmp (weight
, "bold") == 0)
7044 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
7046 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
7048 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
7050 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7051 but take overlap into account. */
7052 memmove (family
+ foundry_len
+ 1, family
, family_len
);
7053 memcpy (family
, foundry
, foundry_len
);
7054 family
[foundry_len
] = '-';
7055 family
[foundry_len
+ 1 + family_len
] = '-';
7056 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
7062 for (p
= family
; *p
; p
++)
7063 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7064 for some locales. */
7073 add_font_name_table_entry (char *font_name
)
7075 if (font_name_table_size
== 0)
7077 font_name_table_size
= 256;
7078 font_name_table
= (char **)
7079 xmalloc (font_name_table_size
* sizeof (char *));
7081 else if (font_name_count
+ 1 >= font_name_table_size
)
7083 font_name_table_size
*= 2;
7084 font_name_table
= (char **)
7085 xrealloc (font_name_table
,
7086 font_name_table_size
* sizeof (char *));
7089 font_name_table
[font_name_count
++] = font_name
;
7092 /* Sets up the table font_name_table to contain the list of all fonts
7093 in the system the first time the table is used so that the Resource
7094 Manager need not be accessed every time this information is
7098 init_font_name_table ()
7100 #if TARGET_API_MAC_CARBON
7101 FMFontFamilyIterator ffi
;
7102 FMFontFamilyInstanceIterator ffii
;
7104 Lisp_Object text_encoding_info_alist
;
7105 struct gcpro gcpro1
;
7107 text_encoding_info_alist
= create_text_encoding_info_alist ();
7110 #if USE_CG_TEXT_DRAWING
7111 init_cg_text_anti_aliasing_threshold ();
7113 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
7114 text_encoding_info_alist
)))
7117 ItemCount nfonts
, i
;
7118 ATSUFontID
*font_ids
= NULL
;
7119 Ptr name
, prev_name
= NULL
;
7123 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
7124 make_float (DEFAULT_REHASH_SIZE
),
7125 make_float (DEFAULT_REHASH_THRESHOLD
),
7127 err
= ATSUFontCount (&nfonts
);
7129 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
7131 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
7133 for (i
= 0; i
< nfonts
; i
++)
7135 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7136 kFontMacintoshPlatform
, kFontNoScript
,
7137 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
7140 name
= xmalloc (name_len
+ 1);
7143 name
[name_len
] = '\0';
7144 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7145 kFontMacintoshPlatform
, kFontNoScript
,
7146 kFontNoLanguage
, name_len
, name
,
7149 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
7152 && (prev_name
== NULL
7153 || strcmp (name
, prev_name
) != 0))
7155 static char *cs
= "iso10646-1";
7157 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
7159 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
7161 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
7163 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
7164 italic
| bold
, cs
));
7165 Fputhash (make_unibyte_string (name
, name_len
),
7166 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
7180 /* Create a dummy instance iterator here to avoid creating and
7181 destroying it in the loop. */
7182 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7184 /* Create an iterator to enumerate the font families. */
7185 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7188 FMDisposeFontFamilyInstanceIterator (&ffii
);
7192 GCPRO1 (text_encoding_info_alist
);
7194 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7200 TextEncoding encoding
;
7201 TextEncodingBase sc
;
7202 Lisp_Object text_encoding_info
;
7204 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7210 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7212 sc
= GetTextEncodingBase (encoding
);
7213 text_encoding_info
= assq_no_quit (make_number (sc
),
7214 text_encoding_info_alist
);
7215 if (NILP (text_encoding_info
))
7216 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7217 text_encoding_info_alist
);
7218 decode_mac_font_name (name
, sizeof (name
),
7219 XCAR (XCDR (text_encoding_info
)));
7220 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7222 fm_font_family_alist
);
7224 /* Point the instance iterator at the current font family. */
7225 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7228 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7231 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7233 if (size
> 0 || style
== normal
)
7234 for (; !NILP (rest
); rest
= XCDR (rest
))
7236 char *cs
= SDATA (XCAR (rest
));
7240 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7242 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7244 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7246 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7252 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7261 /* Dispose of the iterators. */
7262 FMDisposeFontFamilyIterator (&ffi
);
7263 FMDisposeFontFamilyInstanceIterator (&ffii
);
7264 #else /* !TARGET_API_MAC_CARBON */
7266 SInt16 fontnum
, old_fontnum
;
7267 int num_mac_fonts
= CountResources('FOND');
7269 Handle font_handle
, font_handle_2
;
7270 short id
, scriptcode
;
7273 struct FontAssoc
*fat
;
7274 struct AsscEntry
*assc_entry
;
7275 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
7276 struct gcpro gcpro1
;
7278 GetPort (&port
); /* save the current font number used */
7279 old_fontnum
= port
->txFont
;
7281 text_encoding_info_alist
= create_text_encoding_info_alist ();
7283 GCPRO1 (text_encoding_info_alist
);
7285 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7287 font_handle
= GetIndResource ('FOND', i
);
7291 GetResInfo (font_handle
, &id
, &type
, name
);
7292 GetFNum (name
, &fontnum
);
7298 scriptcode
= FontToScript (fontnum
);
7299 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7300 text_encoding_info_alist
);
7301 if (NILP (text_encoding_info
))
7302 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7303 text_encoding_info_alist
);
7304 decode_mac_font_name (name
, sizeof (name
),
7305 XCAR (XCDR (text_encoding_info
)));
7306 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7307 make_number (fontnum
)),
7308 fm_font_family_alist
);
7311 HLock (font_handle
);
7313 if (GetResourceSizeOnDisk (font_handle
)
7314 >= sizeof (struct FamRec
))
7316 fat
= (struct FontAssoc
*) (*font_handle
7317 + sizeof (struct FamRec
));
7319 = (struct AsscEntry
*) (*font_handle
7320 + sizeof (struct FamRec
)
7321 + sizeof (struct FontAssoc
));
7323 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7325 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7327 for (; !NILP (rest
); rest
= XCDR (rest
))
7329 char *cs
= SDATA (XCAR (rest
));
7331 add_font_name_table_entry (mac_to_x_fontname (name
,
7332 assc_entry
->fontSize
,
7333 assc_entry
->fontStyle
,
7339 HUnlock (font_handle
);
7340 font_handle_2
= GetNextFOND (font_handle
);
7341 ReleaseResource (font_handle
);
7342 font_handle
= font_handle_2
;
7344 while (ResError () == noErr
&& font_handle
);
7349 TextFont (old_fontnum
);
7350 #endif /* !TARGET_API_MAC_CARBON */
7355 mac_clear_font_name_table ()
7359 for (i
= 0; i
< font_name_count
; i
++)
7360 xfree (font_name_table
[i
]);
7361 xfree (font_name_table
);
7362 font_name_table
= NULL
;
7363 font_name_table_size
= font_name_count
= 0;
7364 fm_font_family_alist
= Qnil
;
7368 enum xlfd_scalable_field_index
7370 XLFD_SCL_PIXEL_SIZE
,
7371 XLFD_SCL_POINT_SIZE
,
7376 static int xlfd_scalable_fields
[] =
7385 mac_do_list_fonts (pattern
, maxnames
)
7390 Lisp_Object font_list
= Qnil
;
7391 struct xlfdpat
*pat
;
7393 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7396 if (font_name_table
== NULL
) /* Initialize when first used. */
7397 init_font_name_table ();
7399 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7402 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7403 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7404 fonts are scaled according to the specified size. */
7407 field
= xlfd_scalable_fields
;
7415 if ('0' <= *ptr
&& *ptr
<= '9')
7417 *val
= *ptr
++ - '0';
7418 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7419 *val
= *val
* 10 + *ptr
++ - '0';
7426 ptr
= strchr (ptr
, '-');
7429 while (ptr
&& i
< 14);
7431 if (i
== 14 && ptr
== NULL
)
7433 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7434 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7435 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7436 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7438 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7439 scl_val
[XLFD_SCL_POINT_SIZE
] =
7440 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7441 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7443 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7444 scl_val
[XLFD_SCL_AVGWIDTH
] =
7445 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7446 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7450 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7452 pat
= xlfdpat_create (pattern
);
7456 exact
= xlfdpat_exact_p (pat
);
7458 for (i
= 0; i
< font_name_count
; i
++)
7460 if (xlfdpat_match (pat
, font_name_table
[i
]))
7462 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7463 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7466 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7467 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7469 int former_len
= ptr
- font_name_table
[i
];
7471 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7474 memcpy (scaled
, font_name_table
[i
], former_len
);
7475 sprintf (scaled
+ former_len
,
7476 "-%d-%d-72-72-m-%d-%s",
7477 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7478 scl_val
[XLFD_SCL_POINT_SIZE
],
7479 scl_val
[XLFD_SCL_AVGWIDTH
],
7480 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7482 if (xlfdpat_match (pat
, scaled
))
7484 font_list
= Fcons (build_string (scaled
), font_list
);
7486 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7494 xlfdpat_destroy (pat
);
7499 /* Return a list of names of available fonts matching PATTERN on frame F.
7501 Frame F null means we have not yet created any frame on Mac, and
7502 consult the first display in x_display_list. MAXNAMES sets a limit
7503 on how many fonts to match. */
7506 x_list_fonts (f
, pattern
, size
, maxnames
)
7508 Lisp_Object pattern
;
7511 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7512 struct mac_display_info
*dpyinfo
7513 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7515 xassert (size
<= 0);
7517 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7518 if (NILP (patterns
))
7519 patterns
= Fcons (pattern
, Qnil
);
7521 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7523 pattern
= XCAR (patterns
);
7525 if (!STRINGP (pattern
))
7528 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7529 key
= Fcons (pattern
, make_number (maxnames
));
7531 list
= Fassoc (key
, tem
);
7534 list
= Fcdr_safe (list
);
7535 /* We have a cashed list. Don't have to get the list again. */
7540 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7543 /* MAC_TODO: add code for matching outline fonts here */
7545 /* Now store the result in the cache. */
7546 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7547 Fcons (Fcons (key
, list
),
7548 XCAR (XCDR (dpyinfo
->name_list_element
))));
7551 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7560 /* Check that FONT is valid on frame F. It is if it can be found in F's
7564 x_check_font (f
, font
)
7569 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7571 xassert (font
!= NULL
);
7573 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7574 if (dpyinfo
->font_table
[i
].name
7575 && font
== dpyinfo
->font_table
[i
].font
)
7578 xassert (i
< dpyinfo
->n_fonts
);
7581 #endif /* GLYPH_DEBUG != 0 */
7583 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7584 Note: There are (broken) X fonts out there with invalid XFontStruct
7585 min_bounds contents. For example, handa@etl.go.jp reports that
7586 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7587 have font->min_bounds.width == 0. */
7590 x_font_min_bounds (font
, w
, h
)
7591 MacFontStruct
*font
;
7594 *h
= FONT_HEIGHT (font
);
7595 *w
= font
->min_bounds
.width
;
7599 /* Compute the smallest character width and smallest font height over
7600 all fonts available on frame F. Set the members smallest_char_width
7601 and smallest_font_height in F's x_display_info structure to
7602 the values computed. Value is non-zero if smallest_font_height or
7603 smallest_char_width become smaller than they were before. */
7606 x_compute_min_glyph_bounds (f
)
7610 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7611 MacFontStruct
*font
;
7612 int old_width
= dpyinfo
->smallest_char_width
;
7613 int old_height
= dpyinfo
->smallest_font_height
;
7615 dpyinfo
->smallest_font_height
= 100000;
7616 dpyinfo
->smallest_char_width
= 100000;
7618 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7619 if (dpyinfo
->font_table
[i
].name
)
7621 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7624 font
= (MacFontStruct
*) fontp
->font
;
7625 xassert (font
!= (MacFontStruct
*) ~0);
7626 x_font_min_bounds (font
, &w
, &h
);
7628 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7629 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7632 xassert (dpyinfo
->smallest_char_width
> 0
7633 && dpyinfo
->smallest_font_height
> 0);
7635 return (dpyinfo
->n_fonts
== 1
7636 || dpyinfo
->smallest_char_width
< old_width
7637 || dpyinfo
->smallest_font_height
< old_height
);
7641 /* Determine whether given string is a fully-specified XLFD: all 14
7642 fields are present, none is '*'. */
7645 is_fully_specified_xlfd (char *p
)
7653 for (i
= 0; i
< 13; i
++)
7655 q
= strchr (p
+ 1, '-');
7658 if (q
- p
== 2 && *(p
+ 1) == '*')
7663 if (strchr (p
+ 1, '-') != NULL
)
7666 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7673 /* XLoadQueryFont creates and returns an internal representation for a
7674 font in a MacFontStruct struct. There is really no concept
7675 corresponding to "loading" a font on the Mac. But we check its
7676 existence and find the font number and all other information for it
7677 and store them in the returned MacFontStruct. */
7679 static MacFontStruct
*
7680 XLoadQueryFont (Display
*dpy
, char *fontname
)
7688 static ATSUFontID font_id
;
7689 ATSUStyle mac_style
= NULL
;
7692 #if TARGET_API_MAC_CARBON
7693 TextEncoding encoding
;
7698 MacFontStruct
*font
;
7699 XCharStruct
*space_bounds
= NULL
, *pcm
;
7701 if (is_fully_specified_xlfd (fontname
))
7705 Lisp_Object matched_fonts
;
7707 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7708 if (NILP (matched_fonts
))
7710 name
= SDATA (XCAR (matched_fonts
));
7713 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7717 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7720 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7721 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7722 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7723 sizeof (Boolean
), sizeof (Boolean
)};
7724 static Fixed size_fixed
;
7725 static Boolean bold_p
, italic_p
;
7726 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7727 &bold_p
, &italic_p
};
7728 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
,
7730 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
,
7731 kDecomposeDiacriticsSelector
};
7732 Lisp_Object font_id_cons
;
7734 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7735 atsu_font_id_hash
, Qnil
);
7736 if (NILP (font_id_cons
))
7738 font_id
= cons_to_long (font_id_cons
);
7739 size_fixed
= Long2Fix (size
);
7740 bold_p
= (fontface
& bold
) != 0;
7741 italic_p
= (fontface
& italic
) != 0;
7742 err
= ATSUCreateStyle (&mac_style
);
7745 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7749 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7750 tags
, sizes
, values
);
7752 scriptcode
= kTextEncodingMacUnicode
;
7757 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7761 fontnum
= XINT (XCDR (tmp
));
7762 #if TARGET_API_MAC_CARBON
7763 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7765 scriptcode
= GetTextEncodingBase (encoding
);
7767 scriptcode
= FontToScript (fontnum
);
7771 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7773 font
->mac_fontnum
= fontnum
;
7774 font
->mac_fontsize
= size
;
7775 font
->mac_fontface
= fontface
;
7776 font
->mac_scriptcode
= scriptcode
;
7778 font
->mac_style
= mac_style
;
7779 #if USE_CG_TEXT_DRAWING
7780 font
->cg_font
= NULL
;
7781 font
->cg_glyphs
= NULL
;
7785 /* Apple Japanese (SJIS) font is listed as both
7786 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7787 (Roman script) in init_font_name_table (). The latter should be
7788 treated as a one-byte font. */
7789 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7790 font
->mac_scriptcode
= smRoman
;
7792 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7795 if (font
->mac_style
)
7800 font
->min_byte1
= 0;
7801 font
->max_byte1
= 0xff;
7802 font
->min_char_or_byte2
= 0;
7803 font
->max_char_or_byte2
= 0xff;
7805 font
->bounds
.rows
= xmalloc (sizeof (XCharStructRow
*) * 0x100);
7806 if (font
->bounds
.rows
== NULL
)
7808 mac_unload_font (&one_mac_display_info
, font
);
7811 bzero (font
->bounds
.rows
, sizeof (XCharStructRow
*) * 0x100);
7812 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStructRow
));
7813 if (font
->bounds
.rows
[0] == NULL
)
7815 mac_unload_font (&one_mac_display_info
, font
);
7818 bzero (font
->bounds
.rows
[0], sizeof (XCharStructRow
));
7820 #if USE_CG_TEXT_DRAWING
7822 FMFontFamily font_family
;
7824 ATSFontRef ats_font
;
7826 err
= FMGetFontFamilyInstanceFromFont (font_id
, &font_family
, &style
);
7828 err
= FMGetFontFromFontFamilyInstance (font_family
, fontface
,
7830 /* Use CG text drawing if italic/bold is not synthesized. */
7831 if (err
== noErr
&& style
== fontface
)
7833 ats_font
= FMGetATSFontRefFromFont (font_id
);
7834 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7839 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7840 if (font
->cg_glyphs
)
7841 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7843 space_bounds
= font
->bounds
.rows
[0]->per_char
+ 0x20;
7844 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7845 &font
->ascent
, &font
->descent
,
7847 #if USE_CG_TEXT_DRAWING
7848 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7856 mac_unload_font (&one_mac_display_info
, font
);
7859 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], 0x20);
7861 pcm
= font
->bounds
.rows
[0]->per_char
;
7862 for (c
= 0x21; c
<= 0xff; c
++)
7865 /* Soft hyphen is not supported in ATSUI. */
7873 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7874 #if USE_CG_TEXT_DRAWING
7875 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7881 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], c
);
7883 #if USE_CG_TEXT_DRAWING
7884 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7886 /* Don't use CG text drawing if font substitution occurs in
7887 ASCII or Latin-1 characters. */
7888 CGFontRelease (font
->cg_font
);
7889 font
->cg_font
= NULL
;
7890 xfree (font
->cg_glyphs
);
7891 font
->cg_glyphs
= NULL
;
7900 SInt16 old_fontnum
, old_fontsize
;
7902 FontInfo the_fontinfo
;
7903 int is_two_byte_font
;
7905 /* Save the current font number used. */
7907 #if TARGET_API_MAC_CARBON
7908 old_fontnum
= GetPortTextFont (port
);
7909 old_fontsize
= GetPortTextSize (port
);
7910 old_fontface
= GetPortTextFace (port
);
7912 old_fontnum
= port
->txFont
;
7913 old_fontsize
= port
->txSize
;
7914 old_fontface
= port
->txFace
;
7919 TextFace (fontface
);
7921 GetFontInfo (&the_fontinfo
);
7923 font
->ascent
= the_fontinfo
.ascent
;
7924 font
->descent
= the_fontinfo
.descent
;
7926 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7927 || font
->mac_scriptcode
== smTradChinese
7928 || font
->mac_scriptcode
== smSimpChinese
7929 || font
->mac_scriptcode
== smKorean
);
7931 if (is_two_byte_font
)
7935 font
->min_byte1
= 0xa1;
7936 font
->max_byte1
= 0xfe;
7937 font
->min_char_or_byte2
= 0xa1;
7938 font
->max_char_or_byte2
= 0xfe;
7940 /* Use the width of an "ideographic space" of that font
7941 because the_fontinfo.widMax returns the wrong width for
7943 switch (font
->mac_scriptcode
)
7946 font
->min_byte1
= 0x81;
7947 font
->max_byte1
= 0xfc;
7948 font
->min_char_or_byte2
= 0x40;
7949 font
->max_char_or_byte2
= 0xfc;
7950 char_width
= StringWidth("\p\x81\x40");
7953 font
->min_char_or_byte2
= 0x40;
7954 char_width
= StringWidth("\p\xa1\x40");
7957 char_width
= StringWidth("\p\xa1\xa1");
7960 char_width
= StringWidth("\p\xa1\xa1");
7964 font
->bounds
.per_char
= NULL
;
7966 if (fontface
& italic
)
7967 font
->max_bounds
.rbearing
= char_width
+ 1;
7969 font
->max_bounds
.rbearing
= char_width
;
7970 font
->max_bounds
.lbearing
= 0;
7971 font
->max_bounds
.width
= char_width
;
7972 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7973 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7975 font
->min_bounds
= font
->max_bounds
;
7981 font
->min_byte1
= font
->max_byte1
= 0;
7982 font
->min_char_or_byte2
= 0x20;
7983 font
->max_char_or_byte2
= 0xff;
7985 font
->bounds
.per_char
=
7986 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7987 if (font
->bounds
.per_char
== NULL
)
7989 mac_unload_font (&one_mac_display_info
, font
);
7992 bzero (font
->bounds
.per_char
,
7993 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7995 space_bounds
= font
->bounds
.per_char
;
7996 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
7997 space_bounds
, NULL
);
7999 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
8000 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
8003 /* Restore previous font number, size and face. */
8004 TextFont (old_fontnum
);
8005 TextSize (old_fontsize
);
8006 TextFace (old_fontface
);
8013 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
8014 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
8017 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
8019 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
8021 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
8023 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
8026 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
8028 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
8030 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
8032 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
8037 font
->mac_style
== NULL
&&
8039 font
->max_bounds
.width
== font
->min_bounds
.width
8040 && font
->min_bounds
.lbearing
>= 0
8041 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
8043 /* Fixed width and no overhangs. */
8044 xfree (font
->bounds
.per_char
);
8045 font
->bounds
.per_char
= NULL
;
8049 #if !defined (MAC_OS8) || USE_ATSUI
8050 /* AppKit and WebKit do some adjustment to the heights of Courier,
8051 Helvetica, and Times. This only works on the environments where
8052 srcCopy text transfer mode is never used. */
8054 #ifdef MAC_OS8 /* implies USE_ATSUI */
8057 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
8058 || strcmp (family
, "times") == 0))
8059 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
8067 mac_unload_font (dpyinfo
, font
)
8068 struct mac_display_info
*dpyinfo
;
8071 xfree (font
->full_name
);
8073 if (font
->mac_style
)
8077 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
8078 if (font
->bounds
.rows
[i
])
8079 xfree (font
->bounds
.rows
[i
]);
8080 xfree (font
->bounds
.rows
);
8081 ATSUDisposeStyle (font
->mac_style
);
8085 if (font
->bounds
.per_char
)
8086 xfree (font
->bounds
.per_char
);
8087 #if USE_CG_TEXT_DRAWING
8089 CGFontRelease (font
->cg_font
);
8090 if (font
->cg_glyphs
)
8091 xfree (font
->cg_glyphs
);
8097 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8098 pointer to the structure font_info while allocating it dynamically.
8099 If SIZE is 0, load any size of font.
8100 If loading is failed, return NULL. */
8103 x_load_font (f
, fontname
, size
)
8105 register char *fontname
;
8108 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8109 Lisp_Object font_names
;
8111 /* Get a list of all the fonts that match this name. Once we
8112 have a list of matching fonts, we compare them against the fonts
8113 we already have by comparing names. */
8114 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8116 if (!NILP (font_names
))
8121 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8122 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8123 if (dpyinfo
->font_table
[i
].name
8124 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8125 SDATA (XCAR (tail
)))
8126 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8127 SDATA (XCAR (tail
)))))
8128 return (dpyinfo
->font_table
+ i
);
8133 /* Load the font and add it to the table. */
8136 struct MacFontStruct
*font
;
8137 struct font_info
*fontp
;
8138 unsigned long value
;
8141 fontname
= (char *) SDATA (XCAR (font_names
));
8144 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
8149 /* Find a free slot in the font table. */
8150 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8151 if (dpyinfo
->font_table
[i
].name
== NULL
)
8154 /* If no free slot found, maybe enlarge the font table. */
8155 if (i
== dpyinfo
->n_fonts
8156 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8159 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8160 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8162 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8165 fontp
= dpyinfo
->font_table
+ i
;
8166 if (i
== dpyinfo
->n_fonts
)
8169 /* Now fill in the slots of *FONTP. */
8171 bzero (fontp
, sizeof (*fontp
));
8173 fontp
->font_idx
= i
;
8174 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
8175 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
8177 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
8179 /* Fixed width font. */
8180 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8187 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8188 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8190 fontp
->space_width
= pcm
->width
;
8192 fontp
->space_width
= FONT_WIDTH (font
);
8196 int width
= pcm
->width
;
8197 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8198 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8199 width
+= pcm
->width
;
8200 fontp
->average_width
= width
/ 95;
8203 fontp
->average_width
= FONT_WIDTH (font
);
8206 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8207 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8209 fontp
->size
= font
->max_bounds
.width
;
8210 fontp
->height
= FONT_HEIGHT (font
);
8212 /* For some font, ascent and descent in max_bounds field is
8213 larger than the above value. */
8214 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8215 if (max_height
> fontp
->height
)
8216 fontp
->height
= max_height
;
8219 /* The slot `encoding' specifies how to map a character
8220 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8221 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8222 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8223 2:0xA020..0xFF7F). For the moment, we don't know which charset
8224 uses this font. So, we set information in fontp->encoding[1]
8225 which is never used by any charset. If mapping can't be
8226 decided, set FONT_ENCODING_NOT_DECIDED. */
8227 if (font
->mac_scriptcode
== smJapanese
)
8228 fontp
->encoding
[1] = 4;
8232 = (font
->max_byte1
== 0
8234 ? (font
->min_char_or_byte2
< 0x80
8235 ? (font
->max_char_or_byte2
< 0x80
8236 ? 0 /* 0x20..0x7F */
8237 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8238 : 1) /* 0xA0..0xFF */
8240 : (font
->min_byte1
< 0x80
8241 ? (font
->max_byte1
< 0x80
8242 ? (font
->min_char_or_byte2
< 0x80
8243 ? (font
->max_char_or_byte2
< 0x80
8244 ? 0 /* 0x2020..0x7F7F */
8245 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8246 : 3) /* 0x20A0..0x7FFF */
8247 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8248 : (font
->min_char_or_byte2
< 0x80
8249 ? (font
->max_char_or_byte2
< 0x80
8250 ? 2 /* 0xA020..0xFF7F */
8251 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8252 : 1))); /* 0xA0A0..0xFFFF */
8255 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8256 fontp
->baseline_offset
8257 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8258 ? (long) value
: 0);
8259 fontp
->relative_compose
8260 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8261 ? (long) value
: 0);
8262 fontp
->default_ascent
8263 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8264 ? (long) value
: 0);
8266 fontp
->baseline_offset
= 0;
8267 fontp
->relative_compose
= 0;
8268 fontp
->default_ascent
= 0;
8271 /* Set global flag fonts_changed_p to non-zero if the font loaded
8272 has a character with a smaller width than any other character
8273 before, or if the font loaded has a smaller height than any
8274 other font loaded before. If this happens, it will make a
8275 glyph matrix reallocation necessary. */
8276 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8283 /* Return a pointer to struct font_info of a font named FONTNAME for
8284 frame F. If no such font is loaded, return NULL. */
8287 x_query_font (f
, fontname
)
8289 register char *fontname
;
8291 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8294 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8295 if (dpyinfo
->font_table
[i
].name
8296 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8297 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8298 return (dpyinfo
->font_table
+ i
);
8303 /* Find a CCL program for a font specified by FONTP, and set the member
8304 `encoder' of the structure. */
8307 x_find_ccl_program (fontp
)
8308 struct font_info
*fontp
;
8310 Lisp_Object list
, elt
;
8312 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8316 && STRINGP (XCAR (elt
))
8317 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8323 struct ccl_program
*ccl
8324 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8326 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8329 fontp
->font_encoder
= ccl
;
8335 /* The Mac Event loop code */
8337 #if !TARGET_API_MAC_CARBON
8339 #include <Quickdraw.h>
8340 #include <Balloons.h>
8341 #include <Devices.h>
8343 #include <Gestalt.h>
8345 #include <Processes.h>
8347 #include <ToolUtils.h>
8348 #include <TextUtils.h>
8349 #include <Dialogs.h>
8352 #include <Resources.h>
8357 #endif /* ! TARGET_API_MAC_CARBON */
8362 #define WINDOW_RESOURCE 128
8363 #define TERM_WINDOW_RESOURCE 129
8365 #define DEFAULT_NUM_COLS 80
8367 #define MIN_DOC_SIZE 64
8368 #define MAX_DOC_SIZE 32767
8370 #define EXTRA_STACK_ALLOC (256 * 1024)
8372 #define ARGV_STRING_LIST_ID 129
8373 #define ABOUT_ALERT_ID 128
8374 #define RAM_TOO_LARGE_ALERT_ID 129
8376 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8377 Lisp_Object Qreverse
;
8380 /* Modifier associated with the control key, or nil to ignore. */
8381 Lisp_Object Vmac_control_modifier
;
8383 /* Modifier associated with the option key, or nil to ignore. */
8384 Lisp_Object Vmac_option_modifier
;
8386 /* Modifier associated with the command key, or nil to ignore. */
8387 Lisp_Object Vmac_command_modifier
;
8389 /* Modifier associated with the function key, or nil to ignore. */
8390 Lisp_Object Vmac_function_modifier
;
8392 /* True if the option and command modifiers should be used to emulate
8393 a three button mouse */
8394 Lisp_Object Vmac_emulate_three_button_mouse
;
8396 #if USE_CARBON_EVENTS
8397 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8398 mouse-2, instead of mouse-3. */
8399 int mac_wheel_button_is_mouse_2
;
8401 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8402 for processing before Emacs sees it. */
8403 int mac_pass_command_to_system
;
8405 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8406 for processing before Emacs sees it. */
8407 int mac_pass_control_to_system
;
8410 /* Points to the variable `inev' in the function XTread_socket. It is
8411 used for passing an input event to the function back from
8412 Carbon/Apple event handlers. */
8413 static struct input_event
*read_socket_inev
= NULL
;
8415 Point saved_menu_event_location
;
8418 #if USE_CARBON_EVENTS
8419 static Lisp_Object Qhicommand
;
8421 extern int mac_ready_for_apple_events
;
8422 extern Lisp_Object Qundefined
;
8423 extern void init_apple_event_handler
P_ ((void));
8424 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8425 Lisp_Object
*, Lisp_Object
*,
8427 extern OSErr init_coercion_handler
P_ ((void));
8429 #if TARGET_API_MAC_CARBON
8431 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
8432 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
8433 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
8434 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
8437 #if USE_CARBON_EVENTS
8439 extern void init_service_handler ();
8440 static Lisp_Object Qservices
, Qpaste
, Qperform
;
8442 /* Window Event Handler */
8443 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8446 OSErr
install_window_handler (WindowPtr
);
8448 extern void init_emacs_passwd_dir ();
8449 extern int emacs_main (int, char **, char **);
8451 extern void initialize_applescript();
8452 extern void terminate_applescript();
8455 #if USE_CARBON_EVENTS
8456 mac_to_emacs_modifiers (UInt32 mods
)
8458 mac_to_emacs_modifiers (EventModifiers mods
)
8461 unsigned int result
= 0;
8462 if (mods
& shiftKey
)
8463 result
|= shift_modifier
;
8465 /* Deactivated to simplify configuration:
8466 if Vmac_option_modifier is non-NIL, we fully process the Option
8467 key. Otherwise, we only process it if an additional Ctrl or Command
8468 is pressed. That way the system may convert the character to a
8470 if ((mods & optionKey) &&
8471 (( !NILP(Vmac_option_modifier) ||
8472 ((mods & cmdKey) || (mods & controlKey))))) */
8474 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8475 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8477 result
|= XUINT(val
);
8479 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8480 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8482 result
|= XUINT(val
);
8484 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8485 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8487 result
|= XUINT(val
);
8491 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8492 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8494 result
|= XUINT(val
);
8502 mac_get_emulated_btn ( UInt32 modifiers
)
8505 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8506 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8507 if (modifiers
& cmdKey
)
8508 result
= cmdIs3
? 2 : 1;
8509 else if (modifiers
& optionKey
)
8510 result
= cmdIs3
? 1 : 2;
8515 #if USE_CARBON_EVENTS
8516 /* Obtains the event modifiers from the event ref and then calls
8517 mac_to_emacs_modifiers. */
8519 mac_event_to_emacs_modifiers (EventRef eventRef
)
8522 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8523 sizeof (UInt32
), NULL
, &mods
);
8524 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8525 GetEventClass(eventRef
) == kEventClassMouse
)
8527 mods
&= ~(optionKey
| cmdKey
);
8529 return mac_to_emacs_modifiers (mods
);
8532 /* Given an event ref, return the code to use for the mouse button
8533 code in the emacs input_event. */
8535 mac_get_mouse_btn (EventRef ref
)
8537 EventMouseButton result
= kEventMouseButtonPrimary
;
8538 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8539 sizeof (EventMouseButton
), NULL
, &result
);
8542 case kEventMouseButtonPrimary
:
8543 if (NILP (Vmac_emulate_three_button_mouse
))
8547 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8548 sizeof (UInt32
), NULL
, &mods
);
8549 return mac_get_emulated_btn(mods
);
8551 case kEventMouseButtonSecondary
:
8552 return mac_wheel_button_is_mouse_2
? 2 : 1;
8553 case kEventMouseButtonTertiary
:
8554 case 4: /* 4 is the number for the mouse wheel button */
8555 return mac_wheel_button_is_mouse_2
? 1 : 2;
8561 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8562 events. However the click of the mouse wheel is not converted to a
8563 mouseDown or mouseUp event. Likewise for dead key down events.
8564 This calls ConvertEventRef, but then checks to see if it is a mouse
8565 up/down, or a dead key down carbon event that has not been
8566 converted, and if so, converts it by hand (to be picked up in the
8567 XTread_socket loop). */
8568 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8571 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8576 switch (GetEventClass (eventRef
))
8578 case kEventClassMouse
:
8579 switch (GetEventKind (eventRef
))
8581 case kEventMouseDown
:
8582 eventRec
->what
= mouseDown
;
8587 eventRec
->what
= mouseUp
;
8596 case kEventClassKeyboard
:
8597 switch (GetEventKind (eventRef
))
8599 case kEventRawKeyDown
:
8601 unsigned char char_codes
;
8604 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
8605 typeChar
, NULL
, sizeof (char),
8608 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
8609 typeUInt32
, NULL
, sizeof (UInt32
),
8613 eventRec
->what
= keyDown
;
8614 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8631 /* Need where and when. */
8634 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8635 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8636 /* Use two step process because new event modifiers are 32-bit
8637 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8638 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8639 NULL
, sizeof (UInt32
), NULL
, &mods
);
8640 eventRec
->modifiers
= mods
;
8642 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8653 Handle menubar_handle
;
8654 MenuHandle menu_handle
;
8656 menubar_handle
= GetNewMBar (128);
8657 if(menubar_handle
== NULL
)
8659 SetMenuBar (menubar_handle
);
8662 #if !TARGET_API_MAC_CARBON
8663 menu_handle
= GetMenuHandle (M_APPLE
);
8664 if(menu_handle
!= NULL
)
8665 AppendResMenu (menu_handle
,'DRVR');
8673 do_init_managers (void)
8675 #if !TARGET_API_MAC_CARBON
8676 InitGraf (&qd
.thePort
);
8678 FlushEvents (everyEvent
, 0);
8683 #endif /* !TARGET_API_MAC_CARBON */
8686 #if !TARGET_API_MAC_CARBON
8687 /* set up some extra stack space for use by emacs */
8688 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8690 /* MaxApplZone must be called for AppleScript to execute more
8691 complicated scripts */
8694 #endif /* !TARGET_API_MAC_CARBON */
8698 do_check_ram_size (void)
8700 SInt32 physical_ram_size
, logical_ram_size
;
8702 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8703 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8704 || physical_ram_size
> (1 << VALBITS
)
8705 || logical_ram_size
> (1 << VALBITS
))
8707 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8713 do_window_update (WindowPtr win
)
8715 struct frame
*f
= mac_window_to_frame (win
);
8719 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8721 if (win
!= tip_window
)
8723 if (f
->async_visible
== 0)
8725 /* Update events may occur when a frame gets iconified. */
8727 f
->async_visible
= 1;
8728 f
->async_iconified
= 0;
8729 SET_FRAME_GARBAGED (f
);
8735 #if TARGET_API_MAC_CARBON
8736 RgnHandle region
= NewRgn ();
8738 GetPortVisibleRegion (GetWindowPort (win
), region
);
8739 GetRegionBounds (region
, &r
);
8740 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8741 UpdateControls (win
, region
);
8742 DisposeRgn (region
);
8744 r
= (*win
->visRgn
)->rgnBBox
;
8745 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8746 UpdateControls (win
, win
->visRgn
);
8755 is_emacs_window (WindowPtr win
)
8757 Lisp_Object tail
, frame
;
8762 FOR_EACH_FRAME (tail
, frame
)
8763 if (FRAME_MAC_P (XFRAME (frame
)))
8764 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8773 /* Window-activate events will do the job. */
8779 /* Window-deactivate events will do the job. */
8784 do_apple_menu (SInt16 menu_item
)
8786 #if !TARGET_API_MAC_CARBON
8788 SInt16 da_driver_refnum
;
8790 if (menu_item
== I_ABOUT
)
8791 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8794 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8795 da_driver_refnum
= OpenDeskAcc (item_name
);
8797 #endif /* !TARGET_API_MAC_CARBON */
8801 do_menu_choice (SInt32 menu_choice
)
8803 SInt16 menu_id
, menu_item
;
8805 menu_id
= HiWord (menu_choice
);
8806 menu_item
= LoWord (menu_choice
);
8814 do_apple_menu (menu_item
);
8819 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8820 MenuHandle menu
= GetMenuHandle (menu_id
);
8825 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8826 menubar_selection_callback (f
, refcon
);
8835 /* Handle drags in size box. Based on code contributed by Ben
8836 Mesander and IM - Window Manager A. */
8839 do_grow_window (WindowPtr w
, EventRecord
*e
)
8842 int rows
, columns
, width
, height
;
8843 struct frame
*f
= mac_window_to_frame (w
);
8844 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8845 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8846 #if TARGET_API_MAC_CARBON
8852 if (size_hints
->flags
& PMinSize
)
8854 min_width
= size_hints
->min_width
;
8855 min_height
= size_hints
->min_height
;
8857 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8859 #if TARGET_API_MAC_CARBON
8860 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8862 height
= new_rect
.bottom
- new_rect
.top
;
8863 width
= new_rect
.right
- new_rect
.left
;
8865 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8866 /* see if it really changed size */
8869 height
= HiWord (grow_size
);
8870 width
= LoWord (grow_size
);
8873 if (width
!= FRAME_PIXEL_WIDTH (f
)
8874 || height
!= FRAME_PIXEL_HEIGHT (f
))
8876 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8877 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8879 x_set_window_size (f
, 0, columns
, rows
);
8884 /* Handle clicks in zoom box. Calculation of "standard state" based
8885 on code in IM - Window Manager A and code contributed by Ben
8886 Mesander. The standard state of an Emacs window is 80-characters
8887 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8890 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8893 Rect zoom_rect
, port_rect
;
8895 int w_title_height
, columns
, rows
, width
, height
;
8896 struct frame
*f
= mac_window_to_frame (w
);
8897 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8899 #if TARGET_API_MAC_CARBON
8901 Point standard_size
;
8903 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8904 standard_size
.v
= dpyinfo
->height
;
8906 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8907 zoom_in_or_out
= inZoomIn
;
8910 /* Adjust the standard size according to character boundaries. */
8912 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8913 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8914 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8915 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8916 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8917 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8918 && port_rect
.left
== zoom_rect
.left
8919 && port_rect
.top
== zoom_rect
.top
)
8920 zoom_in_or_out
= inZoomIn
;
8922 zoom_in_or_out
= inZoomOut
;
8925 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8927 #else /* not TARGET_API_MAC_CARBON */
8928 GetPort (&save_port
);
8930 SetPortWindowPort (w
);
8932 /* Clear window to avoid flicker. */
8933 EraseRect (&(w
->portRect
));
8934 if (zoom_in_or_out
== inZoomOut
)
8936 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8937 LocalToGlobal (&top_left
);
8939 /* calculate height of window's title bar */
8940 w_title_height
= top_left
.v
- 1
8941 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8943 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8944 zoom_rect
= qd
.screenBits
.bounds
;
8945 zoom_rect
.top
+= w_title_height
;
8946 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8948 zoom_rect
.right
= zoom_rect
.left
8949 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8951 /* Adjust the standard size according to character boundaries. */
8952 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8954 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8956 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8960 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8962 SetPort (save_port
);
8963 #endif /* not TARGET_API_MAC_CARBON */
8965 /* retrieve window size and update application values */
8966 #if TARGET_API_MAC_CARBON
8967 GetWindowPortBounds (w
, &port_rect
);
8969 port_rect
= w
->portRect
;
8971 height
= port_rect
.bottom
- port_rect
.top
;
8972 width
= port_rect
.right
- port_rect
.left
;
8974 if (width
!= FRAME_PIXEL_WIDTH (f
)
8975 || height
!= FRAME_PIXEL_HEIGHT (f
))
8977 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8978 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8980 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8981 SET_FRAME_GARBAGED (f
);
8982 cancel_mouse_face (f
);
8984 FRAME_PIXEL_WIDTH (f
) = width
;
8985 FRAME_PIXEL_HEIGHT (f
) = height
;
8987 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8991 mac_store_apple_event (class, id
, desc
)
8992 Lisp_Object
class, id
;
8996 struct input_event buf
;
8999 desc_copy
= xmalloc (sizeof (AEDesc
));
9000 if (desc_copy
== NULL
)
9003 err
= AEDuplicateDesc (desc
, desc_copy
);
9008 buf
.kind
= MAC_APPLE_EVENT
;
9011 buf
.code
= (int)desc_copy
;
9012 XSETFRAME (buf
.frame_or_window
,
9013 mac_focus_frame (&one_mac_display_info
));
9015 kbd_buffer_store_event (&buf
);
9022 mac_make_lispy_event_code (code
)
9025 AEDesc
*desc
= (AEDesc
*)code
;
9028 obj
= mac_aedesc_to_lisp (desc
);
9029 AEDisposeDesc (desc
);
9035 #if USE_CARBON_EVENTS
9036 static pascal OSStatus
9037 mac_handle_command_event (next_handler
, event
, data
)
9038 EventHandlerCallRef next_handler
;
9042 OSStatus result
, err
;
9044 Lisp_Object class_key
, id_key
, binding
;
9046 result
= CallNextEventHandler (next_handler
, event
);
9047 if (result
!= eventNotHandledErr
)
9050 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9051 NULL
, sizeof (HICommand
), NULL
, &command
);
9053 if (err
!= noErr
|| command
.commandID
== 0)
9054 return eventNotHandledErr
;
9056 /* A HICommand event is mapped to an Apple event whose event class
9057 symbol is `hicommand' and event ID is its command ID. */
9058 class_key
= Qhicommand
;
9059 mac_find_apple_event_spec (0, command
.commandID
,
9060 &class_key
, &id_key
, &binding
);
9061 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
9062 if (INTEGERP (binding
))
9063 return XINT (binding
);
9066 AppleEvent apple_event
;
9068 static EventParamName names
[] = {kEventParamDirectObject
,
9069 kEventParamKeyModifiers
};
9070 static EventParamType types
[] = {typeHICommand
,
9072 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
9076 err
= mac_store_apple_event (class_key
, id_key
, &apple_event
);
9077 AEDisposeDesc (&apple_event
);
9083 return eventNotHandledErr
;
9087 init_command_handler ()
9090 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
9091 static EventHandlerUPP handle_command_eventUPP
= NULL
;
9093 if (handle_command_eventUPP
== NULL
)
9094 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
9095 return InstallApplicationEventHandler (handle_command_eventUPP
,
9096 GetEventTypeCount (specs
), specs
,
9100 static pascal OSStatus
9101 mac_handle_window_event (next_handler
, event
, data
)
9102 EventHandlerCallRef next_handler
;
9107 OSStatus result
, err
;
9109 XSizeHints
*size_hints
;
9111 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
9112 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9114 return eventNotHandledErr
;
9116 switch (GetEventKind (event
))
9118 case kEventWindowUpdate
:
9119 result
= CallNextEventHandler (next_handler
, event
);
9120 if (result
!= eventNotHandledErr
)
9123 do_window_update (wp
);
9126 case kEventWindowBoundsChanging
:
9127 result
= CallNextEventHandler (next_handler
, event
);
9128 if (result
!= eventNotHandledErr
)
9131 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9132 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9136 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
9137 if ((attributes
& kWindowBoundsChangeUserResize
)
9138 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9139 == (PResizeInc
| PBaseSize
| PMinSize
)))
9144 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
9145 typeQDRectangle
, NULL
, sizeof (Rect
),
9150 width
= bounds
.right
- bounds
.left
;
9151 height
= bounds
.bottom
- bounds
.top
;
9153 if (width
< size_hints
->min_width
)
9154 width
= size_hints
->min_width
;
9156 width
= size_hints
->base_width
9157 + (int) ((width
- size_hints
->base_width
)
9158 / (float) size_hints
->width_inc
+ .5)
9159 * size_hints
->width_inc
;
9161 if (height
< size_hints
->min_height
)
9162 height
= size_hints
->min_height
;
9164 height
= size_hints
->base_height
9165 + (int) ((height
- size_hints
->base_height
)
9166 / (float) size_hints
->height_inc
+ .5)
9167 * size_hints
->height_inc
;
9169 bounds
.right
= bounds
.left
+ width
;
9170 bounds
.bottom
= bounds
.top
+ height
;
9171 SetEventParameter (event
, kEventParamCurrentBounds
,
9172 typeQDRectangle
, sizeof (Rect
), &bounds
);
9177 case kEventWindowShown
:
9178 case kEventWindowHidden
:
9179 case kEventWindowExpanded
:
9180 case kEventWindowCollapsed
:
9181 result
= CallNextEventHandler (next_handler
, event
);
9183 mac_handle_visibility_change (mac_window_to_frame (wp
));
9189 return eventNotHandledErr
;
9192 static pascal OSStatus
9193 mac_handle_mouse_event (next_handler
, event
, data
)
9194 EventHandlerCallRef next_handler
;
9198 OSStatus result
, err
;
9200 switch (GetEventKind (event
))
9202 case kEventMouseWheelMoved
:
9206 EventMouseWheelAxis axis
;
9210 result
= CallNextEventHandler (next_handler
, event
);
9211 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9214 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9215 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9219 f
= mac_window_to_frame (wp
);
9220 if (f
!= mac_focus_frame (&one_mac_display_info
))
9223 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
9224 typeMouseWheelAxis
, NULL
,
9225 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9226 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
9229 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
9230 typeSInt32
, NULL
, sizeof (SInt32
),
9234 err
= GetEventParameter (event
, kEventParamMouseLocation
,
9235 typeQDPoint
, NULL
, sizeof (Point
),
9239 read_socket_inev
->kind
= WHEEL_EVENT
;
9240 read_socket_inev
->code
= 0;
9241 read_socket_inev
->modifiers
=
9242 (mac_event_to_emacs_modifiers (event
)
9243 | ((delta
< 0) ? down_modifier
: up_modifier
));
9244 SetPortWindowPort (wp
);
9245 GlobalToLocal (&point
);
9246 XSETINT (read_socket_inev
->x
, point
.h
);
9247 XSETINT (read_socket_inev
->y
, point
.v
);
9248 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9258 return eventNotHandledErr
;
9263 mac_store_services_event (event
)
9267 AppleEvent apple_event
;
9270 switch (GetEventKind (event
))
9272 case kEventServicePaste
:
9274 err
= create_apple_event_from_event_ref (event
, 0, NULL
, NULL
,
9278 case kEventServicePerform
:
9280 static EventParamName names
[] = {kEventParamServiceMessageName
,
9281 kEventParamServiceUserData
};
9282 static EventParamType types
[] = {typeCFStringRef
,
9286 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
9297 err
= mac_store_apple_event (Qservices
, id_key
, &apple_event
);
9298 AEDisposeDesc (&apple_event
);
9303 #endif /* MAC_OSX */
9304 #endif /* USE_CARBON_EVENTS */
9308 install_window_handler (window
)
9312 #if USE_CARBON_EVENTS
9313 EventTypeSpec specs_window
[] =
9314 {{kEventClassWindow
, kEventWindowUpdate
},
9315 {kEventClassWindow
, kEventWindowBoundsChanging
},
9316 {kEventClassWindow
, kEventWindowShown
},
9317 {kEventClassWindow
, kEventWindowHidden
},
9318 {kEventClassWindow
, kEventWindowExpanded
},
9319 {kEventClassWindow
, kEventWindowCollapsed
}};
9320 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9321 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9322 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9324 if (handle_window_eventUPP
== NULL
)
9325 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9326 if (handle_mouse_eventUPP
== NULL
)
9327 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9328 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9329 GetEventTypeCount (specs_window
),
9330 specs_window
, NULL
, NULL
);
9332 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9333 GetEventTypeCount (specs_mouse
),
9334 specs_mouse
, NULL
, NULL
);
9336 #if TARGET_API_MAC_CARBON
9337 if (mac_do_track_dragUPP
== NULL
)
9338 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
9339 if (mac_do_receive_dragUPP
== NULL
)
9340 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
9343 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
9345 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
9351 remove_window_handler (window
)
9354 #if TARGET_API_MAC_CARBON
9355 if (mac_do_track_dragUPP
)
9356 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
9357 if (mac_do_receive_dragUPP
)
9358 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
9362 #if TARGET_API_MAC_CARBON
9364 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9365 void *handlerRefCon
, DragReference theDrag
)
9367 static int can_accept
;
9370 ItemReference theItem
;
9371 FlavorFlags theFlags
;
9374 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9375 return dragNotAcceptedErr
;
9379 case kDragTrackingEnterHandler
:
9380 CountDragItems (theDrag
, &items
);
9382 for (index
= 1; index
<= items
; index
++)
9384 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9385 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9386 if (result
== noErr
)
9394 case kDragTrackingEnterWindow
:
9397 RgnHandle hilite_rgn
= NewRgn ();
9399 struct frame
*f
= mac_window_to_frame (window
);
9401 GetWindowPortBounds (window
, &r
);
9402 OffsetRect (&r
, -r
.left
, -r
.top
);
9403 RectRgn (hilite_rgn
, &r
);
9404 ShowDragHilite (theDrag
, hilite_rgn
, true);
9405 DisposeRgn (hilite_rgn
);
9406 SetThemeCursor (kThemeCopyArrowCursor
);
9410 case kDragTrackingInWindow
:
9413 case kDragTrackingLeaveWindow
:
9416 struct frame
*f
= mac_window_to_frame (window
);
9418 HideDragHilite (theDrag
);
9419 SetThemeCursor (kThemeArrowCursor
);
9423 case kDragTrackingLeaveHandler
:
9431 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9432 DragReference theDrag
)
9436 FlavorFlags theFlags
;
9439 ItemReference theItem
;
9441 Size size
= sizeof (HFSFlavor
);
9442 Lisp_Object file_list
;
9444 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9445 return dragNotAcceptedErr
;
9448 GetDragMouse (theDrag
, &mouse
, 0L);
9449 CountDragItems (theDrag
, &items
);
9450 for (index
= 1; index
<= items
; index
++)
9452 /* Only handle file references. */
9453 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9454 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9455 if (result
== noErr
)
9460 err
= GetFlavorData (theDrag
, theItem
, flavorTypeHFS
,
9463 err
= AECoercePtr (typeFSS
, &data
.fileSpec
, sizeof (FSSpec
),
9464 TYPE_FILE_NAME
, &desc
);
9469 /* x-dnd functions expect undecoded filenames. */
9470 file
= make_uninit_string (AEGetDescDataSize (&desc
));
9471 err
= AEGetDescData (&desc
, SDATA (file
), SBYTES (file
));
9473 file_list
= Fcons (file
, file_list
);
9474 AEDisposeDesc (&desc
);
9478 /* If there are items in the list, construct an event and post it to
9479 the queue like an interrupt using kbd_buffer_store_event. */
9480 if (!NILP (file_list
))
9482 struct input_event event
;
9484 struct frame
*f
= mac_window_to_frame (window
);
9487 GlobalToLocal (&mouse
);
9488 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9490 event
.kind
= DRAG_N_DROP_EVENT
;
9492 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9493 event
.timestamp
= TickCount () * (1000 / 60);
9494 XSETINT (event
.x
, mouse
.h
);
9495 XSETINT (event
.y
, mouse
.v
);
9496 XSETFRAME (frame
, f
);
9497 event
.frame_or_window
= frame
;
9498 event
.arg
= file_list
;
9499 /* Post to the interrupt queue */
9500 kbd_buffer_store_event (&event
);
9501 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9503 ProcessSerialNumber psn
;
9504 GetCurrentProcess (&psn
);
9505 SetFrontProcess (&psn
);
9511 return dragNotAcceptedErr
;
9518 profiler_exit_proc ()
9520 ProfilerDump ("\pEmacs.prof");
9525 /* These few functions implement Emacs as a normal Mac application
9526 (almost): set up the heap and the Toolbox, handle necessary system
9527 events plus a few simple menu events. They also set up Emacs's
9528 access to functions defined in the rest of this file. Emacs uses
9529 function hooks to perform all its terminal I/O. A complete list of
9530 these functions appear in termhooks.h. For what they do, read the
9531 comments there and see also w32term.c and xterm.c. What's
9532 noticeably missing here is the event loop, which is normally
9533 present in most Mac application. After performing the necessary
9534 Mac initializations, main passes off control to emacs_main
9535 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9536 (defined further below) to read input. This is where
9537 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9544 #if __profile__ /* is the profiler on? */
9545 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9550 /* set creator and type for files created by MSL */
9555 do_init_managers ();
9560 do_check_ram_size ();
9563 init_emacs_passwd_dir ();
9567 init_coercion_handler ();
9569 initialize_applescript ();
9571 init_apple_event_handler ();
9577 /* set up argv array from STR# resource */
9578 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9582 /* free up AppleScript resources on exit */
9583 atexit (terminate_applescript
);
9585 #if __profile__ /* is the profiler on? */
9586 atexit (profiler_exit_proc
);
9589 /* 3rd param "envp" never used in emacs_main */
9590 (void) emacs_main (argc
, argv
, 0);
9593 /* Never reached - real exit in Fkill_emacs */
9598 /* Table for translating Mac keycode to X keysym values. Contributed
9600 Mapping for special keys is now identical to that in Apple X11
9601 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9602 on the right of the Cmd key on laptops, and fn + `enter' (->
9604 static unsigned char keycode_to_xkeysym_table
[] = {
9605 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9606 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9607 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9609 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9610 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9611 /*0x38*/ 0, 0, 0, 0,
9612 /*0x3C*/ 0, 0, 0, 0,
9614 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9615 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9616 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9617 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9619 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9620 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9621 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9622 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9624 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9625 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9626 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9627 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9629 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9630 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9631 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9632 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9637 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9639 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9640 return *xKeySym
!= 0;
9643 static unsigned char fn_keycode_to_xkeysym_table
[] = {
9644 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9645 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9646 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9648 /*0x30*/ 0, 0, 0, 0,
9649 /*0x34*/ 0, 0, 0, 0,
9650 /*0x38*/ 0, 0, 0, 0,
9651 /*0x3C*/ 0, 0, 0, 0,
9653 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
9654 /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
9655 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
9656 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
9658 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
9659 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
9660 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
9661 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
9663 /*0x60*/ 0, 0, 0, 0,
9664 /*0x64*/ 0, 0, 0, 0,
9665 /*0x68*/ 0, 0, 0, 0,
9666 /*0x6C*/ 0, 0, 0, 0,
9668 /*0x70*/ 0, 0, 0, 0,
9669 /*0x74*/ 0, 0, 0, 0,
9670 /*0x78*/ 0, 0, 0, 0,
9674 convert_fn_keycode (EventRef eventRef
, int keyCode
, int *newCode
)
9677 /* Use the special map to translate keys when function modifier is
9678 to be caught. KeyTranslate can't be used in that case.
9679 We can't detect the function key using the input_event.modifiers,
9680 because this uses the high word of an UInt32. Therefore,
9681 we'll just read it out of the original eventRef.
9685 /* TODO / known issues
9687 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9688 The above table always translates to lower characters. We need to use
9689 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9691 - The table is meant for English language keyboards, and it will work
9692 for many others with the exception of key combinations like Fn-ö on
9693 a German keyboard, which is currently mapped to Fn-;.
9694 How to solve this without keeping separate tables for all keyboards
9695 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9696 value for keycode with the modifiers in he high byte, i.e. no room for the
9697 Fn modifier. That's why we need the table.
9702 if (!NILP(Vmac_function_modifier
))
9704 err
= GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
9705 NULL
, sizeof (UInt32
), NULL
, &mods
);
9706 if (err
!= noErr
&& mods
& kEventKeyModifierFnMask
)
9707 { *newCode
= fn_keycode_to_xkeysym_table
[keyCode
& 0x7f];
9709 return (*newCode
!= 0);
9717 backtranslate_modified_keycode(int mods
, int keycode
, int def
)
9719 EventModifiers mapped_modifiers
=
9720 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9721 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9722 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9724 if (mods
& mapped_modifiers
)
9726 /* This code comes from Keyboard Resource,
9727 Appendix C of IM - Text. This is necessary
9728 since shift is ignored in KCHR table
9729 translation when option or command is pressed.
9730 It also does not translate correctly
9731 control-shift chars like C-% so mask off shift
9734 Not done for combinations with the option key (alt)
9735 unless it is to be caught by Emacs: this is
9736 to preserve key combinations translated by the OS
9739 /* Mask off modifier keys that are mapped to some Emacs
9741 int new_modifiers
= mods
& ~mapped_modifiers
;
9742 /* set high byte of keycode to modifier high byte*/
9743 int new_keycode
= keycode
| new_modifiers
;
9744 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9745 unsigned long some_state
= 0;
9746 return (int) KeyTranslate (kchr_ptr
, new_keycode
,
9747 &some_state
) & 0xff;
9748 /* TO DO: Recognize two separate resulting characters, "for
9749 example, when the user presses Option-E followed by N, you
9750 can map this through the KeyTranslate function using the
9751 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9752 returns as two characters in the bytes labeled Character code
9753 1 and Character code 2." (from Carbon API doc) */
9761 #if !USE_CARBON_EVENTS
9762 static RgnHandle mouse_region
= NULL
;
9765 mac_wait_next_event (er
, sleep_time
, dequeue
)
9770 static EventRecord er_buf
= {nullEvent
};
9771 UInt32 target_tick
, current_tick
;
9772 EventMask event_mask
;
9774 if (mouse_region
== NULL
)
9775 mouse_region
= NewRgn ();
9777 event_mask
= everyEvent
;
9778 if (!mac_ready_for_apple_events
)
9779 event_mask
-= highLevelEventMask
;
9781 current_tick
= TickCount ();
9782 target_tick
= current_tick
+ sleep_time
;
9784 if (er_buf
.what
== nullEvent
)
9785 while (!WaitNextEvent (event_mask
, &er_buf
,
9786 target_tick
- current_tick
, mouse_region
))
9788 current_tick
= TickCount ();
9789 if (target_tick
<= current_tick
)
9795 er_buf
.what
= nullEvent
;
9798 #endif /* not USE_CARBON_EVENTS */
9800 /* Emacs calls this whenever it wants to read an input event from the
9803 XTread_socket (sd
, expected
, hold_quit
)
9805 struct input_event
*hold_quit
;
9807 struct input_event inev
;
9809 #if USE_CARBON_EVENTS
9811 EventTargetRef toolbox_dispatcher
;
9814 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9816 if (interrupt_input_blocked
)
9818 interrupt_input_pending
= 1;
9822 interrupt_input_pending
= 0;
9825 /* So people can tell when we have read the available input. */
9826 input_signal_count
++;
9830 #if USE_CARBON_EVENTS
9831 toolbox_dispatcher
= GetEventDispatcherTarget ();
9835 mac_prepare_for_quickdraw (NULL
),
9837 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9838 kEventRemoveFromQueue
, &eventRef
))
9839 #else /* !USE_CARBON_EVENTS */
9840 while (mac_wait_next_event (&er
, 0, true))
9841 #endif /* !USE_CARBON_EVENTS */
9845 unsigned long timestamp
;
9847 /* It is necessary to set this (additional) argument slot of an
9848 event to nil because keyboard.c protects incompletely
9849 processed event from being garbage collected by placing them
9850 in the kbd_buffer_gcpro vector. */
9852 inev
.kind
= NO_EVENT
;
9855 #if USE_CARBON_EVENTS
9856 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9858 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9861 #if USE_CARBON_EVENTS
9862 /* Handle new events */
9863 if (!mac_convert_event_ref (eventRef
, &er
))
9865 /* There used to be a handler for the kEventMouseWheelMoved
9866 event here. But as of Mac OS X 10.4, this kind of event
9867 is not directly posted to the main event queue by
9868 two-finger scrolling on the trackpad. Instead, some
9869 private event is posted and it is converted to a wheel
9870 event by the default handler for the application target.
9871 The converted one can be received by a Carbon event
9872 handler installed on a window target. */
9873 read_socket_inev
= &inev
;
9874 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9875 read_socket_inev
= NULL
;
9878 #endif /* USE_CARBON_EVENTS */
9884 WindowPtr window_ptr
;
9885 ControlPartCode part_code
;
9888 #if USE_CARBON_EVENTS
9889 /* This is needed to send mouse events like aqua window
9890 buttons to the correct handler. */
9891 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9892 != eventNotHandledErr
)
9895 last_mouse_glyph_frame
= 0;
9897 if (dpyinfo
->grabbed
&& last_mouse_frame
9898 && FRAME_LIVE_P (last_mouse_frame
))
9900 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9901 part_code
= inContent
;
9905 part_code
= FindWindow (er
.where
, &window_ptr
);
9906 if (tip_window
&& window_ptr
== tip_window
)
9908 HideWindow (tip_window
);
9909 part_code
= FindWindow (er
.where
, &window_ptr
);
9913 if (er
.what
!= mouseDown
&&
9914 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
9920 f
= mac_focus_frame (dpyinfo
);
9921 saved_menu_event_location
= er
.where
;
9922 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9923 XSETFRAME (inev
.frame_or_window
, f
);
9927 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9928 SelectWindow (window_ptr
);
9931 ControlPartCode control_part_code
;
9933 Point mouse_loc
= er
.where
;
9935 ControlKind control_kind
;
9938 f
= mac_window_to_frame (window_ptr
);
9939 /* convert to local coordinates of new window */
9940 SetPortWindowPort (window_ptr
);
9942 GlobalToLocal (&mouse_loc
);
9943 #if TARGET_API_MAC_CARBON
9944 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9945 &control_part_code
);
9948 GetControlKind (ch
, &control_kind
);
9951 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9955 #if USE_CARBON_EVENTS
9956 inev
.code
= mac_get_mouse_btn (eventRef
);
9957 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9959 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9960 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9962 XSETINT (inev
.x
, mouse_loc
.h
);
9963 XSETINT (inev
.y
, mouse_loc
.v
);
9965 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9967 #ifndef USE_TOOLKIT_SCROLL_BARS
9968 /* control_part_code becomes kControlNoPart if
9969 a progress indicator is clicked. */
9970 && control_part_code
!= kControlNoPart
9971 #else /* USE_TOOLKIT_SCROLL_BARS */
9973 && control_kind
.kind
== kControlKindScrollBar
9974 #endif /* MAC_OSX */
9975 #endif /* USE_TOOLKIT_SCROLL_BARS */
9978 struct scroll_bar
*bar
;
9980 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9982 bar
= tracked_scroll_bar
;
9983 #ifndef USE_TOOLKIT_SCROLL_BARS
9984 control_part_code
= kControlIndicatorPart
;
9988 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9989 #ifdef USE_TOOLKIT_SCROLL_BARS
9990 /* Make the "Ctrl-Mouse-2 splits window" work
9991 for toolkit scroll bars. */
9992 if (er
.modifiers
& controlKey
)
9993 x_scroll_bar_handle_click (bar
, control_part_code
,
9995 else if (er
.what
== mouseDown
)
9996 x_scroll_bar_handle_press (bar
, control_part_code
,
9999 x_scroll_bar_handle_release (bar
, &inev
);
10000 #else /* not USE_TOOLKIT_SCROLL_BARS */
10001 x_scroll_bar_handle_click (bar
, control_part_code
,
10003 if (er
.what
== mouseDown
10004 && control_part_code
== kControlIndicatorPart
)
10005 tracked_scroll_bar
= bar
;
10007 tracked_scroll_bar
= NULL
;
10008 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10012 Lisp_Object window
;
10013 int x
= mouse_loc
.h
;
10014 int y
= mouse_loc
.v
;
10016 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
10017 if (EQ (window
, f
->tool_bar_window
))
10019 if (er
.what
== mouseDown
)
10020 handle_tool_bar_click (f
, x
, y
, 1, 0);
10022 handle_tool_bar_click (f
, x
, y
, 0,
10028 XSETFRAME (inev
.frame_or_window
, f
);
10029 inev
.kind
= MOUSE_CLICK_EVENT
;
10033 if (er
.what
== mouseDown
)
10035 dpyinfo
->grabbed
|= (1 << inev
.code
);
10036 last_mouse_frame
= f
;
10039 last_tool_bar_item
= -1;
10043 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
10044 /* If a button is released though it was not
10045 previously pressed, that would be because
10046 of multi-button emulation. */
10047 dpyinfo
->grabbed
= 0;
10049 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
10052 /* Ignore any mouse motion that happened before
10053 this event; any subsequent mouse-movement Emacs
10054 events should reflect only motion after the
10057 f
->mouse_moved
= 0;
10059 #ifdef USE_TOOLKIT_SCROLL_BARS
10060 if (inev
.kind
== MOUSE_CLICK_EVENT
)
10065 inev
.modifiers
|= down_modifier
;
10068 inev
.modifiers
|= up_modifier
;
10075 #if TARGET_API_MAC_CARBON
10076 DragWindow (window_ptr
, er
.where
, NULL
);
10077 #else /* not TARGET_API_MAC_CARBON */
10078 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10079 #endif /* not TARGET_API_MAC_CARBON */
10080 /* Update the frame parameters. */
10082 struct frame
*f
= mac_window_to_frame (window_ptr
);
10084 if (f
&& !f
->async_iconified
)
10085 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
10090 if (TrackGoAway (window_ptr
, er
.where
))
10092 inev
.kind
= DELETE_WINDOW_EVENT
;
10093 XSETFRAME (inev
.frame_or_window
,
10094 mac_window_to_frame (window_ptr
));
10098 /* window resize handling added --ben */
10100 do_grow_window (window_ptr
, &er
);
10103 /* window zoom handling added --ben */
10106 if (TrackBox (window_ptr
, er
.where
, part_code
))
10107 do_zoom_window (window_ptr
, part_code
);
10117 #if USE_CARBON_EVENTS
10118 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10119 != eventNotHandledErr
)
10122 do_window_update ((WindowPtr
) er
.message
);
10127 #if USE_CARBON_EVENTS
10128 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10129 != eventNotHandledErr
)
10132 switch ((er
.message
>> 24) & 0x000000FF)
10134 case suspendResumeMessage
:
10135 if ((er
.message
& resumeFlag
) == 1)
10141 case mouseMovedMessage
:
10142 #if !USE_CARBON_EVENTS
10143 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
10144 er
.where
.h
+ 1, er
.where
.v
+ 1);
10146 previous_help_echo_string
= help_echo_string
;
10147 help_echo_string
= Qnil
;
10149 if (dpyinfo
->grabbed
&& last_mouse_frame
10150 && FRAME_LIVE_P (last_mouse_frame
))
10151 f
= last_mouse_frame
;
10153 f
= dpyinfo
->x_focus_frame
;
10155 if (dpyinfo
->mouse_face_hidden
)
10157 dpyinfo
->mouse_face_hidden
= 0;
10158 clear_mouse_face (dpyinfo
);
10163 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
10164 Point mouse_pos
= er
.where
;
10166 SetPortWindowPort (wp
);
10168 GlobalToLocal (&mouse_pos
);
10170 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10171 #ifdef USE_TOOLKIT_SCROLL_BARS
10172 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
10174 #else /* not USE_TOOLKIT_SCROLL_BARS */
10175 x_scroll_bar_note_movement (tracked_scroll_bar
,
10177 - XINT (tracked_scroll_bar
->top
),
10178 er
.when
* (1000 / 60));
10179 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10182 /* Generate SELECT_WINDOW_EVENTs when needed. */
10183 if (mouse_autoselect_window
)
10185 Lisp_Object window
;
10187 window
= window_from_coordinates (f
,
10192 /* Window will be selected only when it is
10193 not selected now and last mouse movement
10194 event was not in it. Minibuffer window
10195 will be selected iff it is active. */
10196 if (WINDOWP (window
)
10197 && !EQ (window
, last_window
)
10198 && !EQ (window
, selected_window
))
10200 inev
.kind
= SELECT_WINDOW_EVENT
;
10201 inev
.frame_or_window
= window
;
10204 last_window
=window
;
10206 if (!note_mouse_movement (f
, &mouse_pos
))
10207 help_echo_string
= previous_help_echo_string
;
10211 /* If the contents of the global variable
10212 help_echo_string has changed, generate a
10214 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10222 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10224 #if USE_CARBON_EVENTS
10225 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10226 != eventNotHandledErr
)
10229 if (window_ptr
== tip_window
)
10231 HideWindow (tip_window
);
10235 if (!is_emacs_window (window_ptr
))
10238 if ((er
.modifiers
& activeFlag
) != 0)
10240 /* A window has been activated */
10241 Point mouse_loc
= er
.where
;
10243 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10245 SetPortWindowPort (window_ptr
);
10246 GlobalToLocal (&mouse_loc
);
10247 /* Window-activated event counts as mouse movement,
10248 so update things that depend on mouse position. */
10249 note_mouse_movement (mac_window_to_frame (window_ptr
),
10254 /* A window has been deactivated */
10255 #if USE_TOOLKIT_SCROLL_BARS
10256 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10258 struct input_event event
;
10260 EVENT_INIT (event
);
10261 event
.kind
= NO_EVENT
;
10262 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10263 if (event
.kind
!= NO_EVENT
)
10265 event
.timestamp
= timestamp
;
10266 kbd_buffer_store_event_hold (&event
, hold_quit
);
10271 dpyinfo
->grabbed
= 0;
10273 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10275 f
= mac_window_to_frame (window_ptr
);
10276 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10278 /* If we move outside the frame, then we're
10279 certainly no longer on any text in the
10281 clear_mouse_face (dpyinfo
);
10282 dpyinfo
->mouse_face_mouse_frame
= 0;
10285 /* Generate a nil HELP_EVENT to cancel a help-echo.
10286 Do it only if there's something to cancel.
10287 Otherwise, the startup message is cleared when the
10288 mouse leaves the frame. */
10289 if (any_help_event_p
)
10298 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10301 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10302 /* When using Carbon Events, we need to pass raw keyboard
10303 events to the TSM ourselves. If TSM handles it, it
10304 will pass back noErr, otherwise it will pass back
10305 "eventNotHandledErr" and we can process it
10307 if ((mac_pass_command_to_system
10308 || !(er
.modifiers
& cmdKey
))
10309 && (mac_pass_control_to_system
10310 || !(er
.modifiers
& controlKey
))
10311 && (NILP (Vmac_option_modifier
)
10312 || !(er
.modifiers
& optionKey
)))
10313 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10314 != eventNotHandledErr
)
10319 if (dpyinfo
->x_focus_frame
== NULL
)
10321 /* Beep if keyboard input occurs when all the frames
10329 static SInt16 last_key_script
= -1;
10330 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10332 if (last_key_script
!= current_key_script
)
10334 struct input_event event
;
10336 EVENT_INIT (event
);
10337 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10339 event
.code
= current_key_script
;
10340 event
.timestamp
= timestamp
;
10341 kbd_buffer_store_event (&event
);
10344 last_key_script
= current_key_script
;
10349 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10351 clear_mouse_face (dpyinfo
);
10352 dpyinfo
->mouse_face_hidden
= 1;
10355 /* translate the keycode back to determine the original key */
10356 /* Convert key code if function key is pressed.
10357 Otherwise, if non-ASCII-event, take care of that
10358 without re-translating the key code. */
10359 #if USE_CARBON_EVENTS
10360 if (convert_fn_keycode (eventRef
, keycode
, &xkeysym
))
10362 inev
.code
= xkeysym
;
10363 /* this doesn't work - tried to add shift modifiers */
10365 backtranslate_modified_keycode(er
.modifiers
& (~0x2200),
10366 xkeysym
| 0x80, xkeysym
);
10367 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10371 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10373 inev
.code
= 0xff00 | xkeysym
;
10374 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10379 backtranslate_modified_keycode(er
.modifiers
, keycode
,
10380 er
.message
& charCodeMask
);
10381 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10385 #if USE_CARBON_EVENTS
10386 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10388 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10390 inev
.modifiers
|= (extra_keyboard_modifiers
10391 & (meta_modifier
| alt_modifier
10392 | hyper_modifier
| super_modifier
));
10393 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10396 case kHighLevelEvent
:
10397 read_socket_inev
= &inev
;
10398 AEProcessAppleEvent (&er
);
10399 read_socket_inev
= NULL
;
10405 #if USE_CARBON_EVENTS
10406 ReleaseEvent (eventRef
);
10409 if (inev
.kind
!= NO_EVENT
)
10411 inev
.timestamp
= timestamp
;
10412 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10417 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10422 XSETFRAME (frame
, f
);
10428 any_help_event_p
= 1;
10429 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10430 help_echo_object
, help_echo_pos
);
10434 help_echo_string
= Qnil
;
10435 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10442 /* If the focus was just given to an autoraising frame,
10444 /* ??? This ought to be able to handle more than one such frame. */
10445 if (pending_autoraise_frame
)
10447 x_raise_frame (pending_autoraise_frame
);
10448 pending_autoraise_frame
= 0;
10451 #if !USE_CARBON_EVENTS
10452 /* Check which frames are still visible. We do this here because
10453 there doesn't seem to be any direct notification from the Window
10454 Manager that the visibility of a window has changed (at least,
10455 not in all cases). */
10457 Lisp_Object tail
, frame
;
10459 FOR_EACH_FRAME (tail
, frame
)
10461 struct frame
*f
= XFRAME (frame
);
10463 /* The tooltip has been drawn already. Avoid the
10464 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10465 if (EQ (frame
, tip_frame
))
10468 if (FRAME_MAC_P (f
))
10469 mac_handle_visibility_change (f
);
10480 /* Need to override CodeWarrior's input function so no conversion is
10481 done on newlines Otherwise compiled functions in .elc files will be
10482 read incorrectly. Defined in ...:MSL C:MSL
10483 Common:Source:buffer_io.c. */
10486 __convert_to_newlines (unsigned char * p
, size_t * n
)
10488 #pragma unused(p,n)
10492 __convert_from_newlines (unsigned char * p
, size_t * n
)
10494 #pragma unused(p,n)
10500 make_mac_terminal_frame (struct frame
*f
)
10505 XSETFRAME (frame
, f
);
10507 f
->output_method
= output_mac
;
10508 f
->output_data
.mac
= (struct mac_output
*)
10509 xmalloc (sizeof (struct mac_output
));
10510 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10512 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10514 FRAME_COLS (f
) = 96;
10515 FRAME_LINES (f
) = 4;
10517 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10518 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10520 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10522 f
->output_data
.mac
->cursor_pixel
= 0;
10523 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10524 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10525 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10527 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10528 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10529 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10530 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10531 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10532 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10534 FRAME_FONTSET (f
) = -1;
10535 f
->output_data
.mac
->explicit_parent
= 0;
10538 f
->border_width
= 0;
10540 f
->internal_border_width
= 0;
10545 f
->new_text_cols
= 0;
10546 f
->new_text_lines
= 0;
10548 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10549 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10550 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10554 if (!(FRAME_MAC_WINDOW (f
) =
10555 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10556 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10558 /* so that update events can find this mac_output struct */
10559 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10565 /* Need to be initialized for unshow_buffer in window.c. */
10566 selected_window
= f
->selected_window
;
10568 Fmodify_frame_parameters (frame
,
10569 Fcons (Fcons (Qfont
,
10570 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10571 Fmodify_frame_parameters (frame
,
10572 Fcons (Fcons (Qforeground_color
,
10573 build_string ("black")), Qnil
));
10574 Fmodify_frame_parameters (frame
,
10575 Fcons (Fcons (Qbackground_color
,
10576 build_string ("white")), Qnil
));
10581 /***********************************************************************
10583 ***********************************************************************/
10585 int mac_initialized
= 0;
10588 mac_initialize_display_info ()
10590 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10591 GDHandle main_device_handle
;
10593 bzero (dpyinfo
, sizeof (*dpyinfo
));
10596 dpyinfo
->mac_id_name
10597 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10598 + SCHARS (Vsystem_name
)
10600 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10601 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10603 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10604 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10607 main_device_handle
= LMGetMainDevice();
10609 dpyinfo
->reference_count
= 0;
10610 dpyinfo
->resx
= 72.0;
10611 dpyinfo
->resy
= 72.0;
10612 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10614 /* HasDepth returns true if it is possible to have a 32 bit display,
10615 but this may not be what is actually used. Mac OSX can do better.
10616 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10617 header for CGGetActiveDisplayList says that the first display returned
10618 is the active one, so we use that. */
10620 CGDirectDisplayID disp_id
[1];
10621 CGDisplayCount disp_count
;
10622 CGDisplayErr error_code
;
10624 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10625 if (error_code
!= 0)
10626 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10628 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10631 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10632 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10633 gdDevType
, dpyinfo
->color_p
))
10636 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10637 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10638 dpyinfo
->grabbed
= 0;
10639 dpyinfo
->root_window
= NULL
;
10640 dpyinfo
->image_cache
= make_image_cache ();
10642 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10643 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10644 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10645 dpyinfo
->mouse_face_window
= Qnil
;
10646 dpyinfo
->mouse_face_overlay
= Qnil
;
10647 dpyinfo
->mouse_face_hidden
= 0;
10652 mac_make_rdb (xrm_option
)
10655 XrmDatabase database
;
10657 database
= xrm_get_preference_database (NULL
);
10659 xrm_merge_string_database (database
, xrm_option
);
10664 struct mac_display_info
*
10665 mac_term_init (display_name
, xrm_option
, resource_name
)
10666 Lisp_Object display_name
;
10668 char *resource_name
;
10670 struct mac_display_info
*dpyinfo
;
10674 if (!mac_initialized
)
10677 mac_initialized
= 1;
10680 if (x_display_list
)
10681 error ("Sorry, this version can only handle one display");
10683 mac_initialize_display_info ();
10685 dpyinfo
= &one_mac_display_info
;
10687 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10689 /* Put this display on the chain. */
10690 dpyinfo
->next
= x_display_list
;
10691 x_display_list
= dpyinfo
;
10693 /* Put it on x_display_name_list. */
10694 x_display_name_list
= Fcons (Fcons (display_name
,
10695 Fcons (Qnil
, dpyinfo
->xrdb
)),
10696 x_display_name_list
);
10697 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10703 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10706 x_delete_display (dpyinfo
)
10707 struct mac_display_info
*dpyinfo
;
10711 /* Discard this display from x_display_name_list and x_display_list.
10712 We can't use Fdelq because that can quit. */
10713 if (! NILP (x_display_name_list
)
10714 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10715 x_display_name_list
= XCDR (x_display_name_list
);
10720 tail
= x_display_name_list
;
10721 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10723 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10725 XSETCDR (tail
, XCDR (XCDR (tail
)));
10728 tail
= XCDR (tail
);
10732 if (x_display_list
== dpyinfo
)
10733 x_display_list
= dpyinfo
->next
;
10736 struct x_display_info
*tail
;
10738 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10739 if (tail
->next
== dpyinfo
)
10740 tail
->next
= tail
->next
->next
;
10743 /* Free the font names in the font table. */
10744 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10745 if (dpyinfo
->font_table
[i
].name
)
10747 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10748 xfree (dpyinfo
->font_table
[i
].full_name
);
10749 xfree (dpyinfo
->font_table
[i
].name
);
10752 if (dpyinfo
->font_table
->font_encoder
)
10753 xfree (dpyinfo
->font_table
->font_encoder
);
10755 xfree (dpyinfo
->font_table
);
10756 xfree (dpyinfo
->mac_id_name
);
10758 if (x_display_list
== 0)
10760 mac_clear_font_name_table ();
10761 bzero (dpyinfo
, sizeof (*dpyinfo
));
10770 extern int inhibit_window_system
;
10771 extern int noninteractive
;
10772 CFBundleRef appsBundle
;
10775 /* No need to test if already -nw*/
10776 if (inhibit_window_system
|| noninteractive
)
10779 appsBundle
= CFBundleGetMainBundle();
10780 if (appsBundle
!= NULL
)
10782 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10783 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10784 /* We found the bundle identifier, now we know we are valid. */
10791 /* MAC_TODO: Have this start the bundled executable */
10793 /* For now, prevent the fatal error by bringing it up in the terminal */
10794 inhibit_window_system
= 1;
10798 MakeMeTheFrontProcess ()
10800 ProcessSerialNumber psn
;
10803 err
= GetCurrentProcess (&psn
);
10805 (void) SetFrontProcess (&psn
);
10808 /***** Code to handle C-g testing *****/
10810 /* Contains the Mac modifier formed from quit_char */
10811 int mac_quit_char_modifiers
= 0;
10812 int mac_quit_char_keycode
;
10813 extern int quit_char
;
10816 mac_determine_quit_char_modifiers()
10818 /* Todo: Determine modifiers from quit_char. */
10819 UInt32 qc_modifiers
= ctrl_modifier
;
10821 /* Map modifiers */
10822 mac_quit_char_modifiers
= 0;
10823 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
10824 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
10825 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
10829 init_quit_char_handler ()
10831 /* TODO: Let this support keys other the 'g' */
10832 mac_quit_char_keycode
= 5;
10833 /* Look at <architecture/adb_kb_map.h> for details */
10834 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10836 mac_determine_quit_char_modifiers();
10838 #endif /* MAC_OSX */
10846 MenuItemIndex menu_index
;
10848 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10849 &menu
, &menu_index
);
10851 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10852 #if USE_CARBON_EVENTS
10853 EnableMenuCommand (NULL
, kHICommandPreferences
);
10854 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10855 &menu
, &menu_index
);
10858 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10859 InsertMenuItemTextWithCFString (menu
, NULL
,
10860 0, kMenuItemAttrSeparator
, 0);
10861 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10862 0, 0, kHICommandAbout
);
10864 #endif /* USE_CARBON_EVENTS */
10865 #else /* !MAC_OSX */
10866 #if USE_CARBON_EVENTS
10867 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10873 /* Set up use of X before we make the first connection. */
10875 extern frame_parm_handler mac_frame_parm_handlers
[];
10877 static struct redisplay_interface x_redisplay_interface
=
10879 mac_frame_parm_handlers
,
10883 x_clear_end_of_line
,
10885 x_after_update_window_line
,
10886 x_update_window_begin
,
10887 x_update_window_end
,
10890 0, /* flush_display_optional */
10891 x_clear_window_mouse_face
,
10892 x_get_glyph_overhangs
,
10893 x_fix_overlapping_area
,
10894 x_draw_fringe_bitmap
,
10895 0, /* define_fringe_bitmap */
10896 0, /* destroy_fringe_bitmap */
10897 mac_per_char_metric
,
10899 mac_compute_glyph_string_overhangs
,
10900 x_draw_glyph_string
,
10901 mac_define_frame_cursor
,
10902 mac_clear_frame_area
,
10903 mac_draw_window_cursor
,
10904 mac_draw_vertical_window_border
,
10905 mac_shift_glyphs_for_insert
10911 rif
= &x_redisplay_interface
;
10913 clear_frame_hook
= x_clear_frame
;
10914 ins_del_lines_hook
= x_ins_del_lines
;
10915 delete_glyphs_hook
= x_delete_glyphs
;
10916 ring_bell_hook
= XTring_bell
;
10917 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10918 set_terminal_modes_hook
= XTset_terminal_modes
;
10919 update_begin_hook
= x_update_begin
;
10920 update_end_hook
= x_update_end
;
10921 set_terminal_window_hook
= XTset_terminal_window
;
10922 read_socket_hook
= XTread_socket
;
10923 frame_up_to_date_hook
= XTframe_up_to_date
;
10924 mouse_position_hook
= XTmouse_position
;
10925 frame_rehighlight_hook
= XTframe_rehighlight
;
10926 frame_raise_lower_hook
= XTframe_raise_lower
;
10928 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10929 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10930 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10931 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10933 scroll_region_ok
= 1; /* we'll scroll partial frames */
10934 char_ins_del_ok
= 1;
10935 line_ins_del_ok
= 1; /* we'll just blt 'em */
10936 fast_clear_end_of_line
= 1; /* X does this well */
10937 memory_below_frame
= 0; /* we don't remember what scrolls
10941 last_tool_bar_item
= -1;
10942 any_help_event_p
= 0;
10944 /* Try to use interrupt input; if we can't, then start polling. */
10945 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10949 #if TARGET_API_MAC_CARBON
10951 #if USE_CARBON_EVENTS
10953 init_service_handler ();
10955 init_quit_char_handler ();
10956 #endif /* MAC_OSX */
10958 init_command_handler ();
10961 #endif /* USE_CARBON_EVENTS */
10964 init_coercion_handler ();
10966 init_apple_event_handler ();
10968 if (!inhibit_window_system
)
10969 MakeMeTheFrontProcess ();
10980 staticpro (&x_error_message_string
);
10981 x_error_message_string
= Qnil
;
10984 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
10985 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
10986 Qalt
= intern ("alt"); staticpro (&Qalt
);
10987 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
10988 Qsuper
= intern ("super"); staticpro (&Qsuper
);
10989 Qmodifier_value
= intern ("modifier-value");
10990 staticpro (&Qmodifier_value
);
10992 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
10993 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10994 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10995 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10996 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10998 #if USE_CARBON_EVENTS
10999 Qhicommand
= intern ("hicommand"); staticpro (&Qhicommand
);
11001 Qservices
= intern ("services"); staticpro (&Qservices
);
11002 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
11003 Qperform
= intern ("perform"); staticpro (&Qperform
);
11008 Fprovide (intern ("mac-carbon"), Qnil
);
11011 staticpro (&Qreverse
);
11012 Qreverse
= intern ("reverse");
11014 staticpro (&x_display_name_list
);
11015 x_display_name_list
= Qnil
;
11017 staticpro (&last_mouse_scroll_bar
);
11018 last_mouse_scroll_bar
= Qnil
;
11020 staticpro (&fm_font_family_alist
);
11021 fm_font_family_alist
= Qnil
;
11024 staticpro (&atsu_font_id_hash
);
11025 atsu_font_id_hash
= Qnil
;
11028 /* We don't yet support this, but defining this here avoids whining
11029 from cus-start.el and other places, like "M-x set-variable". */
11030 DEFVAR_BOOL ("x-use-underline-position-properties",
11031 &x_use_underline_position_properties
,
11032 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11033 nil means ignore them. If you encounter fonts with bogus
11034 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11035 to 4.1, set this to nil.
11037 NOTE: Not supported on Mac yet. */);
11038 x_use_underline_position_properties
= 0;
11040 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
11041 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
11042 #ifdef USE_TOOLKIT_SCROLL_BARS
11043 Vx_toolkit_scroll_bars
= Qt
;
11045 Vx_toolkit_scroll_bars
= Qnil
;
11048 staticpro (&last_mouse_motion_frame
);
11049 last_mouse_motion_frame
= Qnil
;
11051 /* Variables to configure modifier key assignment. */
11053 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
11054 doc
: /* *Modifier key assumed when the Mac control key is pressed.
11055 The value can be `control', `meta', `alt', `hyper', or `super' for the
11056 respective modifier. The default is `control'. */);
11057 Vmac_control_modifier
= Qcontrol
;
11059 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
11060 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
11061 The value can be `control', `meta', `alt', `hyper', or `super' for the
11062 respective modifier. If the value is nil then the key will act as the
11063 normal Mac control modifier, and the option key can be used to compose
11064 characters depending on the chosen Mac keyboard setting. */);
11065 Vmac_option_modifier
= Qnil
;
11067 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
11068 doc
: /* *Modifier key assumed when the Mac command key is pressed.
11069 The value can be `control', `meta', `alt', `hyper', or `super' for the
11070 respective modifier. The default is `meta'. */);
11071 Vmac_command_modifier
= Qmeta
;
11073 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
11074 doc
: /* *Modifier key assumed when the Mac function key is pressed.
11075 The value can be `control', `meta', `alt', `hyper', or `super' for the
11076 respective modifier. Note that remapping the function key may lead to
11077 unexpected results for some keys on non-US/GB keyboards. */);
11078 Vmac_function_modifier
= Qnil
;
11080 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11081 &Vmac_emulate_three_button_mouse
,
11082 doc
: /* *Specify a way of three button mouse emulation.
11083 The value can be nil, t, or the symbol `reverse'.
11084 nil means that no emulation should be done and the modifiers should be
11085 placed on the mouse-1 event.
11086 t means that when the option-key is held down while pressing the mouse
11087 button, the click will register as mouse-2 and while the command-key
11088 is held down, the click will register as mouse-3.
11089 The symbol `reverse' means that the option-key will register for
11090 mouse-3 and the command-key will register for mouse-2. */);
11091 Vmac_emulate_three_button_mouse
= Qnil
;
11093 #if USE_CARBON_EVENTS
11094 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
11095 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11096 Otherwise, the right click will be treated as mouse-2 and the wheel
11097 button will be mouse-3. */);
11098 mac_wheel_button_is_mouse_2
= 1;
11100 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
11101 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
11102 mac_pass_command_to_system
= 1;
11104 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
11105 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
11106 mac_pass_control_to_system
= 1;
11110 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
11111 doc
: /* *If non-nil, allow anti-aliasing.
11112 The text will be rendered using Core Graphics text rendering which
11113 may anti-alias the text. */);
11114 mac_use_core_graphics
= 0;
11116 /* Register an entry for `mac-roman' so that it can be used when
11117 creating the terminal frame on Mac OS 9 before loading
11118 term/mac-win.elc. */
11119 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
11120 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
11121 Each entry should be of the form:
11123 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
11125 where CHARSET-NAME is a string used in font names to identify the
11126 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
11127 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
11128 Vmac_charset_info_alist
=
11129 Fcons (list3 (build_string ("mac-roman"),
11130 make_number (smRoman
), Qnil
), Qnil
);
11133 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
11134 (do not change this comment) */