1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005 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 */
71 #include <sys/param.h>
76 #include "dispextern.h"
78 #include "termhooks.h"
86 #include "intervals.h"
92 /* Non-nil means Emacs uses toolkit scroll bars. */
94 Lisp_Object Vx_toolkit_scroll_bars
;
96 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
97 Lisp_Object Vmac_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 /* This is a chain of structures for all the X displays currently in
111 struct x_display_info
*x_display_list
;
113 /* This is a list of cons cells, each of the form (NAME
114 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
115 x_display_list and in the same order. NAME is the name of the
116 frame. FONT-LIST-CACHE records previous values returned by
117 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
118 equivalent, which is implemented with a Lisp object, for the
121 Lisp_Object x_display_name_list
;
123 /* This is display since Mac does not support multiple ones. */
124 struct mac_display_info one_mac_display_info
;
126 /* Frame being updated by update_frame. This is declared in term.c.
127 This is set by update_begin and looked at by all the XT functions.
128 It is zero while not inside an update. In that case, the XT
129 functions assume that `selected_frame' is the frame to apply to. */
131 extern struct frame
*updating_frame
;
133 /* This is a frame waiting to be auto-raised, within XTread_socket. */
135 struct frame
*pending_autoraise_frame
;
139 Formerly, we used PointerMotionHintMask (in standard_event_mask)
140 so that we would have to call XQueryPointer after each MotionNotify
141 event to ask for another such event. However, this made mouse tracking
142 slow, and there was a bug that made it eventually stop.
144 Simply asking for MotionNotify all the time seems to work better.
146 In order to avoid asking for motion events and then throwing most
147 of them away or busy-polling the server for mouse positions, we ask
148 the server for pointer motion hints. This means that we get only
149 one event per group of mouse movements. "Groups" are delimited by
150 other kinds of events (focus changes and button clicks, for
151 example), or by XQueryPointer calls; when one of these happens, we
152 get another MotionNotify event the next time the mouse moves. This
153 is at least as efficient as getting motion events when mouse
154 tracking is on, and I suspect only negligibly worse when tracking
157 /* Where the mouse was last time we reported a mouse event. */
159 static Rect last_mouse_glyph
;
160 static FRAME_PTR last_mouse_glyph_frame
;
162 /* The scroll bar in which the last X motion event occurred.
164 If the last X motion event occurred in a scroll bar, we set this so
165 XTmouse_position can know whether to report a scroll bar motion or
168 If the last X motion event didn't occur in a scroll bar, we set
169 this to Qnil, to tell XTmouse_position to return an ordinary motion
172 static Lisp_Object last_mouse_scroll_bar
;
174 /* This is a hack. We would really prefer that XTmouse_position would
175 return the time associated with the position it returns, but there
176 doesn't seem to be any way to wrest the time-stamp from the server
177 along with the position query. So, we just keep track of the time
178 of the last movement we received, and return that in hopes that
179 it's somewhat accurate. */
181 static Time last_mouse_movement_time
;
183 struct scroll_bar
*tracked_scroll_bar
= NULL
;
185 /* Incremented by XTread_socket whenever it really tries to read
189 static int volatile input_signal_count
;
191 static int input_signal_count
;
194 extern Lisp_Object Vsystem_name
;
196 /* A mask of extra modifier bits to put into every keyboard char. */
198 extern EMACS_INT extra_keyboard_modifiers
;
200 /* The keysyms to use for the various modifiers. */
202 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
,
203 Qmeta
, Qmodifier_value
;
205 extern int inhibit_window_system
;
207 #if __MRC__ && !TARGET_API_MAC_CARBON
208 QDGlobals qd
; /* QuickDraw global information structure. */
211 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
213 struct mac_display_info
*mac_display_info_for_display (Display
*);
214 static void x_update_window_end
P_ ((struct window
*, int, int));
215 static int x_io_error_quitter
P_ ((Display
*));
216 int x_catch_errors
P_ ((Display
*));
217 void x_uncatch_errors
P_ ((Display
*, int));
218 void x_lower_frame
P_ ((struct frame
*));
219 void x_scroll_bar_clear
P_ ((struct frame
*));
220 int x_had_errors_p
P_ ((Display
*));
221 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
222 void x_raise_frame
P_ ((struct frame
*));
223 void x_set_window_size
P_ ((struct frame
*, int, int, int));
224 void x_wm_set_window_state
P_ ((struct frame
*, int));
225 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
226 void mac_initialize
P_ ((void));
227 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
228 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
229 static void x_update_end
P_ ((struct frame
*));
230 static void XTframe_up_to_date
P_ ((struct frame
*));
231 static void XTset_terminal_modes
P_ ((void));
232 static void XTreset_terminal_modes
P_ ((void));
233 static void x_clear_frame
P_ ((void));
234 static void frame_highlight
P_ ((struct frame
*));
235 static void frame_unhighlight
P_ ((struct frame
*));
236 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
237 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
238 struct frame
*, struct input_event
*));
239 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
240 EventRecord
*, struct input_event
*));
241 static void XTframe_rehighlight
P_ ((struct frame
*));
242 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
243 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
244 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
245 enum text_cursor_kinds
));
247 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
248 static void x_flush
P_ ((struct frame
*f
));
249 static void x_update_begin
P_ ((struct frame
*));
250 static void x_update_window_begin
P_ ((struct window
*));
251 static void x_after_update_window_line
P_ ((struct glyph_row
*));
252 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
253 enum scroll_bar_part
*,
254 Lisp_Object
*, Lisp_Object
*,
257 static int is_emacs_window
P_ ((WindowPtr
));
259 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
261 /* Defined in macmenu.h. */
262 extern void menubar_selection_callback (FRAME_PTR
, int);
264 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
265 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
266 #define GC_FONT(gc) ((gc)->xgcv.font)
267 #define GC_CLIP_REGION(gc) ((gc)->clip_region)
268 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
270 static RgnHandle saved_port_clip_region
= NULL
;
273 mac_begin_clip (region
)
276 static RgnHandle new_region
= NULL
;
278 if (saved_port_clip_region
== NULL
)
279 saved_port_clip_region
= NewRgn ();
280 if (new_region
== NULL
)
281 new_region
= NewRgn ();
285 GetClip (saved_port_clip_region
);
286 SectRgn (saved_port_clip_region
, region
, new_region
);
287 SetClip (new_region
);
292 mac_end_clip (region
)
296 SetClip (saved_port_clip_region
);
300 /* X display function emulation */
303 XFreePixmap (display
, pixmap
)
304 Display
*display
; /* not used */
307 DisposeGWorld (pixmap
);
311 /* Mac version of XDrawLine. */
314 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
319 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
321 RGBForeColor (GC_FORE_COLOR (gc
));
323 mac_begin_clip (GC_CLIP_REGION (gc
));
326 mac_end_clip (GC_CLIP_REGION (gc
));
330 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
339 GetGWorld (&old_port
, &old_gdh
);
342 RGBForeColor (GC_FORE_COLOR (gc
));
344 LockPixels (GetGWorldPixMap (p
));
347 UnlockPixels (GetGWorldPixMap (p
));
349 SetGWorld (old_port
, old_gdh
);
354 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
358 unsigned int width
, height
;
362 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
364 RGBBackColor (GC_BACK_COLOR (gc
));
365 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
367 mac_begin_clip (GC_CLIP_REGION (gc
));
369 mac_end_clip (GC_CLIP_REGION (gc
));
371 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
375 /* Mac version of XClearArea. */
378 mac_clear_area (f
, x
, y
, width
, height
)
381 unsigned int width
, height
;
383 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
386 /* Mac version of XClearWindow. */
392 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
394 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
396 #if TARGET_API_MAC_CARBON
400 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
403 #else /* not TARGET_API_MAC_CARBON */
404 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
405 #endif /* not TARGET_API_MAC_CARBON */
409 /* Mac replacement for XCopyArea. */
412 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
415 int x
, y
, width
, height
;
416 unsigned short *bits
;
422 bitmap
.rowBytes
= sizeof(unsigned short);
423 bitmap
.baseAddr
= (char *)bits
;
424 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
426 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
428 RGBForeColor (GC_FORE_COLOR (gc
));
429 RGBBackColor (GC_BACK_COLOR (gc
));
430 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
432 mac_begin_clip (GC_CLIP_REGION (gc
));
433 #if TARGET_API_MAC_CARBON
439 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
440 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
441 UnlockPortBits (port
);
443 #else /* not TARGET_API_MAC_CARBON */
444 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
445 overlay_p
? srcOr
: srcCopy
, 0);
446 #endif /* not TARGET_API_MAC_CARBON */
447 mac_end_clip (GC_CLIP_REGION (gc
));
449 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
453 /* Mac replacement for XCreateBitmapFromBitmapData. */
456 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
461 static unsigned char swap_nibble
[16]
462 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
463 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
464 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
465 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
469 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
470 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
471 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
472 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
473 for (i
= 0; i
< h
; i
++)
475 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
476 for (j
= 0; j
< w1
; j
++)
478 /* Bitswap XBM bytes to match how Mac does things. */
479 unsigned char c
= *bits
++;
480 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
481 | (swap_nibble
[(c
>>4) & 0xf]));;
485 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
490 mac_free_bitmap (bitmap
)
493 xfree (bitmap
->baseAddr
);
498 XCreatePixmap (display
, w
, width
, height
, depth
)
499 Display
*display
; /* not used */
501 unsigned int width
, height
;
508 SetPortWindowPort (w
);
510 SetRect (&r
, 0, 0, width
, height
);
511 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
519 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
520 Display
*display
; /* not used */
523 unsigned int width
, height
;
524 unsigned long fg
, bg
;
531 static GC gc
= NULL
; /* not reentrant */
534 gc
= XCreateGC (display
, w
, 0, NULL
);
536 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
540 GetGWorld (&old_port
, &old_gdh
);
541 SetGWorld (pixmap
, NULL
);
542 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
543 XSetForeground (display
, gc
, fg
);
544 XSetBackground (display
, gc
, bg
);
545 RGBForeColor (GC_FORE_COLOR (gc
));
546 RGBBackColor (GC_BACK_COLOR (gc
));
547 LockPixels (GetGWorldPixMap (pixmap
));
548 #if TARGET_API_MAC_CARBON
549 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
550 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
551 #else /* not TARGET_API_MAC_CARBON */
552 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
553 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
554 #endif /* not TARGET_API_MAC_CARBON */
555 UnlockPixels (GetGWorldPixMap (pixmap
));
556 SetGWorld (old_port
, old_gdh
);
557 mac_free_bitmap (&bitmap
);
563 /* Mac replacement for XFillRectangle. */
566 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
570 unsigned int width
, height
;
574 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
576 RGBForeColor (GC_FORE_COLOR (gc
));
577 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
579 mac_begin_clip (GC_CLIP_REGION (gc
));
580 PaintRect (&r
); /* using foreground color of gc */
581 mac_end_clip (GC_CLIP_REGION (gc
));
585 /* Mac replacement for XDrawRectangle: dest is a window. */
588 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
592 unsigned int width
, height
;
596 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
598 RGBForeColor (GC_FORE_COLOR (gc
));
599 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
601 mac_begin_clip (GC_CLIP_REGION (gc
));
602 FrameRect (&r
); /* using foreground color of gc */
603 mac_end_clip (GC_CLIP_REGION (gc
));
609 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
610 ConstUniCharArrayPtr text
;
611 UniCharCount text_length
;
613 ATSUTextLayout
*text_layout
;
616 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
618 if (saved_text_layout
== NULL
)
620 UniCharCount lengths
[] = {kATSUToTextEnd
};
621 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
622 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
623 static ATSLineLayoutOptions line_layout
=
624 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
625 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
627 kATSLineIsDisplayOnly
| kATSLineFractDisable
630 ATSUAttributeValuePtr values
[] = {&line_layout
};
632 err
= ATSUCreateTextLayoutWithTextPtr (text
,
633 kATSUFromTextBeginning
,
639 err
= ATSUSetLayoutControls (saved_text_layout
,
640 sizeof (tags
) / sizeof (tags
[0]),
641 tags
, sizes
, values
);
642 /* XXX: Should we do this? */
644 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
648 err
= ATSUSetRunStyle (saved_text_layout
, style
,
649 kATSUFromTextBeginning
, kATSUToTextEnd
);
651 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
652 kATSUFromTextBeginning
,
658 *text_layout
= saved_text_layout
;
665 mac_invert_rectangle (f
, x
, y
, width
, height
)
668 unsigned int width
, height
;
672 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
674 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
681 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, mode
, bytes_per_char
)
686 int nchars
, mode
, bytes_per_char
;
688 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
689 UInt32 textFlags
, savedFlags
;
690 if (!NILP(Vmac_use_core_graphics
)) {
691 textFlags
= kQDUseCGTextRendering
;
692 savedFlags
= SwapQDTextFlags(textFlags
);
696 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
698 RGBForeColor (GC_FORE_COLOR (gc
));
700 RGBBackColor (GC_BACK_COLOR (gc
));
703 if (GC_FONT (gc
)->mac_style
)
706 ATSUTextLayout text_layout
;
708 xassert (bytes_per_char
== 2);
710 #ifndef WORDS_BIG_ENDIAN
713 UniChar
*text
= (UniChar
*)buf
;
715 for (i
= 0; i
< nchars
; i
++)
716 text
[i
] = EndianU16_BtoN (text
[i
]);
719 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
721 GC_FONT (gc
)->mac_style
,
726 if (NILP (Vmac_use_core_graphics
))
729 mac_begin_clip (GC_CLIP_REGION (gc
));
731 ATSUDrawText (text_layout
,
732 kATSUFromTextBeginning
, kATSUToTextEnd
,
733 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
734 mac_end_clip (GC_CLIP_REGION (gc
));
740 CGContextRef context
;
741 float port_height
= FRAME_PIXEL_HEIGHT (f
);
742 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
743 ByteCount sizes
[] = {sizeof (CGContextRef
)};
744 ATSUAttributeValuePtr values
[] = {&context
};
747 QDBeginCGContext (port
, &context
);
748 if (gc
->n_clip_rects
)
750 CGContextTranslateCTM (context
, 0, port_height
);
751 CGContextScaleCTM (context
, 1, -1);
752 CGContextClipToRects (context
, gc
->clip_rects
,
754 CGContextScaleCTM (context
, 1, -1);
755 CGContextTranslateCTM (context
, 0, -port_height
);
757 CGContextSetRGBFillColor
759 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
760 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
761 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
763 err
= ATSUSetLayoutControls (text_layout
,
764 sizeof (tags
) / sizeof (tags
[0]),
765 tags
, sizes
, values
);
767 ATSUDrawText (text_layout
,
768 kATSUFromTextBeginning
, kATSUToTextEnd
,
769 Long2Fix (x
), Long2Fix (port_height
- y
));
770 CGContextSynchronize (context
);
771 QDEndCGContext (port
, &context
);
773 /* This doesn't work on Mac OS X 10.1. */
774 ATSUClearLayoutControls (text_layout
,
775 sizeof (tags
) / sizeof (tags
[0]),
778 ATSUSetLayoutControls (text_layout
,
779 sizeof (tags
) / sizeof (tags
[0]),
780 tags
, sizes
, values
);
789 TextFont (GC_FONT (gc
)->mac_fontnum
);
790 TextSize (GC_FONT (gc
)->mac_fontsize
);
791 TextFace (GC_FONT (gc
)->mac_fontface
);
794 mac_begin_clip (GC_CLIP_REGION (gc
));
796 DrawText (buf
, 0, nchars
* bytes_per_char
);
797 mac_end_clip (GC_CLIP_REGION (gc
));
803 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
804 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
805 if (!NILP(Vmac_use_core_graphics
))
806 SwapQDTextFlags(savedFlags
);
811 /* Mac replacement for XDrawString. */
814 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
821 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
825 /* Mac replacement for XDrawString16. */
828 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
835 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
, 2);
839 /* Mac replacement for XDrawImageString. */
842 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
)
849 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
853 /* Mac replacement for XDrawString16. */
856 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
)
863 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
, 2);
867 #if USE_CG_TEXT_DRAWING
868 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
870 static int cg_text_anti_aliasing_threshold
= 8;
873 init_cg_text_anti_aliasing_threshold ()
876 Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"),
880 cg_text_anti_aliasing_threshold
= XINT (val
);
884 mac_draw_string_cg (f
, gc
, x
, y
, buf
, nchars
)
892 float port_height
, gx
, gy
;
894 CGContextRef context
;
898 if (NILP (Vmac_use_core_graphics
) || GC_FONT (gc
)->cg_font
== NULL
)
901 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
902 port_height
= FRAME_PIXEL_HEIGHT (f
);
904 gy
= port_height
- y
;
905 glyphs
= (CGGlyph
*)buf
;
906 advances
= xmalloc (sizeof (CGSize
) * nchars
);
907 for (i
= 0; i
< nchars
; i
++)
909 advances
[i
].width
= x_per_char_metric (GC_FONT (gc
), buf
)->width
;
910 advances
[i
].height
= 0;
911 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
915 QDBeginCGContext (port
, &context
);
916 if (gc
->n_clip_rects
)
918 CGContextTranslateCTM (context
, 0, port_height
);
919 CGContextScaleCTM (context
, 1, -1);
920 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
921 CGContextScaleCTM (context
, 1, -1);
922 CGContextTranslateCTM (context
, 0, -port_height
);
924 CGContextSetRGBFillColor (context
,
925 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
926 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
927 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
929 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
930 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
931 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
932 CGContextSetShouldAntialias (context
, false);
933 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
934 CGContextSetTextPosition (context
, gx
, gy
);
935 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
937 for (i
= 0; i
< nchars
; i
++)
939 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
940 gx
+= advances
[i
].width
;
943 CGContextSynchronize (context
);
944 QDEndCGContext (port
, &context
);
953 /* Mac replacement for XCopyArea: dest must be window. */
956 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
961 unsigned int width
, height
;
966 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
968 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
969 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
971 ForeColor (blackColor
);
972 BackColor (whiteColor
);
974 mac_begin_clip (GC_CLIP_REGION (gc
));
975 LockPixels (GetGWorldPixMap (src
));
976 #if TARGET_API_MAC_CARBON
982 CopyBits (GetPortBitMapForCopyBits (src
),
983 GetPortBitMapForCopyBits (port
),
984 &src_r
, &dest_r
, srcCopy
, 0);
985 UnlockPortBits (port
);
987 #else /* not TARGET_API_MAC_CARBON */
988 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
989 &src_r
, &dest_r
, srcCopy
, 0);
990 #endif /* not TARGET_API_MAC_CARBON */
991 UnlockPixels (GetGWorldPixMap (src
));
992 mac_end_clip (GC_CLIP_REGION (gc
));
994 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
999 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1000 width
, height
, dest_x
, dest_y
)
1005 unsigned int width
, height
;
1010 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1012 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1013 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1015 ForeColor (blackColor
);
1016 BackColor (whiteColor
);
1018 mac_begin_clip (GC_CLIP_REGION (gc
));
1019 LockPixels (GetGWorldPixMap (src
));
1020 LockPixels (GetGWorldPixMap (mask
));
1021 #if TARGET_API_MAC_CARBON
1026 LockPortBits (port
);
1027 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1028 GetPortBitMapForCopyBits (port
),
1029 &src_r
, &src_r
, &dest_r
);
1030 UnlockPortBits (port
);
1032 #else /* not TARGET_API_MAC_CARBON */
1033 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1034 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1035 #endif /* not TARGET_API_MAC_CARBON */
1036 UnlockPixels (GetGWorldPixMap (mask
));
1037 UnlockPixels (GetGWorldPixMap (src
));
1038 mac_end_clip (GC_CLIP_REGION (gc
));
1040 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1044 /* Mac replacement for XCopyArea: used only for scrolling. */
1047 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1051 unsigned int width
, height
;
1054 #if TARGET_API_MAC_CARBON
1056 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1058 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1059 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1060 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1061 kScrollWindowNoOptions
, dummy
);
1063 #else /* not TARGET_API_MAC_CARBON */
1065 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1069 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1070 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1072 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1073 color mapping in CopyBits. Otherwise, it will be slow. */
1074 ForeColor (blackColor
);
1075 BackColor (whiteColor
);
1076 mac_begin_clip (GC_CLIP_REGION (gc
));
1077 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1078 mac_end_clip (GC_CLIP_REGION (gc
));
1080 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1081 #endif /* not TARGET_API_MAC_CARBON */
1085 /* Mac replacement for XChangeGC. */
1088 XChangeGC (display
, gc
, mask
, xgcv
)
1094 if (mask
& GCForeground
)
1095 XSetForeground (display
, gc
, xgcv
->foreground
);
1096 if (mask
& GCBackground
)
1097 XSetBackground (display
, gc
, xgcv
->background
);
1099 XSetFont (display
, gc
, xgcv
->font
);
1103 /* Mac replacement for XCreateGC. */
1106 XCreateGC (display
, window
, mask
, xgcv
)
1112 GC gc
= xmalloc (sizeof (*gc
));
1116 bzero (gc
, sizeof (*gc
));
1117 XChangeGC (display
, gc
, mask
, xgcv
);
1124 /* Used in xfaces.c. */
1127 XFreeGC (display
, gc
)
1131 if (gc
->clip_region
)
1132 DisposeRgn (gc
->clip_region
);
1137 /* Mac replacement for XGetGCValues. */
1140 XGetGCValues (display
, gc
, mask
, xgcv
)
1146 if (mask
& GCForeground
)
1147 xgcv
->foreground
= gc
->xgcv
.foreground
;
1148 if (mask
& GCBackground
)
1149 xgcv
->background
= gc
->xgcv
.background
;
1151 xgcv
->font
= gc
->xgcv
.font
;
1155 /* Mac replacement for XSetForeground. */
1158 XSetForeground (display
, gc
, color
)
1161 unsigned long color
;
1163 if (gc
->xgcv
.foreground
!= color
)
1165 gc
->xgcv
.foreground
= color
;
1166 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1167 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1168 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1173 /* Mac replacement for XSetBackground. */
1176 XSetBackground (display
, gc
, color
)
1179 unsigned long color
;
1181 if (gc
->xgcv
.background
!= color
)
1183 gc
->xgcv
.background
= color
;
1184 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1185 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1186 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1191 /* Mac replacement for XSetFont. */
1194 XSetFont (display
, gc
, font
)
1199 gc
->xgcv
.font
= font
;
1203 /* Mac replacement for XSetClipRectangles. */
1206 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1214 if (n
< 0 || n
> MAX_CLIP_RECTS
)
1218 if (gc
->clip_region
)
1220 DisposeRgn (gc
->clip_region
);
1221 gc
->clip_region
= NULL
;
1226 if (gc
->clip_region
== NULL
)
1227 gc
->clip_region
= NewRgn ();
1228 RectRgn (gc
->clip_region
, rectangles
);
1231 RgnHandle region
= NewRgn ();
1233 for (i
= 1; i
< n
; i
++)
1235 RectRgn (region
, rectangles
+ i
);
1236 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1238 DisposeRgn (region
);
1241 #if defined (MAC_OSX) && USE_ATSUI
1242 gc
->n_clip_rects
= n
;
1244 for (i
= 0; i
< n
; i
++)
1246 Rect
*rect
= rectangles
+ i
;
1248 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1249 rect
->right
- rect
->left
,
1250 rect
->bottom
- rect
->top
);
1256 /* Mac replacement for XSetClipMask. */
1259 mac_reset_clip_rectangles (display
, gc
)
1263 mac_set_clip_rectangles (display
, gc
, NULL
, 0);
1267 /* Mac replacement for XSetWindowBackground. */
1270 XSetWindowBackground (display
, w
, color
)
1273 unsigned long color
;
1275 #if !TARGET_API_MAC_CARBON
1276 AuxWinHandle aw_handle
;
1277 CTabHandle ctab_handle
;
1278 ColorSpecPtr ct_table
;
1283 bg_color
.red
= RED16_FROM_ULONG (color
);
1284 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1285 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1287 #if TARGET_API_MAC_CARBON
1288 SetWindowContentColor (w
, &bg_color
);
1290 if (GetAuxWin (w
, &aw_handle
))
1292 ctab_handle
= (*aw_handle
)->awCTable
;
1293 HandToHand ((Handle
*) &ctab_handle
);
1294 ct_table
= (*ctab_handle
)->ctTable
;
1295 ct_size
= (*ctab_handle
)->ctSize
;
1296 while (ct_size
> -1)
1298 if (ct_table
->value
== 0)
1300 ct_table
->rgb
= bg_color
;
1301 CTabChanged (ctab_handle
);
1302 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1310 /* x_sync is a no-op on Mac. */
1318 /* Flush display of frame F, or of all frames if F is null. */
1324 #if TARGET_API_MAC_CARBON
1327 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1329 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1335 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1336 Calls to XFlush should be unnecessary because the X output buffer
1337 is flushed automatically as needed by calls to XPending,
1338 XNextEvent, or XWindowEvent according to the XFlush man page.
1339 XTread_socket calls XPending. Removing XFlush improves
1342 #define XFlush(DISPLAY) (void) 0
1345 /* Return the struct mac_display_info corresponding to DPY. There's
1348 struct mac_display_info
*
1349 mac_display_info_for_display (dpy
)
1352 return &one_mac_display_info
;
1357 /***********************************************************************
1358 Starting and ending an update
1359 ***********************************************************************/
1361 /* Start an update of frame F. This function is installed as a hook
1362 for update_begin, i.e. it is called when update_begin is called.
1363 This function is called prior to calls to x_update_window_begin for
1364 each window being updated. */
1370 #if TARGET_API_MAC_CARBON
1371 /* During update of a frame, availability of input events is
1372 periodically checked with ReceiveNextEvent if
1373 redisplay-dont-pause is nil. That normally flushes window buffer
1374 changes for every check, and thus screen update looks waving even
1375 if no input is available. So we disable screen updates during
1376 update of a frame. */
1378 DisableScreenUpdates ();
1384 /* Start update of window W. Set the global variable updated_window
1385 to the window being updated and set output_cursor to the cursor
1389 x_update_window_begin (w
)
1392 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1393 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1396 set_output_cursor (&w
->cursor
);
1400 if (f
== display_info
->mouse_face_mouse_frame
)
1402 /* Don't do highlighting for mouse motion during the update. */
1403 display_info
->mouse_face_defer
= 1;
1405 /* If F needs to be redrawn, simply forget about any prior mouse
1407 if (FRAME_GARBAGED_P (f
))
1408 display_info
->mouse_face_window
= Qnil
;
1410 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1411 their mouse_face_p flag set, which means that they are always
1412 unequal to rows in a desired matrix which never have that
1413 flag set. So, rows containing mouse-face glyphs are never
1414 scrolled, and we don't have to switch the mouse highlight off
1415 here to prevent it from being scrolled. */
1417 /* Can we tell that this update does not affect the window
1418 where the mouse highlight is? If so, no need to turn off.
1419 Likewise, don't do anything if the frame is garbaged;
1420 in that case, the frame's current matrix that we would use
1421 is all wrong, and we will redisplay that line anyway. */
1422 if (!NILP (display_info
->mouse_face_window
)
1423 && w
== XWINDOW (display_info
->mouse_face_window
))
1427 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1428 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1431 if (i
< w
->desired_matrix
->nrows
)
1432 clear_mouse_face (display_info
);
1441 /* Draw a vertical window border from (x,y0) to (x,y1) */
1444 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1448 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1451 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1453 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1456 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1459 /* End update of window W (which is equal to updated_window).
1461 Draw vertical borders between horizontally adjacent windows, and
1462 display W's cursor if CURSOR_ON_P is non-zero.
1464 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1465 glyphs in mouse-face were overwritten. In that case we have to
1466 make sure that the mouse-highlight is properly redrawn.
1468 W may be a menu bar pseudo-window in case we don't have X toolkit
1469 support. Such windows don't have a cursor, so don't display it
1473 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1475 int cursor_on_p
, mouse_face_overwritten_p
;
1477 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1479 if (!w
->pseudo_window_p
)
1484 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1486 output_cursor
.x
, output_cursor
.y
);
1488 if (draw_window_fringes (w
, 1))
1489 x_draw_vertical_border (w
);
1494 /* If a row with mouse-face was overwritten, arrange for
1495 XTframe_up_to_date to redisplay the mouse highlight. */
1496 if (mouse_face_overwritten_p
)
1498 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1499 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1500 dpyinfo
->mouse_face_window
= Qnil
;
1503 updated_window
= NULL
;
1507 /* End update of frame F. This function is installed as a hook in
1514 /* Mouse highlight may be displayed again. */
1515 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1518 #if TARGET_API_MAC_CARBON
1519 EnableScreenUpdates ();
1521 XFlush (FRAME_MAC_DISPLAY (f
));
1526 /* This function is called from various places in xdisp.c whenever a
1527 complete update has been performed. The global variable
1528 updated_window is not available here. */
1531 XTframe_up_to_date (f
)
1534 if (FRAME_MAC_P (f
))
1536 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1538 if (dpyinfo
->mouse_face_deferred_gc
1539 || f
== dpyinfo
->mouse_face_mouse_frame
)
1542 if (dpyinfo
->mouse_face_mouse_frame
)
1543 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1544 dpyinfo
->mouse_face_mouse_x
,
1545 dpyinfo
->mouse_face_mouse_y
);
1546 dpyinfo
->mouse_face_deferred_gc
= 0;
1553 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1554 arrow bitmaps, or clear the fringes if no bitmaps are required
1555 before DESIRED_ROW is made current. The window being updated is
1556 found in updated_window. This function is called from
1557 update_window_line only if it is known that there are differences
1558 between bitmaps to be drawn between current row and DESIRED_ROW. */
1561 x_after_update_window_line (desired_row
)
1562 struct glyph_row
*desired_row
;
1564 struct window
*w
= updated_window
;
1570 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1571 desired_row
->redraw_fringe_bitmaps_p
= 1;
1573 /* When a window has disappeared, make sure that no rest of
1574 full-width rows stays visible in the internal border. Could
1575 check here if updated_window is the leftmost/rightmost window,
1576 but I guess it's not worth doing since vertically split windows
1577 are almost never used, internal border is rarely set, and the
1578 overhead is very small. */
1579 if (windows_or_buffers_changed
1580 && desired_row
->full_width_p
1581 && (f
= XFRAME (w
->frame
),
1582 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1584 && (height
= desired_row
->visible_height
,
1587 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1589 /* Internal border is drawn below the tool bar. */
1590 if (WINDOWP (f
->tool_bar_window
)
1591 && w
== XWINDOW (f
->tool_bar_window
))
1595 mac_clear_area (f
, 0, y
, width
, height
);
1596 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1602 /* Draw the bitmap WHICH in one of the left or right fringes of
1603 window W. ROW is the glyph row for which to display the bitmap; it
1604 determines the vertical position at which the bitmap has to be
1608 x_draw_fringe_bitmap (w
, row
, p
)
1610 struct glyph_row
*row
;
1611 struct draw_fringe_bitmap_params
*p
;
1613 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1614 Display
*display
= FRAME_MAC_DISPLAY (f
);
1615 struct face
*face
= p
->face
;
1618 /* Must clip because of partially visible lines. */
1619 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1622 /* Adjust position of "bottom aligned" bitmap on partially
1623 visible last row. */
1625 int oldVH
= row
->visible_height
;
1626 row
->visible_height
= p
->h
;
1627 row
->y
-= rowY
- p
->y
;
1628 x_clip_to_row (w
, row
, -1, face
->gc
);
1630 row
->visible_height
= oldVH
;
1633 x_clip_to_row (w
, row
, -1, face
->gc
);
1635 if (p
->bx
>= 0 && !p
->overlay_p
)
1637 #if 0 /* MAC_TODO: stipple */
1638 /* In case the same realized face is used for fringes and
1639 for something displayed in the text (e.g. face `region' on
1640 mono-displays, the fill style may have been changed to
1641 FillSolid in x_draw_glyph_string_background. */
1643 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1645 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1648 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1650 #if 0 /* MAC_TODO: stipple */
1652 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1658 unsigned short *bits
= p
->bits
+ p
->dh
;
1661 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1662 XSetForeground (display
, face
->gc
,
1664 ? (p
->overlay_p
? face
->background
1665 : f
->output_data
.mac
->cursor_pixel
)
1666 : face
->foreground
));
1667 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
1668 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1669 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1672 mac_reset_clip_rectangles (display
, face
->gc
);
1677 /* This is called when starting Emacs and when restarting after
1678 suspend. When starting Emacs, no window is mapped. And nothing
1679 must be done to Emacs's own window if it is suspended (though that
1683 XTset_terminal_modes ()
1687 /* This is called when exiting or suspending Emacs. Exiting will make
1688 the windows go away, and suspending requires no action. */
1691 XTreset_terminal_modes ()
1697 /***********************************************************************
1699 ***********************************************************************/
1701 /* Function prototypes of this page. */
1703 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1704 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1707 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1708 is not contained in the font. */
1710 static INLINE XCharStruct
*
1711 x_per_char_metric (font
, char2b
)
1715 /* The result metric information. */
1716 XCharStruct
*pcm
= NULL
;
1718 xassert (font
&& char2b
);
1721 if (font
->mac_style
)
1723 if (char2b
->byte1
>= font
->min_byte1
1724 && char2b
->byte1
<= font
->max_byte1
1725 && char2b
->byte2
>= font
->min_char_or_byte2
1726 && char2b
->byte2
<= font
->max_char_or_byte2
)
1728 pcm
= (font
->per_char
1729 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1730 * (char2b
->byte1
- font
->min_byte1
))
1731 + (char2b
->byte2
- font
->min_char_or_byte2
));
1734 if (pcm
&& !pcm
->valid_p
)
1737 ATSUTextLayout text_layout
;
1740 ATSTrapezoid glyph_bounds
;
1743 c
= (char2b
->byte1
<< 8) + char2b
->byte2
;
1745 err
= atsu_get_text_layout_with_text_ptr (&c
, 1,
1749 err
= ATSUMeasureTextImage (text_layout
,
1750 kATSUFromTextBeginning
, kATSUToTextEnd
,
1751 0, 0, &char_bounds
);
1754 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1755 kATSUFromTextBeginning
, kATSUToTextEnd
,
1756 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1757 kATSUseFractionalOrigins
,
1759 kATSUseDeviceOrigins
,
1761 1, &glyph_bounds
, NULL
);
1767 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1768 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1770 char_width
= Fix2Long (glyph_bounds
.upperRight
.x
1771 - glyph_bounds
.upperLeft
.x
);
1772 STORE_XCHARSTRUCT (*pcm
, char_width
, char_bounds
);
1779 if (font
->per_char
!= NULL
)
1781 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1783 /* min_char_or_byte2 specifies the linear character index
1784 corresponding to the first element of the per_char array,
1785 max_char_or_byte2 is the index of the last character. A
1786 character with non-zero CHAR2B->byte1 is not in the font.
1787 A character with byte2 less than min_char_or_byte2 or
1788 greater max_char_or_byte2 is not in the font. */
1789 if (char2b
->byte1
== 0
1790 && char2b
->byte2
>= font
->min_char_or_byte2
1791 && char2b
->byte2
<= font
->max_char_or_byte2
)
1792 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1796 /* If either min_byte1 or max_byte1 are nonzero, both
1797 min_char_or_byte2 and max_char_or_byte2 are less than
1798 256, and the 2-byte character index values corresponding
1799 to the per_char array element N (counting from 0) are:
1801 byte1 = N/D + min_byte1
1802 byte2 = N\D + min_char_or_byte2
1806 D = max_char_or_byte2 - min_char_or_byte2 + 1
1807 / = integer division
1808 \ = integer modulus */
1809 if (char2b
->byte1
>= font
->min_byte1
1810 && char2b
->byte1
<= font
->max_byte1
1811 && char2b
->byte2
>= font
->min_char_or_byte2
1812 && char2b
->byte2
<= font
->max_char_or_byte2
)
1814 pcm
= (font
->per_char
1815 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1816 * (char2b
->byte1
- font
->min_byte1
))
1817 + (char2b
->byte2
- font
->min_char_or_byte2
));
1823 /* If the per_char pointer is null, all glyphs between the first
1824 and last character indexes inclusive have the same
1825 information, as given by both min_bounds and max_bounds. */
1826 if (char2b
->byte2
>= font
->min_char_or_byte2
1827 && char2b
->byte2
<= font
->max_char_or_byte2
)
1828 pcm
= &font
->max_bounds
;
1834 return ((pcm
== NULL
1835 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1842 static XCharStruct
*
1843 mac_per_char_metric (font
, char2b
, font_type
)
1848 return x_per_char_metric (font
, char2b
);
1852 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1853 the two-byte form of C. Encoding is returned in *CHAR2B. */
1856 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1859 struct font_info
*font_info
;
1862 int charset
= CHAR_CHARSET (c
);
1863 XFontStruct
*font
= font_info
->font
;
1865 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1866 This may be either a program in a special encoder language or a
1868 if (font_info
->font_encoder
)
1870 /* It's a program. */
1871 struct ccl_program
*ccl
= font_info
->font_encoder
;
1873 check_ccl_update (ccl
);
1874 if (CHARSET_DIMENSION (charset
) == 1)
1876 ccl
->reg
[0] = charset
;
1877 ccl
->reg
[1] = char2b
->byte2
;
1882 ccl
->reg
[0] = charset
;
1883 ccl
->reg
[1] = char2b
->byte1
;
1884 ccl
->reg
[2] = char2b
->byte2
;
1887 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1889 /* We assume that MSBs are appropriately set/reset by CCL
1891 if (font
->max_byte1
== 0) /* 1-byte font */
1892 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1894 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1896 else if (font_info
->encoding
[charset
])
1898 /* Fixed encoding scheme. See fontset.h for the meaning of the
1899 encoding numbers. */
1900 int enc
= font_info
->encoding
[charset
];
1902 if ((enc
== 1 || enc
== 2)
1903 && CHARSET_DIMENSION (charset
) == 2)
1904 char2b
->byte1
|= 0x80;
1906 if (enc
== 1 || enc
== 3)
1907 char2b
->byte2
|= 0x80;
1913 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1914 char2b
->byte1
= sjis1
;
1915 char2b
->byte2
= sjis2
;
1920 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1922 return FONT_TYPE_UNKNOWN
;
1927 /***********************************************************************
1929 ***********************************************************************/
1933 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1934 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1935 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1937 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1938 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1939 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1940 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1941 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
1942 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1943 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1944 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1945 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1946 unsigned long *, double, int));*/
1947 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1948 double, int, unsigned long));
1949 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1950 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1951 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1952 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1953 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1954 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1956 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1957 int, int, int, int, int, int,
1959 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1960 int, int, int, Rect
*));
1963 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1967 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1972 struct glyph_string
*s
;
1974 if (s
->font
== FRAME_FONT (s
->f
)
1975 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1976 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1978 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1981 /* Cursor on non-default face: must merge. */
1985 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1986 xgcv
.foreground
= s
->face
->background
;
1988 /* If the glyph would be invisible, try a different foreground. */
1989 if (xgcv
.foreground
== xgcv
.background
)
1990 xgcv
.foreground
= s
->face
->foreground
;
1991 if (xgcv
.foreground
== xgcv
.background
)
1992 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1993 if (xgcv
.foreground
== xgcv
.background
)
1994 xgcv
.foreground
= s
->face
->foreground
;
1996 /* Make sure the cursor is distinct from text in this face. */
1997 if (xgcv
.background
== s
->face
->background
1998 && xgcv
.foreground
== s
->face
->foreground
)
2000 xgcv
.background
= s
->face
->foreground
;
2001 xgcv
.foreground
= s
->face
->background
;
2004 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2005 xgcv
.font
= s
->font
;
2006 mask
= GCForeground
| GCBackground
| GCFont
;
2008 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2009 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2012 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2013 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2015 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2020 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2023 x_set_mouse_face_gc (s
)
2024 struct glyph_string
*s
;
2029 /* What face has to be used last for the mouse face? */
2030 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2031 face
= FACE_FROM_ID (s
->f
, face_id
);
2033 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2035 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2036 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2038 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2039 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2040 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2042 /* If font in this face is same as S->font, use it. */
2043 if (s
->font
== s
->face
->font
)
2044 s
->gc
= s
->face
->gc
;
2047 /* Otherwise construct scratch_cursor_gc with values from FACE
2052 xgcv
.background
= s
->face
->background
;
2053 xgcv
.foreground
= s
->face
->foreground
;
2054 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2055 xgcv
.font
= s
->font
;
2056 mask
= GCForeground
| GCBackground
| GCFont
;
2058 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2059 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2062 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2063 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2065 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2068 xassert (s
->gc
!= 0);
2072 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2073 Faces to use in the mode line have already been computed when the
2074 matrix was built, so there isn't much to do, here. */
2077 x_set_mode_line_face_gc (s
)
2078 struct glyph_string
*s
;
2080 s
->gc
= s
->face
->gc
;
2084 /* Set S->gc of glyph string S for drawing that glyph string. Set
2085 S->stippled_p to a non-zero value if the face of S has a stipple
2089 x_set_glyph_string_gc (s
)
2090 struct glyph_string
*s
;
2092 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2094 if (s
->hl
== DRAW_NORMAL_TEXT
)
2096 s
->gc
= s
->face
->gc
;
2097 s
->stippled_p
= s
->face
->stipple
!= 0;
2099 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2101 x_set_mode_line_face_gc (s
);
2102 s
->stippled_p
= s
->face
->stipple
!= 0;
2104 else if (s
->hl
== DRAW_CURSOR
)
2106 x_set_cursor_gc (s
);
2109 else if (s
->hl
== DRAW_MOUSE_FACE
)
2111 x_set_mouse_face_gc (s
);
2112 s
->stippled_p
= s
->face
->stipple
!= 0;
2114 else if (s
->hl
== DRAW_IMAGE_RAISED
2115 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2117 s
->gc
= s
->face
->gc
;
2118 s
->stippled_p
= s
->face
->stipple
!= 0;
2122 s
->gc
= s
->face
->gc
;
2123 s
->stippled_p
= s
->face
->stipple
!= 0;
2126 /* GC must have been set. */
2127 xassert (s
->gc
!= 0);
2131 /* Set clipping for output of glyph string S. S may be part of a mode
2132 line or menu if we don't have X toolkit support. */
2135 x_set_glyph_string_clipping (s
)
2136 struct glyph_string
*s
;
2138 Rect rects
[MAX_CLIP_RECTS
];
2141 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2142 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2147 Compute left and right overhang of glyph string S. If S is a glyph
2148 string for a composition, assume overhangs don't exist. */
2151 mac_compute_glyph_string_overhangs (s
)
2152 struct glyph_string
*s
;
2155 && s
->first_glyph
->type
== CHAR_GLYPH
)
2158 MacFontStruct
*font
= s
->font
;
2161 if (font
->mac_style
)
2164 ATSUTextLayout text_layout
;
2168 SetRect (&r
, 0, 0, 0, 0);
2169 buf
= xmalloc (sizeof (UniChar
) * s
->nchars
);
2172 for (i
= 0; i
< s
->nchars
; i
++)
2173 buf
[i
] = (s
->char2b
[i
].byte1
<< 8) + s
->char2b
[i
].byte2
;
2175 err
= atsu_get_text_layout_with_text_ptr (buf
, s
->nchars
,
2179 err
= ATSUMeasureTextImage (text_layout
,
2180 kATSUFromTextBeginning
,
2189 TextFont (font
->mac_fontnum
);
2190 TextSize (font
->mac_fontsize
);
2191 TextFace (font
->mac_fontface
);
2194 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2198 char *buf
= xmalloc (s
->nchars
);
2201 SetRect (&r
, 0, 0, 0, 0);
2204 for (i
= 0; i
< s
->nchars
; ++i
)
2205 buf
[i
] = s
->char2b
[i
].byte2
;
2206 QDTextBounds (s
->nchars
, buf
, &r
);
2214 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2215 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2220 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2223 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2224 struct glyph_string
*s
;
2227 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2231 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2232 on Mac OS X because:
2233 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2234 into an offscreen graphics world first. So performance gain
2235 cannot be expected.)
2236 - It lowers rendering quality.
2237 - Some fonts leave garbage on cursor movement. */
2239 /* Draw the background of glyph_string S. If S->background_filled_p
2240 is non-zero don't draw it. FORCE_P non-zero means draw the
2241 background even if it wouldn't be drawn normally. This is used
2242 when a string preceding S draws into the background of S, or S
2243 contains the first component of a composition. */
2246 x_draw_glyph_string_background (s
, force_p
)
2247 struct glyph_string
*s
;
2250 /* Nothing to do if background has already been drawn or if it
2251 shouldn't be drawn in the first place. */
2252 if (!s
->background_filled_p
)
2254 int box_line_width
= max (s
->face
->box_line_width
, 0);
2256 #if 0 /* MAC_TODO: stipple */
2259 /* Fill background with a stipple pattern. */
2260 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2261 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2262 s
->y
+ box_line_width
,
2263 s
->background_width
,
2264 s
->height
- 2 * box_line_width
);
2265 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2266 s
->background_filled_p
= 1;
2270 #if defined (MAC_OS8) && !USE_ATSUI
2271 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2272 || s
->font_not_found_p
2273 || s
->extends_to_end_of_line_p
2277 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2278 s
->background_width
,
2279 s
->height
- 2 * box_line_width
);
2280 s
->background_filled_p
= 1;
2286 /* Draw the foreground of glyph string S. */
2289 x_draw_glyph_string_foreground (s
)
2290 struct glyph_string
*s
;
2294 /* If first glyph of S has a left box line, start drawing the text
2295 of S to the right of that box line. */
2296 if (s
->face
->box
!= FACE_NO_BOX
2297 && s
->first_glyph
->left_box_line_p
)
2298 x
= s
->x
+ abs (s
->face
->box_line_width
);
2302 /* Draw characters of S as rectangles if S's font could not be
2304 if (s
->font_not_found_p
)
2306 for (i
= 0; i
< s
->nchars
; ++i
)
2308 struct glyph
*g
= s
->first_glyph
+ i
;
2309 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2310 g
->pixel_width
- 1, s
->height
- 1);
2311 x
+= g
->pixel_width
;
2316 char *char1b
= (char *) s
->char2b
;
2317 int boff
= s
->font_info
->baseline_offset
;
2319 if (s
->font_info
->vertical_centering
)
2320 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2322 /* If we can use 8-bit functions, condense S->char2b. */
2325 && GC_FONT (s
->gc
)->mac_style
== NULL
2328 for (i
= 0; i
< s
->nchars
; ++i
)
2329 char1b
[i
] = s
->char2b
[i
].byte2
;
2331 #if defined (MAC_OS8) && !USE_ATSUI
2332 /* Draw text with XDrawString if background has already been
2333 filled. Otherwise, use XDrawImageString. (Note that
2334 XDrawImageString is usually faster than XDrawString.) Always
2335 use XDrawImageString when drawing the cursor so that there is
2336 no chance that characters under a box cursor are invisible. */
2338 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2341 /* Draw characters with 16-bit or 8-bit functions. */
2344 || GC_FONT (s
->gc
)->mac_style
2347 #if USE_CG_TEXT_DRAWING
2349 && mac_draw_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2350 s
->char2b
, s
->nchars
))
2354 mac_draw_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2355 s
->char2b
, s
->nchars
);
2357 mac_draw_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2360 #if defined (MAC_OS8) && !USE_ATSUI
2364 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2365 s
->char2b
, s
->nchars
);
2367 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2374 /* Draw the foreground of composite glyph string S. */
2377 x_draw_composite_glyph_string_foreground (s
)
2378 struct glyph_string
*s
;
2382 /* If first glyph of S has a left box line, start drawing the text
2383 of S to the right of that box line. */
2384 if (s
->face
->box
!= FACE_NO_BOX
2385 && s
->first_glyph
->left_box_line_p
)
2386 x
= s
->x
+ abs (s
->face
->box_line_width
);
2390 /* S is a glyph string for a composition. S->gidx is the index of
2391 the first character drawn for glyphs of this composition.
2392 S->gidx == 0 means we are drawing the very first character of
2393 this composition. */
2395 /* Draw a rectangle for the composition if the font for the very
2396 first character of the composition could not be loaded. */
2397 if (s
->font_not_found_p
)
2400 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2401 s
->width
- 1, s
->height
- 1);
2405 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2406 mac_draw_string_16 (s
->f
, s
->gc
,
2407 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2408 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2414 #ifdef USE_X_TOOLKIT
2416 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2419 /* Return the frame on which widget WIDGET is used.. Abort if frame
2420 cannot be determined. */
2422 static struct frame
*
2423 x_frame_of_widget (widget
)
2426 struct x_display_info
*dpyinfo
;
2430 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2432 /* Find the top-level shell of the widget. Note that this function
2433 can be called when the widget is not yet realized, so XtWindow
2434 (widget) == 0. That's the reason we can't simply use
2435 x_any_window_to_frame. */
2436 while (!XtIsTopLevelShell (widget
))
2437 widget
= XtParent (widget
);
2439 /* Look for a frame with that top-level widget. Allocate the color
2440 on that frame to get the right gamma correction value. */
2441 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2442 if (GC_FRAMEP (XCAR (tail
))
2443 && (f
= XFRAME (XCAR (tail
)),
2444 (f
->output_data
.nothing
!= 1
2445 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2446 && f
->output_data
.x
->widget
== widget
)
2453 /* Allocate the color COLOR->pixel on the screen and display of
2454 widget WIDGET in colormap CMAP. If an exact match cannot be
2455 allocated, try the nearest color available. Value is non-zero
2456 if successful. This is called from lwlib. */
2459 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2464 struct frame
*f
= x_frame_of_widget (widget
);
2465 return x_alloc_nearest_color (f
, cmap
, color
);
2469 #endif /* USE_X_TOOLKIT */
2471 #if 0 /* MAC_TODO */
2473 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2474 CMAP. If an exact match can't be allocated, try the nearest color
2475 available. Value is non-zero if successful. Set *COLOR to the
2479 x_alloc_nearest_color (f
, cmap
, color
)
2484 Display
*display
= FRAME_X_DISPLAY (f
);
2485 Screen
*screen
= FRAME_X_SCREEN (f
);
2488 gamma_correct (f
, color
);
2489 rc
= XAllocColor (display
, cmap
, color
);
2492 /* If we got to this point, the colormap is full, so we're going
2493 to try to get the next closest color. The algorithm used is
2494 a least-squares matching, which is what X uses for closest
2495 color matching with StaticColor visuals. */
2497 unsigned long nearest_delta
= ~0;
2498 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2499 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2501 for (i
= 0; i
< ncells
; ++i
)
2503 XQueryColors (display
, cmap
, cells
, ncells
);
2505 for (nearest
= i
= 0; i
< ncells
; ++i
)
2507 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2508 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2509 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2510 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2512 if (delta
< nearest_delta
)
2515 nearest_delta
= delta
;
2519 color
->red
= cells
[nearest
].red
;
2520 color
->green
= cells
[nearest
].green
;
2521 color
->blue
= cells
[nearest
].blue
;
2522 rc
= XAllocColor (display
, cmap
, color
);
2525 #ifdef DEBUG_X_COLORS
2527 register_color (color
->pixel
);
2528 #endif /* DEBUG_X_COLORS */
2534 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2535 It's necessary to do this instead of just using PIXEL directly to
2536 get color reference counts right. */
2539 x_copy_color (f
, pixel
)
2541 unsigned long pixel
;
2545 color
.pixel
= pixel
;
2547 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2548 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2550 #ifdef DEBUG_X_COLORS
2551 register_color (pixel
);
2557 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2558 It's necessary to do this instead of just using PIXEL directly to
2559 get color reference counts right. */
2562 x_copy_dpy_color (dpy
, cmap
, pixel
)
2565 unsigned long pixel
;
2569 color
.pixel
= pixel
;
2571 XQueryColor (dpy
, cmap
, &color
);
2572 XAllocColor (dpy
, cmap
, &color
);
2574 #ifdef DEBUG_X_COLORS
2575 register_color (pixel
);
2580 #endif /* MAC_TODO */
2583 /* Brightness beyond which a color won't have its highlight brightness
2586 Nominally, highlight colors for `3d' faces are calculated by
2587 brightening an object's color by a constant scale factor, but this
2588 doesn't yield good results for dark colors, so for colors who's
2589 brightness is less than this value (on a scale of 0-255) have to
2590 use an additional additive factor.
2592 The value here is set so that the default menu-bar/mode-line color
2593 (grey75) will not have its highlights changed at all. */
2594 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2597 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2598 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2599 If this produces the same color as COLOR, try a color where all RGB
2600 values have DELTA added. Return the allocated color in *COLOR.
2601 DISPLAY is the X display, CMAP is the colormap to operate on.
2602 Value is non-zero if successful. */
2605 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2607 unsigned long *color
;
2614 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2617 /* Change RGB values by specified FACTOR. Avoid overflow! */
2618 xassert (factor
>= 0);
2619 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2620 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2621 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2623 /* Calculate brightness of COLOR. */
2624 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2625 + BLUE_FROM_ULONG (*color
)) / 6;
2627 /* We only boost colors that are darker than
2628 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2629 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2630 /* Make an additive adjustment to NEW, because it's dark enough so
2631 that scaling by FACTOR alone isn't enough. */
2633 /* How far below the limit this color is (0 - 1, 1 being darker). */
2634 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2635 /* The additive adjustment. */
2636 int min_delta
= delta
* dimness
* factor
/ 2;
2639 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2640 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2641 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2643 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2644 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2645 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2649 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2650 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2651 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2653 /* MAC_TODO: Map to palette and retry with delta if same? */
2654 /* MAC_TODO: Free colors (if using palette)? */
2665 /* Set up the foreground color for drawing relief lines of glyph
2666 string S. RELIEF is a pointer to a struct relief containing the GC
2667 with which lines will be drawn. Use a color that is FACTOR or
2668 DELTA lighter or darker than the relief's background which is found
2669 in S->f->output_data.x->relief_background. If such a color cannot
2670 be allocated, use DEFAULT_PIXEL, instead. */
2673 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2675 struct relief
*relief
;
2678 unsigned long default_pixel
;
2681 struct mac_output
*di
= f
->output_data
.mac
;
2682 unsigned long mask
= GCForeground
;
2683 unsigned long pixel
;
2684 unsigned long background
= di
->relief_background
;
2685 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2687 /* MAC_TODO: Free colors (if using palette)? */
2689 /* Allocate new color. */
2690 xgcv
.foreground
= default_pixel
;
2692 if (dpyinfo
->n_planes
!= 1
2693 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2695 relief
->allocated_p
= 1;
2696 xgcv
.foreground
= relief
->pixel
= pixel
;
2699 if (relief
->gc
== 0)
2701 #if 0 /* MAC_TODO: stipple */
2702 xgcv
.stipple
= dpyinfo
->gray
;
2705 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2708 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2712 /* Set up colors for the relief lines around glyph string S. */
2715 x_setup_relief_colors (s
)
2716 struct glyph_string
*s
;
2718 struct mac_output
*di
= s
->f
->output_data
.mac
;
2719 unsigned long color
;
2721 if (s
->face
->use_box_color_for_shadows_p
)
2722 color
= s
->face
->box_color
;
2723 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2725 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2726 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2731 /* Get the background color of the face. */
2732 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2733 color
= xgcv
.background
;
2736 if (di
->white_relief
.gc
== 0
2737 || color
!= di
->relief_background
)
2739 di
->relief_background
= color
;
2740 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2741 WHITE_PIX_DEFAULT (s
->f
));
2742 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2743 BLACK_PIX_DEFAULT (s
->f
));
2748 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2749 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2750 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2751 relief. LEFT_P non-zero means draw a relief on the left side of
2752 the rectangle. RIGHT_P non-zero means draw a relief on the right
2753 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2757 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2758 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2760 int left_x
, top_y
, right_x
, bottom_y
, width
;
2761 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2764 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2769 gc
= f
->output_data
.mac
->white_relief
.gc
;
2771 gc
= f
->output_data
.mac
->black_relief
.gc
;
2772 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2776 for (i
= 0; i
< width
; ++i
)
2777 mac_draw_line (f
, gc
,
2778 left_x
+ i
* left_p
, top_y
+ i
,
2779 right_x
- i
* right_p
, top_y
+ i
);
2783 for (i
= 0; i
< width
; ++i
)
2784 mac_draw_line (f
, gc
,
2785 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2787 mac_reset_clip_rectangles (dpy
, gc
);
2789 gc
= f
->output_data
.mac
->black_relief
.gc
;
2791 gc
= f
->output_data
.mac
->white_relief
.gc
;
2792 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2796 for (i
= 0; i
< width
; ++i
)
2797 mac_draw_line (f
, gc
,
2798 left_x
+ i
* left_p
, bottom_y
- i
,
2799 right_x
- i
* right_p
, bottom_y
- i
);
2803 for (i
= 0; i
< width
; ++i
)
2804 mac_draw_line (f
, gc
,
2805 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2807 mac_reset_clip_rectangles (dpy
, gc
);
2811 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2812 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2813 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2814 left side of the rectangle. RIGHT_P non-zero means draw a line
2815 on the right side of the rectangle. CLIP_RECT is the clipping
2816 rectangle to use when drawing. */
2819 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2820 left_p
, right_p
, clip_rect
)
2821 struct glyph_string
*s
;
2822 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2827 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2828 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2829 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
2832 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2833 right_x
- left_x
+ 1, width
);
2837 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2838 width
, bottom_y
- top_y
+ 1);
2841 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
2842 right_x
- left_x
+ 1, width
);
2846 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
2847 top_y
, width
, bottom_y
- top_y
+ 1);
2849 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2850 mac_reset_clip_rectangles (s
->display
, s
->gc
);
2854 /* Draw a box around glyph string S. */
2857 x_draw_glyph_string_box (s
)
2858 struct glyph_string
*s
;
2860 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2861 int left_p
, right_p
;
2862 struct glyph
*last_glyph
;
2865 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2866 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2867 : window_box_right (s
->w
, s
->area
));
2869 /* The glyph that may have a right box line. */
2870 last_glyph
= (s
->cmp
|| s
->img
2872 : s
->first_glyph
+ s
->nchars
- 1);
2874 width
= abs (s
->face
->box_line_width
);
2875 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2877 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2879 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2881 bottom_y
= top_y
+ s
->height
- 1;
2883 left_p
= (s
->first_glyph
->left_box_line_p
2884 || (s
->hl
== DRAW_MOUSE_FACE
2886 || s
->prev
->hl
!= s
->hl
)));
2887 right_p
= (last_glyph
->right_box_line_p
2888 || (s
->hl
== DRAW_MOUSE_FACE
2890 || s
->next
->hl
!= s
->hl
)));
2892 get_glyph_string_clip_rect (s
, &clip_rect
);
2894 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2895 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2896 left_p
, right_p
, &clip_rect
);
2899 x_setup_relief_colors (s
);
2900 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2901 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2906 /* Draw foreground of image glyph string S. */
2909 x_draw_image_foreground (s
)
2910 struct glyph_string
*s
;
2913 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2915 /* If first glyph of S has a left box line, start drawing it to the
2916 right of that line. */
2917 if (s
->face
->box
!= FACE_NO_BOX
2918 && s
->first_glyph
->left_box_line_p
2920 x
+= abs (s
->face
->box_line_width
);
2922 /* If there is a margin around the image, adjust x- and y-position
2924 if (s
->slice
.x
== 0)
2925 x
+= s
->img
->hmargin
;
2926 if (s
->slice
.y
== 0)
2927 y
+= s
->img
->vmargin
;
2931 x_set_glyph_string_clipping (s
);
2934 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
2935 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2936 s
->slice
.width
, s
->slice
.height
, x
, y
);
2939 mac_copy_area (s
->img
->pixmap
,
2940 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2941 s
->slice
.width
, s
->slice
.height
, x
, y
);
2943 /* When the image has a mask, we can expect that at
2944 least part of a mouse highlight or a block cursor will
2945 be visible. If the image doesn't have a mask, make
2946 a block cursor visible by drawing a rectangle around
2947 the image. I believe it's looking better if we do
2948 nothing here for mouse-face. */
2949 if (s
->hl
== DRAW_CURSOR
)
2951 int r
= s
->img
->relief
;
2953 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
2954 s
->slice
.width
+ r
*2 - 1,
2955 s
->slice
.height
+ r
*2 - 1);
2960 /* Draw a rectangle if image could not be loaded. */
2961 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
2962 s
->slice
.width
- 1, s
->slice
.height
- 1);
2966 /* Draw a relief around the image glyph string S. */
2969 x_draw_image_relief (s
)
2970 struct glyph_string
*s
;
2972 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2975 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2977 /* If first glyph of S has a left box line, start drawing it to the
2978 right of that line. */
2979 if (s
->face
->box
!= FACE_NO_BOX
2980 && s
->first_glyph
->left_box_line_p
2982 x
+= abs (s
->face
->box_line_width
);
2984 /* If there is a margin around the image, adjust x- and y-position
2986 if (s
->slice
.x
== 0)
2987 x
+= s
->img
->hmargin
;
2988 if (s
->slice
.y
== 0)
2989 y
+= s
->img
->vmargin
;
2991 if (s
->hl
== DRAW_IMAGE_SUNKEN
2992 || s
->hl
== DRAW_IMAGE_RAISED
)
2994 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2995 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2999 thick
= abs (s
->img
->relief
);
3000 raised_p
= s
->img
->relief
> 0;
3005 x1
= x
+ s
->slice
.width
+ thick
- 1;
3006 y1
= y
+ s
->slice
.height
+ thick
- 1;
3008 x_setup_relief_colors (s
);
3009 get_glyph_string_clip_rect (s
, &r
);
3010 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3012 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3014 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3019 /* Draw part of the background of glyph string S. X, Y, W, and H
3020 give the rectangle to draw. */
3023 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3024 struct glyph_string
*s
;
3027 #if 0 /* MAC_TODO: stipple */
3030 /* Fill background with a stipple pattern. */
3031 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3032 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3033 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3036 #endif /* MAC_TODO */
3037 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3041 /* Draw image glyph string S.
3044 s->x +-------------------------
3047 | +-------------------------
3050 | | +-------------------
3056 x_draw_image_glyph_string (s
)
3057 struct glyph_string
*s
;
3060 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3061 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3065 height
= s
->height
- 2 * box_line_vwidth
;
3068 /* Fill background with face under the image. Do it only if row is
3069 taller than image or if image has a clip mask to reduce
3071 s
->stippled_p
= s
->face
->stipple
!= 0;
3072 if (height
> s
->slice
.height
3076 || s
->img
->pixmap
== 0
3077 || s
->width
!= s
->background_width
)
3080 if (s
->first_glyph
->left_box_line_p
3082 x
+= box_line_hwidth
;
3085 if (s
->slice
.y
== 0)
3086 y
+= box_line_vwidth
;
3088 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3090 s
->background_filled_p
= 1;
3093 /* Draw the foreground. */
3094 x_draw_image_foreground (s
);
3096 /* If we must draw a relief around the image, do it. */
3098 || s
->hl
== DRAW_IMAGE_RAISED
3099 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3100 x_draw_image_relief (s
);
3104 /* Draw stretch glyph string S. */
3107 x_draw_stretch_glyph_string (s
)
3108 struct glyph_string
*s
;
3110 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3111 s
->stippled_p
= s
->face
->stipple
!= 0;
3113 if (s
->hl
== DRAW_CURSOR
3114 && !x_stretch_cursor_p
)
3116 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3117 as wide as the stretch glyph. */
3118 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3121 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3123 /* Clear rest using the GC of the original non-cursor face. */
3124 if (width
< s
->background_width
)
3126 int x
= s
->x
+ width
, y
= s
->y
;
3127 int w
= s
->background_width
- width
, h
= s
->height
;
3131 if (s
->row
->mouse_face_p
3132 && cursor_in_mouse_face_p (s
->w
))
3134 x_set_mouse_face_gc (s
);
3140 get_glyph_string_clip_rect (s
, &r
);
3141 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3143 #if 0 /* MAC_TODO: stipple */
3144 if (s
->face
->stipple
)
3146 /* Fill background with a stipple pattern. */
3147 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3148 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3149 XSetFillStyle (s
->display
, gc
, FillSolid
);
3152 #endif /* MAC_TODO */
3153 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3156 else if (!s
->background_filled_p
)
3157 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3160 s
->background_filled_p
= 1;
3164 /* Draw glyph string S. */
3167 x_draw_glyph_string (s
)
3168 struct glyph_string
*s
;
3170 int relief_drawn_p
= 0;
3172 /* If S draws into the background of its successor that does not
3173 draw a cursor, draw the background of the successor first so that
3174 S can draw into it. This makes S->next use XDrawString instead
3175 of XDrawImageString. */
3176 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3177 && s
->next
->hl
!= DRAW_CURSOR
)
3179 xassert (s
->next
->img
== NULL
);
3180 x_set_glyph_string_gc (s
->next
);
3181 x_set_glyph_string_clipping (s
->next
);
3182 x_draw_glyph_string_background (s
->next
, 1);
3185 /* Set up S->gc, set clipping and draw S. */
3186 x_set_glyph_string_gc (s
);
3188 /* Draw relief (if any) in advance for char/composition so that the
3189 glyph string can be drawn over it. */
3190 if (!s
->for_overlaps
3191 && s
->face
->box
!= FACE_NO_BOX
3192 && (s
->first_glyph
->type
== CHAR_GLYPH
3193 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3196 x_set_glyph_string_clipping (s
);
3197 x_draw_glyph_string_background (s
, 1);
3198 x_draw_glyph_string_box (s
);
3199 x_set_glyph_string_clipping (s
);
3203 x_set_glyph_string_clipping (s
);
3205 switch (s
->first_glyph
->type
)
3208 x_draw_image_glyph_string (s
);
3212 x_draw_stretch_glyph_string (s
);
3216 if (s
->for_overlaps
)
3217 s
->background_filled_p
= 1;
3219 x_draw_glyph_string_background (s
, 0);
3220 x_draw_glyph_string_foreground (s
);
3223 case COMPOSITE_GLYPH
:
3224 if (s
->for_overlaps
|| s
->gidx
> 0)
3225 s
->background_filled_p
= 1;
3227 x_draw_glyph_string_background (s
, 1);
3228 x_draw_composite_glyph_string_foreground (s
);
3235 if (!s
->for_overlaps
)
3237 /* Draw underline. */
3238 if (s
->face
->underline_p
)
3240 unsigned long h
= 1;
3241 unsigned long dy
= s
->height
- h
;
3243 if (s
->face
->underline_defaulted_p
)
3244 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3249 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3250 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3251 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3253 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3257 /* Draw overline. */
3258 if (s
->face
->overline_p
)
3260 unsigned long dy
= 0, h
= 1;
3262 if (s
->face
->overline_color_defaulted_p
)
3263 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3268 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3269 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3270 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3272 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3276 /* Draw strike-through. */
3277 if (s
->face
->strike_through_p
)
3279 unsigned long h
= 1;
3280 unsigned long dy
= (s
->height
- h
) / 2;
3282 if (s
->face
->strike_through_color_defaulted_p
)
3283 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3288 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3289 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3290 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3292 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3296 /* Draw relief if not yet drawn. */
3297 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3298 x_draw_glyph_string_box (s
);
3301 /* Reset clipping. */
3302 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3305 /* Shift display to make room for inserted glyphs. */
3308 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3310 int x
, y
, width
, height
, shift_by
;
3312 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3313 x
, y
, width
, height
,
3317 /* Delete N glyphs at the nominal cursor position. Not implemented
3328 /* Clear entire frame. If updating_frame is non-null, clear that
3329 frame. Otherwise clear the selected frame. */
3339 f
= SELECTED_FRAME ();
3341 /* Clearing the frame will erase any cursor, so mark them all as no
3343 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3344 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3345 output_cursor
.x
= -1;
3347 /* We don't set the output cursor here because there will always
3348 follow an explicit cursor_to. */
3350 mac_clear_window (f
);
3352 /* We have to clear the scroll bars, too. If we have changed
3353 colors or something like that, then they should be notified. */
3354 x_scroll_bar_clear (f
);
3356 XFlush (FRAME_MAC_DISPLAY (f
));
3362 /* Invert the middle quarter of the frame for .15 sec. */
3364 /* We use the select system call to do the waiting, so we have to make
3365 sure it's available. If it isn't, we just won't do visual bells. */
3367 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3370 /* Subtract the `struct timeval' values X and Y, storing the result in
3371 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3374 timeval_subtract (result
, x
, y
)
3375 struct timeval
*result
, x
, y
;
3377 /* Perform the carry for the later subtraction by updating y. This
3378 is safer because on some systems the tv_sec member is unsigned. */
3379 if (x
.tv_usec
< y
.tv_usec
)
3381 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3382 y
.tv_usec
-= 1000000 * nsec
;
3386 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3388 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3389 y
.tv_usec
+= 1000000 * nsec
;
3393 /* Compute the time remaining to wait. tv_usec is certainly
3395 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3396 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3398 /* Return indication of whether the result should be considered
3400 return x
.tv_sec
< y
.tv_sec
;
3407 /* Get the height not including a menu bar widget. */
3408 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3409 /* Height of each line to flash. */
3410 int flash_height
= FRAME_LINE_HEIGHT (f
);
3411 /* These will be the left and right margins of the rectangles. */
3412 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3413 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3417 /* Don't flash the area between a scroll bar and the frame
3418 edge it is next to. */
3419 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3421 case vertical_scroll_bar_left
:
3422 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3425 case vertical_scroll_bar_right
:
3426 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3433 width
= flash_right
- flash_left
;
3437 /* If window is tall, flash top and bottom line. */
3438 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3440 mac_invert_rectangle (f
, flash_left
,
3441 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3442 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3443 width
, flash_height
);
3444 mac_invert_rectangle (f
, flash_left
,
3445 (height
- flash_height
3446 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3447 width
, flash_height
);
3450 /* If it is short, flash it all. */
3451 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3452 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3457 struct timeval wakeup
;
3459 EMACS_GET_TIME (wakeup
);
3461 /* Compute time to wait until, propagating carry from usecs. */
3462 wakeup
.tv_usec
+= 150000;
3463 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3464 wakeup
.tv_usec
%= 1000000;
3466 /* Keep waiting until past the time wakeup or any input gets
3468 while (! detect_input_pending ())
3470 struct timeval current
;
3471 struct timeval timeout
;
3473 EMACS_GET_TIME (current
);
3475 /* Break if result would be negative. */
3476 if (timeval_subtract (¤t
, wakeup
, current
))
3479 /* How long `select' should wait. */
3481 timeout
.tv_usec
= 10000;
3483 /* Try to wait that long--but we might wake up sooner. */
3484 select (0, NULL
, NULL
, NULL
, &timeout
);
3488 /* If window is tall, flash top and bottom line. */
3489 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3491 mac_invert_rectangle (f
, flash_left
,
3492 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3493 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3494 width
, flash_height
);
3495 mac_invert_rectangle (f
, flash_left
,
3496 (height
- flash_height
3497 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3498 width
, flash_height
);
3501 /* If it is short, flash it all. */
3502 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3503 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3510 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3513 /* Make audible bell. */
3518 struct frame
*f
= SELECTED_FRAME ();
3520 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3528 XFlush (FRAME_MAC_DISPLAY (f
));
3534 /* Specify how many text lines, from the top of the window,
3535 should be affected by insert-lines and delete-lines operations.
3536 This, and those operations, are used only within an update
3537 that is bounded by calls to x_update_begin and x_update_end. */
3540 XTset_terminal_window (n
)
3543 /* This function intentionally left blank. */
3548 /***********************************************************************
3550 ***********************************************************************/
3552 /* Perform an insert-lines or delete-lines operation, inserting N
3553 lines or deleting -N lines at vertical position VPOS. */
3556 x_ins_del_lines (vpos
, n
)
3563 /* Scroll part of the display as described by RUN. */
3566 x_scroll_run (w
, run
)
3570 struct frame
*f
= XFRAME (w
->frame
);
3571 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3573 /* Get frame-relative bounding box of the text display area of W,
3574 without mode lines. Include in this box the left and right
3576 window_box (w
, -1, &x
, &y
, &width
, &height
);
3578 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3579 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3580 bottom_y
= y
+ height
;
3584 /* Scrolling up. Make sure we don't copy part of the mode
3585 line at the bottom. */
3586 if (from_y
+ run
->height
> bottom_y
)
3587 height
= bottom_y
- from_y
;
3589 height
= run
->height
;
3593 /* Scolling down. Make sure we don't copy over the mode line.
3595 if (to_y
+ run
->height
> bottom_y
)
3596 height
= bottom_y
- to_y
;
3598 height
= run
->height
;
3603 /* Cursor off. Will be switched on again in x_update_window_end. */
3607 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3617 /***********************************************************************
3619 ***********************************************************************/
3627 ControlRef root_control
;
3630 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3632 ActivateControl (root_control
);
3634 x_update_cursor (f
, 1);
3638 frame_unhighlight (f
)
3642 ControlRef root_control
;
3645 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3647 DeactivateControl (root_control
);
3649 x_update_cursor (f
, 1);
3652 /* The focus has changed. Update the frames as necessary to reflect
3653 the new situation. Note that we can't change the selected frame
3654 here, because the Lisp code we are interrupting might become confused.
3655 Each event gets marked with the frame in which it occurred, so the
3656 Lisp code can tell when the switch took place by examining the events. */
3659 x_new_focus_frame (dpyinfo
, frame
)
3660 struct x_display_info
*dpyinfo
;
3661 struct frame
*frame
;
3663 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3665 if (frame
!= dpyinfo
->x_focus_frame
)
3667 /* Set this before calling other routines, so that they see
3668 the correct value of x_focus_frame. */
3669 dpyinfo
->x_focus_frame
= frame
;
3671 if (old_focus
&& old_focus
->auto_lower
)
3672 x_lower_frame (old_focus
);
3675 selected_frame
= frame
;
3676 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3678 Fselect_window (selected_frame
->selected_window
, Qnil
);
3679 choose_minibuf_frame ();
3682 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3683 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3685 pending_autoraise_frame
= 0;
3688 x_frame_rehighlight (dpyinfo
);
3691 /* Handle FocusIn and FocusOut state changes for FRAME.
3692 If FRAME has focus and there exists more than one frame, puts
3693 a FOCUS_IN_EVENT into *BUFP. */
3696 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3698 struct mac_display_info
*dpyinfo
;
3699 struct frame
*frame
;
3700 struct input_event
*bufp
;
3702 if (type
== activeFlag
)
3704 if (dpyinfo
->x_focus_event_frame
!= frame
)
3706 x_new_focus_frame (dpyinfo
, frame
);
3707 dpyinfo
->x_focus_event_frame
= frame
;
3709 /* Don't stop displaying the initial startup message
3710 for a switch-frame event we don't need. */
3711 if (GC_NILP (Vterminal_frame
)
3712 && GC_CONSP (Vframe_list
)
3713 && !GC_NILP (XCDR (Vframe_list
)))
3715 bufp
->kind
= FOCUS_IN_EVENT
;
3716 XSETFRAME (bufp
->frame_or_window
, frame
);
3722 if (dpyinfo
->x_focus_event_frame
== frame
)
3724 dpyinfo
->x_focus_event_frame
= 0;
3725 x_new_focus_frame (dpyinfo
, 0);
3730 /* The focus may have changed. Figure out if it is a real focus change,
3731 by checking both FocusIn/Out and Enter/LeaveNotify events.
3733 Returns FOCUS_IN_EVENT event in *BUFP. */
3736 x_detect_focus_change (dpyinfo
, event
, bufp
)
3737 struct mac_display_info
*dpyinfo
;
3739 struct input_event
*bufp
;
3741 struct frame
*frame
;
3743 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3747 /* On Mac, this is only called from focus events, so no switch needed. */
3748 mac_focus_changed ((event
->modifiers
& activeFlag
),
3749 dpyinfo
, frame
, bufp
);
3753 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3756 x_mouse_leave (dpyinfo
)
3757 struct x_display_info
*dpyinfo
;
3759 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3762 /* The focus has changed, or we have redirected a frame's focus to
3763 another frame (this happens when a frame uses a surrogate
3764 mini-buffer frame). Shift the highlight as appropriate.
3766 The FRAME argument doesn't necessarily have anything to do with which
3767 frame is being highlighted or un-highlighted; we only use it to find
3768 the appropriate X display info. */
3771 XTframe_rehighlight (frame
)
3772 struct frame
*frame
;
3774 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3778 x_frame_rehighlight (dpyinfo
)
3779 struct x_display_info
*dpyinfo
;
3781 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3783 if (dpyinfo
->x_focus_frame
)
3785 dpyinfo
->x_highlight_frame
3786 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3787 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3788 : dpyinfo
->x_focus_frame
);
3789 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3791 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3792 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3796 dpyinfo
->x_highlight_frame
= 0;
3798 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3801 frame_unhighlight (old_highlight
);
3802 if (dpyinfo
->x_highlight_frame
)
3803 frame_highlight (dpyinfo
->x_highlight_frame
);
3809 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3811 #if 0 /* MAC_TODO */
3812 /* Initialize mode_switch_bit and modifier_meaning. */
3814 x_find_modifier_meanings (dpyinfo
)
3815 struct x_display_info
*dpyinfo
;
3817 int min_code
, max_code
;
3820 XModifierKeymap
*mods
;
3822 dpyinfo
->meta_mod_mask
= 0;
3823 dpyinfo
->shift_lock_mask
= 0;
3824 dpyinfo
->alt_mod_mask
= 0;
3825 dpyinfo
->super_mod_mask
= 0;
3826 dpyinfo
->hyper_mod_mask
= 0;
3829 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3831 min_code
= dpyinfo
->display
->min_keycode
;
3832 max_code
= dpyinfo
->display
->max_keycode
;
3835 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3836 min_code
, max_code
- min_code
+ 1,
3838 mods
= XGetModifierMapping (dpyinfo
->display
);
3840 /* Scan the modifier table to see which modifier bits the Meta and
3841 Alt keysyms are on. */
3843 int row
, col
; /* The row and column in the modifier table. */
3845 for (row
= 3; row
< 8; row
++)
3846 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3849 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3851 /* Zeroes are used for filler. Skip them. */
3855 /* Are any of this keycode's keysyms a meta key? */
3859 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3861 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3867 dpyinfo
->meta_mod_mask
|= (1 << row
);
3872 dpyinfo
->alt_mod_mask
|= (1 << row
);
3877 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3882 dpyinfo
->super_mod_mask
|= (1 << row
);
3886 /* Ignore this if it's not on the lock modifier. */
3887 if ((1 << row
) == LockMask
)
3888 dpyinfo
->shift_lock_mask
= LockMask
;
3896 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3897 if (! dpyinfo
->meta_mod_mask
)
3899 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3900 dpyinfo
->alt_mod_mask
= 0;
3903 /* If some keys are both alt and meta,
3904 make them just meta, not alt. */
3905 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3907 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3910 XFree ((char *) syms
);
3911 XFreeModifiermap (mods
);
3914 #endif /* MAC_TODO */
3916 /* Convert between the modifier bits X uses and the modifier bits
3920 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3921 struct x_display_info
*dpyinfo
;
3922 unsigned short state
;
3924 return (((state
& shiftKey
) ? shift_modifier
: 0)
3925 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3926 | ((state
& cmdKey
) ? meta_modifier
: 0)
3927 | ((state
& optionKey
) ? alt_modifier
: 0));
3930 #if 0 /* MAC_TODO */
3931 static unsigned short
3932 x_emacs_to_x_modifiers (dpyinfo
, state
)
3933 struct x_display_info
*dpyinfo
;
3936 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3937 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3938 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3939 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3940 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3941 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3943 #endif /* MAC_TODO */
3945 /* Convert a keysym to its name. */
3948 x_get_keysym_name (keysym
)
3955 value
= XKeysymToString (keysym
);
3966 /* Function to report a mouse movement to the mainstream Emacs code.
3967 The input handler calls this.
3969 We have received a mouse movement event, which is given in *event.
3970 If the mouse is over a different glyph than it was last time, tell
3971 the mainstream emacs code by setting mouse_moved. If not, ask for
3972 another motion event, so we can check again the next time it moves. */
3974 static Point last_mouse_motion_position
;
3975 static Lisp_Object last_mouse_motion_frame
;
3978 note_mouse_movement (frame
, pos
)
3982 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3983 #if TARGET_API_MAC_CARBON
3987 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3988 last_mouse_motion_position
= *pos
;
3989 XSETFRAME (last_mouse_motion_frame
, frame
);
3991 #if TARGET_API_MAC_CARBON
3992 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3994 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3997 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3998 /* This case corresponds to LeaveNotify in X11. */
4000 /* If we move outside the frame, then we're certainly no
4001 longer on any text in the frame. */
4002 clear_mouse_face (dpyinfo
);
4003 dpyinfo
->mouse_face_mouse_frame
= 0;
4004 if (!dpyinfo
->grabbed
)
4005 rif
->define_frame_cursor (frame
,
4006 frame
->output_data
.mac
->nontext_cursor
);
4010 /* Has the mouse moved off the glyph it was on at the last sighting? */
4011 if (frame
!= last_mouse_glyph_frame
4012 || !PtInRect (*pos
, &last_mouse_glyph
))
4014 frame
->mouse_moved
= 1;
4015 last_mouse_scroll_bar
= Qnil
;
4016 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4017 /* Remember which glyph we're now on. */
4018 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4019 last_mouse_glyph_frame
= frame
;
4027 /************************************************************************
4029 ************************************************************************/
4031 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4034 redo_mouse_highlight ()
4036 if (!NILP (last_mouse_motion_frame
)
4037 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4038 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4039 last_mouse_motion_position
.h
,
4040 last_mouse_motion_position
.v
);
4044 static struct frame
*
4045 mac_focus_frame (dpyinfo
)
4046 struct mac_display_info
*dpyinfo
;
4048 if (dpyinfo
->x_focus_frame
)
4049 return dpyinfo
->x_focus_frame
;
4051 /* Mac version may get events, such as a menu bar click, even when
4052 all the frames are invisible. In this case, we regard the
4053 event came to the selected frame. */
4054 return SELECTED_FRAME ();
4058 /* Return the current position of the mouse.
4059 *FP should be a frame which indicates which display to ask about.
4061 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4062 and *PART to the frame, window, and scroll bar part that the mouse
4063 is over. Set *X and *Y to the portion and whole of the mouse's
4064 position on the scroll bar.
4066 If the mouse movement started elsewhere, set *FP to the frame the
4067 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4070 Set *TIME to the server time-stamp for the time at which the mouse
4071 was at this position.
4073 Don't store anything if we don't have a valid set of values to report.
4075 This clears the mouse_moved flag, so we can wait for the next mouse
4079 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4082 Lisp_Object
*bar_window
;
4083 enum scroll_bar_part
*part
;
4085 unsigned long *time
;
4091 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4092 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4095 Lisp_Object frame
, tail
;
4097 /* Clear the mouse-moved flag for every frame on this display. */
4098 FOR_EACH_FRAME (tail
, frame
)
4099 XFRAME (frame
)->mouse_moved
= 0;
4101 last_mouse_scroll_bar
= Qnil
;
4103 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4104 && FRAME_LIVE_P (last_mouse_frame
))
4105 f1
= last_mouse_frame
;
4107 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4111 /* Ok, we found a frame. Store all the values.
4112 last_mouse_glyph is a rectangle used to reduce the
4113 generation of mouse events. To not miss any motion
4114 events, we must divide the frame into rectangles of the
4115 size of the smallest character that could be displayed
4116 on it, i.e. into the same rectangles that matrices on
4117 the frame are divided into. */
4120 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4121 GetMouse (&mouse_pos
);
4122 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4124 last_mouse_glyph_frame
= f1
;
4129 XSETINT (*x
, mouse_pos
.h
);
4130 XSETINT (*y
, mouse_pos
.v
);
4131 *time
= last_mouse_movement_time
;
4139 /************************************************************************
4141 ************************************************************************/
4143 #ifdef USE_TOOLKIT_SCROLL_BARS
4145 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4146 static OSStatus install_scroll_bar_timer
P_ ((void));
4147 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4148 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4149 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4150 struct input_event
*));
4151 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4153 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4155 struct input_event
*));
4156 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4157 struct input_event
*));
4158 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4159 Point
, struct input_event
*));
4160 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4163 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4165 static int last_scroll_bar_part
;
4167 static EventLoopTimerRef scroll_bar_timer
;
4169 static int scroll_bar_timer_event_posted_p
;
4171 #define SCROLL_BAR_FIRST_DELAY 0.5
4172 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4175 scroll_bar_timer_callback (timer
, data
)
4176 EventLoopTimerRef timer
;
4179 EventRef event
= NULL
;
4182 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4183 kEventAttributeNone
, &event
);
4188 GetMouse (&mouse_pos
);
4189 LocalToGlobal (&mouse_pos
);
4190 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4191 sizeof (Point
), &mouse_pos
);
4195 UInt32 modifiers
= GetCurrentKeyModifiers ();
4197 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4198 sizeof (UInt32
), &modifiers
);
4201 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4202 kEventPriorityStandard
);
4204 scroll_bar_timer_event_posted_p
= 1;
4207 ReleaseEvent (event
);
4211 install_scroll_bar_timer ()
4213 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4215 if (scroll_bar_timer_callbackUPP
== NULL
)
4216 scroll_bar_timer_callbackUPP
=
4217 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4219 if (scroll_bar_timer
== NULL
)
4220 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4221 kEventDurationForever as delays. */
4223 InstallEventLoopTimer (GetCurrentEventLoop (),
4224 kEventDurationForever
, kEventDurationForever
,
4225 scroll_bar_timer_callbackUPP
, NULL
,
4230 set_scroll_bar_timer (delay
)
4231 EventTimerInterval delay
;
4233 if (scroll_bar_timer
== NULL
)
4234 install_scroll_bar_timer ();
4236 scroll_bar_timer_event_posted_p
= 0;
4238 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4242 control_part_code_to_scroll_bar_part (part_code
)
4243 ControlPartCode part_code
;
4247 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4248 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4249 case kControlPageUpPart
: return scroll_bar_above_handle
;
4250 case kControlPageDownPart
: return scroll_bar_below_handle
;
4251 case kControlIndicatorPart
: return scroll_bar_handle
;
4258 construct_scroll_bar_click (bar
, part
, bufp
)
4259 struct scroll_bar
*bar
;
4261 struct input_event
*bufp
;
4263 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4264 bufp
->frame_or_window
= bar
->window
;
4268 XSETINT (bufp
->x
, 0);
4269 XSETINT (bufp
->y
, 0);
4270 bufp
->modifiers
= 0;
4274 get_control_part_bounds (ch
, part_code
, rect
)
4276 ControlPartCode part_code
;
4279 RgnHandle region
= NewRgn ();
4282 err
= GetControlRegion (ch
, part_code
, region
);
4284 GetRegionBounds (region
, rect
);
4285 DisposeRgn (region
);
4291 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4292 struct scroll_bar
*bar
;
4293 ControlPartCode part_code
;
4294 struct input_event
*bufp
;
4296 int part
= control_part_code_to_scroll_bar_part (part_code
);
4301 if (part
!= scroll_bar_handle
)
4303 construct_scroll_bar_click (bar
, part
, bufp
);
4304 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4305 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4308 last_scroll_bar_part
= part
;
4309 bar
->dragging
= Qnil
;
4310 tracked_scroll_bar
= bar
;
4314 x_scroll_bar_handle_release (bar
, bufp
)
4315 struct scroll_bar
*bar
;
4316 struct input_event
*bufp
;
4318 if (last_scroll_bar_part
!= scroll_bar_handle
4319 || !GC_NILP (bar
->dragging
))
4320 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4322 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4323 set_scroll_bar_timer (kEventDurationForever
);
4325 last_scroll_bar_part
= -1;
4326 bar
->dragging
= Qnil
;
4327 tracked_scroll_bar
= NULL
;
4331 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4333 struct scroll_bar
*bar
;
4335 struct input_event
*bufp
;
4337 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4339 if (last_scroll_bar_part
== scroll_bar_handle
)
4344 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4345 kControlIndicatorPart
, &r
);
4347 if (GC_NILP (bar
->dragging
))
4348 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4350 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4351 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4352 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4357 if (top
> top_range
)
4360 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4361 XSETINT (bufp
->x
, top
);
4362 XSETINT (bufp
->y
, top_range
);
4366 ControlPartCode part_code
;
4367 int unhilite_p
= 0, part
;
4369 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4373 part
= control_part_code_to_scroll_bar_part (part_code
);
4375 switch (last_scroll_bar_part
)
4377 case scroll_bar_above_handle
:
4378 case scroll_bar_below_handle
:
4379 if (part
!= scroll_bar_above_handle
4380 && part
!= scroll_bar_below_handle
)
4384 case scroll_bar_up_arrow
:
4385 case scroll_bar_down_arrow
:
4386 if (part
!= scroll_bar_up_arrow
4387 && part
!= scroll_bar_down_arrow
)
4394 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4395 else if (part
!= last_scroll_bar_part
4396 || scroll_bar_timer_event_posted_p
)
4398 construct_scroll_bar_click (bar
, part
, bufp
);
4399 last_scroll_bar_part
= part
;
4400 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4401 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4406 /* Set the thumb size and position of scroll bar BAR. We are currently
4407 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4410 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4411 struct scroll_bar
*bar
;
4412 int portion
, position
, whole
;
4414 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4416 int value
, viewsize
, maximum
;
4418 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4419 value
= 0, viewsize
= 1, maximum
= 0;
4424 maximum
= max (0, whole
- portion
);
4429 SetControl32BitMinimum (ch
, 0);
4430 SetControl32BitMaximum (ch
, maximum
);
4431 SetControl32BitValue (ch
, value
);
4432 SetControlViewSize (ch
, viewsize
);
4437 #endif /* USE_TOOLKIT_SCROLL_BARS */
4441 /************************************************************************
4442 Scroll bars, general
4443 ************************************************************************/
4445 /* Create a scroll bar and return the scroll bar vector for it. W is
4446 the Emacs window on which to create the scroll bar. TOP, LEFT,
4447 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4450 static struct scroll_bar
*
4451 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4453 int top
, left
, width
, height
, disp_top
, disp_height
;
4455 struct frame
*f
= XFRAME (w
->frame
);
4456 struct scroll_bar
*bar
4457 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4465 r
.right
= left
+ width
;
4466 r
.bottom
= disp_top
+ disp_height
;
4468 #if TARGET_API_MAC_CARBON
4469 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4470 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4472 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4473 0, 0, 0, scrollBarProc
, (long) bar
);
4475 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4477 XSETWINDOW (bar
->window
, w
);
4478 XSETINT (bar
->top
, top
);
4479 XSETINT (bar
->left
, left
);
4480 XSETINT (bar
->width
, width
);
4481 XSETINT (bar
->height
, height
);
4482 XSETINT (bar
->start
, 0);
4483 XSETINT (bar
->end
, 0);
4484 bar
->dragging
= Qnil
;
4485 #ifdef USE_TOOLKIT_SCROLL_BARS
4486 bar
->track_top
= Qnil
;
4487 bar
->track_height
= Qnil
;
4490 /* Add bar to its frame's list of scroll bars. */
4491 bar
->next
= FRAME_SCROLL_BARS (f
);
4493 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4494 if (!NILP (bar
->next
))
4495 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4502 /* Draw BAR's handle in the proper position.
4504 If the handle is already drawn from START to END, don't bother
4505 redrawing it, unless REBUILD is non-zero; in that case, always
4506 redraw it. (REBUILD is handy for drawing the handle after expose
4509 Normally, we want to constrain the start and end of the handle to
4510 fit inside its rectangle, but if the user is dragging the scroll
4511 bar handle, we want to let them drag it down all the way, so that
4512 the bar's top is as far down as it goes; otherwise, there's no way
4513 to move to the very end of the buffer. */
4515 #ifndef USE_TOOLKIT_SCROLL_BARS
4518 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4519 struct scroll_bar
*bar
;
4523 int dragging
= ! NILP (bar
->dragging
);
4524 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4525 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4526 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4527 int length
= end
- start
;
4529 /* If the display is already accurate, do nothing. */
4531 && start
== XINT (bar
->start
)
4532 && end
== XINT (bar
->end
))
4537 /* Make sure the values are reasonable, and try to preserve the
4538 distance between start and end. */
4541 else if (start
> top_range
)
4543 end
= start
+ length
;
4547 else if (end
> top_range
&& ! dragging
)
4550 /* Store the adjusted setting in the scroll bar. */
4551 XSETINT (bar
->start
, start
);
4552 XSETINT (bar
->end
, end
);
4554 /* Clip the end position, just for display. */
4555 if (end
> top_range
)
4558 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4559 top positions, to make sure the handle is always at least that
4560 many pixels tall. */
4561 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4563 SetControlMinimum (ch
, 0);
4564 /* Don't inadvertently activate deactivated scroll bars */
4565 if (GetControlMaximum (ch
) != -1)
4566 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4568 SetControlValue (ch
, start
);
4569 #if TARGET_API_MAC_CARBON
4570 SetControlViewSize (ch
, end
- start
);
4576 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4578 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4582 x_scroll_bar_remove (bar
)
4583 struct scroll_bar
*bar
;
4585 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4589 /* Destroy the Mac scroll bar control */
4590 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4592 /* Disassociate this scroll bar from its window. */
4593 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4599 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4600 that we are displaying PORTION characters out of a total of WHOLE
4601 characters, starting at POSITION. If WINDOW has no scroll bar,
4605 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4607 int portion
, whole
, position
;
4609 struct frame
*f
= XFRAME (w
->frame
);
4610 struct scroll_bar
*bar
;
4611 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4612 int window_y
, window_height
;
4614 /* Get window dimensions. */
4615 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4617 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4618 height
= window_height
;
4620 /* Compute the left edge of the scroll bar area. */
4621 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4623 /* Compute the width of the scroll bar which might be less than
4624 the width of the area reserved for the scroll bar. */
4625 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4626 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4630 /* Compute the left edge of the scroll bar. */
4631 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4634 sb_left
= left
+ width
- sb_width
;
4636 /* Adjustments according to Inside Macintosh to make it look nice */
4638 disp_height
= height
;
4644 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4650 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4653 /* Does the scroll bar exist yet? */
4654 if (NILP (w
->vertical_scroll_bar
))
4657 mac_clear_area (f
, left
, top
, width
, height
);
4659 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4661 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4665 /* It may just need to be moved and resized. */
4668 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4669 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4673 /* If already correctly positioned, do nothing. */
4674 if (!(XINT (bar
->left
) == sb_left
4675 && XINT (bar
->top
) == top
4676 && XINT (bar
->width
) == sb_width
4677 && XINT (bar
->height
) == height
))
4679 /* Since toolkit scroll bars are smaller than the space reserved
4680 for them on the frame, we have to clear "under" them. */
4681 mac_clear_area (f
, left
, top
, width
, height
);
4684 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4685 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4687 if (sb_width
< disp_height
)
4690 /* Remember new settings. */
4691 XSETINT (bar
->left
, sb_left
);
4692 XSETINT (bar
->top
, top
);
4693 XSETINT (bar
->width
, sb_width
);
4694 XSETINT (bar
->height
, height
);
4695 #ifdef USE_TOOLKIT_SCROLL_BARS
4696 bar
->track_top
= Qnil
;
4697 bar
->track_height
= Qnil
;
4704 #ifdef USE_TOOLKIT_SCROLL_BARS
4705 if (NILP (bar
->track_top
))
4707 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4712 SetControl32BitMinimum (ch
, 0);
4713 SetControl32BitMaximum (ch
, 1);
4714 SetControlViewSize (ch
, 1);
4716 /* Move the scroll bar thumb to the top. */
4717 SetControl32BitValue (ch
, 0);
4718 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4720 /* Move the scroll bar thumb to the bottom. */
4721 SetControl32BitValue (ch
, 1);
4722 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4724 UnionRect (&r0
, &r1
, &r0
);
4725 XSETINT (bar
->track_top
, r0
.top
);
4726 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4731 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4732 #else /* not USE_TOOLKIT_SCROLL_BARS */
4733 /* Set the scroll bar's current state, unless we're currently being
4735 if (NILP (bar
->dragging
))
4737 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4740 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4743 int start
= ((double) position
* top_range
) / whole
;
4744 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4745 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4748 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4752 /* The following three hooks are used when we're doing a thorough
4753 redisplay of the frame. We don't explicitly know which scroll bars
4754 are going to be deleted, because keeping track of when windows go
4755 away is a real pain - "Can you say set-window-configuration, boys
4756 and girls?" Instead, we just assert at the beginning of redisplay
4757 that *all* scroll bars are to be removed, and then save a scroll bar
4758 from the fiery pit when we actually redisplay its window. */
4760 /* Arrange for all scroll bars on FRAME to be removed at the next call
4761 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4762 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4765 XTcondemn_scroll_bars (frame
)
4768 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4769 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4772 bar
= FRAME_SCROLL_BARS (frame
);
4773 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4774 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4775 XSCROLL_BAR (bar
)->prev
= Qnil
;
4776 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4777 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4778 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4783 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4784 Note that WINDOW isn't necessarily condemned at all. */
4787 XTredeem_scroll_bar (window
)
4788 struct window
*window
;
4790 struct scroll_bar
*bar
;
4793 /* We can't redeem this window's scroll bar if it doesn't have one. */
4794 if (NILP (window
->vertical_scroll_bar
))
4797 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4799 /* Unlink it from the condemned list. */
4800 f
= XFRAME (WINDOW_FRAME (window
));
4801 if (NILP (bar
->prev
))
4803 /* If the prev pointer is nil, it must be the first in one of
4805 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4806 /* It's not condemned. Everything's fine. */
4808 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4809 window
->vertical_scroll_bar
))
4810 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4812 /* If its prev pointer is nil, it must be at the front of
4813 one or the other! */
4817 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4819 if (! NILP (bar
->next
))
4820 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4822 bar
->next
= FRAME_SCROLL_BARS (f
);
4824 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4825 if (! NILP (bar
->next
))
4826 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4829 /* Remove all scroll bars on FRAME that haven't been saved since the
4830 last call to `*condemn_scroll_bars_hook'. */
4833 XTjudge_scroll_bars (f
)
4836 Lisp_Object bar
, next
;
4838 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4840 /* Clear out the condemned list now so we won't try to process any
4841 more events on the hapless scroll bars. */
4842 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4844 for (; ! NILP (bar
); bar
= next
)
4846 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4848 x_scroll_bar_remove (b
);
4851 b
->next
= b
->prev
= Qnil
;
4854 /* Now there should be no references to the condemned scroll bars,
4855 and they should get garbage-collected. */
4859 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4860 is set to something other than NO_EVENT, it is enqueued.
4862 This may be called from a signal handler, so we have to ignore GC
4866 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4867 struct scroll_bar
*bar
;
4868 ControlPartCode part_code
;
4870 struct input_event
*bufp
;
4872 int win_y
, top_range
;
4874 if (! GC_WINDOWP (bar
->window
))
4877 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4878 bufp
->frame_or_window
= bar
->window
;
4881 bar
->dragging
= Qnil
;
4885 case kControlUpButtonPart
:
4886 bufp
->part
= scroll_bar_up_arrow
;
4888 case kControlDownButtonPart
:
4889 bufp
->part
= scroll_bar_down_arrow
;
4891 case kControlPageUpPart
:
4892 bufp
->part
= scroll_bar_above_handle
;
4894 case kControlPageDownPart
:
4895 bufp
->part
= scroll_bar_below_handle
;
4897 #if TARGET_API_MAC_CARBON
4900 case kControlIndicatorPart
:
4902 if (er
->what
== mouseDown
)
4903 bar
->dragging
= make_number (0);
4904 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4905 bufp
->part
= scroll_bar_handle
;
4909 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4910 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4912 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4916 if (! NILP (bar
->dragging
))
4917 win_y
-= XINT (bar
->dragging
);
4921 if (win_y
> top_range
)
4924 XSETINT (bufp
->x
, win_y
);
4925 XSETINT (bufp
->y
, top_range
);
4928 #ifndef USE_TOOLKIT_SCROLL_BARS
4930 /* Handle some mouse motion while someone is dragging the scroll bar.
4932 This may be called from a signal handler, so we have to ignore GC
4936 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4937 struct scroll_bar
*bar
;
4941 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4943 last_mouse_movement_time
= t
;
4946 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4948 /* If we're dragging the bar, display it. */
4949 if (! GC_NILP (bar
->dragging
))
4951 /* Where should the handle be now? */
4952 int new_start
= y_pos
- 24;
4954 if (new_start
!= XINT (bar
->start
))
4956 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4958 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4963 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4965 /* Return information to the user about the current position of the mouse
4966 on the scroll bar. */
4969 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4971 Lisp_Object
*bar_window
;
4972 enum scroll_bar_part
*part
;
4974 unsigned long *time
;
4976 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4977 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4978 #if TARGET_API_MAC_CARBON
4979 WindowPtr wp
= GetControlOwner (ch
);
4981 WindowPtr wp
= (*ch
)->contrlOwner
;
4984 struct frame
*f
= mac_window_to_frame (wp
);
4985 int win_y
, top_range
;
4987 SetPortWindowPort (wp
);
4989 GetMouse (&mouse_pos
);
4991 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4992 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4994 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4998 if (! NILP (bar
->dragging
))
4999 win_y
-= XINT (bar
->dragging
);
5003 if (win_y
> top_range
)
5007 *bar_window
= bar
->window
;
5009 if (! NILP (bar
->dragging
))
5010 *part
= scroll_bar_handle
;
5011 else if (win_y
< XINT (bar
->start
))
5012 *part
= scroll_bar_above_handle
;
5013 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5014 *part
= scroll_bar_handle
;
5016 *part
= scroll_bar_below_handle
;
5018 XSETINT (*x
, win_y
);
5019 XSETINT (*y
, top_range
);
5022 last_mouse_scroll_bar
= Qnil
;
5024 *time
= last_mouse_movement_time
;
5028 /* The screen has been cleared so we may have changed foreground or
5029 background colors, and the scroll bars may need to be redrawn.
5030 Clear out the scroll bars, and ask for expose events, so we can
5034 x_scroll_bar_clear (f
)
5037 XTcondemn_scroll_bars (f
);
5038 XTjudge_scroll_bars (f
);
5042 /***********************************************************************
5044 ***********************************************************************/
5046 /* Set clipping for output in glyph row ROW. W is the window in which
5047 we operate. GC is the graphics context to set clipping in.
5049 ROW may be a text row or, e.g., a mode line. Text rows must be
5050 clipped to the interior of the window dedicated to text display,
5051 mode lines must be clipped to the whole window. */
5054 x_clip_to_row (w
, row
, area
, gc
)
5056 struct glyph_row
*row
;
5060 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5062 int window_x
, window_y
, window_width
;
5064 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5066 clip_rect
.left
= window_x
;
5067 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5068 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5069 clip_rect
.right
= clip_rect
.left
+ window_width
;
5070 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5072 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5076 /* Draw a hollow box cursor on window W in glyph row ROW. */
5079 x_draw_hollow_cursor (w
, row
)
5081 struct glyph_row
*row
;
5083 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5084 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5085 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5088 struct glyph
*cursor_glyph
;
5091 /* Get the glyph the cursor is on. If we can't tell because
5092 the current matrix is invalid or such, give up. */
5093 cursor_glyph
= get_phys_cursor_glyph (w
);
5094 if (cursor_glyph
== NULL
)
5097 /* Compute frame-relative coordinates for phys cursor. */
5098 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5099 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5100 wd
= w
->phys_cursor_width
;
5102 /* The foreground of cursor_gc is typically the same as the normal
5103 background color, which can cause the cursor box to be invisible. */
5104 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5105 if (dpyinfo
->scratch_cursor_gc
)
5106 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5108 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5109 GCForeground
, &xgcv
);
5110 gc
= dpyinfo
->scratch_cursor_gc
;
5112 /* Set clipping, draw the rectangle, and reset clipping again. */
5113 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5114 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
);
5115 mac_reset_clip_rectangles (dpy
, gc
);
5119 /* Draw a bar cursor on window W in glyph row ROW.
5121 Implementation note: One would like to draw a bar cursor with an
5122 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5123 Unfortunately, I didn't find a font yet that has this property set.
5127 x_draw_bar_cursor (w
, row
, width
, kind
)
5129 struct glyph_row
*row
;
5131 enum text_cursor_kinds kind
;
5133 struct frame
*f
= XFRAME (w
->frame
);
5134 struct glyph
*cursor_glyph
;
5136 /* If cursor is out of bounds, don't draw garbage. This can happen
5137 in mini-buffer windows when switching between echo area glyphs
5139 cursor_glyph
= get_phys_cursor_glyph (w
);
5140 if (cursor_glyph
== NULL
)
5143 /* If on an image, draw like a normal cursor. That's usually better
5144 visible than drawing a bar, esp. if the image is large so that
5145 the bar might not be in the window. */
5146 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5148 struct glyph_row
*row
;
5149 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5150 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5154 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5155 Window window
= FRAME_MAC_WINDOW (f
);
5156 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5157 unsigned long mask
= GCForeground
| GCBackground
;
5158 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5161 /* If the glyph's background equals the color we normally draw
5162 the bar cursor in, the bar cursor in its normal color is
5163 invisible. Use the glyph's foreground color instead in this
5164 case, on the assumption that the glyph's colors are chosen so
5165 that the glyph is legible. */
5166 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5167 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5169 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5172 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5175 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5176 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5180 width
= FRAME_CURSOR_WIDTH (f
);
5181 width
= min (cursor_glyph
->pixel_width
, width
);
5183 w
->phys_cursor_width
= width
;
5184 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5186 if (kind
== BAR_CURSOR
)
5187 mac_fill_rectangle (f
, gc
,
5188 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5189 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5190 width
, row
->height
);
5192 mac_fill_rectangle (f
, gc
,
5193 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5194 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5195 row
->height
- width
),
5196 cursor_glyph
->pixel_width
,
5199 mac_reset_clip_rectangles (dpy
, gc
);
5204 /* RIF: Define cursor CURSOR on frame F. */
5207 mac_define_frame_cursor (f
, cursor
)
5211 SetThemeCursor (cursor
);
5215 /* RIF: Clear area on frame F. */
5218 mac_clear_frame_area (f
, x
, y
, width
, height
)
5220 int x
, y
, width
, height
;
5222 mac_clear_area (f
, x
, y
, width
, height
);
5226 /* RIF: Draw cursor on window W. */
5229 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5231 struct glyph_row
*glyph_row
;
5233 int cursor_type
, cursor_width
;
5238 w
->phys_cursor_type
= cursor_type
;
5239 w
->phys_cursor_on_p
= 1;
5241 if (glyph_row
->exact_window_width_line_p
5242 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5244 glyph_row
->cursor_in_fringe_p
= 1;
5245 draw_fringe_bitmap (w
, glyph_row
, 0);
5248 switch (cursor_type
)
5250 case HOLLOW_BOX_CURSOR
:
5251 x_draw_hollow_cursor (w
, glyph_row
);
5254 case FILLED_BOX_CURSOR
:
5255 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5259 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5263 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5267 w
->phys_cursor_width
= 0;
5279 #if 0 /* MAC_TODO: no icon support yet. */
5281 x_bitmap_icon (f
, icon
)
5287 if (FRAME_W32_WINDOW (f
) == 0)
5291 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5292 else if (STRINGP (icon
))
5293 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5294 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5295 else if (SYMBOLP (icon
))
5299 if (EQ (icon
, intern ("application")))
5300 name
= (LPCTSTR
) IDI_APPLICATION
;
5301 else if (EQ (icon
, intern ("hand")))
5302 name
= (LPCTSTR
) IDI_HAND
;
5303 else if (EQ (icon
, intern ("question")))
5304 name
= (LPCTSTR
) IDI_QUESTION
;
5305 else if (EQ (icon
, intern ("exclamation")))
5306 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5307 else if (EQ (icon
, intern ("asterisk")))
5308 name
= (LPCTSTR
) IDI_ASTERISK
;
5309 else if (EQ (icon
, intern ("winlogo")))
5310 name
= (LPCTSTR
) IDI_WINLOGO
;
5314 hicon
= LoadIcon (NULL
, name
);
5322 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5327 #endif /* MAC_TODO */
5329 /************************************************************************
5331 ************************************************************************/
5333 /* Display Error Handling functions not used on W32. Listing them here
5334 helps diff stay in step when comparing w32term.c with xterm.c.
5336 x_error_catcher (display, error)
5337 x_catch_errors (dpy)
5338 x_catch_errors_unwind (old_val)
5339 x_check_errors (dpy, format)
5340 x_had_errors_p (dpy)
5341 x_clear_errors (dpy)
5342 x_uncatch_errors (dpy, count)
5344 x_connection_signal (signalnum)
5345 x_connection_closed (dpy, error_message)
5346 x_error_quitter (display, error)
5347 x_error_handler (display, error)
5348 x_io_error_quitter (display)
5353 /* Changing the font of the frame. */
5355 /* Give frame F the font named FONTNAME as its default font, and
5356 return the full name of that font. FONTNAME may be a wildcard
5357 pattern; in that case, we choose some font that fits the pattern.
5358 The return value shows which font we chose. */
5361 x_new_font (f
, fontname
)
5363 register char *fontname
;
5365 struct font_info
*fontp
5366 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5371 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5372 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5373 FRAME_FONTSET (f
) = -1;
5375 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5376 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5377 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5379 compute_fringe_widths (f
, 1);
5381 /* Compute the scroll bar width in character columns. */
5382 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5384 int wid
= FRAME_COLUMN_WIDTH (f
);
5385 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5386 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5390 int wid
= FRAME_COLUMN_WIDTH (f
);
5391 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5394 /* Now make the frame display the given font. */
5395 if (FRAME_MAC_WINDOW (f
) != 0)
5397 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5399 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5401 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5404 /* Don't change the size of a tip frame; there's no point in
5405 doing it because it's done in Fx_show_tip, and it leads to
5406 problems because the tip frame has no widget. */
5407 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5408 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5411 return build_string (fontp
->full_name
);
5414 /* Give frame F the fontset named FONTSETNAME as its default font, and
5415 return the full name of that fontset. FONTSETNAME may be a wildcard
5416 pattern; in that case, we choose some fontset that fits the pattern.
5417 The return value shows which fontset we chose. */
5420 x_new_fontset (f
, fontsetname
)
5424 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5430 if (FRAME_FONTSET (f
) == fontset
)
5431 /* This fontset is already set in frame F. There's nothing more
5433 return fontset_name (fontset
);
5435 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5437 if (!STRINGP (result
))
5438 /* Can't load ASCII font. */
5441 /* Since x_new_font doesn't update any fontset information, do it now. */
5442 FRAME_FONTSET (f
) = fontset
;
5444 return build_string (fontsetname
);
5448 /***********************************************************************
5449 TODO: W32 Input Methods
5450 ***********************************************************************/
5451 /* Listing missing functions from xterm.c helps diff stay in step.
5453 xim_destroy_callback (xim, client_data, call_data)
5454 xim_open_dpy (dpyinfo, resource_name)
5456 xim_instantiate_callback (display, client_data, call_data)
5457 xim_initialize (dpyinfo, resource_name)
5458 xim_close_dpy (dpyinfo)
5464 mac_get_window_bounds (f
, inner
, outer
)
5466 Rect
*inner
, *outer
;
5468 #if TARGET_API_MAC_CARBON
5469 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5470 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5471 #else /* not TARGET_API_MAC_CARBON */
5472 RgnHandle region
= NewRgn ();
5474 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5475 *inner
= (*region
)->rgnBBox
;
5476 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5477 *outer
= (*region
)->rgnBBox
;
5478 DisposeRgn (region
);
5479 #endif /* not TARGET_API_MAC_CARBON */
5484 /* Calculate the absolute position in frame F
5485 from its current recorded position values and gravity. */
5488 x_calc_absolute_position (f
)
5491 int width_diff
= 0, height_diff
= 0;
5492 int flags
= f
->size_hint_flags
;
5495 /* We have nothing to do if the current position
5496 is already for the top-left corner. */
5497 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5500 /* Find the offsets of the outside upper-left corner of
5501 the inner window, with respect to the outer window. */
5502 mac_get_window_bounds (f
, &inner
, &outer
);
5504 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5505 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5507 /* Treat negative positions as relative to the leftmost bottommost
5508 position that fits on the screen. */
5509 if (flags
& XNegative
)
5510 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5512 - FRAME_PIXEL_WIDTH (f
)
5515 if (flags
& YNegative
)
5516 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5518 - FRAME_PIXEL_HEIGHT (f
)
5521 /* The left_pos and top_pos
5522 are now relative to the top and left screen edges,
5523 so the flags should correspond. */
5524 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5527 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5528 to really change the position, and 0 when calling from
5529 x_make_frame_visible (in that case, XOFF and YOFF are the current
5530 position values). It is -1 when calling from x_set_frame_parameters,
5531 which means, do adjust for borders but don't change the gravity. */
5534 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5536 register int xoff
, yoff
;
5539 if (change_gravity
> 0)
5543 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5545 f
->size_hint_flags
|= XNegative
;
5547 f
->size_hint_flags
|= YNegative
;
5548 f
->win_gravity
= NorthWestGravity
;
5550 x_calc_absolute_position (f
);
5553 x_wm_set_size_hint (f
, (long) 0, 0);
5555 #if TARGET_API_MAC_CARBON
5556 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5557 /* If the title bar is completely outside the screen, adjust the
5559 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5560 kWindowConstrainMoveRegardlessOfFit
5561 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5562 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5565 Rect inner
, outer
, screen_rect
, dummy
;
5566 RgnHandle region
= NewRgn ();
5568 mac_get_window_bounds (f
, &inner
, &outer
);
5569 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5570 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5571 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5572 f
->top_pos
+ f
->y_pixels_diff
, false);
5574 /* If the title bar is completely outside the screen, adjust the
5575 position. The variable `outer' holds the title bar rectangle.
5576 The variable `inner' holds slightly smaller one than `outer',
5577 so that the calculation of overlapping may not become too
5579 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5580 outer
= (*region
)->rgnBBox
;
5581 DisposeRgn (region
);
5583 InsetRect (&inner
, 8, 8);
5584 screen_rect
= qd
.screenBits
.bounds
;
5585 screen_rect
.top
+= GetMBarHeight ();
5587 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5589 if (inner
.right
<= screen_rect
.left
)
5590 f
->left_pos
= screen_rect
.left
;
5591 else if (inner
.left
>= screen_rect
.right
)
5592 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5594 if (inner
.bottom
<= screen_rect
.top
)
5595 f
->top_pos
= screen_rect
.top
;
5596 else if (inner
.top
>= screen_rect
.bottom
)
5597 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5599 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5600 f
->top_pos
+ f
->y_pixels_diff
, false);
5608 /* Call this to change the size of frame F's x-window.
5609 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5610 for this size change and subsequent size changes.
5611 Otherwise we leave the window gravity unchanged. */
5614 x_set_window_size (f
, change_gravity
, cols
, rows
)
5619 int pixelwidth
, pixelheight
;
5623 check_frame_size (f
, &rows
, &cols
);
5624 f
->scroll_bar_actual_width
5625 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5627 compute_fringe_widths (f
, 0);
5629 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5630 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5632 f
->win_gravity
= NorthWestGravity
;
5633 x_wm_set_size_hint (f
, (long) 0, 0);
5635 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5636 #if TARGET_API_MAC_CARBON
5637 if (f
->output_data
.mac
->hourglass_control
)
5638 MoveControl (f
->output_data
.mac
->hourglass_control
,
5639 pixelwidth
- HOURGLASS_WIDTH
, 0);
5642 /* Now, strictly speaking, we can't be sure that this is accurate,
5643 but the window manager will get around to dealing with the size
5644 change request eventually, and we'll hear how it went when the
5645 ConfigureNotify event gets here.
5647 We could just not bother storing any of this information here,
5648 and let the ConfigureNotify event set everything up, but that
5649 might be kind of confusing to the Lisp code, since size changes
5650 wouldn't be reported in the frame parameters until some random
5651 point in the future when the ConfigureNotify event arrives.
5653 We pass 1 for DELAY since we can't run Lisp code inside of
5655 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5656 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5657 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5659 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5660 receive in the ConfigureNotify event; if we get what we asked
5661 for, then the event won't cause the screen to become garbaged, so
5662 we have to make sure to do it here. */
5663 SET_FRAME_GARBAGED (f
);
5665 XFlush (FRAME_X_DISPLAY (f
));
5667 /* If cursor was outside the new size, mark it as off. */
5668 mark_window_cursors_off (XWINDOW (f
->root_window
));
5670 /* Clear out any recollection of where the mouse highlighting was,
5671 since it might be in a place that's outside the new frame size.
5672 Actually checking whether it is outside is a pain in the neck,
5673 so don't try--just let the highlighting be done afresh with new size. */
5674 cancel_mouse_face (f
);
5679 /* Mouse warping. */
5681 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5684 x_set_mouse_position (f
, x
, y
)
5690 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5691 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5693 if (pix_x
< 0) pix_x
= 0;
5694 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5696 if (pix_y
< 0) pix_y
= 0;
5697 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5699 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5703 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5707 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5710 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5711 0, 0, 0, 0, pix_x
, pix_y
);
5716 /* focus shifting, raising and lowering. */
5719 x_focus_on_frame (f
)
5722 #if 0 /* This proves to be unpleasant. */
5726 /* I don't think that the ICCCM allows programs to do things like this
5727 without the interaction of the window manager. Whatever you end up
5728 doing with this code, do it to x_unfocus_frame too. */
5729 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5730 RevertToPointerRoot
, CurrentTime
);
5740 /* Raise frame F. */
5746 if (f
->async_visible
)
5749 SelectWindow (FRAME_MAC_WINDOW (f
));
5754 /* Lower frame F. */
5760 if (f
->async_visible
)
5763 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5769 XTframe_raise_lower (f
, raise_flag
)
5779 /* Change of visibility. */
5782 mac_handle_visibility_change (f
)
5785 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5786 int visible
= 0, iconified
= 0;
5787 struct input_event buf
;
5789 if (IsWindowVisible (wp
))
5790 if (IsWindowCollapsed (wp
))
5795 if (!f
->async_visible
&& visible
)
5799 /* wait_reading_process_output will notice this and update
5800 the frame's display structures. If we were made
5801 invisible, we should not set garbaged, because that stops
5802 redrawing on Update events. */
5803 SET_FRAME_GARBAGED (f
);
5806 buf
.kind
= DEICONIFY_EVENT
;
5807 XSETFRAME (buf
.frame_or_window
, f
);
5808 kbd_buffer_store_event (&buf
);
5810 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5811 /* Force a redisplay sooner or later to update the
5812 frame titles in case this is the second frame. */
5813 record_asynch_buffer_change ();
5815 else if (f
->async_visible
&& !visible
)
5819 buf
.kind
= ICONIFY_EVENT
;
5820 XSETFRAME (buf
.frame_or_window
, f
);
5821 kbd_buffer_store_event (&buf
);
5824 f
->async_visible
= visible
;
5825 f
->async_iconified
= iconified
;
5828 /* This tries to wait until the frame is really visible.
5829 However, if the window manager asks the user where to position
5830 the frame, this will return before the user finishes doing that.
5831 The frame will not actually be visible at that time,
5832 but it will become visible later when the window manager
5833 finishes with it. */
5836 x_make_frame_visible (f
)
5840 int original_top
, original_left
;
5844 if (! FRAME_VISIBLE_P (f
))
5846 /* We test FRAME_GARBAGED_P here to make sure we don't
5847 call x_set_offset a second time
5848 if we get to x_make_frame_visible a second time
5849 before the window gets really visible. */
5850 if (! FRAME_ICONIFIED_P (f
)
5851 && ! f
->output_data
.mac
->asked_for_visible
)
5852 #if TARGET_API_MAC_CARBON
5853 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5855 struct frame
*sf
= SELECTED_FRAME ();
5856 if (!FRAME_MAC_P (sf
))
5857 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5858 kWindowCenterOnMainScreen
);
5860 RepositionWindow (FRAME_MAC_WINDOW (f
),
5861 FRAME_MAC_WINDOW (sf
),
5862 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5863 kWindowCascadeStartAtParentWindowScreen
5865 kWindowCascadeOnParentWindowScreen
5868 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5872 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5874 f
->output_data
.mac
->asked_for_visible
= 1;
5876 SelectWindow (FRAME_MAC_WINDOW (f
));
5877 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
5878 ShowWindow (FRAME_MAC_WINDOW (f
));
5881 XFlush (FRAME_MAC_DISPLAY (f
));
5883 /* Synchronize to ensure Emacs knows the frame is visible
5884 before we do anything else. We do this loop with input not blocked
5885 so that incoming events are handled. */
5890 /* This must come after we set COUNT. */
5893 XSETFRAME (frame
, f
);
5895 /* Wait until the frame is visible. Process X events until a
5896 MapNotify event has been seen, or until we think we won't get a
5897 MapNotify at all.. */
5898 for (count
= input_signal_count
+ 10;
5899 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5901 /* Force processing of queued events. */
5904 /* Machines that do polling rather than SIGIO have been
5905 observed to go into a busy-wait here. So we'll fake an
5906 alarm signal to let the handler know that there's something
5907 to be read. We used to raise a real alarm, but it seems
5908 that the handler isn't always enabled here. This is
5910 if (input_polling_used ())
5912 /* It could be confusing if a real alarm arrives while
5913 processing the fake one. Turn it off and let the
5914 handler reset it. */
5915 extern void poll_for_input_1
P_ ((void));
5916 int old_poll_suppress_count
= poll_suppress_count
;
5917 poll_suppress_count
= 1;
5918 poll_for_input_1 ();
5919 poll_suppress_count
= old_poll_suppress_count
;
5922 /* See if a MapNotify event has been processed. */
5923 FRAME_SAMPLE_VISIBILITY (f
);
5928 /* Change from mapped state to withdrawn state. */
5930 /* Make the frame visible (mapped and not iconified). */
5933 x_make_frame_invisible (f
)
5936 /* A deactivate event does not occur when the last visible frame is
5937 made invisible. So if we clear the highlight here, it will not
5938 be rehighlighted when it is made visible. */
5940 /* Don't keep the highlight on an invisible frame. */
5941 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5942 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5947 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5948 that the current position of the window is user-specified, rather than
5949 program-specified, so that when the window is mapped again, it will be
5950 placed at the same location, without forcing the user to position it
5951 by hand again (they have already done that once for this window.) */
5952 x_wm_set_size_hint (f
, (long) 0, 1);
5954 HideWindow (FRAME_MAC_WINDOW (f
));
5958 #if !USE_CARBON_EVENTS
5959 mac_handle_visibility_change (f
);
5963 /* Change window state from mapped to iconified. */
5971 /* A deactivate event does not occur when the last visible frame is
5972 iconified. So if we clear the highlight here, it will not be
5973 rehighlighted when it is deiconified. */
5975 /* Don't keep the highlight on an invisible frame. */
5976 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5977 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5980 if (f
->async_iconified
)
5985 FRAME_SAMPLE_VISIBILITY (f
);
5987 if (! FRAME_VISIBLE_P (f
))
5988 ShowWindow (FRAME_MAC_WINDOW (f
));
5990 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5995 error ("Can't notify window manager of iconification");
5997 #if !USE_CARBON_EVENTS
5998 mac_handle_visibility_change (f
);
6003 /* Free X resources of frame F. */
6006 x_free_frame_resources (f
)
6009 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6010 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6014 if (wp
!= tip_window
)
6015 remove_window_handler (wp
);
6018 if (wp
== tip_window
)
6019 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6020 closed' event. So we reset tip_window here. */
6023 free_frame_menubar (f
);
6025 if (FRAME_FACE_CACHE (f
))
6026 free_frame_faces (f
);
6030 if (FRAME_SIZE_HINTS (f
))
6031 xfree (FRAME_SIZE_HINTS (f
));
6033 xfree (f
->output_data
.mac
);
6034 f
->output_data
.mac
= NULL
;
6036 if (f
== dpyinfo
->x_focus_frame
)
6037 dpyinfo
->x_focus_frame
= 0;
6038 if (f
== dpyinfo
->x_focus_event_frame
)
6039 dpyinfo
->x_focus_event_frame
= 0;
6040 if (f
== dpyinfo
->x_highlight_frame
)
6041 dpyinfo
->x_highlight_frame
= 0;
6043 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6045 dpyinfo
->mouse_face_beg_row
6046 = dpyinfo
->mouse_face_beg_col
= -1;
6047 dpyinfo
->mouse_face_end_row
6048 = dpyinfo
->mouse_face_end_col
= -1;
6049 dpyinfo
->mouse_face_window
= Qnil
;
6050 dpyinfo
->mouse_face_deferred_gc
= 0;
6051 dpyinfo
->mouse_face_mouse_frame
= 0;
6058 /* Destroy the X window of frame F. */
6061 x_destroy_window (f
)
6064 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6066 x_free_frame_resources (f
);
6068 dpyinfo
->reference_count
--;
6072 /* Setting window manager hints. */
6074 /* Set the normal size hints for the window manager, for frame F.
6075 FLAGS is the flags word to use--or 0 meaning preserve the flags
6076 that the window now has.
6077 If USER_POSITION is nonzero, we set the USPosition
6078 flag (this is useful when FLAGS is 0). */
6080 x_wm_set_size_hint (f
, flags
, user_position
)
6085 int base_width
, base_height
, width_inc
, height_inc
;
6086 int min_rows
= 0, min_cols
= 0;
6087 XSizeHints
*size_hints
;
6089 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6090 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6091 width_inc
= FRAME_COLUMN_WIDTH (f
);
6092 height_inc
= FRAME_LINE_HEIGHT (f
);
6094 check_frame_size (f
, &min_rows
, &min_cols
);
6096 size_hints
= FRAME_SIZE_HINTS (f
);
6097 if (size_hints
== NULL
)
6099 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6100 bzero (size_hints
, sizeof (XSizeHints
));
6103 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6104 size_hints
->width_inc
= width_inc
;
6105 size_hints
->height_inc
= height_inc
;
6106 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6107 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6108 size_hints
->base_width
= base_width
;
6109 size_hints
->base_height
= base_height
;
6112 size_hints
->flags
= flags
;
6113 else if (user_position
)
6115 size_hints
->flags
&= ~ PPosition
;
6116 size_hints
->flags
|= USPosition
;
6120 #if 0 /* MAC_TODO: hide application instead of iconify? */
6121 /* Used for IconicState or NormalState */
6124 x_wm_set_window_state (f
, state
)
6128 #ifdef USE_X_TOOLKIT
6131 XtSetArg (al
[0], XtNinitialState
, state
);
6132 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6133 #else /* not USE_X_TOOLKIT */
6134 Window window
= FRAME_X_WINDOW (f
);
6136 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6137 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6139 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6140 #endif /* not USE_X_TOOLKIT */
6144 x_wm_set_icon_pixmap (f
, pixmap_id
)
6150 #ifndef USE_X_TOOLKIT
6151 Window window
= FRAME_X_WINDOW (f
);
6156 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6157 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6161 /* It seems there is no way to turn off use of an icon pixmap.
6162 The following line does it, only if no icon has yet been created,
6163 for some window managers. But with mwm it crashes.
6164 Some people say it should clear the IconPixmapHint bit in this case,
6165 but that doesn't work, and the X consortium said it isn't the
6166 right thing at all. Since there is no way to win,
6167 best to explicitly give up. */
6169 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6175 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6179 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6180 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6183 #else /* not USE_X_TOOLKIT */
6185 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6186 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6188 #endif /* not USE_X_TOOLKIT */
6191 #endif /* MAC_TODO */
6194 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6198 #if 0 /* MAC_TODO: no icons on Mac */
6199 #ifdef USE_X_TOOLKIT
6200 Window window
= XtWindow (f
->output_data
.x
->widget
);
6202 Window window
= FRAME_X_WINDOW (f
);
6205 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6206 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6207 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6209 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6210 #endif /* MAC_TODO */
6214 /***********************************************************************
6216 ***********************************************************************/
6218 /* An XLFD pattern is divided into blocks delimited by '*'. This
6219 structure holds information for each block. */
6220 struct xlfdpat_block
6222 /* Length of the pattern string in this block. Non-zero except for
6223 the first and the last blocks. */
6226 /* Pattern string except the last character in this block. The last
6227 character is replaced with NUL in order to use it as a
6229 unsigned char *pattern
;
6231 /* Last character of the pattern string. Must not be '?'. */
6232 unsigned char last_char
;
6234 /* One of the tables for the Boyer-Moore string search. It
6235 specifies the number of positions to proceed for each character
6236 with which the match fails. */
6239 /* The skip value for the last character in the above `skip' is
6240 assigned to `infinity' in order to simplify a loop condition.
6241 The original value is saved here. */
6247 /* Normalized pattern string. "Normalized" means that capital
6248 letters are lowered, blocks are not empty except the first and
6249 the last ones, and trailing '?'s in a block that is not the last
6250 one are moved to the next one. The last character in each block
6251 is replaced with NUL. */
6254 /* Number of characters except '*'s and trailing '?'s in the
6255 normalized pattern string. */
6258 /* Number of trailing '?'s in the normalized pattern string. */
6259 int trailing_anychars
;
6261 /* Number of blocks and information for each block. The latter is
6262 NULL if the pattern is exact (no '*' or '?' in it). */
6264 struct xlfdpat_block
*blocks
;
6268 xlfdpat_destroy (pat
)
6269 struct xlfdpat
*pat
;
6276 xfree (pat
->blocks
);
6283 static struct xlfdpat
*
6284 xlfdpat_create (pattern
)
6287 struct xlfdpat
*pat
;
6288 int nblocks
, i
, skip
;
6289 unsigned char last_char
, *p
, *q
, *anychar_head
;
6290 struct xlfdpat_block
*blk
;
6292 pat
= xmalloc (sizeof (struct xlfdpat
));
6296 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6297 if (pat
->buf
== NULL
)
6300 /* Normalize the pattern string and store it to `pat->buf'. */
6302 anychar_head
= NULL
;
6305 for (p
= pattern
; *p
; p
++)
6307 unsigned char c
= *p
;
6310 if (last_char
== '*')
6311 /* ...a** -> ...a* */
6315 if (last_char
== '?')
6316 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6317 /* ...*??* -> ...*?? */
6320 /* ...a??* -> ...a*?? */
6322 *anychar_head
++ = '*';
6329 if (last_char
!= '?')
6333 /* On Mac OS X 10.3, tolower also converts non-ASCII
6334 characters for some locales. */
6338 *q
++ = last_char
= c
;
6342 pat
->nblocks
= nblocks
;
6343 if (last_char
!= '?')
6344 pat
->trailing_anychars
= 0;
6347 pat
->trailing_anychars
= q
- anychar_head
;
6350 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6352 if (anychar_head
== NULL
&& nblocks
== 1)
6354 /* The pattern is exact. */
6359 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6360 if (pat
->blocks
== NULL
)
6363 /* Divide the normalized pattern into blocks. */
6365 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6370 blk
->len
= p
- blk
->pattern
;
6374 blk
->len
= q
- blk
->pattern
;
6376 /* Setup a table for the Boyer-Moore string search. */
6377 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6380 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6381 blk
->pattern
[blk
->len
- 1] = '\0';
6383 for (skip
= 1; skip
< blk
->len
; skip
++)
6384 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6387 for (i
= 0; i
< 256; i
++)
6388 blk
->skip
[i
] = skip
;
6390 p
= blk
->pattern
+ (blk
->len
- skip
);
6392 blk
->skip
[*p
++] = skip
;
6394 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6400 xlfdpat_destroy (pat
);
6405 xlfdpat_exact_p (pat
)
6406 struct xlfdpat
*pat
;
6408 return pat
->blocks
== NULL
;
6411 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6412 that the pattern in *BLK matches with its prefix. Return NULL
6413 there is no such strings. STRING must be lowered in advance. */
6416 xlfdpat_block_match_1 (blk
, string
, start_max
)
6417 struct xlfdpat_block
*blk
;
6418 unsigned char *string
;
6421 int start
, infinity
;
6422 unsigned char *p
, *s
;
6424 xassert (blk
->len
> 0);
6425 xassert (start_max
+ blk
->len
<= strlen (string
));
6426 xassert (blk
->last_char
!= '?');
6428 /* See the comments in the function `boyer_moore' (search.c) for the
6429 use of `infinity'. */
6430 infinity
= start_max
+ blk
->len
+ 1;
6431 blk
->skip
[blk
->last_char
] = infinity
;
6436 /* Check the last character of the pattern. */
6437 s
= string
+ blk
->len
- 1;
6440 start
+= blk
->skip
[*(s
+ start
)];
6442 while (start
<= start_max
);
6444 if (start
< infinity
)
6445 /* Couldn't find the last character. */
6448 /* No less than `infinity' means we could find the last
6449 character at `s[start - infinity]'. */
6452 /* Check the remaining characters. We prefer making no-'?'
6453 cases faster because the use of '?' is really rare. */
6458 while (*p
++ == *s
++)
6461 while (*(p
- 1) == '?');
6463 if (*(p
- 1) == '\0')
6465 return string
+ start
;
6468 start
+= blk
->last_char_skip
;
6470 while (start
<= start_max
);
6475 #define xlfdpat_block_match(b, s, m) \
6476 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6477 : xlfdpat_block_match_1 (b, s, m))
6479 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6480 matches with STRING. STRING must be lowered in advance. */
6483 xlfdpat_match (pat
, string
)
6484 struct xlfdpat
*pat
;
6485 unsigned char *string
;
6487 int str_len
, nblocks
, i
, start_max
;
6488 struct xlfdpat_block
*blk
;
6491 xassert (pat
->nblocks
> 0);
6493 if (xlfdpat_exact_p (pat
))
6494 return strcmp (pat
->buf
, string
) == 0;
6496 /* The number of the characters in the string must not be smaller
6497 than that in the pattern. */
6498 str_len
= strlen (string
);
6499 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6502 /* Chop off the trailing '?'s. */
6503 str_len
-= pat
->trailing_anychars
;
6505 /* The last block. When it is non-empty, it must match at the end
6507 nblocks
= pat
->nblocks
;
6508 blk
= pat
->blocks
+ (nblocks
- 1);
6510 /* The last block is also the first one. */
6511 return (str_len
== blk
->len
6512 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6513 else if (blk
->len
!= 0)
6514 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6517 /* The first block. When it is non-empty, it must match at the
6518 beginning of the string. */
6522 s
= xlfdpat_block_match (blk
, string
, 0);
6525 string
= s
+ blk
->len
;
6528 /* The rest of the blocks. */
6529 start_max
= str_len
- pat
->nchars
;
6530 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6532 s
= xlfdpat_block_match (blk
, string
, start_max
);
6535 start_max
-= s
- string
;
6536 string
= s
+ blk
->len
;
6543 /***********************************************************************
6545 ***********************************************************************/
6547 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6550 x_get_font_info (f
, font_idx
)
6554 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6557 /* the global font name table */
6558 static char **font_name_table
= NULL
;
6559 static int font_name_table_size
= 0;
6560 static int font_name_count
= 0;
6562 /* Alist linking font family names to Font Manager font family
6563 references (which can also be used as QuickDraw font IDs). We use
6564 an alist because hash tables are not ready when the terminal frame
6565 for Mac OS Classic is created. */
6566 static Lisp_Object fm_font_family_alist
;
6568 /* Hash table linking font family names to ATSU font IDs. */
6569 static Lisp_Object atsu_font_id_hash
;
6572 /* Alist linking character set strings to Mac text encoding and Emacs
6574 static Lisp_Object Vmac_charset_info_alist
;
6577 create_text_encoding_info_alist ()
6579 Lisp_Object result
= Qnil
, rest
;
6581 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6583 Lisp_Object charset_info
= XCAR (rest
);
6584 Lisp_Object charset
, coding_system
, text_encoding
;
6585 Lisp_Object existing_info
;
6587 if (!(CONSP (charset_info
)
6588 && STRINGP (charset
= XCAR (charset_info
))
6589 && CONSP (XCDR (charset_info
))
6590 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6591 && CONSP (XCDR (XCDR (charset_info
)))
6592 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6595 existing_info
= assq_no_quit (text_encoding
, result
);
6596 if (NILP (existing_info
))
6597 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6600 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6601 XSETCDR (XCDR (existing_info
),
6602 Fcons (charset
, XCDR (XCDR (existing_info
))));
6610 decode_mac_font_name (name
, size
, coding_system
)
6613 Lisp_Object coding_system
;
6615 struct coding_system coding
;
6618 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6620 for (p
= name
; *p
; p
++)
6621 if (!isascii (*p
) || iscntrl (*p
))
6626 setup_coding_system (coding_system
, &coding
);
6627 coding
.src_multibyte
= 0;
6628 coding
.dst_multibyte
= 1;
6629 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6630 coding
.composing
= COMPOSITION_DISABLED
;
6631 buf
= (char *) alloca (size
);
6633 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6634 bcopy (buf
, name
, coding
.produced
);
6635 name
[coding
.produced
] = '\0';
6639 /* If there's just one occurrence of '-' in the family name, it is
6640 replaced with '_'. (More than one occurrence of '-' means a
6641 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6642 p
= strchr (name
, '-');
6643 if (p
&& strchr (p
+ 1, '-') == NULL
)
6646 for (p
= name
; *p
; p
++)
6647 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6648 for some locales. */
6655 mac_to_x_fontname (name
, size
, style
, charset
)
6663 char xf
[256], *result
;
6666 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6670 strcpy(foundry
, "Apple");
6671 strcpy(family
, name
);
6674 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6675 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6676 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6678 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6679 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6680 for (p
= result
; *p
; p
++)
6681 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6682 for some locales. */
6689 /* Parse fully-specified and instantiated X11 font spec XF, and store
6690 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6691 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6692 caller must allocate at least 256 and 32 bytes respectively. For
6693 ordinary Mac fonts, the value stored to FAMILY should just be their
6694 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6695 intlfonts collection contain their charset designation in their
6696 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6697 types of font names are handled accordingly. */
6699 const int kDefaultFontSize
= 12;
6702 parse_x_font_name (xf
, family
, size
, style
, charset
)
6708 Str31 foundry
, weight
;
6709 int point_size
, avgwidth
;
6712 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6713 foundry
, family
, weight
, slant
, size
,
6714 &point_size
, &avgwidth
, charset
) != 8
6715 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6716 foundry
, family
, weight
, slant
, size
,
6717 &point_size
, &avgwidth
, charset
) != 8)
6723 *size
= point_size
/ 10;
6724 else if (avgwidth
> 0)
6725 *size
= avgwidth
/ 10;
6728 *size
= kDefaultFontSize
;
6731 if (strcmp (weight
, "bold") == 0)
6736 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
6738 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
6740 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
6742 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6743 but take overlap into account. */
6744 memmove (family
+ foundry_len
+ 1, family
, family_len
);
6745 memcpy (family
, foundry
, foundry_len
);
6746 family
[foundry_len
] = '-';
6747 family
[foundry_len
+ 1 + family_len
] = '-';
6748 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
6754 for (p
= family
; *p
; p
++)
6755 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6756 for some locales. */
6765 add_font_name_table_entry (char *font_name
)
6767 if (font_name_table_size
== 0)
6769 font_name_table_size
= 256;
6770 font_name_table
= (char **)
6771 xmalloc (font_name_table_size
* sizeof (char *));
6773 else if (font_name_count
+ 1 >= font_name_table_size
)
6775 font_name_table_size
*= 2;
6776 font_name_table
= (char **)
6777 xrealloc (font_name_table
,
6778 font_name_table_size
* sizeof (char *));
6781 font_name_table
[font_name_count
++] = font_name
;
6784 /* Sets up the table font_name_table to contain the list of all fonts
6785 in the system the first time the table is used so that the Resource
6786 Manager need not be accessed every time this information is
6790 init_font_name_table ()
6792 #if TARGET_API_MAC_CARBON
6793 FMFontFamilyIterator ffi
;
6794 FMFontFamilyInstanceIterator ffii
;
6796 Lisp_Object text_encoding_info_alist
;
6797 struct gcpro gcpro1
;
6799 text_encoding_info_alist
= create_text_encoding_info_alist ();
6802 #if USE_CG_TEXT_DRAWING
6803 init_cg_text_anti_aliasing_threshold ();
6805 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6806 text_encoding_info_alist
)))
6809 ItemCount nfonts
, i
;
6810 ATSUFontID
*font_ids
= NULL
;
6811 Ptr name
, prev_name
= NULL
;
6815 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6816 make_float (DEFAULT_REHASH_SIZE
),
6817 make_float (DEFAULT_REHASH_THRESHOLD
),
6819 err
= ATSUFontCount (&nfonts
);
6821 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6823 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6825 for (i
= 0; i
< nfonts
; i
++)
6827 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6828 kFontMacintoshPlatform
, kFontNoScript
,
6829 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
6832 name
= xmalloc (name_len
+ 1);
6835 name
[name_len
] = '\0';
6836 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6837 kFontMacintoshPlatform
, kFontNoScript
,
6838 kFontNoLanguage
, name_len
, name
,
6841 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
6844 && (prev_name
== NULL
6845 || strcmp (name
, prev_name
) != 0))
6847 static char *cs
= "iso10646-1";
6849 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6851 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6853 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6855 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6856 italic
| bold
, cs
));
6857 Fputhash (make_unibyte_string (name
, name_len
),
6858 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
6872 /* Create a dummy instance iterator here to avoid creating and
6873 destroying it in the loop. */
6874 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6876 /* Create an iterator to enumerate the font families. */
6877 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6880 FMDisposeFontFamilyInstanceIterator (&ffii
);
6884 GCPRO1 (text_encoding_info_alist
);
6886 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6892 TextEncoding encoding
;
6893 TextEncodingBase sc
;
6894 Lisp_Object text_encoding_info
;
6896 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6902 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6904 sc
= GetTextEncodingBase (encoding
);
6905 text_encoding_info
= assq_no_quit (make_number (sc
),
6906 text_encoding_info_alist
);
6907 if (NILP (text_encoding_info
))
6908 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6909 text_encoding_info_alist
);
6910 decode_mac_font_name (name
, sizeof (name
),
6911 XCAR (XCDR (text_encoding_info
)));
6912 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
6914 fm_font_family_alist
);
6916 /* Point the instance iterator at the current font family. */
6917 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6920 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6923 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6925 if (size
> 0 || style
== normal
)
6926 for (; !NILP (rest
); rest
= XCDR (rest
))
6928 char *cs
= SDATA (XCAR (rest
));
6932 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6934 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6936 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6938 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6944 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6953 /* Dispose of the iterators. */
6954 FMDisposeFontFamilyIterator (&ffi
);
6955 FMDisposeFontFamilyInstanceIterator (&ffii
);
6956 #else /* !TARGET_API_MAC_CARBON */
6958 SInt16 fontnum
, old_fontnum
;
6959 int num_mac_fonts
= CountResources('FOND');
6961 Handle font_handle
, font_handle_2
;
6962 short id
, scriptcode
;
6965 struct FontAssoc
*fat
;
6966 struct AsscEntry
*assc_entry
;
6967 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
6968 struct gcpro gcpro1
;
6970 GetPort (&port
); /* save the current font number used */
6971 old_fontnum
= port
->txFont
;
6973 text_encoding_info_alist
= create_text_encoding_info_alist ();
6975 GCPRO1 (text_encoding_info_alist
);
6977 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6979 font_handle
= GetIndResource ('FOND', i
);
6983 GetResInfo (font_handle
, &id
, &type
, name
);
6984 GetFNum (name
, &fontnum
);
6990 scriptcode
= FontToScript (fontnum
);
6991 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
6992 text_encoding_info_alist
);
6993 if (NILP (text_encoding_info
))
6994 text_encoding_info
= assq_no_quit (make_number (smRoman
),
6995 text_encoding_info_alist
);
6996 decode_mac_font_name (name
, sizeof (name
),
6997 XCAR (XCDR (text_encoding_info
)));
6998 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
6999 make_number (fontnum
)),
7000 fm_font_family_alist
);
7003 HLock (font_handle
);
7005 if (GetResourceSizeOnDisk (font_handle
)
7006 >= sizeof (struct FamRec
))
7008 fat
= (struct FontAssoc
*) (*font_handle
7009 + sizeof (struct FamRec
));
7011 = (struct AsscEntry
*) (*font_handle
7012 + sizeof (struct FamRec
)
7013 + sizeof (struct FontAssoc
));
7015 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7017 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7019 for (; !NILP (rest
); rest
= XCDR (rest
))
7021 char *cs
= SDATA (XCAR (rest
));
7023 add_font_name_table_entry (mac_to_x_fontname (name
,
7024 assc_entry
->fontSize
,
7025 assc_entry
->fontStyle
,
7031 HUnlock (font_handle
);
7032 font_handle_2
= GetNextFOND (font_handle
);
7033 ReleaseResource (font_handle
);
7034 font_handle
= font_handle_2
;
7036 while (ResError () == noErr
&& font_handle
);
7041 TextFont (old_fontnum
);
7042 #endif /* !TARGET_API_MAC_CARBON */
7047 mac_clear_font_name_table ()
7051 for (i
= 0; i
< font_name_count
; i
++)
7052 xfree (font_name_table
[i
]);
7053 xfree (font_name_table
);
7054 font_name_table
= NULL
;
7055 font_name_table_size
= font_name_count
= 0;
7056 fm_font_family_alist
= Qnil
;
7060 enum xlfd_scalable_field_index
7062 XLFD_SCL_PIXEL_SIZE
,
7063 XLFD_SCL_POINT_SIZE
,
7068 static int xlfd_scalable_fields
[] =
7077 mac_do_list_fonts (pattern
, maxnames
)
7082 Lisp_Object font_list
= Qnil
;
7083 struct xlfdpat
*pat
;
7085 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7088 if (font_name_table
== NULL
) /* Initialize when first used. */
7089 init_font_name_table ();
7091 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7094 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7095 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7096 fonts are scaled according to the specified size. */
7099 field
= xlfd_scalable_fields
;
7107 if ('0' <= *ptr
&& *ptr
<= '9')
7109 *val
= *ptr
++ - '0';
7110 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7111 *val
= *val
* 10 + *ptr
++ - '0';
7118 ptr
= strchr (ptr
, '-');
7121 while (ptr
&& i
< 14);
7123 if (i
== 14 && ptr
== NULL
)
7125 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7126 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7127 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7128 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7130 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7131 scl_val
[XLFD_SCL_POINT_SIZE
] =
7132 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7133 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7135 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7136 scl_val
[XLFD_SCL_AVGWIDTH
] =
7137 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7138 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7142 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7144 pat
= xlfdpat_create (pattern
);
7148 exact
= xlfdpat_exact_p (pat
);
7150 for (i
= 0; i
< font_name_count
; i
++)
7152 if (xlfdpat_match (pat
, font_name_table
[i
]))
7154 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7155 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7158 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7159 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7161 int former_len
= ptr
- font_name_table
[i
];
7163 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7166 memcpy (scaled
, font_name_table
[i
], former_len
);
7167 sprintf (scaled
+ former_len
,
7168 "-%d-%d-72-72-m-%d-%s",
7169 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7170 scl_val
[XLFD_SCL_POINT_SIZE
],
7171 scl_val
[XLFD_SCL_AVGWIDTH
],
7172 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7174 if (xlfdpat_match (pat
, scaled
))
7176 font_list
= Fcons (build_string (scaled
), font_list
);
7178 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7186 xlfdpat_destroy (pat
);
7191 /* Return a list of names of available fonts matching PATTERN on frame F.
7193 Frame F null means we have not yet created any frame on Mac, and
7194 consult the first display in x_display_list. MAXNAMES sets a limit
7195 on how many fonts to match. */
7198 x_list_fonts (f
, pattern
, size
, maxnames
)
7200 Lisp_Object pattern
;
7203 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7204 struct mac_display_info
*dpyinfo
7205 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7207 xassert (size
<= 0);
7209 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7210 if (NILP (patterns
))
7211 patterns
= Fcons (pattern
, Qnil
);
7213 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7215 pattern
= XCAR (patterns
);
7217 if (!STRINGP (pattern
))
7220 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7221 key
= Fcons (pattern
, make_number (maxnames
));
7223 list
= Fassoc (key
, tem
);
7226 list
= Fcdr_safe (list
);
7227 /* We have a cashed list. Don't have to get the list again. */
7232 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7235 /* MAC_TODO: add code for matching outline fonts here */
7237 /* Now store the result in the cache. */
7238 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7239 Fcons (Fcons (key
, list
),
7240 XCAR (XCDR (dpyinfo
->name_list_element
))));
7243 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7252 /* Check that FONT is valid on frame F. It is if it can be found in F's
7256 x_check_font (f
, font
)
7261 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7263 xassert (font
!= NULL
);
7265 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7266 if (dpyinfo
->font_table
[i
].name
7267 && font
== dpyinfo
->font_table
[i
].font
)
7270 xassert (i
< dpyinfo
->n_fonts
);
7273 #endif /* GLYPH_DEBUG != 0 */
7275 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7276 Note: There are (broken) X fonts out there with invalid XFontStruct
7277 min_bounds contents. For example, handa@etl.go.jp reports that
7278 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7279 have font->min_bounds.width == 0. */
7282 x_font_min_bounds (font
, w
, h
)
7283 MacFontStruct
*font
;
7286 *h
= FONT_HEIGHT (font
);
7287 *w
= font
->min_bounds
.width
;
7291 /* Compute the smallest character width and smallest font height over
7292 all fonts available on frame F. Set the members smallest_char_width
7293 and smallest_font_height in F's x_display_info structure to
7294 the values computed. Value is non-zero if smallest_font_height or
7295 smallest_char_width become smaller than they were before. */
7298 x_compute_min_glyph_bounds (f
)
7302 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7303 MacFontStruct
*font
;
7304 int old_width
= dpyinfo
->smallest_char_width
;
7305 int old_height
= dpyinfo
->smallest_font_height
;
7307 dpyinfo
->smallest_font_height
= 100000;
7308 dpyinfo
->smallest_char_width
= 100000;
7310 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7311 if (dpyinfo
->font_table
[i
].name
)
7313 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7316 font
= (MacFontStruct
*) fontp
->font
;
7317 xassert (font
!= (MacFontStruct
*) ~0);
7318 x_font_min_bounds (font
, &w
, &h
);
7320 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7321 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7324 xassert (dpyinfo
->smallest_char_width
> 0
7325 && dpyinfo
->smallest_font_height
> 0);
7327 return (dpyinfo
->n_fonts
== 1
7328 || dpyinfo
->smallest_char_width
< old_width
7329 || dpyinfo
->smallest_font_height
< old_height
);
7333 /* Determine whether given string is a fully-specified XLFD: all 14
7334 fields are present, none is '*'. */
7337 is_fully_specified_xlfd (char *p
)
7345 for (i
= 0; i
< 13; i
++)
7347 q
= strchr (p
+ 1, '-');
7350 if (q
- p
== 2 && *(p
+ 1) == '*')
7355 if (strchr (p
+ 1, '-') != NULL
)
7358 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7365 /* XLoadQueryFont creates and returns an internal representation for a
7366 font in a MacFontStruct struct. There is really no concept
7367 corresponding to "loading" a font on the Mac. But we check its
7368 existence and find the font number and all other information for it
7369 and store them in the returned MacFontStruct. */
7371 static MacFontStruct
*
7372 XLoadQueryFont (Display
*dpy
, char *fontname
)
7374 int i
, size
, char_width
;
7380 static ATSUFontID font_id
;
7381 ATSUStyle mac_style
= NULL
;
7384 #if TARGET_API_MAC_CARBON
7385 TextEncoding encoding
;
7390 MacFontStruct
*font
;
7392 if (is_fully_specified_xlfd (fontname
))
7396 Lisp_Object matched_fonts
;
7398 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7399 if (NILP (matched_fonts
))
7401 name
= SDATA (XCAR (matched_fonts
));
7404 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7408 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7411 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7412 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7413 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7414 sizeof (Boolean
), sizeof (Boolean
)};
7415 static Fixed size_fixed
;
7416 static Boolean bold_p
, italic_p
;
7417 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7418 &bold_p
, &italic_p
};
7419 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
};
7420 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
};
7421 Lisp_Object font_id_cons
;
7423 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7424 atsu_font_id_hash
, Qnil
);
7425 if (NILP (font_id_cons
))
7427 font_id
= cons_to_long (font_id_cons
);
7428 size_fixed
= Long2Fix (size
);
7429 bold_p
= (fontface
& bold
) != 0;
7430 italic_p
= (fontface
& italic
) != 0;
7431 err
= ATSUCreateStyle (&mac_style
);
7434 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7438 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7439 tags
, sizes
, values
);
7441 scriptcode
= kTextEncodingMacUnicode
;
7446 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7450 fontnum
= XINT (XCDR (tmp
));
7451 #if TARGET_API_MAC_CARBON
7452 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7454 scriptcode
= GetTextEncodingBase (encoding
);
7456 scriptcode
= FontToScript (fontnum
);
7460 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7462 font
->mac_fontnum
= fontnum
;
7463 font
->mac_fontsize
= size
;
7464 font
->mac_fontface
= fontface
;
7465 font
->mac_scriptcode
= scriptcode
;
7467 font
->mac_style
= mac_style
;
7468 #if USE_CG_TEXT_DRAWING
7469 font
->cg_font
= NULL
;
7470 font
->cg_glyphs
= NULL
;
7474 /* Apple Japanese (SJIS) font is listed as both
7475 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7476 (Roman script) in init_font_name_table (). The latter should be
7477 treated as a one-byte font. */
7478 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7479 font
->mac_scriptcode
= smRoman
;
7481 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7484 if (font
->mac_style
)
7487 ATSUTextLayout text_layout
;
7489 Rect char_bounds
, min_bounds
, max_bounds
;
7490 int min_width
, max_width
;
7491 ATSTrapezoid glyph_bounds
;
7493 font
->per_char
= xmalloc (sizeof (XCharStruct
) * 0x10000);
7494 if (font
->per_char
== NULL
)
7496 mac_unload_font (&one_mac_display_info
, font
);
7499 bzero (font
->per_char
, sizeof (XCharStruct
) * 0x10000);
7501 #if USE_CG_TEXT_DRAWING
7503 FMFontFamily font_family
;
7505 ATSFontRef ats_font
;
7507 err
= FMGetFontFamilyInstanceFromFont (font_id
, &font_family
, &style
);
7509 err
= FMGetFontFromFontFamilyInstance (font_family
, fontface
,
7511 /* Use CG text drawing if italic/bold is not synthesized. */
7512 if (err
== noErr
&& style
== fontface
)
7514 ats_font
= FMGetATSFontRefFromFont (font_id
);
7515 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7520 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7521 if (font
->cg_glyphs
)
7522 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7525 err
= atsu_get_text_layout_with_text_ptr (&c
, 1,
7530 mac_unload_font (&one_mac_display_info
, font
);
7534 for (c
= 0x20; c
<= 0xff; c
++)
7537 /* Soft hyphen is not supported in ATSUI. */
7541 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7542 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7547 err
= ATSUClearLayoutCache (text_layout
, kATSUFromTextBeginning
);
7549 err
= ATSUMeasureTextImage (text_layout
,
7550 kATSUFromTextBeginning
, kATSUToTextEnd
,
7551 0, 0, &char_bounds
);
7553 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
7554 kATSUFromTextBeginning
, kATSUToTextEnd
,
7555 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
7556 kATSUseFractionalOrigins
,
7558 kATSUseDeviceOrigins
,
7560 1, &glyph_bounds
, NULL
);
7563 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
7564 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
7566 char_width
= Fix2Long (glyph_bounds
.upperRight
.x
7567 - glyph_bounds
.upperLeft
.x
);
7568 STORE_XCHARSTRUCT (font
->per_char
[c
],
7569 char_width
, char_bounds
);
7572 min_width
= max_width
= char_width
;
7573 min_bounds
= max_bounds
= char_bounds
;
7574 font
->ascent
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
7575 font
->descent
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
7581 min_width
= min (min_width
, char_width
);
7582 max_width
= max (max_width
, char_width
);
7584 if (!EmptyRect (&char_bounds
))
7586 SetRect (&min_bounds
,
7587 max (min_bounds
.left
, char_bounds
.left
),
7588 max (min_bounds
.top
, char_bounds
.top
),
7589 min (min_bounds
.right
, char_bounds
.right
),
7590 min (min_bounds
.bottom
, char_bounds
.bottom
));
7591 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7595 #if USE_CG_TEXT_DRAWING
7596 if (err
== noErr
&& char_width
> 0 && font
->cg_font
)
7598 ATSUGlyphInfoArray glyph_info_array
;
7599 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
7601 err
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
7602 kATSUToTextEnd
, NULL
, NULL
, NULL
);
7604 err
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
7605 kATSUToTextEnd
, &count
,
7608 font
->cg_glyphs
[c
] = glyph_info_array
.glyphs
[0].glyphID
;
7611 /* Don't use CG text drawing if font substitution
7612 occurs in ASCII or Latin-1 characters. */
7613 CGFontRelease (font
->cg_font
);
7614 font
->cg_font
= NULL
;
7615 xfree (font
->cg_glyphs
);
7616 font
->cg_glyphs
= NULL
;
7622 font
->min_byte1
= 0;
7623 font
->max_byte1
= 0xff;
7624 font
->min_char_or_byte2
= 0;
7625 font
->max_char_or_byte2
= 0xff;
7631 SInt16 old_fontnum
, old_fontsize
;
7633 FontInfo the_fontinfo
;
7634 int is_two_byte_font
;
7636 /* Save the current font number used. */
7638 #if TARGET_API_MAC_CARBON
7639 old_fontnum
= GetPortTextFont (port
);
7640 old_fontsize
= GetPortTextSize (port
);
7641 old_fontface
= GetPortTextFace (port
);
7643 old_fontnum
= port
->txFont
;
7644 old_fontsize
= port
->txSize
;
7645 old_fontface
= port
->txFace
;
7650 TextFace (fontface
);
7652 GetFontInfo (&the_fontinfo
);
7654 font
->ascent
= the_fontinfo
.ascent
;
7655 font
->descent
= the_fontinfo
.descent
;
7657 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7658 || font
->mac_scriptcode
== smTradChinese
7659 || font
->mac_scriptcode
== smSimpChinese
7660 || font
->mac_scriptcode
== smKorean
);
7662 if (is_two_byte_font
)
7664 font
->min_byte1
= 0xa1;
7665 font
->max_byte1
= 0xfe;
7666 font
->min_char_or_byte2
= 0xa1;
7667 font
->max_char_or_byte2
= 0xfe;
7669 /* Use the width of an "ideographic space" of that font
7670 because the_fontinfo.widMax returns the wrong width for
7672 switch (font
->mac_scriptcode
)
7675 font
->min_byte1
= 0x81;
7676 font
->max_byte1
= 0xfc;
7677 font
->min_char_or_byte2
= 0x40;
7678 font
->max_char_or_byte2
= 0xfc;
7679 char_width
= StringWidth("\p\x81\x40");
7682 font
->min_char_or_byte2
= 0x40;
7683 char_width
= StringWidth("\p\xa1\x40");
7686 char_width
= StringWidth("\p\xa1\xa1");
7689 char_width
= StringWidth("\p\xa1\xa1");
7695 font
->min_byte1
= font
->max_byte1
= 0;
7696 font
->min_char_or_byte2
= 0x20;
7697 font
->max_char_or_byte2
= 0xff;
7699 /* Do this instead of use the_fontinfo.widMax, which
7700 incorrectly returns 15 for 12-point Monaco! */
7701 char_width
= CharWidth ('m');
7704 if (is_two_byte_font
)
7706 font
->per_char
= NULL
;
7708 if (fontface
& italic
)
7709 font
->max_bounds
.rbearing
= char_width
+ 1;
7711 font
->max_bounds
.rbearing
= char_width
;
7712 font
->max_bounds
.lbearing
= 0;
7713 font
->max_bounds
.width
= char_width
;
7714 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7715 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7717 font
->min_bounds
= font
->max_bounds
;
7721 int c
, min_width
, max_width
;
7722 Rect char_bounds
, min_bounds
, max_bounds
;
7725 font
->per_char
= xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7726 bzero (font
->per_char
, sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7728 min_width
= max_width
= char_width
;
7729 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
7730 SetRect (&max_bounds
, 0, 0, 0, 0);
7731 for (c
= 0x20; c
<= 0xff; c
++)
7735 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7736 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7741 char_width
= CharWidth (ch
);
7742 QDTextBounds (1, &ch
, &char_bounds
);
7743 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
7744 char_width
, char_bounds
);
7745 /* Some Japanese fonts (in SJIS encoding) return 0 as
7746 the character width of 0x7f. */
7749 min_width
= min (min_width
, char_width
);
7750 max_width
= max (max_width
, char_width
);
7752 if (!EmptyRect (&char_bounds
))
7754 SetRect (&min_bounds
,
7755 max (min_bounds
.left
, char_bounds
.left
),
7756 max (min_bounds
.top
, char_bounds
.top
),
7757 min (min_bounds
.right
, char_bounds
.right
),
7758 min (min_bounds
.bottom
, char_bounds
.bottom
));
7759 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7762 if (min_width
== max_width
7763 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
7765 /* Fixed width and no overhangs. */
7766 xfree (font
->per_char
);
7767 font
->per_char
= NULL
;
7771 /* Restore previous font number, size and face. */
7772 TextFont (old_fontnum
);
7773 TextSize (old_fontsize
);
7774 TextFace (old_fontface
);
7777 #if !defined (MAC_OS8) || USE_ATSUI
7778 /* AppKit and WebKit do some adjustment to the heights of Courier,
7779 Helvetica, and Times. This only works on the environments where
7780 the XDrawImageString counterpart is never used. */
7781 if (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
7782 || strcmp (family
, "times") == 0)
7783 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
7791 mac_unload_font (dpyinfo
, font
)
7792 struct mac_display_info
*dpyinfo
;
7795 xfree (font
->full_name
);
7797 xfree (font
->per_char
);
7799 if (font
->mac_style
)
7800 ATSUDisposeStyle (font
->mac_style
);
7801 #if USE_CG_TEXT_DRAWING
7803 CGFontRelease (font
->cg_font
);
7804 if (font
->cg_glyphs
)
7805 xfree (font
->cg_glyphs
);
7812 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7813 pointer to the structure font_info while allocating it dynamically.
7814 If SIZE is 0, load any size of font.
7815 If loading is failed, return NULL. */
7818 x_load_font (f
, fontname
, size
)
7820 register char *fontname
;
7823 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7824 Lisp_Object font_names
;
7826 /* Get a list of all the fonts that match this name. Once we
7827 have a list of matching fonts, we compare them against the fonts
7828 we already have by comparing names. */
7829 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7831 if (!NILP (font_names
))
7836 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7837 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7838 if (dpyinfo
->font_table
[i
].name
7839 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7840 SDATA (XCAR (tail
)))
7841 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7842 SDATA (XCAR (tail
)))))
7843 return (dpyinfo
->font_table
+ i
);
7848 /* Load the font and add it to the table. */
7851 struct MacFontStruct
*font
;
7852 struct font_info
*fontp
;
7853 unsigned long value
;
7856 fontname
= (char *) SDATA (XCAR (font_names
));
7859 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7864 /* Find a free slot in the font table. */
7865 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7866 if (dpyinfo
->font_table
[i
].name
== NULL
)
7869 /* If no free slot found, maybe enlarge the font table. */
7870 if (i
== dpyinfo
->n_fonts
7871 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7874 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7875 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7877 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7880 fontp
= dpyinfo
->font_table
+ i
;
7881 if (i
== dpyinfo
->n_fonts
)
7884 /* Now fill in the slots of *FONTP. */
7886 bzero (fontp
, sizeof (*fontp
));
7888 fontp
->font_idx
= i
;
7889 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7890 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7892 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7894 /* Fixed width font. */
7895 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7902 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7903 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7905 fontp
->space_width
= pcm
->width
;
7907 fontp
->space_width
= FONT_WIDTH (font
);
7911 int width
= pcm
->width
;
7912 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7913 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7914 width
+= pcm
->width
;
7915 fontp
->average_width
= width
/ 95;
7918 fontp
->average_width
= FONT_WIDTH (font
);
7921 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7922 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7924 fontp
->size
= font
->max_bounds
.width
;
7925 fontp
->height
= FONT_HEIGHT (font
);
7927 /* For some font, ascent and descent in max_bounds field is
7928 larger than the above value. */
7929 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7930 if (max_height
> fontp
->height
)
7931 fontp
->height
= max_height
;
7934 /* The slot `encoding' specifies how to map a character
7935 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7936 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7937 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7938 2:0xA020..0xFF7F). For the moment, we don't know which charset
7939 uses this font. So, we set information in fontp->encoding[1]
7940 which is never used by any charset. If mapping can't be
7941 decided, set FONT_ENCODING_NOT_DECIDED. */
7942 if (font
->mac_scriptcode
== smJapanese
)
7943 fontp
->encoding
[1] = 4;
7947 = (font
->max_byte1
== 0
7949 ? (font
->min_char_or_byte2
< 0x80
7950 ? (font
->max_char_or_byte2
< 0x80
7951 ? 0 /* 0x20..0x7F */
7952 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
7953 : 1) /* 0xA0..0xFF */
7955 : (font
->min_byte1
< 0x80
7956 ? (font
->max_byte1
< 0x80
7957 ? (font
->min_char_or_byte2
< 0x80
7958 ? (font
->max_char_or_byte2
< 0x80
7959 ? 0 /* 0x2020..0x7F7F */
7960 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
7961 : 3) /* 0x20A0..0x7FFF */
7962 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
7963 : (font
->min_char_or_byte2
< 0x80
7964 ? (font
->max_char_or_byte2
< 0x80
7965 ? 2 /* 0xA020..0xFF7F */
7966 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
7967 : 1))); /* 0xA0A0..0xFFFF */
7970 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7971 fontp
->baseline_offset
7972 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
7973 ? (long) value
: 0);
7974 fontp
->relative_compose
7975 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
7976 ? (long) value
: 0);
7977 fontp
->default_ascent
7978 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
7979 ? (long) value
: 0);
7981 fontp
->baseline_offset
= 0;
7982 fontp
->relative_compose
= 0;
7983 fontp
->default_ascent
= 0;
7986 /* Set global flag fonts_changed_p to non-zero if the font loaded
7987 has a character with a smaller width than any other character
7988 before, or if the font loaded has a smaller height than any
7989 other font loaded before. If this happens, it will make a
7990 glyph matrix reallocation necessary. */
7991 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
7998 /* Return a pointer to struct font_info of a font named FONTNAME for
7999 frame F. If no such font is loaded, return NULL. */
8002 x_query_font (f
, fontname
)
8004 register char *fontname
;
8006 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8009 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8010 if (dpyinfo
->font_table
[i
].name
8011 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8012 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8013 return (dpyinfo
->font_table
+ i
);
8018 /* Find a CCL program for a font specified by FONTP, and set the member
8019 `encoder' of the structure. */
8022 x_find_ccl_program (fontp
)
8023 struct font_info
*fontp
;
8025 Lisp_Object list
, elt
;
8027 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8031 && STRINGP (XCAR (elt
))
8032 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8038 struct ccl_program
*ccl
8039 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8041 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8044 fontp
->font_encoder
= ccl
;
8050 /* The Mac Event loop code */
8052 #if !TARGET_API_MAC_CARBON
8054 #include <Quickdraw.h>
8055 #include <Balloons.h>
8056 #include <Devices.h>
8058 #include <Gestalt.h>
8060 #include <Processes.h>
8062 #include <ToolUtils.h>
8063 #include <TextUtils.h>
8064 #include <Dialogs.h>
8067 #include <Resources.h>
8072 #endif /* ! TARGET_API_MAC_CARBON */
8077 #define WINDOW_RESOURCE 128
8078 #define TERM_WINDOW_RESOURCE 129
8080 #define DEFAULT_NUM_COLS 80
8082 #define MIN_DOC_SIZE 64
8083 #define MAX_DOC_SIZE 32767
8085 #define EXTRA_STACK_ALLOC (256 * 1024)
8087 #define ARGV_STRING_LIST_ID 129
8088 #define ABOUT_ALERT_ID 128
8089 #define RAM_TOO_LARGE_ALERT_ID 129
8091 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8092 Lisp_Object Qreverse
;
8095 /* Modifier associated with the control key, or nil to ignore. */
8096 Lisp_Object Vmac_control_modifier
;
8098 /* Modifier associated with the option key, or nil to ignore. */
8099 Lisp_Object Vmac_option_modifier
;
8101 /* Modifier associated with the command key, or nil to ignore. */
8102 Lisp_Object Vmac_command_modifier
;
8104 /* Modifier associated with the function key, or nil to ignore. */
8105 Lisp_Object Vmac_function_modifier
;
8107 /* True if the option and command modifiers should be used to emulate
8108 a three button mouse */
8109 Lisp_Object Vmac_emulate_three_button_mouse
;
8111 #if USE_CARBON_EVENTS
8112 /* True if the mouse wheel button (i.e. button 4) should map to
8113 mouse-2, instead of mouse-3. */
8114 Lisp_Object Vmac_wheel_button_is_mouse_2
;
8116 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
8117 for processing before Emacs sees it. */
8118 Lisp_Object Vmac_pass_command_to_system
;
8120 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
8121 for processing before Emacs sees it. */
8122 Lisp_Object Vmac_pass_control_to_system
;
8125 /* Points to the variable `inev' in the function XTread_socket. It is
8126 used for passing an input event to the function back from
8127 Carbon/Apple event handlers. */
8128 static struct input_event
*read_socket_inev
= NULL
;
8130 /* Set in term/mac-win.el to indicate that event loop can now generate
8131 drag and drop events. */
8132 Lisp_Object Qmac_ready_for_drag_n_drop
;
8134 Point saved_menu_event_location
;
8137 static void init_required_apple_events (void);
8139 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
8141 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
8142 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
8143 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
8145 #if TARGET_API_MAC_CARBON
8147 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
8148 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
8149 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
8150 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
8153 static Lisp_Object Qapplication
, Qabout
;
8154 #if USE_CARBON_EVENTS
8156 extern void init_service_handler ();
8157 static Lisp_Object Qpreferences
, Qservices
, Qpaste
, Qperform
;
8159 /* Window Event Handler */
8160 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8163 OSErr
install_window_handler (WindowPtr
);
8165 extern void init_emacs_passwd_dir ();
8166 extern int emacs_main (int, char **, char **);
8168 extern void initialize_applescript();
8169 extern void terminate_applescript();
8172 #if USE_CARBON_EVENTS
8173 mac_to_emacs_modifiers (UInt32 mods
)
8175 mac_to_emacs_modifiers (EventModifiers mods
)
8178 unsigned int result
= 0;
8179 if (mods
& shiftKey
)
8180 result
|= shift_modifier
;
8184 /* Deactivated to simplify configuration:
8185 if Vmac_option_modifier is non-NIL, we fully process the Option
8186 key. Otherwise, we only process it if an additional Ctrl or Command
8187 is pressed. That way the system may convert the character to a
8189 if ((mods & optionKey) &&
8190 (( !NILP(Vmac_option_modifier) ||
8191 ((mods & cmdKey) || (mods & controlKey))))) */
8193 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8194 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8196 result
|= XUINT(val
);
8198 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8199 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8201 result
|= XUINT(val
);
8203 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8204 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8206 result
|= XUINT(val
);
8210 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8211 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8213 result
|= XUINT(val
);
8221 mac_get_emulated_btn ( UInt32 modifiers
)
8224 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8225 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8226 if (modifiers
& cmdKey
)
8227 result
= cmdIs3
? 2 : 1;
8228 else if (modifiers
& optionKey
)
8229 result
= cmdIs3
? 1 : 2;
8234 #if USE_CARBON_EVENTS
8235 /* Obtains the event modifiers from the event ref and then calls
8236 mac_to_emacs_modifiers. */
8238 mac_event_to_emacs_modifiers (EventRef eventRef
)
8241 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8242 sizeof (UInt32
), NULL
, &mods
);
8243 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8244 GetEventClass(eventRef
) == kEventClassMouse
)
8246 mods
&= ~(optionKey
| cmdKey
);
8248 return mac_to_emacs_modifiers (mods
);
8251 /* Given an event ref, return the code to use for the mouse button
8252 code in the emacs input_event. */
8254 mac_get_mouse_btn (EventRef ref
)
8256 EventMouseButton result
= kEventMouseButtonPrimary
;
8257 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8258 sizeof (EventMouseButton
), NULL
, &result
);
8261 case kEventMouseButtonPrimary
:
8262 if (NILP (Vmac_emulate_three_button_mouse
))
8266 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8267 sizeof (UInt32
), NULL
, &mods
);
8268 return mac_get_emulated_btn(mods
);
8270 case kEventMouseButtonSecondary
:
8271 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
8272 case kEventMouseButtonTertiary
:
8273 case 4: /* 4 is the number for the mouse wheel button */
8274 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
8280 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8281 events. However the click of the mouse wheel is not converted to a
8282 mouseDown or mouseUp event. Likewise for dead key down events.
8283 This calls ConvertEventRef, but then checks to see if it is a mouse
8284 up/down, or a dead key down carbon event that has not been
8285 converted, and if so, converts it by hand (to be picked up in the
8286 XTread_socket loop). */
8287 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8289 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8294 switch (GetEventClass (eventRef
))
8296 case kEventClassMouse
:
8297 switch (GetEventKind (eventRef
))
8299 case kEventMouseDown
:
8300 eventRec
->what
= mouseDown
;
8305 eventRec
->what
= mouseUp
;
8314 case kEventClassKeyboard
:
8315 switch (GetEventKind (eventRef
))
8317 case kEventRawKeyDown
:
8319 unsigned char char_codes
;
8322 eventRec
->what
= keyDown
;
8323 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
8324 NULL
, sizeof (char), NULL
, &char_codes
);
8325 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
8326 NULL
, sizeof (UInt32
), NULL
, &key_code
);
8327 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8343 /* Need where and when. */
8346 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8347 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8348 /* Use two step process because new event modifiers are 32-bit
8349 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8350 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8351 NULL
, sizeof (UInt32
), NULL
, &mods
);
8352 eventRec
->modifiers
= mods
;
8354 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8365 Handle menubar_handle
;
8366 MenuHandle menu_handle
;
8368 menubar_handle
= GetNewMBar (128);
8369 if(menubar_handle
== NULL
)
8371 SetMenuBar (menubar_handle
);
8374 #if !TARGET_API_MAC_CARBON
8375 menu_handle
= GetMenuHandle (M_APPLE
);
8376 if(menu_handle
!= NULL
)
8377 AppendResMenu (menu_handle
,'DRVR');
8385 do_init_managers (void)
8387 #if !TARGET_API_MAC_CARBON
8388 InitGraf (&qd
.thePort
);
8390 FlushEvents (everyEvent
, 0);
8395 #endif /* !TARGET_API_MAC_CARBON */
8398 #if !TARGET_API_MAC_CARBON
8399 /* set up some extra stack space for use by emacs */
8400 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8402 /* MaxApplZone must be called for AppleScript to execute more
8403 complicated scripts */
8406 #endif /* !TARGET_API_MAC_CARBON */
8410 do_check_ram_size (void)
8412 SInt32 physical_ram_size
, logical_ram_size
;
8414 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8415 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8416 || physical_ram_size
> (1 << VALBITS
)
8417 || logical_ram_size
> (1 << VALBITS
))
8419 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8425 do_window_update (WindowPtr win
)
8427 struct frame
*f
= mac_window_to_frame (win
);
8431 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8433 if (win
!= tip_window
)
8435 if (f
->async_visible
== 0)
8437 /* Update events may occur when a frame gets iconified. */
8439 f
->async_visible
= 1;
8440 f
->async_iconified
= 0;
8441 SET_FRAME_GARBAGED (f
);
8447 #if TARGET_API_MAC_CARBON
8448 RgnHandle region
= NewRgn ();
8450 GetPortVisibleRegion (GetWindowPort (win
), region
);
8451 GetRegionBounds (region
, &r
);
8452 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8453 UpdateControls (win
, region
);
8454 DisposeRgn (region
);
8456 r
= (*win
->visRgn
)->rgnBBox
;
8457 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8458 UpdateControls (win
, win
->visRgn
);
8467 is_emacs_window (WindowPtr win
)
8469 Lisp_Object tail
, frame
;
8474 FOR_EACH_FRAME (tail
, frame
)
8475 if (FRAME_MAC_P (XFRAME (frame
)))
8476 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8485 /* Window-activate events will do the job. */
8491 /* Window-deactivate events will do the job. */
8496 do_apple_menu (SInt16 menu_item
)
8498 #if !TARGET_API_MAC_CARBON
8500 SInt16 da_driver_refnum
;
8502 if (menu_item
== I_ABOUT
)
8503 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8506 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8507 da_driver_refnum
= OpenDeskAcc (item_name
);
8509 #endif /* !TARGET_API_MAC_CARBON */
8513 do_menu_choice (SInt32 menu_choice
)
8515 SInt16 menu_id
, menu_item
;
8517 menu_id
= HiWord (menu_choice
);
8518 menu_item
= LoWord (menu_choice
);
8526 do_apple_menu (menu_item
);
8531 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8532 MenuHandle menu
= GetMenuHandle (menu_id
);
8537 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8538 menubar_selection_callback (f
, refcon
);
8547 /* Handle drags in size box. Based on code contributed by Ben
8548 Mesander and IM - Window Manager A. */
8551 do_grow_window (WindowPtr w
, EventRecord
*e
)
8554 int rows
, columns
, width
, height
;
8555 struct frame
*f
= mac_window_to_frame (w
);
8556 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8557 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8558 #if TARGET_API_MAC_CARBON
8564 if (size_hints
->flags
& PMinSize
)
8566 min_width
= size_hints
->min_width
;
8567 min_height
= size_hints
->min_height
;
8569 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8571 #if TARGET_API_MAC_CARBON
8572 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8574 height
= new_rect
.bottom
- new_rect
.top
;
8575 width
= new_rect
.right
- new_rect
.left
;
8577 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8578 /* see if it really changed size */
8581 height
= HiWord (grow_size
);
8582 width
= LoWord (grow_size
);
8585 if (width
!= FRAME_PIXEL_WIDTH (f
)
8586 || height
!= FRAME_PIXEL_HEIGHT (f
))
8588 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8589 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8591 x_set_window_size (f
, 0, columns
, rows
);
8596 /* Handle clicks in zoom box. Calculation of "standard state" based
8597 on code in IM - Window Manager A and code contributed by Ben
8598 Mesander. The standard state of an Emacs window is 80-characters
8599 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8602 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8605 Rect zoom_rect
, port_rect
;
8607 int w_title_height
, columns
, rows
, width
, height
;
8608 struct frame
*f
= mac_window_to_frame (w
);
8609 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8611 #if TARGET_API_MAC_CARBON
8613 Point standard_size
;
8615 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8616 standard_size
.v
= dpyinfo
->height
;
8618 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8619 zoom_in_or_out
= inZoomIn
;
8622 /* Adjust the standard size according to character boundaries. */
8624 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8625 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8626 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8627 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8628 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8629 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8630 && port_rect
.left
== zoom_rect
.left
8631 && port_rect
.top
== zoom_rect
.top
)
8632 zoom_in_or_out
= inZoomIn
;
8634 zoom_in_or_out
= inZoomOut
;
8637 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8639 #else /* not TARGET_API_MAC_CARBON */
8640 GetPort (&save_port
);
8642 SetPortWindowPort (w
);
8644 /* Clear window to avoid flicker. */
8645 EraseRect (&(w
->portRect
));
8646 if (zoom_in_or_out
== inZoomOut
)
8648 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8649 LocalToGlobal (&top_left
);
8651 /* calculate height of window's title bar */
8652 w_title_height
= top_left
.v
- 1
8653 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8655 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8656 zoom_rect
= qd
.screenBits
.bounds
;
8657 zoom_rect
.top
+= w_title_height
;
8658 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8660 zoom_rect
.right
= zoom_rect
.left
8661 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8663 /* Adjust the standard size according to character boundaries. */
8664 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8666 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8668 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8672 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8674 SetPort (save_port
);
8675 #endif /* not TARGET_API_MAC_CARBON */
8677 /* retrieve window size and update application values */
8678 #if TARGET_API_MAC_CARBON
8679 GetWindowPortBounds (w
, &port_rect
);
8681 port_rect
= w
->portRect
;
8683 height
= port_rect
.bottom
- port_rect
.top
;
8684 width
= port_rect
.right
- port_rect
.left
;
8686 if (width
!= FRAME_PIXEL_WIDTH (f
)
8687 || height
!= FRAME_PIXEL_HEIGHT (f
))
8689 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8690 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8692 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8693 SET_FRAME_GARBAGED (f
);
8694 cancel_mouse_face (f
);
8696 FRAME_PIXEL_WIDTH (f
) = width
;
8697 FRAME_PIXEL_HEIGHT (f
) = height
;
8699 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8702 /* Intialize AppleEvent dispatcher table for the required events. */
8704 init_required_apple_events ()
8709 /* Make sure we have apple events before starting. */
8710 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
8714 if (!(result
& (1 << gestaltAppleEventsPresent
)))
8717 #if TARGET_API_MAC_CARBON
8718 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8719 NewAEEventHandlerUPP
8720 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8723 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8724 NewAEEventHandlerProc
8725 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8731 #if TARGET_API_MAC_CARBON
8732 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8733 NewAEEventHandlerUPP
8734 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8737 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8738 NewAEEventHandlerProc
8739 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8745 #if TARGET_API_MAC_CARBON
8746 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8747 NewAEEventHandlerUPP
8748 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8751 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8752 NewAEEventHandlerProc
8753 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8759 #if TARGET_API_MAC_CARBON
8760 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8761 NewAEEventHandlerUPP
8762 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8765 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8766 NewAEEventHandlerProc
8767 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8775 mac_store_application_menu_event (event
)
8776 #if USE_CARBON_EVENTS
8782 struct input_event buf
;
8783 Lisp_Object frame
, entry
;
8787 XSETFRAME (frame
, mac_focus_frame (&one_mac_display_info
));
8788 buf
.kind
= MENU_BAR_EVENT
;
8789 buf
.frame_or_window
= frame
;
8791 kbd_buffer_store_event (&buf
);
8793 buf
.arg
= Qapplication
;
8794 kbd_buffer_store_event (&buf
);
8796 #if USE_CARBON_EVENTS
8797 switch (GetEventClass (event
))
8800 case kEventClassService
:
8801 buf
.arg
= Qservices
;
8802 kbd_buffer_store_event (&buf
);
8803 switch (GetEventKind (event
))
8805 case kEventServicePaste
:
8809 case kEventServicePerform
:
8812 CFStringRef message
;
8814 err
= GetEventParameter (event
, kEventParamServiceMessageName
,
8815 typeCFStringRef
, NULL
,
8816 sizeof (CFStringRef
), NULL
, &message
);
8818 kbd_buffer_store_event (&buf
);
8819 if (err
== noErr
&& message
)
8820 entry
= intern (SDATA (cfstring_to_lisp (message
)));
8830 #endif /* MAC_OSX */
8831 case kEventClassCommand
:
8835 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
,
8836 NULL
, sizeof (HICommand
), NULL
, &command
);
8837 switch (command
.commandID
)
8839 case kHICommandAbout
:
8843 case kHICommandPreferences
:
8844 entry
= Qpreferences
;
8846 #endif /* MAC_OSX */
8847 case kHICommandQuit
:
8859 #else /* USE_CARBON_EVENTS */
8862 case kHICommandAbout
:
8865 case kHICommandQuit
:
8874 kbd_buffer_store_event (&buf
);
8877 #if USE_CARBON_EVENTS
8878 static pascal OSStatus
8879 mac_handle_command_event (next_handler
, event
, data
)
8880 EventHandlerCallRef next_handler
;
8887 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8888 sizeof (HICommand
), NULL
, &command
);
8890 switch (command
.commandID
)
8892 case kHICommandAbout
:
8894 case kHICommandPreferences
:
8895 #endif /* MAC_OSX */
8896 result
= CallNextEventHandler (next_handler
, event
);
8897 if (result
!= eventNotHandledErr
)
8900 mac_store_application_menu_event (event
);
8907 return eventNotHandledErr
;
8911 init_command_handler ()
8914 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8915 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8917 if (handle_command_eventUPP
== NULL
)
8918 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8919 return InstallApplicationEventHandler (handle_command_eventUPP
,
8920 GetEventTypeCount (specs
), specs
,
8924 static pascal OSStatus
8925 mac_handle_window_event (next_handler
, event
, data
)
8926 EventHandlerCallRef next_handler
;
8933 XSizeHints
*size_hints
;
8935 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8936 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8938 switch (GetEventKind (event
))
8940 case kEventWindowUpdate
:
8941 result
= CallNextEventHandler (next_handler
, event
);
8942 if (result
!= eventNotHandledErr
)
8945 do_window_update (wp
);
8948 case kEventWindowBoundsChanging
:
8949 result
= CallNextEventHandler (next_handler
, event
);
8950 if (result
!= eventNotHandledErr
)
8953 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8954 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8955 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8956 if ((attributes
& kWindowBoundsChangeUserResize
)
8957 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8958 == (PResizeInc
| PBaseSize
| PMinSize
)))
8963 GetEventParameter (event
, kEventParamCurrentBounds
,
8965 NULL
, sizeof (Rect
), NULL
, &bounds
);
8966 width
= bounds
.right
- bounds
.left
;
8967 height
= bounds
.bottom
- bounds
.top
;
8969 if (width
< size_hints
->min_width
)
8970 width
= size_hints
->min_width
;
8972 width
= size_hints
->base_width
8973 + (int) ((width
- size_hints
->base_width
)
8974 / (float) size_hints
->width_inc
+ .5)
8975 * size_hints
->width_inc
;
8977 if (height
< size_hints
->min_height
)
8978 height
= size_hints
->min_height
;
8980 height
= size_hints
->base_height
8981 + (int) ((height
- size_hints
->base_height
)
8982 / (float) size_hints
->height_inc
+ .5)
8983 * size_hints
->height_inc
;
8985 bounds
.right
= bounds
.left
+ width
;
8986 bounds
.bottom
= bounds
.top
+ height
;
8987 SetEventParameter (event
, kEventParamCurrentBounds
,
8988 typeQDRectangle
, sizeof (Rect
), &bounds
);
8993 case kEventWindowShown
:
8994 case kEventWindowHidden
:
8995 case kEventWindowExpanded
:
8996 case kEventWindowCollapsed
:
8997 result
= CallNextEventHandler (next_handler
, event
);
8999 mac_handle_visibility_change (mac_window_to_frame (wp
));
9005 return eventNotHandledErr
;
9008 static pascal OSStatus
9009 mac_handle_mouse_event (next_handler
, event
, data
)
9010 EventHandlerCallRef next_handler
;
9016 switch (GetEventKind (event
))
9018 case kEventMouseWheelMoved
:
9022 EventMouseWheelAxis axis
;
9026 result
= CallNextEventHandler (next_handler
, event
);
9027 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9030 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9031 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9032 f
= mac_window_to_frame (wp
);
9033 if (f
!= mac_focus_frame (&one_mac_display_info
))
9036 GetEventParameter (event
, kEventParamMouseWheelAxis
,
9037 typeMouseWheelAxis
, NULL
,
9038 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9039 if (axis
!= kEventMouseWheelAxisY
)
9042 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
9043 NULL
, sizeof (SInt32
), NULL
, &delta
);
9044 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
9045 NULL
, sizeof (Point
), NULL
, &point
);
9046 read_socket_inev
->kind
= WHEEL_EVENT
;
9047 read_socket_inev
->code
= 0;
9048 read_socket_inev
->modifiers
=
9049 (mac_event_to_emacs_modifiers (event
)
9050 | ((delta
< 0) ? down_modifier
: up_modifier
));
9051 SetPortWindowPort (wp
);
9052 GlobalToLocal (&point
);
9053 XSETINT (read_socket_inev
->x
, point
.h
);
9054 XSETINT (read_socket_inev
->y
, point
.v
);
9055 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9065 return eventNotHandledErr
;
9067 #endif /* USE_CARBON_EVENTS */
9071 install_window_handler (window
)
9075 #if USE_CARBON_EVENTS
9076 EventTypeSpec specs_window
[] =
9077 {{kEventClassWindow
, kEventWindowUpdate
},
9078 {kEventClassWindow
, kEventWindowBoundsChanging
},
9079 {kEventClassWindow
, kEventWindowShown
},
9080 {kEventClassWindow
, kEventWindowHidden
},
9081 {kEventClassWindow
, kEventWindowExpanded
},
9082 {kEventClassWindow
, kEventWindowCollapsed
}};
9083 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9084 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9085 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9087 if (handle_window_eventUPP
== NULL
)
9088 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9089 if (handle_mouse_eventUPP
== NULL
)
9090 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9091 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9092 GetEventTypeCount (specs_window
),
9093 specs_window
, NULL
, NULL
);
9095 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9096 GetEventTypeCount (specs_mouse
),
9097 specs_mouse
, NULL
, NULL
);
9099 #if TARGET_API_MAC_CARBON
9100 if (mac_do_track_dragUPP
== NULL
)
9101 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
9102 if (mac_do_receive_dragUPP
== NULL
)
9103 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
9106 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
9108 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
9114 remove_window_handler (window
)
9117 #if TARGET_API_MAC_CARBON
9118 if (mac_do_track_dragUPP
)
9119 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
9120 if (mac_do_receive_dragUPP
)
9121 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
9125 /* Open Application Apple Event */
9127 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
9133 /* Called when we receive an AppleEvent with an ID of
9134 "kAEOpenDocuments". This routine gets the direct parameter,
9135 extracts the FSSpecs in it, and puts their names on a list. */
9136 #pragma options align=mac68k
9137 typedef struct SelectionRange
{
9138 short unused1
; // 0 (not used)
9139 short lineNum
; // line to select (<0 to specify range)
9140 long startRange
; // start of selection range (if line < 0)
9141 long endRange
; // end of selection range (if line < 0)
9142 long unused2
; // 0 (not used)
9143 long theDate
; // modification date/time
9145 #pragma options align=reset
9148 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
9153 DescType actual_type
;
9155 SelectionRange position
;
9156 Lisp_Object file_list
= Qnil
;
9158 xassert (read_socket_inev
);
9160 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
9162 goto descriptor_error_exit
;
9164 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
9166 file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
9167 make_number (position
.startRange
+ 1),
9168 make_number (position
.endRange
+ 1)),
9171 /* Check to see that we got all of the required parameters from the
9172 event descriptor. For an 'odoc' event this should just be the
9174 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
9175 &actual_type
, (Ptr
) &keyword
,
9176 sizeof (keyword
), &actual_size
);
9177 /* No error means that we found some unused parameters.
9178 errAEDescNotFound means that there are no more parameters. If we
9179 get an error code other than that, flag it. */
9180 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
9182 err
= errAEEventNotHandled
;
9187 /* Got all the parameters we need. Now, go through the direct
9188 object list and parse it up. */
9190 long num_files_to_open
;
9192 err
= AECountItems (&the_desc
, &num_files_to_open
);
9197 /* AE file list is one based so just use that for indexing here. */
9198 for (i
= 1; i
<= num_files_to_open
; i
++)
9200 char unix_path_name
[MAXPATHLEN
];
9204 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
9205 &actual_type
, &fref
, sizeof (FSRef
),
9207 if (err
!= noErr
|| actual_type
!= typeFSRef
)
9210 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
9215 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
9216 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
9217 if (err
!= noErr
) continue;
9219 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
9220 sizeof (unix_path_name
) - 1) == noErr
)
9222 /* x-dnd functions expect undecoded filenames. */
9223 file_list
= Fcons (make_unibyte_string (unix_path_name
,
9224 strlen (unix_path_name
)),
9229 /* Build a DRAG_N_DROP_EVENT type event as is done in
9230 constuct_drag_n_drop in w32term.c. */
9231 if (!NILP (file_list
))
9233 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
9237 read_socket_inev
->kind
= DRAG_N_DROP_EVENT
;
9238 read_socket_inev
->code
= 0;
9239 read_socket_inev
->modifiers
= 0;
9241 XSETINT (read_socket_inev
->x
, 0);
9242 XSETINT (read_socket_inev
->y
, 0);
9244 XSETFRAME (frame
, f
);
9245 read_socket_inev
->frame_or_window
= Fcons (frame
, file_list
);
9248 /* Regardless of whether Emacs was suspended or in the
9249 foreground, ask it to redraw its entire screen. Otherwise
9250 parts of the screen can be left in an inconsistent
9252 wp
= FRAME_MAC_WINDOW (f
);
9254 #if TARGET_API_MAC_CARBON
9258 GetWindowPortBounds (wp
, &r
);
9259 InvalWindowRect (wp
, &r
);
9261 #else /* not TARGET_API_MAC_CARBON */
9262 InvalRect (&(wp
->portRect
));
9263 #endif /* not TARGET_API_MAC_CARBON */
9269 /* Nuke the coerced file list in any case */
9270 err2
= AEDisposeDesc(&the_desc
);
9272 descriptor_error_exit
:
9273 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
9278 #if TARGET_API_MAC_CARBON
9280 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9281 void *handlerRefCon
, DragReference theDrag
)
9283 static int can_accept
;
9286 ItemReference theItem
;
9287 FlavorFlags theFlags
;
9290 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9291 return dragNotAcceptedErr
;
9295 case kDragTrackingEnterHandler
:
9296 CountDragItems (theDrag
, &items
);
9298 for (index
= 1; index
<= items
; index
++)
9300 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9301 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9302 if (result
== noErr
)
9310 case kDragTrackingEnterWindow
:
9313 RgnHandle hilite_rgn
= NewRgn ();
9315 struct frame
*f
= mac_window_to_frame (window
);
9317 GetWindowPortBounds (window
, &r
);
9318 OffsetRect (&r
, -r
.left
, -r
.top
);
9319 RectRgn (hilite_rgn
, &r
);
9320 ShowDragHilite (theDrag
, hilite_rgn
, true);
9321 DisposeRgn (hilite_rgn
);
9322 SetThemeCursor (kThemeCopyArrowCursor
);
9326 case kDragTrackingInWindow
:
9329 case kDragTrackingLeaveWindow
:
9332 struct frame
*f
= mac_window_to_frame (window
);
9334 HideDragHilite (theDrag
);
9335 SetThemeCursor (kThemeArrowCursor
);
9339 case kDragTrackingLeaveHandler
:
9347 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9348 DragReference theDrag
)
9352 FlavorFlags theFlags
;
9355 ItemReference theItem
;
9357 Size size
= sizeof (HFSFlavor
);
9358 Lisp_Object file_list
;
9360 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9361 return dragNotAcceptedErr
;
9364 GetDragMouse (theDrag
, &mouse
, 0L);
9365 CountDragItems (theDrag
, &items
);
9366 for (index
= 1; index
<= items
; index
++)
9368 /* Only handle file references. */
9369 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9370 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9371 if (result
== noErr
)
9376 char unix_path_name
[MAXPATHLEN
];
9378 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
9380 /* Use Carbon routines, otherwise it converts the file name
9381 to /Macintosh HD/..., which is not correct. */
9382 FSpMakeFSRef (&data
.fileSpec
, &fref
);
9383 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
9385 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
9386 sizeof (unix_path_name
) - 1) == noErr
)
9388 /* x-dnd functions expect undecoded filenames. */
9389 file_list
= Fcons (make_unibyte_string (unix_path_name
,
9390 strlen (unix_path_name
)),
9394 /* If there are items in the list, construct an event and post it to
9395 the queue like an interrupt using kbd_buffer_store_event. */
9396 if (!NILP (file_list
))
9398 struct input_event event
;
9400 struct frame
*f
= mac_window_to_frame (window
);
9403 GlobalToLocal (&mouse
);
9404 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9406 event
.kind
= DRAG_N_DROP_EVENT
;
9408 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9409 event
.timestamp
= TickCount () * (1000 / 60);
9410 XSETINT (event
.x
, mouse
.h
);
9411 XSETINT (event
.y
, mouse
.v
);
9412 XSETFRAME (frame
, f
);
9413 event
.frame_or_window
= Fcons (frame
, file_list
);
9415 /* Post to the interrupt queue */
9416 kbd_buffer_store_event (&event
);
9417 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9419 ProcessSerialNumber psn
;
9420 GetCurrentProcess (&psn
);
9421 SetFrontProcess (&psn
);
9427 return dragNotAcceptedErr
;
9432 /* Print Document Apple Event */
9434 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
9436 return errAEEventNotHandled
;
9441 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
9443 #if USE_CARBON_EVENTS
9445 EventRef event
= NULL
;
9446 static const HICommand quit_command
= {kEventAttributeNone
, kHICommandQuit
};
9448 err
= CreateEvent (NULL
, kEventClassCommand
, kEventCommandProcess
, 0,
9449 kEventAttributeUserEvent
, &event
);
9451 err
= SetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9452 sizeof (HICommand
), &quit_command
);
9454 mac_store_application_menu_event (event
);
9456 ReleaseEvent (event
);
9461 return errAEEventNotHandled
;
9463 mac_store_application_menu_event (kHICommandQuit
);
9472 profiler_exit_proc ()
9474 ProfilerDump ("\pEmacs.prof");
9479 /* These few functions implement Emacs as a normal Mac application
9480 (almost): set up the heap and the Toolbox, handle necessary system
9481 events plus a few simple menu events. They also set up Emacs's
9482 access to functions defined in the rest of this file. Emacs uses
9483 function hooks to perform all its terminal I/O. A complete list of
9484 these functions appear in termhooks.h. For what they do, read the
9485 comments there and see also w32term.c and xterm.c. What's
9486 noticeably missing here is the event loop, which is normally
9487 present in most Mac application. After performing the necessary
9488 Mac initializations, main passes off control to emacs_main
9489 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9490 (defined further below) to read input. This is where
9491 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9498 #if __profile__ /* is the profiler on? */
9499 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9504 /* set creator and type for files created by MSL */
9509 do_init_managers ();
9514 do_check_ram_size ();
9517 init_emacs_passwd_dir ();
9521 initialize_applescript ();
9523 init_required_apple_events ();
9529 /* set up argv array from STR# resource */
9530 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9534 /* free up AppleScript resources on exit */
9535 atexit (terminate_applescript
);
9537 #if __profile__ /* is the profiler on? */
9538 atexit (profiler_exit_proc
);
9541 /* 3rd param "envp" never used in emacs_main */
9542 (void) emacs_main (argc
, argv
, 0);
9545 /* Never reached - real exit in Fkill_emacs */
9550 /* Table for translating Mac keycode to X keysym values. Contributed
9552 Mapping for special keys is now identical to that in Apple X11
9553 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9554 on the right of the Cmd key on laptops, and fn + `enter' (->
9556 static unsigned char keycode_to_xkeysym_table
[] = {
9557 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9558 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9559 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9561 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9562 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9563 /*0x38*/ 0, 0, 0, 0,
9564 /*0x3C*/ 0, 0, 0, 0,
9566 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9567 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9568 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9569 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9571 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9572 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9573 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9574 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9576 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9577 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9578 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9579 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9581 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9582 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9583 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9584 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9589 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9591 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9592 return *xKeySym
!= 0;
9595 static unsigned char fn_keycode_to_xkeysym_table
[] = {
9596 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9597 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9598 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9600 /*0x30*/ 0, 0, 0, 0,
9601 /*0x34*/ 0, 0, 0, 0,
9602 /*0x38*/ 0, 0, 0, 0,
9603 /*0x3C*/ 0, 0, 0, 0,
9605 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
9606 /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
9607 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
9608 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
9610 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
9611 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
9612 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
9613 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
9615 /*0x60*/ 0, 0, 0, 0,
9616 /*0x64*/ 0, 0, 0, 0,
9617 /*0x68*/ 0, 0, 0, 0,
9618 /*0x6C*/ 0, 0, 0, 0,
9620 /*0x70*/ 0, 0, 0, 0,
9621 /*0x74*/ 0, 0, 0, 0,
9622 /*0x78*/ 0, 0, 0, 0,
9626 convert_fn_keycode (EventRef eventRef
, int keyCode
, int *newCode
)
9629 /* Use the special map to translate keys when function modifier is
9630 to be caught. KeyTranslate can't be used in that case.
9631 We can't detect the function key using the input_event.modifiers,
9632 because this uses the high word of an UInt32. Therefore,
9633 we'll just read it out of the original eventRef.
9637 /* TODO / known issues
9639 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9640 The above table always translates to lower characters. We need to use
9641 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9643 - The table is meant for English language keyboards, and it will work
9644 for many others with the exception of key combinations like Fn-ö on
9645 a German keyboard, which is currently mapped to Fn-;.
9646 How to solve this without keeping separate tables for all keyboards
9647 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9648 value for keycode with the modifiers in he high byte, i.e. no room for the
9649 Fn modifier. That's why we need the table.
9654 if (!NILP(Vmac_function_modifier
))
9656 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9657 sizeof (UInt32
), NULL
, &mods
);
9658 if (mods
& kEventKeyModifierFnMask
)
9659 { *newCode
= fn_keycode_to_xkeysym_table
[keyCode
& 0x7f];
9661 return (*newCode
!= 0);
9669 backtranslate_modified_keycode(int mods
, int keycode
, int def
)
9673 (NILP (Vmac_option_modifier
) ? 0 : optionKey
) |
9676 /* This code comes from Keyboard Resource,
9677 Appendix C of IM - Text. This is necessary
9678 since shift is ignored in KCHR table
9679 translation when option or command is pressed.
9680 It also does not translate correctly
9681 control-shift chars like C-% so mask off shift
9684 Not done for combinations with the option key (alt)
9685 unless it is to be caught by Emacs: this is
9686 to preserve key combinations translated by the OS
9689 /* mask off option and command */
9690 int new_modifiers
= mods
& 0xe600;
9691 /* set high byte of keycode to modifier high byte*/
9692 int new_keycode
= keycode
| new_modifiers
;
9693 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9694 unsigned long some_state
= 0;
9695 return (int) KeyTranslate (kchr_ptr
, new_keycode
,
9696 &some_state
) & 0xff;
9697 /* TO DO: Recognize two separate resulting characters, "for
9698 example, when the user presses Option-E followed by N, you
9699 can map this through the KeyTranslate function using the
9700 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9701 returns as two characters in the bytes labeled Character code
9702 1 and Character code 2." (from Carbon API doc) */
9710 #if !USE_CARBON_EVENTS
9711 static RgnHandle mouse_region
= NULL
;
9714 mac_wait_next_event (er
, sleep_time
, dequeue
)
9719 static EventRecord er_buf
= {nullEvent
};
9720 UInt32 target_tick
, current_tick
;
9721 EventMask event_mask
;
9723 if (mouse_region
== NULL
)
9724 mouse_region
= NewRgn ();
9726 event_mask
= everyEvent
;
9727 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
9728 event_mask
-= highLevelEventMask
;
9730 current_tick
= TickCount ();
9731 target_tick
= current_tick
+ sleep_time
;
9733 if (er_buf
.what
== nullEvent
)
9734 while (!WaitNextEvent (event_mask
, &er_buf
,
9735 target_tick
- current_tick
, mouse_region
))
9737 current_tick
= TickCount ();
9738 if (target_tick
<= current_tick
)
9744 er_buf
.what
= nullEvent
;
9747 #endif /* not USE_CARBON_EVENTS */
9749 /* Emacs calls this whenever it wants to read an input event from the
9752 XTread_socket (sd
, expected
, hold_quit
)
9754 struct input_event
*hold_quit
;
9756 struct input_event inev
;
9758 #if USE_CARBON_EVENTS
9760 EventTargetRef toolbox_dispatcher
;
9763 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9765 if (interrupt_input_blocked
)
9767 interrupt_input_pending
= 1;
9771 interrupt_input_pending
= 0;
9774 /* So people can tell when we have read the available input. */
9775 input_signal_count
++;
9777 #if USE_CARBON_EVENTS
9778 toolbox_dispatcher
= GetEventDispatcherTarget ();
9780 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9781 kEventRemoveFromQueue
, &eventRef
))
9782 #else /* !USE_CARBON_EVENTS */
9783 while (mac_wait_next_event (&er
, 0, true))
9784 #endif /* !USE_CARBON_EVENTS */
9788 unsigned long timestamp
;
9790 /* It is necessary to set this (additional) argument slot of an
9791 event to nil because keyboard.c protects incompletely
9792 processed event from being garbage collected by placing them
9793 in the kbd_buffer_gcpro vector. */
9795 inev
.kind
= NO_EVENT
;
9798 #if USE_CARBON_EVENTS
9799 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9801 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9804 #if USE_CARBON_EVENTS
9805 /* Handle new events */
9806 if (!mac_convert_event_ref (eventRef
, &er
))
9808 /* There used to be a handler for the kEventMouseWheelMoved
9809 event here. But as of Mac OS X 10.4, this kind of event
9810 is not directly posted to the main event queue by
9811 two-finger scrolling on the trackpad. Instead, some
9812 private event is posted and it is converted to a wheel
9813 event by the default handler for the application target.
9814 The converted one can be received by a Carbon event
9815 handler installed on a window target. */
9816 read_socket_inev
= &inev
;
9817 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9818 read_socket_inev
= NULL
;
9821 #endif /* USE_CARBON_EVENTS */
9827 WindowPtr window_ptr
;
9828 ControlPartCode part_code
;
9831 #if USE_CARBON_EVENTS
9832 /* This is needed to send mouse events like aqua window
9833 buttons to the correct handler. */
9834 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9835 != eventNotHandledErr
)
9838 last_mouse_glyph_frame
= 0;
9840 if (dpyinfo
->grabbed
&& last_mouse_frame
9841 && FRAME_LIVE_P (last_mouse_frame
))
9843 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9844 part_code
= inContent
;
9848 part_code
= FindWindow (er
.where
, &window_ptr
);
9849 if (tip_window
&& window_ptr
== tip_window
)
9851 HideWindow (tip_window
);
9852 part_code
= FindWindow (er
.where
, &window_ptr
);
9856 if (er
.what
!= mouseDown
&&
9857 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
9863 f
= mac_focus_frame (dpyinfo
);
9864 saved_menu_event_location
= er
.where
;
9865 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9866 XSETFRAME (inev
.frame_or_window
, f
);
9870 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9871 SelectWindow (window_ptr
);
9874 ControlPartCode control_part_code
;
9876 Point mouse_loc
= er
.where
;
9878 ControlKind control_kind
;
9881 f
= mac_window_to_frame (window_ptr
);
9882 /* convert to local coordinates of new window */
9883 SetPortWindowPort (window_ptr
);
9885 GlobalToLocal (&mouse_loc
);
9886 #if TARGET_API_MAC_CARBON
9887 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9888 &control_part_code
);
9891 GetControlKind (ch
, &control_kind
);
9894 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9898 #if USE_CARBON_EVENTS
9899 inev
.code
= mac_get_mouse_btn (eventRef
);
9900 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9902 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9903 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9905 XSETINT (inev
.x
, mouse_loc
.h
);
9906 XSETINT (inev
.y
, mouse_loc
.v
);
9908 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9910 #ifndef USE_TOOLKIT_SCROLL_BARS
9911 /* control_part_code becomes kControlNoPart if
9912 a progress indicator is clicked. */
9913 && control_part_code
!= kControlNoPart
9914 #else /* USE_TOOLKIT_SCROLL_BARS */
9916 && control_kind
.kind
== kControlKindScrollBar
9917 #endif /* MAC_OSX */
9918 #endif /* USE_TOOLKIT_SCROLL_BARS */
9921 struct scroll_bar
*bar
;
9923 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9925 bar
= tracked_scroll_bar
;
9926 #ifndef USE_TOOLKIT_SCROLL_BARS
9927 control_part_code
= kControlIndicatorPart
;
9931 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9932 #ifdef USE_TOOLKIT_SCROLL_BARS
9933 /* Make the "Ctrl-Mouse-2 splits window" work
9934 for toolkit scroll bars. */
9935 if (er
.modifiers
& controlKey
)
9936 x_scroll_bar_handle_click (bar
, control_part_code
,
9938 else if (er
.what
== mouseDown
)
9939 x_scroll_bar_handle_press (bar
, control_part_code
,
9942 x_scroll_bar_handle_release (bar
, &inev
);
9943 #else /* not USE_TOOLKIT_SCROLL_BARS */
9944 x_scroll_bar_handle_click (bar
, control_part_code
,
9946 if (er
.what
== mouseDown
9947 && control_part_code
== kControlIndicatorPart
)
9948 tracked_scroll_bar
= bar
;
9950 tracked_scroll_bar
= NULL
;
9951 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9956 int x
= mouse_loc
.h
;
9957 int y
= mouse_loc
.v
;
9959 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9960 if (EQ (window
, f
->tool_bar_window
))
9962 if (er
.what
== mouseDown
)
9963 handle_tool_bar_click (f
, x
, y
, 1, 0);
9965 handle_tool_bar_click (f
, x
, y
, 0,
9971 XSETFRAME (inev
.frame_or_window
, f
);
9972 inev
.kind
= MOUSE_CLICK_EVENT
;
9976 if (er
.what
== mouseDown
)
9978 dpyinfo
->grabbed
|= (1 << inev
.code
);
9979 last_mouse_frame
= f
;
9982 last_tool_bar_item
= -1;
9986 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9987 /* If a button is released though it was not
9988 previously pressed, that would be because
9989 of multi-button emulation. */
9990 dpyinfo
->grabbed
= 0;
9992 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9995 /* Ignore any mouse motion that happened before
9996 this event; any subsequent mouse-movement Emacs
9997 events should reflect only motion after the
10000 f
->mouse_moved
= 0;
10002 #ifdef USE_TOOLKIT_SCROLL_BARS
10003 if (inev
.kind
== MOUSE_CLICK_EVENT
)
10008 inev
.modifiers
|= down_modifier
;
10011 inev
.modifiers
|= up_modifier
;
10018 #if TARGET_API_MAC_CARBON
10019 DragWindow (window_ptr
, er
.where
, NULL
);
10020 #else /* not TARGET_API_MAC_CARBON */
10021 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10022 #endif /* not TARGET_API_MAC_CARBON */
10023 /* Update the frame parameters. */
10025 struct frame
*f
= mac_window_to_frame (window_ptr
);
10027 if (f
&& !f
->async_iconified
)
10028 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
10033 if (TrackGoAway (window_ptr
, er
.where
))
10035 inev
.kind
= DELETE_WINDOW_EVENT
;
10036 XSETFRAME (inev
.frame_or_window
,
10037 mac_window_to_frame (window_ptr
));
10041 /* window resize handling added --ben */
10043 do_grow_window (window_ptr
, &er
);
10046 /* window zoom handling added --ben */
10049 if (TrackBox (window_ptr
, er
.where
, part_code
))
10050 do_zoom_window (window_ptr
, part_code
);
10060 #if USE_CARBON_EVENTS
10061 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10062 != eventNotHandledErr
)
10065 do_window_update ((WindowPtr
) er
.message
);
10070 #if USE_CARBON_EVENTS
10071 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10072 != eventNotHandledErr
)
10075 switch ((er
.message
>> 24) & 0x000000FF)
10077 case suspendResumeMessage
:
10078 if ((er
.message
& resumeFlag
) == 1)
10084 case mouseMovedMessage
:
10085 #if !USE_CARBON_EVENTS
10086 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
10087 er
.where
.h
+ 1, er
.where
.v
+ 1);
10089 previous_help_echo_string
= help_echo_string
;
10090 help_echo_string
= Qnil
;
10092 if (dpyinfo
->grabbed
&& last_mouse_frame
10093 && FRAME_LIVE_P (last_mouse_frame
))
10094 f
= last_mouse_frame
;
10096 f
= dpyinfo
->x_focus_frame
;
10098 if (dpyinfo
->mouse_face_hidden
)
10100 dpyinfo
->mouse_face_hidden
= 0;
10101 clear_mouse_face (dpyinfo
);
10106 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
10107 Point mouse_pos
= er
.where
;
10109 SetPortWindowPort (wp
);
10111 GlobalToLocal (&mouse_pos
);
10113 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10114 #ifdef USE_TOOLKIT_SCROLL_BARS
10115 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
10117 #else /* not USE_TOOLKIT_SCROLL_BARS */
10118 x_scroll_bar_note_movement (tracked_scroll_bar
,
10120 - XINT (tracked_scroll_bar
->top
),
10121 er
.when
* (1000 / 60));
10122 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10125 /* Generate SELECT_WINDOW_EVENTs when needed. */
10126 if (mouse_autoselect_window
)
10128 Lisp_Object window
;
10130 window
= window_from_coordinates (f
,
10135 /* Window will be selected only when it is
10136 not selected now and last mouse movement
10137 event was not in it. Minibuffer window
10138 will be selected iff it is active. */
10139 if (WINDOWP (window
)
10140 && !EQ (window
, last_window
)
10141 && !EQ (window
, selected_window
))
10143 inev
.kind
= SELECT_WINDOW_EVENT
;
10144 inev
.frame_or_window
= window
;
10147 last_window
=window
;
10149 if (!note_mouse_movement (f
, &mouse_pos
))
10150 help_echo_string
= previous_help_echo_string
;
10154 /* If the contents of the global variable
10155 help_echo_string has changed, generate a
10157 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10165 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10167 #if USE_CARBON_EVENTS
10168 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10169 != eventNotHandledErr
)
10172 if (window_ptr
== tip_window
)
10174 HideWindow (tip_window
);
10178 if (!is_emacs_window (window_ptr
))
10181 if ((er
.modifiers
& activeFlag
) != 0)
10183 /* A window has been activated */
10184 Point mouse_loc
= er
.where
;
10186 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10188 SetPortWindowPort (window_ptr
);
10189 GlobalToLocal (&mouse_loc
);
10190 /* Window-activated event counts as mouse movement,
10191 so update things that depend on mouse position. */
10192 note_mouse_movement (mac_window_to_frame (window_ptr
),
10197 /* A window has been deactivated */
10198 #if USE_TOOLKIT_SCROLL_BARS
10199 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10201 struct input_event event
;
10203 EVENT_INIT (event
);
10204 event
.kind
= NO_EVENT
;
10205 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10206 if (event
.kind
!= NO_EVENT
)
10208 event
.timestamp
= timestamp
;
10209 kbd_buffer_store_event_hold (&event
, hold_quit
);
10214 dpyinfo
->grabbed
= 0;
10216 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10218 f
= mac_window_to_frame (window_ptr
);
10219 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10221 /* If we move outside the frame, then we're
10222 certainly no longer on any text in the
10224 clear_mouse_face (dpyinfo
);
10225 dpyinfo
->mouse_face_mouse_frame
= 0;
10228 /* Generate a nil HELP_EVENT to cancel a help-echo.
10229 Do it only if there's something to cancel.
10230 Otherwise, the startup message is cleared when the
10231 mouse leaves the frame. */
10232 if (any_help_event_p
)
10241 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10244 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10245 /* When using Carbon Events, we need to pass raw keyboard
10246 events to the TSM ourselves. If TSM handles it, it
10247 will pass back noErr, otherwise it will pass back
10248 "eventNotHandledErr" and we can process it
10250 if ((!NILP (Vmac_pass_command_to_system
)
10251 || !(er
.modifiers
& cmdKey
))
10252 && (!NILP (Vmac_pass_control_to_system
)
10253 || !(er
.modifiers
& controlKey
))
10254 && (NILP (Vmac_option_modifier
)
10255 || !(er
.modifiers
& optionKey
)))
10256 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10257 != eventNotHandledErr
)
10262 if (dpyinfo
->x_focus_frame
== NULL
)
10264 /* Beep if keyboard input occurs when all the frames
10272 static SInt16 last_key_script
= -1;
10273 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10275 if (last_key_script
!= current_key_script
)
10277 struct input_event event
;
10279 EVENT_INIT (event
);
10280 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10282 event
.code
= current_key_script
;
10283 event
.timestamp
= timestamp
;
10284 kbd_buffer_store_event (&event
);
10287 last_key_script
= current_key_script
;
10292 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10294 clear_mouse_face (dpyinfo
);
10295 dpyinfo
->mouse_face_hidden
= 1;
10298 /* translate the keycode back to determine the original key */
10299 /* Convert key code if function key is pressed.
10300 Otherwise, if non-ASCII-event, take care of that
10301 without re-translating the key code. */
10302 #if USE_CARBON_EVENTS
10303 if (convert_fn_keycode (eventRef
, keycode
, &xkeysym
))
10305 inev
.code
= xkeysym
;
10306 /* this doesn't work - tried to add shift modifiers */
10308 backtranslate_modified_keycode(er
.modifiers
& (~0x2200),
10309 xkeysym
| 0x80, xkeysym
);
10310 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10314 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10316 inev
.code
= 0xff00 | xkeysym
;
10317 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10323 backtranslate_modified_keycode(er
.modifiers
, keycode
,
10324 er
.message
& charCodeMask
);
10325 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10330 #if USE_CARBON_EVENTS
10331 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10333 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10335 inev
.modifiers
|= (extra_keyboard_modifiers
10336 & (meta_modifier
| alt_modifier
10337 | hyper_modifier
| super_modifier
));
10338 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10341 case kHighLevelEvent
:
10342 read_socket_inev
= &inev
;
10343 AEProcessAppleEvent (&er
);
10344 read_socket_inev
= NULL
;
10350 #if USE_CARBON_EVENTS
10351 ReleaseEvent (eventRef
);
10354 if (inev
.kind
!= NO_EVENT
)
10356 inev
.timestamp
= timestamp
;
10357 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10362 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10367 XSETFRAME (frame
, f
);
10373 any_help_event_p
= 1;
10374 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10375 help_echo_object
, help_echo_pos
);
10379 help_echo_string
= Qnil
;
10380 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10387 /* If the focus was just given to an autoraising frame,
10389 /* ??? This ought to be able to handle more than one such frame. */
10390 if (pending_autoraise_frame
)
10392 x_raise_frame (pending_autoraise_frame
);
10393 pending_autoraise_frame
= 0;
10396 #if !USE_CARBON_EVENTS
10397 /* Check which frames are still visible. We do this here because
10398 there doesn't seem to be any direct notification from the Window
10399 Manager that the visibility of a window has changed (at least,
10400 not in all cases). */
10402 Lisp_Object tail
, frame
;
10404 FOR_EACH_FRAME (tail
, frame
)
10406 struct frame
*f
= XFRAME (frame
);
10408 /* The tooltip has been drawn already. Avoid the
10409 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10410 if (EQ (frame
, tip_frame
))
10413 if (FRAME_MAC_P (f
))
10414 mac_handle_visibility_change (f
);
10424 /* Need to override CodeWarrior's input function so no conversion is
10425 done on newlines Otherwise compiled functions in .elc files will be
10426 read incorrectly. Defined in ...:MSL C:MSL
10427 Common:Source:buffer_io.c. */
10430 __convert_to_newlines (unsigned char * p
, size_t * n
)
10432 #pragma unused(p,n)
10436 __convert_from_newlines (unsigned char * p
, size_t * n
)
10438 #pragma unused(p,n)
10444 make_mac_terminal_frame (struct frame
*f
)
10449 XSETFRAME (frame
, f
);
10451 f
->output_method
= output_mac
;
10452 f
->output_data
.mac
= (struct mac_output
*)
10453 xmalloc (sizeof (struct mac_output
));
10454 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10456 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10458 FRAME_COLS (f
) = 96;
10459 FRAME_LINES (f
) = 4;
10461 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10462 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10464 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10466 f
->output_data
.mac
->cursor_pixel
= 0;
10467 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10468 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10469 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10471 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10472 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10473 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10474 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10475 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10476 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10478 FRAME_FONTSET (f
) = -1;
10479 f
->output_data
.mac
->explicit_parent
= 0;
10482 f
->border_width
= 0;
10484 f
->internal_border_width
= 0;
10489 f
->new_text_cols
= 0;
10490 f
->new_text_lines
= 0;
10492 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10493 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10494 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10498 if (!(FRAME_MAC_WINDOW (f
) =
10499 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10500 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10502 /* so that update events can find this mac_output struct */
10503 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10509 /* Need to be initialized for unshow_buffer in window.c. */
10510 selected_window
= f
->selected_window
;
10512 Fmodify_frame_parameters (frame
,
10513 Fcons (Fcons (Qfont
,
10514 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10515 Fmodify_frame_parameters (frame
,
10516 Fcons (Fcons (Qforeground_color
,
10517 build_string ("black")), Qnil
));
10518 Fmodify_frame_parameters (frame
,
10519 Fcons (Fcons (Qbackground_color
,
10520 build_string ("white")), Qnil
));
10525 /***********************************************************************
10527 ***********************************************************************/
10529 int mac_initialized
= 0;
10532 mac_initialize_display_info ()
10534 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10535 GDHandle main_device_handle
;
10537 bzero (dpyinfo
, sizeof (*dpyinfo
));
10540 dpyinfo
->mac_id_name
10541 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10542 + SCHARS (Vsystem_name
)
10544 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10545 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10547 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10548 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10551 main_device_handle
= LMGetMainDevice();
10553 dpyinfo
->reference_count
= 0;
10554 dpyinfo
->resx
= 72.0;
10555 dpyinfo
->resy
= 72.0;
10556 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10558 /* HasDepth returns true if it is possible to have a 32 bit display,
10559 but this may not be what is actually used. Mac OSX can do better.
10560 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10561 header for CGGetActiveDisplayList says that the first display returned
10562 is the active one, so we use that. */
10564 CGDirectDisplayID disp_id
[1];
10565 CGDisplayCount disp_count
;
10566 CGDisplayErr error_code
;
10568 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10569 if (error_code
!= 0)
10570 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10572 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10575 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10576 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10577 gdDevType
, dpyinfo
->color_p
))
10580 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10581 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10582 dpyinfo
->grabbed
= 0;
10583 dpyinfo
->root_window
= NULL
;
10584 dpyinfo
->image_cache
= make_image_cache ();
10586 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10587 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10588 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10589 dpyinfo
->mouse_face_window
= Qnil
;
10590 dpyinfo
->mouse_face_overlay
= Qnil
;
10591 dpyinfo
->mouse_face_hidden
= 0;
10596 mac_make_rdb (xrm_option
)
10599 XrmDatabase database
;
10601 database
= xrm_get_preference_database (NULL
);
10603 xrm_merge_string_database (database
, xrm_option
);
10608 struct mac_display_info
*
10609 mac_term_init (display_name
, xrm_option
, resource_name
)
10610 Lisp_Object display_name
;
10612 char *resource_name
;
10614 struct mac_display_info
*dpyinfo
;
10618 if (!mac_initialized
)
10621 mac_initialized
= 1;
10624 if (x_display_list
)
10625 error ("Sorry, this version can only handle one display");
10627 mac_initialize_display_info ();
10629 dpyinfo
= &one_mac_display_info
;
10631 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10633 /* Put this display on the chain. */
10634 dpyinfo
->next
= x_display_list
;
10635 x_display_list
= dpyinfo
;
10637 /* Put it on x_display_name_list. */
10638 x_display_name_list
= Fcons (Fcons (display_name
,
10639 Fcons (Qnil
, dpyinfo
->xrdb
)),
10640 x_display_name_list
);
10641 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10647 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10650 x_delete_display (dpyinfo
)
10651 struct mac_display_info
*dpyinfo
;
10655 /* Discard this display from x_display_name_list and x_display_list.
10656 We can't use Fdelq because that can quit. */
10657 if (! NILP (x_display_name_list
)
10658 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10659 x_display_name_list
= XCDR (x_display_name_list
);
10664 tail
= x_display_name_list
;
10665 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10667 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10669 XSETCDR (tail
, XCDR (XCDR (tail
)));
10672 tail
= XCDR (tail
);
10676 if (x_display_list
== dpyinfo
)
10677 x_display_list
= dpyinfo
->next
;
10680 struct x_display_info
*tail
;
10682 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10683 if (tail
->next
== dpyinfo
)
10684 tail
->next
= tail
->next
->next
;
10687 /* Free the font names in the font table. */
10688 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10689 if (dpyinfo
->font_table
[i
].name
)
10691 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10692 xfree (dpyinfo
->font_table
[i
].full_name
);
10693 xfree (dpyinfo
->font_table
[i
].name
);
10696 if (dpyinfo
->font_table
->font_encoder
)
10697 xfree (dpyinfo
->font_table
->font_encoder
);
10699 xfree (dpyinfo
->font_table
);
10700 xfree (dpyinfo
->mac_id_name
);
10702 if (x_display_list
== 0)
10704 mac_clear_font_name_table ();
10705 bzero (dpyinfo
, sizeof (*dpyinfo
));
10714 extern int inhibit_window_system
;
10715 extern int noninteractive
;
10716 CFBundleRef appsBundle
;
10719 /* No need to test if already -nw*/
10720 if (inhibit_window_system
|| noninteractive
)
10723 appsBundle
= CFBundleGetMainBundle();
10724 if (appsBundle
!= NULL
)
10726 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10727 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10728 /* We found the bundle identifier, now we know we are valid. */
10735 /* MAC_TODO: Have this start the bundled executable */
10737 /* For now, prevent the fatal error by bringing it up in the terminal */
10738 inhibit_window_system
= 1;
10742 MakeMeTheFrontProcess ()
10744 ProcessSerialNumber psn
;
10747 err
= GetCurrentProcess (&psn
);
10749 (void) SetFrontProcess (&psn
);
10752 /***** Code to handle C-g testing *****/
10754 /* Contains the Mac modifier formed from quit_char */
10755 int mac_quit_char_modifiers
= 0;
10756 int mac_quit_char_keycode
;
10757 extern int quit_char
;
10760 mac_determine_quit_char_modifiers()
10762 /* Todo: Determine modifiers from quit_char. */
10763 UInt32 qc_modifiers
= ctrl_modifier
;
10765 /* Map modifiers */
10766 mac_quit_char_modifiers
= 0;
10767 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
10768 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
10769 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
10773 init_quit_char_handler ()
10775 /* TODO: Let this support keys other the 'g' */
10776 mac_quit_char_keycode
= 5;
10777 /* Look at <architecture/adb_kb_map.h> for details */
10778 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10780 mac_determine_quit_char_modifiers();
10782 #endif /* MAC_OSX */
10790 MenuItemIndex menu_index
;
10792 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10793 &menu
, &menu_index
);
10795 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10796 #if USE_CARBON_EVENTS
10797 EnableMenuCommand (NULL
, kHICommandPreferences
);
10798 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10799 &menu
, &menu_index
);
10802 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10803 InsertMenuItemTextWithCFString (menu
, NULL
,
10804 0, kMenuItemAttrSeparator
, 0);
10805 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10806 0, 0, kHICommandAbout
);
10808 #endif /* USE_CARBON_EVENTS */
10809 #else /* !MAC_OSX */
10810 #if USE_CARBON_EVENTS
10811 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10817 /* Set up use of X before we make the first connection. */
10819 extern frame_parm_handler mac_frame_parm_handlers
[];
10821 static struct redisplay_interface x_redisplay_interface
=
10823 mac_frame_parm_handlers
,
10827 x_clear_end_of_line
,
10829 x_after_update_window_line
,
10830 x_update_window_begin
,
10831 x_update_window_end
,
10834 0, /* flush_display_optional */
10835 x_clear_window_mouse_face
,
10836 x_get_glyph_overhangs
,
10837 x_fix_overlapping_area
,
10838 x_draw_fringe_bitmap
,
10839 0, /* define_fringe_bitmap */
10840 0, /* destroy_fringe_bitmap */
10841 mac_per_char_metric
,
10843 mac_compute_glyph_string_overhangs
,
10844 x_draw_glyph_string
,
10845 mac_define_frame_cursor
,
10846 mac_clear_frame_area
,
10847 mac_draw_window_cursor
,
10848 mac_draw_vertical_window_border
,
10849 mac_shift_glyphs_for_insert
10855 rif
= &x_redisplay_interface
;
10857 clear_frame_hook
= x_clear_frame
;
10858 ins_del_lines_hook
= x_ins_del_lines
;
10859 delete_glyphs_hook
= x_delete_glyphs
;
10860 ring_bell_hook
= XTring_bell
;
10861 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10862 set_terminal_modes_hook
= XTset_terminal_modes
;
10863 update_begin_hook
= x_update_begin
;
10864 update_end_hook
= x_update_end
;
10865 set_terminal_window_hook
= XTset_terminal_window
;
10866 read_socket_hook
= XTread_socket
;
10867 frame_up_to_date_hook
= XTframe_up_to_date
;
10868 mouse_position_hook
= XTmouse_position
;
10869 frame_rehighlight_hook
= XTframe_rehighlight
;
10870 frame_raise_lower_hook
= XTframe_raise_lower
;
10872 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10873 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10874 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10875 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10877 scroll_region_ok
= 1; /* we'll scroll partial frames */
10878 char_ins_del_ok
= 1;
10879 line_ins_del_ok
= 1; /* we'll just blt 'em */
10880 fast_clear_end_of_line
= 1; /* X does this well */
10881 memory_below_frame
= 0; /* we don't remember what scrolls
10885 last_tool_bar_item
= -1;
10886 any_help_event_p
= 0;
10888 /* Try to use interrupt input; if we can't, then start polling. */
10889 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10893 #if TARGET_API_MAC_CARBON
10894 init_required_apple_events ();
10896 #if USE_CARBON_EVENTS
10898 init_service_handler ();
10900 init_quit_char_handler ();
10901 #endif /* MAC_OSX */
10903 init_command_handler ();
10906 #endif /* USE_CARBON_EVENTS */
10909 if (!inhibit_window_system
)
10910 MakeMeTheFrontProcess ();
10921 staticpro (&x_error_message_string
);
10922 x_error_message_string
= Qnil
;
10925 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
10926 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
10927 Qalt
= intern ("alt"); staticpro (&Qalt
);
10928 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
10929 Qsuper
= intern ("super"); staticpro (&Qsuper
);
10930 Qmodifier_value
= intern ("modifier-value");
10931 staticpro (&Qmodifier_value
);
10933 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
10934 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10935 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10936 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10937 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10939 Qapplication
= intern ("application"); staticpro (&Qapplication
);
10940 Qabout
= intern ("about"); staticpro (&Qabout
);
10942 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10943 Qpreferences
= intern ("preferences"); staticpro (&Qpreferences
);
10944 Qservices
= intern ("services"); staticpro (&Qservices
);
10945 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10946 Qperform
= intern ("perform"); staticpro (&Qperform
);
10950 Fprovide (intern ("mac-carbon"), Qnil
);
10953 staticpro (&Qreverse
);
10954 Qreverse
= intern ("reverse");
10956 staticpro (&Qmac_ready_for_drag_n_drop
);
10957 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
10959 staticpro (&x_display_name_list
);
10960 x_display_name_list
= Qnil
;
10962 staticpro (&last_mouse_scroll_bar
);
10963 last_mouse_scroll_bar
= Qnil
;
10965 staticpro (&fm_font_family_alist
);
10966 fm_font_family_alist
= Qnil
;
10969 staticpro (&atsu_font_id_hash
);
10970 atsu_font_id_hash
= Qnil
;
10973 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10974 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10975 #ifdef USE_TOOLKIT_SCROLL_BARS
10976 Vx_toolkit_scroll_bars
= Qt
;
10978 Vx_toolkit_scroll_bars
= Qnil
;
10981 staticpro (&last_mouse_motion_frame
);
10982 last_mouse_motion_frame
= Qnil
;
10984 /* Variables to configure modifier key assignment. */
10986 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
10987 doc
: /* Modifier key assumed when the Mac control key is pressed.
10988 The value can be `alt', `control', `hyper', or `super' for the
10989 respective modifier. The default is `control'. */);
10990 Vmac_control_modifier
= Qcontrol
;
10992 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10993 doc
: /* Modifier key assumed when the Mac alt/option key is pressed.
10994 The value can be `alt', `control', `hyper', or `super' for the
10995 respective modifier. If the value is nil then the key will act as the
10996 normal Mac control modifier, and the option key can be used to compose
10997 characters depending on the chosen Mac keyboard setting. */);
10998 Vmac_option_modifier
= Qnil
;
11000 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
11001 doc
: /* Modifier key assumed when the Mac command key is pressed.
11002 The value can be `alt', `control', `hyper', or `super' for the
11003 respective modifier. The default is `meta'. */);
11004 Vmac_command_modifier
= Qmeta
;
11006 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
11007 doc
: /* Modifier key assumed when the Mac function key is pressed.
11008 The value can be `alt', `control', `hyper', or `super' for the
11009 respective modifier. Note that remapping the function key may lead to
11010 unexpected results for some keys on non-US/GB keyboards. */);
11011 Vmac_function_modifier
= Qnil
;
11013 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11014 &Vmac_emulate_three_button_mouse
,
11015 doc
: /* Specify a way of three button mouse emulation.
11016 The value can be nil, t, or the symbol `reverse'.
11017 nil means that no emulation should be done and the modifiers should be
11018 placed on the mouse-1 event.
11019 t means that when the option-key is held down while pressing the mouse
11020 button, the click will register as mouse-2 and while the command-key
11021 is held down, the click will register as mouse-3.
11022 The symbol `reverse' means that the option-key will register for
11023 mouse-3 and the command-key will register for mouse-2. */);
11024 Vmac_emulate_three_button_mouse
= Qnil
;
11026 #if USE_CARBON_EVENTS
11027 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
11028 doc
: /* Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11029 Otherwise, the right click will be treated as mouse-2 and the wheel
11030 button will be mouse-3. */);
11031 Vmac_wheel_button_is_mouse_2
= Qt
;
11033 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
11034 doc
: /* Non-nil if command key presses are passed on to the Mac Toolbox. */);
11035 Vmac_pass_command_to_system
= Qt
;
11037 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
11038 doc
: /* Non-nil if control key presses are passed on to the Mac Toolbox. */);
11039 Vmac_pass_control_to_system
= Qt
;
11043 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
11044 doc
: /* If non-nil, allow anti-aliasing.
11045 The text will be rendered using Core Graphics text rendering which
11046 may anti-alias the text. */);
11047 Vmac_use_core_graphics
= Qnil
;
11049 /* Register an entry for `mac-roman' so that it can be used when
11050 creating the terminal frame on Mac OS 9 before loading
11051 term/mac-win.elc. */
11052 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
11053 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
11054 Each entry should be of the form:
11056 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
11058 where CHARSET-NAME is a string used in font names to identify the
11059 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
11060 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
11061 Vmac_charset_info_alist
=
11062 Fcons (list3 (build_string ("mac-roman"),
11063 make_number (smRoman
), Qnil
), Qnil
);
11066 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
11067 (do not change this comment) */