1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
29 #include "blockinput.h"
37 #if TARGET_API_MAC_CARBON
38 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
39 obtain events from the event queue. If set to 0, WaitNextEvent is
41 #define USE_CARBON_EVENTS 1
42 #else /* not TARGET_API_MAC_CARBON */
43 #include <Quickdraw.h>
44 #include <ToolUtils.h>
48 #include <Resources.h>
50 #include <TextUtils.h>
54 #if defined (__MRC__) || (__MSL__ >= 0x6000)
55 #include <ControlDefinitions.h>
61 #endif /* not TARGET_API_MAC_CARBON */
72 #include <sys/param.h>
76 #include "dispextern.h"
78 #include "termhooks.h"
85 #include "intervals.h"
86 #include "composite.h"
89 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
90 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
91 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
92 #define macShiftKey (shiftKey)
93 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
94 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
96 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
98 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
101 /* Non-nil means Emacs uses toolkit scroll bars. */
103 Lisp_Object Vx_toolkit_scroll_bars
;
105 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
106 Lisp_Object Vmac_use_core_graphics
;
109 /* Non-zero means that a HELP_EVENT has been generated since Emacs
112 static int any_help_event_p
;
114 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
115 static Lisp_Object last_window
;
117 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
119 int x_use_underline_position_properties
;
121 /* Non-zero means draw block and hollow cursor as wide as the glyph
122 under it. For example, if a block cursor is over a tab, it will be
123 drawn as wide as that tab on the display. */
126 /* This is a chain of structures for all the X displays currently in
129 struct x_display_info
*x_display_list
;
131 /* This is a list of cons cells, each of the form (NAME
132 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
133 x_display_list and in the same order. NAME is the name of the
134 frame. FONT-LIST-CACHE records previous values returned by
135 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
136 equivalent, which is implemented with a Lisp object, for the
139 Lisp_Object x_display_name_list
;
141 /* This is display since Mac does not support multiple ones. */
142 struct mac_display_info one_mac_display_info
;
144 /* Frame being updated by update_frame. This is declared in term.c.
145 This is set by update_begin and looked at by all the XT functions.
146 It is zero while not inside an update. In that case, the XT
147 functions assume that `selected_frame' is the frame to apply to. */
149 extern struct frame
*updating_frame
;
151 extern int waiting_for_input
;
153 /* This is a frame waiting to be auto-raised, within XTread_socket. */
155 struct frame
*pending_autoraise_frame
;
159 Formerly, we used PointerMotionHintMask (in standard_event_mask)
160 so that we would have to call XQueryPointer after each MotionNotify
161 event to ask for another such event. However, this made mouse tracking
162 slow, and there was a bug that made it eventually stop.
164 Simply asking for MotionNotify all the time seems to work better.
166 In order to avoid asking for motion events and then throwing most
167 of them away or busy-polling the server for mouse positions, we ask
168 the server for pointer motion hints. This means that we get only
169 one event per group of mouse movements. "Groups" are delimited by
170 other kinds of events (focus changes and button clicks, for
171 example), or by XQueryPointer calls; when one of these happens, we
172 get another MotionNotify event the next time the mouse moves. This
173 is at least as efficient as getting motion events when mouse
174 tracking is on, and I suspect only negligibly worse when tracking
177 /* Where the mouse was last time we reported a mouse event. */
179 static Rect last_mouse_glyph
;
180 static Lisp_Object last_mouse_press_frame
;
182 /* The scroll bar in which the last X motion event occurred.
184 If the last X motion event occurred in a scroll bar, we set this so
185 XTmouse_position can know whether to report a scroll bar motion or
188 If the last X motion event didn't occur in a scroll bar, we set
189 this to Qnil, to tell XTmouse_position to return an ordinary motion
192 static Lisp_Object last_mouse_scroll_bar
;
194 /* This is a hack. We would really prefer that XTmouse_position would
195 return the time associated with the position it returns, but there
196 doesn't seem to be any way to wrest the time-stamp from the server
197 along with the position query. So, we just keep track of the time
198 of the last movement we received, and return that in hopes that
199 it's somewhat accurate. */
201 static Time last_mouse_movement_time
;
203 struct scroll_bar
*tracked_scroll_bar
= NULL
;
205 /* Incremented by XTread_socket whenever it really tries to read
209 static int volatile input_signal_count
;
211 static int input_signal_count
;
214 /* Used locally within XTread_socket. */
216 static int x_noop_count
;
218 /* Initial values of argv and argc. */
220 extern char **initial_argv
;
221 extern int initial_argc
;
223 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
225 /* Tells if a window manager is present or not. */
227 extern Lisp_Object Vx_no_window_manager
;
231 /* A mask of extra modifier bits to put into every keyboard char. */
233 extern int extra_keyboard_modifiers
;
235 /* The keysyms to use for the various modifiers. */
237 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qmodifier_value
;
239 static Lisp_Object Qvendor_specific_keysyms
;
242 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
245 extern int inhibit_window_system
;
247 #if __MRC__ && !TARGET_API_MAC_CARBON
248 QDGlobals qd
; /* QuickDraw global information structure. */
252 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
253 struct mac_display_info
*mac_display_info_for_display (Display
*);
254 static void x_update_window_end
P_ ((struct window
*, int, int));
255 static int x_io_error_quitter
P_ ((Display
*));
256 int x_catch_errors
P_ ((Display
*));
257 void x_uncatch_errors
P_ ((Display
*, int));
258 void x_lower_frame
P_ ((struct frame
*));
259 void x_scroll_bar_clear
P_ ((struct frame
*));
260 int x_had_errors_p
P_ ((Display
*));
261 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
262 void x_raise_frame
P_ ((struct frame
*));
263 void x_set_window_size
P_ ((struct frame
*, int, int, int));
264 void x_wm_set_window_state
P_ ((struct frame
*, int));
265 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
266 void mac_initialize
P_ ((void));
267 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
268 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
269 static void x_update_end
P_ ((struct frame
*));
270 static void XTframe_up_to_date
P_ ((struct frame
*));
271 static void XTset_terminal_modes
P_ ((void));
272 static void XTreset_terminal_modes
P_ ((void));
273 static void x_clear_frame
P_ ((void));
274 static void frame_highlight
P_ ((struct frame
*));
275 static void frame_unhighlight
P_ ((struct frame
*));
276 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
277 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
278 struct frame
*, struct input_event
*));
279 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
280 EventRecord
*, struct input_event
*));
281 static void XTframe_rehighlight
P_ ((struct frame
*));
282 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
283 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
284 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
285 enum text_cursor_kinds
));
287 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
288 static void x_flush
P_ ((struct frame
*f
));
289 static void x_update_begin
P_ ((struct frame
*));
290 static void x_update_window_begin
P_ ((struct window
*));
291 static void x_after_update_window_line
P_ ((struct glyph_row
*));
293 static int is_emacs_window (WindowPtr
);
295 int x_bitmap_icon (struct frame
*, Lisp_Object
);
296 void x_make_frame_visible (struct frame
*);
298 extern void window_scroll (Lisp_Object
, int, int, int);
300 /* Defined in macmenu.h. */
301 extern void menubar_selection_callback (FRAME_PTR
, int);
302 extern void set_frame_menubar (FRAME_PTR
, int, int);
304 /* X display function emulation */
307 XFreePixmap (display
, pixmap
)
308 Display
*display
; /* not used */
311 DisposeGWorld (pixmap
);
315 /* Set foreground color for subsequent QuickDraw commands. Assume
316 graphic port has already been set. */
319 mac_set_forecolor (unsigned long color
)
323 fg_color
.red
= RED16_FROM_ULONG (color
);
324 fg_color
.green
= GREEN16_FROM_ULONG (color
);
325 fg_color
.blue
= BLUE16_FROM_ULONG (color
);
327 RGBForeColor (&fg_color
);
331 /* Set background color for subsequent QuickDraw commands. Assume
332 graphic port has already been set. */
335 mac_set_backcolor (unsigned long color
)
339 bg_color
.red
= RED16_FROM_ULONG (color
);
340 bg_color
.green
= GREEN16_FROM_ULONG (color
);
341 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
343 RGBBackColor (&bg_color
);
346 /* Set foreground and background color for subsequent QuickDraw
347 commands. Assume that the graphic port has already been set. */
350 mac_set_colors (gc
, bg_save
)
355 GetBackColor (bg_save
);
356 mac_set_forecolor (gc
->foreground
);
357 mac_set_backcolor (gc
->background
);
360 /* Mac version of XDrawLine. */
363 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
371 SetPortWindowPort (w
);
373 mac_set_colors (gc
, &old_bg
);
378 RGBBackColor (&old_bg
);
382 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
391 GetGWorld (&old_port
, &old_gdh
);
394 mac_set_colors (gc
, NULL
);
396 LockPixels (GetGWorldPixMap (p
));
399 UnlockPixels (GetGWorldPixMap (p
));
401 SetGWorld (old_port
, old_gdh
);
404 /* Mac version of XClearArea. */
407 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
411 unsigned int width
, height
;
414 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
419 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
420 xgc
.background
= mwp
->x_compatible
.background_pixel
;
422 SetPortWindowPort (w
);
424 mac_set_colors (&xgc
, &old_bg
);
425 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
429 RGBBackColor (&old_bg
);
432 /* Mac version of XClearWindow. */
435 XClearWindow (display
, w
)
439 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
442 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
443 xgc
.background
= mwp
->x_compatible
.background_pixel
;
445 SetPortWindowPort (w
);
447 mac_set_colors (&xgc
, NULL
);
449 #if TARGET_API_MAC_CARBON
453 GetWindowPortBounds (w
, &r
);
456 #else /* not TARGET_API_MAC_CARBON */
457 EraseRect (&(w
->portRect
));
458 #endif /* not TARGET_API_MAC_CARBON */
462 /* Mac replacement for XCopyArea. */
465 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
469 int x
, y
, width
, height
;
470 unsigned short *bits
;
477 bitmap
.rowBytes
= sizeof(unsigned short);
478 bitmap
.baseAddr
= (char *)bits
;
479 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
481 SetPortWindowPort (w
);
483 mac_set_colors (gc
, &old_bg
);
484 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
486 #if TARGET_API_MAC_CARBON
487 LockPortBits (GetWindowPort (w
));
488 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
489 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
490 UnlockPortBits (GetWindowPort (w
));
491 #else /* not TARGET_API_MAC_CARBON */
492 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
493 overlay_p
? srcOr
: srcCopy
, 0);
494 #endif /* not TARGET_API_MAC_CARBON */
496 RGBBackColor (&old_bg
);
500 /* Mac replacement for XSetClipRectangles. */
503 mac_set_clip_rectangle (display
, w
, r
)
508 SetPortWindowPort (w
);
514 /* Mac replacement for XSetClipMask. */
517 mac_reset_clipping (display
, w
)
523 SetPortWindowPort (w
);
525 SetRect (&r
, -32767, -32767, 32767, 32767);
530 /* Mac replacement for XCreateBitmapFromBitmapData. */
533 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
538 static unsigned char swap_nibble
[16]
539 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
540 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
541 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
542 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
546 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
547 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
548 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
549 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
550 for (i
= 0; i
< h
; i
++)
552 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
553 for (j
= 0; j
< w1
; j
++)
555 /* Bitswap XBM bytes to match how Mac does things. */
556 unsigned char c
= *bits
++;
557 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
558 | (swap_nibble
[(c
>>4) & 0xf]));;
562 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
567 mac_free_bitmap (bitmap
)
570 xfree (bitmap
->baseAddr
);
575 XCreatePixmap (display
, w
, width
, height
, depth
)
576 Display
*display
; /* not used */
578 unsigned int width
, height
;
585 SetPortWindowPort (w
);
587 SetRect (&r
, 0, 0, width
, height
);
588 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
596 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
597 Display
*display
; /* not used */
600 unsigned int width
, height
;
601 unsigned long fg
, bg
;
602 unsigned int depth
; /* not used */
609 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
613 GetGWorld (&old_port
, &old_gdh
);
614 SetGWorld (pixmap
, NULL
);
615 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
616 mac_set_forecolor (fg
);
617 mac_set_backcolor (bg
);
618 LockPixels (GetGWorldPixMap (pixmap
));
619 #if TARGET_API_MAC_CARBON
620 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
621 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
622 #else /* not TARGET_API_MAC_CARBON */
623 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
624 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
625 #endif /* not TARGET_API_MAC_CARBON */
626 UnlockPixels (GetGWorldPixMap (pixmap
));
627 SetGWorld (old_port
, old_gdh
);
628 mac_free_bitmap (&bitmap
);
634 /* Mac replacement for XFillRectangle. */
637 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
642 unsigned int width
, height
;
647 SetPortWindowPort (w
);
649 mac_set_colors (gc
, &old_bg
);
650 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
652 PaintRect (&r
); /* using foreground color of gc */
654 RGBBackColor (&old_bg
);
658 #if 0 /* TODO: figure out if we need to do this on Mac. */
660 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
665 unsigned int width
, height
;
671 GetGWorld (&old_port
, &old_gdh
);
673 mac_set_colors (gc
, NULL
);
674 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
676 LockPixels (GetGWorldPixMap (p
));
677 PaintRect (&r
); /* using foreground color of gc */
678 UnlockPixels (GetGWorldPixMap (p
));
680 SetGWorld (old_port
, old_gdh
);
685 /* Mac replacement for XDrawRectangle: dest is a window. */
688 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
693 unsigned int width
, height
;
698 SetPortWindowPort (w
);
700 mac_set_colors (gc
, &old_bg
);
701 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
703 FrameRect (&r
); /* using foreground color of gc */
705 RGBBackColor (&old_bg
);
709 #if 0 /* TODO: figure out if we need to do this on Mac. */
710 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
713 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
718 unsigned int width
, height
;
724 GetGWorld (&old_port
, &old_gdh
);
726 mac_set_colors (gc
, NULL
);
727 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
729 LockPixels (GetGWorldPixMap (p
));
730 FrameRect (&r
); /* using foreground color of gc */
731 UnlockPixels (GetGWorldPixMap (p
));
733 SetGWorld (old_port
, old_gdh
);
739 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
746 int nchars
, mode
, bytes_per_char
;
750 SetPortWindowPort (w
);
751 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
752 UInt32 textFlags
, savedFlags
;
753 if (!NILP(Vmac_use_core_graphics
)) {
754 textFlags
= kQDUseCGTextRendering
;
755 savedFlags
= SwapQDTextFlags(textFlags
);
759 mac_set_colors (gc
, &old_bg
);
761 TextFont (gc
->font
->mac_fontnum
);
762 TextSize (gc
->font
->mac_fontsize
);
763 TextFace (gc
->font
->mac_fontface
);
767 DrawText (buf
, 0, nchars
* bytes_per_char
);
769 RGBBackColor (&old_bg
);
770 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
771 if (!NILP(Vmac_use_core_graphics
))
772 SwapQDTextFlags(savedFlags
);
777 /* Mac replacement for XDrawString. */
780 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
788 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
792 /* Mac replacement for XDrawString16. */
795 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
803 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
808 /* Mac replacement for XDrawImageString. */
811 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
819 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
823 /* Mac replacement for XDrawString16. */
826 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
834 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
839 /* Mac replacement for XCopyArea: dest must be window. */
842 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
849 unsigned int width
, height
;
854 SetPortWindowPort (dest
);
856 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
857 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
859 ForeColor (blackColor
);
860 BackColor (whiteColor
);
862 LockPixels (GetGWorldPixMap (src
));
863 #if TARGET_API_MAC_CARBON
864 LockPortBits (GetWindowPort (dest
));
865 CopyBits (GetPortBitMapForCopyBits (src
),
866 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
867 &src_r
, &dest_r
, srcCopy
, 0);
868 UnlockPortBits (GetWindowPort (dest
));
869 #else /* not TARGET_API_MAC_CARBON */
870 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
871 &src_r
, &dest_r
, srcCopy
, 0);
872 #endif /* not TARGET_API_MAC_CARBON */
873 UnlockPixels (GetGWorldPixMap (src
));
878 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
879 width
, height
, dest_x
, dest_y
)
885 unsigned int width
, height
;
890 SetPortWindowPort (dest
);
892 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
893 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
895 ForeColor (blackColor
);
896 BackColor (whiteColor
);
898 LockPixels (GetGWorldPixMap (src
));
899 LockPixels (GetGWorldPixMap (mask
));
900 #if TARGET_API_MAC_CARBON
901 LockPortBits (GetWindowPort (dest
));
902 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
903 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
904 &src_r
, &src_r
, &dest_r
);
905 UnlockPortBits (GetWindowPort (dest
));
906 #else /* not TARGET_API_MAC_CARBON */
907 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
908 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
909 #endif /* not TARGET_API_MAC_CARBON */
910 UnlockPixels (GetGWorldPixMap (mask
));
911 UnlockPixels (GetGWorldPixMap (src
));
916 /* Convert a pair of local coordinates to global (screen) coordinates.
917 Assume graphic port has been properly set. */
919 local_to_global_coord (short *h
, short *v
)
933 /* Mac replacement for XCopyArea: used only for scrolling. */
936 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
941 unsigned int width
, height
;
944 #if TARGET_API_MAC_CARBON
946 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
948 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
949 ScrollWindowRect (w
, &src_r
, dest_x
- src_x
, dest_y
- src_y
,
950 kScrollWindowNoOptions
, dummy
);
952 #else /* not TARGET_API_MAC_CARBON */
957 mac_set_colors (gc
, NULL
);
960 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
961 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
964 /* Need to use global coordinates and screenBits since src and dest
965 areas overlap in general. */
966 local_to_global_coord (&src_r
.left
, &src_r
.top
);
967 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
968 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
969 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
971 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
973 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
974 color mapping in CopyBits. Otherwise, it will be slow. */
975 ForeColor (blackColor
);
976 BackColor (whiteColor
);
977 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
979 mac_set_colors (gc
, NULL
);
981 #endif /* not TARGET_API_MAC_CARBON */
985 #if 0 /* TODO: figure out if we need to do this on Mac. */
986 /* Mac replacement for XCopyArea: dest must be Pixmap. */
989 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
995 unsigned int width
, height
;
1002 GetGWorld (&old_port
, &old_gdh
);
1003 SetGWorld (dest
, NULL
);
1004 ForeColor (blackColor
);
1005 BackColor (whiteColor
);
1007 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1008 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1010 LockPixels (GetGWorldPixMap (src
));
1011 LockPixels (GetGWorldPixMap (dest
));
1012 #if TARGET_API_MAC_CARBON
1013 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
1014 &src_r
, &dest_r
, srcCopy
, 0);
1015 #else /* not TARGET_API_MAC_CARBON */
1016 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
1017 &src_r
, &dest_r
, srcCopy
, 0);
1018 #endif /* not TARGET_API_MAC_CARBON */
1019 UnlockPixels (GetGWorldPixMap (dest
));
1020 UnlockPixels (GetGWorldPixMap (src
));
1022 SetGWorld (old_port
, old_gdh
);
1027 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
1028 width
, height
, dest_x
, dest_y
)
1030 Pixmap src
, mask
, dest
;
1033 unsigned int width
, height
;
1040 GetGWorld (&old_port
, &old_gdh
);
1041 SetGWorld (dest
, NULL
);
1042 ForeColor (blackColor
);
1043 BackColor (whiteColor
);
1045 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1046 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1048 LockPixels (GetGWorldPixMap (src
));
1049 LockPixels (GetGWorldPixMap (mask
));
1050 LockPixels (GetGWorldPixMap (dest
));
1051 #if TARGET_API_MAC_CARBON
1052 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1053 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
1054 #else /* not TARGET_API_MAC_CARBON */
1055 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1056 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
1057 #endif /* not TARGET_API_MAC_CARBON */
1058 UnlockPixels (GetGWorldPixMap (dest
));
1059 UnlockPixels (GetGWorldPixMap (mask
));
1060 UnlockPixels (GetGWorldPixMap (src
));
1062 SetGWorld (old_port
, old_gdh
);
1067 /* Mac replacement for XChangeGC. */
1070 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1073 if (mask
& GCForeground
)
1074 gc
->foreground
= xgcv
->foreground
;
1075 if (mask
& GCBackground
)
1076 gc
->background
= xgcv
->background
;
1078 gc
->font
= xgcv
->font
;
1082 /* Mac replacement for XCreateGC. */
1085 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1088 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1089 bzero (gc
, sizeof (XGCValues
));
1091 XChangeGC (ignore
, gc
, mask
, xgcv
);
1097 /* Used in xfaces.c. */
1100 XFreeGC (display
, gc
)
1108 /* Mac replacement for XGetGCValues. */
1111 XGetGCValues (void* ignore
, XGCValues
*gc
,
1112 unsigned long mask
, XGCValues
*xgcv
)
1114 XChangeGC (ignore
, xgcv
, mask
, gc
);
1118 /* Mac replacement for XSetForeground. */
1121 XSetForeground (display
, gc
, color
)
1124 unsigned long color
;
1126 gc
->foreground
= color
;
1130 /* Mac replacement for XSetBackground. */
1133 XSetBackground (display
, gc
, color
)
1136 unsigned long color
;
1138 gc
->background
= color
;
1142 /* Mac replacement for XSetWindowBackground. */
1145 XSetWindowBackground (display
, w
, color
)
1148 unsigned long color
;
1150 #if !TARGET_API_MAC_CARBON
1151 AuxWinHandle aw_handle
;
1152 CTabHandle ctab_handle
;
1153 ColorSpecPtr ct_table
;
1158 bg_color
.red
= RED16_FROM_ULONG (color
);
1159 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1160 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1162 #if TARGET_API_MAC_CARBON
1163 SetWindowContentColor (w
, &bg_color
);
1165 if (GetAuxWin (w
, &aw_handle
))
1167 ctab_handle
= (*aw_handle
)->awCTable
;
1168 HandToHand ((Handle
*) &ctab_handle
);
1169 ct_table
= (*ctab_handle
)->ctTable
;
1170 ct_size
= (*ctab_handle
)->ctSize
;
1171 while (ct_size
> -1)
1173 if (ct_table
->value
== 0)
1175 ct_table
->rgb
= bg_color
;
1176 CTabChanged (ctab_handle
);
1177 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1186 /* Mac replacement for XSetFont. */
1189 XSetFont (display
, gc
, font
)
1198 /* x_sync is a no-op on Mac. */
1206 /* Flush display of frame F, or of all frames if F is null. */
1212 #if TARGET_API_MAC_CARBON
1215 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1217 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1223 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1224 Calls to XFlush should be unnecessary because the X output buffer
1225 is flushed automatically as needed by calls to XPending,
1226 XNextEvent, or XWindowEvent according to the XFlush man page.
1227 XTread_socket calls XPending. Removing XFlush improves
1230 #define XFlush(DISPLAY) (void) 0
1233 /* Return the struct mac_display_info corresponding to DPY. There's
1236 struct mac_display_info
*
1237 mac_display_info_for_display (dpy
)
1240 return &one_mac_display_info
;
1245 /***********************************************************************
1246 Starting and ending an update
1247 ***********************************************************************/
1249 /* Start an update of frame F. This function is installed as a hook
1250 for update_begin, i.e. it is called when update_begin is called.
1251 This function is called prior to calls to x_update_window_begin for
1252 each window being updated. */
1258 #if TARGET_API_MAC_CARBON
1259 /* During update of a frame, availability of input events is
1260 periodically checked with ReceiveNextEvent if
1261 redisplay-dont-pause is nil. That normally flushes window buffer
1262 changes for every check, and thus screen update looks waving even
1263 if no input is available. So we disable screen updates during
1264 update of a frame. */
1266 DisableScreenUpdates ();
1272 /* Start update of window W. Set the global variable updated_window
1273 to the window being updated and set output_cursor to the cursor
1277 x_update_window_begin (w
)
1280 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1281 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1284 set_output_cursor (&w
->cursor
);
1288 if (f
== display_info
->mouse_face_mouse_frame
)
1290 /* Don't do highlighting for mouse motion during the update. */
1291 display_info
->mouse_face_defer
= 1;
1293 /* If F needs to be redrawn, simply forget about any prior mouse
1295 if (FRAME_GARBAGED_P (f
))
1296 display_info
->mouse_face_window
= Qnil
;
1298 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1299 their mouse_face_p flag set, which means that they are always
1300 unequal to rows in a desired matrix which never have that
1301 flag set. So, rows containing mouse-face glyphs are never
1302 scrolled, and we don't have to switch the mouse highlight off
1303 here to prevent it from being scrolled. */
1305 /* Can we tell that this update does not affect the window
1306 where the mouse highlight is? If so, no need to turn off.
1307 Likewise, don't do anything if the frame is garbaged;
1308 in that case, the frame's current matrix that we would use
1309 is all wrong, and we will redisplay that line anyway. */
1310 if (!NILP (display_info
->mouse_face_window
)
1311 && w
== XWINDOW (display_info
->mouse_face_window
))
1315 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1316 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1319 if (i
< w
->desired_matrix
->nrows
)
1320 clear_mouse_face (display_info
);
1329 /* Draw a vertical window border from (x,y0) to (x,y1) */
1332 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1336 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1338 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1339 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1343 /* End update of window W (which is equal to updated_window).
1345 Draw vertical borders between horizontally adjacent windows, and
1346 display W's cursor if CURSOR_ON_P is non-zero.
1348 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1349 glyphs in mouse-face were overwritten. In that case we have to
1350 make sure that the mouse-highlight is properly redrawn.
1352 W may be a menu bar pseudo-window in case we don't have X toolkit
1353 support. Such windows don't have a cursor, so don't display it
1357 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1359 int cursor_on_p
, mouse_face_overwritten_p
;
1361 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1363 if (!w
->pseudo_window_p
)
1368 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1370 output_cursor
.x
, output_cursor
.y
);
1372 if (draw_window_fringes (w
, 1))
1373 x_draw_vertical_border (w
);
1378 /* If a row with mouse-face was overwritten, arrange for
1379 XTframe_up_to_date to redisplay the mouse highlight. */
1380 if (mouse_face_overwritten_p
)
1382 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1383 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1384 dpyinfo
->mouse_face_window
= Qnil
;
1388 /* Unhide the caret. This won't actually show the cursor, unless it
1389 was visible before the corresponding call to HideCaret in
1390 x_update_window_begin. */
1391 if (w32_use_visible_system_caret
)
1392 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1395 updated_window
= NULL
;
1399 /* End update of frame F. This function is installed as a hook in
1406 /* Mouse highlight may be displayed again. */
1407 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1410 #if TARGET_API_MAC_CARBON
1411 EnableScreenUpdates ();
1413 XFlush (FRAME_MAC_DISPLAY (f
));
1418 /* This function is called from various places in xdisp.c whenever a
1419 complete update has been performed. The global variable
1420 updated_window is not available here. */
1423 XTframe_up_to_date (f
)
1426 if (FRAME_MAC_P (f
))
1428 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1430 if (dpyinfo
->mouse_face_deferred_gc
1431 || f
== dpyinfo
->mouse_face_mouse_frame
)
1434 if (dpyinfo
->mouse_face_mouse_frame
)
1435 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1436 dpyinfo
->mouse_face_mouse_x
,
1437 dpyinfo
->mouse_face_mouse_y
);
1438 dpyinfo
->mouse_face_deferred_gc
= 0;
1445 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1446 arrow bitmaps, or clear the fringes if no bitmaps are required
1447 before DESIRED_ROW is made current. The window being updated is
1448 found in updated_window. This function is called from
1449 update_window_line only if it is known that there are differences
1450 between bitmaps to be drawn between current row and DESIRED_ROW. */
1453 x_after_update_window_line (desired_row
)
1454 struct glyph_row
*desired_row
;
1456 struct window
*w
= updated_window
;
1462 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1463 desired_row
->redraw_fringe_bitmaps_p
= 1;
1465 /* When a window has disappeared, make sure that no rest of
1466 full-width rows stays visible in the internal border. Could
1467 check here if updated_window is the leftmost/rightmost window,
1468 but I guess it's not worth doing since vertically split windows
1469 are almost never used, internal border is rarely set, and the
1470 overhead is very small. */
1471 if (windows_or_buffers_changed
1472 && desired_row
->full_width_p
1473 && (f
= XFRAME (w
->frame
),
1474 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1476 && (height
= desired_row
->visible_height
,
1479 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1480 /* Internal border is drawn below the tool bar. */
1481 if (WINDOWP (f
->tool_bar_window
)
1482 && w
== XWINDOW (f
->tool_bar_window
))
1487 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1488 0, y
, width
, height
, 0);
1489 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1490 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1498 /* Draw the bitmap WHICH in one of the left or right fringes of
1499 window W. ROW is the glyph row for which to display the bitmap; it
1500 determines the vertical position at which the bitmap has to be
1504 x_draw_fringe_bitmap (w
, row
, p
)
1506 struct glyph_row
*row
;
1507 struct draw_fringe_bitmap_params
*p
;
1509 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1510 Display
*display
= FRAME_MAC_DISPLAY (f
);
1511 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1513 GC gc
= f
->output_data
.mac
->normal_gc
;
1514 struct face
*face
= p
->face
;
1517 /* Must clip because of partially visible lines. */
1518 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1521 /* Adjust position of "bottom aligned" bitmap on partially
1522 visible last row. */
1524 int oldVH
= row
->visible_height
;
1525 row
->visible_height
= p
->h
;
1526 row
->y
-= rowY
- p
->y
;
1527 x_clip_to_row (w
, row
, -1, gc
);
1529 row
->visible_height
= oldVH
;
1532 x_clip_to_row (w
, row
, -1, gc
);
1534 if (p
->bx
>= 0 && !p
->overlay_p
)
1537 gcv
.foreground
= face
->background
;
1539 #if 0 /* MAC_TODO: stipple */
1540 /* In case the same realized face is used for fringes and
1541 for something displayed in the text (e.g. face `region' on
1542 mono-displays, the fill style may have been changed to
1543 FillSolid in x_draw_glyph_string_background. */
1545 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1547 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1550 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1552 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1554 #if 0 /* MAC_TODO: stipple */
1556 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1562 unsigned short *bits
= p
->bits
+ p
->dh
;
1564 gcv
.foreground
= (p
->cursor_p
1565 ? (p
->overlay_p
? face
->background
1566 : f
->output_data
.mac
->cursor_pixel
)
1567 : face
->foreground
);
1568 gcv
.background
= face
->background
;
1570 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
,
1571 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1574 mac_reset_clipping (display
, window
);
1578 /* This is called when starting Emacs and when restarting after
1579 suspend. When starting Emacs, no window is mapped. And nothing
1580 must be done to Emacs's own window if it is suspended (though that
1584 XTset_terminal_modes ()
1588 /* This is called when exiting or suspending Emacs. Exiting will make
1589 the windows go away, and suspending requires no action. */
1592 XTreset_terminal_modes ()
1597 /***********************************************************************
1599 ***********************************************************************/
1601 /* Function prototypes of this page. */
1603 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1604 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1607 /* Return a pointer to per-char metric information in FONT of a
1608 character pointed by B which is a pointer to an XChar2b. */
1610 #define PER_CHAR_METRIC(font, b) \
1612 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1613 + (((font)->min_byte1 || (font)->max_byte1) \
1614 ? (((b)->byte1 - (font)->min_byte1) \
1615 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1617 : &((font)->max_bounds))
1620 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1621 is not contained in the font. */
1623 static INLINE XCharStruct
*
1624 x_per_char_metric (font
, char2b
)
1628 /* The result metric information. */
1629 XCharStruct
*pcm
= NULL
;
1631 xassert (font
&& char2b
);
1633 if (font
->per_char
!= NULL
)
1635 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1637 /* min_char_or_byte2 specifies the linear character index
1638 corresponding to the first element of the per_char array,
1639 max_char_or_byte2 is the index of the last character. A
1640 character with non-zero CHAR2B->byte1 is not in the font.
1641 A character with byte2 less than min_char_or_byte2 or
1642 greater max_char_or_byte2 is not in the font. */
1643 if (char2b
->byte1
== 0
1644 && char2b
->byte2
>= font
->min_char_or_byte2
1645 && char2b
->byte2
<= font
->max_char_or_byte2
)
1646 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1650 /* If either min_byte1 or max_byte1 are nonzero, both
1651 min_char_or_byte2 and max_char_or_byte2 are less than
1652 256, and the 2-byte character index values corresponding
1653 to the per_char array element N (counting from 0) are:
1655 byte1 = N/D + min_byte1
1656 byte2 = N\D + min_char_or_byte2
1660 D = max_char_or_byte2 - min_char_or_byte2 + 1
1661 / = integer division
1662 \ = integer modulus */
1663 if (char2b
->byte1
>= font
->min_byte1
1664 && char2b
->byte1
<= font
->max_byte1
1665 && char2b
->byte2
>= font
->min_char_or_byte2
1666 && char2b
->byte2
<= font
->max_char_or_byte2
)
1668 pcm
= (font
->per_char
1669 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1670 * (char2b
->byte1
- font
->min_byte1
))
1671 + (char2b
->byte2
- font
->min_char_or_byte2
));
1677 /* If the per_char pointer is null, all glyphs between the first
1678 and last character indexes inclusive have the same
1679 information, as given by both min_bounds and max_bounds. */
1680 if (char2b
->byte2
>= font
->min_char_or_byte2
1681 && char2b
->byte2
<= font
->max_char_or_byte2
)
1682 pcm
= &font
->max_bounds
;
1685 return ((pcm
== NULL
1686 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1693 static XCharStruct
*
1694 mac_per_char_metric (font
, char2b
, font_type
)
1699 return x_per_char_metric (font
, char2b
);
1703 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1704 the two-byte form of C. Encoding is returned in *CHAR2B. */
1707 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1710 struct font_info
*font_info
;
1713 int charset
= CHAR_CHARSET (c
);
1714 XFontStruct
*font
= font_info
->font
;
1716 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1717 This may be either a program in a special encoder language or a
1719 if (font_info
->font_encoder
)
1721 /* It's a program. */
1722 struct ccl_program
*ccl
= font_info
->font_encoder
;
1724 if (CHARSET_DIMENSION (charset
) == 1)
1726 ccl
->reg
[0] = charset
;
1727 ccl
->reg
[1] = char2b
->byte2
;
1731 ccl
->reg
[0] = charset
;
1732 ccl
->reg
[1] = char2b
->byte1
;
1733 ccl
->reg
[2] = char2b
->byte2
;
1736 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1738 /* We assume that MSBs are appropriately set/reset by CCL
1740 if (font
->max_byte1
== 0) /* 1-byte font */
1741 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1743 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1745 else if (font_info
->encoding
[charset
])
1747 /* Fixed encoding scheme. See fontset.h for the meaning of the
1748 encoding numbers. */
1749 int enc
= font_info
->encoding
[charset
];
1751 if ((enc
== 1 || enc
== 2)
1752 && CHARSET_DIMENSION (charset
) == 2)
1753 char2b
->byte1
|= 0x80;
1755 if (enc
== 1 || enc
== 3)
1756 char2b
->byte2
|= 0x80;
1762 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1763 char2b
->byte1
= sjis1
;
1764 char2b
->byte2
= sjis2
;
1769 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1771 return FONT_TYPE_UNKNOWN
;
1776 /***********************************************************************
1778 ***********************************************************************/
1781 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1782 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1783 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1785 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1786 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1787 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1788 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1789 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1790 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1791 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1792 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1793 unsigned long *, double, int));*/
1794 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1795 double, int, unsigned long));
1796 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1797 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1798 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1799 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1800 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1801 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1803 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1804 int, int, int, int, int, int,
1806 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1807 int, int, int, Rect
*));
1810 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1814 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1819 struct glyph_string
*s
;
1821 if (s
->font
== FRAME_FONT (s
->f
)
1822 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1823 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1825 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1828 /* Cursor on non-default face: must merge. */
1832 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1833 xgcv
.foreground
= s
->face
->background
;
1835 /* If the glyph would be invisible, try a different foreground. */
1836 if (xgcv
.foreground
== xgcv
.background
)
1837 xgcv
.foreground
= s
->face
->foreground
;
1838 if (xgcv
.foreground
== xgcv
.background
)
1839 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1840 if (xgcv
.foreground
== xgcv
.background
)
1841 xgcv
.foreground
= s
->face
->foreground
;
1843 /* Make sure the cursor is distinct from text in this face. */
1844 if (xgcv
.background
== s
->face
->background
1845 && xgcv
.foreground
== s
->face
->foreground
)
1847 xgcv
.background
= s
->face
->foreground
;
1848 xgcv
.foreground
= s
->face
->background
;
1851 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1852 xgcv
.font
= s
->font
;
1853 mask
= GCForeground
| GCBackground
| GCFont
;
1855 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1856 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1859 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1860 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1862 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1867 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1870 x_set_mouse_face_gc (s
)
1871 struct glyph_string
*s
;
1876 /* What face has to be used last for the mouse face? */
1877 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1878 face
= FACE_FROM_ID (s
->f
, face_id
);
1880 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1882 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1883 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1885 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1886 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1887 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1889 /* If font in this face is same as S->font, use it. */
1890 if (s
->font
== s
->face
->font
)
1891 s
->gc
= s
->face
->gc
;
1894 /* Otherwise construct scratch_cursor_gc with values from FACE
1899 xgcv
.background
= s
->face
->background
;
1900 xgcv
.foreground
= s
->face
->foreground
;
1901 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1902 xgcv
.font
= s
->font
;
1903 mask
= GCForeground
| GCBackground
| GCFont
;
1905 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1906 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1909 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1910 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1912 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1915 xassert (s
->gc
!= 0);
1919 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1920 Faces to use in the mode line have already been computed when the
1921 matrix was built, so there isn't much to do, here. */
1924 x_set_mode_line_face_gc (s
)
1925 struct glyph_string
*s
;
1927 s
->gc
= s
->face
->gc
;
1931 /* Set S->gc of glyph string S for drawing that glyph string. Set
1932 S->stippled_p to a non-zero value if the face of S has a stipple
1936 x_set_glyph_string_gc (s
)
1937 struct glyph_string
*s
;
1939 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1941 if (s
->hl
== DRAW_NORMAL_TEXT
)
1943 s
->gc
= s
->face
->gc
;
1944 s
->stippled_p
= s
->face
->stipple
!= 0;
1946 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1948 x_set_mode_line_face_gc (s
);
1949 s
->stippled_p
= s
->face
->stipple
!= 0;
1951 else if (s
->hl
== DRAW_CURSOR
)
1953 x_set_cursor_gc (s
);
1956 else if (s
->hl
== DRAW_MOUSE_FACE
)
1958 x_set_mouse_face_gc (s
);
1959 s
->stippled_p
= s
->face
->stipple
!= 0;
1961 else if (s
->hl
== DRAW_IMAGE_RAISED
1962 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1964 s
->gc
= s
->face
->gc
;
1965 s
->stippled_p
= s
->face
->stipple
!= 0;
1969 s
->gc
= s
->face
->gc
;
1970 s
->stippled_p
= s
->face
->stipple
!= 0;
1973 /* GC must have been set. */
1974 xassert (s
->gc
!= 0);
1978 /* Set clipping for output of glyph string S. S may be part of a mode
1979 line or menu if we don't have X toolkit support. */
1982 x_set_glyph_string_clipping (s
)
1983 struct glyph_string
*s
;
1986 get_glyph_string_clip_rect (s
, &r
);
1987 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
1992 Compute left and right overhang of glyph string S. If S is a glyph
1993 string for a composition, assume overhangs don't exist. */
1996 mac_compute_glyph_string_overhangs (s
)
1997 struct glyph_string
*s
;
2000 && s
->first_glyph
->type
== CHAR_GLYPH
)
2003 MacFontStruct
*font
= s
->font
;
2005 TextFont (font
->mac_fontnum
);
2006 TextSize (font
->mac_fontsize
);
2007 TextFace (font
->mac_fontface
);
2010 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2014 char *buf
= xmalloc (s
->nchars
);
2017 SetRect (&r
, 0, 0, 0, 0);
2020 for (i
= 0; i
< s
->nchars
; ++i
)
2021 buf
[i
] = s
->char2b
[i
].byte2
;
2022 QDTextBounds (s
->nchars
, buf
, &r
);
2027 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2028 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2033 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2036 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2037 struct glyph_string
*s
;
2042 xgcv
.foreground
= s
->gc
->background
;
2043 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2047 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2048 on Mac OS X because:
2049 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2050 into an offscreen graphics world first. So performance gain
2051 cannot be expected.)
2052 - It lowers rendering quality.
2053 - Some fonts leave garbage on cursor movement. */
2055 /* Draw the background of glyph_string S. If S->background_filled_p
2056 is non-zero don't draw it. FORCE_P non-zero means draw the
2057 background even if it wouldn't be drawn normally. This is used
2058 when a string preceding S draws into the background of S, or S
2059 contains the first component of a composition. */
2062 x_draw_glyph_string_background (s
, force_p
)
2063 struct glyph_string
*s
;
2066 /* Nothing to do if background has already been drawn or if it
2067 shouldn't be drawn in the first place. */
2068 if (!s
->background_filled_p
)
2070 int box_line_width
= max (s
->face
->box_line_width
, 0);
2072 #if 0 /* MAC_TODO: stipple */
2075 /* Fill background with a stipple pattern. */
2076 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2077 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2078 s
->y
+ box_line_width
,
2079 s
->background_width
,
2080 s
->height
- 2 * box_line_width
);
2081 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2082 s
->background_filled_p
= 1;
2087 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2088 || s
->font_not_found_p
2089 || s
->extends_to_end_of_line_p
2093 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2094 s
->background_width
,
2095 s
->height
- 2 * box_line_width
);
2096 s
->background_filled_p
= 1;
2102 /* Draw the foreground of glyph string S. */
2105 x_draw_glyph_string_foreground (s
)
2106 struct glyph_string
*s
;
2110 /* If first glyph of S has a left box line, start drawing the text
2111 of S to the right of that box line. */
2112 if (s
->face
->box
!= FACE_NO_BOX
2113 && s
->first_glyph
->left_box_line_p
)
2114 x
= s
->x
+ abs (s
->face
->box_line_width
);
2118 /* Draw characters of S as rectangles if S's font could not be
2120 if (s
->font_not_found_p
)
2122 for (i
= 0; i
< s
->nchars
; ++i
)
2124 struct glyph
*g
= s
->first_glyph
+ i
;
2125 mac_draw_rectangle (s
->display
, s
->window
,
2126 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2128 x
+= g
->pixel_width
;
2133 char *char1b
= (char *) s
->char2b
;
2134 int boff
= s
->font_info
->baseline_offset
;
2136 if (s
->font_info
->vertical_centering
)
2137 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2139 /* If we can use 8-bit functions, condense S->char2b. */
2141 for (i
= 0; i
< s
->nchars
; ++i
)
2142 char1b
[i
] = s
->char2b
[i
].byte2
;
2145 /* Draw text with XDrawString if background has already been
2146 filled. Otherwise, use XDrawImageString. (Note that
2147 XDrawImageString is usually faster than XDrawString.) Always
2148 use XDrawImageString when drawing the cursor so that there is
2149 no chance that characters under a box cursor are invisible. */
2150 if (s
->for_overlaps_p
2151 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2154 /* Draw characters with 16-bit or 8-bit functions. */
2156 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2157 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2159 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2160 s
->ybase
- boff
, char1b
, s
->nchars
);
2166 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2167 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2169 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2170 s
->ybase
- boff
, char1b
, s
->nchars
);
2176 /* Draw the foreground of composite glyph string S. */
2179 x_draw_composite_glyph_string_foreground (s
)
2180 struct glyph_string
*s
;
2184 /* If first glyph of S has a left box line, start drawing the text
2185 of S to the right of that box line. */
2186 if (s
->face
->box
!= FACE_NO_BOX
2187 && s
->first_glyph
->left_box_line_p
)
2188 x
= s
->x
+ abs (s
->face
->box_line_width
);
2192 /* S is a glyph string for a composition. S->gidx is the index of
2193 the first character drawn for glyphs of this composition.
2194 S->gidx == 0 means we are drawing the very first character of
2195 this composition. */
2197 /* Draw a rectangle for the composition if the font for the very
2198 first character of the composition could not be loaded. */
2199 if (s
->font_not_found_p
)
2202 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2203 s
->width
- 1, s
->height
- 1);
2207 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2208 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2209 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2210 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2216 #ifdef USE_X_TOOLKIT
2218 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2221 /* Return the frame on which widget WIDGET is used.. Abort if frame
2222 cannot be determined. */
2224 static struct frame
*
2225 x_frame_of_widget (widget
)
2228 struct x_display_info
*dpyinfo
;
2232 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2234 /* Find the top-level shell of the widget. Note that this function
2235 can be called when the widget is not yet realized, so XtWindow
2236 (widget) == 0. That's the reason we can't simply use
2237 x_any_window_to_frame. */
2238 while (!XtIsTopLevelShell (widget
))
2239 widget
= XtParent (widget
);
2241 /* Look for a frame with that top-level widget. Allocate the color
2242 on that frame to get the right gamma correction value. */
2243 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2244 if (GC_FRAMEP (XCAR (tail
))
2245 && (f
= XFRAME (XCAR (tail
)),
2246 (f
->output_data
.nothing
!= 1
2247 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2248 && f
->output_data
.x
->widget
== widget
)
2255 /* Allocate the color COLOR->pixel on the screen and display of
2256 widget WIDGET in colormap CMAP. If an exact match cannot be
2257 allocated, try the nearest color available. Value is non-zero
2258 if successful. This is called from lwlib. */
2261 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2266 struct frame
*f
= x_frame_of_widget (widget
);
2267 return x_alloc_nearest_color (f
, cmap
, color
);
2271 #endif /* USE_X_TOOLKIT */
2273 #if 0 /* MAC_TODO */
2275 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2276 CMAP. If an exact match can't be allocated, try the nearest color
2277 available. Value is non-zero if successful. Set *COLOR to the
2281 x_alloc_nearest_color (f
, cmap
, color
)
2286 Display
*display
= FRAME_X_DISPLAY (f
);
2287 Screen
*screen
= FRAME_X_SCREEN (f
);
2290 gamma_correct (f
, color
);
2291 rc
= XAllocColor (display
, cmap
, color
);
2294 /* If we got to this point, the colormap is full, so we're going
2295 to try to get the next closest color. The algorithm used is
2296 a least-squares matching, which is what X uses for closest
2297 color matching with StaticColor visuals. */
2299 unsigned long nearest_delta
= ~0;
2300 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2301 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2303 for (i
= 0; i
< ncells
; ++i
)
2305 XQueryColors (display
, cmap
, cells
, ncells
);
2307 for (nearest
= i
= 0; i
< ncells
; ++i
)
2309 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2310 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2311 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2312 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2314 if (delta
< nearest_delta
)
2317 nearest_delta
= delta
;
2321 color
->red
= cells
[nearest
].red
;
2322 color
->green
= cells
[nearest
].green
;
2323 color
->blue
= cells
[nearest
].blue
;
2324 rc
= XAllocColor (display
, cmap
, color
);
2327 #ifdef DEBUG_X_COLORS
2329 register_color (color
->pixel
);
2330 #endif /* DEBUG_X_COLORS */
2336 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2337 It's necessary to do this instead of just using PIXEL directly to
2338 get color reference counts right. */
2341 x_copy_color (f
, pixel
)
2343 unsigned long pixel
;
2347 color
.pixel
= pixel
;
2349 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2350 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2352 #ifdef DEBUG_X_COLORS
2353 register_color (pixel
);
2359 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2360 It's necessary to do this instead of just using PIXEL directly to
2361 get color reference counts right. */
2364 x_copy_dpy_color (dpy
, cmap
, pixel
)
2367 unsigned long pixel
;
2371 color
.pixel
= pixel
;
2373 XQueryColor (dpy
, cmap
, &color
);
2374 XAllocColor (dpy
, cmap
, &color
);
2376 #ifdef DEBUG_X_COLORS
2377 register_color (pixel
);
2382 #endif /* MAC_TODO */
2385 /* Brightness beyond which a color won't have its highlight brightness
2388 Nominally, highlight colors for `3d' faces are calculated by
2389 brightening an object's color by a constant scale factor, but this
2390 doesn't yield good results for dark colors, so for colors who's
2391 brightness is less than this value (on a scale of 0-255) have to
2392 use an additional additive factor.
2394 The value here is set so that the default menu-bar/mode-line color
2395 (grey75) will not have its highlights changed at all. */
2396 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2399 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2400 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2401 If this produces the same color as COLOR, try a color where all RGB
2402 values have DELTA added. Return the allocated color in *COLOR.
2403 DISPLAY is the X display, CMAP is the colormap to operate on.
2404 Value is non-zero if successful. */
2407 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2409 unsigned long *color
;
2416 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2419 /* Change RGB values by specified FACTOR. Avoid overflow! */
2420 xassert (factor
>= 0);
2421 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2422 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2423 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2425 /* Calculate brightness of COLOR. */
2426 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2427 + BLUE_FROM_ULONG (*color
)) / 6;
2429 /* We only boost colors that are darker than
2430 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2431 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2432 /* Make an additive adjustment to NEW, because it's dark enough so
2433 that scaling by FACTOR alone isn't enough. */
2435 /* How far below the limit this color is (0 - 1, 1 being darker). */
2436 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2437 /* The additive adjustment. */
2438 int min_delta
= delta
* dimness
* factor
/ 2;
2441 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2442 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2443 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2445 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2446 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2447 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2451 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2452 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2453 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2455 /* MAC_TODO: Map to palette and retry with delta if same? */
2456 /* MAC_TODO: Free colors (if using palette)? */
2467 /* Set up the foreground color for drawing relief lines of glyph
2468 string S. RELIEF is a pointer to a struct relief containing the GC
2469 with which lines will be drawn. Use a color that is FACTOR or
2470 DELTA lighter or darker than the relief's background which is found
2471 in S->f->output_data.x->relief_background. If such a color cannot
2472 be allocated, use DEFAULT_PIXEL, instead. */
2475 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2477 struct relief
*relief
;
2480 unsigned long default_pixel
;
2483 struct mac_output
*di
= f
->output_data
.mac
;
2484 unsigned long mask
= GCForeground
;
2485 unsigned long pixel
;
2486 unsigned long background
= di
->relief_background
;
2487 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2489 /* MAC_TODO: Free colors (if using palette)? */
2491 /* Allocate new color. */
2492 xgcv
.foreground
= default_pixel
;
2494 if (dpyinfo
->n_planes
!= 1
2495 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2497 relief
->allocated_p
= 1;
2498 xgcv
.foreground
= relief
->pixel
= pixel
;
2501 if (relief
->gc
== 0)
2503 #if 0 /* MAC_TODO: stipple */
2504 xgcv
.stipple
= dpyinfo
->gray
;
2507 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2510 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2514 /* Set up colors for the relief lines around glyph string S. */
2517 x_setup_relief_colors (s
)
2518 struct glyph_string
*s
;
2520 struct mac_output
*di
= s
->f
->output_data
.mac
;
2521 unsigned long color
;
2523 if (s
->face
->use_box_color_for_shadows_p
)
2524 color
= s
->face
->box_color
;
2525 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2527 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2528 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2533 /* Get the background color of the face. */
2534 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2535 color
= xgcv
.background
;
2538 if (di
->white_relief
.gc
== 0
2539 || color
!= di
->relief_background
)
2541 di
->relief_background
= color
;
2542 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2543 WHITE_PIX_DEFAULT (s
->f
));
2544 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2545 BLACK_PIX_DEFAULT (s
->f
));
2550 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2551 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2552 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2553 relief. LEFT_P non-zero means draw a relief on the left side of
2554 the rectangle. RIGHT_P non-zero means draw a relief on the right
2555 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2559 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2560 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2562 int left_x
, top_y
, right_x
, bottom_y
, width
;
2563 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2566 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2567 Window window
= FRAME_MAC_WINDOW (f
);
2572 gc
= f
->output_data
.mac
->white_relief
.gc
;
2574 gc
= f
->output_data
.mac
->black_relief
.gc
;
2575 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2579 for (i
= 0; i
< width
; ++i
)
2580 XDrawLine (dpy
, window
, gc
,
2581 left_x
+ i
* left_p
, top_y
+ i
,
2582 right_x
- i
* right_p
, top_y
+ i
);
2586 for (i
= 0; i
< width
; ++i
)
2587 XDrawLine (dpy
, window
, gc
,
2588 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2590 mac_reset_clipping (dpy
, window
);
2592 gc
= f
->output_data
.mac
->black_relief
.gc
;
2594 gc
= f
->output_data
.mac
->white_relief
.gc
;
2595 mac_set_clip_rectangle (dpy
, window
,
2600 for (i
= 0; i
< width
; ++i
)
2601 XDrawLine (dpy
, window
, gc
,
2602 left_x
+ i
* left_p
, bottom_y
- i
,
2603 right_x
- i
* right_p
, bottom_y
- i
);
2607 for (i
= 0; i
< width
; ++i
)
2608 XDrawLine (dpy
, window
, gc
,
2609 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2611 mac_reset_clipping (dpy
, window
);
2615 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2616 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2617 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2618 left side of the rectangle. RIGHT_P non-zero means draw a line
2619 on the right side of the rectangle. CLIP_RECT is the clipping
2620 rectangle to use when drawing. */
2623 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2624 left_p
, right_p
, clip_rect
)
2625 struct glyph_string
*s
;
2626 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2631 xgcv
.foreground
= s
->face
->box_color
;
2632 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2635 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2636 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2640 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2641 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2644 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2645 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2649 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2650 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2652 mac_reset_clipping (s
->display
, s
->window
);
2656 /* Draw a box around glyph string S. */
2659 x_draw_glyph_string_box (s
)
2660 struct glyph_string
*s
;
2662 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2663 int left_p
, right_p
;
2664 struct glyph
*last_glyph
;
2667 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2668 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2669 : window_box_right (s
->w
, s
->area
));
2671 /* The glyph that may have a right box line. */
2672 last_glyph
= (s
->cmp
|| s
->img
2674 : s
->first_glyph
+ s
->nchars
- 1);
2676 width
= abs (s
->face
->box_line_width
);
2677 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2679 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2681 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2683 bottom_y
= top_y
+ s
->height
- 1;
2685 left_p
= (s
->first_glyph
->left_box_line_p
2686 || (s
->hl
== DRAW_MOUSE_FACE
2688 || s
->prev
->hl
!= s
->hl
)));
2689 right_p
= (last_glyph
->right_box_line_p
2690 || (s
->hl
== DRAW_MOUSE_FACE
2692 || s
->next
->hl
!= s
->hl
)));
2694 get_glyph_string_clip_rect (s
, &clip_rect
);
2696 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2697 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2698 left_p
, right_p
, &clip_rect
);
2701 x_setup_relief_colors (s
);
2702 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2703 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2708 /* Draw foreground of image glyph string S. */
2711 x_draw_image_foreground (s
)
2712 struct glyph_string
*s
;
2715 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2717 /* If first glyph of S has a left box line, start drawing it to the
2718 right of that line. */
2719 if (s
->face
->box
!= FACE_NO_BOX
2720 && s
->first_glyph
->left_box_line_p
2722 x
+= abs (s
->face
->box_line_width
);
2724 /* If there is a margin around the image, adjust x- and y-position
2726 if (s
->slice
.x
== 0)
2727 x
+= s
->img
->hmargin
;
2728 if (s
->slice
.y
== 0)
2729 y
+= s
->img
->vmargin
;
2733 x_set_glyph_string_clipping (s
);
2736 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2737 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2738 s
->slice
.width
, s
->slice
.height
, x
, y
);
2741 mac_copy_area (s
->display
, s
->img
->pixmap
,
2742 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2743 s
->slice
.width
, s
->slice
.height
, x
, y
);
2745 /* When the image has a mask, we can expect that at
2746 least part of a mouse highlight or a block cursor will
2747 be visible. If the image doesn't have a mask, make
2748 a block cursor visible by drawing a rectangle around
2749 the image. I believe it's looking better if we do
2750 nothing here for mouse-face. */
2751 if (s
->hl
== DRAW_CURSOR
)
2753 int r
= s
->img
->relief
;
2755 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2757 s
->slice
.width
+ r
*2 - 1,
2758 s
->slice
.height
+ r
*2 - 1);
2763 /* Draw a rectangle if image could not be loaded. */
2764 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2765 s
->slice
.width
- 1, s
->slice
.height
- 1);
2769 /* Draw a relief around the image glyph string S. */
2772 x_draw_image_relief (s
)
2773 struct glyph_string
*s
;
2775 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2778 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2780 /* If first glyph of S has a left box line, start drawing it to the
2781 right of that line. */
2782 if (s
->face
->box
!= FACE_NO_BOX
2783 && s
->first_glyph
->left_box_line_p
2785 x
+= abs (s
->face
->box_line_width
);
2787 /* If there is a margin around the image, adjust x- and y-position
2789 if (s
->slice
.x
== 0)
2790 x
+= s
->img
->hmargin
;
2791 if (s
->slice
.y
== 0)
2792 y
+= s
->img
->vmargin
;
2794 if (s
->hl
== DRAW_IMAGE_SUNKEN
2795 || s
->hl
== DRAW_IMAGE_RAISED
)
2797 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2798 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2802 thick
= abs (s
->img
->relief
);
2803 raised_p
= s
->img
->relief
> 0;
2808 x1
= x
+ s
->slice
.width
+ thick
- 1;
2809 y1
= y
+ s
->slice
.height
+ thick
- 1;
2811 x_setup_relief_colors (s
);
2812 get_glyph_string_clip_rect (s
, &r
);
2813 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2815 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2817 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2822 #if 0 /* TODO: figure out if we need to do this on Mac. */
2823 /* Draw the foreground of image glyph string S to PIXMAP. */
2826 x_draw_image_foreground_1 (s
, pixmap
)
2827 struct glyph_string
*s
;
2831 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2833 /* If first glyph of S has a left box line, start drawing it to the
2834 right of that line. */
2835 if (s
->face
->box
!= FACE_NO_BOX
2836 && s
->first_glyph
->left_box_line_p
2838 x
+= abs (s
->face
->box_line_width
);
2840 /* If there is a margin around the image, adjust x- and y-position
2842 if (s
->slice
.x
== 0)
2843 x
+= s
->img
->hmargin
;
2844 if (s
->slice
.y
== 0)
2845 y
+= s
->img
->vmargin
;
2850 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2851 s
->img
->mask
, pixmap
, s
->gc
,
2852 s
->slice
.x
, s
->slice
.y
,
2853 s
->slice
.width
, s
->slice
.height
,
2857 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2858 s
->slice
.x
, s
->slice
.y
,
2859 s
->slice
.width
, s
->slice
.height
,
2862 /* When the image has a mask, we can expect that at
2863 least part of a mouse highlight or a block cursor will
2864 be visible. If the image doesn't have a mask, make
2865 a block cursor visible by drawing a rectangle around
2866 the image. I believe it's looking better if we do
2867 nothing here for mouse-face. */
2868 if (s
->hl
== DRAW_CURSOR
)
2870 int r
= s
->img
->relief
;
2872 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2873 s
->slice
.width
+ r
*2 - 1,
2874 s
->slice
.height
+ r
*2 - 1);
2879 /* Draw a rectangle if image could not be loaded. */
2880 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2881 s
->slice
.width
- 1, s
->slice
.height
- 1);
2886 /* Draw part of the background of glyph string S. X, Y, W, and H
2887 give the rectangle to draw. */
2890 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2891 struct glyph_string
*s
;
2894 #if 0 /* MAC_TODO: stipple */
2897 /* Fill background with a stipple pattern. */
2898 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2899 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2900 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2903 #endif /* MAC_TODO */
2904 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2908 /* Draw image glyph string S.
2911 s->x +-------------------------
2914 | +-------------------------
2917 | | +-------------------
2923 x_draw_image_glyph_string (s
)
2924 struct glyph_string
*s
;
2927 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2928 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2932 height
= s
->height
- 2 * box_line_vwidth
;
2935 /* Fill background with face under the image. Do it only if row is
2936 taller than image or if image has a clip mask to reduce
2938 s
->stippled_p
= s
->face
->stipple
!= 0;
2939 if (height
> s
->slice
.height
2943 || s
->img
->pixmap
== 0
2944 || s
->width
!= s
->background_width
)
2947 if (s
->first_glyph
->left_box_line_p
2949 x
+= box_line_hwidth
;
2952 if (s
->slice
.y
== 0)
2953 y
+= box_line_vwidth
;
2955 #if 0 /* TODO: figure out if we need to do this on Mac. */
2958 /* Create a pixmap as large as the glyph string. Fill it
2959 with the background color. Copy the image to it, using
2960 its mask. Copy the temporary pixmap to the display. */
2961 int depth
= one_mac_display_info
.n_planes
;
2963 /* Create a pixmap as large as the glyph string. */
2964 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2965 s
->background_width
,
2968 /* Fill the pixmap with the background color/stipple. */
2969 #if 0 /* TODO: stipple */
2972 /* Fill background with a stipple pattern. */
2973 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2974 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2975 0, 0, s
->background_width
, s
->height
);
2976 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2982 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2984 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2985 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2986 0, 0, s
->background_width
,
2988 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2993 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2995 s
->background_filled_p
= 1;
2998 /* Draw the foreground. */
2999 #if 0 /* TODO: figure out if we need to do this on Mac. */
3002 x_draw_image_foreground_1 (s
, pixmap
);
3003 x_set_glyph_string_clipping (s
);
3004 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
3005 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3006 mac_reset_clipping (s
->display
, s
->window
);
3007 XFreePixmap (s
->display
, pixmap
);
3011 x_draw_image_foreground (s
);
3013 /* If we must draw a relief around the image, do it. */
3015 || s
->hl
== DRAW_IMAGE_RAISED
3016 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3017 x_draw_image_relief (s
);
3021 /* Draw stretch glyph string S. */
3024 x_draw_stretch_glyph_string (s
)
3025 struct glyph_string
*s
;
3027 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3028 s
->stippled_p
= s
->face
->stipple
!= 0;
3030 if (s
->hl
== DRAW_CURSOR
3031 && !x_stretch_cursor_p
)
3033 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3034 as wide as the stretch glyph. */
3035 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3038 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3040 /* Clear rest using the GC of the original non-cursor face. */
3041 if (width
< s
->background_width
)
3043 int x
= s
->x
+ width
, y
= s
->y
;
3044 int w
= s
->background_width
- width
, h
= s
->height
;
3048 if (s
->row
->mouse_face_p
3049 && cursor_in_mouse_face_p (s
->w
))
3051 x_set_mouse_face_gc (s
);
3057 get_glyph_string_clip_rect (s
, &r
);
3058 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3060 #if 0 /* MAC_TODO: stipple */
3061 if (s
->face
->stipple
)
3063 /* Fill background with a stipple pattern. */
3064 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3065 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3066 XSetFillStyle (s
->display
, gc
, FillSolid
);
3069 #endif /* MAC_TODO */
3072 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3073 XSetForeground (s
->display
, gc
, xgcv
.background
);
3074 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3075 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3078 mac_reset_clipping (s
->display
, s
->window
);
3081 else if (!s
->background_filled_p
)
3082 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3085 s
->background_filled_p
= 1;
3089 /* Draw glyph string S. */
3092 x_draw_glyph_string (s
)
3093 struct glyph_string
*s
;
3095 int relief_drawn_p
= 0;
3097 /* If S draws into the background of its successor that does not
3098 draw a cursor, draw the background of the successor first so that
3099 S can draw into it. This makes S->next use XDrawString instead
3100 of XDrawImageString. */
3101 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
3102 && s
->next
->hl
!= DRAW_CURSOR
)
3104 xassert (s
->next
->img
== NULL
);
3105 x_set_glyph_string_gc (s
->next
);
3106 x_set_glyph_string_clipping (s
->next
);
3107 x_draw_glyph_string_background (s
->next
, 1);
3110 /* Set up S->gc, set clipping and draw S. */
3111 x_set_glyph_string_gc (s
);
3113 /* Draw relief (if any) in advance for char/composition so that the
3114 glyph string can be drawn over it. */
3115 if (!s
->for_overlaps_p
3116 && s
->face
->box
!= FACE_NO_BOX
3117 && (s
->first_glyph
->type
== CHAR_GLYPH
3118 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3121 x_set_glyph_string_clipping (s
);
3122 x_draw_glyph_string_background (s
, 1);
3123 x_draw_glyph_string_box (s
);
3124 x_set_glyph_string_clipping (s
);
3128 x_set_glyph_string_clipping (s
);
3130 switch (s
->first_glyph
->type
)
3133 x_draw_image_glyph_string (s
);
3137 x_draw_stretch_glyph_string (s
);
3141 if (s
->for_overlaps_p
)
3142 s
->background_filled_p
= 1;
3144 x_draw_glyph_string_background (s
, 0);
3145 x_draw_glyph_string_foreground (s
);
3148 case COMPOSITE_GLYPH
:
3149 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3150 s
->background_filled_p
= 1;
3152 x_draw_glyph_string_background (s
, 1);
3153 x_draw_composite_glyph_string_foreground (s
);
3160 if (!s
->for_overlaps_p
)
3162 /* Draw underline. */
3163 if (s
->face
->underline_p
)
3165 unsigned long h
= 1;
3166 unsigned long dy
= s
->height
- h
;
3168 if (s
->face
->underline_defaulted_p
)
3169 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3174 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3175 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3176 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3178 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3182 /* Draw overline. */
3183 if (s
->face
->overline_p
)
3185 unsigned long dy
= 0, h
= 1;
3187 if (s
->face
->overline_color_defaulted_p
)
3188 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3193 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3194 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3195 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3197 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3201 /* Draw strike-through. */
3202 if (s
->face
->strike_through_p
)
3204 unsigned long h
= 1;
3205 unsigned long dy
= (s
->height
- h
) / 2;
3207 if (s
->face
->strike_through_color_defaulted_p
)
3208 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3213 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3214 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3215 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3217 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3221 /* Draw relief if not yet drawn. */
3222 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3223 x_draw_glyph_string_box (s
);
3226 /* Reset clipping. */
3227 mac_reset_clipping (s
->display
, s
->window
);
3230 /* Shift display to make room for inserted glyphs. */
3233 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3235 int x
, y
, width
, height
, shift_by
;
3237 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3238 f
->output_data
.mac
->normal_gc
,
3239 x
, y
, width
, height
,
3243 /* Delete N glyphs at the nominal cursor position. Not implemented
3254 /* Clear entire frame. If updating_frame is non-null, clear that
3255 frame. Otherwise clear the selected frame. */
3265 f
= SELECTED_FRAME ();
3267 /* Clearing the frame will erase any cursor, so mark them all as no
3269 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3270 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3271 output_cursor
.x
= -1;
3273 /* We don't set the output cursor here because there will always
3274 follow an explicit cursor_to. */
3276 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3278 /* We have to clear the scroll bars, too. If we have changed
3279 colors or something like that, then they should be notified. */
3280 x_scroll_bar_clear (f
);
3282 XFlush (FRAME_MAC_DISPLAY (f
));
3288 /* Invert the middle quarter of the frame for .15 sec. */
3290 /* We use the select system call to do the waiting, so we have to make
3291 sure it's available. If it isn't, we just won't do visual bells. */
3293 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3296 /* Subtract the `struct timeval' values X and Y, storing the result in
3297 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3300 timeval_subtract (result
, x
, y
)
3301 struct timeval
*result
, x
, y
;
3303 /* Perform the carry for the later subtraction by updating y. This
3304 is safer because on some systems the tv_sec member is unsigned. */
3305 if (x
.tv_usec
< y
.tv_usec
)
3307 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3308 y
.tv_usec
-= 1000000 * nsec
;
3312 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3314 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3315 y
.tv_usec
+= 1000000 * nsec
;
3319 /* Compute the time remaining to wait. tv_usec is certainly
3321 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3322 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3324 /* Return indication of whether the result should be considered
3326 return x
.tv_sec
< y
.tv_sec
;
3338 struct timeval wakeup
;
3340 EMACS_GET_TIME (wakeup
);
3342 /* Compute time to wait until, propagating carry from usecs. */
3343 wakeup
.tv_usec
+= 150000;
3344 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3345 wakeup
.tv_usec
%= 1000000;
3347 /* Keep waiting until past the time wakeup. */
3350 struct timeval timeout
;
3352 EMACS_GET_TIME (timeout
);
3354 /* In effect, timeout = wakeup - timeout.
3355 Break if result would be negative. */
3356 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3359 /* Try to wait that long--but we might wake up sooner. */
3360 select (0, NULL
, NULL
, NULL
, &timeout
);
3369 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3372 /* Make audible bell. */
3377 struct frame
*f
= SELECTED_FRAME ();
3379 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3387 XFlush (FRAME_MAC_DISPLAY (f
));
3394 /* Specify how many text lines, from the top of the window,
3395 should be affected by insert-lines and delete-lines operations.
3396 This, and those operations, are used only within an update
3397 that is bounded by calls to x_update_begin and x_update_end. */
3400 XTset_terminal_window (n
)
3403 /* This function intentionally left blank. */
3408 /***********************************************************************
3410 ***********************************************************************/
3412 /* Perform an insert-lines or delete-lines operation, inserting N
3413 lines or deleting -N lines at vertical position VPOS. */
3416 x_ins_del_lines (vpos
, n
)
3423 /* Scroll part of the display as described by RUN. */
3426 x_scroll_run (w
, run
)
3430 struct frame
*f
= XFRAME (w
->frame
);
3431 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3433 /* Get frame-relative bounding box of the text display area of W,
3434 without mode lines. Include in this box the left and right
3436 window_box (w
, -1, &x
, &y
, &width
, &height
);
3438 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3439 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3440 bottom_y
= y
+ height
;
3444 /* Scrolling up. Make sure we don't copy part of the mode
3445 line at the bottom. */
3446 if (from_y
+ run
->height
> bottom_y
)
3447 height
= bottom_y
- from_y
;
3449 height
= run
->height
;
3453 /* Scolling down. Make sure we don't copy over the mode line.
3455 if (to_y
+ run
->height
> bottom_y
)
3456 height
= bottom_y
- to_y
;
3458 height
= run
->height
;
3463 /* Cursor off. Will be switched on again in x_update_window_end. */
3467 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3468 f
->output_data
.mac
->normal_gc
,
3478 /***********************************************************************
3480 ***********************************************************************/
3488 ControlRef root_control
;
3491 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3493 ActivateControl (root_control
);
3495 x_update_cursor (f
, 1);
3499 frame_unhighlight (f
)
3503 ControlRef root_control
;
3506 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3508 DeactivateControl (root_control
);
3510 x_update_cursor (f
, 1);
3513 /* The focus has changed. Update the frames as necessary to reflect
3514 the new situation. Note that we can't change the selected frame
3515 here, because the Lisp code we are interrupting might become confused.
3516 Each event gets marked with the frame in which it occurred, so the
3517 Lisp code can tell when the switch took place by examining the events. */
3520 x_new_focus_frame (dpyinfo
, frame
)
3521 struct x_display_info
*dpyinfo
;
3522 struct frame
*frame
;
3524 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3526 if (frame
!= dpyinfo
->x_focus_frame
)
3528 /* Set this before calling other routines, so that they see
3529 the correct value of x_focus_frame. */
3530 dpyinfo
->x_focus_frame
= frame
;
3532 if (old_focus
&& old_focus
->auto_lower
)
3533 x_lower_frame (old_focus
);
3536 selected_frame
= frame
;
3537 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3539 Fselect_window (selected_frame
->selected_window
, Qnil
);
3540 choose_minibuf_frame ();
3543 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3544 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3546 pending_autoraise_frame
= 0;
3549 x_frame_rehighlight (dpyinfo
);
3552 /* Handle FocusIn and FocusOut state changes for FRAME.
3553 If FRAME has focus and there exists more than one frame, puts
3554 a FOCUS_IN_EVENT into *BUFP. */
3557 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3559 struct mac_display_info
*dpyinfo
;
3560 struct frame
*frame
;
3561 struct input_event
*bufp
;
3563 if (type
== activeFlag
)
3565 if (dpyinfo
->x_focus_event_frame
!= frame
)
3567 x_new_focus_frame (dpyinfo
, frame
);
3568 dpyinfo
->x_focus_event_frame
= frame
;
3570 /* Don't stop displaying the initial startup message
3571 for a switch-frame event we don't need. */
3572 if (GC_NILP (Vterminal_frame
)
3573 && GC_CONSP (Vframe_list
)
3574 && !GC_NILP (XCDR (Vframe_list
)))
3576 bufp
->kind
= FOCUS_IN_EVENT
;
3577 XSETFRAME (bufp
->frame_or_window
, frame
);
3583 if (dpyinfo
->x_focus_event_frame
== frame
)
3585 dpyinfo
->x_focus_event_frame
= 0;
3586 x_new_focus_frame (dpyinfo
, 0);
3591 /* The focus may have changed. Figure out if it is a real focus change,
3592 by checking both FocusIn/Out and Enter/LeaveNotify events.
3594 Returns FOCUS_IN_EVENT event in *BUFP. */
3597 x_detect_focus_change (dpyinfo
, event
, bufp
)
3598 struct mac_display_info
*dpyinfo
;
3600 struct input_event
*bufp
;
3602 struct frame
*frame
;
3604 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3608 /* On Mac, this is only called from focus events, so no switch needed. */
3609 mac_focus_changed ((event
->modifiers
& activeFlag
),
3610 dpyinfo
, frame
, bufp
);
3614 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3617 x_mouse_leave (dpyinfo
)
3618 struct x_display_info
*dpyinfo
;
3620 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3623 /* The focus has changed, or we have redirected a frame's focus to
3624 another frame (this happens when a frame uses a surrogate
3625 mini-buffer frame). Shift the highlight as appropriate.
3627 The FRAME argument doesn't necessarily have anything to do with which
3628 frame is being highlighted or un-highlighted; we only use it to find
3629 the appropriate X display info. */
3632 XTframe_rehighlight (frame
)
3633 struct frame
*frame
;
3635 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3639 x_frame_rehighlight (dpyinfo
)
3640 struct x_display_info
*dpyinfo
;
3642 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3644 if (dpyinfo
->x_focus_frame
)
3646 dpyinfo
->x_highlight_frame
3647 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3648 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3649 : dpyinfo
->x_focus_frame
);
3650 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3652 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3653 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3657 dpyinfo
->x_highlight_frame
= 0;
3659 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3662 frame_unhighlight (old_highlight
);
3663 if (dpyinfo
->x_highlight_frame
)
3664 frame_highlight (dpyinfo
->x_highlight_frame
);
3670 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3672 #if 0 /* MAC_TODO */
3673 /* Initialize mode_switch_bit and modifier_meaning. */
3675 x_find_modifier_meanings (dpyinfo
)
3676 struct x_display_info
*dpyinfo
;
3678 int min_code
, max_code
;
3681 XModifierKeymap
*mods
;
3683 dpyinfo
->meta_mod_mask
= 0;
3684 dpyinfo
->shift_lock_mask
= 0;
3685 dpyinfo
->alt_mod_mask
= 0;
3686 dpyinfo
->super_mod_mask
= 0;
3687 dpyinfo
->hyper_mod_mask
= 0;
3690 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3692 min_code
= dpyinfo
->display
->min_keycode
;
3693 max_code
= dpyinfo
->display
->max_keycode
;
3696 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3697 min_code
, max_code
- min_code
+ 1,
3699 mods
= XGetModifierMapping (dpyinfo
->display
);
3701 /* Scan the modifier table to see which modifier bits the Meta and
3702 Alt keysyms are on. */
3704 int row
, col
; /* The row and column in the modifier table. */
3706 for (row
= 3; row
< 8; row
++)
3707 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3710 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3712 /* Zeroes are used for filler. Skip them. */
3716 /* Are any of this keycode's keysyms a meta key? */
3720 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3722 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3728 dpyinfo
->meta_mod_mask
|= (1 << row
);
3733 dpyinfo
->alt_mod_mask
|= (1 << row
);
3738 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3743 dpyinfo
->super_mod_mask
|= (1 << row
);
3747 /* Ignore this if it's not on the lock modifier. */
3748 if ((1 << row
) == LockMask
)
3749 dpyinfo
->shift_lock_mask
= LockMask
;
3757 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3758 if (! dpyinfo
->meta_mod_mask
)
3760 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3761 dpyinfo
->alt_mod_mask
= 0;
3764 /* If some keys are both alt and meta,
3765 make them just meta, not alt. */
3766 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3768 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3771 XFree ((char *) syms
);
3772 XFreeModifiermap (mods
);
3775 #endif /* MAC_TODO */
3777 /* Convert between the modifier bits X uses and the modifier bits
3781 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3782 struct x_display_info
*dpyinfo
;
3783 unsigned short state
;
3785 return (((state
& shiftKey
) ? shift_modifier
: 0)
3786 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3787 | ((state
& cmdKey
) ? meta_modifier
: 0)
3788 | ((state
& optionKey
) ? alt_modifier
: 0));
3791 #if 0 /* MAC_TODO */
3792 static unsigned short
3793 x_emacs_to_x_modifiers (dpyinfo
, state
)
3794 struct x_display_info
*dpyinfo
;
3797 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3798 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3799 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3800 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3801 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3802 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3804 #endif /* MAC_TODO */
3806 /* Convert a keysym to its name. */
3809 x_get_keysym_name (keysym
)
3816 value
= XKeysymToString (keysym
);
3828 /* Mouse clicks and mouse movement. Rah. */
3830 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3832 If the event is a button press, then note that we have grabbed
3836 construct_mouse_click (result
, event
, f
)
3837 struct input_event
*result
;
3843 result
->kind
= MOUSE_CLICK_EVENT
;
3844 result
->code
= 0; /* only one mouse button */
3845 result
->timestamp
= event
->when
;
3846 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3848 mouseLoc
= event
->where
;
3850 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3852 GlobalToLocal (&mouseLoc
);
3853 XSETINT (result
->x
, mouseLoc
.h
);
3854 XSETINT (result
->y
, mouseLoc
.v
);
3856 XSETFRAME (result
->frame_or_window
, f
);
3864 /* Function to report a mouse movement to the mainstream Emacs code.
3865 The input handler calls this.
3867 We have received a mouse movement event, which is given in *event.
3868 If the mouse is over a different glyph than it was last time, tell
3869 the mainstream emacs code by setting mouse_moved. If not, ask for
3870 another motion event, so we can check again the next time it moves. */
3872 static Point last_mouse_motion_position
;
3873 static Lisp_Object last_mouse_motion_frame
;
3876 note_mouse_movement (frame
, pos
)
3880 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3881 #if TARGET_API_MAC_CARBON
3885 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3886 last_mouse_motion_position
= *pos
;
3887 XSETFRAME (last_mouse_motion_frame
, frame
);
3889 #if TARGET_API_MAC_CARBON
3890 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3892 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3895 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3896 /* This case corresponds to LeaveNotify in X11. */
3898 /* If we move outside the frame, then we're certainly no
3899 longer on any text in the frame. */
3900 clear_mouse_face (dpyinfo
);
3901 dpyinfo
->mouse_face_mouse_frame
= 0;
3902 if (!dpyinfo
->grabbed
)
3903 rif
->define_frame_cursor (frame
,
3904 frame
->output_data
.mac
->nontext_cursor
);
3907 /* Has the mouse moved off the glyph it was on at the last sighting? */
3908 else if (pos
->h
< last_mouse_glyph
.left
3909 || pos
->h
>= last_mouse_glyph
.right
3910 || pos
->v
< last_mouse_glyph
.top
3911 || pos
->v
>= last_mouse_glyph
.bottom
)
3913 frame
->mouse_moved
= 1;
3914 last_mouse_scroll_bar
= Qnil
;
3915 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3919 /* This is used for debugging, to turn off note_mouse_highlight. */
3921 int disable_mouse_highlight
;
3925 /************************************************************************
3927 ************************************************************************/
3929 static struct scroll_bar
*x_window_to_scroll_bar ();
3930 static void x_scroll_bar_report_motion ();
3931 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3934 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3937 redo_mouse_highlight ()
3939 if (!NILP (last_mouse_motion_frame
)
3940 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3941 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3942 last_mouse_motion_position
.h
,
3943 last_mouse_motion_position
.v
);
3947 /* Try to determine frame pixel position and size of the glyph under
3948 frame pixel coordinates X/Y on frame F . Return the position and
3949 size in *RECT. Value is non-zero if we could compute these
3953 glyph_rect (f
, x
, y
, rect
)
3960 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3964 struct window
*w
= XWINDOW (window
);
3965 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3966 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3968 for (; r
< end
&& r
->enabled_p
; ++r
)
3969 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3971 /* Found the row at y. */
3972 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3973 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3976 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3977 rect
->bottom
= rect
->top
+ r
->height
;
3981 /* x is to the left of the first glyph in the row. */
3982 /* Shouldn't this be a pixel value?
3983 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3985 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3986 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3990 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3991 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3993 /* x is on a glyph. */
3994 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3995 rect
->right
= rect
->left
+ g
->pixel_width
;
3999 /* x is to the right of the last glyph in the row. */
4000 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
4001 /* Shouldn't this be a pixel value?
4002 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
4004 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
4009 /* The y is not on any row. */
4013 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4015 /* Record the position of the mouse in last_mouse_glyph. */
4017 remember_mouse_glyph (f1
, gx
, gy
)
4021 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
4023 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
4024 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
4026 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
4027 round down even for negative values. */
4033 /* This was the original code from XTmouse_position, but it seems
4034 to give the position of the glyph diagonally next to the one
4035 the mouse is over. */
4036 gx
= (gx
+ width
- 1) / width
* width
;
4037 gy
= (gy
+ height
- 1) / height
* height
;
4039 gx
= gx
/ width
* width
;
4040 gy
= gy
/ height
* height
;
4043 last_mouse_glyph
.left
= gx
;
4044 last_mouse_glyph
.top
= gy
;
4045 last_mouse_glyph
.right
= gx
+ width
;
4046 last_mouse_glyph
.bottom
= gy
+ height
;
4051 static struct frame
*
4052 mac_focus_frame (dpyinfo
)
4053 struct mac_display_info
*dpyinfo
;
4055 if (dpyinfo
->x_focus_frame
)
4056 return dpyinfo
->x_focus_frame
;
4058 /* Mac version may get events, such as a menu bar click, even when
4059 all the frames are invisible. In this case, we regard the
4060 event came to the selected frame. */
4061 return SELECTED_FRAME ();
4065 /* Return the current position of the mouse.
4066 *fp should be a frame which indicates which display to ask about.
4068 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4069 and *part to the frame, window, and scroll bar part that the mouse
4070 is over. Set *x and *y to the portion and whole of the mouse's
4071 position on the scroll bar.
4073 If the mouse movement started elsewhere, set *fp to the frame the
4074 mouse is on, *bar_window to nil, and *x and *y to the character cell
4077 Set *time to the server time-stamp for the time at which the mouse
4078 was at this position.
4080 Don't store anything if we don't have a valid set of values to report.
4082 This clears the mouse_moved flag, so we can wait for the next mouse
4086 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4089 Lisp_Object
*bar_window
;
4090 enum scroll_bar_part
*part
;
4092 unsigned long *time
;
4095 int ignore1
, ignore2
;
4096 struct frame
*f
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4097 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
4098 Lisp_Object frame
, tail
;
4102 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4103 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4106 /* Clear the mouse-moved flag for every frame on this display. */
4107 FOR_EACH_FRAME (tail
, frame
)
4108 XFRAME (frame
)->mouse_moved
= 0;
4110 last_mouse_scroll_bar
= Qnil
;
4112 SetPortWindowPort (wp
);
4114 GetMouse (&mouse_pos
);
4116 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4117 &last_mouse_glyph
, insist
);
4120 *part
= scroll_bar_handle
;
4122 XSETINT (*x
, mouse_pos
.h
);
4123 XSETINT (*y
, mouse_pos
.v
);
4124 *time
= last_mouse_movement_time
;
4131 /************************************************************************
4133 ************************************************************************/
4135 #ifdef USE_TOOLKIT_SCROLL_BARS
4137 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4138 static OSStatus install_scroll_bar_timer
P_ ((void));
4139 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4140 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4141 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4143 struct input_event
*));
4144 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4146 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4149 struct input_event
*));
4150 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4152 struct input_event
*));
4153 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4154 Point
, unsigned long,
4155 struct input_event
*));
4156 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4159 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4161 static int last_scroll_bar_part
;
4163 static EventLoopTimerRef scroll_bar_timer
;
4165 static int scroll_bar_timer_event_posted_p
;
4167 #define SCROLL_BAR_FIRST_DELAY 0.5
4168 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4171 scroll_bar_timer_callback (timer
, data
)
4172 EventLoopTimerRef timer
;
4175 EventRef event
= NULL
;
4178 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4179 kEventAttributeNone
, &event
);
4184 GetMouse (&mouse_pos
);
4185 LocalToGlobal (&mouse_pos
);
4186 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4187 sizeof (Point
), &mouse_pos
);
4191 UInt32 modifiers
= GetCurrentKeyModifiers ();
4193 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4194 sizeof (UInt32
), &modifiers
);
4197 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4198 kEventPriorityStandard
);
4200 scroll_bar_timer_event_posted_p
= 1;
4203 ReleaseEvent (event
);
4207 install_scroll_bar_timer ()
4209 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4211 if (scroll_bar_timer_callbackUPP
== NULL
)
4212 scroll_bar_timer_callbackUPP
=
4213 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4215 if (scroll_bar_timer
== NULL
)
4216 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4217 kEventDurationForever as delays. */
4219 InstallEventLoopTimer (GetCurrentEventLoop (),
4220 kEventDurationForever
, kEventDurationForever
,
4221 scroll_bar_timer_callbackUPP
, NULL
,
4226 set_scroll_bar_timer (delay
)
4227 EventTimerInterval delay
;
4229 if (scroll_bar_timer
== NULL
)
4230 install_scroll_bar_timer ();
4232 scroll_bar_timer_event_posted_p
= 0;
4234 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4238 control_part_code_to_scroll_bar_part (part_code
)
4239 ControlPartCode part_code
;
4243 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4244 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4245 case kControlPageUpPart
: return scroll_bar_above_handle
;
4246 case kControlPageDownPart
: return scroll_bar_below_handle
;
4247 case kControlIndicatorPart
: return scroll_bar_handle
;
4254 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
)
4255 struct scroll_bar
*bar
;
4257 unsigned long timestamp
;
4258 struct input_event
*bufp
;
4260 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4261 bufp
->frame_or_window
= bar
->window
;
4265 bufp
->timestamp
= timestamp
;
4266 XSETINT (bufp
->x
, 0);
4267 XSETINT (bufp
->y
, 0);
4268 bufp
->modifiers
= 0;
4272 get_control_part_bounds (ch
, part_code
, rect
)
4274 ControlPartCode part_code
;
4277 RgnHandle region
= NewRgn ();
4280 err
= GetControlRegion (ch
, part_code
, region
);
4282 GetRegionBounds (region
, rect
);
4283 DisposeRgn (region
);
4289 x_scroll_bar_handle_press (bar
, part_code
, timestamp
, bufp
)
4290 struct scroll_bar
*bar
;
4291 ControlPartCode part_code
;
4292 unsigned long timestamp
;
4293 struct input_event
*bufp
;
4295 int part
= control_part_code_to_scroll_bar_part (part_code
);
4300 if (part
!= scroll_bar_handle
)
4302 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
);
4303 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4304 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4307 last_scroll_bar_part
= part
;
4308 bar
->dragging
= Qnil
;
4309 tracked_scroll_bar
= bar
;
4313 x_scroll_bar_handle_release (bar
, timestamp
, bufp
)
4314 struct scroll_bar
*bar
;
4315 unsigned long timestamp
;
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
, timestamp
, 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
, timestamp
, bufp
)
4333 struct scroll_bar
*bar
;
4335 unsigned long timestamp
;
4336 struct input_event
*bufp
;
4338 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4340 if (last_scroll_bar_part
== scroll_bar_handle
)
4345 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4346 kControlIndicatorPart
, &r
);
4348 if (GC_NILP (bar
->dragging
))
4349 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4351 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4352 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4353 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4358 if (top
> top_range
)
4361 construct_scroll_bar_click (bar
, scroll_bar_handle
, timestamp
, bufp
);
4362 XSETINT (bufp
->x
, top
);
4363 XSETINT (bufp
->y
, top_range
);
4367 ControlPartCode part_code
;
4368 int unhilite_p
= 0, part
;
4370 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4374 part
= control_part_code_to_scroll_bar_part (part_code
);
4376 switch (last_scroll_bar_part
)
4378 case scroll_bar_above_handle
:
4379 case scroll_bar_below_handle
:
4380 if (part
!= scroll_bar_above_handle
4381 && part
!= scroll_bar_below_handle
)
4385 case scroll_bar_up_arrow
:
4386 case scroll_bar_down_arrow
:
4387 if (part
!= scroll_bar_up_arrow
4388 && part
!= scroll_bar_down_arrow
)
4395 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4396 else if (part
!= last_scroll_bar_part
4397 || scroll_bar_timer_event_posted_p
)
4399 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
);
4400 last_scroll_bar_part
= part
;
4401 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4402 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4407 /* Set the thumb size and position of scroll bar BAR. We are currently
4408 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4411 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4412 struct scroll_bar
*bar
;
4413 int portion
, position
, whole
;
4415 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4417 int value
, viewsize
, maximum
;
4419 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4420 value
= 0, viewsize
= 1, maximum
= 0;
4425 maximum
= max (0, whole
- portion
);
4430 SetControl32BitMinimum (ch
, 0);
4431 SetControl32BitMaximum (ch
, maximum
);
4432 SetControl32BitValue (ch
, value
);
4433 SetControlViewSize (ch
, viewsize
);
4438 #endif /* USE_TOOLKIT_SCROLL_BARS */
4442 /************************************************************************
4443 Scroll bars, general
4444 ************************************************************************/
4446 /* Create a scroll bar and return the scroll bar vector for it. W is
4447 the Emacs window on which to create the scroll bar. TOP, LEFT,
4448 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4451 static struct scroll_bar
*
4452 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4454 int top
, left
, width
, height
, disp_top
, disp_height
;
4456 struct frame
*f
= XFRAME (w
->frame
);
4457 struct scroll_bar
*bar
4458 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4466 r
.right
= left
+ width
;
4467 r
.bottom
= disp_top
+ disp_height
;
4469 #if TARGET_API_MAC_CARBON
4470 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4471 kControlScrollBarProc
, (long) bar
);
4473 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4474 scrollBarProc
, (long) bar
);
4476 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4478 XSETWINDOW (bar
->window
, w
);
4479 XSETINT (bar
->top
, top
);
4480 XSETINT (bar
->left
, left
);
4481 XSETINT (bar
->width
, width
);
4482 XSETINT (bar
->height
, height
);
4483 XSETINT (bar
->start
, 0);
4484 XSETINT (bar
->end
, 0);
4485 bar
->dragging
= Qnil
;
4486 #ifdef USE_TOOLKIT_SCROLL_BARS
4487 bar
->track_top
= Qnil
;
4488 bar
->track_height
= Qnil
;
4491 /* Add bar to its frame's list of scroll bars. */
4492 bar
->next
= FRAME_SCROLL_BARS (f
);
4494 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4495 if (!NILP (bar
->next
))
4496 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4503 /* Draw BAR's handle in the proper position.
4505 If the handle is already drawn from START to END, don't bother
4506 redrawing it, unless REBUILD is non-zero; in that case, always
4507 redraw it. (REBUILD is handy for drawing the handle after expose
4510 Normally, we want to constrain the start and end of the handle to
4511 fit inside its rectangle, but if the user is dragging the scroll
4512 bar handle, we want to let them drag it down all the way, so that
4513 the bar's top is as far down as it goes; otherwise, there's no way
4514 to move to the very end of the buffer. */
4516 #ifndef USE_TOOLKIT_SCROLL_BARS
4519 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4520 struct scroll_bar
*bar
;
4524 int dragging
= ! NILP (bar
->dragging
);
4525 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4526 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4527 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4528 int length
= end
- start
;
4530 /* If the display is already accurate, do nothing. */
4532 && start
== XINT (bar
->start
)
4533 && end
== XINT (bar
->end
))
4538 /* Make sure the values are reasonable, and try to preserve the
4539 distance between start and end. */
4542 else if (start
> top_range
)
4544 end
= start
+ length
;
4548 else if (end
> top_range
&& ! dragging
)
4551 /* Store the adjusted setting in the scroll bar. */
4552 XSETINT (bar
->start
, start
);
4553 XSETINT (bar
->end
, end
);
4555 /* Clip the end position, just for display. */
4556 if (end
> top_range
)
4559 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4560 top positions, to make sure the handle is always at least that
4561 many pixels tall. */
4562 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4564 SetControlMinimum (ch
, 0);
4565 /* Don't inadvertently activate deactivated scroll bars */
4566 if (GetControlMaximum (ch
) != -1)
4567 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4569 SetControlValue (ch
, start
);
4570 #if TARGET_API_MAC_CARBON
4571 SetControlViewSize (ch
, end
- start
);
4577 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4579 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4583 x_scroll_bar_remove (bar
)
4584 struct scroll_bar
*bar
;
4586 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4590 /* Destroy the Mac scroll bar control */
4591 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4593 /* Disassociate this scroll bar from its window. */
4594 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,
4604 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4606 int portion
, whole
, position
;
4608 struct frame
*f
= XFRAME (w
->frame
);
4609 struct scroll_bar
*bar
;
4610 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4611 int window_y
, window_height
;
4613 /* Get window dimensions. */
4614 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4616 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4617 height
= window_height
;
4619 /* Compute the left edge of the scroll bar area. */
4620 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4622 /* Compute the width of the scroll bar which might be less than
4623 the width of the area reserved for the scroll bar. */
4624 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4625 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4629 /* Compute the left edge of the scroll bar. */
4630 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4633 sb_left
= left
+ width
- sb_width
;
4635 /* Adjustments according to Inside Macintosh to make it look nice */
4637 disp_height
= height
;
4643 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4649 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4652 /* Does the scroll bar exist yet? */
4653 if (NILP (w
->vertical_scroll_bar
))
4656 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4657 left
, top
, width
, height
, 0);
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 /* Clear areas not covered by the scroll bar because it's not as
4680 wide as the area reserved for it . This makes sure a
4681 previous mode line display is cleared after C-x 2 C-x 1, for
4683 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4684 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4685 left
, top
, area_width
, height
, 0);
4688 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4689 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4690 sb_left
- 1, top
, 1, height
, 0);
4694 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4695 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4699 /* Remember new settings. */
4700 XSETINT (bar
->left
, sb_left
);
4701 XSETINT (bar
->top
, top
);
4702 XSETINT (bar
->width
, sb_width
);
4703 XSETINT (bar
->height
, height
);
4704 #ifdef USE_TOOLKIT_SCROLL_BARS
4705 bar
->track_top
= Qnil
;
4706 bar
->track_height
= Qnil
;
4713 #ifdef USE_TOOLKIT_SCROLL_BARS
4714 if (NILP (bar
->track_top
))
4716 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4721 SetControl32BitMinimum (ch
, 0);
4722 SetControl32BitMaximum (ch
, 1);
4723 SetControlViewSize (ch
, 1);
4725 /* Move the scroll bar thumb to the top. */
4726 SetControl32BitValue (ch
, 0);
4727 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4729 /* Move the scroll bar thumb to the bottom. */
4730 SetControl32BitValue (ch
, 1);
4731 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4733 UnionRect (&r0
, &r1
, &r0
);
4734 XSETINT (bar
->track_top
, r0
.top
);
4735 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4740 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4741 #else /* not USE_TOOLKIT_SCROLL_BARS */
4742 /* Set the scroll bar's current state, unless we're currently being
4744 if (NILP (bar
->dragging
))
4746 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4749 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4752 int start
= ((double) position
* top_range
) / whole
;
4753 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4754 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4757 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4761 /* The following three hooks are used when we're doing a thorough
4762 redisplay of the frame. We don't explicitly know which scroll bars
4763 are going to be deleted, because keeping track of when windows go
4764 away is a real pain - "Can you say set-window-configuration, boys
4765 and girls?" Instead, we just assert at the beginning of redisplay
4766 that *all* scroll bars are to be removed, and then save a scroll bar
4767 from the fiery pit when we actually redisplay its window. */
4769 /* Arrange for all scroll bars on FRAME to be removed at the next call
4770 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4771 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4774 XTcondemn_scroll_bars (frame
)
4777 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4778 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4781 bar
= FRAME_SCROLL_BARS (frame
);
4782 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4783 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4784 XSCROLL_BAR (bar
)->prev
= Qnil
;
4785 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4786 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4787 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4792 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4793 Note that WINDOW isn't necessarily condemned at all. */
4796 XTredeem_scroll_bar (window
)
4797 struct window
*window
;
4799 struct scroll_bar
*bar
;
4801 /* We can't redeem this window's scroll bar if it doesn't have one. */
4802 if (NILP (window
->vertical_scroll_bar
))
4805 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4807 /* Unlink it from the condemned list. */
4809 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4811 if (NILP (bar
->prev
))
4813 /* If the prev pointer is nil, it must be the first in one of
4815 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4816 /* It's not condemned. Everything's fine. */
4818 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4819 window
->vertical_scroll_bar
))
4820 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4822 /* If its prev pointer is nil, it must be at the front of
4823 one or the other! */
4827 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4829 if (! NILP (bar
->next
))
4830 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4832 bar
->next
= FRAME_SCROLL_BARS (f
);
4834 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4835 if (! NILP (bar
->next
))
4836 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4840 /* Remove all scroll bars on FRAME that haven't been saved since the
4841 last call to `*condemn_scroll_bars_hook'. */
4844 XTjudge_scroll_bars (f
)
4847 Lisp_Object bar
, next
;
4849 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4851 /* Clear out the condemned list now so we won't try to process any
4852 more events on the hapless scroll bars. */
4853 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4855 for (; ! NILP (bar
); bar
= next
)
4857 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4859 x_scroll_bar_remove (b
);
4862 b
->next
= b
->prev
= Qnil
;
4865 /* Now there should be no references to the condemned scroll bars,
4866 and they should get garbage-collected. */
4870 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4871 is set to something other than NO_EVENT, it is enqueued.
4873 This may be called from a signal handler, so we have to ignore GC
4877 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4878 struct scroll_bar
*bar
;
4879 ControlPartCode part_code
;
4881 struct input_event
*bufp
;
4883 int win_y
, top_range
;
4885 if (! GC_WINDOWP (bar
->window
))
4888 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4889 bufp
->frame_or_window
= bar
->window
;
4892 bar
->dragging
= Qnil
;
4896 case kControlUpButtonPart
:
4897 bufp
->part
= scroll_bar_up_arrow
;
4899 case kControlDownButtonPart
:
4900 bufp
->part
= scroll_bar_down_arrow
;
4902 case kControlPageUpPart
:
4903 bufp
->part
= scroll_bar_above_handle
;
4905 case kControlPageDownPart
:
4906 bufp
->part
= scroll_bar_below_handle
;
4908 #if TARGET_API_MAC_CARBON
4911 case kControlIndicatorPart
:
4913 if (er
->what
== mouseDown
)
4914 bar
->dragging
= make_number (0);
4915 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4916 bufp
->part
= scroll_bar_handle
;
4920 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4921 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4923 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4927 if (! NILP (bar
->dragging
))
4928 win_y
-= XINT (bar
->dragging
);
4932 if (win_y
> top_range
)
4935 XSETINT (bufp
->x
, win_y
);
4936 XSETINT (bufp
->y
, top_range
);
4939 #ifndef USE_TOOLKIT_SCROLL_BARS
4941 /* Handle some mouse motion while someone is dragging the scroll bar.
4943 This may be called from a signal handler, so we have to ignore GC
4947 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4948 struct scroll_bar
*bar
;
4952 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4954 last_mouse_movement_time
= t
;
4957 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4959 /* If we're dragging the bar, display it. */
4960 if (! GC_NILP (bar
->dragging
))
4962 /* Where should the handle be now? */
4963 int new_start
= y_pos
- 24;
4965 if (new_start
!= XINT (bar
->start
))
4967 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4969 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4974 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4976 /* Return information to the user about the current position of the
4977 mouse on the scroll bar. */
4980 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4982 Lisp_Object
*bar_window
;
4983 enum scroll_bar_part
*part
;
4985 unsigned long *time
;
4987 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4988 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4989 #if TARGET_API_MAC_CARBON
4990 WindowPtr wp
= GetControlOwner (ch
);
4992 WindowPtr wp
= (*ch
)->contrlOwner
;
4995 struct frame
*f
= mac_window_to_frame (wp
);
4996 int win_y
, top_range
;
4998 SetPortWindowPort (wp
);
5000 GetMouse (&mouse_pos
);
5002 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5003 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5005 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5009 if (! NILP (bar
->dragging
))
5010 win_y
-= XINT (bar
->dragging
);
5014 if (win_y
> top_range
)
5018 *bar_window
= bar
->window
;
5020 if (! NILP (bar
->dragging
))
5021 *part
= scroll_bar_handle
;
5022 else if (win_y
< XINT (bar
->start
))
5023 *part
= scroll_bar_above_handle
;
5024 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5025 *part
= scroll_bar_handle
;
5027 *part
= scroll_bar_below_handle
;
5029 XSETINT (*x
, win_y
);
5030 XSETINT (*y
, top_range
);
5033 last_mouse_scroll_bar
= Qnil
;
5035 *time
= last_mouse_movement_time
;
5039 /* The screen has been cleared so we may have changed foreground or
5040 background colors, and the scroll bars may need to be redrawn.
5041 Clear out the scroll bars, and ask for expose events, so we can
5045 x_scroll_bar_clear (f
)
5048 XTcondemn_scroll_bars (f
);
5049 XTjudge_scroll_bars (f
);
5053 /***********************************************************************
5055 ***********************************************************************/
5057 /* Set clipping for output in glyph row ROW. W is the window in which
5058 we operate. GC is the graphics context to set clipping in.
5060 ROW may be a text row or, e.g., a mode line. Text rows must be
5061 clipped to the interior of the window dedicated to text display,
5062 mode lines must be clipped to the whole window. */
5065 x_clip_to_row (w
, row
, area
, gc
)
5067 struct glyph_row
*row
;
5071 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5073 int window_x
, window_y
, window_width
;
5075 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5077 clip_rect
.left
= window_x
;
5078 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5079 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5080 clip_rect
.right
= clip_rect
.left
+ window_width
;
5081 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5083 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
5087 /* Draw a hollow box cursor on window W in glyph row ROW. */
5090 x_draw_hollow_cursor (w
, row
)
5092 struct glyph_row
*row
;
5094 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5095 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5096 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5099 struct glyph
*cursor_glyph
;
5102 /* Get the glyph the cursor is on. If we can't tell because
5103 the current matrix is invalid or such, give up. */
5104 cursor_glyph
= get_phys_cursor_glyph (w
);
5105 if (cursor_glyph
== NULL
)
5108 /* Compute frame-relative coordinates for phys cursor. */
5109 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5110 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5111 wd
= w
->phys_cursor_width
;
5113 /* The foreground of cursor_gc is typically the same as the normal
5114 background color, which can cause the cursor box to be invisible. */
5115 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5116 if (dpyinfo
->scratch_cursor_gc
)
5117 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5119 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5120 GCForeground
, &xgcv
);
5121 gc
= dpyinfo
->scratch_cursor_gc
;
5123 /* Set clipping, draw the rectangle, and reset clipping again. */
5124 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5125 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
5126 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5130 /* Draw a bar cursor on window W in glyph row ROW.
5132 Implementation note: One would like to draw a bar cursor with an
5133 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5134 Unfortunately, I didn't find a font yet that has this property set.
5138 x_draw_bar_cursor (w
, row
, width
, kind
)
5140 struct glyph_row
*row
;
5142 enum text_cursor_kinds kind
;
5144 struct frame
*f
= XFRAME (w
->frame
);
5145 struct glyph
*cursor_glyph
;
5147 /* If cursor is out of bounds, don't draw garbage. This can happen
5148 in mini-buffer windows when switching between echo area glyphs
5150 cursor_glyph
= get_phys_cursor_glyph (w
);
5151 if (cursor_glyph
== NULL
)
5154 /* If on an image, draw like a normal cursor. That's usually better
5155 visible than drawing a bar, esp. if the image is large so that
5156 the bar might not be in the window. */
5157 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5159 struct glyph_row
*row
;
5160 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5161 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5165 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5166 Window window
= FRAME_MAC_WINDOW (f
);
5167 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5168 unsigned long mask
= GCForeground
| GCBackground
;
5169 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5172 /* If the glyph's background equals the color we normally draw
5173 the bar cursor in, the bar cursor in its normal color is
5174 invisible. Use the glyph's foreground color instead in this
5175 case, on the assumption that the glyph's colors are chosen so
5176 that the glyph is legible. */
5177 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5178 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5180 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5183 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5186 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5187 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5191 width
= FRAME_CURSOR_WIDTH (f
);
5192 width
= min (cursor_glyph
->pixel_width
, width
);
5194 w
->phys_cursor_width
= width
;
5195 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5197 if (kind
== BAR_CURSOR
)
5198 XFillRectangle (dpy
, window
, gc
,
5199 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5200 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5201 width
, row
->height
);
5203 XFillRectangle (dpy
, window
, gc
,
5204 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5205 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5206 row
->height
- width
),
5207 cursor_glyph
->pixel_width
,
5210 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5215 /* RIF: Define cursor CURSOR on frame F. */
5218 mac_define_frame_cursor (f
, cursor
)
5222 SetThemeCursor (cursor
);
5226 /* RIF: Clear area on frame F. */
5229 mac_clear_frame_area (f
, x
, y
, width
, height
)
5231 int x
, y
, width
, height
;
5233 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5234 x
, y
, width
, height
, 0);
5238 /* RIF: Draw cursor on window W. */
5241 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5243 struct glyph_row
*glyph_row
;
5245 int cursor_type
, cursor_width
;
5250 w
->phys_cursor_type
= cursor_type
;
5251 w
->phys_cursor_on_p
= 1;
5253 if (glyph_row
->exact_window_width_line_p
5254 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5256 glyph_row
->cursor_in_fringe_p
= 1;
5257 draw_fringe_bitmap (w
, glyph_row
, 0);
5260 switch (cursor_type
)
5262 case HOLLOW_BOX_CURSOR
:
5263 x_draw_hollow_cursor (w
, glyph_row
);
5266 case FILLED_BOX_CURSOR
:
5267 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5271 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5275 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5279 w
->phys_cursor_width
= 0;
5291 #if 0 /* MAC_TODO: no icon support yet. */
5293 x_bitmap_icon (f
, icon
)
5299 if (FRAME_W32_WINDOW (f
) == 0)
5303 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5304 else if (STRINGP (icon
))
5305 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5306 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5307 else if (SYMBOLP (icon
))
5311 if (EQ (icon
, intern ("application")))
5312 name
= (LPCTSTR
) IDI_APPLICATION
;
5313 else if (EQ (icon
, intern ("hand")))
5314 name
= (LPCTSTR
) IDI_HAND
;
5315 else if (EQ (icon
, intern ("question")))
5316 name
= (LPCTSTR
) IDI_QUESTION
;
5317 else if (EQ (icon
, intern ("exclamation")))
5318 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5319 else if (EQ (icon
, intern ("asterisk")))
5320 name
= (LPCTSTR
) IDI_ASTERISK
;
5321 else if (EQ (icon
, intern ("winlogo")))
5322 name
= (LPCTSTR
) IDI_WINLOGO
;
5326 hicon
= LoadIcon (NULL
, name
);
5334 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5339 #endif /* MAC_TODO */
5341 /************************************************************************
5343 ************************************************************************/
5345 /* Display Error Handling functions not used on W32. Listing them here
5346 helps diff stay in step when comparing w32term.c with xterm.c.
5348 x_error_catcher (display, error)
5349 x_catch_errors (dpy)
5350 x_catch_errors_unwind (old_val)
5351 x_check_errors (dpy, format)
5352 x_had_errors_p (dpy)
5353 x_clear_errors (dpy)
5354 x_uncatch_errors (dpy, count)
5356 x_connection_signal (signalnum)
5357 x_connection_closed (dpy, error_message)
5358 x_error_quitter (display, error)
5359 x_error_handler (display, error)
5360 x_io_error_quitter (display)
5365 /* Changing the font of the frame. */
5367 /* Give frame F the font named FONTNAME as its default font, and
5368 return the full name of that font. FONTNAME may be a wildcard
5369 pattern; in that case, we choose some font that fits the pattern.
5370 The return value shows which font we chose. */
5373 x_new_font (f
, fontname
)
5375 register char *fontname
;
5377 struct font_info
*fontp
5378 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5383 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5384 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5385 FRAME_FONTSET (f
) = -1;
5387 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5388 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5389 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5391 compute_fringe_widths (f
, 1);
5393 /* Compute the scroll bar width in character columns. */
5394 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5396 int wid
= FRAME_COLUMN_WIDTH (f
);
5397 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5398 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5402 int wid
= FRAME_COLUMN_WIDTH (f
);
5403 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5406 /* Now make the frame display the given font. */
5407 if (FRAME_MAC_WINDOW (f
) != 0)
5409 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5411 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5413 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5416 /* Don't change the size of a tip frame; there's no point in
5417 doing it because it's done in Fx_show_tip, and it leads to
5418 problems because the tip frame has no widget. */
5419 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5420 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5423 return build_string (fontp
->full_name
);
5426 /* Give frame F the fontset named FONTSETNAME as its default font, and
5427 return the full name of that fontset. FONTSETNAME may be a wildcard
5428 pattern; in that case, we choose some fontset that fits the pattern.
5429 The return value shows which fontset we chose. */
5432 x_new_fontset (f
, fontsetname
)
5436 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5442 if (FRAME_FONTSET (f
) == fontset
)
5443 /* This fontset is already set in frame F. There's nothing more
5445 return fontset_name (fontset
);
5447 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5449 if (!STRINGP (result
))
5450 /* Can't load ASCII font. */
5453 /* Since x_new_font doesn't update any fontset information, do it now. */
5454 FRAME_FONTSET (f
) = fontset
;
5456 return build_string (fontsetname
);
5460 /***********************************************************************
5461 TODO: W32 Input Methods
5462 ***********************************************************************/
5463 /* Listing missing functions from xterm.c helps diff stay in step.
5465 xim_destroy_callback (xim, client_data, call_data)
5466 xim_open_dpy (dpyinfo, resource_name)
5468 xim_instantiate_callback (display, client_data, call_data)
5469 xim_initialize (dpyinfo, resource_name)
5470 xim_close_dpy (dpyinfo)
5476 mac_get_window_bounds (f
, inner
, outer
)
5478 Rect
*inner
, *outer
;
5480 #if TARGET_API_MAC_CARBON
5481 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5482 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5483 #else /* not TARGET_API_MAC_CARBON */
5484 RgnHandle region
= NewRgn ();
5486 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5487 *inner
= (*region
)->rgnBBox
;
5488 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5489 *outer
= (*region
)->rgnBBox
;
5490 DisposeRgn (region
);
5491 #endif /* not TARGET_API_MAC_CARBON */
5495 /* Calculate the absolute position in frame F
5496 from its current recorded position values and gravity. */
5499 x_calc_absolute_position (f
)
5502 int width_diff
= 0, height_diff
= 0;
5503 int flags
= f
->size_hint_flags
;
5506 /* We have nothing to do if the current position
5507 is already for the top-left corner. */
5508 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5511 /* Find the offsets of the outside upper-left corner of
5512 the inner window, with respect to the outer window. */
5513 mac_get_window_bounds (f
, &inner
, &outer
);
5515 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5516 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5518 /* Treat negative positions as relative to the leftmost bottommost
5519 position that fits on the screen. */
5520 if (flags
& XNegative
)
5521 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5523 - FRAME_PIXEL_WIDTH (f
)
5526 if (flags
& YNegative
)
5527 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5529 - FRAME_PIXEL_HEIGHT (f
)
5532 /* The left_pos and top_pos
5533 are now relative to the top and left screen edges,
5534 so the flags should correspond. */
5535 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5538 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5539 to really change the position, and 0 when calling from
5540 x_make_frame_visible (in that case, XOFF and YOFF are the current
5541 position values). It is -1 when calling from x_set_frame_parameters,
5542 which means, do adjust for borders but don't change the gravity. */
5545 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5547 register int xoff
, yoff
;
5550 if (change_gravity
> 0)
5554 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5556 f
->size_hint_flags
|= XNegative
;
5558 f
->size_hint_flags
|= YNegative
;
5559 f
->win_gravity
= NorthWestGravity
;
5561 x_calc_absolute_position (f
);
5564 x_wm_set_size_hint (f
, (long) 0, 0);
5566 #if TARGET_API_MAC_CARBON
5567 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5568 /* If the title bar is completely outside the screen, adjust the
5570 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5571 kWindowConstrainMoveRegardlessOfFit
5572 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5573 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5576 Rect inner
, outer
, screen_rect
, dummy
;
5577 RgnHandle region
= NewRgn ();
5579 mac_get_window_bounds (f
, &inner
, &outer
);
5580 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5581 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5582 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5583 f
->top_pos
+ f
->y_pixels_diff
, false);
5585 /* If the title bar is completely outside the screen, adjust the
5586 position. The variable `outer' holds the title bar rectangle.
5587 The variable `inner' holds slightly smaller one than `outer',
5588 so that the calculation of overlapping may not become too
5590 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5591 outer
= (*region
)->rgnBBox
;
5592 DisposeRgn (region
);
5594 InsetRect (&inner
, 8, 8);
5595 screen_rect
= qd
.screenBits
.bounds
;
5596 screen_rect
.top
+= GetMBarHeight ();
5598 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5600 if (inner
.right
<= screen_rect
.left
)
5601 f
->left_pos
= screen_rect
.left
;
5602 else if (inner
.left
>= screen_rect
.right
)
5603 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5605 if (inner
.bottom
<= screen_rect
.top
)
5606 f
->top_pos
= screen_rect
.top
;
5607 else if (inner
.top
>= screen_rect
.bottom
)
5608 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5610 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5611 f
->top_pos
+ f
->y_pixels_diff
, false);
5619 /* Call this to change the size of frame F's x-window.
5620 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5621 for this size change and subsequent size changes.
5622 Otherwise we leave the window gravity unchanged. */
5625 x_set_window_size (f
, change_gravity
, cols
, rows
)
5630 int pixelwidth
, pixelheight
;
5634 check_frame_size (f
, &rows
, &cols
);
5635 f
->scroll_bar_actual_width
5636 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5638 compute_fringe_widths (f
, 0);
5640 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5641 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5643 f
->win_gravity
= NorthWestGravity
;
5644 x_wm_set_size_hint (f
, (long) 0, 0);
5646 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5647 #if TARGET_API_MAC_CARBON
5648 if (f
->output_data
.mac
->hourglass_control
)
5649 MoveControl (f
->output_data
.mac
->hourglass_control
,
5650 pixelwidth
- HOURGLASS_WIDTH
, 0);
5653 /* Now, strictly speaking, we can't be sure that this is accurate,
5654 but the window manager will get around to dealing with the size
5655 change request eventually, and we'll hear how it went when the
5656 ConfigureNotify event gets here.
5658 We could just not bother storing any of this information here,
5659 and let the ConfigureNotify event set everything up, but that
5660 might be kind of confusing to the Lisp code, since size changes
5661 wouldn't be reported in the frame parameters until some random
5662 point in the future when the ConfigureNotify event arrives.
5664 We pass 1 for DELAY since we can't run Lisp code inside of
5666 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5667 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5668 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5670 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5671 receive in the ConfigureNotify event; if we get what we asked
5672 for, then the event won't cause the screen to become garbaged, so
5673 we have to make sure to do it here. */
5674 SET_FRAME_GARBAGED (f
);
5676 XFlush (FRAME_X_DISPLAY (f
));
5678 /* If cursor was outside the new size, mark it as off. */
5679 mark_window_cursors_off (XWINDOW (f
->root_window
));
5681 /* Clear out any recollection of where the mouse highlighting was,
5682 since it might be in a place that's outside the new frame size.
5683 Actually checking whether it is outside is a pain in the neck,
5684 so don't try--just let the highlighting be done afresh with new size. */
5685 cancel_mouse_face (f
);
5690 /* Mouse warping. */
5692 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5695 x_set_mouse_position (f
, x
, y
)
5701 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5702 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5704 if (pix_x
< 0) pix_x
= 0;
5705 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5707 if (pix_y
< 0) pix_y
= 0;
5708 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5710 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5714 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5718 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5721 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5722 0, 0, 0, 0, pix_x
, pix_y
);
5728 /* focus shifting, raising and lowering. */
5731 x_focus_on_frame (f
)
5734 #if 0 /* This proves to be unpleasant. */
5738 /* I don't think that the ICCCM allows programs to do things like this
5739 without the interaction of the window manager. Whatever you end up
5740 doing with this code, do it to x_unfocus_frame too. */
5741 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5742 RevertToPointerRoot
, CurrentTime
);
5752 /* Raise frame F. */
5757 if (f
->async_visible
)
5760 SelectWindow (FRAME_MAC_WINDOW (f
));
5765 /* Lower frame F. */
5770 if (f
->async_visible
)
5773 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5779 XTframe_raise_lower (f
, raise_flag
)
5789 /* Change of visibility. */
5791 /* This tries to wait until the frame is really visible.
5792 However, if the window manager asks the user where to position
5793 the frame, this will return before the user finishes doing that.
5794 The frame will not actually be visible at that time,
5795 but it will become visible later when the window manager
5796 finishes with it. */
5799 x_make_frame_visible (f
)
5803 int original_top
, original_left
;
5807 if (! FRAME_VISIBLE_P (f
))
5809 /* We test FRAME_GARBAGED_P here to make sure we don't
5810 call x_set_offset a second time
5811 if we get to x_make_frame_visible a second time
5812 before the window gets really visible. */
5813 if (! FRAME_ICONIFIED_P (f
)
5814 && ! f
->output_data
.mac
->asked_for_visible
)
5815 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5817 f
->output_data
.mac
->asked_for_visible
= 1;
5819 #if TARGET_API_MAC_CARBON
5820 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5822 struct frame
*sf
= SELECTED_FRAME ();
5823 if (!FRAME_MAC_P (sf
))
5824 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5825 kWindowCenterOnMainScreen
);
5827 RepositionWindow (FRAME_MAC_WINDOW (f
),
5828 FRAME_MAC_WINDOW (sf
),
5829 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5830 kWindowCascadeStartAtParentWindowScreen
5832 kWindowCascadeOnParentWindowScreen
5835 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5838 ShowWindow (FRAME_MAC_WINDOW (f
));
5841 XFlush (FRAME_MAC_DISPLAY (f
));
5843 /* Synchronize to ensure Emacs knows the frame is visible
5844 before we do anything else. We do this loop with input not blocked
5845 so that incoming events are handled. */
5850 /* This must come after we set COUNT. */
5853 XSETFRAME (frame
, f
);
5855 /* Wait until the frame is visible. Process X events until a
5856 MapNotify event has been seen, or until we think we won't get a
5857 MapNotify at all.. */
5858 for (count
= input_signal_count
+ 10;
5859 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5861 /* Force processing of queued events. */
5864 /* Machines that do polling rather than SIGIO have been
5865 observed to go into a busy-wait here. So we'll fake an
5866 alarm signal to let the handler know that there's something
5867 to be read. We used to raise a real alarm, but it seems
5868 that the handler isn't always enabled here. This is
5870 if (input_polling_used ())
5872 /* It could be confusing if a real alarm arrives while
5873 processing the fake one. Turn it off and let the
5874 handler reset it. */
5875 extern void poll_for_input_1
P_ ((void));
5876 int old_poll_suppress_count
= poll_suppress_count
;
5877 poll_suppress_count
= 1;
5878 poll_for_input_1 ();
5879 poll_suppress_count
= old_poll_suppress_count
;
5882 /* See if a MapNotify event has been processed. */
5883 FRAME_SAMPLE_VISIBILITY (f
);
5888 /* Change from mapped state to withdrawn state. */
5890 /* Make the frame visible (mapped and not iconified). */
5893 x_make_frame_invisible (f
)
5896 /* Don't keep the highlight on an invisible frame. */
5897 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5898 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5902 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5903 that the current position of the window is user-specified, rather than
5904 program-specified, so that when the window is mapped again, it will be
5905 placed at the same location, without forcing the user to position it
5906 by hand again (they have already done that once for this window.) */
5907 x_wm_set_size_hint (f
, (long) 0, 1);
5909 HideWindow (FRAME_MAC_WINDOW (f
));
5911 /* We can't distinguish this from iconification
5912 just by the event that we get from the server.
5913 So we can't win using the usual strategy of letting
5914 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5915 and synchronize with the server to make sure we agree. */
5917 FRAME_ICONIFIED_P (f
) = 0;
5918 f
->async_visible
= 0;
5919 f
->async_iconified
= 0;
5924 /* Change window state from mapped to iconified. */
5930 /* Don't keep the highlight on an invisible frame. */
5931 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5932 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5935 /* Review: Since window is still visible in dock, still allow updates? */
5936 if (f
->async_iconified
)
5942 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5948 /* Free X resources of frame F. */
5951 x_free_frame_resources (f
)
5954 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5955 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5959 if (wp
!= tip_window
)
5960 remove_window_handler (wp
);
5963 if (wp
== tip_window
)
5964 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5965 closed' event. So we reset tip_window here. */
5968 free_frame_menubar (f
);
5970 if (FRAME_FACE_CACHE (f
))
5971 free_frame_faces (f
);
5975 if (FRAME_SIZE_HINTS (f
))
5976 xfree (FRAME_SIZE_HINTS (f
));
5978 xfree (f
->output_data
.mac
);
5979 f
->output_data
.mac
= NULL
;
5981 if (f
== dpyinfo
->x_focus_frame
)
5982 dpyinfo
->x_focus_frame
= 0;
5983 if (f
== dpyinfo
->x_focus_event_frame
)
5984 dpyinfo
->x_focus_event_frame
= 0;
5985 if (f
== dpyinfo
->x_highlight_frame
)
5986 dpyinfo
->x_highlight_frame
= 0;
5988 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5990 dpyinfo
->mouse_face_beg_row
5991 = dpyinfo
->mouse_face_beg_col
= -1;
5992 dpyinfo
->mouse_face_end_row
5993 = dpyinfo
->mouse_face_end_col
= -1;
5994 dpyinfo
->mouse_face_window
= Qnil
;
5995 dpyinfo
->mouse_face_deferred_gc
= 0;
5996 dpyinfo
->mouse_face_mouse_frame
= 0;
6003 /* Destroy the X window of frame F. */
6006 x_destroy_window (f
)
6009 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6011 x_free_frame_resources (f
);
6013 dpyinfo
->reference_count
--;
6017 /* Setting window manager hints. */
6019 /* Set the normal size hints for the window manager, for frame F.
6020 FLAGS is the flags word to use--or 0 meaning preserve the flags
6021 that the window now has.
6022 If USER_POSITION is nonzero, we set the USPosition
6023 flag (this is useful when FLAGS is 0). */
6025 x_wm_set_size_hint (f
, flags
, user_position
)
6030 int base_width
, base_height
, width_inc
, height_inc
;
6031 int min_rows
= 0, min_cols
= 0;
6032 XSizeHints
*size_hints
;
6034 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6035 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6036 width_inc
= FRAME_COLUMN_WIDTH (f
);
6037 height_inc
= FRAME_LINE_HEIGHT (f
);
6039 check_frame_size (f
, &min_rows
, &min_cols
);
6041 size_hints
= FRAME_SIZE_HINTS (f
);
6042 if (size_hints
== NULL
)
6044 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6045 bzero (size_hints
, sizeof (XSizeHints
));
6048 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6049 size_hints
->width_inc
= width_inc
;
6050 size_hints
->height_inc
= height_inc
;
6051 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6052 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6053 size_hints
->base_width
= base_width
;
6054 size_hints
->base_height
= base_height
;
6057 size_hints
->flags
= flags
;
6058 else if (user_position
)
6060 size_hints
->flags
&= ~ PPosition
;
6061 size_hints
->flags
|= USPosition
;
6065 #if 0 /* MAC_TODO: hide application instead of iconify? */
6066 /* Used for IconicState or NormalState */
6069 x_wm_set_window_state (f
, state
)
6073 #ifdef USE_X_TOOLKIT
6076 XtSetArg (al
[0], XtNinitialState
, state
);
6077 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6078 #else /* not USE_X_TOOLKIT */
6079 Window window
= FRAME_X_WINDOW (f
);
6081 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6082 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6084 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6085 #endif /* not USE_X_TOOLKIT */
6089 x_wm_set_icon_pixmap (f
, pixmap_id
)
6095 #ifndef USE_X_TOOLKIT
6096 Window window
= FRAME_X_WINDOW (f
);
6101 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6102 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6106 /* It seems there is no way to turn off use of an icon pixmap.
6107 The following line does it, only if no icon has yet been created,
6108 for some window managers. But with mwm it crashes.
6109 Some people say it should clear the IconPixmapHint bit in this case,
6110 but that doesn't work, and the X consortium said it isn't the
6111 right thing at all. Since there is no way to win,
6112 best to explicitly give up. */
6114 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6120 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6124 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6125 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6128 #else /* not USE_X_TOOLKIT */
6130 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6131 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6133 #endif /* not USE_X_TOOLKIT */
6136 #endif /* MAC_TODO */
6139 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6143 #if 0 /* MAC_TODO: no icons on Mac */
6144 #ifdef USE_X_TOOLKIT
6145 Window window
= XtWindow (f
->output_data
.x
->widget
);
6147 Window window
= FRAME_X_WINDOW (f
);
6150 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6151 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6152 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6154 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6155 #endif /* MAC_TODO */
6159 /***********************************************************************
6161 ***********************************************************************/
6163 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6166 x_get_font_info (f
, font_idx
)
6170 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6173 /* the global font name table */
6174 char **font_name_table
= NULL
;
6175 int font_name_table_size
= 0;
6176 int font_name_count
= 0;
6178 /* Alist linking character set strings to Mac text encoding and Emacs
6180 static Lisp_Object Vmac_charset_info_alist
;
6183 create_text_encoding_info_alist ()
6185 Lisp_Object result
= Qnil
, rest
;
6187 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6189 Lisp_Object charset_info
= XCAR (rest
);
6190 Lisp_Object charset
, coding_system
, text_encoding
;
6191 Lisp_Object existing_info
;
6193 if (!(CONSP (charset_info
)
6194 && STRINGP (charset
= XCAR (charset_info
))
6195 && CONSP (XCDR (charset_info
))
6196 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6197 && CONSP (XCDR (XCDR (charset_info
)))
6198 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6201 existing_info
= assq_no_quit (text_encoding
, result
);
6202 if (NILP (existing_info
))
6203 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6206 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6207 XSETCDR (XCDR (existing_info
),
6208 Fcons (charset
, XCDR (XCDR (existing_info
))));
6216 decode_mac_font_name (name
, size
, coding_system
)
6219 Lisp_Object coding_system
;
6221 struct coding_system coding
;
6224 for (p
= name
; *p
; p
++)
6225 if (!isascii (*p
) || iscntrl (*p
))
6229 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6232 setup_coding_system (coding_system
, &coding
);
6233 coding
.src_multibyte
= 0;
6234 coding
.dst_multibyte
= 1;
6235 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6236 coding
.composing
= COMPOSITION_DISABLED
;
6237 buf
= (char *) alloca (size
);
6239 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6240 bcopy (buf
, name
, coding
.produced
);
6241 name
[coding
.produced
] = '\0';
6246 mac_to_x_fontname (name
, size
, style
, charset
)
6252 char foundry
[32], family
[32], cs
[32];
6253 char xf
[256], *result
, *p
;
6255 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) == 3)
6259 strcpy(foundry
, "Apple");
6260 strcpy(family
, name
);
6263 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6264 foundry
, family
, style
& bold
? "bold" : "medium",
6265 style
& italic
? 'i' : 'r', size
, size
* 10,
6266 size
? 75 : 0, size
? 75 : 0, size
* 10, charset
);
6268 result
= (char *) xmalloc (strlen (xf
) + 1);
6269 strcpy (result
, xf
);
6270 for (p
= result
; *p
; p
++)
6276 /* Convert an X font spec to the corresponding mac font name, which
6277 can then be passed to GetFNum after conversion to a Pascal string.
6278 For ordinary Mac fonts, this should just be their names, like
6279 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6280 collection contain their charset designation in their names, like
6281 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6282 names are handled accordingly. */
6284 x_font_name_to_mac_font_name (xf
, mf
, mf_decoded
, style
, cs
)
6285 char *xf
, *mf
, *mf_decoded
;
6289 char foundry
[32], family
[32], weight
[20], slant
[2], *p
;
6290 Lisp_Object charset_info
, coding_system
= Qnil
;
6291 struct coding_system coding
;
6295 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6296 foundry
, family
, weight
, slant
, cs
) != 5 &&
6297 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6298 foundry
, family
, weight
, slant
, cs
) != 5)
6302 if (strcmp (weight
, "bold") == 0)
6307 charset_info
= Fassoc (build_string (cs
), Vmac_charset_info_alist
);
6308 if (!NILP (charset_info
))
6310 strcpy (mf_decoded
, family
);
6311 coding_system
= Fcar (Fcdr (Fcdr (charset_info
)));
6314 sprintf (mf_decoded
, "%s-%s-%s", foundry
, family
, cs
);
6316 for (p
= mf_decoded
; *p
; p
++)
6317 if (!isascii (*p
) || iscntrl (*p
))
6321 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6322 strcpy (mf
, mf_decoded
);
6325 setup_coding_system (coding_system
, &coding
);
6326 coding
.src_multibyte
= 1;
6327 coding
.dst_multibyte
= 1;
6328 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6329 encode_coding (&coding
, mf_decoded
, mf
,
6330 strlen (mf_decoded
), sizeof (Str32
) - 1);
6331 mf
[coding
.produced
] = '\0';
6337 add_font_name_table_entry (char *font_name
)
6339 if (font_name_table_size
== 0)
6341 font_name_table_size
= 16;
6342 font_name_table
= (char **)
6343 xmalloc (font_name_table_size
* sizeof (char *));
6345 else if (font_name_count
+ 1 >= font_name_table_size
)
6347 font_name_table_size
+= 16;
6348 font_name_table
= (char **)
6349 xrealloc (font_name_table
,
6350 font_name_table_size
* sizeof (char *));
6353 font_name_table
[font_name_count
++] = font_name
;
6356 /* Sets up the table font_name_table to contain the list of all fonts
6357 in the system the first time the table is used so that the Resource
6358 Manager need not be accessed every time this information is
6362 init_font_name_table ()
6364 #if TARGET_API_MAC_CARBON
6365 FMFontFamilyIterator ffi
;
6366 FMFontFamilyInstanceIterator ffii
;
6368 Lisp_Object text_encoding_info_alist
;
6369 struct gcpro gcpro1
;
6371 /* Create a dummy instance iterator here to avoid creating and
6372 destroying it in the loop. */
6373 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6375 /* Create an iterator to enumerate the font families. */
6376 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6379 FMDisposeFontFamilyInstanceIterator (&ffii
);
6383 text_encoding_info_alist
= create_text_encoding_info_alist ();
6385 GCPRO1 (text_encoding_info_alist
);
6387 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6393 TextEncoding encoding
;
6394 TextEncodingBase sc
;
6395 Lisp_Object text_encoding_info
;
6397 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6403 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6405 sc
= GetTextEncodingBase (encoding
);
6406 text_encoding_info
= assq_no_quit (make_number (sc
),
6407 text_encoding_info_alist
);
6408 if (!NILP (text_encoding_info
))
6409 decode_mac_font_name (name
, sizeof (name
),
6410 XCAR (XCDR (text_encoding_info
)));
6412 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6413 text_encoding_info_alist
);
6415 /* Point the instance iterator at the current font family. */
6416 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6419 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6422 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6424 for (; !NILP (rest
); rest
= XCDR (rest
))
6426 char *cs
= SDATA (XCAR (rest
));
6430 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6432 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6434 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6436 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6442 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6451 /* Dispose of the iterators. */
6452 FMDisposeFontFamilyIterator (&ffi
);
6453 FMDisposeFontFamilyInstanceIterator (&ffii
);
6454 #else /* !TARGET_API_MAC_CARBON */
6456 SInt16 fontnum
, old_fontnum
;
6457 int num_mac_fonts
= CountResources('FOND');
6459 Handle font_handle
, font_handle_2
;
6460 short id
, scriptcode
;
6463 struct FontAssoc
*fat
;
6464 struct AsscEntry
*assc_entry
;
6465 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
6466 struct gcpro gcpro1
;
6468 GetPort (&port
); /* save the current font number used */
6469 old_fontnum
= port
->txFont
;
6471 text_encoding_info_alist
= create_text_encoding_info_alist ();
6473 GCPRO1 (text_encoding_info_alist
);
6475 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6477 font_handle
= GetIndResource ('FOND', i
);
6481 GetResInfo (font_handle
, &id
, &type
, name
);
6482 GetFNum (name
, &fontnum
);
6488 scriptcode
= FontToScript (fontnum
);
6489 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
6490 text_encoding_info_alist
);
6491 if (!NILP (text_encoding_info
))
6492 decode_mac_font_name (name
, sizeof (name
),
6493 XCAR (XCDR (text_encoding_info
)));
6495 text_encoding_info
= assq_no_quit (make_number (smRoman
),
6496 text_encoding_info_alist
);
6499 HLock (font_handle
);
6501 if (GetResourceSizeOnDisk (font_handle
)
6502 >= sizeof (struct FamRec
))
6504 fat
= (struct FontAssoc
*) (*font_handle
6505 + sizeof (struct FamRec
));
6507 = (struct AsscEntry
*) (*font_handle
6508 + sizeof (struct FamRec
)
6509 + sizeof (struct FontAssoc
));
6511 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6513 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6515 for (; !NILP (rest
); rest
= XCDR (rest
))
6517 char *cs
= SDATA (XCAR (rest
));
6519 add_font_name_table_entry (mac_to_x_fontname (name
,
6520 assc_entry
->fontSize
,
6521 assc_entry
->fontStyle
,
6527 HUnlock (font_handle
);
6528 font_handle_2
= GetNextFOND (font_handle
);
6529 ReleaseResource (font_handle
);
6530 font_handle
= font_handle_2
;
6532 while (ResError () == noErr
&& font_handle
);
6537 TextFont (old_fontnum
);
6538 #endif /* !TARGET_API_MAC_CARBON */
6543 mac_clear_font_name_table ()
6547 for (i
= 0; i
< font_name_count
; i
++)
6548 xfree (font_name_table
[i
]);
6549 xfree (font_name_table
);
6550 font_name_table
= NULL
;
6551 font_name_table_size
= font_name_count
= 0;
6555 enum xlfd_scalable_field_index
6557 XLFD_SCL_PIXEL_SIZE
,
6558 XLFD_SCL_POINT_SIZE
,
6563 static int xlfd_scalable_fields
[] =
6572 mac_c_string_match (regexp
, string
, nonspecial
, exact
)
6574 const char *string
, *nonspecial
;
6579 if (strcmp (string
, nonspecial
) == 0)
6580 return build_string (string
);
6582 else if (strstr (string
, nonspecial
))
6584 Lisp_Object str
= build_string (string
);
6586 if (fast_string_match (regexp
, str
) >= 0)
6594 mac_do_list_fonts (pattern
, maxnames
)
6599 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6600 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6603 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6604 char *longest_start
, *cur_start
, *nonspecial
;
6605 int longest_len
, exact
;
6607 if (font_name_table
== NULL
) /* Initialize when first used. */
6608 init_font_name_table ();
6610 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6613 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6614 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6615 fonts are scaled according to the specified size. */
6618 field
= xlfd_scalable_fields
;
6626 if ('0' <= *ptr
&& *ptr
<= '9')
6628 *val
= *ptr
++ - '0';
6629 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6630 *val
= *val
* 10 + *ptr
++ - '0';
6637 ptr
= strchr (ptr
, '-');
6640 while (ptr
&& i
< 14);
6642 if (i
== 14 && ptr
== NULL
)
6644 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
6645 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
6646 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
6647 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
6649 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
6650 scl_val
[XLFD_SCL_POINT_SIZE
] =
6651 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6652 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
6654 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
6655 scl_val
[XLFD_SCL_AVGWIDTH
] =
6656 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6657 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
6661 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6666 longest_start
= cur_start
= ptr
;
6670 /* Turn pattern into a regexp and do a regexp match. Also find the
6671 longest substring containing no special characters. */
6672 for (; *pattern
; pattern
++)
6674 if (*pattern
== '?' || *pattern
== '*')
6676 if (ptr
- cur_start
> longest_len
)
6678 longest_start
= cur_start
;
6679 longest_len
= ptr
- cur_start
;
6683 if (*pattern
== '?')
6685 else /* if (*pattern == '*') */
6693 *ptr
++ = tolower (*pattern
);
6696 if (ptr
- cur_start
> longest_len
)
6698 longest_start
= cur_start
;
6699 longest_len
= ptr
- cur_start
;
6705 nonspecial
= xmalloc (longest_len
+ 1);
6706 strncpy (nonspecial
, longest_start
, longest_len
);
6707 nonspecial
[longest_len
] = '\0';
6709 pattern_regex
= build_string (regex
);
6711 for (i
= 0; i
< font_name_count
; i
++)
6713 fontname
= mac_c_string_match (pattern_regex
, font_name_table
[i
],
6715 if (!NILP (fontname
))
6717 font_list
= Fcons (fontname
, font_list
);
6718 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6721 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6722 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
6724 int former_len
= ptr
- font_name_table
[i
];
6726 memcpy (scaled
, font_name_table
[i
], former_len
);
6727 sprintf (scaled
+ former_len
,
6728 "-%d-%d-75-75-m-%d-%s",
6729 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6730 scl_val
[XLFD_SCL_POINT_SIZE
],
6731 scl_val
[XLFD_SCL_AVGWIDTH
],
6732 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
6733 fontname
= mac_c_string_match (pattern_regex
, scaled
,
6735 if (!NILP (fontname
))
6737 font_list
= Fcons (fontname
, font_list
);
6738 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6749 /* Return a list of names of available fonts matching PATTERN on frame F.
6751 Frame F null means we have not yet created any frame on Mac, and
6752 consult the first display in x_display_list. MAXNAMES sets a limit
6753 on how many fonts to match. */
6756 x_list_fonts (f
, pattern
, size
, maxnames
)
6758 Lisp_Object pattern
;
6761 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
6762 struct mac_display_info
*dpyinfo
6763 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
6765 xassert (size
<= 0);
6767 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6768 if (NILP (patterns
))
6769 patterns
= Fcons (pattern
, Qnil
);
6771 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
6773 pattern
= XCAR (patterns
);
6775 if (!STRINGP (pattern
))
6778 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
6779 key
= Fcons (pattern
, make_number (maxnames
));
6781 list
= Fassoc (key
, tem
);
6784 list
= Fcdr_safe (list
);
6785 /* We have a cashed list. Don't have to get the list again. */
6790 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6793 /* MAC_TODO: add code for matching outline fonts here */
6795 /* Now store the result in the cache. */
6796 XSETCAR (XCDR (dpyinfo
->name_list_element
),
6797 Fcons (Fcons (key
, list
),
6798 XCAR (XCDR (dpyinfo
->name_list_element
))));
6801 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6810 /* Check that FONT is valid on frame F. It is if it can be found in F's
6814 x_check_font (f
, font
)
6819 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6821 xassert (font
!= NULL
);
6823 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6824 if (dpyinfo
->font_table
[i
].name
6825 && font
== dpyinfo
->font_table
[i
].font
)
6828 xassert (i
< dpyinfo
->n_fonts
);
6831 #endif /* GLYPH_DEBUG != 0 */
6833 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6834 Note: There are (broken) X fonts out there with invalid XFontStruct
6835 min_bounds contents. For example, handa@etl.go.jp reports that
6836 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6837 have font->min_bounds.width == 0. */
6840 x_font_min_bounds (font
, w
, h
)
6841 MacFontStruct
*font
;
6844 *h
= FONT_HEIGHT (font
);
6845 *w
= font
->min_bounds
.width
;
6849 /* Compute the smallest character width and smallest font height over
6850 all fonts available on frame F. Set the members smallest_char_width
6851 and smallest_font_height in F's x_display_info structure to
6852 the values computed. Value is non-zero if smallest_font_height or
6853 smallest_char_width become smaller than they were before. */
6856 x_compute_min_glyph_bounds (f
)
6860 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6861 MacFontStruct
*font
;
6862 int old_width
= dpyinfo
->smallest_char_width
;
6863 int old_height
= dpyinfo
->smallest_font_height
;
6865 dpyinfo
->smallest_font_height
= 100000;
6866 dpyinfo
->smallest_char_width
= 100000;
6868 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6869 if (dpyinfo
->font_table
[i
].name
)
6871 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6874 font
= (MacFontStruct
*) fontp
->font
;
6875 xassert (font
!= (MacFontStruct
*) ~0);
6876 x_font_min_bounds (font
, &w
, &h
);
6878 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6879 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6882 xassert (dpyinfo
->smallest_char_width
> 0
6883 && dpyinfo
->smallest_font_height
> 0);
6885 return (dpyinfo
->n_fonts
== 1
6886 || dpyinfo
->smallest_char_width
< old_width
6887 || dpyinfo
->smallest_font_height
< old_height
);
6891 /* Determine whether given string is a fully-specified XLFD: all 14
6892 fields are present, none is '*'. */
6895 is_fully_specified_xlfd (char *p
)
6903 for (i
= 0; i
< 13; i
++)
6905 q
= strchr (p
+ 1, '-');
6908 if (q
- p
== 2 && *(p
+ 1) == '*')
6913 if (strchr (p
+ 1, '-') != NULL
)
6916 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6923 const int kDefaultFontSize
= 12;
6926 /* XLoadQueryFont creates and returns an internal representation for a
6927 font in a MacFontStruct struct. There is really no concept
6928 corresponding to "loading" a font on the Mac. But we check its
6929 existence and find the font number and all other information for it
6930 and store them in the returned MacFontStruct. */
6932 static MacFontStruct
*
6933 XLoadQueryFont (Display
*dpy
, char *fontname
)
6935 int i
, size
, point_size
, avgwidth
, is_two_byte_font
, char_width
;
6938 SInt16 old_fontnum
, old_fontsize
;
6940 Str32 mfontname
, mfontname_decoded
, charset
;
6943 #if TARGET_API_MAC_CARBON
6944 TextEncoding encoding
;
6949 MacFontStruct
*font
;
6950 FontInfo the_fontinfo
;
6952 UInt32 old_flags
, new_flags
;
6955 if (is_fully_specified_xlfd (fontname
))
6959 Lisp_Object matched_fonts
;
6961 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6962 if (NILP (matched_fonts
))
6964 name
= SDATA (XCAR (matched_fonts
));
6967 GetPort (&port
); /* save the current font number used */
6968 #if TARGET_API_MAC_CARBON
6969 old_fontnum
= GetPortTextFont (port
);
6970 old_fontsize
= GetPortTextSize (port
);
6971 old_fontface
= GetPortTextFace (port
);
6973 old_fontnum
= port
->txFont
;
6974 old_fontsize
= port
->txSize
;
6975 old_fontface
= port
->txFace
;
6978 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size
, &point_size
, &avgwidth
) != 3)
6984 size
= point_size
/ 10;
6985 else if (avgwidth
> 0)
6986 size
= avgwidth
/ 10;
6989 size
= kDefaultFontSize
;
6991 x_font_name_to_mac_font_name (name
, mfontname
, mfontname_decoded
,
6992 &fontface
, charset
);
6994 #if TARGET_API_MAC_CARBON
6995 fontnum
= FMGetFontFamilyFromName (mfontname
);
6996 if (fontnum
== kInvalidFontFamily
6997 || FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
6999 scriptcode
= GetTextEncodingBase (encoding
);
7001 GetFNum (mfontname
, &fontnum
);
7004 scriptcode
= FontToScript (fontnum
);
7007 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7009 font
->mac_fontnum
= fontnum
;
7010 font
->mac_fontsize
= size
;
7011 font
->mac_fontface
= fontface
;
7012 font
->mac_scriptcode
= scriptcode
;
7014 /* Apple Japanese (SJIS) font is listed as both
7015 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7016 (Roman script) in init_font_name_table (). The latter should be
7017 treated as a one-byte font. */
7018 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7019 font
->mac_scriptcode
= smRoman
;
7021 font
->full_name
= mac_to_x_fontname (mfontname_decoded
, size
, fontface
, charset
);
7023 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
7024 font
->mac_scriptcode
== smTradChinese
||
7025 font
->mac_scriptcode
== smSimpChinese
||
7026 font
->mac_scriptcode
== smKorean
;
7030 TextFace (fontface
);
7032 GetFontInfo (&the_fontinfo
);
7034 font
->ascent
= the_fontinfo
.ascent
;
7035 font
->descent
= the_fontinfo
.descent
;
7037 font
->min_byte1
= 0;
7038 if (is_two_byte_font
)
7039 font
->max_byte1
= 1;
7041 font
->max_byte1
= 0;
7042 font
->min_char_or_byte2
= 0x20;
7043 font
->max_char_or_byte2
= 0xff;
7045 if (is_two_byte_font
)
7047 /* Use the width of an "ideographic space" of that font because
7048 the_fontinfo.widMax returns the wrong width for some fonts. */
7049 switch (font
->mac_scriptcode
)
7052 char_width
= StringWidth("\p\x81\x40");
7055 char_width
= StringWidth("\p\xa1\x40");
7058 char_width
= StringWidth("\p\xa1\xa1");
7061 char_width
= StringWidth("\p\xa1\xa1");
7066 /* Do this instead of use the_fontinfo.widMax, which incorrectly
7067 returns 15 for 12-point Monaco! */
7068 char_width
= CharWidth ('m');
7070 if (is_two_byte_font
)
7072 font
->per_char
= NULL
;
7074 if (fontface
& italic
)
7075 font
->max_bounds
.rbearing
= char_width
+ 1;
7077 font
->max_bounds
.rbearing
= char_width
;
7078 font
->max_bounds
.lbearing
= 0;
7079 font
->max_bounds
.width
= char_width
;
7080 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7081 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7083 font
->min_bounds
= font
->max_bounds
;
7087 font
->per_char
= (XCharStruct
*)
7088 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7090 int c
, min_width
, max_width
;
7091 Rect char_bounds
, min_bounds
, max_bounds
;
7094 min_width
= max_width
= char_width
;
7095 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
7096 SetRect (&max_bounds
, 0, 0, 0, 0);
7097 for (c
= 0x20; c
<= 0xff; c
++)
7100 char_width
= CharWidth (ch
);
7101 QDTextBounds (1, &ch
, &char_bounds
);
7102 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
7103 char_width
, char_bounds
);
7104 /* Some Japanese fonts (in SJIS encoding) return 0 as the
7105 character width of 0x7f. */
7108 min_width
= min (min_width
, char_width
);
7109 max_width
= max (max_width
, char_width
);
7111 if (!EmptyRect (&char_bounds
))
7113 SetRect (&min_bounds
,
7114 max (min_bounds
.left
, char_bounds
.left
),
7115 max (min_bounds
.top
, char_bounds
.top
),
7116 min (min_bounds
.right
, char_bounds
.right
),
7117 min (min_bounds
.bottom
, char_bounds
.bottom
));
7118 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7121 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7122 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7123 if (min_width
== max_width
7124 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
7126 /* Fixed width and no overhangs. */
7127 xfree (font
->per_char
);
7128 font
->per_char
= NULL
;
7133 TextFont (old_fontnum
); /* restore previous font number, size and face */
7134 TextSize (old_fontsize
);
7135 TextFace (old_fontface
);
7142 mac_unload_font (dpyinfo
, font
)
7143 struct mac_display_info
*dpyinfo
;
7146 xfree (font
->full_name
);
7148 xfree (font
->per_char
);
7153 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7154 pointer to the structure font_info while allocating it dynamically.
7155 If SIZE is 0, load any size of font.
7156 If loading is failed, return NULL. */
7159 x_load_font (f
, fontname
, size
)
7161 register char *fontname
;
7164 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7165 Lisp_Object font_names
;
7167 /* Get a list of all the fonts that match this name. Once we
7168 have a list of matching fonts, we compare them against the fonts
7169 we already have by comparing names. */
7170 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7172 if (!NILP (font_names
))
7177 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7178 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7179 if (dpyinfo
->font_table
[i
].name
7180 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7181 SDATA (XCAR (tail
)))
7182 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7183 SDATA (XCAR (tail
)))))
7184 return (dpyinfo
->font_table
+ i
);
7189 /* Load the font and add it to the table. */
7192 struct MacFontStruct
*font
;
7193 struct font_info
*fontp
;
7194 unsigned long value
;
7197 fontname
= (char *) SDATA (XCAR (font_names
));
7200 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7205 /* Find a free slot in the font table. */
7206 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7207 if (dpyinfo
->font_table
[i
].name
== NULL
)
7210 /* If no free slot found, maybe enlarge the font table. */
7211 if (i
== dpyinfo
->n_fonts
7212 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7215 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7216 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7218 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7221 fontp
= dpyinfo
->font_table
+ i
;
7222 if (i
== dpyinfo
->n_fonts
)
7225 /* Now fill in the slots of *FONTP. */
7227 bzero (fontp
, sizeof (*fontp
));
7229 fontp
->font_idx
= i
;
7230 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7231 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7233 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7235 /* Fixed width font. */
7236 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7243 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7244 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7246 fontp
->space_width
= pcm
->width
;
7248 fontp
->space_width
= FONT_WIDTH (font
);
7252 int width
= pcm
->width
;
7253 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7254 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7255 width
+= pcm
->width
;
7256 fontp
->average_width
= width
/ 95;
7259 fontp
->average_width
= FONT_WIDTH (font
);
7262 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7263 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7265 fontp
->size
= font
->max_bounds
.width
;
7266 fontp
->height
= FONT_HEIGHT (font
);
7268 /* For some font, ascent and descent in max_bounds field is
7269 larger than the above value. */
7270 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7271 if (max_height
> fontp
->height
)
7272 fontp
->height
= max_height
;
7275 /* The slot `encoding' specifies how to map a character
7276 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7277 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7278 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7279 2:0xA020..0xFF7F). For the moment, we don't know which charset
7280 uses this font. So, we set information in fontp->encoding[1]
7281 which is never used by any charset. If mapping can't be
7282 decided, set FONT_ENCODING_NOT_DECIDED. */
7283 if (font
->mac_scriptcode
== smJapanese
)
7284 fontp
->encoding
[1] = 4;
7288 = (font
->max_byte1
== 0
7290 ? (font
->min_char_or_byte2
< 0x80
7291 ? (font
->max_char_or_byte2
< 0x80
7292 ? 0 /* 0x20..0x7F */
7293 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
7294 : 1) /* 0xA0..0xFF */
7296 : (font
->min_byte1
< 0x80
7297 ? (font
->max_byte1
< 0x80
7298 ? (font
->min_char_or_byte2
< 0x80
7299 ? (font
->max_char_or_byte2
< 0x80
7300 ? 0 /* 0x2020..0x7F7F */
7301 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
7302 : 3) /* 0x20A0..0x7FFF */
7303 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
7304 : (font
->min_char_or_byte2
< 0x80
7305 ? (font
->max_char_or_byte2
< 0x80
7306 ? 2 /* 0xA020..0xFF7F */
7307 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
7308 : 1))); /* 0xA0A0..0xFFFF */
7311 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7312 fontp
->baseline_offset
7313 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
7314 ? (long) value
: 0);
7315 fontp
->relative_compose
7316 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
7317 ? (long) value
: 0);
7318 fontp
->default_ascent
7319 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
7320 ? (long) value
: 0);
7322 fontp
->baseline_offset
= 0;
7323 fontp
->relative_compose
= 0;
7324 fontp
->default_ascent
= 0;
7327 /* Set global flag fonts_changed_p to non-zero if the font loaded
7328 has a character with a smaller width than any other character
7329 before, or if the font loaded has a smalle>r height than any
7330 other font loaded before. If this happens, it will make a
7331 glyph matrix reallocation necessary. */
7332 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
7339 /* Return a pointer to struct font_info of a font named FONTNAME for
7340 frame F. If no such font is loaded, return NULL. */
7343 x_query_font (f
, fontname
)
7345 register char *fontname
;
7347 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7350 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7351 if (dpyinfo
->font_table
[i
].name
7352 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7353 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7354 return (dpyinfo
->font_table
+ i
);
7359 /* Find a CCL program for a font specified by FONTP, and set the member
7360 `encoder' of the structure. */
7363 x_find_ccl_program (fontp
)
7364 struct font_info
*fontp
;
7366 Lisp_Object list
, elt
;
7368 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7372 && STRINGP (XCAR (elt
))
7373 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7379 struct ccl_program
*ccl
7380 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7382 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7385 fontp
->font_encoder
= ccl
;
7391 /* The Mac Event loop code */
7393 #if !TARGET_API_MAC_CARBON
7395 #include <Quickdraw.h>
7396 #include <Balloons.h>
7397 #include <Devices.h>
7399 #include <Gestalt.h>
7401 #include <Processes.h>
7403 #include <ToolUtils.h>
7404 #include <TextUtils.h>
7405 #include <Dialogs.h>
7408 #include <Resources.h>
7413 #endif /* ! TARGET_API_MAC_CARBON */
7418 #define WINDOW_RESOURCE 128
7419 #define TERM_WINDOW_RESOURCE 129
7421 #define DEFAULT_NUM_COLS 80
7423 #define MIN_DOC_SIZE 64
7424 #define MAX_DOC_SIZE 32767
7427 /* sleep time for WaitNextEvent */
7428 #define WNE_SLEEP_AT_SUSPEND 10
7429 #define WNE_SLEEP_AT_RESUME 1
7431 /* the flag appl_is_suspended is used both for determining the sleep
7432 time to be passed to WaitNextEvent and whether the cursor should be
7433 drawn when updating the display. The cursor is turned off when
7434 Emacs is suspended. Redrawing it is unnecessary and what needs to
7435 be done depends on whether the cursor lies inside or outside the
7436 redraw region. So we might as well skip drawing it when Emacs is
7438 static Boolean app_is_suspended
= false;
7439 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7442 #define EXTRA_STACK_ALLOC (256 * 1024)
7444 #define ARGV_STRING_LIST_ID 129
7445 #define ABOUT_ALERT_ID 128
7446 #define RAM_TOO_LARGE_ALERT_ID 129
7448 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7449 Lisp_Object Qreverse
;
7451 /* True if using command key as meta key. */
7452 Lisp_Object Vmac_command_key_is_meta
;
7454 /* Modifier associated with the option key, or nil for normal behavior. */
7455 Lisp_Object Vmac_option_modifier
;
7457 /* True if the ctrl and meta keys should be reversed. */
7458 Lisp_Object Vmac_reverse_ctrl_meta
;
7460 /* True if the option and command modifiers should be used to emulate
7461 a three button mouse */
7462 Lisp_Object Vmac_emulate_three_button_mouse
;
7464 #if USE_CARBON_EVENTS
7465 /* True if the mouse wheel button (i.e. button 4) should map to
7466 mouse-2, instead of mouse-3. */
7467 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7469 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7470 for processing before Emacs sees it. */
7471 Lisp_Object Vmac_pass_command_to_system
;
7473 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7474 for processing before Emacs sees it. */
7475 Lisp_Object Vmac_pass_control_to_system
;
7477 /* Points to the variable `inev' in the function XTread_socket. It is
7478 used for passing an input event to the function back from a Carbon
7480 static struct input_event
*read_socket_inev
= NULL
;
7483 /* Set in term/mac-win.el to indicate that event loop can now generate
7484 drag and drop events. */
7485 Lisp_Object Qmac_ready_for_drag_n_drop
;
7487 Lisp_Object drag_and_drop_file_list
;
7489 Point saved_menu_event_location
;
7492 static void init_required_apple_events (void);
7494 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7496 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7497 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7498 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7500 #if TARGET_API_MAC_CARBON
7502 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7503 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7504 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7505 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7508 static Lisp_Object Qapplication
, Qabout
;
7509 #if USE_CARBON_EVENTS
7511 extern void init_service_handler ();
7512 static Lisp_Object Qpreferences
, Qservices
, Qpaste
, Qperform
;
7514 /* Window Event Handler */
7515 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7518 OSErr
install_window_handler (WindowPtr
);
7520 extern void init_emacs_passwd_dir ();
7521 extern int emacs_main (int, char **, char **);
7523 extern void initialize_applescript();
7524 extern void terminate_applescript();
7527 #if USE_CARBON_EVENTS
7528 mac_to_emacs_modifiers (UInt32 mods
)
7530 mac_to_emacs_modifiers (EventModifiers mods
)
7533 unsigned int result
= 0;
7534 if (mods
& macShiftKey
)
7535 result
|= shift_modifier
;
7536 if (mods
& macCtrlKey
)
7537 result
|= ctrl_modifier
;
7538 if (mods
& macMetaKey
)
7539 result
|= meta_modifier
;
7540 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7541 result
|= alt_modifier
;
7542 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7543 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7545 result
|= XUINT(val
);
7552 mac_get_emulated_btn ( UInt32 modifiers
)
7555 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7556 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7557 if (modifiers
& cmdKey
)
7558 result
= cmdIs3
? 2 : 1;
7559 else if (modifiers
& optionKey
)
7560 result
= cmdIs3
? 1 : 2;
7565 #if USE_CARBON_EVENTS
7566 /* Obtains the event modifiers from the event ref and then calls
7567 mac_to_emacs_modifiers. */
7569 mac_event_to_emacs_modifiers (EventRef eventRef
)
7572 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7573 sizeof (UInt32
), NULL
, &mods
);
7574 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7575 GetEventClass(eventRef
) == kEventClassMouse
)
7577 mods
&= ~(optionKey
| cmdKey
);
7579 return mac_to_emacs_modifiers (mods
);
7582 /* Given an event ref, return the code to use for the mouse button
7583 code in the emacs input_event. */
7585 mac_get_mouse_btn (EventRef ref
)
7587 EventMouseButton result
= kEventMouseButtonPrimary
;
7588 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7589 sizeof (EventMouseButton
), NULL
, &result
);
7592 case kEventMouseButtonPrimary
:
7593 if (NILP (Vmac_emulate_three_button_mouse
))
7597 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7598 sizeof (UInt32
), NULL
, &mods
);
7599 return mac_get_emulated_btn(mods
);
7601 case kEventMouseButtonSecondary
:
7602 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7603 case kEventMouseButtonTertiary
:
7604 case 4: /* 4 is the number for the mouse wheel button */
7605 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7611 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7612 events. However the click of the mouse wheel is not converted to a
7613 mouseDown or mouseUp event. Likewise for dead key down events.
7614 This calls ConvertEventRef, but then checks to see if it is a mouse
7615 up/down, or a dead key down carbon event that has not been
7616 converted, and if so, converts it by hand (to be picked up in the
7617 XTread_socket loop). */
7618 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7620 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7625 switch (GetEventClass (eventRef
))
7627 case kEventClassMouse
:
7628 switch (GetEventKind (eventRef
))
7630 case kEventMouseDown
:
7631 eventRec
->what
= mouseDown
;
7636 eventRec
->what
= mouseUp
;
7645 case kEventClassKeyboard
:
7646 switch (GetEventKind (eventRef
))
7648 case kEventRawKeyDown
:
7650 unsigned char char_codes
;
7653 eventRec
->what
= keyDown
;
7654 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
7655 NULL
, sizeof (char), NULL
, &char_codes
);
7656 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
7657 NULL
, sizeof (UInt32
), NULL
, &key_code
);
7658 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
7674 /* Need where and when. */
7677 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
7678 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
7679 /* Use two step process because new event modifiers are 32-bit
7680 and old are 16-bit. Currently, only loss is NumLock & Fn. */
7681 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
7682 NULL
, sizeof (UInt32
), NULL
, &mods
);
7683 eventRec
->modifiers
= mods
;
7685 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7696 Handle menubar_handle
;
7697 MenuHandle menu_handle
;
7699 menubar_handle
= GetNewMBar (128);
7700 if(menubar_handle
== NULL
)
7702 SetMenuBar (menubar_handle
);
7705 #if !TARGET_API_MAC_CARBON
7706 menu_handle
= GetMenuHandle (M_APPLE
);
7707 if(menu_handle
!= NULL
)
7708 AppendResMenu (menu_handle
,'DRVR');
7716 do_init_managers (void)
7718 #if !TARGET_API_MAC_CARBON
7719 InitGraf (&qd
.thePort
);
7721 FlushEvents (everyEvent
, 0);
7726 #endif /* !TARGET_API_MAC_CARBON */
7729 #if !TARGET_API_MAC_CARBON
7730 /* set up some extra stack space for use by emacs */
7731 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7733 /* MaxApplZone must be called for AppleScript to execute more
7734 complicated scripts */
7737 #endif /* !TARGET_API_MAC_CARBON */
7741 do_check_ram_size (void)
7743 SInt32 physical_ram_size
, logical_ram_size
;
7745 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7746 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7747 || physical_ram_size
> (1 << VALBITS
)
7748 || logical_ram_size
> (1 << VALBITS
))
7750 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7756 do_window_update (WindowPtr win
)
7758 struct frame
*f
= mac_window_to_frame (win
);
7762 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7764 if (win
!= tip_window
)
7766 if (f
->async_visible
== 0)
7768 f
->async_visible
= 1;
7769 f
->async_iconified
= 0;
7770 SET_FRAME_GARBAGED (f
);
7772 /* An update event is equivalent to MapNotify on X, so report
7773 visibility changes properly. */
7774 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7775 /* Force a redisplay sooner or later to update the
7776 frame titles in case this is the second frame. */
7777 record_asynch_buffer_change ();
7783 #if TARGET_API_MAC_CARBON
7785 RgnHandle region
= NewRgn ();
7787 GetPortVisibleRegion (GetWindowPort (win
), region
);
7788 GetRegionBounds (region
, &r
);
7789 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7790 UpdateControls (win
, region
);
7791 DisposeRgn (region
);
7794 r
= (*win
->visRgn
)->rgnBBox
;
7795 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7796 UpdateControls (win
, win
->visRgn
);
7805 is_emacs_window (WindowPtr win
)
7807 Lisp_Object tail
, frame
;
7812 FOR_EACH_FRAME (tail
, frame
)
7813 if (FRAME_MAC_P (XFRAME (frame
)))
7814 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7823 /* Window-activate events will do the job. */
7825 app_is_suspended
= false;
7826 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7833 /* Window-deactivate events will do the job. */
7835 app_is_suspended
= true;
7836 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7842 do_apple_menu (SInt16 menu_item
)
7844 #if !TARGET_API_MAC_CARBON
7846 SInt16 da_driver_refnum
;
7848 if (menu_item
== I_ABOUT
)
7849 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7852 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7853 da_driver_refnum
= OpenDeskAcc (item_name
);
7855 #endif /* !TARGET_API_MAC_CARBON */
7859 do_menu_choice (SInt32 menu_choice
)
7861 SInt16 menu_id
, menu_item
;
7863 menu_id
= HiWord (menu_choice
);
7864 menu_item
= LoWord (menu_choice
);
7872 do_apple_menu (menu_item
);
7877 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
7878 MenuHandle menu
= GetMenuHandle (menu_id
);
7883 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7884 menubar_selection_callback (f
, refcon
);
7893 /* Handle drags in size box. Based on code contributed by Ben
7894 Mesander and IM - Window Manager A. */
7897 do_grow_window (WindowPtr w
, EventRecord
*e
)
7900 int rows
, columns
, width
, height
;
7901 struct frame
*f
= mac_window_to_frame (w
);
7902 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
7903 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
7904 #if TARGET_API_MAC_CARBON
7910 if (size_hints
->flags
& PMinSize
)
7912 min_width
= size_hints
->min_width
;
7913 min_height
= size_hints
->min_height
;
7915 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7917 #if TARGET_API_MAC_CARBON
7918 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
7920 height
= new_rect
.bottom
- new_rect
.top
;
7921 width
= new_rect
.right
- new_rect
.left
;
7923 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7924 /* see if it really changed size */
7927 height
= HiWord (grow_size
);
7928 width
= LoWord (grow_size
);
7931 if (width
!= FRAME_PIXEL_WIDTH (f
)
7932 || height
!= FRAME_PIXEL_HEIGHT (f
))
7934 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7935 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7937 x_set_window_size (f
, 0, columns
, rows
);
7942 /* Handle clicks in zoom box. Calculation of "standard state" based
7943 on code in IM - Window Manager A and code contributed by Ben
7944 Mesander. The standard state of an Emacs window is 80-characters
7945 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7948 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7951 Rect zoom_rect
, port_rect
;
7953 int w_title_height
, columns
, rows
, width
, height
;
7954 struct frame
*f
= mac_window_to_frame (w
);
7955 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7957 #if TARGET_API_MAC_CARBON
7959 Point standard_size
;
7961 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7962 standard_size
.v
= dpyinfo
->height
;
7964 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7965 zoom_in_or_out
= inZoomIn
;
7968 /* Adjust the standard size according to character boundaries. */
7970 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7971 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7972 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7973 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7974 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
7975 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
7976 && port_rect
.left
== zoom_rect
.left
7977 && port_rect
.top
== zoom_rect
.top
)
7978 zoom_in_or_out
= inZoomIn
;
7980 zoom_in_or_out
= inZoomOut
;
7983 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
7985 #else /* not TARGET_API_MAC_CARBON */
7986 GetPort (&save_port
);
7988 SetPortWindowPort (w
);
7990 /* Clear window to avoid flicker. */
7991 EraseRect (&(w
->portRect
));
7992 if (zoom_in_or_out
== inZoomOut
)
7994 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
7995 LocalToGlobal (&top_left
);
7997 /* calculate height of window's title bar */
7998 w_title_height
= top_left
.v
- 1
7999 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8001 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8002 zoom_rect
= qd
.screenBits
.bounds
;
8003 zoom_rect
.top
+= w_title_height
;
8004 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8006 zoom_rect
.right
= zoom_rect
.left
8007 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8009 /* Adjust the standard size according to character boundaries. */
8010 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8012 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8014 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8018 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8020 SetPort (save_port
);
8021 #endif /* not TARGET_API_MAC_CARBON */
8023 /* retrieve window size and update application values */
8024 #if TARGET_API_MAC_CARBON
8025 GetWindowPortBounds (w
, &port_rect
);
8027 port_rect
= w
->portRect
;
8029 height
= port_rect
.bottom
- port_rect
.top
;
8030 width
= port_rect
.right
- port_rect
.left
;
8032 if (width
!= FRAME_PIXEL_WIDTH (f
)
8033 || height
!= FRAME_PIXEL_HEIGHT (f
))
8035 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8036 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8038 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8039 SET_FRAME_GARBAGED (f
);
8040 cancel_mouse_face (f
);
8042 FRAME_PIXEL_WIDTH (f
) = width
;
8043 FRAME_PIXEL_HEIGHT (f
) = height
;
8045 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8048 /* Intialize AppleEvent dispatcher table for the required events. */
8050 init_required_apple_events ()
8055 /* Make sure we have apple events before starting. */
8056 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
8060 if (!(result
& (1 << gestaltAppleEventsPresent
)))
8063 #if TARGET_API_MAC_CARBON
8064 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8065 NewAEEventHandlerUPP
8066 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8069 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8070 NewAEEventHandlerProc
8071 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8077 #if TARGET_API_MAC_CARBON
8078 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8079 NewAEEventHandlerUPP
8080 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8083 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8084 NewAEEventHandlerProc
8085 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8091 #if TARGET_API_MAC_CARBON
8092 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8093 NewAEEventHandlerUPP
8094 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8097 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8098 NewAEEventHandlerProc
8099 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8105 #if TARGET_API_MAC_CARBON
8106 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8107 NewAEEventHandlerUPP
8108 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8111 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8112 NewAEEventHandlerProc
8113 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8121 mac_store_application_menu_event (event
)
8122 #if USE_CARBON_EVENTS
8128 struct input_event buf
;
8129 Lisp_Object frame
, entry
;
8133 XSETFRAME (frame
, mac_focus_frame (&one_mac_display_info
));
8134 buf
.kind
= MENU_BAR_EVENT
;
8135 buf
.frame_or_window
= frame
;
8137 kbd_buffer_store_event (&buf
);
8139 buf
.arg
= Qapplication
;
8140 kbd_buffer_store_event (&buf
);
8142 #if USE_CARBON_EVENTS
8143 switch (GetEventClass (event
))
8146 case kEventClassService
:
8147 buf
.arg
= Qservices
;
8148 kbd_buffer_store_event (&buf
);
8149 switch (GetEventKind (event
))
8151 case kEventServicePaste
:
8155 case kEventServicePerform
:
8158 CFStringRef message
;
8160 err
= GetEventParameter (event
, kEventParamServiceMessageName
,
8161 typeCFStringRef
, NULL
,
8162 sizeof (CFStringRef
), NULL
, &message
);
8164 kbd_buffer_store_event (&buf
);
8165 if (err
== noErr
&& message
)
8166 entry
= intern (SDATA (cfstring_to_lisp (message
)));
8176 #endif /* MAC_OSX */
8177 case kEventClassCommand
:
8181 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
,
8182 NULL
, sizeof (HICommand
), NULL
, &command
);
8183 switch (command
.commandID
)
8185 case kHICommandAbout
:
8189 case kHICommandPreferences
:
8190 entry
= Qpreferences
;
8192 #endif /* MAC_OSX */
8193 case kHICommandQuit
:
8205 #else /* USE_CARBON_EVENTS */
8208 case kHICommandAbout
:
8211 case kHICommandQuit
:
8220 kbd_buffer_store_event (&buf
);
8223 #if USE_CARBON_EVENTS
8224 static pascal OSStatus
8225 mac_handle_command_event (next_handler
, event
, data
)
8226 EventHandlerCallRef next_handler
;
8233 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8234 sizeof (HICommand
), NULL
, &command
);
8236 switch (command
.commandID
)
8238 case kHICommandAbout
:
8240 case kHICommandPreferences
:
8241 #endif /* MAC_OSX */
8242 result
= CallNextEventHandler (next_handler
, event
);
8243 if (result
!= eventNotHandledErr
)
8246 mac_store_application_menu_event (event
);
8253 return eventNotHandledErr
;
8257 init_command_handler ()
8260 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8261 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8263 if (handle_command_eventUPP
== NULL
)
8264 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8265 return InstallApplicationEventHandler (handle_command_eventUPP
,
8266 GetEventTypeCount (specs
), specs
,
8270 static pascal OSStatus
8271 mac_handle_window_event (next_handler
, event
, data
)
8272 EventHandlerCallRef next_handler
;
8279 XSizeHints
*size_hints
;
8281 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8282 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8284 switch (GetEventKind (event
))
8286 case kEventWindowUpdate
:
8287 result
= CallNextEventHandler (next_handler
, event
);
8288 if (result
!= eventNotHandledErr
)
8291 do_window_update (wp
);
8294 case kEventWindowBoundsChanging
:
8295 result
= CallNextEventHandler (next_handler
, event
);
8296 if (result
!= eventNotHandledErr
)
8299 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8300 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8301 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8302 if ((attributes
& kWindowBoundsChangeUserResize
)
8303 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8304 == (PResizeInc
| PBaseSize
| PMinSize
)))
8309 GetEventParameter (event
, kEventParamCurrentBounds
,
8311 NULL
, sizeof (Rect
), NULL
, &bounds
);
8312 width
= bounds
.right
- bounds
.left
;
8313 height
= bounds
.bottom
- bounds
.top
;
8315 if (width
< size_hints
->min_width
)
8316 width
= size_hints
->min_width
;
8318 width
= size_hints
->base_width
8319 + (int) ((width
- size_hints
->base_width
)
8320 / (float) size_hints
->width_inc
+ .5)
8321 * size_hints
->width_inc
;
8323 if (height
< size_hints
->min_height
)
8324 height
= size_hints
->min_height
;
8326 height
= size_hints
->base_height
8327 + (int) ((height
- size_hints
->base_height
)
8328 / (float) size_hints
->height_inc
+ .5)
8329 * size_hints
->height_inc
;
8331 bounds
.right
= bounds
.left
+ width
;
8332 bounds
.bottom
= bounds
.top
+ height
;
8333 SetEventParameter (event
, kEventParamCurrentBounds
,
8334 typeQDRectangle
, sizeof (Rect
), &bounds
);
8340 return eventNotHandledErr
;
8343 static pascal OSStatus
8344 mac_handle_mouse_event (next_handler
, event
, data
)
8345 EventHandlerCallRef next_handler
;
8351 switch (GetEventKind (event
))
8353 case kEventMouseWheelMoved
:
8357 EventMouseWheelAxis axis
;
8361 result
= CallNextEventHandler (next_handler
, event
);
8362 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
8365 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
8366 NULL
, sizeof (WindowRef
), NULL
, &wp
);
8367 f
= mac_window_to_frame (wp
);
8368 if (f
!= mac_focus_frame (&one_mac_display_info
))
8371 GetEventParameter (event
, kEventParamMouseWheelAxis
,
8372 typeMouseWheelAxis
, NULL
,
8373 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
8374 if (axis
!= kEventMouseWheelAxisY
)
8377 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
8378 NULL
, sizeof (SInt32
), NULL
, &delta
);
8379 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
8380 NULL
, sizeof (Point
), NULL
, &point
);
8381 read_socket_inev
->kind
= WHEEL_EVENT
;
8382 read_socket_inev
->code
= 0;
8383 read_socket_inev
->modifiers
=
8384 (mac_event_to_emacs_modifiers (event
)
8385 | ((delta
< 0) ? down_modifier
: up_modifier
));
8386 SetPortWindowPort (wp
);
8387 GlobalToLocal (&point
);
8388 XSETINT (read_socket_inev
->x
, point
.h
);
8389 XSETINT (read_socket_inev
->y
, point
.v
);
8390 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
8391 read_socket_inev
->timestamp
=
8392 EventTimeToTicks (GetEventTime (event
)) * (1000/60);
8402 return eventNotHandledErr
;
8404 #endif /* USE_CARBON_EVENTS */
8408 install_window_handler (window
)
8412 #if USE_CARBON_EVENTS
8413 EventTypeSpec specs_window
[] =
8414 {{kEventClassWindow
, kEventWindowUpdate
},
8415 {kEventClassWindow
, kEventWindowBoundsChanging
}};
8416 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
8417 static EventHandlerUPP handle_window_eventUPP
= NULL
;
8418 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
8420 if (handle_window_eventUPP
== NULL
)
8421 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
8422 if (handle_mouse_eventUPP
== NULL
)
8423 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
8424 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
8425 GetEventTypeCount (specs_window
),
8426 specs_window
, NULL
, NULL
);
8428 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
8429 GetEventTypeCount (specs_mouse
),
8430 specs_mouse
, NULL
, NULL
);
8432 #if TARGET_API_MAC_CARBON
8433 if (mac_do_track_dragUPP
== NULL
)
8434 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8435 if (mac_do_receive_dragUPP
== NULL
)
8436 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8439 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8441 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8447 remove_window_handler (window
)
8450 #if TARGET_API_MAC_CARBON
8451 if (mac_do_track_dragUPP
)
8452 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8453 if (mac_do_receive_dragUPP
)
8454 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8458 /* Open Application Apple Event */
8460 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8466 /* Defined in mac.c. */
8468 path_from_vol_dir_name (char *, int, short, long, char *);
8471 /* Called when we receive an AppleEvent with an ID of
8472 "kAEOpenDocuments". This routine gets the direct parameter,
8473 extracts the FSSpecs in it, and puts their names on a list. */
8474 #pragma options align=mac68k
8475 typedef struct SelectionRange
{
8476 short unused1
; // 0 (not used)
8477 short lineNum
; // line to select (<0 to specify range)
8478 long startRange
; // start of selection range (if line < 0)
8479 long endRange
; // end of selection range (if line < 0)
8480 long unused2
; // 0 (not used)
8481 long theDate
; // modification date/time
8483 #pragma options align=reset
8486 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8491 DescType actual_type
;
8493 SelectionRange position
;
8495 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8497 goto descriptor_error_exit
;
8499 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8501 drag_and_drop_file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8502 make_number (position
.startRange
+ 1),
8503 make_number (position
.endRange
+ 1)),
8504 drag_and_drop_file_list
);
8506 /* Check to see that we got all of the required parameters from the
8507 event descriptor. For an 'odoc' event this should just be the
8509 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8510 &actual_type
, (Ptr
) &keyword
,
8511 sizeof (keyword
), &actual_size
);
8512 /* No error means that we found some unused parameters.
8513 errAEDescNotFound means that there are no more parameters. If we
8514 get an error code other than that, flag it. */
8515 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8517 err
= errAEEventNotHandled
;
8522 /* Got all the parameters we need. Now, go through the direct
8523 object list and parse it up. */
8525 long num_files_to_open
;
8527 err
= AECountItems (&the_desc
, &num_files_to_open
);
8532 /* AE file list is one based so just use that for indexing here. */
8533 for (i
= 1; i
<= num_files_to_open
; i
++)
8535 char unix_path_name
[MAXPATHLEN
];
8539 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8540 &actual_type
, &fref
, sizeof (FSRef
),
8542 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8545 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8550 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8551 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8552 if (err
!= noErr
) continue;
8554 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
8555 sizeof (unix_path_name
) - 1) == noErr
)
8557 /* x-dnd functions expect undecoded filenames. */
8558 drag_and_drop_file_list
=
8559 Fcons (make_unibyte_string (unix_path_name
,
8560 strlen (unix_path_name
)),
8561 drag_and_drop_file_list
);
8567 /* Nuke the coerced file list in any case */
8568 err2
= AEDisposeDesc(&the_desc
);
8570 descriptor_error_exit
:
8571 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8576 #if TARGET_API_MAC_CARBON
8578 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8579 void *handlerRefCon
, DragReference theDrag
)
8581 static int can_accept
;
8584 ItemReference theItem
;
8585 FlavorFlags theFlags
;
8588 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8589 return dragNotAcceptedErr
;
8593 case kDragTrackingEnterHandler
:
8594 CountDragItems (theDrag
, &items
);
8596 for (index
= 1; index
<= items
; index
++)
8598 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8599 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8600 if (result
== noErr
)
8608 case kDragTrackingEnterWindow
:
8611 RgnHandle hilite_rgn
= NewRgn ();
8613 struct frame
*f
= mac_window_to_frame (window
);
8615 GetWindowPortBounds (window
, &r
);
8616 OffsetRect (&r
, -r
.left
, -r
.top
);
8617 RectRgn (hilite_rgn
, &r
);
8618 ShowDragHilite (theDrag
, hilite_rgn
, true);
8619 DisposeRgn (hilite_rgn
);
8620 SetThemeCursor (kThemeCopyArrowCursor
);
8624 case kDragTrackingInWindow
:
8627 case kDragTrackingLeaveWindow
:
8630 struct frame
*f
= mac_window_to_frame (window
);
8632 HideDragHilite (theDrag
);
8633 SetThemeCursor (kThemeArrowCursor
);
8637 case kDragTrackingLeaveHandler
:
8645 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8646 DragReference theDrag
)
8650 FlavorFlags theFlags
;
8653 ItemReference theItem
;
8655 Size size
= sizeof (HFSFlavor
);
8657 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8658 return dragNotAcceptedErr
;
8660 drag_and_drop_file_list
= Qnil
;
8661 GetDragMouse (theDrag
, &mouse
, 0L);
8662 CountDragItems (theDrag
, &items
);
8663 for (index
= 1; index
<= items
; index
++)
8665 /* Only handle file references. */
8666 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8667 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8668 if (result
== noErr
)
8673 char unix_path_name
[MAXPATHLEN
];
8675 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8677 /* Use Carbon routines, otherwise it converts the file name
8678 to /Macintosh HD/..., which is not correct. */
8679 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8680 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8682 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
8683 sizeof (unix_path_name
) - 1) == noErr
)
8685 /* x-dnd functions expect undecoded filenames. */
8686 drag_and_drop_file_list
=
8687 Fcons (make_unibyte_string (unix_path_name
,
8688 strlen (unix_path_name
)),
8689 drag_and_drop_file_list
);
8692 /* If there are items in the list, construct an event and post it to
8693 the queue like an interrupt using kbd_buffer_store_event. */
8694 if (!NILP (drag_and_drop_file_list
))
8696 struct input_event event
;
8698 struct frame
*f
= mac_window_to_frame (window
);
8701 GlobalToLocal (&mouse
);
8702 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8704 event
.kind
= DRAG_N_DROP_EVENT
;
8706 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8707 event
.timestamp
= TickCount () * (1000 / 60);
8708 XSETINT (event
.x
, mouse
.h
);
8709 XSETINT (event
.y
, mouse
.v
);
8710 XSETFRAME (frame
, f
);
8711 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8713 /* Post to the interrupt queue */
8714 kbd_buffer_store_event (&event
);
8715 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8717 ProcessSerialNumber psn
;
8718 GetCurrentProcess (&psn
);
8719 SetFrontProcess (&psn
);
8725 return dragNotAcceptedErr
;
8730 /* Print Document Apple Event */
8732 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8734 return errAEEventNotHandled
;
8739 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8741 #if USE_CARBON_EVENTS
8743 EventRef event
= NULL
;
8744 static const HICommand quit_command
= {kEventAttributeNone
, kHICommandQuit
};
8746 err
= CreateEvent (NULL
, kEventClassCommand
, kEventCommandProcess
, 0,
8747 kEventAttributeUserEvent
, &event
);
8749 err
= SetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
8750 sizeof (HICommand
), &quit_command
);
8752 mac_store_application_menu_event (event
);
8754 ReleaseEvent (event
);
8759 return errAEEventNotHandled
;
8761 mac_store_application_menu_event (kHICommandQuit
);
8770 profiler_exit_proc ()
8772 ProfilerDump ("\pEmacs.prof");
8777 /* These few functions implement Emacs as a normal Mac application
8778 (almost): set up the heap and the Toolbox, handle necessary system
8779 events plus a few simple menu events. They also set up Emacs's
8780 access to functions defined in the rest of this file. Emacs uses
8781 function hooks to perform all its terminal I/O. A complete list of
8782 these functions appear in termhooks.h. For what they do, read the
8783 comments there and see also w32term.c and xterm.c. What's
8784 noticeably missing here is the event loop, which is normally
8785 present in most Mac application. After performing the necessary
8786 Mac initializations, main passes off control to emacs_main
8787 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
8788 (defined further below) to read input. This is where
8789 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
8796 #if __profile__ /* is the profiler on? */
8797 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
8802 /* set creator and type for files created by MSL */
8807 do_init_managers ();
8812 do_check_ram_size ();
8815 init_emacs_passwd_dir ();
8819 initialize_applescript ();
8821 init_required_apple_events ();
8827 /* set up argv array from STR# resource */
8828 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
8832 /* free up AppleScript resources on exit */
8833 atexit (terminate_applescript
);
8835 #if __profile__ /* is the profiler on? */
8836 atexit (profiler_exit_proc
);
8839 /* 3rd param "envp" never used in emacs_main */
8840 (void) emacs_main (argc
, argv
, 0);
8843 /* Never reached - real exit in Fkill_emacs */
8848 /* Table for translating Mac keycode to X keysym values. Contributed
8850 Mapping for special keys is now identical to that in Apple X11
8851 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8852 on the right of the Cmd key on laptops, and fn + `enter' (->
8854 static unsigned char keycode_to_xkeysym_table
[] = {
8855 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8856 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8857 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8859 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8860 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8861 /*0x38*/ 0, 0, 0, 0,
8862 /*0x3C*/ 0, 0, 0, 0,
8864 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8865 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8866 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8867 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8869 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8870 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8871 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8872 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8874 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8875 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8876 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8877 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8879 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8880 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8881 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8882 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8886 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8888 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8889 return *xKeySym
!= 0;
8892 #if !USE_CARBON_EVENTS
8893 static RgnHandle mouse_region
= NULL
;
8896 mac_wait_next_event (er
, sleep_time
, dequeue
)
8901 static EventRecord er_buf
= {nullEvent
};
8902 UInt32 target_tick
, current_tick
;
8903 EventMask event_mask
;
8905 if (mouse_region
== NULL
)
8906 mouse_region
= NewRgn ();
8908 event_mask
= everyEvent
;
8909 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8910 event_mask
-= highLevelEventMask
;
8912 current_tick
= TickCount ();
8913 target_tick
= current_tick
+ sleep_time
;
8915 if (er_buf
.what
== nullEvent
)
8916 while (!WaitNextEvent (event_mask
, &er_buf
,
8917 target_tick
- current_tick
, mouse_region
))
8919 current_tick
= TickCount ();
8920 if (target_tick
<= current_tick
)
8926 er_buf
.what
= nullEvent
;
8929 #endif /* not USE_CARBON_EVENTS */
8931 /* Emacs calls this whenever it wants to read an input event from the
8934 XTread_socket (sd
, expected
, hold_quit
)
8936 struct input_event
*hold_quit
;
8938 struct input_event inev
;
8940 #if USE_CARBON_EVENTS
8942 EventTargetRef toolbox_dispatcher
;
8945 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8947 if (interrupt_input_blocked
)
8949 interrupt_input_pending
= 1;
8953 interrupt_input_pending
= 0;
8956 /* So people can tell when we have read the available input. */
8957 input_signal_count
++;
8959 #if USE_CARBON_EVENTS
8960 toolbox_dispatcher
= GetEventDispatcherTarget ();
8962 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8963 kEventRemoveFromQueue
, &eventRef
))
8964 #else /* !USE_CARBON_EVENTS */
8965 while (mac_wait_next_event (&er
, 0, true))
8966 #endif /* !USE_CARBON_EVENTS */
8971 /* It is necessary to set this (additional) argument slot of an
8972 event to nil because keyboard.c protects incompletely
8973 processed event from being garbage collected by placing them
8974 in the kbd_buffer_gcpro vector. */
8976 inev
.kind
= NO_EVENT
;
8979 #if USE_CARBON_EVENTS
8980 /* Handle new events */
8981 if (!mac_convert_event_ref (eventRef
, &er
))
8983 /* There used to be a handler for the kEventMouseWheelMoved
8984 event here. But as of Mac OS X 10.4, this kind of event
8985 is not directly posted to the main event queue by
8986 two-finger scrolling on the trackpad. Instead, some
8987 private event is posted and it is converted to a wheel
8988 event by the default handler for the application target.
8989 The converted one can be received by a Carbon event
8990 handler installed on a window target. */
8991 read_socket_inev
= &inev
;
8992 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8993 read_socket_inev
= NULL
;
8996 #endif /* USE_CARBON_EVENTS */
9002 WindowPtr window_ptr
;
9003 ControlPartCode part_code
;
9006 #if USE_CARBON_EVENTS
9007 /* This is needed to send mouse events like aqua window
9008 buttons to the correct handler. */
9009 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9010 != eventNotHandledErr
)
9014 if (dpyinfo
->grabbed
&& last_mouse_frame
9015 && FRAME_LIVE_P (last_mouse_frame
))
9017 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9018 part_code
= inContent
;
9022 part_code
= FindWindow (er
.where
, &window_ptr
);
9023 if (tip_window
&& window_ptr
== tip_window
)
9025 HideWindow (tip_window
);
9026 part_code
= FindWindow (er
.where
, &window_ptr
);
9030 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
9036 f
= mac_focus_frame (dpyinfo
);
9037 saved_menu_event_location
= er
.where
;
9038 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9039 XSETFRAME (inev
.frame_or_window
, f
);
9043 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9044 SelectWindow (window_ptr
);
9047 ControlPartCode control_part_code
;
9049 Point mouse_loc
= er
.where
;
9051 ControlKind control_kind
;
9054 f
= mac_window_to_frame (window_ptr
);
9055 /* convert to local coordinates of new window */
9056 SetPortWindowPort (window_ptr
);
9058 GlobalToLocal (&mouse_loc
);
9059 #if TARGET_API_MAC_CARBON
9060 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9061 &control_part_code
);
9064 GetControlKind (ch
, &control_kind
);
9067 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9071 #if USE_CARBON_EVENTS
9072 inev
.code
= mac_get_mouse_btn (eventRef
);
9073 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9075 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9076 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9078 XSETINT (inev
.x
, mouse_loc
.h
);
9079 XSETINT (inev
.y
, mouse_loc
.v
);
9080 inev
.timestamp
= er
.when
* (1000 / 60);
9081 /* ticks to milliseconds */
9083 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9085 #ifndef USE_TOOLKIT_SCROLL_BARS
9086 /* control_part_code becomes kControlNoPart if
9087 a progress indicator is clicked. */
9088 && control_part_code
!= kControlNoPart
9089 #else /* USE_TOOLKIT_SCROLL_BARS */
9091 && control_kind
.kind
== kControlKindScrollBar
9092 #endif /* MAC_OSX */
9093 #endif /* USE_TOOLKIT_SCROLL_BARS */
9096 struct scroll_bar
*bar
;
9098 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9100 bar
= tracked_scroll_bar
;
9101 #ifndef USE_TOOLKIT_SCROLL_BARS
9102 control_part_code
= kControlIndicatorPart
;
9106 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9107 #ifdef USE_TOOLKIT_SCROLL_BARS
9108 /* Make the "Ctrl-Mouse-2 splits window" work
9109 for toolkit scroll bars. */
9110 if (er
.modifiers
& controlKey
)
9111 x_scroll_bar_handle_click (bar
, control_part_code
,
9113 else if (er
.what
== mouseDown
)
9114 x_scroll_bar_handle_press (bar
, control_part_code
,
9115 inev
.timestamp
, &inev
);
9117 x_scroll_bar_handle_release (bar
, inev
.timestamp
,
9119 #else /* not USE_TOOLKIT_SCROLL_BARS */
9120 x_scroll_bar_handle_click (bar
, control_part_code
,
9122 if (er
.what
== mouseDown
9123 && control_part_code
== kControlIndicatorPart
)
9124 tracked_scroll_bar
= bar
;
9126 tracked_scroll_bar
= NULL
;
9127 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9132 int x
= mouse_loc
.h
;
9133 int y
= mouse_loc
.v
;
9135 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9136 if (EQ (window
, f
->tool_bar_window
))
9138 if (er
.what
== mouseDown
)
9139 handle_tool_bar_click (f
, x
, y
, 1, 0);
9141 handle_tool_bar_click (f
, x
, y
, 0,
9147 XSETFRAME (inev
.frame_or_window
, f
);
9148 inev
.kind
= MOUSE_CLICK_EVENT
;
9152 if (er
.what
== mouseDown
)
9154 dpyinfo
->grabbed
|= (1 << inev
.code
);
9155 last_mouse_frame
= f
;
9156 /* Ignore any mouse motion that happened
9157 before this event; any subsequent
9158 mouse-movement Emacs events should reflect
9159 only motion after the ButtonPress. */
9164 last_tool_bar_item
= -1;
9168 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9169 /* If a button is released though it was not
9170 previously pressed, that would be because
9171 of multi-button emulation. */
9172 dpyinfo
->grabbed
= 0;
9174 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9177 #ifdef USE_TOOLKIT_SCROLL_BARS
9178 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9183 inev
.modifiers
|= down_modifier
;
9186 inev
.modifiers
|= up_modifier
;
9193 #if TARGET_API_MAC_CARBON
9194 DragWindow (window_ptr
, er
.where
, NULL
);
9195 #else /* not TARGET_API_MAC_CARBON */
9196 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9197 #endif /* not TARGET_API_MAC_CARBON */
9198 /* Update the frame parameters. */
9200 struct frame
*f
= mac_window_to_frame (window_ptr
);
9202 if (f
&& !f
->async_iconified
)
9203 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9208 if (TrackGoAway (window_ptr
, er
.where
))
9210 inev
.kind
= DELETE_WINDOW_EVENT
;
9211 XSETFRAME (inev
.frame_or_window
,
9212 mac_window_to_frame (window_ptr
));
9216 /* window resize handling added --ben */
9218 do_grow_window (window_ptr
, &er
);
9221 /* window zoom handling added --ben */
9224 if (TrackBox (window_ptr
, er
.where
, part_code
))
9225 do_zoom_window (window_ptr
, part_code
);
9235 #if USE_CARBON_EVENTS
9236 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9237 != eventNotHandledErr
)
9240 do_window_update ((WindowPtr
) er
.message
);
9245 #if USE_CARBON_EVENTS
9246 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9247 != eventNotHandledErr
)
9250 switch ((er
.message
>> 24) & 0x000000FF)
9252 case suspendResumeMessage
:
9253 if ((er
.message
& resumeFlag
) == 1)
9259 case mouseMovedMessage
:
9260 #if !USE_CARBON_EVENTS
9261 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9262 er
.where
.h
+ 1, er
.where
.v
+ 1);
9264 previous_help_echo_string
= help_echo_string
;
9265 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
9268 if (dpyinfo
->grabbed
&& last_mouse_frame
9269 && FRAME_LIVE_P (last_mouse_frame
))
9270 f
= last_mouse_frame
;
9272 f
= dpyinfo
->x_focus_frame
;
9274 if (dpyinfo
->mouse_face_hidden
)
9276 dpyinfo
->mouse_face_hidden
= 0;
9277 clear_mouse_face (dpyinfo
);
9282 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9283 Point mouse_pos
= er
.where
;
9285 SetPortWindowPort (wp
);
9287 GlobalToLocal (&mouse_pos
);
9289 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9290 #ifdef USE_TOOLKIT_SCROLL_BARS
9291 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9292 mouse_pos
, er
.when
* (1000 / 60),
9294 #else /* not USE_TOOLKIT_SCROLL_BARS */
9295 x_scroll_bar_note_movement (tracked_scroll_bar
,
9297 - XINT (tracked_scroll_bar
->top
),
9298 er
.when
* (1000 / 60));
9299 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9302 /* Generate SELECT_WINDOW_EVENTs when needed. */
9303 if (mouse_autoselect_window
)
9307 window
= window_from_coordinates (f
,
9312 /* Window will be selected only when it is
9313 not selected now and last mouse movement
9314 event was not in it. Minibuffer window
9315 will be selected iff it is active. */
9316 if (WINDOWP (window
)
9317 && !EQ (window
, last_window
)
9318 && !EQ (window
, selected_window
))
9320 inev
.kind
= SELECT_WINDOW_EVENT
;
9321 inev
.frame_or_window
= window
;
9326 note_mouse_movement (f
, &mouse_pos
);
9330 /* If the contents of the global variable
9331 help_echo_string has changed, generate a
9333 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
9341 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
9343 #if USE_CARBON_EVENTS
9344 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9345 != eventNotHandledErr
)
9348 if (window_ptr
== tip_window
)
9350 HideWindow (tip_window
);
9354 if (!is_emacs_window (window_ptr
))
9357 if ((er
.modifiers
& activeFlag
) != 0)
9359 /* A window has been activated */
9360 Point mouse_loc
= er
.where
;
9362 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9364 SetPortWindowPort (window_ptr
);
9365 GlobalToLocal (&mouse_loc
);
9366 /* Window-activated event counts as mouse movement,
9367 so update things that depend on mouse position. */
9368 note_mouse_movement (mac_window_to_frame (window_ptr
),
9373 /* A window has been deactivated */
9374 #if USE_TOOLKIT_SCROLL_BARS
9375 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9377 struct input_event event
;
9380 event
.kind
= NO_EVENT
;
9381 x_scroll_bar_handle_release (tracked_scroll_bar
,
9382 er
.when
* (1000 / 60),
9384 if (event
.kind
!= NO_EVENT
)
9386 kbd_buffer_store_event_hold (&event
, hold_quit
);
9391 dpyinfo
->grabbed
= 0;
9393 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9395 f
= mac_window_to_frame (window_ptr
);
9396 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9398 /* If we move outside the frame, then we're
9399 certainly no longer on any text in the
9401 clear_mouse_face (dpyinfo
);
9402 dpyinfo
->mouse_face_mouse_frame
= 0;
9405 /* Generate a nil HELP_EVENT to cancel a help-echo.
9406 Do it only if there's something to cancel.
9407 Otherwise, the startup message is cleared when the
9408 mouse leaves the frame. */
9409 if (any_help_event_p
)
9418 int keycode
= (er
.message
& keyCodeMask
) >> 8;
9421 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9422 /* When using Carbon Events, we need to pass raw keyboard
9423 events to the TSM ourselves. If TSM handles it, it
9424 will pass back noErr, otherwise it will pass back
9425 "eventNotHandledErr" and we can process it
9427 if ((!NILP (Vmac_pass_command_to_system
)
9428 || !(er
.modifiers
& cmdKey
))
9429 && (!NILP (Vmac_pass_control_to_system
)
9430 || !(er
.modifiers
& controlKey
))
9431 && (!NILP (Vmac_command_key_is_meta
)
9432 && NILP (Vmac_option_modifier
)
9433 || !(er
.modifiers
& optionKey
)))
9434 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9435 != eventNotHandledErr
)
9440 if (dpyinfo
->x_focus_frame
== NULL
)
9442 /* Beep if keyboard input occurs when all the frames
9450 static SInt16 last_key_script
= -1;
9451 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
9453 if (last_key_script
!= current_key_script
)
9455 struct input_event event
;
9458 event
.kind
= LANGUAGE_CHANGE_EVENT
;
9460 event
.code
= current_key_script
;
9461 kbd_buffer_store_event (&event
);
9464 last_key_script
= current_key_script
;
9469 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
9471 clear_mouse_face (dpyinfo
);
9472 dpyinfo
->mouse_face_hidden
= 1;
9475 if (keycode_to_xkeysym (keycode
, &xkeysym
))
9477 inev
.code
= 0xff00 | xkeysym
;
9478 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
9482 if (er
.modifiers
& (controlKey
|
9483 (NILP (Vmac_command_key_is_meta
) ? optionKey
9486 /* This code comes from Keyboard Resource,
9487 Appendix C of IM - Text. This is necessary
9488 since shift is ignored in KCHR table
9489 translation when option or command is pressed.
9490 It also does not translate correctly
9491 control-shift chars like C-% so mask off shift
9493 int new_modifiers
= er
.modifiers
& 0xe600;
9494 /* mask off option and command */
9495 int new_keycode
= keycode
| new_modifiers
;
9496 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9497 unsigned long some_state
= 0;
9498 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9499 &some_state
) & 0xff;
9501 else if (!NILP (Vmac_option_modifier
)
9502 && (er
.modifiers
& optionKey
))
9504 /* When using the option key as an emacs modifier,
9505 convert the pressed key code back to one
9506 without the Mac option modifier applied. */
9507 int new_modifiers
= er
.modifiers
& ~optionKey
;
9508 int new_keycode
= keycode
| new_modifiers
;
9509 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9510 unsigned long some_state
= 0;
9511 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9512 &some_state
) & 0xff;
9515 inev
.code
= er
.message
& charCodeMask
;
9516 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9520 #if USE_CARBON_EVENTS
9521 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9523 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9525 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
9526 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9529 case kHighLevelEvent
:
9530 drag_and_drop_file_list
= Qnil
;
9532 AEProcessAppleEvent(&er
);
9534 /* Build a DRAG_N_DROP_EVENT type event as is done in
9535 constuct_drag_n_drop in w32term.c. */
9536 if (!NILP (drag_and_drop_file_list
))
9538 struct frame
*f
= mac_focus_frame (dpyinfo
);
9542 inev
.kind
= DRAG_N_DROP_EVENT
;
9544 inev
.timestamp
= er
.when
* (1000 / 60);
9545 /* ticks to milliseconds */
9546 #if USE_CARBON_EVENTS
9547 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9549 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9552 XSETINT (inev
.x
, 0);
9553 XSETINT (inev
.y
, 0);
9555 XSETFRAME (frame
, f
);
9556 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9559 /* Regardless of whether Emacs was suspended or in the
9560 foreground, ask it to redraw its entire screen.
9561 Otherwise parts of the screen can be left in an
9562 inconsistent state. */
9563 wp
= FRAME_MAC_WINDOW (f
);
9565 #if TARGET_API_MAC_CARBON
9569 GetWindowPortBounds (wp
, &r
);
9570 InvalWindowRect (wp
, &r
);
9572 #else /* not TARGET_API_MAC_CARBON */
9573 InvalRect (&(wp
->portRect
));
9574 #endif /* not TARGET_API_MAC_CARBON */
9580 #if USE_CARBON_EVENTS
9581 ReleaseEvent (eventRef
);
9584 if (inev
.kind
!= NO_EVENT
)
9586 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9591 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9596 XSETFRAME (frame
, f
);
9602 any_help_event_p
= 1;
9603 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9604 help_echo_object
, help_echo_pos
);
9608 help_echo_string
= Qnil
;
9609 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9616 /* If the focus was just given to an autoraising frame,
9618 /* ??? This ought to be able to handle more than one such frame. */
9619 if (pending_autoraise_frame
)
9621 x_raise_frame (pending_autoraise_frame
);
9622 pending_autoraise_frame
= 0;
9630 /* Need to override CodeWarrior's input function so no conversion is
9631 done on newlines Otherwise compiled functions in .elc files will be
9632 read incorrectly. Defined in ...:MSL C:MSL
9633 Common:Source:buffer_io.c. */
9636 __convert_to_newlines (unsigned char * p
, size_t * n
)
9642 __convert_from_newlines (unsigned char * p
, size_t * n
)
9650 make_mac_terminal_frame (struct frame
*f
)
9655 XSETFRAME (frame
, f
);
9657 f
->output_method
= output_mac
;
9658 f
->output_data
.mac
= (struct mac_output
*)
9659 xmalloc (sizeof (struct mac_output
));
9660 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9662 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9664 FRAME_COLS (f
) = 96;
9665 FRAME_LINES (f
) = 4;
9667 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9668 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9670 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9672 f
->output_data
.mac
->cursor_pixel
= 0;
9673 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9674 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9675 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9677 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9678 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9679 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9680 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9681 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9682 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9684 FRAME_FONTSET (f
) = -1;
9685 f
->output_data
.mac
->explicit_parent
= 0;
9688 f
->border_width
= 0;
9690 f
->internal_border_width
= 0;
9695 f
->new_text_cols
= 0;
9696 f
->new_text_lines
= 0;
9698 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9699 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9700 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9704 if (!(FRAME_MAC_WINDOW (f
) =
9705 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9706 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9708 /* so that update events can find this mac_output struct */
9709 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9715 /* Need to be initialized for unshow_buffer in window.c. */
9716 selected_window
= f
->selected_window
;
9718 Fmodify_frame_parameters (frame
,
9719 Fcons (Fcons (Qfont
,
9720 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9721 Fmodify_frame_parameters (frame
,
9722 Fcons (Fcons (Qforeground_color
,
9723 build_string ("black")), Qnil
));
9724 Fmodify_frame_parameters (frame
,
9725 Fcons (Fcons (Qbackground_color
,
9726 build_string ("white")), Qnil
));
9731 /***********************************************************************
9733 ***********************************************************************/
9735 int mac_initialized
= 0;
9738 mac_initialize_display_info ()
9740 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9741 GDHandle main_device_handle
;
9743 bzero (dpyinfo
, sizeof (*dpyinfo
));
9746 dpyinfo
->mac_id_name
9747 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9748 + SCHARS (Vsystem_name
)
9750 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9751 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9753 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9754 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9757 main_device_handle
= LMGetMainDevice();
9759 dpyinfo
->reference_count
= 0;
9760 dpyinfo
->resx
= 75.0;
9761 dpyinfo
->resy
= 75.0;
9762 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9764 /* HasDepth returns true if it is possible to have a 32 bit display,
9765 but this may not be what is actually used. Mac OSX can do better.
9766 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9767 header for CGGetActiveDisplayList says that the first display returned
9768 is the active one, so we use that. */
9770 CGDirectDisplayID disp_id
[1];
9771 CGDisplayCount disp_count
;
9772 CGDisplayErr error_code
;
9774 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
9775 if (error_code
!= 0)
9776 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
9778 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
9781 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
9782 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
9783 gdDevType
, dpyinfo
->color_p
))
9786 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
9787 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
9788 dpyinfo
->grabbed
= 0;
9789 dpyinfo
->root_window
= NULL
;
9790 dpyinfo
->image_cache
= make_image_cache ();
9792 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9793 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9794 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9795 dpyinfo
->mouse_face_window
= Qnil
;
9796 dpyinfo
->mouse_face_overlay
= Qnil
;
9797 dpyinfo
->mouse_face_hidden
= 0;
9802 mac_make_rdb (xrm_option
)
9805 XrmDatabase database
;
9807 database
= xrm_get_preference_database (NULL
);
9809 xrm_merge_string_database (database
, xrm_option
);
9814 struct mac_display_info
*
9815 mac_term_init (display_name
, xrm_option
, resource_name
)
9816 Lisp_Object display_name
;
9818 char *resource_name
;
9820 struct mac_display_info
*dpyinfo
;
9824 if (!mac_initialized
)
9827 mac_initialized
= 1;
9831 error ("Sorry, this version can only handle one display");
9833 mac_initialize_display_info ();
9835 dpyinfo
= &one_mac_display_info
;
9837 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
9839 /* Put this display on the chain. */
9840 dpyinfo
->next
= x_display_list
;
9841 x_display_list
= dpyinfo
;
9843 /* Put it on x_display_name_list. */
9844 x_display_name_list
= Fcons (Fcons (display_name
,
9845 Fcons (Qnil
, dpyinfo
->xrdb
)),
9846 x_display_name_list
);
9847 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9853 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9856 x_delete_display (dpyinfo
)
9857 struct mac_display_info
*dpyinfo
;
9861 /* Discard this display from x_display_name_list and x_display_list.
9862 We can't use Fdelq because that can quit. */
9863 if (! NILP (x_display_name_list
)
9864 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9865 x_display_name_list
= XCDR (x_display_name_list
);
9870 tail
= x_display_name_list
;
9871 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9873 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9875 XSETCDR (tail
, XCDR (XCDR (tail
)));
9882 if (x_display_list
== dpyinfo
)
9883 x_display_list
= dpyinfo
->next
;
9886 struct x_display_info
*tail
;
9888 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9889 if (tail
->next
== dpyinfo
)
9890 tail
->next
= tail
->next
->next
;
9893 /* Free the font names in the font table. */
9894 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9895 if (dpyinfo
->font_table
[i
].name
)
9897 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9898 xfree (dpyinfo
->font_table
[i
].full_name
);
9899 xfree (dpyinfo
->font_table
[i
].name
);
9902 if (dpyinfo
->font_table
->font_encoder
)
9903 xfree (dpyinfo
->font_table
->font_encoder
);
9905 xfree (dpyinfo
->font_table
);
9906 xfree (dpyinfo
->mac_id_name
);
9908 if (x_display_list
== 0)
9910 mac_clear_font_name_table ();
9911 bzero (dpyinfo
, sizeof (*dpyinfo
));
9920 extern int inhibit_window_system
;
9921 extern int noninteractive
;
9922 CFBundleRef appsBundle
;
9925 /* No need to test if already -nw*/
9926 if (inhibit_window_system
|| noninteractive
)
9929 appsBundle
= CFBundleGetMainBundle();
9930 if (appsBundle
!= NULL
)
9932 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
9933 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
9934 /* We found the bundle identifier, now we know we are valid. */
9941 /* MAC_TODO: Have this start the bundled executable */
9943 /* For now, prevent the fatal error by bringing it up in the terminal */
9944 inhibit_window_system
= 1;
9948 MakeMeTheFrontProcess ()
9950 ProcessSerialNumber psn
;
9953 err
= GetCurrentProcess (&psn
);
9955 (void) SetFrontProcess (&psn
);
9958 /***** Code to handle C-g testing *****/
9960 /* Contains the Mac modifier formed from quit_char */
9961 int mac_quit_char_modifiers
= 0;
9962 int mac_quit_char_keycode
;
9963 extern int quit_char
;
9966 mac_determine_quit_char_modifiers()
9968 /* Todo: Determine modifiers from quit_char. */
9969 UInt32 qc_modifiers
= ctrl_modifier
;
9972 mac_quit_char_modifiers
= 0;
9973 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
9974 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
9975 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
9976 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
9980 init_quit_char_handler ()
9982 /* TODO: Let this support keys other the 'g' */
9983 mac_quit_char_keycode
= 5;
9984 /* Look at <architecture/adb_kb_map.h> for details */
9985 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9987 mac_determine_quit_char_modifiers();
9991 quit_char_comp (EventRef inEvent
, void *inCompData
)
9993 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
9995 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
9999 UInt32 keyModifiers
;
10000 GetEventParameter(inEvent
, kEventParamKeyCode
,
10001 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
10002 if (keyCode
!= mac_quit_char_keycode
)
10004 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
10005 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
10006 if (keyModifiers
!= mac_quit_char_modifiers
)
10013 mac_check_for_quit_char ()
10016 static EMACS_TIME last_check_time
= { 0, 0 };
10017 static EMACS_TIME one_second
= { 1, 0 };
10020 /* If windows are not initialized, return immediately (keep it bouncin'). */
10021 if (!mac_quit_char_modifiers
)
10024 /* Don't check if last check is less than a second ago. */
10025 EMACS_GET_TIME (now
);
10026 EMACS_SUB_TIME (t
, now
, last_check_time
);
10027 if (EMACS_TIME_LT (t
, one_second
))
10029 last_check_time
= now
;
10031 /* Redetermine modifiers because they are based on lisp variables */
10032 mac_determine_quit_char_modifiers ();
10034 /* Fill the queue with events */
10036 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
10037 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
10042 struct input_event e
;
10044 /* Use an input_event to emulate what the interrupt handler does. */
10046 e
.kind
= ASCII_KEYSTROKE_EVENT
;
10047 e
.code
= quit_char
;
10049 e
.modifiers
= NULL
;
10050 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
10051 XSETFRAME (e
.frame_or_window
, mac_focus_frame (&one_mac_display_info
));
10052 /* Remove event from queue to prevent looping. */
10053 RemoveEventFromQueue (GetMainEventQueue (), event
);
10054 ReleaseEvent (event
);
10055 kbd_buffer_store_event (&e
);
10058 #endif /* MAC_OSX */
10066 MenuItemIndex menu_index
;
10068 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10069 &menu
, &menu_index
);
10071 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10072 #if USE_CARBON_EVENTS
10073 EnableMenuCommand (NULL
, kHICommandPreferences
);
10074 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10075 &menu
, &menu_index
);
10078 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10079 InsertMenuItemTextWithCFString (menu
, NULL
,
10080 0, kMenuItemAttrSeparator
, 0);
10081 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10082 0, 0, kHICommandAbout
);
10084 #endif /* USE_CARBON_EVENTS */
10085 #else /* !MAC_OSX */
10086 #if USE_CARBON_EVENTS
10087 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10093 /* Set up use of X before we make the first connection. */
10095 extern frame_parm_handler mac_frame_parm_handlers
[];
10097 static struct redisplay_interface x_redisplay_interface
=
10099 mac_frame_parm_handlers
,
10103 x_clear_end_of_line
,
10105 x_after_update_window_line
,
10106 x_update_window_begin
,
10107 x_update_window_end
,
10110 0, /* flush_display_optional */
10111 x_clear_window_mouse_face
,
10112 x_get_glyph_overhangs
,
10113 x_fix_overlapping_area
,
10114 x_draw_fringe_bitmap
,
10115 0, /* define_fringe_bitmap */
10116 0, /* destroy_fringe_bitmap */
10117 mac_per_char_metric
,
10119 mac_compute_glyph_string_overhangs
,
10120 x_draw_glyph_string
,
10121 mac_define_frame_cursor
,
10122 mac_clear_frame_area
,
10123 mac_draw_window_cursor
,
10124 mac_draw_vertical_window_border
,
10125 mac_shift_glyphs_for_insert
10131 rif
= &x_redisplay_interface
;
10133 clear_frame_hook
= x_clear_frame
;
10134 ins_del_lines_hook
= x_ins_del_lines
;
10135 delete_glyphs_hook
= x_delete_glyphs
;
10136 ring_bell_hook
= XTring_bell
;
10137 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10138 set_terminal_modes_hook
= XTset_terminal_modes
;
10139 update_begin_hook
= x_update_begin
;
10140 update_end_hook
= x_update_end
;
10141 set_terminal_window_hook
= XTset_terminal_window
;
10142 read_socket_hook
= XTread_socket
;
10143 frame_up_to_date_hook
= XTframe_up_to_date
;
10144 mouse_position_hook
= XTmouse_position
;
10145 frame_rehighlight_hook
= XTframe_rehighlight
;
10146 frame_raise_lower_hook
= XTframe_raise_lower
;
10148 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10149 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10150 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10151 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10153 scroll_region_ok
= 1; /* we'll scroll partial frames */
10154 char_ins_del_ok
= 1;
10155 line_ins_del_ok
= 1; /* we'll just blt 'em */
10156 fast_clear_end_of_line
= 1; /* X does this well */
10157 memory_below_frame
= 0; /* we don't remember what scrolls
10162 last_tool_bar_item
= -1;
10163 any_help_event_p
= 0;
10165 /* Try to use interrupt input; if we can't, then start polling. */
10166 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10170 #if TARGET_API_MAC_CARBON
10171 init_required_apple_events ();
10173 #if USE_CARBON_EVENTS
10175 init_service_handler ();
10177 init_quit_char_handler ();
10178 #endif /* MAC_OSX */
10180 init_command_handler ();
10183 #endif /* USE_CARBON_EVENTS */
10186 if (!inhibit_window_system
)
10187 MakeMeTheFrontProcess ();
10198 staticpro (&x_error_message_string
);
10199 x_error_message_string
= Qnil
;
10202 Qmodifier_value
= intern ("modifier-value");
10203 Qalt
= intern ("alt");
10204 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10205 Qhyper
= intern ("hyper");
10206 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10207 Qsuper
= intern ("super");
10208 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10210 Qapplication
= intern ("application"); staticpro (&Qapplication
);
10211 Qabout
= intern ("about"); staticpro (&Qabout
);
10213 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10214 Qpreferences
= intern ("preferences"); staticpro (&Qpreferences
);
10215 Qservices
= intern ("services"); staticpro (&Qservices
);
10216 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10217 Qperform
= intern ("perform"); staticpro (&Qperform
);
10221 Fprovide (intern ("mac-carbon"), Qnil
);
10224 staticpro (&Qreverse
);
10225 Qreverse
= intern ("reverse");
10227 staticpro (&x_display_name_list
);
10228 x_display_name_list
= Qnil
;
10230 staticpro (&last_mouse_scroll_bar
);
10231 last_mouse_scroll_bar
= Qnil
;
10233 staticpro (&Qvendor_specific_keysyms
);
10234 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
10236 staticpro (&last_mouse_press_frame
);
10237 last_mouse_press_frame
= Qnil
;
10239 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
10240 staticpro (&Qmac_ready_for_drag_n_drop
);
10242 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10243 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10244 #ifdef USE_TOOLKIT_SCROLL_BARS
10245 Vx_toolkit_scroll_bars
= Qt
;
10247 Vx_toolkit_scroll_bars
= Qnil
;
10250 DEFVAR_BOOL ("x-use-underline-position-properties",
10251 &x_use_underline_position_properties
,
10252 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10253 nil means ignore them. If you encounter fonts with bogus
10254 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10255 to 4.1, set this to nil. */);
10256 x_use_underline_position_properties
= 0;
10258 staticpro (&last_mouse_motion_frame
);
10259 last_mouse_motion_frame
= Qnil
;
10261 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
10262 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
10263 Otherwise the option key is used. */);
10264 Vmac_command_key_is_meta
= Qt
;
10266 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10267 doc
: /* Modifier to use for the Mac alt/option key. The value can
10268 be alt, hyper, or super for the respective modifier. If the value is
10269 nil then the key will act as the normal Mac option modifier. */);
10270 Vmac_option_modifier
= Qnil
;
10272 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
10273 doc
: /* Non-nil means that the control and meta keys are reversed. This is
10274 useful for non-standard keyboard layouts. */);
10275 Vmac_reverse_ctrl_meta
= Qnil
;
10277 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10278 &Vmac_emulate_three_button_mouse
,
10279 doc
: /* t means that when the option-key is held down while pressing the
10280 mouse button, the click will register as mouse-2 and while the
10281 command-key is held down, the click will register as mouse-3.
10282 'reverse means that the the option-key will register for mouse-3
10283 and the command-key will register for mouse-2. nil means that
10284 no emulation should be done and the modifiers should be placed
10285 on the mouse-1 event. */);
10286 Vmac_emulate_three_button_mouse
= Qnil
;
10288 #if USE_CARBON_EVENTS
10289 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
10290 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
10291 the right click will be mouse-3.
10292 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10293 Vmac_wheel_button_is_mouse_2
= Qt
;
10295 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
10296 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10297 Toolbox for processing before Emacs sees it. */);
10298 Vmac_pass_command_to_system
= Qt
;
10300 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
10301 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10302 Toolbox for processing before Emacs sees it. */);
10303 Vmac_pass_control_to_system
= Qt
;
10307 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
10308 doc
: /* If non-nil, allow anti-aliasing.
10309 The text will be rendered using Core Graphics text rendering which
10310 may anti-alias the text. */);
10311 Vmac_use_core_graphics
= Qnil
;
10313 /* Register an entry for `mac-roman' so that it can be used when
10314 creating the terminal frame on Mac OS 9 before loading
10315 term/mac-win.elc. */
10316 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10317 doc
: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10318 Each entry should be of the form:
10320 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10322 where CHARSET-NAME is a string used in font names to identify the
10323 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10324 is a coding system corresponding to TEXT-ENCODING. */);
10325 Vmac_charset_info_alist
=
10326 Fcons (list3 (build_string ("mac-roman"),
10327 make_number (smRoman
), Qnil
), Qnil
);
10330 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10331 (do not change this comment) */