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
));
1339 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1341 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1344 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1345 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1349 /* End update of window W (which is equal to updated_window).
1351 Draw vertical borders between horizontally adjacent windows, and
1352 display W's cursor if CURSOR_ON_P is non-zero.
1354 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1355 glyphs in mouse-face were overwritten. In that case we have to
1356 make sure that the mouse-highlight is properly redrawn.
1358 W may be a menu bar pseudo-window in case we don't have X toolkit
1359 support. Such windows don't have a cursor, so don't display it
1363 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1365 int cursor_on_p
, mouse_face_overwritten_p
;
1367 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1369 if (!w
->pseudo_window_p
)
1374 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1376 output_cursor
.x
, output_cursor
.y
);
1378 if (draw_window_fringes (w
, 1))
1379 x_draw_vertical_border (w
);
1384 /* If a row with mouse-face was overwritten, arrange for
1385 XTframe_up_to_date to redisplay the mouse highlight. */
1386 if (mouse_face_overwritten_p
)
1388 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1389 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1390 dpyinfo
->mouse_face_window
= Qnil
;
1394 /* Unhide the caret. This won't actually show the cursor, unless it
1395 was visible before the corresponding call to HideCaret in
1396 x_update_window_begin. */
1397 if (w32_use_visible_system_caret
)
1398 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1401 updated_window
= NULL
;
1405 /* End update of frame F. This function is installed as a hook in
1412 /* Mouse highlight may be displayed again. */
1413 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1416 #if TARGET_API_MAC_CARBON
1417 EnableScreenUpdates ();
1419 XFlush (FRAME_MAC_DISPLAY (f
));
1424 /* This function is called from various places in xdisp.c whenever a
1425 complete update has been performed. The global variable
1426 updated_window is not available here. */
1429 XTframe_up_to_date (f
)
1432 if (FRAME_MAC_P (f
))
1434 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1436 if (dpyinfo
->mouse_face_deferred_gc
1437 || f
== dpyinfo
->mouse_face_mouse_frame
)
1440 if (dpyinfo
->mouse_face_mouse_frame
)
1441 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1442 dpyinfo
->mouse_face_mouse_x
,
1443 dpyinfo
->mouse_face_mouse_y
);
1444 dpyinfo
->mouse_face_deferred_gc
= 0;
1451 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1452 arrow bitmaps, or clear the fringes if no bitmaps are required
1453 before DESIRED_ROW is made current. The window being updated is
1454 found in updated_window. This function is called from
1455 update_window_line only if it is known that there are differences
1456 between bitmaps to be drawn between current row and DESIRED_ROW. */
1459 x_after_update_window_line (desired_row
)
1460 struct glyph_row
*desired_row
;
1462 struct window
*w
= updated_window
;
1468 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1469 desired_row
->redraw_fringe_bitmaps_p
= 1;
1471 /* When a window has disappeared, make sure that no rest of
1472 full-width rows stays visible in the internal border. Could
1473 check here if updated_window is the leftmost/rightmost window,
1474 but I guess it's not worth doing since vertically split windows
1475 are almost never used, internal border is rarely set, and the
1476 overhead is very small. */
1477 if (windows_or_buffers_changed
1478 && desired_row
->full_width_p
1479 && (f
= XFRAME (w
->frame
),
1480 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1482 && (height
= desired_row
->visible_height
,
1485 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1486 /* Internal border is drawn below the tool bar. */
1487 if (WINDOWP (f
->tool_bar_window
)
1488 && w
== XWINDOW (f
->tool_bar_window
))
1493 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1494 0, y
, width
, height
, 0);
1495 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1496 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1504 /* Draw the bitmap WHICH in one of the left or right fringes of
1505 window W. ROW is the glyph row for which to display the bitmap; it
1506 determines the vertical position at which the bitmap has to be
1510 x_draw_fringe_bitmap (w
, row
, p
)
1512 struct glyph_row
*row
;
1513 struct draw_fringe_bitmap_params
*p
;
1515 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1516 Display
*display
= FRAME_MAC_DISPLAY (f
);
1517 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1519 GC gc
= f
->output_data
.mac
->normal_gc
;
1520 struct face
*face
= p
->face
;
1523 /* Must clip because of partially visible lines. */
1524 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1527 /* Adjust position of "bottom aligned" bitmap on partially
1528 visible last row. */
1530 int oldVH
= row
->visible_height
;
1531 row
->visible_height
= p
->h
;
1532 row
->y
-= rowY
- p
->y
;
1533 x_clip_to_row (w
, row
, -1, gc
);
1535 row
->visible_height
= oldVH
;
1538 x_clip_to_row (w
, row
, -1, gc
);
1540 if (p
->bx
>= 0 && !p
->overlay_p
)
1543 gcv
.foreground
= face
->background
;
1545 #if 0 /* MAC_TODO: stipple */
1546 /* In case the same realized face is used for fringes and
1547 for something displayed in the text (e.g. face `region' on
1548 mono-displays, the fill style may have been changed to
1549 FillSolid in x_draw_glyph_string_background. */
1551 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1553 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1556 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1558 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1560 #if 0 /* MAC_TODO: stipple */
1562 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1568 unsigned short *bits
= p
->bits
+ p
->dh
;
1570 gcv
.foreground
= (p
->cursor_p
1571 ? (p
->overlay_p
? face
->background
1572 : f
->output_data
.mac
->cursor_pixel
)
1573 : face
->foreground
);
1574 gcv
.background
= face
->background
;
1576 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
,
1577 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1580 mac_reset_clipping (display
, window
);
1584 /* This is called when starting Emacs and when restarting after
1585 suspend. When starting Emacs, no window is mapped. And nothing
1586 must be done to Emacs's own window if it is suspended (though that
1590 XTset_terminal_modes ()
1594 /* This is called when exiting or suspending Emacs. Exiting will make
1595 the windows go away, and suspending requires no action. */
1598 XTreset_terminal_modes ()
1603 /***********************************************************************
1605 ***********************************************************************/
1607 /* Function prototypes of this page. */
1609 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1610 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1613 /* Return a pointer to per-char metric information in FONT of a
1614 character pointed by B which is a pointer to an XChar2b. */
1616 #define PER_CHAR_METRIC(font, b) \
1618 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1619 + (((font)->min_byte1 || (font)->max_byte1) \
1620 ? (((b)->byte1 - (font)->min_byte1) \
1621 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1623 : &((font)->max_bounds))
1626 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1627 is not contained in the font. */
1629 static INLINE XCharStruct
*
1630 x_per_char_metric (font
, char2b
)
1634 /* The result metric information. */
1635 XCharStruct
*pcm
= NULL
;
1637 xassert (font
&& char2b
);
1639 if (font
->per_char
!= NULL
)
1641 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1643 /* min_char_or_byte2 specifies the linear character index
1644 corresponding to the first element of the per_char array,
1645 max_char_or_byte2 is the index of the last character. A
1646 character with non-zero CHAR2B->byte1 is not in the font.
1647 A character with byte2 less than min_char_or_byte2 or
1648 greater max_char_or_byte2 is not in the font. */
1649 if (char2b
->byte1
== 0
1650 && char2b
->byte2
>= font
->min_char_or_byte2
1651 && char2b
->byte2
<= font
->max_char_or_byte2
)
1652 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1656 /* If either min_byte1 or max_byte1 are nonzero, both
1657 min_char_or_byte2 and max_char_or_byte2 are less than
1658 256, and the 2-byte character index values corresponding
1659 to the per_char array element N (counting from 0) are:
1661 byte1 = N/D + min_byte1
1662 byte2 = N\D + min_char_or_byte2
1666 D = max_char_or_byte2 - min_char_or_byte2 + 1
1667 / = integer division
1668 \ = integer modulus */
1669 if (char2b
->byte1
>= font
->min_byte1
1670 && char2b
->byte1
<= font
->max_byte1
1671 && char2b
->byte2
>= font
->min_char_or_byte2
1672 && char2b
->byte2
<= font
->max_char_or_byte2
)
1674 pcm
= (font
->per_char
1675 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1676 * (char2b
->byte1
- font
->min_byte1
))
1677 + (char2b
->byte2
- font
->min_char_or_byte2
));
1683 /* If the per_char pointer is null, all glyphs between the first
1684 and last character indexes inclusive have the same
1685 information, as given by both min_bounds and max_bounds. */
1686 if (char2b
->byte2
>= font
->min_char_or_byte2
1687 && char2b
->byte2
<= font
->max_char_or_byte2
)
1688 pcm
= &font
->max_bounds
;
1691 return ((pcm
== NULL
1692 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1699 static XCharStruct
*
1700 mac_per_char_metric (font
, char2b
, font_type
)
1705 return x_per_char_metric (font
, char2b
);
1709 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1710 the two-byte form of C. Encoding is returned in *CHAR2B. */
1713 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1716 struct font_info
*font_info
;
1719 int charset
= CHAR_CHARSET (c
);
1720 XFontStruct
*font
= font_info
->font
;
1722 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1723 This may be either a program in a special encoder language or a
1725 if (font_info
->font_encoder
)
1727 /* It's a program. */
1728 struct ccl_program
*ccl
= font_info
->font_encoder
;
1730 check_ccl_update (ccl
);
1731 if (CHARSET_DIMENSION (charset
) == 1)
1733 ccl
->reg
[0] = charset
;
1734 ccl
->reg
[1] = char2b
->byte2
;
1739 ccl
->reg
[0] = charset
;
1740 ccl
->reg
[1] = char2b
->byte1
;
1741 ccl
->reg
[2] = char2b
->byte2
;
1744 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1746 /* We assume that MSBs are appropriately set/reset by CCL
1748 if (font
->max_byte1
== 0) /* 1-byte font */
1749 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1751 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1753 else if (font_info
->encoding
[charset
])
1755 /* Fixed encoding scheme. See fontset.h for the meaning of the
1756 encoding numbers. */
1757 int enc
= font_info
->encoding
[charset
];
1759 if ((enc
== 1 || enc
== 2)
1760 && CHARSET_DIMENSION (charset
) == 2)
1761 char2b
->byte1
|= 0x80;
1763 if (enc
== 1 || enc
== 3)
1764 char2b
->byte2
|= 0x80;
1770 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1771 char2b
->byte1
= sjis1
;
1772 char2b
->byte2
= sjis2
;
1777 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1779 return FONT_TYPE_UNKNOWN
;
1784 /***********************************************************************
1786 ***********************************************************************/
1789 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1790 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1791 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1793 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1794 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1795 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1796 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1797 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1798 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1799 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1800 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1801 unsigned long *, double, int));*/
1802 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1803 double, int, unsigned long));
1804 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1805 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1806 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1807 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1808 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1809 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1811 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1812 int, int, int, int, int, int,
1814 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1815 int, int, int, Rect
*));
1818 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1822 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1827 struct glyph_string
*s
;
1829 if (s
->font
== FRAME_FONT (s
->f
)
1830 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1831 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1833 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1836 /* Cursor on non-default face: must merge. */
1840 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1841 xgcv
.foreground
= s
->face
->background
;
1843 /* If the glyph would be invisible, try a different foreground. */
1844 if (xgcv
.foreground
== xgcv
.background
)
1845 xgcv
.foreground
= s
->face
->foreground
;
1846 if (xgcv
.foreground
== xgcv
.background
)
1847 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1848 if (xgcv
.foreground
== xgcv
.background
)
1849 xgcv
.foreground
= s
->face
->foreground
;
1851 /* Make sure the cursor is distinct from text in this face. */
1852 if (xgcv
.background
== s
->face
->background
1853 && xgcv
.foreground
== s
->face
->foreground
)
1855 xgcv
.background
= s
->face
->foreground
;
1856 xgcv
.foreground
= s
->face
->background
;
1859 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1860 xgcv
.font
= s
->font
;
1861 mask
= GCForeground
| GCBackground
| GCFont
;
1863 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1864 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1867 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1868 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1870 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1875 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1878 x_set_mouse_face_gc (s
)
1879 struct glyph_string
*s
;
1884 /* What face has to be used last for the mouse face? */
1885 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1886 face
= FACE_FROM_ID (s
->f
, face_id
);
1888 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1890 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1891 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1893 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1894 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1895 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1897 /* If font in this face is same as S->font, use it. */
1898 if (s
->font
== s
->face
->font
)
1899 s
->gc
= s
->face
->gc
;
1902 /* Otherwise construct scratch_cursor_gc with values from FACE
1907 xgcv
.background
= s
->face
->background
;
1908 xgcv
.foreground
= s
->face
->foreground
;
1909 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1910 xgcv
.font
= s
->font
;
1911 mask
= GCForeground
| GCBackground
| GCFont
;
1913 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1914 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1917 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1918 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1920 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1923 xassert (s
->gc
!= 0);
1927 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1928 Faces to use in the mode line have already been computed when the
1929 matrix was built, so there isn't much to do, here. */
1932 x_set_mode_line_face_gc (s
)
1933 struct glyph_string
*s
;
1935 s
->gc
= s
->face
->gc
;
1939 /* Set S->gc of glyph string S for drawing that glyph string. Set
1940 S->stippled_p to a non-zero value if the face of S has a stipple
1944 x_set_glyph_string_gc (s
)
1945 struct glyph_string
*s
;
1947 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1949 if (s
->hl
== DRAW_NORMAL_TEXT
)
1951 s
->gc
= s
->face
->gc
;
1952 s
->stippled_p
= s
->face
->stipple
!= 0;
1954 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1956 x_set_mode_line_face_gc (s
);
1957 s
->stippled_p
= s
->face
->stipple
!= 0;
1959 else if (s
->hl
== DRAW_CURSOR
)
1961 x_set_cursor_gc (s
);
1964 else if (s
->hl
== DRAW_MOUSE_FACE
)
1966 x_set_mouse_face_gc (s
);
1967 s
->stippled_p
= s
->face
->stipple
!= 0;
1969 else if (s
->hl
== DRAW_IMAGE_RAISED
1970 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1972 s
->gc
= s
->face
->gc
;
1973 s
->stippled_p
= s
->face
->stipple
!= 0;
1977 s
->gc
= s
->face
->gc
;
1978 s
->stippled_p
= s
->face
->stipple
!= 0;
1981 /* GC must have been set. */
1982 xassert (s
->gc
!= 0);
1986 /* Set clipping for output of glyph string S. S may be part of a mode
1987 line or menu if we don't have X toolkit support. */
1990 x_set_glyph_string_clipping (s
)
1991 struct glyph_string
*s
;
1994 get_glyph_string_clip_rect (s
, &r
);
1995 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
2000 Compute left and right overhang of glyph string S. If S is a glyph
2001 string for a composition, assume overhangs don't exist. */
2004 mac_compute_glyph_string_overhangs (s
)
2005 struct glyph_string
*s
;
2008 && s
->first_glyph
->type
== CHAR_GLYPH
)
2011 MacFontStruct
*font
= s
->font
;
2013 TextFont (font
->mac_fontnum
);
2014 TextSize (font
->mac_fontsize
);
2015 TextFace (font
->mac_fontface
);
2018 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2022 char *buf
= xmalloc (s
->nchars
);
2025 SetRect (&r
, 0, 0, 0, 0);
2028 for (i
= 0; i
< s
->nchars
; ++i
)
2029 buf
[i
] = s
->char2b
[i
].byte2
;
2030 QDTextBounds (s
->nchars
, buf
, &r
);
2035 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2036 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2041 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2044 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2045 struct glyph_string
*s
;
2050 xgcv
.foreground
= s
->gc
->background
;
2051 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2055 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2056 on Mac OS X because:
2057 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2058 into an offscreen graphics world first. So performance gain
2059 cannot be expected.)
2060 - It lowers rendering quality.
2061 - Some fonts leave garbage on cursor movement. */
2063 /* Draw the background of glyph_string S. If S->background_filled_p
2064 is non-zero don't draw it. FORCE_P non-zero means draw the
2065 background even if it wouldn't be drawn normally. This is used
2066 when a string preceding S draws into the background of S, or S
2067 contains the first component of a composition. */
2070 x_draw_glyph_string_background (s
, force_p
)
2071 struct glyph_string
*s
;
2074 /* Nothing to do if background has already been drawn or if it
2075 shouldn't be drawn in the first place. */
2076 if (!s
->background_filled_p
)
2078 int box_line_width
= max (s
->face
->box_line_width
, 0);
2080 #if 0 /* MAC_TODO: stipple */
2083 /* Fill background with a stipple pattern. */
2084 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2085 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2086 s
->y
+ box_line_width
,
2087 s
->background_width
,
2088 s
->height
- 2 * box_line_width
);
2089 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2090 s
->background_filled_p
= 1;
2095 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2096 || s
->font_not_found_p
2097 || s
->extends_to_end_of_line_p
2101 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2102 s
->background_width
,
2103 s
->height
- 2 * box_line_width
);
2104 s
->background_filled_p
= 1;
2110 /* Draw the foreground of glyph string S. */
2113 x_draw_glyph_string_foreground (s
)
2114 struct glyph_string
*s
;
2118 /* If first glyph of S has a left box line, start drawing the text
2119 of S to the right of that box line. */
2120 if (s
->face
->box
!= FACE_NO_BOX
2121 && s
->first_glyph
->left_box_line_p
)
2122 x
= s
->x
+ abs (s
->face
->box_line_width
);
2126 /* Draw characters of S as rectangles if S's font could not be
2128 if (s
->font_not_found_p
)
2130 for (i
= 0; i
< s
->nchars
; ++i
)
2132 struct glyph
*g
= s
->first_glyph
+ i
;
2133 mac_draw_rectangle (s
->display
, s
->window
,
2134 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2136 x
+= g
->pixel_width
;
2141 char *char1b
= (char *) s
->char2b
;
2142 int boff
= s
->font_info
->baseline_offset
;
2144 if (s
->font_info
->vertical_centering
)
2145 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2147 /* If we can use 8-bit functions, condense S->char2b. */
2149 for (i
= 0; i
< s
->nchars
; ++i
)
2150 char1b
[i
] = s
->char2b
[i
].byte2
;
2153 /* Draw text with XDrawString if background has already been
2154 filled. Otherwise, use XDrawImageString. (Note that
2155 XDrawImageString is usually faster than XDrawString.) Always
2156 use XDrawImageString when drawing the cursor so that there is
2157 no chance that characters under a box cursor are invisible. */
2158 if (s
->for_overlaps_p
2159 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2162 /* Draw characters with 16-bit or 8-bit functions. */
2164 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2165 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2167 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2168 s
->ybase
- boff
, char1b
, s
->nchars
);
2174 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2175 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2177 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2178 s
->ybase
- boff
, char1b
, s
->nchars
);
2184 /* Draw the foreground of composite glyph string S. */
2187 x_draw_composite_glyph_string_foreground (s
)
2188 struct glyph_string
*s
;
2192 /* If first glyph of S has a left box line, start drawing the text
2193 of S to the right of that box line. */
2194 if (s
->face
->box
!= FACE_NO_BOX
2195 && s
->first_glyph
->left_box_line_p
)
2196 x
= s
->x
+ abs (s
->face
->box_line_width
);
2200 /* S is a glyph string for a composition. S->gidx is the index of
2201 the first character drawn for glyphs of this composition.
2202 S->gidx == 0 means we are drawing the very first character of
2203 this composition. */
2205 /* Draw a rectangle for the composition if the font for the very
2206 first character of the composition could not be loaded. */
2207 if (s
->font_not_found_p
)
2210 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2211 s
->width
- 1, s
->height
- 1);
2215 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2216 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2217 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2218 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2224 #ifdef USE_X_TOOLKIT
2226 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2229 /* Return the frame on which widget WIDGET is used.. Abort if frame
2230 cannot be determined. */
2232 static struct frame
*
2233 x_frame_of_widget (widget
)
2236 struct x_display_info
*dpyinfo
;
2240 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2242 /* Find the top-level shell of the widget. Note that this function
2243 can be called when the widget is not yet realized, so XtWindow
2244 (widget) == 0. That's the reason we can't simply use
2245 x_any_window_to_frame. */
2246 while (!XtIsTopLevelShell (widget
))
2247 widget
= XtParent (widget
);
2249 /* Look for a frame with that top-level widget. Allocate the color
2250 on that frame to get the right gamma correction value. */
2251 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2252 if (GC_FRAMEP (XCAR (tail
))
2253 && (f
= XFRAME (XCAR (tail
)),
2254 (f
->output_data
.nothing
!= 1
2255 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2256 && f
->output_data
.x
->widget
== widget
)
2263 /* Allocate the color COLOR->pixel on the screen and display of
2264 widget WIDGET in colormap CMAP. If an exact match cannot be
2265 allocated, try the nearest color available. Value is non-zero
2266 if successful. This is called from lwlib. */
2269 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2274 struct frame
*f
= x_frame_of_widget (widget
);
2275 return x_alloc_nearest_color (f
, cmap
, color
);
2279 #endif /* USE_X_TOOLKIT */
2281 #if 0 /* MAC_TODO */
2283 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2284 CMAP. If an exact match can't be allocated, try the nearest color
2285 available. Value is non-zero if successful. Set *COLOR to the
2289 x_alloc_nearest_color (f
, cmap
, color
)
2294 Display
*display
= FRAME_X_DISPLAY (f
);
2295 Screen
*screen
= FRAME_X_SCREEN (f
);
2298 gamma_correct (f
, color
);
2299 rc
= XAllocColor (display
, cmap
, color
);
2302 /* If we got to this point, the colormap is full, so we're going
2303 to try to get the next closest color. The algorithm used is
2304 a least-squares matching, which is what X uses for closest
2305 color matching with StaticColor visuals. */
2307 unsigned long nearest_delta
= ~0;
2308 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2309 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2311 for (i
= 0; i
< ncells
; ++i
)
2313 XQueryColors (display
, cmap
, cells
, ncells
);
2315 for (nearest
= i
= 0; i
< ncells
; ++i
)
2317 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2318 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2319 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2320 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2322 if (delta
< nearest_delta
)
2325 nearest_delta
= delta
;
2329 color
->red
= cells
[nearest
].red
;
2330 color
->green
= cells
[nearest
].green
;
2331 color
->blue
= cells
[nearest
].blue
;
2332 rc
= XAllocColor (display
, cmap
, color
);
2335 #ifdef DEBUG_X_COLORS
2337 register_color (color
->pixel
);
2338 #endif /* DEBUG_X_COLORS */
2344 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2345 It's necessary to do this instead of just using PIXEL directly to
2346 get color reference counts right. */
2349 x_copy_color (f
, pixel
)
2351 unsigned long pixel
;
2355 color
.pixel
= pixel
;
2357 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2358 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2360 #ifdef DEBUG_X_COLORS
2361 register_color (pixel
);
2367 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2368 It's necessary to do this instead of just using PIXEL directly to
2369 get color reference counts right. */
2372 x_copy_dpy_color (dpy
, cmap
, pixel
)
2375 unsigned long pixel
;
2379 color
.pixel
= pixel
;
2381 XQueryColor (dpy
, cmap
, &color
);
2382 XAllocColor (dpy
, cmap
, &color
);
2384 #ifdef DEBUG_X_COLORS
2385 register_color (pixel
);
2390 #endif /* MAC_TODO */
2393 /* Brightness beyond which a color won't have its highlight brightness
2396 Nominally, highlight colors for `3d' faces are calculated by
2397 brightening an object's color by a constant scale factor, but this
2398 doesn't yield good results for dark colors, so for colors who's
2399 brightness is less than this value (on a scale of 0-255) have to
2400 use an additional additive factor.
2402 The value here is set so that the default menu-bar/mode-line color
2403 (grey75) will not have its highlights changed at all. */
2404 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2407 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2408 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2409 If this produces the same color as COLOR, try a color where all RGB
2410 values have DELTA added. Return the allocated color in *COLOR.
2411 DISPLAY is the X display, CMAP is the colormap to operate on.
2412 Value is non-zero if successful. */
2415 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2417 unsigned long *color
;
2424 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2427 /* Change RGB values by specified FACTOR. Avoid overflow! */
2428 xassert (factor
>= 0);
2429 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2430 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2431 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2433 /* Calculate brightness of COLOR. */
2434 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2435 + BLUE_FROM_ULONG (*color
)) / 6;
2437 /* We only boost colors that are darker than
2438 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2439 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2440 /* Make an additive adjustment to NEW, because it's dark enough so
2441 that scaling by FACTOR alone isn't enough. */
2443 /* How far below the limit this color is (0 - 1, 1 being darker). */
2444 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2445 /* The additive adjustment. */
2446 int min_delta
= delta
* dimness
* factor
/ 2;
2449 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2450 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2451 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2453 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2454 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2455 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2459 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2460 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2461 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2463 /* MAC_TODO: Map to palette and retry with delta if same? */
2464 /* MAC_TODO: Free colors (if using palette)? */
2475 /* Set up the foreground color for drawing relief lines of glyph
2476 string S. RELIEF is a pointer to a struct relief containing the GC
2477 with which lines will be drawn. Use a color that is FACTOR or
2478 DELTA lighter or darker than the relief's background which is found
2479 in S->f->output_data.x->relief_background. If such a color cannot
2480 be allocated, use DEFAULT_PIXEL, instead. */
2483 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2485 struct relief
*relief
;
2488 unsigned long default_pixel
;
2491 struct mac_output
*di
= f
->output_data
.mac
;
2492 unsigned long mask
= GCForeground
;
2493 unsigned long pixel
;
2494 unsigned long background
= di
->relief_background
;
2495 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2497 /* MAC_TODO: Free colors (if using palette)? */
2499 /* Allocate new color. */
2500 xgcv
.foreground
= default_pixel
;
2502 if (dpyinfo
->n_planes
!= 1
2503 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2505 relief
->allocated_p
= 1;
2506 xgcv
.foreground
= relief
->pixel
= pixel
;
2509 if (relief
->gc
== 0)
2511 #if 0 /* MAC_TODO: stipple */
2512 xgcv
.stipple
= dpyinfo
->gray
;
2515 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2518 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2522 /* Set up colors for the relief lines around glyph string S. */
2525 x_setup_relief_colors (s
)
2526 struct glyph_string
*s
;
2528 struct mac_output
*di
= s
->f
->output_data
.mac
;
2529 unsigned long color
;
2531 if (s
->face
->use_box_color_for_shadows_p
)
2532 color
= s
->face
->box_color
;
2533 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2535 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2536 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2541 /* Get the background color of the face. */
2542 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2543 color
= xgcv
.background
;
2546 if (di
->white_relief
.gc
== 0
2547 || color
!= di
->relief_background
)
2549 di
->relief_background
= color
;
2550 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2551 WHITE_PIX_DEFAULT (s
->f
));
2552 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2553 BLACK_PIX_DEFAULT (s
->f
));
2558 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2559 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2560 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2561 relief. LEFT_P non-zero means draw a relief on the left side of
2562 the rectangle. RIGHT_P non-zero means draw a relief on the right
2563 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2567 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2568 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2570 int left_x
, top_y
, right_x
, bottom_y
, width
;
2571 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2574 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2575 Window window
= FRAME_MAC_WINDOW (f
);
2580 gc
= f
->output_data
.mac
->white_relief
.gc
;
2582 gc
= f
->output_data
.mac
->black_relief
.gc
;
2583 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2587 for (i
= 0; i
< width
; ++i
)
2588 XDrawLine (dpy
, window
, gc
,
2589 left_x
+ i
* left_p
, top_y
+ i
,
2590 right_x
- i
* right_p
, top_y
+ i
);
2594 for (i
= 0; i
< width
; ++i
)
2595 XDrawLine (dpy
, window
, gc
,
2596 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2598 mac_reset_clipping (dpy
, window
);
2600 gc
= f
->output_data
.mac
->black_relief
.gc
;
2602 gc
= f
->output_data
.mac
->white_relief
.gc
;
2603 mac_set_clip_rectangle (dpy
, window
,
2608 for (i
= 0; i
< width
; ++i
)
2609 XDrawLine (dpy
, window
, gc
,
2610 left_x
+ i
* left_p
, bottom_y
- i
,
2611 right_x
- i
* right_p
, bottom_y
- i
);
2615 for (i
= 0; i
< width
; ++i
)
2616 XDrawLine (dpy
, window
, gc
,
2617 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2619 mac_reset_clipping (dpy
, window
);
2623 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2624 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2625 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2626 left side of the rectangle. RIGHT_P non-zero means draw a line
2627 on the right side of the rectangle. CLIP_RECT is the clipping
2628 rectangle to use when drawing. */
2631 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2632 left_p
, right_p
, clip_rect
)
2633 struct glyph_string
*s
;
2634 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2639 xgcv
.foreground
= s
->face
->box_color
;
2640 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2643 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2644 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2648 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2649 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2652 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2653 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2657 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2658 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2660 mac_reset_clipping (s
->display
, s
->window
);
2664 /* Draw a box around glyph string S. */
2667 x_draw_glyph_string_box (s
)
2668 struct glyph_string
*s
;
2670 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2671 int left_p
, right_p
;
2672 struct glyph
*last_glyph
;
2675 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2676 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2677 : window_box_right (s
->w
, s
->area
));
2679 /* The glyph that may have a right box line. */
2680 last_glyph
= (s
->cmp
|| s
->img
2682 : s
->first_glyph
+ s
->nchars
- 1);
2684 width
= abs (s
->face
->box_line_width
);
2685 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2687 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2689 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2691 bottom_y
= top_y
+ s
->height
- 1;
2693 left_p
= (s
->first_glyph
->left_box_line_p
2694 || (s
->hl
== DRAW_MOUSE_FACE
2696 || s
->prev
->hl
!= s
->hl
)));
2697 right_p
= (last_glyph
->right_box_line_p
2698 || (s
->hl
== DRAW_MOUSE_FACE
2700 || s
->next
->hl
!= s
->hl
)));
2702 get_glyph_string_clip_rect (s
, &clip_rect
);
2704 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2705 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2706 left_p
, right_p
, &clip_rect
);
2709 x_setup_relief_colors (s
);
2710 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2711 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2716 /* Draw foreground of image glyph string S. */
2719 x_draw_image_foreground (s
)
2720 struct glyph_string
*s
;
2723 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2725 /* If first glyph of S has a left box line, start drawing it to the
2726 right of that line. */
2727 if (s
->face
->box
!= FACE_NO_BOX
2728 && s
->first_glyph
->left_box_line_p
2730 x
+= abs (s
->face
->box_line_width
);
2732 /* If there is a margin around the image, adjust x- and y-position
2734 if (s
->slice
.x
== 0)
2735 x
+= s
->img
->hmargin
;
2736 if (s
->slice
.y
== 0)
2737 y
+= s
->img
->vmargin
;
2741 x_set_glyph_string_clipping (s
);
2744 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2745 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2746 s
->slice
.width
, s
->slice
.height
, x
, y
);
2749 mac_copy_area (s
->display
, s
->img
->pixmap
,
2750 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2751 s
->slice
.width
, s
->slice
.height
, x
, y
);
2753 /* When the image has a mask, we can expect that at
2754 least part of a mouse highlight or a block cursor will
2755 be visible. If the image doesn't have a mask, make
2756 a block cursor visible by drawing a rectangle around
2757 the image. I believe it's looking better if we do
2758 nothing here for mouse-face. */
2759 if (s
->hl
== DRAW_CURSOR
)
2761 int r
= s
->img
->relief
;
2763 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2765 s
->slice
.width
+ r
*2 - 1,
2766 s
->slice
.height
+ r
*2 - 1);
2771 /* Draw a rectangle if image could not be loaded. */
2772 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2773 s
->slice
.width
- 1, s
->slice
.height
- 1);
2777 /* Draw a relief around the image glyph string S. */
2780 x_draw_image_relief (s
)
2781 struct glyph_string
*s
;
2783 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2786 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2788 /* If first glyph of S has a left box line, start drawing it to the
2789 right of that line. */
2790 if (s
->face
->box
!= FACE_NO_BOX
2791 && s
->first_glyph
->left_box_line_p
2793 x
+= abs (s
->face
->box_line_width
);
2795 /* If there is a margin around the image, adjust x- and y-position
2797 if (s
->slice
.x
== 0)
2798 x
+= s
->img
->hmargin
;
2799 if (s
->slice
.y
== 0)
2800 y
+= s
->img
->vmargin
;
2802 if (s
->hl
== DRAW_IMAGE_SUNKEN
2803 || s
->hl
== DRAW_IMAGE_RAISED
)
2805 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2806 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2810 thick
= abs (s
->img
->relief
);
2811 raised_p
= s
->img
->relief
> 0;
2816 x1
= x
+ s
->slice
.width
+ thick
- 1;
2817 y1
= y
+ s
->slice
.height
+ thick
- 1;
2819 x_setup_relief_colors (s
);
2820 get_glyph_string_clip_rect (s
, &r
);
2821 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2823 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2825 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2830 #if 0 /* TODO: figure out if we need to do this on Mac. */
2831 /* Draw the foreground of image glyph string S to PIXMAP. */
2834 x_draw_image_foreground_1 (s
, pixmap
)
2835 struct glyph_string
*s
;
2839 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2841 /* If first glyph of S has a left box line, start drawing it to the
2842 right of that line. */
2843 if (s
->face
->box
!= FACE_NO_BOX
2844 && s
->first_glyph
->left_box_line_p
2846 x
+= abs (s
->face
->box_line_width
);
2848 /* If there is a margin around the image, adjust x- and y-position
2850 if (s
->slice
.x
== 0)
2851 x
+= s
->img
->hmargin
;
2852 if (s
->slice
.y
== 0)
2853 y
+= s
->img
->vmargin
;
2858 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2859 s
->img
->mask
, pixmap
, s
->gc
,
2860 s
->slice
.x
, s
->slice
.y
,
2861 s
->slice
.width
, s
->slice
.height
,
2865 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2866 s
->slice
.x
, s
->slice
.y
,
2867 s
->slice
.width
, s
->slice
.height
,
2870 /* When the image has a mask, we can expect that at
2871 least part of a mouse highlight or a block cursor will
2872 be visible. If the image doesn't have a mask, make
2873 a block cursor visible by drawing a rectangle around
2874 the image. I believe it's looking better if we do
2875 nothing here for mouse-face. */
2876 if (s
->hl
== DRAW_CURSOR
)
2878 int r
= s
->img
->relief
;
2880 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2881 s
->slice
.width
+ r
*2 - 1,
2882 s
->slice
.height
+ r
*2 - 1);
2887 /* Draw a rectangle if image could not be loaded. */
2888 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2889 s
->slice
.width
- 1, s
->slice
.height
- 1);
2894 /* Draw part of the background of glyph string S. X, Y, W, and H
2895 give the rectangle to draw. */
2898 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2899 struct glyph_string
*s
;
2902 #if 0 /* MAC_TODO: stipple */
2905 /* Fill background with a stipple pattern. */
2906 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2907 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2908 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2911 #endif /* MAC_TODO */
2912 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2916 /* Draw image glyph string S.
2919 s->x +-------------------------
2922 | +-------------------------
2925 | | +-------------------
2931 x_draw_image_glyph_string (s
)
2932 struct glyph_string
*s
;
2935 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2936 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2940 height
= s
->height
- 2 * box_line_vwidth
;
2943 /* Fill background with face under the image. Do it only if row is
2944 taller than image or if image has a clip mask to reduce
2946 s
->stippled_p
= s
->face
->stipple
!= 0;
2947 if (height
> s
->slice
.height
2951 || s
->img
->pixmap
== 0
2952 || s
->width
!= s
->background_width
)
2955 if (s
->first_glyph
->left_box_line_p
2957 x
+= box_line_hwidth
;
2960 if (s
->slice
.y
== 0)
2961 y
+= box_line_vwidth
;
2963 #if 0 /* TODO: figure out if we need to do this on Mac. */
2966 /* Create a pixmap as large as the glyph string. Fill it
2967 with the background color. Copy the image to it, using
2968 its mask. Copy the temporary pixmap to the display. */
2969 int depth
= one_mac_display_info
.n_planes
;
2971 /* Create a pixmap as large as the glyph string. */
2972 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2973 s
->background_width
,
2976 /* Fill the pixmap with the background color/stipple. */
2977 #if 0 /* TODO: stipple */
2980 /* Fill background with a stipple pattern. */
2981 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2982 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2983 0, 0, s
->background_width
, s
->height
);
2984 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2990 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2992 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2993 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2994 0, 0, s
->background_width
,
2996 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3001 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3003 s
->background_filled_p
= 1;
3006 /* Draw the foreground. */
3007 #if 0 /* TODO: figure out if we need to do this on Mac. */
3010 x_draw_image_foreground_1 (s
, pixmap
);
3011 x_set_glyph_string_clipping (s
);
3012 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
3013 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3014 mac_reset_clipping (s
->display
, s
->window
);
3015 XFreePixmap (s
->display
, pixmap
);
3019 x_draw_image_foreground (s
);
3021 /* If we must draw a relief around the image, do it. */
3023 || s
->hl
== DRAW_IMAGE_RAISED
3024 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3025 x_draw_image_relief (s
);
3029 /* Draw stretch glyph string S. */
3032 x_draw_stretch_glyph_string (s
)
3033 struct glyph_string
*s
;
3035 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3036 s
->stippled_p
= s
->face
->stipple
!= 0;
3038 if (s
->hl
== DRAW_CURSOR
3039 && !x_stretch_cursor_p
)
3041 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3042 as wide as the stretch glyph. */
3043 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3046 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3048 /* Clear rest using the GC of the original non-cursor face. */
3049 if (width
< s
->background_width
)
3051 int x
= s
->x
+ width
, y
= s
->y
;
3052 int w
= s
->background_width
- width
, h
= s
->height
;
3056 if (s
->row
->mouse_face_p
3057 && cursor_in_mouse_face_p (s
->w
))
3059 x_set_mouse_face_gc (s
);
3065 get_glyph_string_clip_rect (s
, &r
);
3066 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3068 #if 0 /* MAC_TODO: stipple */
3069 if (s
->face
->stipple
)
3071 /* Fill background with a stipple pattern. */
3072 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3073 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3074 XSetFillStyle (s
->display
, gc
, FillSolid
);
3077 #endif /* MAC_TODO */
3080 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3081 XSetForeground (s
->display
, gc
, xgcv
.background
);
3082 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3083 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3086 mac_reset_clipping (s
->display
, s
->window
);
3089 else if (!s
->background_filled_p
)
3090 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3093 s
->background_filled_p
= 1;
3097 /* Draw glyph string S. */
3100 x_draw_glyph_string (s
)
3101 struct glyph_string
*s
;
3103 int relief_drawn_p
= 0;
3105 /* If S draws into the background of its successor that does not
3106 draw a cursor, draw the background of the successor first so that
3107 S can draw into it. This makes S->next use XDrawString instead
3108 of XDrawImageString. */
3109 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
3110 && s
->next
->hl
!= DRAW_CURSOR
)
3112 xassert (s
->next
->img
== NULL
);
3113 x_set_glyph_string_gc (s
->next
);
3114 x_set_glyph_string_clipping (s
->next
);
3115 x_draw_glyph_string_background (s
->next
, 1);
3118 /* Set up S->gc, set clipping and draw S. */
3119 x_set_glyph_string_gc (s
);
3121 /* Draw relief (if any) in advance for char/composition so that the
3122 glyph string can be drawn over it. */
3123 if (!s
->for_overlaps_p
3124 && s
->face
->box
!= FACE_NO_BOX
3125 && (s
->first_glyph
->type
== CHAR_GLYPH
3126 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3129 x_set_glyph_string_clipping (s
);
3130 x_draw_glyph_string_background (s
, 1);
3131 x_draw_glyph_string_box (s
);
3132 x_set_glyph_string_clipping (s
);
3136 x_set_glyph_string_clipping (s
);
3138 switch (s
->first_glyph
->type
)
3141 x_draw_image_glyph_string (s
);
3145 x_draw_stretch_glyph_string (s
);
3149 if (s
->for_overlaps_p
)
3150 s
->background_filled_p
= 1;
3152 x_draw_glyph_string_background (s
, 0);
3153 x_draw_glyph_string_foreground (s
);
3156 case COMPOSITE_GLYPH
:
3157 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3158 s
->background_filled_p
= 1;
3160 x_draw_glyph_string_background (s
, 1);
3161 x_draw_composite_glyph_string_foreground (s
);
3168 if (!s
->for_overlaps_p
)
3170 /* Draw underline. */
3171 if (s
->face
->underline_p
)
3173 unsigned long h
= 1;
3174 unsigned long dy
= s
->height
- h
;
3176 if (s
->face
->underline_defaulted_p
)
3177 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3182 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3183 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3184 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3186 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3190 /* Draw overline. */
3191 if (s
->face
->overline_p
)
3193 unsigned long dy
= 0, h
= 1;
3195 if (s
->face
->overline_color_defaulted_p
)
3196 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3201 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3202 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3203 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3205 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3209 /* Draw strike-through. */
3210 if (s
->face
->strike_through_p
)
3212 unsigned long h
= 1;
3213 unsigned long dy
= (s
->height
- h
) / 2;
3215 if (s
->face
->strike_through_color_defaulted_p
)
3216 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3221 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3222 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3223 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3225 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3229 /* Draw relief if not yet drawn. */
3230 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3231 x_draw_glyph_string_box (s
);
3234 /* Reset clipping. */
3235 mac_reset_clipping (s
->display
, s
->window
);
3238 /* Shift display to make room for inserted glyphs. */
3241 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3243 int x
, y
, width
, height
, shift_by
;
3245 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3246 f
->output_data
.mac
->normal_gc
,
3247 x
, y
, width
, height
,
3251 /* Delete N glyphs at the nominal cursor position. Not implemented
3262 /* Clear entire frame. If updating_frame is non-null, clear that
3263 frame. Otherwise clear the selected frame. */
3273 f
= SELECTED_FRAME ();
3275 /* Clearing the frame will erase any cursor, so mark them all as no
3277 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3278 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3279 output_cursor
.x
= -1;
3281 /* We don't set the output cursor here because there will always
3282 follow an explicit cursor_to. */
3284 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3286 /* We have to clear the scroll bars, too. If we have changed
3287 colors or something like that, then they should be notified. */
3288 x_scroll_bar_clear (f
);
3290 XFlush (FRAME_MAC_DISPLAY (f
));
3296 /* Invert the middle quarter of the frame for .15 sec. */
3298 /* We use the select system call to do the waiting, so we have to make
3299 sure it's available. If it isn't, we just won't do visual bells. */
3301 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3304 /* Subtract the `struct timeval' values X and Y, storing the result in
3305 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3308 timeval_subtract (result
, x
, y
)
3309 struct timeval
*result
, x
, y
;
3311 /* Perform the carry for the later subtraction by updating y. This
3312 is safer because on some systems the tv_sec member is unsigned. */
3313 if (x
.tv_usec
< y
.tv_usec
)
3315 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3316 y
.tv_usec
-= 1000000 * nsec
;
3320 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3322 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3323 y
.tv_usec
+= 1000000 * nsec
;
3327 /* Compute the time remaining to wait. tv_usec is certainly
3329 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3330 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3332 /* Return indication of whether the result should be considered
3334 return x
.tv_sec
< y
.tv_sec
;
3346 struct timeval wakeup
;
3348 EMACS_GET_TIME (wakeup
);
3350 /* Compute time to wait until, propagating carry from usecs. */
3351 wakeup
.tv_usec
+= 150000;
3352 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3353 wakeup
.tv_usec
%= 1000000;
3355 /* Keep waiting until past the time wakeup. */
3358 struct timeval timeout
;
3360 EMACS_GET_TIME (timeout
);
3362 /* In effect, timeout = wakeup - timeout.
3363 Break if result would be negative. */
3364 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3367 /* Try to wait that long--but we might wake up sooner. */
3368 select (0, NULL
, NULL
, NULL
, &timeout
);
3377 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3380 /* Make audible bell. */
3385 struct frame
*f
= SELECTED_FRAME ();
3387 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3395 XFlush (FRAME_MAC_DISPLAY (f
));
3402 /* Specify how many text lines, from the top of the window,
3403 should be affected by insert-lines and delete-lines operations.
3404 This, and those operations, are used only within an update
3405 that is bounded by calls to x_update_begin and x_update_end. */
3408 XTset_terminal_window (n
)
3411 /* This function intentionally left blank. */
3416 /***********************************************************************
3418 ***********************************************************************/
3420 /* Perform an insert-lines or delete-lines operation, inserting N
3421 lines or deleting -N lines at vertical position VPOS. */
3424 x_ins_del_lines (vpos
, n
)
3431 /* Scroll part of the display as described by RUN. */
3434 x_scroll_run (w
, run
)
3438 struct frame
*f
= XFRAME (w
->frame
);
3439 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3441 /* Get frame-relative bounding box of the text display area of W,
3442 without mode lines. Include in this box the left and right
3444 window_box (w
, -1, &x
, &y
, &width
, &height
);
3446 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3447 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3448 bottom_y
= y
+ height
;
3452 /* Scrolling up. Make sure we don't copy part of the mode
3453 line at the bottom. */
3454 if (from_y
+ run
->height
> bottom_y
)
3455 height
= bottom_y
- from_y
;
3457 height
= run
->height
;
3461 /* Scolling down. Make sure we don't copy over the mode line.
3463 if (to_y
+ run
->height
> bottom_y
)
3464 height
= bottom_y
- to_y
;
3466 height
= run
->height
;
3471 /* Cursor off. Will be switched on again in x_update_window_end. */
3475 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3476 f
->output_data
.mac
->normal_gc
,
3486 /***********************************************************************
3488 ***********************************************************************/
3496 ControlRef root_control
;
3499 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3501 ActivateControl (root_control
);
3503 x_update_cursor (f
, 1);
3507 frame_unhighlight (f
)
3511 ControlRef root_control
;
3514 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3516 DeactivateControl (root_control
);
3518 x_update_cursor (f
, 1);
3521 /* The focus has changed. Update the frames as necessary to reflect
3522 the new situation. Note that we can't change the selected frame
3523 here, because the Lisp code we are interrupting might become confused.
3524 Each event gets marked with the frame in which it occurred, so the
3525 Lisp code can tell when the switch took place by examining the events. */
3528 x_new_focus_frame (dpyinfo
, frame
)
3529 struct x_display_info
*dpyinfo
;
3530 struct frame
*frame
;
3532 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3534 if (frame
!= dpyinfo
->x_focus_frame
)
3536 /* Set this before calling other routines, so that they see
3537 the correct value of x_focus_frame. */
3538 dpyinfo
->x_focus_frame
= frame
;
3540 if (old_focus
&& old_focus
->auto_lower
)
3541 x_lower_frame (old_focus
);
3544 selected_frame
= frame
;
3545 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3547 Fselect_window (selected_frame
->selected_window
, Qnil
);
3548 choose_minibuf_frame ();
3551 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3552 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3554 pending_autoraise_frame
= 0;
3557 x_frame_rehighlight (dpyinfo
);
3560 /* Handle FocusIn and FocusOut state changes for FRAME.
3561 If FRAME has focus and there exists more than one frame, puts
3562 a FOCUS_IN_EVENT into *BUFP. */
3565 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3567 struct mac_display_info
*dpyinfo
;
3568 struct frame
*frame
;
3569 struct input_event
*bufp
;
3571 if (type
== activeFlag
)
3573 if (dpyinfo
->x_focus_event_frame
!= frame
)
3575 x_new_focus_frame (dpyinfo
, frame
);
3576 dpyinfo
->x_focus_event_frame
= frame
;
3578 /* Don't stop displaying the initial startup message
3579 for a switch-frame event we don't need. */
3580 if (GC_NILP (Vterminal_frame
)
3581 && GC_CONSP (Vframe_list
)
3582 && !GC_NILP (XCDR (Vframe_list
)))
3584 bufp
->kind
= FOCUS_IN_EVENT
;
3585 XSETFRAME (bufp
->frame_or_window
, frame
);
3591 if (dpyinfo
->x_focus_event_frame
== frame
)
3593 dpyinfo
->x_focus_event_frame
= 0;
3594 x_new_focus_frame (dpyinfo
, 0);
3599 /* The focus may have changed. Figure out if it is a real focus change,
3600 by checking both FocusIn/Out and Enter/LeaveNotify events.
3602 Returns FOCUS_IN_EVENT event in *BUFP. */
3605 x_detect_focus_change (dpyinfo
, event
, bufp
)
3606 struct mac_display_info
*dpyinfo
;
3608 struct input_event
*bufp
;
3610 struct frame
*frame
;
3612 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3616 /* On Mac, this is only called from focus events, so no switch needed. */
3617 mac_focus_changed ((event
->modifiers
& activeFlag
),
3618 dpyinfo
, frame
, bufp
);
3622 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3625 x_mouse_leave (dpyinfo
)
3626 struct x_display_info
*dpyinfo
;
3628 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3631 /* The focus has changed, or we have redirected a frame's focus to
3632 another frame (this happens when a frame uses a surrogate
3633 mini-buffer frame). Shift the highlight as appropriate.
3635 The FRAME argument doesn't necessarily have anything to do with which
3636 frame is being highlighted or un-highlighted; we only use it to find
3637 the appropriate X display info. */
3640 XTframe_rehighlight (frame
)
3641 struct frame
*frame
;
3643 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3647 x_frame_rehighlight (dpyinfo
)
3648 struct x_display_info
*dpyinfo
;
3650 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3652 if (dpyinfo
->x_focus_frame
)
3654 dpyinfo
->x_highlight_frame
3655 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3656 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3657 : dpyinfo
->x_focus_frame
);
3658 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3660 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3661 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3665 dpyinfo
->x_highlight_frame
= 0;
3667 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3670 frame_unhighlight (old_highlight
);
3671 if (dpyinfo
->x_highlight_frame
)
3672 frame_highlight (dpyinfo
->x_highlight_frame
);
3678 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3680 #if 0 /* MAC_TODO */
3681 /* Initialize mode_switch_bit and modifier_meaning. */
3683 x_find_modifier_meanings (dpyinfo
)
3684 struct x_display_info
*dpyinfo
;
3686 int min_code
, max_code
;
3689 XModifierKeymap
*mods
;
3691 dpyinfo
->meta_mod_mask
= 0;
3692 dpyinfo
->shift_lock_mask
= 0;
3693 dpyinfo
->alt_mod_mask
= 0;
3694 dpyinfo
->super_mod_mask
= 0;
3695 dpyinfo
->hyper_mod_mask
= 0;
3698 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3700 min_code
= dpyinfo
->display
->min_keycode
;
3701 max_code
= dpyinfo
->display
->max_keycode
;
3704 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3705 min_code
, max_code
- min_code
+ 1,
3707 mods
= XGetModifierMapping (dpyinfo
->display
);
3709 /* Scan the modifier table to see which modifier bits the Meta and
3710 Alt keysyms are on. */
3712 int row
, col
; /* The row and column in the modifier table. */
3714 for (row
= 3; row
< 8; row
++)
3715 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3718 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3720 /* Zeroes are used for filler. Skip them. */
3724 /* Are any of this keycode's keysyms a meta key? */
3728 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3730 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3736 dpyinfo
->meta_mod_mask
|= (1 << row
);
3741 dpyinfo
->alt_mod_mask
|= (1 << row
);
3746 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3751 dpyinfo
->super_mod_mask
|= (1 << row
);
3755 /* Ignore this if it's not on the lock modifier. */
3756 if ((1 << row
) == LockMask
)
3757 dpyinfo
->shift_lock_mask
= LockMask
;
3765 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3766 if (! dpyinfo
->meta_mod_mask
)
3768 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3769 dpyinfo
->alt_mod_mask
= 0;
3772 /* If some keys are both alt and meta,
3773 make them just meta, not alt. */
3774 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3776 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3779 XFree ((char *) syms
);
3780 XFreeModifiermap (mods
);
3783 #endif /* MAC_TODO */
3785 /* Convert between the modifier bits X uses and the modifier bits
3789 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3790 struct x_display_info
*dpyinfo
;
3791 unsigned short state
;
3793 return (((state
& shiftKey
) ? shift_modifier
: 0)
3794 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3795 | ((state
& cmdKey
) ? meta_modifier
: 0)
3796 | ((state
& optionKey
) ? alt_modifier
: 0));
3799 #if 0 /* MAC_TODO */
3800 static unsigned short
3801 x_emacs_to_x_modifiers (dpyinfo
, state
)
3802 struct x_display_info
*dpyinfo
;
3805 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3806 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3807 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3808 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3809 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3810 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3812 #endif /* MAC_TODO */
3814 /* Convert a keysym to its name. */
3817 x_get_keysym_name (keysym
)
3824 value
= XKeysymToString (keysym
);
3836 /* Mouse clicks and mouse movement. Rah. */
3838 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3840 If the event is a button press, then note that we have grabbed
3844 construct_mouse_click (result
, event
, f
)
3845 struct input_event
*result
;
3851 result
->kind
= MOUSE_CLICK_EVENT
;
3852 result
->code
= 0; /* only one mouse button */
3853 result
->timestamp
= event
->when
;
3854 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3856 mouseLoc
= event
->where
;
3858 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3860 GlobalToLocal (&mouseLoc
);
3861 XSETINT (result
->x
, mouseLoc
.h
);
3862 XSETINT (result
->y
, mouseLoc
.v
);
3864 XSETFRAME (result
->frame_or_window
, f
);
3872 /* Function to report a mouse movement to the mainstream Emacs code.
3873 The input handler calls this.
3875 We have received a mouse movement event, which is given in *event.
3876 If the mouse is over a different glyph than it was last time, tell
3877 the mainstream emacs code by setting mouse_moved. If not, ask for
3878 another motion event, so we can check again the next time it moves. */
3880 static Point last_mouse_motion_position
;
3881 static Lisp_Object last_mouse_motion_frame
;
3884 note_mouse_movement (frame
, pos
)
3888 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3889 #if TARGET_API_MAC_CARBON
3893 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3894 last_mouse_motion_position
= *pos
;
3895 XSETFRAME (last_mouse_motion_frame
, frame
);
3897 #if TARGET_API_MAC_CARBON
3898 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3900 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3903 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3904 /* This case corresponds to LeaveNotify in X11. */
3906 /* If we move outside the frame, then we're certainly no
3907 longer on any text in the frame. */
3908 clear_mouse_face (dpyinfo
);
3909 dpyinfo
->mouse_face_mouse_frame
= 0;
3910 if (!dpyinfo
->grabbed
)
3911 rif
->define_frame_cursor (frame
,
3912 frame
->output_data
.mac
->nontext_cursor
);
3915 /* Has the mouse moved off the glyph it was on at the last sighting? */
3916 else if (pos
->h
< last_mouse_glyph
.left
3917 || pos
->h
>= last_mouse_glyph
.right
3918 || pos
->v
< last_mouse_glyph
.top
3919 || pos
->v
>= last_mouse_glyph
.bottom
)
3921 frame
->mouse_moved
= 1;
3922 last_mouse_scroll_bar
= Qnil
;
3923 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3927 /* This is used for debugging, to turn off note_mouse_highlight. */
3929 int disable_mouse_highlight
;
3933 /************************************************************************
3935 ************************************************************************/
3937 static struct scroll_bar
*x_window_to_scroll_bar ();
3938 static void x_scroll_bar_report_motion ();
3939 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3942 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3945 redo_mouse_highlight ()
3947 if (!NILP (last_mouse_motion_frame
)
3948 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3949 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3950 last_mouse_motion_position
.h
,
3951 last_mouse_motion_position
.v
);
3955 /* Try to determine frame pixel position and size of the glyph under
3956 frame pixel coordinates X/Y on frame F . Return the position and
3957 size in *RECT. Value is non-zero if we could compute these
3961 glyph_rect (f
, x
, y
, rect
)
3968 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3972 struct window
*w
= XWINDOW (window
);
3973 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3974 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3976 for (; r
< end
&& r
->enabled_p
; ++r
)
3977 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3979 /* Found the row at y. */
3980 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3981 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3984 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3985 rect
->bottom
= rect
->top
+ r
->height
;
3989 /* x is to the left of the first glyph in the row. */
3990 /* Shouldn't this be a pixel value?
3991 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3993 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3994 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3998 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3999 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
4001 /* x is on a glyph. */
4002 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
4003 rect
->right
= rect
->left
+ g
->pixel_width
;
4007 /* x is to the right of the last glyph in the row. */
4008 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
4009 /* Shouldn't this be a pixel value?
4010 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
4012 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
4017 /* The y is not on any row. */
4021 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4023 /* Record the position of the mouse in last_mouse_glyph. */
4025 remember_mouse_glyph (f1
, gx
, gy
)
4029 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
4031 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
4032 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
4034 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
4035 round down even for negative values. */
4041 /* This was the original code from XTmouse_position, but it seems
4042 to give the position of the glyph diagonally next to the one
4043 the mouse is over. */
4044 gx
= (gx
+ width
- 1) / width
* width
;
4045 gy
= (gy
+ height
- 1) / height
* height
;
4047 gx
= gx
/ width
* width
;
4048 gy
= gy
/ height
* height
;
4051 last_mouse_glyph
.left
= gx
;
4052 last_mouse_glyph
.top
= gy
;
4053 last_mouse_glyph
.right
= gx
+ width
;
4054 last_mouse_glyph
.bottom
= gy
+ height
;
4059 static struct frame
*
4060 mac_focus_frame (dpyinfo
)
4061 struct mac_display_info
*dpyinfo
;
4063 if (dpyinfo
->x_focus_frame
)
4064 return dpyinfo
->x_focus_frame
;
4066 /* Mac version may get events, such as a menu bar click, even when
4067 all the frames are invisible. In this case, we regard the
4068 event came to the selected frame. */
4069 return SELECTED_FRAME ();
4073 /* Return the current position of the mouse.
4074 *fp should be a frame which indicates which display to ask about.
4076 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4077 and *part to the frame, window, and scroll bar part that the mouse
4078 is over. Set *x and *y to the portion and whole of the mouse's
4079 position on the scroll bar.
4081 If the mouse movement started elsewhere, set *fp to the frame the
4082 mouse is on, *bar_window to nil, and *x and *y to the character cell
4085 Set *time to the server time-stamp for the time at which the mouse
4086 was at this position.
4088 Don't store anything if we don't have a valid set of values to report.
4090 This clears the mouse_moved flag, so we can wait for the next mouse
4094 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4097 Lisp_Object
*bar_window
;
4098 enum scroll_bar_part
*part
;
4100 unsigned long *time
;
4103 int ignore1
, ignore2
;
4104 struct frame
*f
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4105 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
4106 Lisp_Object frame
, tail
;
4110 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4111 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4114 /* Clear the mouse-moved flag for every frame on this display. */
4115 FOR_EACH_FRAME (tail
, frame
)
4116 XFRAME (frame
)->mouse_moved
= 0;
4118 last_mouse_scroll_bar
= Qnil
;
4120 SetPortWindowPort (wp
);
4122 GetMouse (&mouse_pos
);
4124 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4125 &last_mouse_glyph
, insist
);
4128 *part
= scroll_bar_handle
;
4130 XSETINT (*x
, mouse_pos
.h
);
4131 XSETINT (*y
, mouse_pos
.v
);
4132 *time
= last_mouse_movement_time
;
4139 /************************************************************************
4141 ************************************************************************/
4143 #ifdef USE_TOOLKIT_SCROLL_BARS
4145 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4146 static OSStatus install_scroll_bar_timer
P_ ((void));
4147 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4148 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4149 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4151 struct input_event
*));
4152 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4154 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4157 struct input_event
*));
4158 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4160 struct input_event
*));
4161 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4162 Point
, unsigned long,
4163 struct input_event
*));
4164 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4167 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4169 static int last_scroll_bar_part
;
4171 static EventLoopTimerRef scroll_bar_timer
;
4173 static int scroll_bar_timer_event_posted_p
;
4175 #define SCROLL_BAR_FIRST_DELAY 0.5
4176 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4179 scroll_bar_timer_callback (timer
, data
)
4180 EventLoopTimerRef timer
;
4183 EventRef event
= NULL
;
4186 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4187 kEventAttributeNone
, &event
);
4192 GetMouse (&mouse_pos
);
4193 LocalToGlobal (&mouse_pos
);
4194 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4195 sizeof (Point
), &mouse_pos
);
4199 UInt32 modifiers
= GetCurrentKeyModifiers ();
4201 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4202 sizeof (UInt32
), &modifiers
);
4205 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4206 kEventPriorityStandard
);
4208 scroll_bar_timer_event_posted_p
= 1;
4211 ReleaseEvent (event
);
4215 install_scroll_bar_timer ()
4217 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4219 if (scroll_bar_timer_callbackUPP
== NULL
)
4220 scroll_bar_timer_callbackUPP
=
4221 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4223 if (scroll_bar_timer
== NULL
)
4224 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4225 kEventDurationForever as delays. */
4227 InstallEventLoopTimer (GetCurrentEventLoop (),
4228 kEventDurationForever
, kEventDurationForever
,
4229 scroll_bar_timer_callbackUPP
, NULL
,
4234 set_scroll_bar_timer (delay
)
4235 EventTimerInterval delay
;
4237 if (scroll_bar_timer
== NULL
)
4238 install_scroll_bar_timer ();
4240 scroll_bar_timer_event_posted_p
= 0;
4242 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4246 control_part_code_to_scroll_bar_part (part_code
)
4247 ControlPartCode part_code
;
4251 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4252 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4253 case kControlPageUpPart
: return scroll_bar_above_handle
;
4254 case kControlPageDownPart
: return scroll_bar_below_handle
;
4255 case kControlIndicatorPart
: return scroll_bar_handle
;
4262 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
)
4263 struct scroll_bar
*bar
;
4265 unsigned long timestamp
;
4266 struct input_event
*bufp
;
4268 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4269 bufp
->frame_or_window
= bar
->window
;
4273 bufp
->timestamp
= timestamp
;
4274 XSETINT (bufp
->x
, 0);
4275 XSETINT (bufp
->y
, 0);
4276 bufp
->modifiers
= 0;
4280 get_control_part_bounds (ch
, part_code
, rect
)
4282 ControlPartCode part_code
;
4285 RgnHandle region
= NewRgn ();
4288 err
= GetControlRegion (ch
, part_code
, region
);
4290 GetRegionBounds (region
, rect
);
4291 DisposeRgn (region
);
4297 x_scroll_bar_handle_press (bar
, part_code
, timestamp
, bufp
)
4298 struct scroll_bar
*bar
;
4299 ControlPartCode part_code
;
4300 unsigned long timestamp
;
4301 struct input_event
*bufp
;
4303 int part
= control_part_code_to_scroll_bar_part (part_code
);
4308 if (part
!= scroll_bar_handle
)
4310 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
);
4311 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4312 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4315 last_scroll_bar_part
= part
;
4316 bar
->dragging
= Qnil
;
4317 tracked_scroll_bar
= bar
;
4321 x_scroll_bar_handle_release (bar
, timestamp
, bufp
)
4322 struct scroll_bar
*bar
;
4323 unsigned long timestamp
;
4324 struct input_event
*bufp
;
4326 if (last_scroll_bar_part
!= scroll_bar_handle
4327 || !GC_NILP (bar
->dragging
))
4328 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, timestamp
, bufp
);
4330 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4331 set_scroll_bar_timer (kEventDurationForever
);
4333 last_scroll_bar_part
= -1;
4334 bar
->dragging
= Qnil
;
4335 tracked_scroll_bar
= NULL
;
4339 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, timestamp
, bufp
)
4341 struct scroll_bar
*bar
;
4343 unsigned long timestamp
;
4344 struct input_event
*bufp
;
4346 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4348 if (last_scroll_bar_part
== scroll_bar_handle
)
4353 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4354 kControlIndicatorPart
, &r
);
4356 if (GC_NILP (bar
->dragging
))
4357 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4359 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4360 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4361 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4366 if (top
> top_range
)
4369 construct_scroll_bar_click (bar
, scroll_bar_handle
, timestamp
, bufp
);
4370 XSETINT (bufp
->x
, top
);
4371 XSETINT (bufp
->y
, top_range
);
4375 ControlPartCode part_code
;
4376 int unhilite_p
= 0, part
;
4378 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4382 part
= control_part_code_to_scroll_bar_part (part_code
);
4384 switch (last_scroll_bar_part
)
4386 case scroll_bar_above_handle
:
4387 case scroll_bar_below_handle
:
4388 if (part
!= scroll_bar_above_handle
4389 && part
!= scroll_bar_below_handle
)
4393 case scroll_bar_up_arrow
:
4394 case scroll_bar_down_arrow
:
4395 if (part
!= scroll_bar_up_arrow
4396 && part
!= scroll_bar_down_arrow
)
4403 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4404 else if (part
!= last_scroll_bar_part
4405 || scroll_bar_timer_event_posted_p
)
4407 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
);
4408 last_scroll_bar_part
= part
;
4409 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4410 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4415 /* Set the thumb size and position of scroll bar BAR. We are currently
4416 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4419 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4420 struct scroll_bar
*bar
;
4421 int portion
, position
, whole
;
4423 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4425 int value
, viewsize
, maximum
;
4427 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4428 value
= 0, viewsize
= 1, maximum
= 0;
4433 maximum
= max (0, whole
- portion
);
4438 SetControl32BitMinimum (ch
, 0);
4439 SetControl32BitMaximum (ch
, maximum
);
4440 SetControl32BitValue (ch
, value
);
4441 SetControlViewSize (ch
, viewsize
);
4446 #endif /* USE_TOOLKIT_SCROLL_BARS */
4450 /************************************************************************
4451 Scroll bars, general
4452 ************************************************************************/
4454 /* Create a scroll bar and return the scroll bar vector for it. W is
4455 the Emacs window on which to create the scroll bar. TOP, LEFT,
4456 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4459 static struct scroll_bar
*
4460 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4462 int top
, left
, width
, height
, disp_top
, disp_height
;
4464 struct frame
*f
= XFRAME (w
->frame
);
4465 struct scroll_bar
*bar
4466 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4474 r
.right
= left
+ width
;
4475 r
.bottom
= disp_top
+ disp_height
;
4477 #if TARGET_API_MAC_CARBON
4478 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4479 kControlScrollBarProc
, (long) bar
);
4481 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4482 scrollBarProc
, (long) bar
);
4484 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4486 XSETWINDOW (bar
->window
, w
);
4487 XSETINT (bar
->top
, top
);
4488 XSETINT (bar
->left
, left
);
4489 XSETINT (bar
->width
, width
);
4490 XSETINT (bar
->height
, height
);
4491 XSETINT (bar
->start
, 0);
4492 XSETINT (bar
->end
, 0);
4493 bar
->dragging
= Qnil
;
4494 #ifdef USE_TOOLKIT_SCROLL_BARS
4495 bar
->track_top
= Qnil
;
4496 bar
->track_height
= Qnil
;
4499 /* Add bar to its frame's list of scroll bars. */
4500 bar
->next
= FRAME_SCROLL_BARS (f
);
4502 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4503 if (!NILP (bar
->next
))
4504 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4511 /* Draw BAR's handle in the proper position.
4513 If the handle is already drawn from START to END, don't bother
4514 redrawing it, unless REBUILD is non-zero; in that case, always
4515 redraw it. (REBUILD is handy for drawing the handle after expose
4518 Normally, we want to constrain the start and end of the handle to
4519 fit inside its rectangle, but if the user is dragging the scroll
4520 bar handle, we want to let them drag it down all the way, so that
4521 the bar's top is as far down as it goes; otherwise, there's no way
4522 to move to the very end of the buffer. */
4524 #ifndef USE_TOOLKIT_SCROLL_BARS
4527 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4528 struct scroll_bar
*bar
;
4532 int dragging
= ! NILP (bar
->dragging
);
4533 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4534 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4535 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4536 int length
= end
- start
;
4538 /* If the display is already accurate, do nothing. */
4540 && start
== XINT (bar
->start
)
4541 && end
== XINT (bar
->end
))
4546 /* Make sure the values are reasonable, and try to preserve the
4547 distance between start and end. */
4550 else if (start
> top_range
)
4552 end
= start
+ length
;
4556 else if (end
> top_range
&& ! dragging
)
4559 /* Store the adjusted setting in the scroll bar. */
4560 XSETINT (bar
->start
, start
);
4561 XSETINT (bar
->end
, end
);
4563 /* Clip the end position, just for display. */
4564 if (end
> top_range
)
4567 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4568 top positions, to make sure the handle is always at least that
4569 many pixels tall. */
4570 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4572 SetControlMinimum (ch
, 0);
4573 /* Don't inadvertently activate deactivated scroll bars */
4574 if (GetControlMaximum (ch
) != -1)
4575 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4577 SetControlValue (ch
, start
);
4578 #if TARGET_API_MAC_CARBON
4579 SetControlViewSize (ch
, end
- start
);
4585 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4587 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4591 x_scroll_bar_remove (bar
)
4592 struct scroll_bar
*bar
;
4594 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4598 /* Destroy the Mac scroll bar control */
4599 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4601 /* Disassociate this scroll bar from its window. */
4602 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4607 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4608 that we are displaying PORTION characters out of a total of WHOLE
4609 characters, starting at POSITION. If WINDOW has no scroll bar,
4612 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4614 int portion
, whole
, position
;
4616 struct frame
*f
= XFRAME (w
->frame
);
4617 struct scroll_bar
*bar
;
4618 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4619 int window_y
, window_height
;
4621 /* Get window dimensions. */
4622 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4624 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4625 height
= window_height
;
4627 /* Compute the left edge of the scroll bar area. */
4628 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4630 /* Compute the width of the scroll bar which might be less than
4631 the width of the area reserved for the scroll bar. */
4632 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4633 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4637 /* Compute the left edge of the scroll bar. */
4638 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4641 sb_left
= left
+ width
- sb_width
;
4643 /* Adjustments according to Inside Macintosh to make it look nice */
4645 disp_height
= height
;
4651 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4657 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4660 /* Does the scroll bar exist yet? */
4661 if (NILP (w
->vertical_scroll_bar
))
4664 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4665 left
, top
, width
, height
, 0);
4667 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4669 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4673 /* It may just need to be moved and resized. */
4676 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4677 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4681 /* If already correctly positioned, do nothing. */
4682 if (!(XINT (bar
->left
) == sb_left
4683 && XINT (bar
->top
) == top
4684 && XINT (bar
->width
) == sb_width
4685 && XINT (bar
->height
) == height
))
4687 /* Clear areas not covered by the scroll bar because it's not as
4688 wide as the area reserved for it . This makes sure a
4689 previous mode line display is cleared after C-x 2 C-x 1, for
4691 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4692 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4693 left
, top
, area_width
, height
, 0);
4696 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4697 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4698 sb_left
- 1, top
, 1, height
, 0);
4702 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4703 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4707 /* Remember new settings. */
4708 XSETINT (bar
->left
, sb_left
);
4709 XSETINT (bar
->top
, top
);
4710 XSETINT (bar
->width
, sb_width
);
4711 XSETINT (bar
->height
, height
);
4712 #ifdef USE_TOOLKIT_SCROLL_BARS
4713 bar
->track_top
= Qnil
;
4714 bar
->track_height
= Qnil
;
4721 #ifdef USE_TOOLKIT_SCROLL_BARS
4722 if (NILP (bar
->track_top
))
4724 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4729 SetControl32BitMinimum (ch
, 0);
4730 SetControl32BitMaximum (ch
, 1);
4731 SetControlViewSize (ch
, 1);
4733 /* Move the scroll bar thumb to the top. */
4734 SetControl32BitValue (ch
, 0);
4735 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4737 /* Move the scroll bar thumb to the bottom. */
4738 SetControl32BitValue (ch
, 1);
4739 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4741 UnionRect (&r0
, &r1
, &r0
);
4742 XSETINT (bar
->track_top
, r0
.top
);
4743 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4748 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4749 #else /* not USE_TOOLKIT_SCROLL_BARS */
4750 /* Set the scroll bar's current state, unless we're currently being
4752 if (NILP (bar
->dragging
))
4754 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4757 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4760 int start
= ((double) position
* top_range
) / whole
;
4761 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4762 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4765 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4769 /* The following three hooks are used when we're doing a thorough
4770 redisplay of the frame. We don't explicitly know which scroll bars
4771 are going to be deleted, because keeping track of when windows go
4772 away is a real pain - "Can you say set-window-configuration, boys
4773 and girls?" Instead, we just assert at the beginning of redisplay
4774 that *all* scroll bars are to be removed, and then save a scroll bar
4775 from the fiery pit when we actually redisplay its window. */
4777 /* Arrange for all scroll bars on FRAME to be removed at the next call
4778 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4779 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4782 XTcondemn_scroll_bars (frame
)
4785 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4786 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4789 bar
= FRAME_SCROLL_BARS (frame
);
4790 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4791 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4792 XSCROLL_BAR (bar
)->prev
= Qnil
;
4793 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4794 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4795 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4800 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4801 Note that WINDOW isn't necessarily condemned at all. */
4804 XTredeem_scroll_bar (window
)
4805 struct window
*window
;
4807 struct scroll_bar
*bar
;
4809 /* We can't redeem this window's scroll bar if it doesn't have one. */
4810 if (NILP (window
->vertical_scroll_bar
))
4813 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4815 /* Unlink it from the condemned list. */
4817 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4819 if (NILP (bar
->prev
))
4821 /* If the prev pointer is nil, it must be the first in one of
4823 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4824 /* It's not condemned. Everything's fine. */
4826 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4827 window
->vertical_scroll_bar
))
4828 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4830 /* If its prev pointer is nil, it must be at the front of
4831 one or the other! */
4835 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4837 if (! NILP (bar
->next
))
4838 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4840 bar
->next
= FRAME_SCROLL_BARS (f
);
4842 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4843 if (! NILP (bar
->next
))
4844 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4848 /* Remove all scroll bars on FRAME that haven't been saved since the
4849 last call to `*condemn_scroll_bars_hook'. */
4852 XTjudge_scroll_bars (f
)
4855 Lisp_Object bar
, next
;
4857 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4859 /* Clear out the condemned list now so we won't try to process any
4860 more events on the hapless scroll bars. */
4861 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4863 for (; ! NILP (bar
); bar
= next
)
4865 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4867 x_scroll_bar_remove (b
);
4870 b
->next
= b
->prev
= Qnil
;
4873 /* Now there should be no references to the condemned scroll bars,
4874 and they should get garbage-collected. */
4878 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4879 is set to something other than NO_EVENT, it is enqueued.
4881 This may be called from a signal handler, so we have to ignore GC
4885 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4886 struct scroll_bar
*bar
;
4887 ControlPartCode part_code
;
4889 struct input_event
*bufp
;
4891 int win_y
, top_range
;
4893 if (! GC_WINDOWP (bar
->window
))
4896 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4897 bufp
->frame_or_window
= bar
->window
;
4900 bar
->dragging
= Qnil
;
4904 case kControlUpButtonPart
:
4905 bufp
->part
= scroll_bar_up_arrow
;
4907 case kControlDownButtonPart
:
4908 bufp
->part
= scroll_bar_down_arrow
;
4910 case kControlPageUpPart
:
4911 bufp
->part
= scroll_bar_above_handle
;
4913 case kControlPageDownPart
:
4914 bufp
->part
= scroll_bar_below_handle
;
4916 #if TARGET_API_MAC_CARBON
4919 case kControlIndicatorPart
:
4921 if (er
->what
== mouseDown
)
4922 bar
->dragging
= make_number (0);
4923 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4924 bufp
->part
= scroll_bar_handle
;
4928 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4929 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4931 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4935 if (! NILP (bar
->dragging
))
4936 win_y
-= XINT (bar
->dragging
);
4940 if (win_y
> top_range
)
4943 XSETINT (bufp
->x
, win_y
);
4944 XSETINT (bufp
->y
, top_range
);
4947 #ifndef USE_TOOLKIT_SCROLL_BARS
4949 /* Handle some mouse motion while someone is dragging the scroll bar.
4951 This may be called from a signal handler, so we have to ignore GC
4955 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4956 struct scroll_bar
*bar
;
4960 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4962 last_mouse_movement_time
= t
;
4965 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4967 /* If we're dragging the bar, display it. */
4968 if (! GC_NILP (bar
->dragging
))
4970 /* Where should the handle be now? */
4971 int new_start
= y_pos
- 24;
4973 if (new_start
!= XINT (bar
->start
))
4975 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4977 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4982 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4984 /* Return information to the user about the current position of the
4985 mouse on the scroll bar. */
4988 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4990 Lisp_Object
*bar_window
;
4991 enum scroll_bar_part
*part
;
4993 unsigned long *time
;
4995 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4996 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4997 #if TARGET_API_MAC_CARBON
4998 WindowPtr wp
= GetControlOwner (ch
);
5000 WindowPtr wp
= (*ch
)->contrlOwner
;
5003 struct frame
*f
= mac_window_to_frame (wp
);
5004 int win_y
, top_range
;
5006 SetPortWindowPort (wp
);
5008 GetMouse (&mouse_pos
);
5010 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5011 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5013 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5017 if (! NILP (bar
->dragging
))
5018 win_y
-= XINT (bar
->dragging
);
5022 if (win_y
> top_range
)
5026 *bar_window
= bar
->window
;
5028 if (! NILP (bar
->dragging
))
5029 *part
= scroll_bar_handle
;
5030 else if (win_y
< XINT (bar
->start
))
5031 *part
= scroll_bar_above_handle
;
5032 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5033 *part
= scroll_bar_handle
;
5035 *part
= scroll_bar_below_handle
;
5037 XSETINT (*x
, win_y
);
5038 XSETINT (*y
, top_range
);
5041 last_mouse_scroll_bar
= Qnil
;
5043 *time
= last_mouse_movement_time
;
5047 /* The screen has been cleared so we may have changed foreground or
5048 background colors, and the scroll bars may need to be redrawn.
5049 Clear out the scroll bars, and ask for expose events, so we can
5053 x_scroll_bar_clear (f
)
5056 XTcondemn_scroll_bars (f
);
5057 XTjudge_scroll_bars (f
);
5061 /***********************************************************************
5063 ***********************************************************************/
5065 /* Set clipping for output in glyph row ROW. W is the window in which
5066 we operate. GC is the graphics context to set clipping in.
5068 ROW may be a text row or, e.g., a mode line. Text rows must be
5069 clipped to the interior of the window dedicated to text display,
5070 mode lines must be clipped to the whole window. */
5073 x_clip_to_row (w
, row
, area
, gc
)
5075 struct glyph_row
*row
;
5079 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5081 int window_x
, window_y
, window_width
;
5083 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5085 clip_rect
.left
= window_x
;
5086 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5087 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5088 clip_rect
.right
= clip_rect
.left
+ window_width
;
5089 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5091 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
5095 /* Draw a hollow box cursor on window W in glyph row ROW. */
5098 x_draw_hollow_cursor (w
, row
)
5100 struct glyph_row
*row
;
5102 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5103 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5104 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5107 struct glyph
*cursor_glyph
;
5110 /* Get the glyph the cursor is on. If we can't tell because
5111 the current matrix is invalid or such, give up. */
5112 cursor_glyph
= get_phys_cursor_glyph (w
);
5113 if (cursor_glyph
== NULL
)
5116 /* Compute frame-relative coordinates for phys cursor. */
5117 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5118 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5119 wd
= w
->phys_cursor_width
;
5121 /* The foreground of cursor_gc is typically the same as the normal
5122 background color, which can cause the cursor box to be invisible. */
5123 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5124 if (dpyinfo
->scratch_cursor_gc
)
5125 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5127 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5128 GCForeground
, &xgcv
);
5129 gc
= dpyinfo
->scratch_cursor_gc
;
5131 /* Set clipping, draw the rectangle, and reset clipping again. */
5132 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5133 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
5134 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5138 /* Draw a bar cursor on window W in glyph row ROW.
5140 Implementation note: One would like to draw a bar cursor with an
5141 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5142 Unfortunately, I didn't find a font yet that has this property set.
5146 x_draw_bar_cursor (w
, row
, width
, kind
)
5148 struct glyph_row
*row
;
5150 enum text_cursor_kinds kind
;
5152 struct frame
*f
= XFRAME (w
->frame
);
5153 struct glyph
*cursor_glyph
;
5155 /* If cursor is out of bounds, don't draw garbage. This can happen
5156 in mini-buffer windows when switching between echo area glyphs
5158 cursor_glyph
= get_phys_cursor_glyph (w
);
5159 if (cursor_glyph
== NULL
)
5162 /* If on an image, draw like a normal cursor. That's usually better
5163 visible than drawing a bar, esp. if the image is large so that
5164 the bar might not be in the window. */
5165 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5167 struct glyph_row
*row
;
5168 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5169 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5173 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5174 Window window
= FRAME_MAC_WINDOW (f
);
5175 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5176 unsigned long mask
= GCForeground
| GCBackground
;
5177 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5180 /* If the glyph's background equals the color we normally draw
5181 the bar cursor in, the bar cursor in its normal color is
5182 invisible. Use the glyph's foreground color instead in this
5183 case, on the assumption that the glyph's colors are chosen so
5184 that the glyph is legible. */
5185 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5186 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5188 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5191 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5194 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5195 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5199 width
= FRAME_CURSOR_WIDTH (f
);
5200 width
= min (cursor_glyph
->pixel_width
, width
);
5202 w
->phys_cursor_width
= width
;
5203 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5205 if (kind
== BAR_CURSOR
)
5206 XFillRectangle (dpy
, window
, gc
,
5207 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5208 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5209 width
, row
->height
);
5211 XFillRectangle (dpy
, window
, gc
,
5212 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5213 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5214 row
->height
- width
),
5215 cursor_glyph
->pixel_width
,
5218 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5223 /* RIF: Define cursor CURSOR on frame F. */
5226 mac_define_frame_cursor (f
, cursor
)
5230 SetThemeCursor (cursor
);
5234 /* RIF: Clear area on frame F. */
5237 mac_clear_frame_area (f
, x
, y
, width
, height
)
5239 int x
, y
, width
, height
;
5241 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5242 x
, y
, width
, height
, 0);
5246 /* RIF: Draw cursor on window W. */
5249 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5251 struct glyph_row
*glyph_row
;
5253 int cursor_type
, cursor_width
;
5258 w
->phys_cursor_type
= cursor_type
;
5259 w
->phys_cursor_on_p
= 1;
5261 if (glyph_row
->exact_window_width_line_p
5262 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5264 glyph_row
->cursor_in_fringe_p
= 1;
5265 draw_fringe_bitmap (w
, glyph_row
, 0);
5268 switch (cursor_type
)
5270 case HOLLOW_BOX_CURSOR
:
5271 x_draw_hollow_cursor (w
, glyph_row
);
5274 case FILLED_BOX_CURSOR
:
5275 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5279 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5283 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5287 w
->phys_cursor_width
= 0;
5299 #if 0 /* MAC_TODO: no icon support yet. */
5301 x_bitmap_icon (f
, icon
)
5307 if (FRAME_W32_WINDOW (f
) == 0)
5311 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5312 else if (STRINGP (icon
))
5313 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5314 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5315 else if (SYMBOLP (icon
))
5319 if (EQ (icon
, intern ("application")))
5320 name
= (LPCTSTR
) IDI_APPLICATION
;
5321 else if (EQ (icon
, intern ("hand")))
5322 name
= (LPCTSTR
) IDI_HAND
;
5323 else if (EQ (icon
, intern ("question")))
5324 name
= (LPCTSTR
) IDI_QUESTION
;
5325 else if (EQ (icon
, intern ("exclamation")))
5326 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5327 else if (EQ (icon
, intern ("asterisk")))
5328 name
= (LPCTSTR
) IDI_ASTERISK
;
5329 else if (EQ (icon
, intern ("winlogo")))
5330 name
= (LPCTSTR
) IDI_WINLOGO
;
5334 hicon
= LoadIcon (NULL
, name
);
5342 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5347 #endif /* MAC_TODO */
5349 /************************************************************************
5351 ************************************************************************/
5353 /* Display Error Handling functions not used on W32. Listing them here
5354 helps diff stay in step when comparing w32term.c with xterm.c.
5356 x_error_catcher (display, error)
5357 x_catch_errors (dpy)
5358 x_catch_errors_unwind (old_val)
5359 x_check_errors (dpy, format)
5360 x_had_errors_p (dpy)
5361 x_clear_errors (dpy)
5362 x_uncatch_errors (dpy, count)
5364 x_connection_signal (signalnum)
5365 x_connection_closed (dpy, error_message)
5366 x_error_quitter (display, error)
5367 x_error_handler (display, error)
5368 x_io_error_quitter (display)
5373 /* Changing the font of the frame. */
5375 /* Give frame F the font named FONTNAME as its default font, and
5376 return the full name of that font. FONTNAME may be a wildcard
5377 pattern; in that case, we choose some font that fits the pattern.
5378 The return value shows which font we chose. */
5381 x_new_font (f
, fontname
)
5383 register char *fontname
;
5385 struct font_info
*fontp
5386 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5391 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5392 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5393 FRAME_FONTSET (f
) = -1;
5395 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5396 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5397 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5399 compute_fringe_widths (f
, 1);
5401 /* Compute the scroll bar width in character columns. */
5402 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5404 int wid
= FRAME_COLUMN_WIDTH (f
);
5405 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5406 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5410 int wid
= FRAME_COLUMN_WIDTH (f
);
5411 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5414 /* Now make the frame display the given font. */
5415 if (FRAME_MAC_WINDOW (f
) != 0)
5417 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5419 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5421 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5424 /* Don't change the size of a tip frame; there's no point in
5425 doing it because it's done in Fx_show_tip, and it leads to
5426 problems because the tip frame has no widget. */
5427 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5428 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5431 return build_string (fontp
->full_name
);
5434 /* Give frame F the fontset named FONTSETNAME as its default font, and
5435 return the full name of that fontset. FONTSETNAME may be a wildcard
5436 pattern; in that case, we choose some fontset that fits the pattern.
5437 The return value shows which fontset we chose. */
5440 x_new_fontset (f
, fontsetname
)
5444 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5450 if (FRAME_FONTSET (f
) == fontset
)
5451 /* This fontset is already set in frame F. There's nothing more
5453 return fontset_name (fontset
);
5455 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5457 if (!STRINGP (result
))
5458 /* Can't load ASCII font. */
5461 /* Since x_new_font doesn't update any fontset information, do it now. */
5462 FRAME_FONTSET (f
) = fontset
;
5464 return build_string (fontsetname
);
5468 /***********************************************************************
5469 TODO: W32 Input Methods
5470 ***********************************************************************/
5471 /* Listing missing functions from xterm.c helps diff stay in step.
5473 xim_destroy_callback (xim, client_data, call_data)
5474 xim_open_dpy (dpyinfo, resource_name)
5476 xim_instantiate_callback (display, client_data, call_data)
5477 xim_initialize (dpyinfo, resource_name)
5478 xim_close_dpy (dpyinfo)
5484 mac_get_window_bounds (f
, inner
, outer
)
5486 Rect
*inner
, *outer
;
5488 #if TARGET_API_MAC_CARBON
5489 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5490 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5491 #else /* not TARGET_API_MAC_CARBON */
5492 RgnHandle region
= NewRgn ();
5494 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5495 *inner
= (*region
)->rgnBBox
;
5496 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5497 *outer
= (*region
)->rgnBBox
;
5498 DisposeRgn (region
);
5499 #endif /* not TARGET_API_MAC_CARBON */
5503 /* Calculate the absolute position in frame F
5504 from its current recorded position values and gravity. */
5507 x_calc_absolute_position (f
)
5510 int width_diff
= 0, height_diff
= 0;
5511 int flags
= f
->size_hint_flags
;
5514 /* We have nothing to do if the current position
5515 is already for the top-left corner. */
5516 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5519 /* Find the offsets of the outside upper-left corner of
5520 the inner window, with respect to the outer window. */
5521 mac_get_window_bounds (f
, &inner
, &outer
);
5523 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5524 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5526 /* Treat negative positions as relative to the leftmost bottommost
5527 position that fits on the screen. */
5528 if (flags
& XNegative
)
5529 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5531 - FRAME_PIXEL_WIDTH (f
)
5534 if (flags
& YNegative
)
5535 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5537 - FRAME_PIXEL_HEIGHT (f
)
5540 /* The left_pos and top_pos
5541 are now relative to the top and left screen edges,
5542 so the flags should correspond. */
5543 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5546 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5547 to really change the position, and 0 when calling from
5548 x_make_frame_visible (in that case, XOFF and YOFF are the current
5549 position values). It is -1 when calling from x_set_frame_parameters,
5550 which means, do adjust for borders but don't change the gravity. */
5553 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5555 register int xoff
, yoff
;
5558 if (change_gravity
> 0)
5562 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5564 f
->size_hint_flags
|= XNegative
;
5566 f
->size_hint_flags
|= YNegative
;
5567 f
->win_gravity
= NorthWestGravity
;
5569 x_calc_absolute_position (f
);
5572 x_wm_set_size_hint (f
, (long) 0, 0);
5574 #if TARGET_API_MAC_CARBON
5575 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5576 /* If the title bar is completely outside the screen, adjust the
5578 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5579 kWindowConstrainMoveRegardlessOfFit
5580 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5581 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5584 Rect inner
, outer
, screen_rect
, dummy
;
5585 RgnHandle region
= NewRgn ();
5587 mac_get_window_bounds (f
, &inner
, &outer
);
5588 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5589 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5590 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5591 f
->top_pos
+ f
->y_pixels_diff
, false);
5593 /* If the title bar is completely outside the screen, adjust the
5594 position. The variable `outer' holds the title bar rectangle.
5595 The variable `inner' holds slightly smaller one than `outer',
5596 so that the calculation of overlapping may not become too
5598 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5599 outer
= (*region
)->rgnBBox
;
5600 DisposeRgn (region
);
5602 InsetRect (&inner
, 8, 8);
5603 screen_rect
= qd
.screenBits
.bounds
;
5604 screen_rect
.top
+= GetMBarHeight ();
5606 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5608 if (inner
.right
<= screen_rect
.left
)
5609 f
->left_pos
= screen_rect
.left
;
5610 else if (inner
.left
>= screen_rect
.right
)
5611 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5613 if (inner
.bottom
<= screen_rect
.top
)
5614 f
->top_pos
= screen_rect
.top
;
5615 else if (inner
.top
>= screen_rect
.bottom
)
5616 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5618 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5619 f
->top_pos
+ f
->y_pixels_diff
, false);
5627 /* Call this to change the size of frame F's x-window.
5628 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5629 for this size change and subsequent size changes.
5630 Otherwise we leave the window gravity unchanged. */
5633 x_set_window_size (f
, change_gravity
, cols
, rows
)
5638 int pixelwidth
, pixelheight
;
5642 check_frame_size (f
, &rows
, &cols
);
5643 f
->scroll_bar_actual_width
5644 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5646 compute_fringe_widths (f
, 0);
5648 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5649 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5651 f
->win_gravity
= NorthWestGravity
;
5652 x_wm_set_size_hint (f
, (long) 0, 0);
5654 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5655 #if TARGET_API_MAC_CARBON
5656 if (f
->output_data
.mac
->hourglass_control
)
5657 MoveControl (f
->output_data
.mac
->hourglass_control
,
5658 pixelwidth
- HOURGLASS_WIDTH
, 0);
5661 /* Now, strictly speaking, we can't be sure that this is accurate,
5662 but the window manager will get around to dealing with the size
5663 change request eventually, and we'll hear how it went when the
5664 ConfigureNotify event gets here.
5666 We could just not bother storing any of this information here,
5667 and let the ConfigureNotify event set everything up, but that
5668 might be kind of confusing to the Lisp code, since size changes
5669 wouldn't be reported in the frame parameters until some random
5670 point in the future when the ConfigureNotify event arrives.
5672 We pass 1 for DELAY since we can't run Lisp code inside of
5674 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5675 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5676 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5678 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5679 receive in the ConfigureNotify event; if we get what we asked
5680 for, then the event won't cause the screen to become garbaged, so
5681 we have to make sure to do it here. */
5682 SET_FRAME_GARBAGED (f
);
5684 XFlush (FRAME_X_DISPLAY (f
));
5686 /* If cursor was outside the new size, mark it as off. */
5687 mark_window_cursors_off (XWINDOW (f
->root_window
));
5689 /* Clear out any recollection of where the mouse highlighting was,
5690 since it might be in a place that's outside the new frame size.
5691 Actually checking whether it is outside is a pain in the neck,
5692 so don't try--just let the highlighting be done afresh with new size. */
5693 cancel_mouse_face (f
);
5698 /* Mouse warping. */
5700 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5703 x_set_mouse_position (f
, x
, y
)
5709 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5710 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5712 if (pix_x
< 0) pix_x
= 0;
5713 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5715 if (pix_y
< 0) pix_y
= 0;
5716 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5718 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5722 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5726 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5729 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5730 0, 0, 0, 0, pix_x
, pix_y
);
5736 /* focus shifting, raising and lowering. */
5739 x_focus_on_frame (f
)
5742 #if 0 /* This proves to be unpleasant. */
5746 /* I don't think that the ICCCM allows programs to do things like this
5747 without the interaction of the window manager. Whatever you end up
5748 doing with this code, do it to x_unfocus_frame too. */
5749 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5750 RevertToPointerRoot
, CurrentTime
);
5760 /* Raise frame F. */
5765 if (f
->async_visible
)
5768 SelectWindow (FRAME_MAC_WINDOW (f
));
5773 /* Lower frame F. */
5778 if (f
->async_visible
)
5781 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5787 XTframe_raise_lower (f
, raise_flag
)
5797 /* Change of visibility. */
5799 /* This tries to wait until the frame is really visible.
5800 However, if the window manager asks the user where to position
5801 the frame, this will return before the user finishes doing that.
5802 The frame will not actually be visible at that time,
5803 but it will become visible later when the window manager
5804 finishes with it. */
5807 x_make_frame_visible (f
)
5811 int original_top
, original_left
;
5815 if (! FRAME_VISIBLE_P (f
))
5817 /* We test FRAME_GARBAGED_P here to make sure we don't
5818 call x_set_offset a second time
5819 if we get to x_make_frame_visible a second time
5820 before the window gets really visible. */
5821 if (! FRAME_ICONIFIED_P (f
)
5822 && ! f
->output_data
.mac
->asked_for_visible
)
5823 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5825 f
->output_data
.mac
->asked_for_visible
= 1;
5827 #if TARGET_API_MAC_CARBON
5828 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5830 struct frame
*sf
= SELECTED_FRAME ();
5831 if (!FRAME_MAC_P (sf
))
5832 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5833 kWindowCenterOnMainScreen
);
5835 RepositionWindow (FRAME_MAC_WINDOW (f
),
5836 FRAME_MAC_WINDOW (sf
),
5837 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5838 kWindowCascadeStartAtParentWindowScreen
5840 kWindowCascadeOnParentWindowScreen
5843 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5846 ShowWindow (FRAME_MAC_WINDOW (f
));
5849 XFlush (FRAME_MAC_DISPLAY (f
));
5851 /* Synchronize to ensure Emacs knows the frame is visible
5852 before we do anything else. We do this loop with input not blocked
5853 so that incoming events are handled. */
5858 /* This must come after we set COUNT. */
5861 XSETFRAME (frame
, f
);
5863 /* Wait until the frame is visible. Process X events until a
5864 MapNotify event has been seen, or until we think we won't get a
5865 MapNotify at all.. */
5866 for (count
= input_signal_count
+ 10;
5867 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5869 /* Force processing of queued events. */
5872 /* Machines that do polling rather than SIGIO have been
5873 observed to go into a busy-wait here. So we'll fake an
5874 alarm signal to let the handler know that there's something
5875 to be read. We used to raise a real alarm, but it seems
5876 that the handler isn't always enabled here. This is
5878 if (input_polling_used ())
5880 /* It could be confusing if a real alarm arrives while
5881 processing the fake one. Turn it off and let the
5882 handler reset it. */
5883 extern void poll_for_input_1
P_ ((void));
5884 int old_poll_suppress_count
= poll_suppress_count
;
5885 poll_suppress_count
= 1;
5886 poll_for_input_1 ();
5887 poll_suppress_count
= old_poll_suppress_count
;
5890 /* See if a MapNotify event has been processed. */
5891 FRAME_SAMPLE_VISIBILITY (f
);
5896 /* Change from mapped state to withdrawn state. */
5898 /* Make the frame visible (mapped and not iconified). */
5901 x_make_frame_invisible (f
)
5904 /* Don't keep the highlight on an invisible frame. */
5905 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5906 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5910 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5911 that the current position of the window is user-specified, rather than
5912 program-specified, so that when the window is mapped again, it will be
5913 placed at the same location, without forcing the user to position it
5914 by hand again (they have already done that once for this window.) */
5915 x_wm_set_size_hint (f
, (long) 0, 1);
5917 HideWindow (FRAME_MAC_WINDOW (f
));
5919 /* We can't distinguish this from iconification
5920 just by the event that we get from the server.
5921 So we can't win using the usual strategy of letting
5922 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5923 and synchronize with the server to make sure we agree. */
5925 FRAME_ICONIFIED_P (f
) = 0;
5926 f
->async_visible
= 0;
5927 f
->async_iconified
= 0;
5932 /* Change window state from mapped to iconified. */
5938 /* Don't keep the highlight on an invisible frame. */
5939 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5940 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5943 /* Review: Since window is still visible in dock, still allow updates? */
5944 if (f
->async_iconified
)
5950 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5956 /* Free X resources of frame F. */
5959 x_free_frame_resources (f
)
5962 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5963 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5967 if (wp
!= tip_window
)
5968 remove_window_handler (wp
);
5971 if (wp
== tip_window
)
5972 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5973 closed' event. So we reset tip_window here. */
5976 free_frame_menubar (f
);
5978 if (FRAME_FACE_CACHE (f
))
5979 free_frame_faces (f
);
5983 if (FRAME_SIZE_HINTS (f
))
5984 xfree (FRAME_SIZE_HINTS (f
));
5986 xfree (f
->output_data
.mac
);
5987 f
->output_data
.mac
= NULL
;
5989 if (f
== dpyinfo
->x_focus_frame
)
5990 dpyinfo
->x_focus_frame
= 0;
5991 if (f
== dpyinfo
->x_focus_event_frame
)
5992 dpyinfo
->x_focus_event_frame
= 0;
5993 if (f
== dpyinfo
->x_highlight_frame
)
5994 dpyinfo
->x_highlight_frame
= 0;
5996 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5998 dpyinfo
->mouse_face_beg_row
5999 = dpyinfo
->mouse_face_beg_col
= -1;
6000 dpyinfo
->mouse_face_end_row
6001 = dpyinfo
->mouse_face_end_col
= -1;
6002 dpyinfo
->mouse_face_window
= Qnil
;
6003 dpyinfo
->mouse_face_deferred_gc
= 0;
6004 dpyinfo
->mouse_face_mouse_frame
= 0;
6011 /* Destroy the X window of frame F. */
6014 x_destroy_window (f
)
6017 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6019 x_free_frame_resources (f
);
6021 dpyinfo
->reference_count
--;
6025 /* Setting window manager hints. */
6027 /* Set the normal size hints for the window manager, for frame F.
6028 FLAGS is the flags word to use--or 0 meaning preserve the flags
6029 that the window now has.
6030 If USER_POSITION is nonzero, we set the USPosition
6031 flag (this is useful when FLAGS is 0). */
6033 x_wm_set_size_hint (f
, flags
, user_position
)
6038 int base_width
, base_height
, width_inc
, height_inc
;
6039 int min_rows
= 0, min_cols
= 0;
6040 XSizeHints
*size_hints
;
6042 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6043 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6044 width_inc
= FRAME_COLUMN_WIDTH (f
);
6045 height_inc
= FRAME_LINE_HEIGHT (f
);
6047 check_frame_size (f
, &min_rows
, &min_cols
);
6049 size_hints
= FRAME_SIZE_HINTS (f
);
6050 if (size_hints
== NULL
)
6052 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6053 bzero (size_hints
, sizeof (XSizeHints
));
6056 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6057 size_hints
->width_inc
= width_inc
;
6058 size_hints
->height_inc
= height_inc
;
6059 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6060 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6061 size_hints
->base_width
= base_width
;
6062 size_hints
->base_height
= base_height
;
6065 size_hints
->flags
= flags
;
6066 else if (user_position
)
6068 size_hints
->flags
&= ~ PPosition
;
6069 size_hints
->flags
|= USPosition
;
6073 #if 0 /* MAC_TODO: hide application instead of iconify? */
6074 /* Used for IconicState or NormalState */
6077 x_wm_set_window_state (f
, state
)
6081 #ifdef USE_X_TOOLKIT
6084 XtSetArg (al
[0], XtNinitialState
, state
);
6085 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6086 #else /* not USE_X_TOOLKIT */
6087 Window window
= FRAME_X_WINDOW (f
);
6089 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6090 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6092 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6093 #endif /* not USE_X_TOOLKIT */
6097 x_wm_set_icon_pixmap (f
, pixmap_id
)
6103 #ifndef USE_X_TOOLKIT
6104 Window window
= FRAME_X_WINDOW (f
);
6109 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6110 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6114 /* It seems there is no way to turn off use of an icon pixmap.
6115 The following line does it, only if no icon has yet been created,
6116 for some window managers. But with mwm it crashes.
6117 Some people say it should clear the IconPixmapHint bit in this case,
6118 but that doesn't work, and the X consortium said it isn't the
6119 right thing at all. Since there is no way to win,
6120 best to explicitly give up. */
6122 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6128 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6132 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6133 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6136 #else /* not USE_X_TOOLKIT */
6138 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6139 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6141 #endif /* not USE_X_TOOLKIT */
6144 #endif /* MAC_TODO */
6147 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6151 #if 0 /* MAC_TODO: no icons on Mac */
6152 #ifdef USE_X_TOOLKIT
6153 Window window
= XtWindow (f
->output_data
.x
->widget
);
6155 Window window
= FRAME_X_WINDOW (f
);
6158 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6159 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6160 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6162 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6163 #endif /* MAC_TODO */
6167 /***********************************************************************
6169 ***********************************************************************/
6171 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6174 x_get_font_info (f
, font_idx
)
6178 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6181 /* the global font name table */
6182 char **font_name_table
= NULL
;
6183 int font_name_table_size
= 0;
6184 int font_name_count
= 0;
6186 /* Alist linking character set strings to Mac text encoding and Emacs
6188 static Lisp_Object Vmac_charset_info_alist
;
6191 create_text_encoding_info_alist ()
6193 Lisp_Object result
= Qnil
, rest
;
6195 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6197 Lisp_Object charset_info
= XCAR (rest
);
6198 Lisp_Object charset
, coding_system
, text_encoding
;
6199 Lisp_Object existing_info
;
6201 if (!(CONSP (charset_info
)
6202 && STRINGP (charset
= XCAR (charset_info
))
6203 && CONSP (XCDR (charset_info
))
6204 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6205 && CONSP (XCDR (XCDR (charset_info
)))
6206 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6209 existing_info
= assq_no_quit (text_encoding
, result
);
6210 if (NILP (existing_info
))
6211 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6214 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6215 XSETCDR (XCDR (existing_info
),
6216 Fcons (charset
, XCDR (XCDR (existing_info
))));
6224 decode_mac_font_name (name
, size
, coding_system
)
6227 Lisp_Object coding_system
;
6229 struct coding_system coding
;
6232 for (p
= name
; *p
; p
++)
6233 if (!isascii (*p
) || iscntrl (*p
))
6237 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6240 setup_coding_system (coding_system
, &coding
);
6241 coding
.src_multibyte
= 0;
6242 coding
.dst_multibyte
= 1;
6243 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6244 coding
.composing
= COMPOSITION_DISABLED
;
6245 buf
= (char *) alloca (size
);
6247 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6248 bcopy (buf
, name
, coding
.produced
);
6249 name
[coding
.produced
] = '\0';
6254 mac_to_x_fontname (name
, size
, style
, charset
)
6262 char xf
[256], *result
, *p
;
6264 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6268 strcpy(foundry
, "Apple");
6269 strcpy(family
, name
);
6272 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6273 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6274 size
, size
* 10, size
? 75 : 0, size
? 75 : 0, size
* 10, charset
);
6276 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6277 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6278 for (p
= result
; *p
; p
++)
6284 /* Convert an X font spec to the corresponding mac font name, which
6285 can then be passed to GetFNum after conversion to a Pascal string.
6286 For ordinary Mac fonts, this should just be their names, like
6287 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6288 collection contain their charset designation in their names, like
6289 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6290 names are handled accordingly. */
6292 x_font_name_to_mac_font_name (xf
, mf
, mf_decoded
, style
, cs
)
6293 char *xf
, *mf
, *mf_decoded
;
6299 char weight
[20], slant
[2], *p
;
6300 Lisp_Object charset_info
, coding_system
= Qnil
;
6301 struct coding_system coding
;
6305 if (sscanf (xf
, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6306 foundry
, family
, weight
, slant
, cs
) != 5 &&
6307 sscanf (xf
, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6308 foundry
, family
, weight
, slant
, cs
) != 5)
6312 if (strcmp (weight
, "bold") == 0)
6317 charset_info
= Fassoc (build_string (cs
), Vmac_charset_info_alist
);
6318 if (!NILP (charset_info
))
6320 strcpy (mf_decoded
, family
);
6321 coding_system
= Fcar (Fcdr (Fcdr (charset_info
)));
6324 sprintf (mf_decoded
, "%s-%s-%s", foundry
, family
, cs
);
6326 for (p
= mf_decoded
; *p
; p
++)
6327 if (!isascii (*p
) || iscntrl (*p
))
6331 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6332 strcpy (mf
, mf_decoded
);
6335 setup_coding_system (coding_system
, &coding
);
6336 coding
.src_multibyte
= 1;
6337 coding
.dst_multibyte
= 1;
6338 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6339 encode_coding (&coding
, mf_decoded
, mf
,
6340 strlen (mf_decoded
), sizeof (Str255
) - 1);
6341 mf
[coding
.produced
] = '\0';
6347 add_font_name_table_entry (char *font_name
)
6349 if (font_name_table_size
== 0)
6351 font_name_table_size
= 16;
6352 font_name_table
= (char **)
6353 xmalloc (font_name_table_size
* sizeof (char *));
6355 else if (font_name_count
+ 1 >= font_name_table_size
)
6357 font_name_table_size
+= 16;
6358 font_name_table
= (char **)
6359 xrealloc (font_name_table
,
6360 font_name_table_size
* sizeof (char *));
6363 font_name_table
[font_name_count
++] = font_name
;
6366 /* Sets up the table font_name_table to contain the list of all fonts
6367 in the system the first time the table is used so that the Resource
6368 Manager need not be accessed every time this information is
6372 init_font_name_table ()
6374 #if TARGET_API_MAC_CARBON
6375 FMFontFamilyIterator ffi
;
6376 FMFontFamilyInstanceIterator ffii
;
6378 Lisp_Object text_encoding_info_alist
;
6379 struct gcpro gcpro1
;
6381 /* Create a dummy instance iterator here to avoid creating and
6382 destroying it in the loop. */
6383 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6385 /* Create an iterator to enumerate the font families. */
6386 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6389 FMDisposeFontFamilyInstanceIterator (&ffii
);
6393 text_encoding_info_alist
= create_text_encoding_info_alist ();
6395 GCPRO1 (text_encoding_info_alist
);
6397 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6403 TextEncoding encoding
;
6404 TextEncodingBase sc
;
6405 Lisp_Object text_encoding_info
;
6407 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6413 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6415 sc
= GetTextEncodingBase (encoding
);
6416 text_encoding_info
= assq_no_quit (make_number (sc
),
6417 text_encoding_info_alist
);
6418 if (!NILP (text_encoding_info
))
6419 decode_mac_font_name (name
, sizeof (name
),
6420 XCAR (XCDR (text_encoding_info
)));
6422 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6423 text_encoding_info_alist
);
6425 /* Point the instance iterator at the current font family. */
6426 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6429 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6432 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6434 for (; !NILP (rest
); rest
= XCDR (rest
))
6436 char *cs
= SDATA (XCAR (rest
));
6440 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6442 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6444 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6446 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6452 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6461 /* Dispose of the iterators. */
6462 FMDisposeFontFamilyIterator (&ffi
);
6463 FMDisposeFontFamilyInstanceIterator (&ffii
);
6464 #else /* !TARGET_API_MAC_CARBON */
6466 SInt16 fontnum
, old_fontnum
;
6467 int num_mac_fonts
= CountResources('FOND');
6469 Handle font_handle
, font_handle_2
;
6470 short id
, scriptcode
;
6473 struct FontAssoc
*fat
;
6474 struct AsscEntry
*assc_entry
;
6475 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
6476 struct gcpro gcpro1
;
6478 GetPort (&port
); /* save the current font number used */
6479 old_fontnum
= port
->txFont
;
6481 text_encoding_info_alist
= create_text_encoding_info_alist ();
6483 GCPRO1 (text_encoding_info_alist
);
6485 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6487 font_handle
= GetIndResource ('FOND', i
);
6491 GetResInfo (font_handle
, &id
, &type
, name
);
6492 GetFNum (name
, &fontnum
);
6498 scriptcode
= FontToScript (fontnum
);
6499 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
6500 text_encoding_info_alist
);
6501 if (!NILP (text_encoding_info
))
6502 decode_mac_font_name (name
, sizeof (name
),
6503 XCAR (XCDR (text_encoding_info
)));
6505 text_encoding_info
= assq_no_quit (make_number (smRoman
),
6506 text_encoding_info_alist
);
6509 HLock (font_handle
);
6511 if (GetResourceSizeOnDisk (font_handle
)
6512 >= sizeof (struct FamRec
))
6514 fat
= (struct FontAssoc
*) (*font_handle
6515 + sizeof (struct FamRec
));
6517 = (struct AsscEntry
*) (*font_handle
6518 + sizeof (struct FamRec
)
6519 + sizeof (struct FontAssoc
));
6521 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6523 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6525 for (; !NILP (rest
); rest
= XCDR (rest
))
6527 char *cs
= SDATA (XCAR (rest
));
6529 add_font_name_table_entry (mac_to_x_fontname (name
,
6530 assc_entry
->fontSize
,
6531 assc_entry
->fontStyle
,
6537 HUnlock (font_handle
);
6538 font_handle_2
= GetNextFOND (font_handle
);
6539 ReleaseResource (font_handle
);
6540 font_handle
= font_handle_2
;
6542 while (ResError () == noErr
&& font_handle
);
6547 TextFont (old_fontnum
);
6548 #endif /* !TARGET_API_MAC_CARBON */
6553 mac_clear_font_name_table ()
6557 for (i
= 0; i
< font_name_count
; i
++)
6558 xfree (font_name_table
[i
]);
6559 xfree (font_name_table
);
6560 font_name_table
= NULL
;
6561 font_name_table_size
= font_name_count
= 0;
6565 enum xlfd_scalable_field_index
6567 XLFD_SCL_PIXEL_SIZE
,
6568 XLFD_SCL_POINT_SIZE
,
6573 static int xlfd_scalable_fields
[] =
6582 mac_c_string_match (regexp
, string
, nonspecial
, exact
)
6584 const char *string
, *nonspecial
;
6589 if (strcmp (string
, nonspecial
) == 0)
6590 return build_string (string
);
6592 else if (strstr (string
, nonspecial
))
6594 Lisp_Object str
= build_string (string
);
6596 if (fast_string_match (regexp
, str
) >= 0)
6604 mac_do_list_fonts (pattern
, maxnames
)
6609 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6610 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6612 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6613 char *longest_start
, *cur_start
, *nonspecial
;
6614 int longest_len
, exact
;
6616 if (font_name_table
== NULL
) /* Initialize when first used. */
6617 init_font_name_table ();
6619 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6622 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6623 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6624 fonts are scaled according to the specified size. */
6627 field
= xlfd_scalable_fields
;
6635 if ('0' <= *ptr
&& *ptr
<= '9')
6637 *val
= *ptr
++ - '0';
6638 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6639 *val
= *val
* 10 + *ptr
++ - '0';
6646 ptr
= strchr (ptr
, '-');
6649 while (ptr
&& i
< 14);
6651 if (i
== 14 && ptr
== NULL
)
6653 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
6654 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
6655 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
6656 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
6658 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
6659 scl_val
[XLFD_SCL_POINT_SIZE
] =
6660 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6661 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
6663 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
6664 scl_val
[XLFD_SCL_AVGWIDTH
] =
6665 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6666 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
6670 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6675 longest_start
= cur_start
= ptr
;
6679 /* Turn pattern into a regexp and do a regexp match. Also find the
6680 longest substring containing no special characters. */
6681 for (; *pattern
; pattern
++)
6683 if (*pattern
== '?' || *pattern
== '*')
6685 if (ptr
- cur_start
> longest_len
)
6687 longest_start
= cur_start
;
6688 longest_len
= ptr
- cur_start
;
6692 if (*pattern
== '?')
6694 else /* if (*pattern == '*') */
6702 *ptr
++ = tolower (*pattern
);
6705 if (ptr
- cur_start
> longest_len
)
6707 longest_start
= cur_start
;
6708 longest_len
= ptr
- cur_start
;
6714 nonspecial
= xmalloc (longest_len
+ 1);
6715 strncpy (nonspecial
, longest_start
, longest_len
);
6716 nonspecial
[longest_len
] = '\0';
6718 pattern_regex
= build_string (regex
);
6720 for (i
= 0; i
< font_name_count
; i
++)
6722 fontname
= mac_c_string_match (pattern_regex
, font_name_table
[i
],
6724 if (!NILP (fontname
))
6726 font_list
= Fcons (fontname
, font_list
);
6727 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6730 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6731 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
6733 int former_len
= ptr
- font_name_table
[i
];
6735 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
6736 memcpy (scaled
, font_name_table
[i
], former_len
);
6737 sprintf (scaled
+ former_len
,
6738 "-%d-%d-75-75-m-%d-%s",
6739 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6740 scl_val
[XLFD_SCL_POINT_SIZE
],
6741 scl_val
[XLFD_SCL_AVGWIDTH
],
6742 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
6743 fontname
= mac_c_string_match (pattern_regex
, scaled
,
6746 if (!NILP (fontname
))
6748 font_list
= Fcons (fontname
, font_list
);
6749 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6760 /* Return a list of names of available fonts matching PATTERN on frame F.
6762 Frame F null means we have not yet created any frame on Mac, and
6763 consult the first display in x_display_list. MAXNAMES sets a limit
6764 on how many fonts to match. */
6767 x_list_fonts (f
, pattern
, size
, maxnames
)
6769 Lisp_Object pattern
;
6772 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
6773 struct mac_display_info
*dpyinfo
6774 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
6776 xassert (size
<= 0);
6778 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6779 if (NILP (patterns
))
6780 patterns
= Fcons (pattern
, Qnil
);
6782 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
6784 pattern
= XCAR (patterns
);
6786 if (!STRINGP (pattern
))
6789 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
6790 key
= Fcons (pattern
, make_number (maxnames
));
6792 list
= Fassoc (key
, tem
);
6795 list
= Fcdr_safe (list
);
6796 /* We have a cashed list. Don't have to get the list again. */
6801 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6804 /* MAC_TODO: add code for matching outline fonts here */
6806 /* Now store the result in the cache. */
6807 XSETCAR (XCDR (dpyinfo
->name_list_element
),
6808 Fcons (Fcons (key
, list
),
6809 XCAR (XCDR (dpyinfo
->name_list_element
))));
6812 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6821 /* Check that FONT is valid on frame F. It is if it can be found in F's
6825 x_check_font (f
, font
)
6830 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6832 xassert (font
!= NULL
);
6834 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6835 if (dpyinfo
->font_table
[i
].name
6836 && font
== dpyinfo
->font_table
[i
].font
)
6839 xassert (i
< dpyinfo
->n_fonts
);
6842 #endif /* GLYPH_DEBUG != 0 */
6844 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6845 Note: There are (broken) X fonts out there with invalid XFontStruct
6846 min_bounds contents. For example, handa@etl.go.jp reports that
6847 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6848 have font->min_bounds.width == 0. */
6851 x_font_min_bounds (font
, w
, h
)
6852 MacFontStruct
*font
;
6855 *h
= FONT_HEIGHT (font
);
6856 *w
= font
->min_bounds
.width
;
6860 /* Compute the smallest character width and smallest font height over
6861 all fonts available on frame F. Set the members smallest_char_width
6862 and smallest_font_height in F's x_display_info structure to
6863 the values computed. Value is non-zero if smallest_font_height or
6864 smallest_char_width become smaller than they were before. */
6867 x_compute_min_glyph_bounds (f
)
6871 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6872 MacFontStruct
*font
;
6873 int old_width
= dpyinfo
->smallest_char_width
;
6874 int old_height
= dpyinfo
->smallest_font_height
;
6876 dpyinfo
->smallest_font_height
= 100000;
6877 dpyinfo
->smallest_char_width
= 100000;
6879 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6880 if (dpyinfo
->font_table
[i
].name
)
6882 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6885 font
= (MacFontStruct
*) fontp
->font
;
6886 xassert (font
!= (MacFontStruct
*) ~0);
6887 x_font_min_bounds (font
, &w
, &h
);
6889 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6890 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6893 xassert (dpyinfo
->smallest_char_width
> 0
6894 && dpyinfo
->smallest_font_height
> 0);
6896 return (dpyinfo
->n_fonts
== 1
6897 || dpyinfo
->smallest_char_width
< old_width
6898 || dpyinfo
->smallest_font_height
< old_height
);
6902 /* Determine whether given string is a fully-specified XLFD: all 14
6903 fields are present, none is '*'. */
6906 is_fully_specified_xlfd (char *p
)
6914 for (i
= 0; i
< 13; i
++)
6916 q
= strchr (p
+ 1, '-');
6919 if (q
- p
== 2 && *(p
+ 1) == '*')
6924 if (strchr (p
+ 1, '-') != NULL
)
6927 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6934 const int kDefaultFontSize
= 12;
6937 /* XLoadQueryFont creates and returns an internal representation for a
6938 font in a MacFontStruct struct. There is really no concept
6939 corresponding to "loading" a font on the Mac. But we check its
6940 existence and find the font number and all other information for it
6941 and store them in the returned MacFontStruct. */
6943 static MacFontStruct
*
6944 XLoadQueryFont (Display
*dpy
, char *fontname
)
6946 int i
, size
, point_size
, avgwidth
, is_two_byte_font
, char_width
;
6949 SInt16 old_fontnum
, old_fontsize
;
6951 Str255 mfontname
, mfontname_decoded
;
6955 #if TARGET_API_MAC_CARBON
6956 TextEncoding encoding
;
6961 MacFontStruct
*font
;
6962 FontInfo the_fontinfo
;
6964 UInt32 old_flags
, new_flags
;
6967 if (is_fully_specified_xlfd (fontname
))
6971 Lisp_Object matched_fonts
;
6973 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6974 if (NILP (matched_fonts
))
6976 name
= SDATA (XCAR (matched_fonts
));
6979 GetPort (&port
); /* save the current font number used */
6980 #if TARGET_API_MAC_CARBON
6981 old_fontnum
= GetPortTextFont (port
);
6982 old_fontsize
= GetPortTextSize (port
);
6983 old_fontface
= GetPortTextFace (port
);
6985 old_fontnum
= port
->txFont
;
6986 old_fontsize
= port
->txSize
;
6987 old_fontface
= port
->txFace
;
6990 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size
, &point_size
, &avgwidth
) != 3)
6996 size
= point_size
/ 10;
6997 else if (avgwidth
> 0)
6998 size
= avgwidth
/ 10;
7001 size
= kDefaultFontSize
;
7003 x_font_name_to_mac_font_name (name
, mfontname
, mfontname_decoded
,
7004 &fontface
, charset
);
7006 #if TARGET_API_MAC_CARBON
7007 fontnum
= FMGetFontFamilyFromName (mfontname
);
7008 if (fontnum
== kInvalidFontFamily
7009 || FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7011 scriptcode
= GetTextEncodingBase (encoding
);
7013 GetFNum (mfontname
, &fontnum
);
7016 scriptcode
= FontToScript (fontnum
);
7019 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7021 font
->mac_fontnum
= fontnum
;
7022 font
->mac_fontsize
= size
;
7023 font
->mac_fontface
= fontface
;
7024 font
->mac_scriptcode
= scriptcode
;
7026 /* Apple Japanese (SJIS) font is listed as both
7027 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7028 (Roman script) in init_font_name_table (). The latter should be
7029 treated as a one-byte font. */
7030 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7031 font
->mac_scriptcode
= smRoman
;
7033 font
->full_name
= mac_to_x_fontname (mfontname_decoded
, size
, fontface
, charset
);
7035 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
7036 font
->mac_scriptcode
== smTradChinese
||
7037 font
->mac_scriptcode
== smSimpChinese
||
7038 font
->mac_scriptcode
== smKorean
;
7042 TextFace (fontface
);
7044 GetFontInfo (&the_fontinfo
);
7046 font
->ascent
= the_fontinfo
.ascent
;
7047 font
->descent
= the_fontinfo
.descent
;
7049 font
->min_byte1
= 0;
7050 if (is_two_byte_font
)
7051 font
->max_byte1
= 1;
7053 font
->max_byte1
= 0;
7054 font
->min_char_or_byte2
= 0x20;
7055 font
->max_char_or_byte2
= 0xff;
7057 if (is_two_byte_font
)
7059 /* Use the width of an "ideographic space" of that font because
7060 the_fontinfo.widMax returns the wrong width for some fonts. */
7061 switch (font
->mac_scriptcode
)
7064 char_width
= StringWidth("\p\x81\x40");
7067 char_width
= StringWidth("\p\xa1\x40");
7070 char_width
= StringWidth("\p\xa1\xa1");
7073 char_width
= StringWidth("\p\xa1\xa1");
7078 /* Do this instead of use the_fontinfo.widMax, which incorrectly
7079 returns 15 for 12-point Monaco! */
7080 char_width
= CharWidth ('m');
7082 if (is_two_byte_font
)
7084 font
->per_char
= NULL
;
7086 if (fontface
& italic
)
7087 font
->max_bounds
.rbearing
= char_width
+ 1;
7089 font
->max_bounds
.rbearing
= char_width
;
7090 font
->max_bounds
.lbearing
= 0;
7091 font
->max_bounds
.width
= char_width
;
7092 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7093 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7095 font
->min_bounds
= font
->max_bounds
;
7099 font
->per_char
= (XCharStruct
*)
7100 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7102 int c
, min_width
, max_width
;
7103 Rect char_bounds
, min_bounds
, max_bounds
;
7106 min_width
= max_width
= char_width
;
7107 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
7108 SetRect (&max_bounds
, 0, 0, 0, 0);
7109 for (c
= 0x20; c
<= 0xff; c
++)
7112 char_width
= CharWidth (ch
);
7113 QDTextBounds (1, &ch
, &char_bounds
);
7114 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
7115 char_width
, char_bounds
);
7116 /* Some Japanese fonts (in SJIS encoding) return 0 as the
7117 character width of 0x7f. */
7120 min_width
= min (min_width
, char_width
);
7121 max_width
= max (max_width
, char_width
);
7123 if (!EmptyRect (&char_bounds
))
7125 SetRect (&min_bounds
,
7126 max (min_bounds
.left
, char_bounds
.left
),
7127 max (min_bounds
.top
, char_bounds
.top
),
7128 min (min_bounds
.right
, char_bounds
.right
),
7129 min (min_bounds
.bottom
, char_bounds
.bottom
));
7130 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7133 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7134 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7135 if (min_width
== max_width
7136 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
7138 /* Fixed width and no overhangs. */
7139 xfree (font
->per_char
);
7140 font
->per_char
= NULL
;
7145 TextFont (old_fontnum
); /* restore previous font number, size and face */
7146 TextSize (old_fontsize
);
7147 TextFace (old_fontface
);
7154 mac_unload_font (dpyinfo
, font
)
7155 struct mac_display_info
*dpyinfo
;
7158 xfree (font
->full_name
);
7160 xfree (font
->per_char
);
7165 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7166 pointer to the structure font_info while allocating it dynamically.
7167 If SIZE is 0, load any size of font.
7168 If loading is failed, return NULL. */
7171 x_load_font (f
, fontname
, size
)
7173 register char *fontname
;
7176 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7177 Lisp_Object font_names
;
7179 /* Get a list of all the fonts that match this name. Once we
7180 have a list of matching fonts, we compare them against the fonts
7181 we already have by comparing names. */
7182 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7184 if (!NILP (font_names
))
7189 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7190 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7191 if (dpyinfo
->font_table
[i
].name
7192 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7193 SDATA (XCAR (tail
)))
7194 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7195 SDATA (XCAR (tail
)))))
7196 return (dpyinfo
->font_table
+ i
);
7201 /* Load the font and add it to the table. */
7204 struct MacFontStruct
*font
;
7205 struct font_info
*fontp
;
7206 unsigned long value
;
7209 fontname
= (char *) SDATA (XCAR (font_names
));
7212 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7217 /* Find a free slot in the font table. */
7218 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7219 if (dpyinfo
->font_table
[i
].name
== NULL
)
7222 /* If no free slot found, maybe enlarge the font table. */
7223 if (i
== dpyinfo
->n_fonts
7224 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7227 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7228 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7230 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7233 fontp
= dpyinfo
->font_table
+ i
;
7234 if (i
== dpyinfo
->n_fonts
)
7237 /* Now fill in the slots of *FONTP. */
7239 bzero (fontp
, sizeof (*fontp
));
7241 fontp
->font_idx
= i
;
7242 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7243 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7245 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7247 /* Fixed width font. */
7248 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7255 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7256 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7258 fontp
->space_width
= pcm
->width
;
7260 fontp
->space_width
= FONT_WIDTH (font
);
7264 int width
= pcm
->width
;
7265 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7266 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7267 width
+= pcm
->width
;
7268 fontp
->average_width
= width
/ 95;
7271 fontp
->average_width
= FONT_WIDTH (font
);
7274 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7275 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7277 fontp
->size
= font
->max_bounds
.width
;
7278 fontp
->height
= FONT_HEIGHT (font
);
7280 /* For some font, ascent and descent in max_bounds field is
7281 larger than the above value. */
7282 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7283 if (max_height
> fontp
->height
)
7284 fontp
->height
= max_height
;
7287 /* The slot `encoding' specifies how to map a character
7288 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7289 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7290 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7291 2:0xA020..0xFF7F). For the moment, we don't know which charset
7292 uses this font. So, we set information in fontp->encoding[1]
7293 which is never used by any charset. If mapping can't be
7294 decided, set FONT_ENCODING_NOT_DECIDED. */
7295 if (font
->mac_scriptcode
== smJapanese
)
7296 fontp
->encoding
[1] = 4;
7300 = (font
->max_byte1
== 0
7302 ? (font
->min_char_or_byte2
< 0x80
7303 ? (font
->max_char_or_byte2
< 0x80
7304 ? 0 /* 0x20..0x7F */
7305 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
7306 : 1) /* 0xA0..0xFF */
7308 : (font
->min_byte1
< 0x80
7309 ? (font
->max_byte1
< 0x80
7310 ? (font
->min_char_or_byte2
< 0x80
7311 ? (font
->max_char_or_byte2
< 0x80
7312 ? 0 /* 0x2020..0x7F7F */
7313 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
7314 : 3) /* 0x20A0..0x7FFF */
7315 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
7316 : (font
->min_char_or_byte2
< 0x80
7317 ? (font
->max_char_or_byte2
< 0x80
7318 ? 2 /* 0xA020..0xFF7F */
7319 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
7320 : 1))); /* 0xA0A0..0xFFFF */
7323 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7324 fontp
->baseline_offset
7325 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
7326 ? (long) value
: 0);
7327 fontp
->relative_compose
7328 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
7329 ? (long) value
: 0);
7330 fontp
->default_ascent
7331 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
7332 ? (long) value
: 0);
7334 fontp
->baseline_offset
= 0;
7335 fontp
->relative_compose
= 0;
7336 fontp
->default_ascent
= 0;
7339 /* Set global flag fonts_changed_p to non-zero if the font loaded
7340 has a character with a smaller width than any other character
7341 before, or if the font loaded has a smalle>r height than any
7342 other font loaded before. If this happens, it will make a
7343 glyph matrix reallocation necessary. */
7344 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
7351 /* Return a pointer to struct font_info of a font named FONTNAME for
7352 frame F. If no such font is loaded, return NULL. */
7355 x_query_font (f
, fontname
)
7357 register char *fontname
;
7359 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7362 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7363 if (dpyinfo
->font_table
[i
].name
7364 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7365 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7366 return (dpyinfo
->font_table
+ i
);
7371 /* Find a CCL program for a font specified by FONTP, and set the member
7372 `encoder' of the structure. */
7375 x_find_ccl_program (fontp
)
7376 struct font_info
*fontp
;
7378 Lisp_Object list
, elt
;
7380 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7384 && STRINGP (XCAR (elt
))
7385 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7391 struct ccl_program
*ccl
7392 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7394 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7397 fontp
->font_encoder
= ccl
;
7403 /* The Mac Event loop code */
7405 #if !TARGET_API_MAC_CARBON
7407 #include <Quickdraw.h>
7408 #include <Balloons.h>
7409 #include <Devices.h>
7411 #include <Gestalt.h>
7413 #include <Processes.h>
7415 #include <ToolUtils.h>
7416 #include <TextUtils.h>
7417 #include <Dialogs.h>
7420 #include <Resources.h>
7425 #endif /* ! TARGET_API_MAC_CARBON */
7430 #define WINDOW_RESOURCE 128
7431 #define TERM_WINDOW_RESOURCE 129
7433 #define DEFAULT_NUM_COLS 80
7435 #define MIN_DOC_SIZE 64
7436 #define MAX_DOC_SIZE 32767
7439 /* sleep time for WaitNextEvent */
7440 #define WNE_SLEEP_AT_SUSPEND 10
7441 #define WNE_SLEEP_AT_RESUME 1
7443 /* the flag appl_is_suspended is used both for determining the sleep
7444 time to be passed to WaitNextEvent and whether the cursor should be
7445 drawn when updating the display. The cursor is turned off when
7446 Emacs is suspended. Redrawing it is unnecessary and what needs to
7447 be done depends on whether the cursor lies inside or outside the
7448 redraw region. So we might as well skip drawing it when Emacs is
7450 static Boolean app_is_suspended
= false;
7451 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7454 #define EXTRA_STACK_ALLOC (256 * 1024)
7456 #define ARGV_STRING_LIST_ID 129
7457 #define ABOUT_ALERT_ID 128
7458 #define RAM_TOO_LARGE_ALERT_ID 129
7460 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7461 Lisp_Object Qreverse
;
7463 /* True if using command key as meta key. */
7464 Lisp_Object Vmac_command_key_is_meta
;
7466 /* Modifier associated with the option key, or nil for normal behavior. */
7467 Lisp_Object Vmac_option_modifier
;
7469 /* True if the ctrl and meta keys should be reversed. */
7470 Lisp_Object Vmac_reverse_ctrl_meta
;
7472 /* True if the option and command modifiers should be used to emulate
7473 a three button mouse */
7474 Lisp_Object Vmac_emulate_three_button_mouse
;
7476 #if USE_CARBON_EVENTS
7477 /* True if the mouse wheel button (i.e. button 4) should map to
7478 mouse-2, instead of mouse-3. */
7479 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7481 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7482 for processing before Emacs sees it. */
7483 Lisp_Object Vmac_pass_command_to_system
;
7485 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7486 for processing before Emacs sees it. */
7487 Lisp_Object Vmac_pass_control_to_system
;
7489 /* Points to the variable `inev' in the function XTread_socket. It is
7490 used for passing an input event to the function back from a Carbon
7492 static struct input_event
*read_socket_inev
= NULL
;
7495 /* Set in term/mac-win.el to indicate that event loop can now generate
7496 drag and drop events. */
7497 Lisp_Object Qmac_ready_for_drag_n_drop
;
7499 Lisp_Object drag_and_drop_file_list
;
7501 Point saved_menu_event_location
;
7504 static void init_required_apple_events (void);
7506 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7508 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7509 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7510 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7512 #if TARGET_API_MAC_CARBON
7514 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7515 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7516 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7517 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7520 static Lisp_Object Qapplication
, Qabout
;
7521 #if USE_CARBON_EVENTS
7523 extern void init_service_handler ();
7524 static Lisp_Object Qpreferences
, Qservices
, Qpaste
, Qperform
;
7526 /* Window Event Handler */
7527 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7530 OSErr
install_window_handler (WindowPtr
);
7532 extern void init_emacs_passwd_dir ();
7533 extern int emacs_main (int, char **, char **);
7535 extern void initialize_applescript();
7536 extern void terminate_applescript();
7539 #if USE_CARBON_EVENTS
7540 mac_to_emacs_modifiers (UInt32 mods
)
7542 mac_to_emacs_modifiers (EventModifiers mods
)
7545 unsigned int result
= 0;
7546 if (mods
& macShiftKey
)
7547 result
|= shift_modifier
;
7548 if (mods
& macCtrlKey
)
7549 result
|= ctrl_modifier
;
7550 if (mods
& macMetaKey
)
7551 result
|= meta_modifier
;
7552 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7553 result
|= alt_modifier
;
7554 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7555 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7557 result
|= XUINT(val
);
7564 mac_get_emulated_btn ( UInt32 modifiers
)
7567 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7568 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7569 if (modifiers
& cmdKey
)
7570 result
= cmdIs3
? 2 : 1;
7571 else if (modifiers
& optionKey
)
7572 result
= cmdIs3
? 1 : 2;
7577 #if USE_CARBON_EVENTS
7578 /* Obtains the event modifiers from the event ref and then calls
7579 mac_to_emacs_modifiers. */
7581 mac_event_to_emacs_modifiers (EventRef eventRef
)
7584 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7585 sizeof (UInt32
), NULL
, &mods
);
7586 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7587 GetEventClass(eventRef
) == kEventClassMouse
)
7589 mods
&= ~(optionKey
| cmdKey
);
7591 return mac_to_emacs_modifiers (mods
);
7594 /* Given an event ref, return the code to use for the mouse button
7595 code in the emacs input_event. */
7597 mac_get_mouse_btn (EventRef ref
)
7599 EventMouseButton result
= kEventMouseButtonPrimary
;
7600 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7601 sizeof (EventMouseButton
), NULL
, &result
);
7604 case kEventMouseButtonPrimary
:
7605 if (NILP (Vmac_emulate_three_button_mouse
))
7609 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7610 sizeof (UInt32
), NULL
, &mods
);
7611 return mac_get_emulated_btn(mods
);
7613 case kEventMouseButtonSecondary
:
7614 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7615 case kEventMouseButtonTertiary
:
7616 case 4: /* 4 is the number for the mouse wheel button */
7617 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7623 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7624 events. However the click of the mouse wheel is not converted to a
7625 mouseDown or mouseUp event. Likewise for dead key down events.
7626 This calls ConvertEventRef, but then checks to see if it is a mouse
7627 up/down, or a dead key down carbon event that has not been
7628 converted, and if so, converts it by hand (to be picked up in the
7629 XTread_socket loop). */
7630 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7632 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7637 switch (GetEventClass (eventRef
))
7639 case kEventClassMouse
:
7640 switch (GetEventKind (eventRef
))
7642 case kEventMouseDown
:
7643 eventRec
->what
= mouseDown
;
7648 eventRec
->what
= mouseUp
;
7657 case kEventClassKeyboard
:
7658 switch (GetEventKind (eventRef
))
7660 case kEventRawKeyDown
:
7662 unsigned char char_codes
;
7665 eventRec
->what
= keyDown
;
7666 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
7667 NULL
, sizeof (char), NULL
, &char_codes
);
7668 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
7669 NULL
, sizeof (UInt32
), NULL
, &key_code
);
7670 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
7686 /* Need where and when. */
7689 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
7690 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
7691 /* Use two step process because new event modifiers are 32-bit
7692 and old are 16-bit. Currently, only loss is NumLock & Fn. */
7693 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
7694 NULL
, sizeof (UInt32
), NULL
, &mods
);
7695 eventRec
->modifiers
= mods
;
7697 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7708 Handle menubar_handle
;
7709 MenuHandle menu_handle
;
7711 menubar_handle
= GetNewMBar (128);
7712 if(menubar_handle
== NULL
)
7714 SetMenuBar (menubar_handle
);
7717 #if !TARGET_API_MAC_CARBON
7718 menu_handle
= GetMenuHandle (M_APPLE
);
7719 if(menu_handle
!= NULL
)
7720 AppendResMenu (menu_handle
,'DRVR');
7728 do_init_managers (void)
7730 #if !TARGET_API_MAC_CARBON
7731 InitGraf (&qd
.thePort
);
7733 FlushEvents (everyEvent
, 0);
7738 #endif /* !TARGET_API_MAC_CARBON */
7741 #if !TARGET_API_MAC_CARBON
7742 /* set up some extra stack space for use by emacs */
7743 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7745 /* MaxApplZone must be called for AppleScript to execute more
7746 complicated scripts */
7749 #endif /* !TARGET_API_MAC_CARBON */
7753 do_check_ram_size (void)
7755 SInt32 physical_ram_size
, logical_ram_size
;
7757 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7758 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7759 || physical_ram_size
> (1 << VALBITS
)
7760 || logical_ram_size
> (1 << VALBITS
))
7762 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7768 do_window_update (WindowPtr win
)
7770 struct frame
*f
= mac_window_to_frame (win
);
7774 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7776 if (win
!= tip_window
)
7778 if (f
->async_visible
== 0)
7780 f
->async_visible
= 1;
7781 f
->async_iconified
= 0;
7782 SET_FRAME_GARBAGED (f
);
7784 /* An update event is equivalent to MapNotify on X, so report
7785 visibility changes properly. */
7786 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7787 /* Force a redisplay sooner or later to update the
7788 frame titles in case this is the second frame. */
7789 record_asynch_buffer_change ();
7795 #if TARGET_API_MAC_CARBON
7797 RgnHandle region
= NewRgn ();
7799 GetPortVisibleRegion (GetWindowPort (win
), region
);
7800 GetRegionBounds (region
, &r
);
7801 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7802 UpdateControls (win
, region
);
7803 DisposeRgn (region
);
7806 r
= (*win
->visRgn
)->rgnBBox
;
7807 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7808 UpdateControls (win
, win
->visRgn
);
7817 is_emacs_window (WindowPtr win
)
7819 Lisp_Object tail
, frame
;
7824 FOR_EACH_FRAME (tail
, frame
)
7825 if (FRAME_MAC_P (XFRAME (frame
)))
7826 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7835 /* Window-activate events will do the job. */
7837 app_is_suspended
= false;
7838 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7845 /* Window-deactivate events will do the job. */
7847 app_is_suspended
= true;
7848 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7854 do_apple_menu (SInt16 menu_item
)
7856 #if !TARGET_API_MAC_CARBON
7858 SInt16 da_driver_refnum
;
7860 if (menu_item
== I_ABOUT
)
7861 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7864 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7865 da_driver_refnum
= OpenDeskAcc (item_name
);
7867 #endif /* !TARGET_API_MAC_CARBON */
7871 do_menu_choice (SInt32 menu_choice
)
7873 SInt16 menu_id
, menu_item
;
7875 menu_id
= HiWord (menu_choice
);
7876 menu_item
= LoWord (menu_choice
);
7884 do_apple_menu (menu_item
);
7889 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
7890 MenuHandle menu
= GetMenuHandle (menu_id
);
7895 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7896 menubar_selection_callback (f
, refcon
);
7905 /* Handle drags in size box. Based on code contributed by Ben
7906 Mesander and IM - Window Manager A. */
7909 do_grow_window (WindowPtr w
, EventRecord
*e
)
7912 int rows
, columns
, width
, height
;
7913 struct frame
*f
= mac_window_to_frame (w
);
7914 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
7915 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
7916 #if TARGET_API_MAC_CARBON
7922 if (size_hints
->flags
& PMinSize
)
7924 min_width
= size_hints
->min_width
;
7925 min_height
= size_hints
->min_height
;
7927 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7929 #if TARGET_API_MAC_CARBON
7930 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
7932 height
= new_rect
.bottom
- new_rect
.top
;
7933 width
= new_rect
.right
- new_rect
.left
;
7935 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7936 /* see if it really changed size */
7939 height
= HiWord (grow_size
);
7940 width
= LoWord (grow_size
);
7943 if (width
!= FRAME_PIXEL_WIDTH (f
)
7944 || height
!= FRAME_PIXEL_HEIGHT (f
))
7946 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7947 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7949 x_set_window_size (f
, 0, columns
, rows
);
7954 /* Handle clicks in zoom box. Calculation of "standard state" based
7955 on code in IM - Window Manager A and code contributed by Ben
7956 Mesander. The standard state of an Emacs window is 80-characters
7957 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7960 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7963 Rect zoom_rect
, port_rect
;
7965 int w_title_height
, columns
, rows
, width
, height
;
7966 struct frame
*f
= mac_window_to_frame (w
);
7967 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7969 #if TARGET_API_MAC_CARBON
7971 Point standard_size
;
7973 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7974 standard_size
.v
= dpyinfo
->height
;
7976 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7977 zoom_in_or_out
= inZoomIn
;
7980 /* Adjust the standard size according to character boundaries. */
7982 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7983 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7984 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7985 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7986 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
7987 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
7988 && port_rect
.left
== zoom_rect
.left
7989 && port_rect
.top
== zoom_rect
.top
)
7990 zoom_in_or_out
= inZoomIn
;
7992 zoom_in_or_out
= inZoomOut
;
7995 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
7997 #else /* not TARGET_API_MAC_CARBON */
7998 GetPort (&save_port
);
8000 SetPortWindowPort (w
);
8002 /* Clear window to avoid flicker. */
8003 EraseRect (&(w
->portRect
));
8004 if (zoom_in_or_out
== inZoomOut
)
8006 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8007 LocalToGlobal (&top_left
);
8009 /* calculate height of window's title bar */
8010 w_title_height
= top_left
.v
- 1
8011 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8013 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8014 zoom_rect
= qd
.screenBits
.bounds
;
8015 zoom_rect
.top
+= w_title_height
;
8016 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8018 zoom_rect
.right
= zoom_rect
.left
8019 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8021 /* Adjust the standard size according to character boundaries. */
8022 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8024 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8026 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8030 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8032 SetPort (save_port
);
8033 #endif /* not TARGET_API_MAC_CARBON */
8035 /* retrieve window size and update application values */
8036 #if TARGET_API_MAC_CARBON
8037 GetWindowPortBounds (w
, &port_rect
);
8039 port_rect
= w
->portRect
;
8041 height
= port_rect
.bottom
- port_rect
.top
;
8042 width
= port_rect
.right
- port_rect
.left
;
8044 if (width
!= FRAME_PIXEL_WIDTH (f
)
8045 || height
!= FRAME_PIXEL_HEIGHT (f
))
8047 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8048 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8050 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8051 SET_FRAME_GARBAGED (f
);
8052 cancel_mouse_face (f
);
8054 FRAME_PIXEL_WIDTH (f
) = width
;
8055 FRAME_PIXEL_HEIGHT (f
) = height
;
8057 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8060 /* Intialize AppleEvent dispatcher table for the required events. */
8062 init_required_apple_events ()
8067 /* Make sure we have apple events before starting. */
8068 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
8072 if (!(result
& (1 << gestaltAppleEventsPresent
)))
8075 #if TARGET_API_MAC_CARBON
8076 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8077 NewAEEventHandlerUPP
8078 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8081 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8082 NewAEEventHandlerProc
8083 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8089 #if TARGET_API_MAC_CARBON
8090 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8091 NewAEEventHandlerUPP
8092 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8095 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8096 NewAEEventHandlerProc
8097 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8103 #if TARGET_API_MAC_CARBON
8104 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8105 NewAEEventHandlerUPP
8106 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8109 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8110 NewAEEventHandlerProc
8111 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8117 #if TARGET_API_MAC_CARBON
8118 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8119 NewAEEventHandlerUPP
8120 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8123 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8124 NewAEEventHandlerProc
8125 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8133 mac_store_application_menu_event (event
)
8134 #if USE_CARBON_EVENTS
8140 struct input_event buf
;
8141 Lisp_Object frame
, entry
;
8145 XSETFRAME (frame
, mac_focus_frame (&one_mac_display_info
));
8146 buf
.kind
= MENU_BAR_EVENT
;
8147 buf
.frame_or_window
= frame
;
8149 kbd_buffer_store_event (&buf
);
8151 buf
.arg
= Qapplication
;
8152 kbd_buffer_store_event (&buf
);
8154 #if USE_CARBON_EVENTS
8155 switch (GetEventClass (event
))
8158 case kEventClassService
:
8159 buf
.arg
= Qservices
;
8160 kbd_buffer_store_event (&buf
);
8161 switch (GetEventKind (event
))
8163 case kEventServicePaste
:
8167 case kEventServicePerform
:
8170 CFStringRef message
;
8172 err
= GetEventParameter (event
, kEventParamServiceMessageName
,
8173 typeCFStringRef
, NULL
,
8174 sizeof (CFStringRef
), NULL
, &message
);
8176 kbd_buffer_store_event (&buf
);
8177 if (err
== noErr
&& message
)
8178 entry
= intern (SDATA (cfstring_to_lisp (message
)));
8188 #endif /* MAC_OSX */
8189 case kEventClassCommand
:
8193 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
,
8194 NULL
, sizeof (HICommand
), NULL
, &command
);
8195 switch (command
.commandID
)
8197 case kHICommandAbout
:
8201 case kHICommandPreferences
:
8202 entry
= Qpreferences
;
8204 #endif /* MAC_OSX */
8205 case kHICommandQuit
:
8217 #else /* USE_CARBON_EVENTS */
8220 case kHICommandAbout
:
8223 case kHICommandQuit
:
8232 kbd_buffer_store_event (&buf
);
8235 #if USE_CARBON_EVENTS
8236 static pascal OSStatus
8237 mac_handle_command_event (next_handler
, event
, data
)
8238 EventHandlerCallRef next_handler
;
8245 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8246 sizeof (HICommand
), NULL
, &command
);
8248 switch (command
.commandID
)
8250 case kHICommandAbout
:
8252 case kHICommandPreferences
:
8253 #endif /* MAC_OSX */
8254 result
= CallNextEventHandler (next_handler
, event
);
8255 if (result
!= eventNotHandledErr
)
8258 mac_store_application_menu_event (event
);
8265 return eventNotHandledErr
;
8269 init_command_handler ()
8272 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8273 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8275 if (handle_command_eventUPP
== NULL
)
8276 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8277 return InstallApplicationEventHandler (handle_command_eventUPP
,
8278 GetEventTypeCount (specs
), specs
,
8282 static pascal OSStatus
8283 mac_handle_window_event (next_handler
, event
, data
)
8284 EventHandlerCallRef next_handler
;
8291 XSizeHints
*size_hints
;
8293 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8294 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8296 switch (GetEventKind (event
))
8298 case kEventWindowUpdate
:
8299 result
= CallNextEventHandler (next_handler
, event
);
8300 if (result
!= eventNotHandledErr
)
8303 do_window_update (wp
);
8306 case kEventWindowBoundsChanging
:
8307 result
= CallNextEventHandler (next_handler
, event
);
8308 if (result
!= eventNotHandledErr
)
8311 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8312 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8313 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8314 if ((attributes
& kWindowBoundsChangeUserResize
)
8315 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8316 == (PResizeInc
| PBaseSize
| PMinSize
)))
8321 GetEventParameter (event
, kEventParamCurrentBounds
,
8323 NULL
, sizeof (Rect
), NULL
, &bounds
);
8324 width
= bounds
.right
- bounds
.left
;
8325 height
= bounds
.bottom
- bounds
.top
;
8327 if (width
< size_hints
->min_width
)
8328 width
= size_hints
->min_width
;
8330 width
= size_hints
->base_width
8331 + (int) ((width
- size_hints
->base_width
)
8332 / (float) size_hints
->width_inc
+ .5)
8333 * size_hints
->width_inc
;
8335 if (height
< size_hints
->min_height
)
8336 height
= size_hints
->min_height
;
8338 height
= size_hints
->base_height
8339 + (int) ((height
- size_hints
->base_height
)
8340 / (float) size_hints
->height_inc
+ .5)
8341 * size_hints
->height_inc
;
8343 bounds
.right
= bounds
.left
+ width
;
8344 bounds
.bottom
= bounds
.top
+ height
;
8345 SetEventParameter (event
, kEventParamCurrentBounds
,
8346 typeQDRectangle
, sizeof (Rect
), &bounds
);
8352 return eventNotHandledErr
;
8355 static pascal OSStatus
8356 mac_handle_mouse_event (next_handler
, event
, data
)
8357 EventHandlerCallRef next_handler
;
8363 switch (GetEventKind (event
))
8365 case kEventMouseWheelMoved
:
8369 EventMouseWheelAxis axis
;
8373 result
= CallNextEventHandler (next_handler
, event
);
8374 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
8377 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
8378 NULL
, sizeof (WindowRef
), NULL
, &wp
);
8379 f
= mac_window_to_frame (wp
);
8380 if (f
!= mac_focus_frame (&one_mac_display_info
))
8383 GetEventParameter (event
, kEventParamMouseWheelAxis
,
8384 typeMouseWheelAxis
, NULL
,
8385 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
8386 if (axis
!= kEventMouseWheelAxisY
)
8389 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
8390 NULL
, sizeof (SInt32
), NULL
, &delta
);
8391 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
8392 NULL
, sizeof (Point
), NULL
, &point
);
8393 read_socket_inev
->kind
= WHEEL_EVENT
;
8394 read_socket_inev
->code
= 0;
8395 read_socket_inev
->modifiers
=
8396 (mac_event_to_emacs_modifiers (event
)
8397 | ((delta
< 0) ? down_modifier
: up_modifier
));
8398 SetPortWindowPort (wp
);
8399 GlobalToLocal (&point
);
8400 XSETINT (read_socket_inev
->x
, point
.h
);
8401 XSETINT (read_socket_inev
->y
, point
.v
);
8402 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
8403 read_socket_inev
->timestamp
=
8404 EventTimeToTicks (GetEventTime (event
)) * (1000/60);
8414 return eventNotHandledErr
;
8416 #endif /* USE_CARBON_EVENTS */
8420 install_window_handler (window
)
8424 #if USE_CARBON_EVENTS
8425 EventTypeSpec specs_window
[] =
8426 {{kEventClassWindow
, kEventWindowUpdate
},
8427 {kEventClassWindow
, kEventWindowBoundsChanging
}};
8428 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
8429 static EventHandlerUPP handle_window_eventUPP
= NULL
;
8430 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
8432 if (handle_window_eventUPP
== NULL
)
8433 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
8434 if (handle_mouse_eventUPP
== NULL
)
8435 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
8436 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
8437 GetEventTypeCount (specs_window
),
8438 specs_window
, NULL
, NULL
);
8440 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
8441 GetEventTypeCount (specs_mouse
),
8442 specs_mouse
, NULL
, NULL
);
8444 #if TARGET_API_MAC_CARBON
8445 if (mac_do_track_dragUPP
== NULL
)
8446 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8447 if (mac_do_receive_dragUPP
== NULL
)
8448 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8451 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8453 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8459 remove_window_handler (window
)
8462 #if TARGET_API_MAC_CARBON
8463 if (mac_do_track_dragUPP
)
8464 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8465 if (mac_do_receive_dragUPP
)
8466 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8470 /* Open Application Apple Event */
8472 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8478 /* Defined in mac.c. */
8480 path_from_vol_dir_name (char *, int, short, long, char *);
8483 /* Called when we receive an AppleEvent with an ID of
8484 "kAEOpenDocuments". This routine gets the direct parameter,
8485 extracts the FSSpecs in it, and puts their names on a list. */
8486 #pragma options align=mac68k
8487 typedef struct SelectionRange
{
8488 short unused1
; // 0 (not used)
8489 short lineNum
; // line to select (<0 to specify range)
8490 long startRange
; // start of selection range (if line < 0)
8491 long endRange
; // end of selection range (if line < 0)
8492 long unused2
; // 0 (not used)
8493 long theDate
; // modification date/time
8495 #pragma options align=reset
8498 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8503 DescType actual_type
;
8505 SelectionRange position
;
8507 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8509 goto descriptor_error_exit
;
8511 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8513 drag_and_drop_file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8514 make_number (position
.startRange
+ 1),
8515 make_number (position
.endRange
+ 1)),
8516 drag_and_drop_file_list
);
8518 /* Check to see that we got all of the required parameters from the
8519 event descriptor. For an 'odoc' event this should just be the
8521 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8522 &actual_type
, (Ptr
) &keyword
,
8523 sizeof (keyword
), &actual_size
);
8524 /* No error means that we found some unused parameters.
8525 errAEDescNotFound means that there are no more parameters. If we
8526 get an error code other than that, flag it. */
8527 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8529 err
= errAEEventNotHandled
;
8534 /* Got all the parameters we need. Now, go through the direct
8535 object list and parse it up. */
8537 long num_files_to_open
;
8539 err
= AECountItems (&the_desc
, &num_files_to_open
);
8544 /* AE file list is one based so just use that for indexing here. */
8545 for (i
= 1; i
<= num_files_to_open
; i
++)
8547 char unix_path_name
[MAXPATHLEN
];
8551 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8552 &actual_type
, &fref
, sizeof (FSRef
),
8554 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8557 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8562 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8563 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8564 if (err
!= noErr
) continue;
8566 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
8567 sizeof (unix_path_name
) - 1) == noErr
)
8569 /* x-dnd functions expect undecoded filenames. */
8570 drag_and_drop_file_list
=
8571 Fcons (make_unibyte_string (unix_path_name
,
8572 strlen (unix_path_name
)),
8573 drag_and_drop_file_list
);
8579 /* Nuke the coerced file list in any case */
8580 err2
= AEDisposeDesc(&the_desc
);
8582 descriptor_error_exit
:
8583 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8588 #if TARGET_API_MAC_CARBON
8590 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8591 void *handlerRefCon
, DragReference theDrag
)
8593 static int can_accept
;
8596 ItemReference theItem
;
8597 FlavorFlags theFlags
;
8600 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8601 return dragNotAcceptedErr
;
8605 case kDragTrackingEnterHandler
:
8606 CountDragItems (theDrag
, &items
);
8608 for (index
= 1; index
<= items
; index
++)
8610 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8611 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8612 if (result
== noErr
)
8620 case kDragTrackingEnterWindow
:
8623 RgnHandle hilite_rgn
= NewRgn ();
8625 struct frame
*f
= mac_window_to_frame (window
);
8627 GetWindowPortBounds (window
, &r
);
8628 OffsetRect (&r
, -r
.left
, -r
.top
);
8629 RectRgn (hilite_rgn
, &r
);
8630 ShowDragHilite (theDrag
, hilite_rgn
, true);
8631 DisposeRgn (hilite_rgn
);
8632 SetThemeCursor (kThemeCopyArrowCursor
);
8636 case kDragTrackingInWindow
:
8639 case kDragTrackingLeaveWindow
:
8642 struct frame
*f
= mac_window_to_frame (window
);
8644 HideDragHilite (theDrag
);
8645 SetThemeCursor (kThemeArrowCursor
);
8649 case kDragTrackingLeaveHandler
:
8657 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8658 DragReference theDrag
)
8662 FlavorFlags theFlags
;
8665 ItemReference theItem
;
8667 Size size
= sizeof (HFSFlavor
);
8669 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8670 return dragNotAcceptedErr
;
8672 drag_and_drop_file_list
= Qnil
;
8673 GetDragMouse (theDrag
, &mouse
, 0L);
8674 CountDragItems (theDrag
, &items
);
8675 for (index
= 1; index
<= items
; index
++)
8677 /* Only handle file references. */
8678 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8679 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8680 if (result
== noErr
)
8685 char unix_path_name
[MAXPATHLEN
];
8687 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8689 /* Use Carbon routines, otherwise it converts the file name
8690 to /Macintosh HD/..., which is not correct. */
8691 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8692 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8694 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
8695 sizeof (unix_path_name
) - 1) == noErr
)
8697 /* x-dnd functions expect undecoded filenames. */
8698 drag_and_drop_file_list
=
8699 Fcons (make_unibyte_string (unix_path_name
,
8700 strlen (unix_path_name
)),
8701 drag_and_drop_file_list
);
8704 /* If there are items in the list, construct an event and post it to
8705 the queue like an interrupt using kbd_buffer_store_event. */
8706 if (!NILP (drag_and_drop_file_list
))
8708 struct input_event event
;
8710 struct frame
*f
= mac_window_to_frame (window
);
8713 GlobalToLocal (&mouse
);
8714 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8716 event
.kind
= DRAG_N_DROP_EVENT
;
8718 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8719 event
.timestamp
= TickCount () * (1000 / 60);
8720 XSETINT (event
.x
, mouse
.h
);
8721 XSETINT (event
.y
, mouse
.v
);
8722 XSETFRAME (frame
, f
);
8723 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8725 /* Post to the interrupt queue */
8726 kbd_buffer_store_event (&event
);
8727 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8729 ProcessSerialNumber psn
;
8730 GetCurrentProcess (&psn
);
8731 SetFrontProcess (&psn
);
8737 return dragNotAcceptedErr
;
8742 /* Print Document Apple Event */
8744 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8746 return errAEEventNotHandled
;
8751 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8753 #if USE_CARBON_EVENTS
8755 EventRef event
= NULL
;
8756 static const HICommand quit_command
= {kEventAttributeNone
, kHICommandQuit
};
8758 err
= CreateEvent (NULL
, kEventClassCommand
, kEventCommandProcess
, 0,
8759 kEventAttributeUserEvent
, &event
);
8761 err
= SetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
8762 sizeof (HICommand
), &quit_command
);
8764 mac_store_application_menu_event (event
);
8766 ReleaseEvent (event
);
8771 return errAEEventNotHandled
;
8773 mac_store_application_menu_event (kHICommandQuit
);
8782 profiler_exit_proc ()
8784 ProfilerDump ("\pEmacs.prof");
8789 /* These few functions implement Emacs as a normal Mac application
8790 (almost): set up the heap and the Toolbox, handle necessary system
8791 events plus a few simple menu events. They also set up Emacs's
8792 access to functions defined in the rest of this file. Emacs uses
8793 function hooks to perform all its terminal I/O. A complete list of
8794 these functions appear in termhooks.h. For what they do, read the
8795 comments there and see also w32term.c and xterm.c. What's
8796 noticeably missing here is the event loop, which is normally
8797 present in most Mac application. After performing the necessary
8798 Mac initializations, main passes off control to emacs_main
8799 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
8800 (defined further below) to read input. This is where
8801 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
8808 #if __profile__ /* is the profiler on? */
8809 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
8814 /* set creator and type for files created by MSL */
8819 do_init_managers ();
8824 do_check_ram_size ();
8827 init_emacs_passwd_dir ();
8831 initialize_applescript ();
8833 init_required_apple_events ();
8839 /* set up argv array from STR# resource */
8840 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
8844 /* free up AppleScript resources on exit */
8845 atexit (terminate_applescript
);
8847 #if __profile__ /* is the profiler on? */
8848 atexit (profiler_exit_proc
);
8851 /* 3rd param "envp" never used in emacs_main */
8852 (void) emacs_main (argc
, argv
, 0);
8855 /* Never reached - real exit in Fkill_emacs */
8860 /* Table for translating Mac keycode to X keysym values. Contributed
8862 Mapping for special keys is now identical to that in Apple X11
8863 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8864 on the right of the Cmd key on laptops, and fn + `enter' (->
8866 static unsigned char keycode_to_xkeysym_table
[] = {
8867 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8868 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8869 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8871 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8872 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8873 /*0x38*/ 0, 0, 0, 0,
8874 /*0x3C*/ 0, 0, 0, 0,
8876 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8877 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8878 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8879 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8881 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8882 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8883 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8884 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8886 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8887 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8888 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8889 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8891 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8892 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8893 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8894 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8898 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8900 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8901 return *xKeySym
!= 0;
8904 #if !USE_CARBON_EVENTS
8905 static RgnHandle mouse_region
= NULL
;
8908 mac_wait_next_event (er
, sleep_time
, dequeue
)
8913 static EventRecord er_buf
= {nullEvent
};
8914 UInt32 target_tick
, current_tick
;
8915 EventMask event_mask
;
8917 if (mouse_region
== NULL
)
8918 mouse_region
= NewRgn ();
8920 event_mask
= everyEvent
;
8921 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8922 event_mask
-= highLevelEventMask
;
8924 current_tick
= TickCount ();
8925 target_tick
= current_tick
+ sleep_time
;
8927 if (er_buf
.what
== nullEvent
)
8928 while (!WaitNextEvent (event_mask
, &er_buf
,
8929 target_tick
- current_tick
, mouse_region
))
8931 current_tick
= TickCount ();
8932 if (target_tick
<= current_tick
)
8938 er_buf
.what
= nullEvent
;
8941 #endif /* not USE_CARBON_EVENTS */
8943 /* Emacs calls this whenever it wants to read an input event from the
8946 XTread_socket (sd
, expected
, hold_quit
)
8948 struct input_event
*hold_quit
;
8950 struct input_event inev
;
8952 #if USE_CARBON_EVENTS
8954 EventTargetRef toolbox_dispatcher
;
8957 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8959 if (interrupt_input_blocked
)
8961 interrupt_input_pending
= 1;
8965 interrupt_input_pending
= 0;
8968 /* So people can tell when we have read the available input. */
8969 input_signal_count
++;
8971 #if USE_CARBON_EVENTS
8972 toolbox_dispatcher
= GetEventDispatcherTarget ();
8974 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8975 kEventRemoveFromQueue
, &eventRef
))
8976 #else /* !USE_CARBON_EVENTS */
8977 while (mac_wait_next_event (&er
, 0, true))
8978 #endif /* !USE_CARBON_EVENTS */
8983 /* It is necessary to set this (additional) argument slot of an
8984 event to nil because keyboard.c protects incompletely
8985 processed event from being garbage collected by placing them
8986 in the kbd_buffer_gcpro vector. */
8988 inev
.kind
= NO_EVENT
;
8991 #if USE_CARBON_EVENTS
8992 /* Handle new events */
8993 if (!mac_convert_event_ref (eventRef
, &er
))
8995 /* There used to be a handler for the kEventMouseWheelMoved
8996 event here. But as of Mac OS X 10.4, this kind of event
8997 is not directly posted to the main event queue by
8998 two-finger scrolling on the trackpad. Instead, some
8999 private event is posted and it is converted to a wheel
9000 event by the default handler for the application target.
9001 The converted one can be received by a Carbon event
9002 handler installed on a window target. */
9003 read_socket_inev
= &inev
;
9004 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9005 read_socket_inev
= NULL
;
9008 #endif /* USE_CARBON_EVENTS */
9014 WindowPtr window_ptr
;
9015 ControlPartCode part_code
;
9018 #if USE_CARBON_EVENTS
9019 /* This is needed to send mouse events like aqua window
9020 buttons to the correct handler. */
9021 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9022 != eventNotHandledErr
)
9026 if (dpyinfo
->grabbed
&& last_mouse_frame
9027 && FRAME_LIVE_P (last_mouse_frame
))
9029 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9030 part_code
= inContent
;
9034 part_code
= FindWindow (er
.where
, &window_ptr
);
9035 if (tip_window
&& window_ptr
== tip_window
)
9037 HideWindow (tip_window
);
9038 part_code
= FindWindow (er
.where
, &window_ptr
);
9042 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
9048 f
= mac_focus_frame (dpyinfo
);
9049 saved_menu_event_location
= er
.where
;
9050 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9051 XSETFRAME (inev
.frame_or_window
, f
);
9055 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9056 SelectWindow (window_ptr
);
9059 ControlPartCode control_part_code
;
9061 Point mouse_loc
= er
.where
;
9063 ControlKind control_kind
;
9066 f
= mac_window_to_frame (window_ptr
);
9067 /* convert to local coordinates of new window */
9068 SetPortWindowPort (window_ptr
);
9070 GlobalToLocal (&mouse_loc
);
9071 #if TARGET_API_MAC_CARBON
9072 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9073 &control_part_code
);
9076 GetControlKind (ch
, &control_kind
);
9079 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9083 #if USE_CARBON_EVENTS
9084 inev
.code
= mac_get_mouse_btn (eventRef
);
9085 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9087 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9088 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9090 XSETINT (inev
.x
, mouse_loc
.h
);
9091 XSETINT (inev
.y
, mouse_loc
.v
);
9092 inev
.timestamp
= er
.when
* (1000 / 60);
9093 /* ticks to milliseconds */
9095 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9097 #ifndef USE_TOOLKIT_SCROLL_BARS
9098 /* control_part_code becomes kControlNoPart if
9099 a progress indicator is clicked. */
9100 && control_part_code
!= kControlNoPart
9101 #else /* USE_TOOLKIT_SCROLL_BARS */
9103 && control_kind
.kind
== kControlKindScrollBar
9104 #endif /* MAC_OSX */
9105 #endif /* USE_TOOLKIT_SCROLL_BARS */
9108 struct scroll_bar
*bar
;
9110 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9112 bar
= tracked_scroll_bar
;
9113 #ifndef USE_TOOLKIT_SCROLL_BARS
9114 control_part_code
= kControlIndicatorPart
;
9118 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9119 #ifdef USE_TOOLKIT_SCROLL_BARS
9120 /* Make the "Ctrl-Mouse-2 splits window" work
9121 for toolkit scroll bars. */
9122 if (er
.modifiers
& controlKey
)
9123 x_scroll_bar_handle_click (bar
, control_part_code
,
9125 else if (er
.what
== mouseDown
)
9126 x_scroll_bar_handle_press (bar
, control_part_code
,
9127 inev
.timestamp
, &inev
);
9129 x_scroll_bar_handle_release (bar
, inev
.timestamp
,
9131 #else /* not USE_TOOLKIT_SCROLL_BARS */
9132 x_scroll_bar_handle_click (bar
, control_part_code
,
9134 if (er
.what
== mouseDown
9135 && control_part_code
== kControlIndicatorPart
)
9136 tracked_scroll_bar
= bar
;
9138 tracked_scroll_bar
= NULL
;
9139 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9144 int x
= mouse_loc
.h
;
9145 int y
= mouse_loc
.v
;
9147 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9148 if (EQ (window
, f
->tool_bar_window
))
9150 if (er
.what
== mouseDown
)
9151 handle_tool_bar_click (f
, x
, y
, 1, 0);
9153 handle_tool_bar_click (f
, x
, y
, 0,
9159 XSETFRAME (inev
.frame_or_window
, f
);
9160 inev
.kind
= MOUSE_CLICK_EVENT
;
9164 if (er
.what
== mouseDown
)
9166 dpyinfo
->grabbed
|= (1 << inev
.code
);
9167 last_mouse_frame
= f
;
9168 /* Ignore any mouse motion that happened
9169 before this event; any subsequent
9170 mouse-movement Emacs events should reflect
9171 only motion after the ButtonPress. */
9176 last_tool_bar_item
= -1;
9180 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9181 /* If a button is released though it was not
9182 previously pressed, that would be because
9183 of multi-button emulation. */
9184 dpyinfo
->grabbed
= 0;
9186 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9189 #ifdef USE_TOOLKIT_SCROLL_BARS
9190 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9195 inev
.modifiers
|= down_modifier
;
9198 inev
.modifiers
|= up_modifier
;
9205 #if TARGET_API_MAC_CARBON
9206 DragWindow (window_ptr
, er
.where
, NULL
);
9207 #else /* not TARGET_API_MAC_CARBON */
9208 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9209 #endif /* not TARGET_API_MAC_CARBON */
9210 /* Update the frame parameters. */
9212 struct frame
*f
= mac_window_to_frame (window_ptr
);
9214 if (f
&& !f
->async_iconified
)
9215 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9220 if (TrackGoAway (window_ptr
, er
.where
))
9222 inev
.kind
= DELETE_WINDOW_EVENT
;
9223 XSETFRAME (inev
.frame_or_window
,
9224 mac_window_to_frame (window_ptr
));
9228 /* window resize handling added --ben */
9230 do_grow_window (window_ptr
, &er
);
9233 /* window zoom handling added --ben */
9236 if (TrackBox (window_ptr
, er
.where
, part_code
))
9237 do_zoom_window (window_ptr
, part_code
);
9247 #if USE_CARBON_EVENTS
9248 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9249 != eventNotHandledErr
)
9252 do_window_update ((WindowPtr
) er
.message
);
9257 #if USE_CARBON_EVENTS
9258 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9259 != eventNotHandledErr
)
9262 switch ((er
.message
>> 24) & 0x000000FF)
9264 case suspendResumeMessage
:
9265 if ((er
.message
& resumeFlag
) == 1)
9271 case mouseMovedMessage
:
9272 #if !USE_CARBON_EVENTS
9273 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9274 er
.where
.h
+ 1, er
.where
.v
+ 1);
9276 previous_help_echo_string
= help_echo_string
;
9277 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
9280 if (dpyinfo
->grabbed
&& last_mouse_frame
9281 && FRAME_LIVE_P (last_mouse_frame
))
9282 f
= last_mouse_frame
;
9284 f
= dpyinfo
->x_focus_frame
;
9286 if (dpyinfo
->mouse_face_hidden
)
9288 dpyinfo
->mouse_face_hidden
= 0;
9289 clear_mouse_face (dpyinfo
);
9294 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9295 Point mouse_pos
= er
.where
;
9297 SetPortWindowPort (wp
);
9299 GlobalToLocal (&mouse_pos
);
9301 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9302 #ifdef USE_TOOLKIT_SCROLL_BARS
9303 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9304 mouse_pos
, er
.when
* (1000 / 60),
9306 #else /* not USE_TOOLKIT_SCROLL_BARS */
9307 x_scroll_bar_note_movement (tracked_scroll_bar
,
9309 - XINT (tracked_scroll_bar
->top
),
9310 er
.when
* (1000 / 60));
9311 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9314 /* Generate SELECT_WINDOW_EVENTs when needed. */
9315 if (mouse_autoselect_window
)
9319 window
= window_from_coordinates (f
,
9324 /* Window will be selected only when it is
9325 not selected now and last mouse movement
9326 event was not in it. Minibuffer window
9327 will be selected iff it is active. */
9328 if (WINDOWP (window
)
9329 && !EQ (window
, last_window
)
9330 && !EQ (window
, selected_window
))
9332 inev
.kind
= SELECT_WINDOW_EVENT
;
9333 inev
.frame_or_window
= window
;
9338 note_mouse_movement (f
, &mouse_pos
);
9342 /* If the contents of the global variable
9343 help_echo_string has changed, generate a
9345 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
9353 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
9355 #if USE_CARBON_EVENTS
9356 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9357 != eventNotHandledErr
)
9360 if (window_ptr
== tip_window
)
9362 HideWindow (tip_window
);
9366 if (!is_emacs_window (window_ptr
))
9369 if ((er
.modifiers
& activeFlag
) != 0)
9371 /* A window has been activated */
9372 Point mouse_loc
= er
.where
;
9374 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9376 SetPortWindowPort (window_ptr
);
9377 GlobalToLocal (&mouse_loc
);
9378 /* Window-activated event counts as mouse movement,
9379 so update things that depend on mouse position. */
9380 note_mouse_movement (mac_window_to_frame (window_ptr
),
9385 /* A window has been deactivated */
9386 #if USE_TOOLKIT_SCROLL_BARS
9387 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9389 struct input_event event
;
9392 event
.kind
= NO_EVENT
;
9393 x_scroll_bar_handle_release (tracked_scroll_bar
,
9394 er
.when
* (1000 / 60),
9396 if (event
.kind
!= NO_EVENT
)
9398 kbd_buffer_store_event_hold (&event
, hold_quit
);
9403 dpyinfo
->grabbed
= 0;
9405 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9407 f
= mac_window_to_frame (window_ptr
);
9408 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9410 /* If we move outside the frame, then we're
9411 certainly no longer on any text in the
9413 clear_mouse_face (dpyinfo
);
9414 dpyinfo
->mouse_face_mouse_frame
= 0;
9417 /* Generate a nil HELP_EVENT to cancel a help-echo.
9418 Do it only if there's something to cancel.
9419 Otherwise, the startup message is cleared when the
9420 mouse leaves the frame. */
9421 if (any_help_event_p
)
9430 int keycode
= (er
.message
& keyCodeMask
) >> 8;
9433 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9434 /* When using Carbon Events, we need to pass raw keyboard
9435 events to the TSM ourselves. If TSM handles it, it
9436 will pass back noErr, otherwise it will pass back
9437 "eventNotHandledErr" and we can process it
9439 if ((!NILP (Vmac_pass_command_to_system
)
9440 || !(er
.modifiers
& cmdKey
))
9441 && (!NILP (Vmac_pass_control_to_system
)
9442 || !(er
.modifiers
& controlKey
))
9443 && (!NILP (Vmac_command_key_is_meta
)
9444 && NILP (Vmac_option_modifier
)
9445 || !(er
.modifiers
& optionKey
)))
9446 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9447 != eventNotHandledErr
)
9452 if (dpyinfo
->x_focus_frame
== NULL
)
9454 /* Beep if keyboard input occurs when all the frames
9462 static SInt16 last_key_script
= -1;
9463 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
9465 if (last_key_script
!= current_key_script
)
9467 struct input_event event
;
9470 event
.kind
= LANGUAGE_CHANGE_EVENT
;
9472 event
.code
= current_key_script
;
9473 kbd_buffer_store_event (&event
);
9476 last_key_script
= current_key_script
;
9481 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
9483 clear_mouse_face (dpyinfo
);
9484 dpyinfo
->mouse_face_hidden
= 1;
9487 if (keycode_to_xkeysym (keycode
, &xkeysym
))
9489 inev
.code
= 0xff00 | xkeysym
;
9490 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
9494 if (er
.modifiers
& (controlKey
|
9495 (NILP (Vmac_command_key_is_meta
) ? optionKey
9498 /* This code comes from Keyboard Resource,
9499 Appendix C of IM - Text. This is necessary
9500 since shift is ignored in KCHR table
9501 translation when option or command is pressed.
9502 It also does not translate correctly
9503 control-shift chars like C-% so mask off shift
9505 int new_modifiers
= er
.modifiers
& 0xe600;
9506 /* mask off option and command */
9507 int new_keycode
= keycode
| new_modifiers
;
9508 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9509 unsigned long some_state
= 0;
9510 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9511 &some_state
) & 0xff;
9513 else if (!NILP (Vmac_option_modifier
)
9514 && (er
.modifiers
& optionKey
))
9516 /* When using the option key as an emacs modifier,
9517 convert the pressed key code back to one
9518 without the Mac option modifier applied. */
9519 int new_modifiers
= er
.modifiers
& ~optionKey
;
9520 int new_keycode
= keycode
| new_modifiers
;
9521 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9522 unsigned long some_state
= 0;
9523 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9524 &some_state
) & 0xff;
9527 inev
.code
= er
.message
& charCodeMask
;
9528 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9532 #if USE_CARBON_EVENTS
9533 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9535 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9537 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
9538 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9541 case kHighLevelEvent
:
9542 drag_and_drop_file_list
= Qnil
;
9544 AEProcessAppleEvent(&er
);
9546 /* Build a DRAG_N_DROP_EVENT type event as is done in
9547 constuct_drag_n_drop in w32term.c. */
9548 if (!NILP (drag_and_drop_file_list
))
9550 struct frame
*f
= mac_focus_frame (dpyinfo
);
9554 inev
.kind
= DRAG_N_DROP_EVENT
;
9556 inev
.timestamp
= er
.when
* (1000 / 60);
9557 /* ticks to milliseconds */
9558 #if USE_CARBON_EVENTS
9559 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9561 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9564 XSETINT (inev
.x
, 0);
9565 XSETINT (inev
.y
, 0);
9567 XSETFRAME (frame
, f
);
9568 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9571 /* Regardless of whether Emacs was suspended or in the
9572 foreground, ask it to redraw its entire screen.
9573 Otherwise parts of the screen can be left in an
9574 inconsistent state. */
9575 wp
= FRAME_MAC_WINDOW (f
);
9577 #if TARGET_API_MAC_CARBON
9581 GetWindowPortBounds (wp
, &r
);
9582 InvalWindowRect (wp
, &r
);
9584 #else /* not TARGET_API_MAC_CARBON */
9585 InvalRect (&(wp
->portRect
));
9586 #endif /* not TARGET_API_MAC_CARBON */
9592 #if USE_CARBON_EVENTS
9593 ReleaseEvent (eventRef
);
9596 if (inev
.kind
!= NO_EVENT
)
9598 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9603 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9608 XSETFRAME (frame
, f
);
9614 any_help_event_p
= 1;
9615 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9616 help_echo_object
, help_echo_pos
);
9620 help_echo_string
= Qnil
;
9621 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9628 /* If the focus was just given to an autoraising frame,
9630 /* ??? This ought to be able to handle more than one such frame. */
9631 if (pending_autoraise_frame
)
9633 x_raise_frame (pending_autoraise_frame
);
9634 pending_autoraise_frame
= 0;
9642 /* Need to override CodeWarrior's input function so no conversion is
9643 done on newlines Otherwise compiled functions in .elc files will be
9644 read incorrectly. Defined in ...:MSL C:MSL
9645 Common:Source:buffer_io.c. */
9648 __convert_to_newlines (unsigned char * p
, size_t * n
)
9654 __convert_from_newlines (unsigned char * p
, size_t * n
)
9662 make_mac_terminal_frame (struct frame
*f
)
9667 XSETFRAME (frame
, f
);
9669 f
->output_method
= output_mac
;
9670 f
->output_data
.mac
= (struct mac_output
*)
9671 xmalloc (sizeof (struct mac_output
));
9672 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9674 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9676 FRAME_COLS (f
) = 96;
9677 FRAME_LINES (f
) = 4;
9679 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9680 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9682 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9684 f
->output_data
.mac
->cursor_pixel
= 0;
9685 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9686 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9687 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9689 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9690 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9691 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9692 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9693 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9694 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9696 FRAME_FONTSET (f
) = -1;
9697 f
->output_data
.mac
->explicit_parent
= 0;
9700 f
->border_width
= 0;
9702 f
->internal_border_width
= 0;
9707 f
->new_text_cols
= 0;
9708 f
->new_text_lines
= 0;
9710 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9711 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9712 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9716 if (!(FRAME_MAC_WINDOW (f
) =
9717 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9718 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9720 /* so that update events can find this mac_output struct */
9721 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9727 /* Need to be initialized for unshow_buffer in window.c. */
9728 selected_window
= f
->selected_window
;
9730 Fmodify_frame_parameters (frame
,
9731 Fcons (Fcons (Qfont
,
9732 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9733 Fmodify_frame_parameters (frame
,
9734 Fcons (Fcons (Qforeground_color
,
9735 build_string ("black")), Qnil
));
9736 Fmodify_frame_parameters (frame
,
9737 Fcons (Fcons (Qbackground_color
,
9738 build_string ("white")), Qnil
));
9743 /***********************************************************************
9745 ***********************************************************************/
9747 int mac_initialized
= 0;
9750 mac_initialize_display_info ()
9752 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9753 GDHandle main_device_handle
;
9755 bzero (dpyinfo
, sizeof (*dpyinfo
));
9758 dpyinfo
->mac_id_name
9759 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9760 + SCHARS (Vsystem_name
)
9762 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9763 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9765 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9766 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9769 main_device_handle
= LMGetMainDevice();
9771 dpyinfo
->reference_count
= 0;
9772 dpyinfo
->resx
= 75.0;
9773 dpyinfo
->resy
= 75.0;
9774 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9776 /* HasDepth returns true if it is possible to have a 32 bit display,
9777 but this may not be what is actually used. Mac OSX can do better.
9778 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9779 header for CGGetActiveDisplayList says that the first display returned
9780 is the active one, so we use that. */
9782 CGDirectDisplayID disp_id
[1];
9783 CGDisplayCount disp_count
;
9784 CGDisplayErr error_code
;
9786 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
9787 if (error_code
!= 0)
9788 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
9790 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
9793 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
9794 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
9795 gdDevType
, dpyinfo
->color_p
))
9798 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
9799 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
9800 dpyinfo
->grabbed
= 0;
9801 dpyinfo
->root_window
= NULL
;
9802 dpyinfo
->image_cache
= make_image_cache ();
9804 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9805 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9806 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9807 dpyinfo
->mouse_face_window
= Qnil
;
9808 dpyinfo
->mouse_face_overlay
= Qnil
;
9809 dpyinfo
->mouse_face_hidden
= 0;
9814 mac_make_rdb (xrm_option
)
9817 XrmDatabase database
;
9819 database
= xrm_get_preference_database (NULL
);
9821 xrm_merge_string_database (database
, xrm_option
);
9826 struct mac_display_info
*
9827 mac_term_init (display_name
, xrm_option
, resource_name
)
9828 Lisp_Object display_name
;
9830 char *resource_name
;
9832 struct mac_display_info
*dpyinfo
;
9836 if (!mac_initialized
)
9839 mac_initialized
= 1;
9843 error ("Sorry, this version can only handle one display");
9845 mac_initialize_display_info ();
9847 dpyinfo
= &one_mac_display_info
;
9849 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
9851 /* Put this display on the chain. */
9852 dpyinfo
->next
= x_display_list
;
9853 x_display_list
= dpyinfo
;
9855 /* Put it on x_display_name_list. */
9856 x_display_name_list
= Fcons (Fcons (display_name
,
9857 Fcons (Qnil
, dpyinfo
->xrdb
)),
9858 x_display_name_list
);
9859 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9865 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9868 x_delete_display (dpyinfo
)
9869 struct mac_display_info
*dpyinfo
;
9873 /* Discard this display from x_display_name_list and x_display_list.
9874 We can't use Fdelq because that can quit. */
9875 if (! NILP (x_display_name_list
)
9876 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9877 x_display_name_list
= XCDR (x_display_name_list
);
9882 tail
= x_display_name_list
;
9883 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9885 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9887 XSETCDR (tail
, XCDR (XCDR (tail
)));
9894 if (x_display_list
== dpyinfo
)
9895 x_display_list
= dpyinfo
->next
;
9898 struct x_display_info
*tail
;
9900 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9901 if (tail
->next
== dpyinfo
)
9902 tail
->next
= tail
->next
->next
;
9905 /* Free the font names in the font table. */
9906 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9907 if (dpyinfo
->font_table
[i
].name
)
9909 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9910 xfree (dpyinfo
->font_table
[i
].full_name
);
9911 xfree (dpyinfo
->font_table
[i
].name
);
9914 if (dpyinfo
->font_table
->font_encoder
)
9915 xfree (dpyinfo
->font_table
->font_encoder
);
9917 xfree (dpyinfo
->font_table
);
9918 xfree (dpyinfo
->mac_id_name
);
9920 if (x_display_list
== 0)
9922 mac_clear_font_name_table ();
9923 bzero (dpyinfo
, sizeof (*dpyinfo
));
9932 extern int inhibit_window_system
;
9933 extern int noninteractive
;
9934 CFBundleRef appsBundle
;
9937 /* No need to test if already -nw*/
9938 if (inhibit_window_system
|| noninteractive
)
9941 appsBundle
= CFBundleGetMainBundle();
9942 if (appsBundle
!= NULL
)
9944 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
9945 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
9946 /* We found the bundle identifier, now we know we are valid. */
9953 /* MAC_TODO: Have this start the bundled executable */
9955 /* For now, prevent the fatal error by bringing it up in the terminal */
9956 inhibit_window_system
= 1;
9960 MakeMeTheFrontProcess ()
9962 ProcessSerialNumber psn
;
9965 err
= GetCurrentProcess (&psn
);
9967 (void) SetFrontProcess (&psn
);
9970 /***** Code to handle C-g testing *****/
9972 /* Contains the Mac modifier formed from quit_char */
9973 int mac_quit_char_modifiers
= 0;
9974 int mac_quit_char_keycode
;
9975 extern int quit_char
;
9978 mac_determine_quit_char_modifiers()
9980 /* Todo: Determine modifiers from quit_char. */
9981 UInt32 qc_modifiers
= ctrl_modifier
;
9984 mac_quit_char_modifiers
= 0;
9985 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
9986 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
9987 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
9988 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
9992 init_quit_char_handler ()
9994 /* TODO: Let this support keys other the 'g' */
9995 mac_quit_char_keycode
= 5;
9996 /* Look at <architecture/adb_kb_map.h> for details */
9997 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9999 mac_determine_quit_char_modifiers();
10003 quit_char_comp (EventRef inEvent
, void *inCompData
)
10005 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
10007 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
10011 UInt32 keyModifiers
;
10012 GetEventParameter(inEvent
, kEventParamKeyCode
,
10013 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
10014 if (keyCode
!= mac_quit_char_keycode
)
10016 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
10017 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
10018 if (keyModifiers
!= mac_quit_char_modifiers
)
10025 mac_check_for_quit_char ()
10028 static EMACS_TIME last_check_time
= { 0, 0 };
10029 static EMACS_TIME one_second
= { 1, 0 };
10032 /* If windows are not initialized, return immediately (keep it bouncin'). */
10033 if (!mac_quit_char_modifiers
)
10036 /* Don't check if last check is less than a second ago. */
10037 EMACS_GET_TIME (now
);
10038 EMACS_SUB_TIME (t
, now
, last_check_time
);
10039 if (EMACS_TIME_LT (t
, one_second
))
10041 last_check_time
= now
;
10043 /* Redetermine modifiers because they are based on lisp variables */
10044 mac_determine_quit_char_modifiers ();
10046 /* Fill the queue with events */
10048 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
10049 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
10054 struct input_event e
;
10056 /* Use an input_event to emulate what the interrupt handler does. */
10058 e
.kind
= ASCII_KEYSTROKE_EVENT
;
10059 e
.code
= quit_char
;
10061 e
.modifiers
= NULL
;
10062 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
10063 XSETFRAME (e
.frame_or_window
, mac_focus_frame (&one_mac_display_info
));
10064 /* Remove event from queue to prevent looping. */
10065 RemoveEventFromQueue (GetMainEventQueue (), event
);
10066 ReleaseEvent (event
);
10067 kbd_buffer_store_event (&e
);
10070 #endif /* MAC_OSX */
10078 MenuItemIndex menu_index
;
10080 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10081 &menu
, &menu_index
);
10083 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10084 #if USE_CARBON_EVENTS
10085 EnableMenuCommand (NULL
, kHICommandPreferences
);
10086 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10087 &menu
, &menu_index
);
10090 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10091 InsertMenuItemTextWithCFString (menu
, NULL
,
10092 0, kMenuItemAttrSeparator
, 0);
10093 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10094 0, 0, kHICommandAbout
);
10096 #endif /* USE_CARBON_EVENTS */
10097 #else /* !MAC_OSX */
10098 #if USE_CARBON_EVENTS
10099 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10105 /* Set up use of X before we make the first connection. */
10107 extern frame_parm_handler mac_frame_parm_handlers
[];
10109 static struct redisplay_interface x_redisplay_interface
=
10111 mac_frame_parm_handlers
,
10115 x_clear_end_of_line
,
10117 x_after_update_window_line
,
10118 x_update_window_begin
,
10119 x_update_window_end
,
10122 0, /* flush_display_optional */
10123 x_clear_window_mouse_face
,
10124 x_get_glyph_overhangs
,
10125 x_fix_overlapping_area
,
10126 x_draw_fringe_bitmap
,
10127 0, /* define_fringe_bitmap */
10128 0, /* destroy_fringe_bitmap */
10129 mac_per_char_metric
,
10131 mac_compute_glyph_string_overhangs
,
10132 x_draw_glyph_string
,
10133 mac_define_frame_cursor
,
10134 mac_clear_frame_area
,
10135 mac_draw_window_cursor
,
10136 mac_draw_vertical_window_border
,
10137 mac_shift_glyphs_for_insert
10143 rif
= &x_redisplay_interface
;
10145 clear_frame_hook
= x_clear_frame
;
10146 ins_del_lines_hook
= x_ins_del_lines
;
10147 delete_glyphs_hook
= x_delete_glyphs
;
10148 ring_bell_hook
= XTring_bell
;
10149 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10150 set_terminal_modes_hook
= XTset_terminal_modes
;
10151 update_begin_hook
= x_update_begin
;
10152 update_end_hook
= x_update_end
;
10153 set_terminal_window_hook
= XTset_terminal_window
;
10154 read_socket_hook
= XTread_socket
;
10155 frame_up_to_date_hook
= XTframe_up_to_date
;
10156 mouse_position_hook
= XTmouse_position
;
10157 frame_rehighlight_hook
= XTframe_rehighlight
;
10158 frame_raise_lower_hook
= XTframe_raise_lower
;
10160 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10161 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10162 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10163 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10165 scroll_region_ok
= 1; /* we'll scroll partial frames */
10166 char_ins_del_ok
= 1;
10167 line_ins_del_ok
= 1; /* we'll just blt 'em */
10168 fast_clear_end_of_line
= 1; /* X does this well */
10169 memory_below_frame
= 0; /* we don't remember what scrolls
10174 last_tool_bar_item
= -1;
10175 any_help_event_p
= 0;
10177 /* Try to use interrupt input; if we can't, then start polling. */
10178 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10182 #if TARGET_API_MAC_CARBON
10183 init_required_apple_events ();
10185 #if USE_CARBON_EVENTS
10187 init_service_handler ();
10189 init_quit_char_handler ();
10190 #endif /* MAC_OSX */
10192 init_command_handler ();
10195 #endif /* USE_CARBON_EVENTS */
10198 if (!inhibit_window_system
)
10199 MakeMeTheFrontProcess ();
10210 staticpro (&x_error_message_string
);
10211 x_error_message_string
= Qnil
;
10214 Qmodifier_value
= intern ("modifier-value");
10215 Qalt
= intern ("alt");
10216 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10217 Qhyper
= intern ("hyper");
10218 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10219 Qsuper
= intern ("super");
10220 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10222 Qapplication
= intern ("application"); staticpro (&Qapplication
);
10223 Qabout
= intern ("about"); staticpro (&Qabout
);
10225 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10226 Qpreferences
= intern ("preferences"); staticpro (&Qpreferences
);
10227 Qservices
= intern ("services"); staticpro (&Qservices
);
10228 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10229 Qperform
= intern ("perform"); staticpro (&Qperform
);
10233 Fprovide (intern ("mac-carbon"), Qnil
);
10236 staticpro (&Qreverse
);
10237 Qreverse
= intern ("reverse");
10239 staticpro (&x_display_name_list
);
10240 x_display_name_list
= Qnil
;
10242 staticpro (&last_mouse_scroll_bar
);
10243 last_mouse_scroll_bar
= Qnil
;
10245 staticpro (&Qvendor_specific_keysyms
);
10246 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
10248 staticpro (&last_mouse_press_frame
);
10249 last_mouse_press_frame
= Qnil
;
10251 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
10252 staticpro (&Qmac_ready_for_drag_n_drop
);
10254 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10255 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10256 #ifdef USE_TOOLKIT_SCROLL_BARS
10257 Vx_toolkit_scroll_bars
= Qt
;
10259 Vx_toolkit_scroll_bars
= Qnil
;
10262 DEFVAR_BOOL ("x-use-underline-position-properties",
10263 &x_use_underline_position_properties
,
10264 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10265 nil means ignore them. If you encounter fonts with bogus
10266 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10267 to 4.1, set this to nil. */);
10268 x_use_underline_position_properties
= 0;
10270 staticpro (&last_mouse_motion_frame
);
10271 last_mouse_motion_frame
= Qnil
;
10273 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
10274 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
10275 Otherwise the option key is used. */);
10276 Vmac_command_key_is_meta
= Qt
;
10278 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10279 doc
: /* Modifier to use for the Mac alt/option key. The value can
10280 be alt, hyper, or super for the respective modifier. If the value is
10281 nil then the key will act as the normal Mac option modifier. */);
10282 Vmac_option_modifier
= Qnil
;
10284 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
10285 doc
: /* Non-nil means that the control and meta keys are reversed. This is
10286 useful for non-standard keyboard layouts. */);
10287 Vmac_reverse_ctrl_meta
= Qnil
;
10289 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10290 &Vmac_emulate_three_button_mouse
,
10291 doc
: /* t means that when the option-key is held down while pressing the
10292 mouse button, the click will register as mouse-2 and while the
10293 command-key is held down, the click will register as mouse-3.
10294 'reverse means that the the option-key will register for mouse-3
10295 and the command-key will register for mouse-2. nil means that
10296 no emulation should be done and the modifiers should be placed
10297 on the mouse-1 event. */);
10298 Vmac_emulate_three_button_mouse
= Qnil
;
10300 #if USE_CARBON_EVENTS
10301 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
10302 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
10303 the right click will be mouse-3.
10304 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10305 Vmac_wheel_button_is_mouse_2
= Qt
;
10307 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
10308 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10309 Toolbox for processing before Emacs sees it. */);
10310 Vmac_pass_command_to_system
= Qt
;
10312 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
10313 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10314 Toolbox for processing before Emacs sees it. */);
10315 Vmac_pass_control_to_system
= Qt
;
10319 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
10320 doc
: /* If non-nil, allow anti-aliasing.
10321 The text will be rendered using Core Graphics text rendering which
10322 may anti-alias the text. */);
10323 Vmac_use_core_graphics
= Qnil
;
10325 /* Register an entry for `mac-roman' so that it can be used when
10326 creating the terminal frame on Mac OS 9 before loading
10327 term/mac-win.elc. */
10328 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10329 doc
: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10330 Each entry should be of the form:
10332 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10334 where CHARSET-NAME is a string used in font names to identify the
10335 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10336 is a coding system corresponding to TEXT-ENCODING. */);
10337 Vmac_charset_info_alist
=
10338 Fcons (list3 (build_string ("mac-roman"),
10339 make_number (smRoman
), Qnil
), Qnil
);
10342 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10343 (do not change this comment) */