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., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, 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"
87 #include "character.h"
91 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
92 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
93 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
94 #define macShiftKey (shiftKey)
95 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
96 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
98 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
100 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
103 /* Non-nil means Emacs uses toolkit scroll bars. */
105 Lisp_Object Vx_toolkit_scroll_bars
;
107 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
108 Lisp_Object Vmac_use_core_graphics
;
111 /* Non-zero means that a HELP_EVENT has been generated since Emacs
114 static int any_help_event_p
;
116 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
117 static Lisp_Object last_window
;
119 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
121 int x_use_underline_position_properties
;
123 /* Non-zero means draw block and hollow cursor as wide as the glyph
124 under it. For example, if a block cursor is over a tab, it will be
125 drawn as wide as that tab on the display. */
128 /* This is a chain of structures for all the X displays currently in
131 struct x_display_info
*x_display_list
;
133 /* This is a list of cons cells, each of the form (NAME
134 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
135 x_display_list and in the same order. NAME is the name of the
136 frame. FONT-LIST-CACHE records previous values returned by
137 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
138 equivalent, which is implemented with a Lisp object, for the
141 Lisp_Object x_display_name_list
;
143 /* This is display since Mac does not support multiple ones. */
144 struct mac_display_info one_mac_display_info
;
146 /* Frame being updated by update_frame. This is declared in term.c.
147 This is set by update_begin and looked at by all the XT functions.
148 It is zero while not inside an update. In that case, the XT
149 functions assume that `selected_frame' is the frame to apply to. */
151 extern struct frame
*updating_frame
;
153 extern int waiting_for_input
;
155 /* This is a frame waiting to be auto-raised, within XTread_socket. */
157 struct frame
*pending_autoraise_frame
;
161 Formerly, we used PointerMotionHintMask (in standard_event_mask)
162 so that we would have to call XQueryPointer after each MotionNotify
163 event to ask for another such event. However, this made mouse tracking
164 slow, and there was a bug that made it eventually stop.
166 Simply asking for MotionNotify all the time seems to work better.
168 In order to avoid asking for motion events and then throwing most
169 of them away or busy-polling the server for mouse positions, we ask
170 the server for pointer motion hints. This means that we get only
171 one event per group of mouse movements. "Groups" are delimited by
172 other kinds of events (focus changes and button clicks, for
173 example), or by XQueryPointer calls; when one of these happens, we
174 get another MotionNotify event the next time the mouse moves. This
175 is at least as efficient as getting motion events when mouse
176 tracking is on, and I suspect only negligibly worse when tracking
179 /* Where the mouse was last time we reported a mouse event. */
181 static Rect last_mouse_glyph
;
182 static Lisp_Object last_mouse_press_frame
;
184 /* The scroll bar in which the last X motion event occurred.
186 If the last X motion event occurred in a scroll bar, we set this so
187 XTmouse_position can know whether to report a scroll bar motion or
190 If the last X motion event didn't occur in a scroll bar, we set
191 this to Qnil, to tell XTmouse_position to return an ordinary motion
194 static Lisp_Object last_mouse_scroll_bar
;
196 /* This is a hack. We would really prefer that XTmouse_position would
197 return the time associated with the position it returns, but there
198 doesn't seem to be any way to wrest the time-stamp from the server
199 along with the position query. So, we just keep track of the time
200 of the last movement we received, and return that in hopes that
201 it's somewhat accurate. */
203 static Time last_mouse_movement_time
;
205 struct scroll_bar
*tracked_scroll_bar
= NULL
;
207 /* Incremented by XTread_socket whenever it really tries to read
211 static int volatile input_signal_count
;
213 static int input_signal_count
;
216 /* Used locally within XTread_socket. */
218 static int x_noop_count
;
220 /* Initial values of argv and argc. */
222 extern char **initial_argv
;
223 extern int initial_argc
;
225 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
227 /* Tells if a window manager is present or not. */
229 extern Lisp_Object Vx_no_window_manager
;
233 /* A mask of extra modifier bits to put into every keyboard char. */
235 extern int extra_keyboard_modifiers
;
237 /* The keysyms to use for the various modifiers. */
239 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qmodifier_value
;
241 static Lisp_Object Qvendor_specific_keysyms
;
244 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
247 extern int inhibit_window_system
;
249 #if __MRC__ && !TARGET_API_MAC_CARBON
250 QDGlobals qd
; /* QuickDraw global information structure. */
254 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
255 struct mac_display_info
*mac_display_info_for_display (Display
*);
256 static void x_update_window_end
P_ ((struct window
*, int, int));
257 static int x_io_error_quitter
P_ ((Display
*));
258 int x_catch_errors
P_ ((Display
*));
259 void x_uncatch_errors
P_ ((Display
*, int));
260 void x_lower_frame
P_ ((struct frame
*));
261 void x_scroll_bar_clear
P_ ((struct frame
*));
262 int x_had_errors_p
P_ ((Display
*));
263 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
264 void x_raise_frame
P_ ((struct frame
*));
265 void x_set_window_size
P_ ((struct frame
*, int, int, int));
266 void x_wm_set_window_state
P_ ((struct frame
*, int));
267 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
268 void mac_initialize
P_ ((void));
269 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
270 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
271 static void x_update_end
P_ ((struct frame
*));
272 static void XTframe_up_to_date
P_ ((struct frame
*));
273 static void XTset_terminal_modes
P_ ((void));
274 static void XTreset_terminal_modes
P_ ((void));
275 static void x_clear_frame
P_ ((void));
276 static void frame_highlight
P_ ((struct frame
*));
277 static void frame_unhighlight
P_ ((struct frame
*));
278 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
279 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
280 struct frame
*, struct input_event
*));
281 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
282 EventRecord
*, struct input_event
*));
283 static void XTframe_rehighlight
P_ ((struct frame
*));
284 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
285 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
286 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
287 enum text_cursor_kinds
));
289 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
290 static void x_flush
P_ ((struct frame
*f
));
291 static void x_update_begin
P_ ((struct frame
*));
292 static void x_update_window_begin
P_ ((struct window
*));
293 static void x_after_update_window_line
P_ ((struct glyph_row
*));
295 static int is_emacs_window (WindowPtr
);
297 int x_bitmap_icon (struct frame
*, Lisp_Object
);
298 void x_make_frame_visible (struct frame
*);
300 extern void window_scroll (Lisp_Object
, int, int, int);
302 /* Defined in macmenu.h. */
303 extern void menubar_selection_callback (FRAME_PTR
, int);
304 extern void set_frame_menubar (FRAME_PTR
, int, int);
306 /* X display function emulation */
309 XFreePixmap (display
, pixmap
)
310 Display
*display
; /* not used */
313 DisposeGWorld (pixmap
);
317 /* Set foreground color for subsequent QuickDraw commands. Assume
318 graphic port has already been set. */
321 mac_set_forecolor (unsigned long color
)
325 fg_color
.red
= RED16_FROM_ULONG (color
);
326 fg_color
.green
= GREEN16_FROM_ULONG (color
);
327 fg_color
.blue
= BLUE16_FROM_ULONG (color
);
329 RGBForeColor (&fg_color
);
333 /* Set background color for subsequent QuickDraw commands. Assume
334 graphic port has already been set. */
337 mac_set_backcolor (unsigned long color
)
341 bg_color
.red
= RED16_FROM_ULONG (color
);
342 bg_color
.green
= GREEN16_FROM_ULONG (color
);
343 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
345 RGBBackColor (&bg_color
);
348 /* Set foreground and background color for subsequent QuickDraw
349 commands. Assume that the graphic port has already been set. */
352 mac_set_colors (gc
, bg_save
)
357 GetBackColor (bg_save
);
358 mac_set_forecolor (gc
->foreground
);
359 mac_set_backcolor (gc
->background
);
362 /* Mac version of XDrawLine. */
365 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
373 SetPortWindowPort (w
);
375 mac_set_colors (gc
, &old_bg
);
380 RGBBackColor (&old_bg
);
384 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
393 GetGWorld (&old_port
, &old_gdh
);
396 mac_set_colors (gc
, NULL
);
398 LockPixels (GetGWorldPixMap (p
));
401 UnlockPixels (GetGWorldPixMap (p
));
403 SetGWorld (old_port
, old_gdh
);
406 /* Mac version of XClearArea. */
409 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
413 unsigned int width
, height
;
416 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
421 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
422 xgc
.background
= mwp
->x_compatible
.background_pixel
;
424 SetPortWindowPort (w
);
426 mac_set_colors (&xgc
, &old_bg
);
427 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
431 RGBBackColor (&old_bg
);
434 /* Mac version of XClearWindow. */
437 XClearWindow (display
, w
)
441 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
444 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
445 xgc
.background
= mwp
->x_compatible
.background_pixel
;
447 SetPortWindowPort (w
);
449 mac_set_colors (&xgc
, NULL
);
451 #if TARGET_API_MAC_CARBON
455 GetWindowPortBounds (w
, &r
);
458 #else /* not TARGET_API_MAC_CARBON */
459 EraseRect (&(w
->portRect
));
460 #endif /* not TARGET_API_MAC_CARBON */
464 /* Mac replacement for XCopyArea. */
467 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
471 int x
, y
, width
, height
;
472 unsigned short *bits
;
479 bitmap
.rowBytes
= sizeof(unsigned short);
480 bitmap
.baseAddr
= (char *)bits
;
481 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
483 SetPortWindowPort (w
);
485 mac_set_colors (gc
, &old_bg
);
486 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
488 #if TARGET_API_MAC_CARBON
489 LockPortBits (GetWindowPort (w
));
490 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
491 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
492 UnlockPortBits (GetWindowPort (w
));
493 #else /* not TARGET_API_MAC_CARBON */
494 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
495 overlay_p
? srcOr
: srcCopy
, 0);
496 #endif /* not TARGET_API_MAC_CARBON */
498 RGBBackColor (&old_bg
);
502 /* Mac replacement for XSetClipRectangles. */
505 mac_set_clip_rectangle (display
, w
, r
)
510 SetPortWindowPort (w
);
516 /* Mac replacement for XSetClipMask. */
519 mac_reset_clipping (display
, w
)
525 SetPortWindowPort (w
);
527 SetRect (&r
, -32767, -32767, 32767, 32767);
532 /* Mac replacement for XCreateBitmapFromBitmapData. */
535 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
540 static unsigned char swap_nibble
[16]
541 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
542 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
543 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
544 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
548 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
549 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
550 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
551 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
552 for (i
= 0; i
< h
; i
++)
554 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
555 for (j
= 0; j
< w1
; j
++)
557 /* Bitswap XBM bytes to match how Mac does things. */
558 unsigned char c
= *bits
++;
559 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
560 | (swap_nibble
[(c
>>4) & 0xf]));;
564 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
569 mac_free_bitmap (bitmap
)
572 xfree (bitmap
->baseAddr
);
577 XCreatePixmap (display
, w
, width
, height
, depth
)
578 Display
*display
; /* not used */
580 unsigned int width
, height
;
587 SetPortWindowPort (w
);
589 SetRect (&r
, 0, 0, width
, height
);
590 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
598 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
599 Display
*display
; /* not used */
602 unsigned int width
, height
;
603 unsigned long fg
, bg
;
604 unsigned int depth
; /* not used */
611 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
615 GetGWorld (&old_port
, &old_gdh
);
616 SetGWorld (pixmap
, NULL
);
617 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
618 mac_set_forecolor (fg
);
619 mac_set_backcolor (bg
);
620 LockPixels (GetGWorldPixMap (pixmap
));
621 #if TARGET_API_MAC_CARBON
622 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
623 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
624 #else /* not TARGET_API_MAC_CARBON */
625 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
626 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
627 #endif /* not TARGET_API_MAC_CARBON */
628 UnlockPixels (GetGWorldPixMap (pixmap
));
629 SetGWorld (old_port
, old_gdh
);
630 mac_free_bitmap (&bitmap
);
636 /* Mac replacement for XFillRectangle. */
639 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
644 unsigned int width
, height
;
649 SetPortWindowPort (w
);
651 mac_set_colors (gc
, &old_bg
);
652 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
654 PaintRect (&r
); /* using foreground color of gc */
656 RGBBackColor (&old_bg
);
660 #if 0 /* TODO: figure out if we need to do this on Mac. */
662 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
667 unsigned int width
, height
;
673 GetGWorld (&old_port
, &old_gdh
);
675 mac_set_colors (gc
, NULL
);
676 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
678 LockPixels (GetGWorldPixMap (p
));
679 PaintRect (&r
); /* using foreground color of gc */
680 UnlockPixels (GetGWorldPixMap (p
));
682 SetGWorld (old_port
, old_gdh
);
687 /* Mac replacement for XDrawRectangle: dest is a window. */
690 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
695 unsigned int width
, height
;
700 SetPortWindowPort (w
);
702 mac_set_colors (gc
, &old_bg
);
703 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
705 FrameRect (&r
); /* using foreground color of gc */
707 RGBBackColor (&old_bg
);
711 #if 0 /* TODO: figure out if we need to do this on Mac. */
712 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
715 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
720 unsigned int width
, height
;
726 GetGWorld (&old_port
, &old_gdh
);
728 mac_set_colors (gc
, NULL
);
729 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
731 LockPixels (GetGWorldPixMap (p
));
732 FrameRect (&r
); /* using foreground color of gc */
733 UnlockPixels (GetGWorldPixMap (p
));
735 SetGWorld (old_port
, old_gdh
);
741 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
748 int nchars
, mode
, bytes_per_char
;
752 SetPortWindowPort (w
);
753 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
754 UInt32 textFlags
, savedFlags
;
755 if (!NILP(Vmac_use_core_graphics
)) {
756 textFlags
= kQDUseCGTextRendering
;
757 savedFlags
= SwapQDTextFlags(textFlags
);
761 mac_set_colors (gc
, &old_bg
);
763 TextFont (gc
->font
->mac_fontnum
);
764 TextSize (gc
->font
->mac_fontsize
);
765 TextFace (gc
->font
->mac_fontface
);
769 DrawText (buf
, 0, nchars
* bytes_per_char
);
771 RGBBackColor (&old_bg
);
772 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
773 if (!NILP(Vmac_use_core_graphics
))
774 SwapQDTextFlags(savedFlags
);
779 /* Mac replacement for XDrawString. */
782 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
790 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
794 /* Mac replacement for XDrawString16. */
797 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
805 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
810 /* Mac replacement for XDrawImageString. */
813 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
821 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
825 /* Mac replacement for XDrawString16. */
828 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
836 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
841 /* Mac replacement for XCopyArea: dest must be window. */
844 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
851 unsigned int width
, height
;
856 SetPortWindowPort (dest
);
858 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
859 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
861 ForeColor (blackColor
);
862 BackColor (whiteColor
);
864 LockPixels (GetGWorldPixMap (src
));
865 #if TARGET_API_MAC_CARBON
866 LockPortBits (GetWindowPort (dest
));
867 CopyBits (GetPortBitMapForCopyBits (src
),
868 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
869 &src_r
, &dest_r
, srcCopy
, 0);
870 UnlockPortBits (GetWindowPort (dest
));
871 #else /* not TARGET_API_MAC_CARBON */
872 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
873 &src_r
, &dest_r
, srcCopy
, 0);
874 #endif /* not TARGET_API_MAC_CARBON */
875 UnlockPixels (GetGWorldPixMap (src
));
880 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
881 width
, height
, dest_x
, dest_y
)
887 unsigned int width
, height
;
892 SetPortWindowPort (dest
);
894 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
895 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
897 ForeColor (blackColor
);
898 BackColor (whiteColor
);
900 LockPixels (GetGWorldPixMap (src
));
901 LockPixels (GetGWorldPixMap (mask
));
902 #if TARGET_API_MAC_CARBON
903 LockPortBits (GetWindowPort (dest
));
904 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
905 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
906 &src_r
, &src_r
, &dest_r
);
907 UnlockPortBits (GetWindowPort (dest
));
908 #else /* not TARGET_API_MAC_CARBON */
909 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
910 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
911 #endif /* not TARGET_API_MAC_CARBON */
912 UnlockPixels (GetGWorldPixMap (mask
));
913 UnlockPixels (GetGWorldPixMap (src
));
918 /* Convert a pair of local coordinates to global (screen) coordinates.
919 Assume graphic port has been properly set. */
921 local_to_global_coord (short *h
, short *v
)
935 /* Mac replacement for XCopyArea: used only for scrolling. */
938 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
943 unsigned int width
, height
;
946 #if TARGET_API_MAC_CARBON
948 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
950 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
951 ScrollWindowRect (w
, &src_r
, dest_x
- src_x
, dest_y
- src_y
,
952 kScrollWindowNoOptions
, dummy
);
954 #else /* not TARGET_API_MAC_CARBON */
959 mac_set_colors (gc
, NULL
);
962 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
963 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
966 /* Need to use global coordinates and screenBits since src and dest
967 areas overlap in general. */
968 local_to_global_coord (&src_r
.left
, &src_r
.top
);
969 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
970 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
971 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
973 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
975 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
976 color mapping in CopyBits. Otherwise, it will be slow. */
977 ForeColor (blackColor
);
978 BackColor (whiteColor
);
979 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
981 mac_set_colors (gc
, NULL
);
983 #endif /* not TARGET_API_MAC_CARBON */
987 #if 0 /* TODO: figure out if we need to do this on Mac. */
988 /* Mac replacement for XCopyArea: dest must be Pixmap. */
991 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
997 unsigned int width
, height
;
1004 GetGWorld (&old_port
, &old_gdh
);
1005 SetGWorld (dest
, NULL
);
1006 ForeColor (blackColor
);
1007 BackColor (whiteColor
);
1009 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1010 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1012 LockPixels (GetGWorldPixMap (src
));
1013 LockPixels (GetGWorldPixMap (dest
));
1014 #if TARGET_API_MAC_CARBON
1015 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
1016 &src_r
, &dest_r
, srcCopy
, 0);
1017 #else /* not TARGET_API_MAC_CARBON */
1018 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
1019 &src_r
, &dest_r
, srcCopy
, 0);
1020 #endif /* not TARGET_API_MAC_CARBON */
1021 UnlockPixels (GetGWorldPixMap (dest
));
1022 UnlockPixels (GetGWorldPixMap (src
));
1024 SetGWorld (old_port
, old_gdh
);
1029 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
1030 width
, height
, dest_x
, dest_y
)
1032 Pixmap src
, mask
, dest
;
1035 unsigned int width
, height
;
1042 GetGWorld (&old_port
, &old_gdh
);
1043 SetGWorld (dest
, NULL
);
1044 ForeColor (blackColor
);
1045 BackColor (whiteColor
);
1047 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1048 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1050 LockPixels (GetGWorldPixMap (src
));
1051 LockPixels (GetGWorldPixMap (mask
));
1052 LockPixels (GetGWorldPixMap (dest
));
1053 #if TARGET_API_MAC_CARBON
1054 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1055 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
1056 #else /* not TARGET_API_MAC_CARBON */
1057 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1058 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
1059 #endif /* not TARGET_API_MAC_CARBON */
1060 UnlockPixels (GetGWorldPixMap (dest
));
1061 UnlockPixels (GetGWorldPixMap (mask
));
1062 UnlockPixels (GetGWorldPixMap (src
));
1064 SetGWorld (old_port
, old_gdh
);
1069 /* Mac replacement for XChangeGC. */
1072 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1075 if (mask
& GCForeground
)
1076 gc
->foreground
= xgcv
->foreground
;
1077 if (mask
& GCBackground
)
1078 gc
->background
= xgcv
->background
;
1080 gc
->font
= xgcv
->font
;
1084 /* Mac replacement for XCreateGC. */
1087 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1090 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1091 bzero (gc
, sizeof (XGCValues
));
1093 XChangeGC (ignore
, gc
, mask
, xgcv
);
1099 /* Used in xfaces.c. */
1102 XFreeGC (display
, gc
)
1110 /* Mac replacement for XGetGCValues. */
1113 XGetGCValues (void* ignore
, XGCValues
*gc
,
1114 unsigned long mask
, XGCValues
*xgcv
)
1116 XChangeGC (ignore
, xgcv
, mask
, gc
);
1120 /* Mac replacement for XSetForeground. */
1123 XSetForeground (display
, gc
, color
)
1126 unsigned long color
;
1128 gc
->foreground
= color
;
1132 /* Mac replacement for XSetBackground. */
1135 XSetBackground (display
, gc
, color
)
1138 unsigned long color
;
1140 gc
->background
= color
;
1144 /* Mac replacement for XSetWindowBackground. */
1147 XSetWindowBackground (display
, w
, color
)
1150 unsigned long color
;
1152 #if !TARGET_API_MAC_CARBON
1153 AuxWinHandle aw_handle
;
1154 CTabHandle ctab_handle
;
1155 ColorSpecPtr ct_table
;
1160 bg_color
.red
= RED16_FROM_ULONG (color
);
1161 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1162 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1164 #if TARGET_API_MAC_CARBON
1165 SetWindowContentColor (w
, &bg_color
);
1167 if (GetAuxWin (w
, &aw_handle
))
1169 ctab_handle
= (*aw_handle
)->awCTable
;
1170 HandToHand ((Handle
*) &ctab_handle
);
1171 ct_table
= (*ctab_handle
)->ctTable
;
1172 ct_size
= (*ctab_handle
)->ctSize
;
1173 while (ct_size
> -1)
1175 if (ct_table
->value
== 0)
1177 ct_table
->rgb
= bg_color
;
1178 CTabChanged (ctab_handle
);
1179 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1188 /* Mac replacement for XSetFont. */
1191 XSetFont (display
, gc
, font
)
1200 /* x_sync is a no-op on Mac. */
1208 /* Flush display of frame F, or of all frames if F is null. */
1214 #if TARGET_API_MAC_CARBON
1217 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1219 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1225 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1226 Calls to XFlush should be unnecessary because the X output buffer
1227 is flushed automatically as needed by calls to XPending,
1228 XNextEvent, or XWindowEvent according to the XFlush man page.
1229 XTread_socket calls XPending. Removing XFlush improves
1232 #define XFlush(DISPLAY) (void) 0
1235 /* Return the struct mac_display_info corresponding to DPY. There's
1238 struct mac_display_info
*
1239 mac_display_info_for_display (dpy
)
1242 return &one_mac_display_info
;
1247 /***********************************************************************
1248 Starting and ending an update
1249 ***********************************************************************/
1251 /* Start an update of frame F. This function is installed as a hook
1252 for update_begin, i.e. it is called when update_begin is called.
1253 This function is called prior to calls to x_update_window_begin for
1254 each window being updated. */
1260 #if TARGET_API_MAC_CARBON
1261 /* During update of a frame, availability of input events is
1262 periodically checked with ReceiveNextEvent if
1263 redisplay-dont-pause is nil. That normally flushes window buffer
1264 changes for every check, and thus screen update looks waving even
1265 if no input is available. So we disable screen updates during
1266 update of a frame. */
1268 DisableScreenUpdates ();
1274 /* Start update of window W. Set the global variable updated_window
1275 to the window being updated and set output_cursor to the cursor
1279 x_update_window_begin (w
)
1282 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1283 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1286 set_output_cursor (&w
->cursor
);
1290 if (f
== display_info
->mouse_face_mouse_frame
)
1292 /* Don't do highlighting for mouse motion during the update. */
1293 display_info
->mouse_face_defer
= 1;
1295 /* If F needs to be redrawn, simply forget about any prior mouse
1297 if (FRAME_GARBAGED_P (f
))
1298 display_info
->mouse_face_window
= Qnil
;
1300 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1301 their mouse_face_p flag set, which means that they are always
1302 unequal to rows in a desired matrix which never have that
1303 flag set. So, rows containing mouse-face glyphs are never
1304 scrolled, and we don't have to switch the mouse highlight off
1305 here to prevent it from being scrolled. */
1307 /* Can we tell that this update does not affect the window
1308 where the mouse highlight is? If so, no need to turn off.
1309 Likewise, don't do anything if the frame is garbaged;
1310 in that case, the frame's current matrix that we would use
1311 is all wrong, and we will redisplay that line anyway. */
1312 if (!NILP (display_info
->mouse_face_window
)
1313 && w
== XWINDOW (display_info
->mouse_face_window
))
1317 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1318 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1321 if (i
< w
->desired_matrix
->nrows
)
1322 clear_mouse_face (display_info
);
1331 /* Draw a vertical window border from (x,y0) to (x,y1) */
1334 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1338 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1340 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1341 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1345 /* End update of window W (which is equal to updated_window).
1347 Draw vertical borders between horizontally adjacent windows, and
1348 display W's cursor if CURSOR_ON_P is non-zero.
1350 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1351 glyphs in mouse-face were overwritten. In that case we have to
1352 make sure that the mouse-highlight is properly redrawn.
1354 W may be a menu bar pseudo-window in case we don't have X toolkit
1355 support. Such windows don't have a cursor, so don't display it
1359 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1361 int cursor_on_p
, mouse_face_overwritten_p
;
1363 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1365 if (!w
->pseudo_window_p
)
1370 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1372 output_cursor
.x
, output_cursor
.y
);
1374 if (draw_window_fringes (w
, 1))
1375 x_draw_vertical_border (w
);
1380 /* If a row with mouse-face was overwritten, arrange for
1381 XTframe_up_to_date to redisplay the mouse highlight. */
1382 if (mouse_face_overwritten_p
)
1384 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1385 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1386 dpyinfo
->mouse_face_window
= Qnil
;
1390 /* Unhide the caret. This won't actually show the cursor, unless it
1391 was visible before the corresponding call to HideCaret in
1392 x_update_window_begin. */
1393 if (w32_use_visible_system_caret
)
1394 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1397 updated_window
= NULL
;
1401 /* End update of frame F. This function is installed as a hook in
1408 /* Mouse highlight may be displayed again. */
1409 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1412 #if TARGET_API_MAC_CARBON
1413 EnableScreenUpdates ();
1415 XFlush (FRAME_MAC_DISPLAY (f
));
1420 /* This function is called from various places in xdisp.c whenever a
1421 complete update has been performed. The global variable
1422 updated_window is not available here. */
1425 XTframe_up_to_date (f
)
1428 if (FRAME_MAC_P (f
))
1430 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1432 if (dpyinfo
->mouse_face_deferred_gc
1433 || f
== dpyinfo
->mouse_face_mouse_frame
)
1436 if (dpyinfo
->mouse_face_mouse_frame
)
1437 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1438 dpyinfo
->mouse_face_mouse_x
,
1439 dpyinfo
->mouse_face_mouse_y
);
1440 dpyinfo
->mouse_face_deferred_gc
= 0;
1447 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1448 arrow bitmaps, or clear the fringes if no bitmaps are required
1449 before DESIRED_ROW is made current. The window being updated is
1450 found in updated_window. This function is called from
1451 update_window_line only if it is known that there are differences
1452 between bitmaps to be drawn between current row and DESIRED_ROW. */
1455 x_after_update_window_line (desired_row
)
1456 struct glyph_row
*desired_row
;
1458 struct window
*w
= updated_window
;
1464 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1465 desired_row
->redraw_fringe_bitmaps_p
= 1;
1467 /* When a window has disappeared, make sure that no rest of
1468 full-width rows stays visible in the internal border. Could
1469 check here if updated_window is the leftmost/rightmost window,
1470 but I guess it's not worth doing since vertically split windows
1471 are almost never used, internal border is rarely set, and the
1472 overhead is very small. */
1473 if (windows_or_buffers_changed
1474 && desired_row
->full_width_p
1475 && (f
= XFRAME (w
->frame
),
1476 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1478 && (height
= desired_row
->visible_height
,
1481 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1482 /* Internal border is drawn below the tool bar. */
1483 if (WINDOWP (f
->tool_bar_window
)
1484 && w
== XWINDOW (f
->tool_bar_window
))
1489 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1490 0, y
, width
, height
, 0);
1491 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1492 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1500 /* Draw the bitmap WHICH in one of the left or right fringes of
1501 window W. ROW is the glyph row for which to display the bitmap; it
1502 determines the vertical position at which the bitmap has to be
1506 x_draw_fringe_bitmap (w
, row
, p
)
1508 struct glyph_row
*row
;
1509 struct draw_fringe_bitmap_params
*p
;
1511 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1512 Display
*display
= FRAME_MAC_DISPLAY (f
);
1513 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1515 GC gc
= f
->output_data
.mac
->normal_gc
;
1516 struct face
*face
= p
->face
;
1519 /* Must clip because of partially visible lines. */
1520 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1523 /* Adjust position of "bottom aligned" bitmap on partially
1524 visible last row. */
1526 int oldVH
= row
->visible_height
;
1527 row
->visible_height
= p
->h
;
1528 row
->y
-= rowY
- p
->y
;
1529 x_clip_to_row (w
, row
, -1, gc
);
1531 row
->visible_height
= oldVH
;
1534 x_clip_to_row (w
, row
, -1, gc
);
1536 if (p
->bx
>= 0 && !p
->overlay_p
)
1539 gcv
.foreground
= face
->background
;
1541 #if 0 /* MAC_TODO: stipple */
1542 /* In case the same realized face is used for fringes and
1543 for something displayed in the text (e.g. face `region' on
1544 mono-displays, the fill style may have been changed to
1545 FillSolid in x_draw_glyph_string_background. */
1547 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1549 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1552 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1554 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1556 #if 0 /* MAC_TODO: stipple */
1558 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1564 unsigned short *bits
= p
->bits
+ p
->dh
;
1566 gcv
.foreground
= (p
->cursor_p
1567 ? (p
->overlay_p
? face
->background
1568 : f
->output_data
.mac
->cursor_pixel
)
1569 : face
->foreground
);
1570 gcv
.background
= face
->background
;
1572 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
,
1573 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1576 mac_reset_clipping (display
, window
);
1580 /* This is called when starting Emacs and when restarting after
1581 suspend. When starting Emacs, no window is mapped. And nothing
1582 must be done to Emacs's own window if it is suspended (though that
1586 XTset_terminal_modes ()
1590 /* This is called when exiting or suspending Emacs. Exiting will make
1591 the windows go away, and suspending requires no action. */
1594 XTreset_terminal_modes ()
1599 /***********************************************************************
1601 ***********************************************************************/
1603 /* Function prototypes of this page. */
1605 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1606 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
1607 struct charset
*, int *));
1610 /* Return a pointer to per-char metric information in FONT of a
1611 character pointed by B which is a pointer to an XChar2b. */
1613 #define PER_CHAR_METRIC(font, b) \
1615 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1616 + (((font)->min_byte1 || (font)->max_byte1) \
1617 ? (((b)->byte1 - (font)->min_byte1) \
1618 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1620 : &((font)->max_bounds))
1623 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1624 is not contained in the font. */
1626 static INLINE XCharStruct
*
1627 x_per_char_metric (font
, char2b
)
1631 /* The result metric information. */
1632 XCharStruct
*pcm
= NULL
;
1634 xassert (font
&& char2b
);
1636 if (font
->per_char
!= NULL
)
1638 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1640 /* min_char_or_byte2 specifies the linear character index
1641 corresponding to the first element of the per_char array,
1642 max_char_or_byte2 is the index of the last character. A
1643 character with non-zero CHAR2B->byte1 is not in the font.
1644 A character with byte2 less than min_char_or_byte2 or
1645 greater max_char_or_byte2 is not in the font. */
1646 if (char2b
->byte1
== 0
1647 && char2b
->byte2
>= font
->min_char_or_byte2
1648 && char2b
->byte2
<= font
->max_char_or_byte2
)
1649 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1653 /* If either min_byte1 or max_byte1 are nonzero, both
1654 min_char_or_byte2 and max_char_or_byte2 are less than
1655 256, and the 2-byte character index values corresponding
1656 to the per_char array element N (counting from 0) are:
1658 byte1 = N/D + min_byte1
1659 byte2 = N\D + min_char_or_byte2
1663 D = max_char_or_byte2 - min_char_or_byte2 + 1
1664 / = integer division
1665 \ = integer modulus */
1666 if (char2b
->byte1
>= font
->min_byte1
1667 && char2b
->byte1
<= font
->max_byte1
1668 && char2b
->byte2
>= font
->min_char_or_byte2
1669 && char2b
->byte2
<= font
->max_char_or_byte2
)
1671 pcm
= (font
->per_char
1672 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1673 * (char2b
->byte1
- font
->min_byte1
))
1674 + (char2b
->byte2
- font
->min_char_or_byte2
));
1680 /* If the per_char pointer is null, all glyphs between the first
1681 and last character indexes inclusive have the same
1682 information, as given by both min_bounds and max_bounds. */
1683 if (char2b
->byte2
>= font
->min_char_or_byte2
1684 && char2b
->byte2
<= font
->max_char_or_byte2
)
1685 pcm
= &font
->max_bounds
;
1688 return ((pcm
== NULL
1689 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1696 static XCharStruct
*
1697 mac_per_char_metric (font
, char2b
, font_type
)
1702 return x_per_char_metric (font
, char2b
);
1706 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1707 the two-byte form of C. Encoding is returned in *CHAR2B. */
1710 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
1713 struct font_info
*font_info
;
1714 struct charset
*charset
;
1717 XFontStruct
*font
= font_info
->font
;
1719 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1720 This may be either a program in a special encoder language or a
1722 if (font_info
->font_encoder
)
1724 /* It's a program. */
1725 struct ccl_program
*ccl
= font_info
->font_encoder
;
1727 if (CHARSET_DIMENSION (charset
) == 1)
1729 ccl
->reg
[0] = CHARSET_ID (charset
);
1730 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
1735 ccl
->reg
[0] = CHARSET_ID (charset
);
1736 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
1737 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
1740 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1742 /* We assume that MSBs are appropriately set/reset by CCL
1744 if (font
->max_byte1
== 0) /* 1-byte font */
1745 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
1747 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
1749 else if (font_info
->encoding_type
)
1751 /* Fixed encoding scheme. See fontset.h for the meaning of the
1752 encoding numbers. */
1753 unsigned char enc
= font_info
->encoding_type
;
1755 if ((enc
== 1 || enc
== 2)
1756 && CHARSET_DIMENSION (charset
) == 2)
1757 char2b
->byte1
|= 0x80;
1759 if (enc
== 1 || enc
== 3)
1760 char2b
->byte2
|= 0x80;
1767 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1768 char2b->byte1 = sjis1;
1769 char2b->byte2 = sjis2;
1775 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1777 return FONT_TYPE_UNKNOWN
;
1782 /***********************************************************************
1784 ***********************************************************************/
1787 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1788 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1789 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1791 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1792 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1793 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1794 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1795 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1796 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1797 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1798 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1799 unsigned long *, double, int));*/
1800 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1801 double, int, unsigned long));
1802 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1803 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1804 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1805 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1806 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1807 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1809 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1810 int, int, int, int, int, int,
1812 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1813 int, int, int, Rect
*));
1816 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1820 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1825 struct glyph_string
*s
;
1827 if (s
->font
== FRAME_FONT (s
->f
)
1828 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1829 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1831 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1834 /* Cursor on non-default face: must merge. */
1838 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1839 xgcv
.foreground
= s
->face
->background
;
1841 /* If the glyph would be invisible, try a different foreground. */
1842 if (xgcv
.foreground
== xgcv
.background
)
1843 xgcv
.foreground
= s
->face
->foreground
;
1844 if (xgcv
.foreground
== xgcv
.background
)
1845 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1846 if (xgcv
.foreground
== xgcv
.background
)
1847 xgcv
.foreground
= s
->face
->foreground
;
1849 /* Make sure the cursor is distinct from text in this face. */
1850 if (xgcv
.background
== s
->face
->background
1851 && xgcv
.foreground
== s
->face
->foreground
)
1853 xgcv
.background
= s
->face
->foreground
;
1854 xgcv
.foreground
= s
->face
->background
;
1857 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1858 xgcv
.font
= s
->font
;
1859 mask
= GCForeground
| GCBackground
| GCFont
;
1861 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1862 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1865 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1866 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1868 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1873 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1876 x_set_mouse_face_gc (s
)
1877 struct glyph_string
*s
;
1882 /* What face has to be used last for the mouse face? */
1883 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1884 face
= FACE_FROM_ID (s
->f
, face_id
);
1886 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1888 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1889 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
1891 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
1892 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1893 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1895 /* If font in this face is same as S->font, use it. */
1896 if (s
->font
== s
->face
->font
)
1897 s
->gc
= s
->face
->gc
;
1900 /* Otherwise construct scratch_cursor_gc with values from FACE
1905 xgcv
.background
= s
->face
->background
;
1906 xgcv
.foreground
= s
->face
->foreground
;
1907 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1908 xgcv
.font
= s
->font
;
1909 mask
= GCForeground
| GCBackground
| GCFont
;
1911 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1912 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1915 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1916 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1918 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1921 xassert (s
->gc
!= 0);
1925 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1926 Faces to use in the mode line have already been computed when the
1927 matrix was built, so there isn't much to do, here. */
1930 x_set_mode_line_face_gc (s
)
1931 struct glyph_string
*s
;
1933 s
->gc
= s
->face
->gc
;
1937 /* Set S->gc of glyph string S for drawing that glyph string. Set
1938 S->stippled_p to a non-zero value if the face of S has a stipple
1942 x_set_glyph_string_gc (s
)
1943 struct glyph_string
*s
;
1945 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1947 if (s
->hl
== DRAW_NORMAL_TEXT
)
1949 s
->gc
= s
->face
->gc
;
1950 s
->stippled_p
= s
->face
->stipple
!= 0;
1952 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1954 x_set_mode_line_face_gc (s
);
1955 s
->stippled_p
= s
->face
->stipple
!= 0;
1957 else if (s
->hl
== DRAW_CURSOR
)
1959 x_set_cursor_gc (s
);
1962 else if (s
->hl
== DRAW_MOUSE_FACE
)
1964 x_set_mouse_face_gc (s
);
1965 s
->stippled_p
= s
->face
->stipple
!= 0;
1967 else if (s
->hl
== DRAW_IMAGE_RAISED
1968 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1970 s
->gc
= s
->face
->gc
;
1971 s
->stippled_p
= s
->face
->stipple
!= 0;
1975 s
->gc
= s
->face
->gc
;
1976 s
->stippled_p
= s
->face
->stipple
!= 0;
1979 /* GC must have been set. */
1980 xassert (s
->gc
!= 0);
1984 /* Set clipping for output of glyph string S. S may be part of a mode
1985 line or menu if we don't have X toolkit support. */
1988 x_set_glyph_string_clipping (s
)
1989 struct glyph_string
*s
;
1992 get_glyph_string_clip_rect (s
, &r
);
1993 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
1998 Compute left and right overhang of glyph string S. If S is a glyph
1999 string for a composition, assume overhangs don't exist. */
2002 mac_compute_glyph_string_overhangs (s
)
2003 struct glyph_string
*s
;
2006 && s
->first_glyph
->type
== CHAR_GLYPH
)
2009 MacFontStruct
*font
= s
->font
;
2011 TextFont (font
->mac_fontnum
);
2012 TextSize (font
->mac_fontsize
);
2013 TextFace (font
->mac_fontface
);
2016 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2020 char *buf
= xmalloc (s
->nchars
);
2023 SetRect (&r
, 0, 0, 0, 0);
2026 for (i
= 0; i
< s
->nchars
; ++i
)
2027 buf
[i
] = s
->char2b
[i
].byte2
;
2028 QDTextBounds (s
->nchars
, buf
, &r
);
2033 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2034 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2039 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2042 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2043 struct glyph_string
*s
;
2048 xgcv
.foreground
= s
->gc
->background
;
2049 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2053 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2054 on Mac OS X because:
2055 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2056 into an offscreen graphics world first. So performance gain
2057 cannot be expected.)
2058 - It lowers rendering quality.
2059 - Some fonts leave garbage on cursor movement. */
2061 /* Draw the background of glyph_string S. If S->background_filled_p
2062 is non-zero don't draw it. FORCE_P non-zero means draw the
2063 background even if it wouldn't be drawn normally. This is used
2064 when a string preceding S draws into the background of S, or S
2065 contains the first component of a composition. */
2068 x_draw_glyph_string_background (s
, force_p
)
2069 struct glyph_string
*s
;
2072 /* Nothing to do if background has already been drawn or if it
2073 shouldn't be drawn in the first place. */
2074 if (!s
->background_filled_p
)
2076 int box_line_width
= max (s
->face
->box_line_width
, 0);
2078 #if 0 /* MAC_TODO: stipple */
2081 /* Fill background with a stipple pattern. */
2082 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2083 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2084 s
->y
+ box_line_width
,
2085 s
->background_width
,
2086 s
->height
- 2 * box_line_width
);
2087 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2088 s
->background_filled_p
= 1;
2093 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2094 || s
->font_not_found_p
2095 || s
->extends_to_end_of_line_p
2099 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2100 s
->background_width
,
2101 s
->height
- 2 * box_line_width
);
2102 s
->background_filled_p
= 1;
2108 /* Draw the foreground of glyph string S. */
2111 x_draw_glyph_string_foreground (s
)
2112 struct glyph_string
*s
;
2116 /* If first glyph of S has a left box line, start drawing the text
2117 of S to the right of that box line. */
2118 if (s
->face
->box
!= FACE_NO_BOX
2119 && s
->first_glyph
->left_box_line_p
)
2120 x
= s
->x
+ abs (s
->face
->box_line_width
);
2124 /* Draw characters of S as rectangles if S's font could not be
2126 if (s
->font_not_found_p
)
2128 for (i
= 0; i
< s
->nchars
; ++i
)
2130 struct glyph
*g
= s
->first_glyph
+ i
;
2131 mac_draw_rectangle (s
->display
, s
->window
,
2132 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2134 x
+= g
->pixel_width
;
2139 char *char1b
= (char *) s
->char2b
;
2140 int boff
= s
->font_info
->baseline_offset
;
2142 if (s
->font_info
->vertical_centering
)
2143 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2145 /* If we can use 8-bit functions, condense S->char2b. */
2147 for (i
= 0; i
< s
->nchars
; ++i
)
2148 char1b
[i
] = s
->char2b
[i
].byte2
;
2151 /* Draw text with XDrawString if background has already been
2152 filled. Otherwise, use XDrawImageString. (Note that
2153 XDrawImageString is usually faster than XDrawString.) Always
2154 use XDrawImageString when drawing the cursor so that there is
2155 no chance that characters under a box cursor are invisible. */
2156 if (s
->for_overlaps_p
2157 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2160 /* Draw characters with 16-bit or 8-bit functions. */
2162 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2163 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2165 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2166 s
->ybase
- boff
, char1b
, s
->nchars
);
2172 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2173 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2175 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2176 s
->ybase
- boff
, char1b
, s
->nchars
);
2182 /* Draw the foreground of composite glyph string S. */
2185 x_draw_composite_glyph_string_foreground (s
)
2186 struct glyph_string
*s
;
2190 /* If first glyph of S has a left box line, start drawing the text
2191 of S to the right of that box line. */
2192 if (s
->face
->box
!= FACE_NO_BOX
2193 && s
->first_glyph
->left_box_line_p
)
2194 x
= s
->x
+ abs (s
->face
->box_line_width
);
2198 /* S is a glyph string for a composition. S->gidx is the index of
2199 the first character drawn for glyphs of this composition.
2200 S->gidx == 0 means we are drawing the very first character of
2201 this composition. */
2203 /* Draw a rectangle for the composition if the font for the very
2204 first character of the composition could not be loaded. */
2205 if (s
->font_not_found_p
)
2208 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2209 s
->width
- 1, s
->height
- 1);
2213 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2214 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2215 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2216 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2222 #ifdef USE_X_TOOLKIT
2224 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2227 /* Return the frame on which widget WIDGET is used.. Abort if frame
2228 cannot be determined. */
2230 static struct frame
*
2231 x_frame_of_widget (widget
)
2234 struct x_display_info
*dpyinfo
;
2238 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2240 /* Find the top-level shell of the widget. Note that this function
2241 can be called when the widget is not yet realized, so XtWindow
2242 (widget) == 0. That's the reason we can't simply use
2243 x_any_window_to_frame. */
2244 while (!XtIsTopLevelShell (widget
))
2245 widget
= XtParent (widget
);
2247 /* Look for a frame with that top-level widget. Allocate the color
2248 on that frame to get the right gamma correction value. */
2249 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2250 if (GC_FRAMEP (XCAR (tail
))
2251 && (f
= XFRAME (XCAR (tail
)),
2252 (f
->output_data
.nothing
!= 1
2253 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2254 && f
->output_data
.x
->widget
== widget
)
2261 /* Allocate the color COLOR->pixel on the screen and display of
2262 widget WIDGET in colormap CMAP. If an exact match cannot be
2263 allocated, try the nearest color available. Value is non-zero
2264 if successful. This is called from lwlib. */
2267 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2272 struct frame
*f
= x_frame_of_widget (widget
);
2273 return x_alloc_nearest_color (f
, cmap
, color
);
2277 #endif /* USE_X_TOOLKIT */
2279 #if 0 /* MAC_TODO */
2281 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2282 CMAP. If an exact match can't be allocated, try the nearest color
2283 available. Value is non-zero if successful. Set *COLOR to the
2287 x_alloc_nearest_color (f
, cmap
, color
)
2292 Display
*display
= FRAME_X_DISPLAY (f
);
2293 Screen
*screen
= FRAME_X_SCREEN (f
);
2296 gamma_correct (f
, color
);
2297 rc
= XAllocColor (display
, cmap
, color
);
2300 /* If we got to this point, the colormap is full, so we're going
2301 to try to get the next closest color. The algorithm used is
2302 a least-squares matching, which is what X uses for closest
2303 color matching with StaticColor visuals. */
2305 unsigned long nearest_delta
= ~0;
2306 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2307 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2309 for (i
= 0; i
< ncells
; ++i
)
2311 XQueryColors (display
, cmap
, cells
, ncells
);
2313 for (nearest
= i
= 0; i
< ncells
; ++i
)
2315 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2316 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2317 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2318 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2320 if (delta
< nearest_delta
)
2323 nearest_delta
= delta
;
2327 color
->red
= cells
[nearest
].red
;
2328 color
->green
= cells
[nearest
].green
;
2329 color
->blue
= cells
[nearest
].blue
;
2330 rc
= XAllocColor (display
, cmap
, color
);
2333 #ifdef DEBUG_X_COLORS
2335 register_color (color
->pixel
);
2336 #endif /* DEBUG_X_COLORS */
2342 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2343 It's necessary to do this instead of just using PIXEL directly to
2344 get color reference counts right. */
2347 x_copy_color (f
, pixel
)
2349 unsigned long pixel
;
2353 color
.pixel
= pixel
;
2355 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2356 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2358 #ifdef DEBUG_X_COLORS
2359 register_color (pixel
);
2365 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2366 It's necessary to do this instead of just using PIXEL directly to
2367 get color reference counts right. */
2370 x_copy_dpy_color (dpy
, cmap
, pixel
)
2373 unsigned long pixel
;
2377 color
.pixel
= pixel
;
2379 XQueryColor (dpy
, cmap
, &color
);
2380 XAllocColor (dpy
, cmap
, &color
);
2382 #ifdef DEBUG_X_COLORS
2383 register_color (pixel
);
2388 #endif /* MAC_TODO */
2391 /* Brightness beyond which a color won't have its highlight brightness
2394 Nominally, highlight colors for `3d' faces are calculated by
2395 brightening an object's color by a constant scale factor, but this
2396 doesn't yield good results for dark colors, so for colors who's
2397 brightness is less than this value (on a scale of 0-255) have to
2398 use an additional additive factor.
2400 The value here is set so that the default menu-bar/mode-line color
2401 (grey75) will not have its highlights changed at all. */
2402 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2405 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2406 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2407 If this produces the same color as COLOR, try a color where all RGB
2408 values have DELTA added. Return the allocated color in *COLOR.
2409 DISPLAY is the X display, CMAP is the colormap to operate on.
2410 Value is non-zero if successful. */
2413 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2415 unsigned long *color
;
2422 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2425 /* Change RGB values by specified FACTOR. Avoid overflow! */
2426 xassert (factor
>= 0);
2427 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2428 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2429 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2431 /* Calculate brightness of COLOR. */
2432 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2433 + BLUE_FROM_ULONG (*color
)) / 6;
2435 /* We only boost colors that are darker than
2436 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2437 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2438 /* Make an additive adjustment to NEW, because it's dark enough so
2439 that scaling by FACTOR alone isn't enough. */
2441 /* How far below the limit this color is (0 - 1, 1 being darker). */
2442 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2443 /* The additive adjustment. */
2444 int min_delta
= delta
* dimness
* factor
/ 2;
2447 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2448 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2449 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2451 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2452 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2453 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2457 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2458 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2459 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2461 /* MAC_TODO: Map to palette and retry with delta if same? */
2462 /* MAC_TODO: Free colors (if using palette)? */
2473 /* Set up the foreground color for drawing relief lines of glyph
2474 string S. RELIEF is a pointer to a struct relief containing the GC
2475 with which lines will be drawn. Use a color that is FACTOR or
2476 DELTA lighter or darker than the relief's background which is found
2477 in S->f->output_data.x->relief_background. If such a color cannot
2478 be allocated, use DEFAULT_PIXEL, instead. */
2481 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2483 struct relief
*relief
;
2486 unsigned long default_pixel
;
2489 struct mac_output
*di
= f
->output_data
.mac
;
2490 unsigned long mask
= GCForeground
;
2491 unsigned long pixel
;
2492 unsigned long background
= di
->relief_background
;
2493 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2495 /* MAC_TODO: Free colors (if using palette)? */
2497 /* Allocate new color. */
2498 xgcv
.foreground
= default_pixel
;
2500 if (dpyinfo
->n_planes
!= 1
2501 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2503 relief
->allocated_p
= 1;
2504 xgcv
.foreground
= relief
->pixel
= pixel
;
2507 if (relief
->gc
== 0)
2509 #if 0 /* MAC_TODO: stipple */
2510 xgcv
.stipple
= dpyinfo
->gray
;
2513 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2516 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2520 /* Set up colors for the relief lines around glyph string S. */
2523 x_setup_relief_colors (s
)
2524 struct glyph_string
*s
;
2526 struct mac_output
*di
= s
->f
->output_data
.mac
;
2527 unsigned long color
;
2529 if (s
->face
->use_box_color_for_shadows_p
)
2530 color
= s
->face
->box_color
;
2531 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2533 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2534 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2539 /* Get the background color of the face. */
2540 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2541 color
= xgcv
.background
;
2544 if (di
->white_relief
.gc
== 0
2545 || color
!= di
->relief_background
)
2547 di
->relief_background
= color
;
2548 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2549 WHITE_PIX_DEFAULT (s
->f
));
2550 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2551 BLACK_PIX_DEFAULT (s
->f
));
2556 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2557 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2558 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2559 relief. LEFT_P non-zero means draw a relief on the left side of
2560 the rectangle. RIGHT_P non-zero means draw a relief on the right
2561 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2565 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2566 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2568 int left_x
, top_y
, right_x
, bottom_y
, width
;
2569 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2572 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2573 Window window
= FRAME_MAC_WINDOW (f
);
2578 gc
= f
->output_data
.mac
->white_relief
.gc
;
2580 gc
= f
->output_data
.mac
->black_relief
.gc
;
2581 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2585 for (i
= 0; i
< width
; ++i
)
2586 XDrawLine (dpy
, window
, gc
,
2587 left_x
+ i
* left_p
, top_y
+ i
,
2588 right_x
- i
* right_p
, top_y
+ i
);
2592 for (i
= 0; i
< width
; ++i
)
2593 XDrawLine (dpy
, window
, gc
,
2594 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2596 mac_reset_clipping (dpy
, window
);
2598 gc
= f
->output_data
.mac
->black_relief
.gc
;
2600 gc
= f
->output_data
.mac
->white_relief
.gc
;
2601 mac_set_clip_rectangle (dpy
, window
,
2606 for (i
= 0; i
< width
; ++i
)
2607 XDrawLine (dpy
, window
, gc
,
2608 left_x
+ i
* left_p
, bottom_y
- i
,
2609 right_x
- i
* right_p
, bottom_y
- i
);
2613 for (i
= 0; i
< width
; ++i
)
2614 XDrawLine (dpy
, window
, gc
,
2615 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2617 mac_reset_clipping (dpy
, window
);
2621 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2622 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2623 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2624 left side of the rectangle. RIGHT_P non-zero means draw a line
2625 on the right side of the rectangle. CLIP_RECT is the clipping
2626 rectangle to use when drawing. */
2629 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2630 left_p
, right_p
, clip_rect
)
2631 struct glyph_string
*s
;
2632 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2637 xgcv
.foreground
= s
->face
->box_color
;
2638 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2641 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2642 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2646 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2647 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2650 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2651 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2655 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2656 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2658 mac_reset_clipping (s
->display
, s
->window
);
2662 /* Draw a box around glyph string S. */
2665 x_draw_glyph_string_box (s
)
2666 struct glyph_string
*s
;
2668 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2669 int left_p
, right_p
;
2670 struct glyph
*last_glyph
;
2673 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2674 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2675 : window_box_right (s
->w
, s
->area
));
2677 /* The glyph that may have a right box line. */
2678 last_glyph
= (s
->cmp
|| s
->img
2680 : s
->first_glyph
+ s
->nchars
- 1);
2682 width
= abs (s
->face
->box_line_width
);
2683 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2685 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2687 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2689 bottom_y
= top_y
+ s
->height
- 1;
2691 left_p
= (s
->first_glyph
->left_box_line_p
2692 || (s
->hl
== DRAW_MOUSE_FACE
2694 || s
->prev
->hl
!= s
->hl
)));
2695 right_p
= (last_glyph
->right_box_line_p
2696 || (s
->hl
== DRAW_MOUSE_FACE
2698 || s
->next
->hl
!= s
->hl
)));
2700 get_glyph_string_clip_rect (s
, &clip_rect
);
2702 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2703 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2704 left_p
, right_p
, &clip_rect
);
2707 x_setup_relief_colors (s
);
2708 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2709 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2714 /* Draw foreground of image glyph string S. */
2717 x_draw_image_foreground (s
)
2718 struct glyph_string
*s
;
2721 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2723 /* If first glyph of S has a left box line, start drawing it to the
2724 right of that line. */
2725 if (s
->face
->box
!= FACE_NO_BOX
2726 && s
->first_glyph
->left_box_line_p
2728 x
+= abs (s
->face
->box_line_width
);
2730 /* If there is a margin around the image, adjust x- and y-position
2732 if (s
->slice
.x
== 0)
2733 x
+= s
->img
->hmargin
;
2734 if (s
->slice
.y
== 0)
2735 y
+= s
->img
->vmargin
;
2739 x_set_glyph_string_clipping (s
);
2742 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2743 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2744 s
->slice
.width
, s
->slice
.height
, x
, y
);
2747 mac_copy_area (s
->display
, s
->img
->pixmap
,
2748 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2749 s
->slice
.width
, s
->slice
.height
, x
, y
);
2751 /* When the image has a mask, we can expect that at
2752 least part of a mouse highlight or a block cursor will
2753 be visible. If the image doesn't have a mask, make
2754 a block cursor visible by drawing a rectangle around
2755 the image. I believe it's looking better if we do
2756 nothing here for mouse-face. */
2757 if (s
->hl
== DRAW_CURSOR
)
2759 int r
= s
->img
->relief
;
2761 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2763 s
->slice
.width
+ r
*2 - 1,
2764 s
->slice
.height
+ r
*2 - 1);
2769 /* Draw a rectangle if image could not be loaded. */
2770 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2771 s
->slice
.width
- 1, s
->slice
.height
- 1);
2775 /* Draw a relief around the image glyph string S. */
2778 x_draw_image_relief (s
)
2779 struct glyph_string
*s
;
2781 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2784 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2786 /* If first glyph of S has a left box line, start drawing it to the
2787 right of that line. */
2788 if (s
->face
->box
!= FACE_NO_BOX
2789 && s
->first_glyph
->left_box_line_p
2791 x
+= abs (s
->face
->box_line_width
);
2793 /* If there is a margin around the image, adjust x- and y-position
2795 if (s
->slice
.x
== 0)
2796 x
+= s
->img
->hmargin
;
2797 if (s
->slice
.y
== 0)
2798 y
+= s
->img
->vmargin
;
2800 if (s
->hl
== DRAW_IMAGE_SUNKEN
2801 || s
->hl
== DRAW_IMAGE_RAISED
)
2803 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2804 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2808 thick
= abs (s
->img
->relief
);
2809 raised_p
= s
->img
->relief
> 0;
2814 x1
= x
+ s
->slice
.width
+ thick
- 1;
2815 y1
= y
+ s
->slice
.height
+ thick
- 1;
2817 x_setup_relief_colors (s
);
2818 get_glyph_string_clip_rect (s
, &r
);
2819 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2821 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2823 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2828 #if 0 /* TODO: figure out if we need to do this on Mac. */
2829 /* Draw the foreground of image glyph string S to PIXMAP. */
2832 x_draw_image_foreground_1 (s
, pixmap
)
2833 struct glyph_string
*s
;
2837 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2839 /* If first glyph of S has a left box line, start drawing it to the
2840 right of that line. */
2841 if (s
->face
->box
!= FACE_NO_BOX
2842 && s
->first_glyph
->left_box_line_p
2844 x
+= abs (s
->face
->box_line_width
);
2846 /* If there is a margin around the image, adjust x- and y-position
2848 if (s
->slice
.x
== 0)
2849 x
+= s
->img
->hmargin
;
2850 if (s
->slice
.y
== 0)
2851 y
+= s
->img
->vmargin
;
2856 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2857 s
->img
->mask
, pixmap
, s
->gc
,
2858 s
->slice
.x
, s
->slice
.y
,
2859 s
->slice
.width
, s
->slice
.height
,
2863 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2864 s
->slice
.x
, s
->slice
.y
,
2865 s
->slice
.width
, s
->slice
.height
,
2868 /* When the image has a mask, we can expect that at
2869 least part of a mouse highlight or a block cursor will
2870 be visible. If the image doesn't have a mask, make
2871 a block cursor visible by drawing a rectangle around
2872 the image. I believe it's looking better if we do
2873 nothing here for mouse-face. */
2874 if (s
->hl
== DRAW_CURSOR
)
2876 int r
= s
->img
->relief
;
2878 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2879 s
->slice
.width
+ r
*2 - 1,
2880 s
->slice
.height
+ r
*2 - 1);
2885 /* Draw a rectangle if image could not be loaded. */
2886 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2887 s
->slice
.width
- 1, s
->slice
.height
- 1);
2892 /* Draw part of the background of glyph string S. X, Y, W, and H
2893 give the rectangle to draw. */
2896 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2897 struct glyph_string
*s
;
2900 #if 0 /* MAC_TODO: stipple */
2903 /* Fill background with a stipple pattern. */
2904 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2905 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2906 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2909 #endif /* MAC_TODO */
2910 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2914 /* Draw image glyph string S.
2917 s->x +-------------------------
2920 | +-------------------------
2923 | | +-------------------
2929 x_draw_image_glyph_string (s
)
2930 struct glyph_string
*s
;
2933 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2934 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2938 height
= s
->height
- 2 * box_line_vwidth
;
2941 /* Fill background with face under the image. Do it only if row is
2942 taller than image or if image has a clip mask to reduce
2944 s
->stippled_p
= s
->face
->stipple
!= 0;
2945 if (height
> s
->slice
.height
2949 || s
->img
->pixmap
== 0
2950 || s
->width
!= s
->background_width
)
2953 if (s
->first_glyph
->left_box_line_p
2955 x
+= box_line_hwidth
;
2958 if (s
->slice
.y
== 0)
2959 y
+= box_line_vwidth
;
2961 #if 0 /* TODO: figure out if we need to do this on Mac. */
2964 /* Create a pixmap as large as the glyph string. Fill it
2965 with the background color. Copy the image to it, using
2966 its mask. Copy the temporary pixmap to the display. */
2967 int depth
= one_mac_display_info
.n_planes
;
2969 /* Create a pixmap as large as the glyph string. */
2970 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2971 s
->background_width
,
2974 /* Fill the pixmap with the background color/stipple. */
2975 #if 0 /* TODO: stipple */
2978 /* Fill background with a stipple pattern. */
2979 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2980 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2981 0, 0, s
->background_width
, s
->height
);
2982 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2988 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2990 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2991 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2992 0, 0, s
->background_width
,
2994 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2999 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3001 s
->background_filled_p
= 1;
3004 /* Draw the foreground. */
3005 #if 0 /* TODO: figure out if we need to do this on Mac. */
3008 x_draw_image_foreground_1 (s
, pixmap
);
3009 x_set_glyph_string_clipping (s
);
3010 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
3011 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3012 mac_reset_clipping (s
->display
, s
->window
);
3013 XFreePixmap (s
->display
, pixmap
);
3017 x_draw_image_foreground (s
);
3019 /* If we must draw a relief around the image, do it. */
3021 || s
->hl
== DRAW_IMAGE_RAISED
3022 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3023 x_draw_image_relief (s
);
3027 /* Draw stretch glyph string S. */
3030 x_draw_stretch_glyph_string (s
)
3031 struct glyph_string
*s
;
3033 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3034 s
->stippled_p
= s
->face
->stipple
!= 0;
3036 if (s
->hl
== DRAW_CURSOR
3037 && !x_stretch_cursor_p
)
3039 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3040 as wide as the stretch glyph. */
3041 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3044 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3046 /* Clear rest using the GC of the original non-cursor face. */
3047 if (width
< s
->background_width
)
3049 int x
= s
->x
+ width
, y
= s
->y
;
3050 int w
= s
->background_width
- width
, h
= s
->height
;
3054 if (s
->row
->mouse_face_p
3055 && cursor_in_mouse_face_p (s
->w
))
3057 x_set_mouse_face_gc (s
);
3063 get_glyph_string_clip_rect (s
, &r
);
3064 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3066 #if 0 /* MAC_TODO: stipple */
3067 if (s
->face
->stipple
)
3069 /* Fill background with a stipple pattern. */
3070 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3071 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3072 XSetFillStyle (s
->display
, gc
, FillSolid
);
3075 #endif /* MAC_TODO */
3078 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3079 XSetForeground (s
->display
, gc
, xgcv
.background
);
3080 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3081 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3084 mac_reset_clipping (s
->display
, s
->window
);
3087 else if (!s
->background_filled_p
)
3088 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3091 s
->background_filled_p
= 1;
3095 /* Draw glyph string S. */
3098 x_draw_glyph_string (s
)
3099 struct glyph_string
*s
;
3101 int relief_drawn_p
= 0;
3103 /* If S draws into the background of its successor that does not
3104 draw a cursor, draw the background of the successor first so that
3105 S can draw into it. This makes S->next use XDrawString instead
3106 of XDrawImageString. */
3107 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
3108 && s
->next
->hl
!= DRAW_CURSOR
)
3110 xassert (s
->next
->img
== NULL
);
3111 x_set_glyph_string_gc (s
->next
);
3112 x_set_glyph_string_clipping (s
->next
);
3113 x_draw_glyph_string_background (s
->next
, 1);
3116 /* Set up S->gc, set clipping and draw S. */
3117 x_set_glyph_string_gc (s
);
3119 /* Draw relief (if any) in advance for char/composition so that the
3120 glyph string can be drawn over it. */
3121 if (!s
->for_overlaps_p
3122 && s
->face
->box
!= FACE_NO_BOX
3123 && (s
->first_glyph
->type
== CHAR_GLYPH
3124 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3127 x_set_glyph_string_clipping (s
);
3128 x_draw_glyph_string_background (s
, 1);
3129 x_draw_glyph_string_box (s
);
3130 x_set_glyph_string_clipping (s
);
3134 x_set_glyph_string_clipping (s
);
3136 switch (s
->first_glyph
->type
)
3139 x_draw_image_glyph_string (s
);
3143 x_draw_stretch_glyph_string (s
);
3147 if (s
->for_overlaps_p
)
3148 s
->background_filled_p
= 1;
3150 x_draw_glyph_string_background (s
, 0);
3151 x_draw_glyph_string_foreground (s
);
3154 case COMPOSITE_GLYPH
:
3155 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3156 s
->background_filled_p
= 1;
3158 x_draw_glyph_string_background (s
, 1);
3159 x_draw_composite_glyph_string_foreground (s
);
3166 if (!s
->for_overlaps_p
)
3168 /* Draw underline. */
3169 if (s
->face
->underline_p
)
3171 unsigned long h
= 1;
3172 unsigned long dy
= s
->height
- h
;
3174 if (s
->face
->underline_defaulted_p
)
3175 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3180 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3181 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3182 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3184 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3188 /* Draw overline. */
3189 if (s
->face
->overline_p
)
3191 unsigned long dy
= 0, h
= 1;
3193 if (s
->face
->overline_color_defaulted_p
)
3194 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3199 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3200 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3201 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3203 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3207 /* Draw strike-through. */
3208 if (s
->face
->strike_through_p
)
3210 unsigned long h
= 1;
3211 unsigned long dy
= (s
->height
- h
) / 2;
3213 if (s
->face
->strike_through_color_defaulted_p
)
3214 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3219 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3220 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3221 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3223 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3227 /* Draw relief if not yet drawn. */
3228 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3229 x_draw_glyph_string_box (s
);
3232 /* Reset clipping. */
3233 mac_reset_clipping (s
->display
, s
->window
);
3236 /* Shift display to make room for inserted glyphs. */
3239 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3241 int x
, y
, width
, height
, shift_by
;
3243 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3244 f
->output_data
.mac
->normal_gc
,
3245 x
, y
, width
, height
,
3249 /* Delete N glyphs at the nominal cursor position. Not implemented
3260 /* Clear entire frame. If updating_frame is non-null, clear that
3261 frame. Otherwise clear the selected frame. */
3271 f
= SELECTED_FRAME ();
3273 /* Clearing the frame will erase any cursor, so mark them all as no
3275 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3276 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3277 output_cursor
.x
= -1;
3279 /* We don't set the output cursor here because there will always
3280 follow an explicit cursor_to. */
3282 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3284 /* We have to clear the scroll bars, too. If we have changed
3285 colors or something like that, then they should be notified. */
3286 x_scroll_bar_clear (f
);
3288 XFlush (FRAME_MAC_DISPLAY (f
));
3294 /* Invert the middle quarter of the frame for .15 sec. */
3296 /* We use the select system call to do the waiting, so we have to make
3297 sure it's available. If it isn't, we just won't do visual bells. */
3299 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3302 /* Subtract the `struct timeval' values X and Y, storing the result in
3303 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3306 timeval_subtract (result
, x
, y
)
3307 struct timeval
*result
, x
, y
;
3309 /* Perform the carry for the later subtraction by updating y. This
3310 is safer because on some systems the tv_sec member is unsigned. */
3311 if (x
.tv_usec
< y
.tv_usec
)
3313 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3314 y
.tv_usec
-= 1000000 * nsec
;
3318 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3320 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3321 y
.tv_usec
+= 1000000 * nsec
;
3325 /* Compute the time remaining to wait. tv_usec is certainly
3327 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3328 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3330 /* Return indication of whether the result should be considered
3332 return x
.tv_sec
< y
.tv_sec
;
3344 struct timeval wakeup
;
3346 EMACS_GET_TIME (wakeup
);
3348 /* Compute time to wait until, propagating carry from usecs. */
3349 wakeup
.tv_usec
+= 150000;
3350 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3351 wakeup
.tv_usec
%= 1000000;
3353 /* Keep waiting until past the time wakeup. */
3356 struct timeval timeout
;
3358 EMACS_GET_TIME (timeout
);
3360 /* In effect, timeout = wakeup - timeout.
3361 Break if result would be negative. */
3362 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3365 /* Try to wait that long--but we might wake up sooner. */
3366 select (0, NULL
, NULL
, NULL
, &timeout
);
3375 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3378 /* Make audible bell. */
3383 struct frame
*f
= SELECTED_FRAME ();
3385 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3393 XFlush (FRAME_MAC_DISPLAY (f
));
3400 /* Specify how many text lines, from the top of the window,
3401 should be affected by insert-lines and delete-lines operations.
3402 This, and those operations, are used only within an update
3403 that is bounded by calls to x_update_begin and x_update_end. */
3406 XTset_terminal_window (n
)
3409 /* This function intentionally left blank. */
3414 /***********************************************************************
3416 ***********************************************************************/
3418 /* Perform an insert-lines or delete-lines operation, inserting N
3419 lines or deleting -N lines at vertical position VPOS. */
3422 x_ins_del_lines (vpos
, n
)
3429 /* Scroll part of the display as described by RUN. */
3432 x_scroll_run (w
, run
)
3436 struct frame
*f
= XFRAME (w
->frame
);
3437 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3439 /* Get frame-relative bounding box of the text display area of W,
3440 without mode lines. Include in this box the left and right
3442 window_box (w
, -1, &x
, &y
, &width
, &height
);
3444 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3445 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3446 bottom_y
= y
+ height
;
3450 /* Scrolling up. Make sure we don't copy part of the mode
3451 line at the bottom. */
3452 if (from_y
+ run
->height
> bottom_y
)
3453 height
= bottom_y
- from_y
;
3455 height
= run
->height
;
3459 /* Scolling down. Make sure we don't copy over the mode line.
3461 if (to_y
+ run
->height
> bottom_y
)
3462 height
= bottom_y
- to_y
;
3464 height
= run
->height
;
3469 /* Cursor off. Will be switched on again in x_update_window_end. */
3473 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3474 f
->output_data
.mac
->normal_gc
,
3484 /***********************************************************************
3486 ***********************************************************************/
3494 ControlRef root_control
;
3497 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3499 ActivateControl (root_control
);
3501 x_update_cursor (f
, 1);
3505 frame_unhighlight (f
)
3509 ControlRef root_control
;
3512 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3514 DeactivateControl (root_control
);
3516 x_update_cursor (f
, 1);
3519 /* The focus has changed. Update the frames as necessary to reflect
3520 the new situation. Note that we can't change the selected frame
3521 here, because the Lisp code we are interrupting might become confused.
3522 Each event gets marked with the frame in which it occurred, so the
3523 Lisp code can tell when the switch took place by examining the events. */
3526 x_new_focus_frame (dpyinfo
, frame
)
3527 struct x_display_info
*dpyinfo
;
3528 struct frame
*frame
;
3530 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3532 if (frame
!= dpyinfo
->x_focus_frame
)
3534 /* Set this before calling other routines, so that they see
3535 the correct value of x_focus_frame. */
3536 dpyinfo
->x_focus_frame
= frame
;
3538 if (old_focus
&& old_focus
->auto_lower
)
3539 x_lower_frame (old_focus
);
3542 selected_frame
= frame
;
3543 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3545 Fselect_window (selected_frame
->selected_window
, Qnil
);
3546 choose_minibuf_frame ();
3549 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3550 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3552 pending_autoraise_frame
= 0;
3555 x_frame_rehighlight (dpyinfo
);
3558 /* Handle FocusIn and FocusOut state changes for FRAME.
3559 If FRAME has focus and there exists more than one frame, puts
3560 a FOCUS_IN_EVENT into *BUFP. */
3563 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3565 struct mac_display_info
*dpyinfo
;
3566 struct frame
*frame
;
3567 struct input_event
*bufp
;
3569 if (type
== activeFlag
)
3571 if (dpyinfo
->x_focus_event_frame
!= frame
)
3573 x_new_focus_frame (dpyinfo
, frame
);
3574 dpyinfo
->x_focus_event_frame
= frame
;
3576 /* Don't stop displaying the initial startup message
3577 for a switch-frame event we don't need. */
3578 if (GC_NILP (Vterminal_frame
)
3579 && GC_CONSP (Vframe_list
)
3580 && !GC_NILP (XCDR (Vframe_list
)))
3582 bufp
->kind
= FOCUS_IN_EVENT
;
3583 XSETFRAME (bufp
->frame_or_window
, frame
);
3589 if (dpyinfo
->x_focus_event_frame
== frame
)
3591 dpyinfo
->x_focus_event_frame
= 0;
3592 x_new_focus_frame (dpyinfo
, 0);
3597 /* The focus may have changed. Figure out if it is a real focus change,
3598 by checking both FocusIn/Out and Enter/LeaveNotify events.
3600 Returns FOCUS_IN_EVENT event in *BUFP. */
3603 x_detect_focus_change (dpyinfo
, event
, bufp
)
3604 struct mac_display_info
*dpyinfo
;
3606 struct input_event
*bufp
;
3608 struct frame
*frame
;
3610 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3614 /* On Mac, this is only called from focus events, so no switch needed. */
3615 mac_focus_changed ((event
->modifiers
& activeFlag
),
3616 dpyinfo
, frame
, bufp
);
3620 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3623 x_mouse_leave (dpyinfo
)
3624 struct x_display_info
*dpyinfo
;
3626 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3629 /* The focus has changed, or we have redirected a frame's focus to
3630 another frame (this happens when a frame uses a surrogate
3631 mini-buffer frame). Shift the highlight as appropriate.
3633 The FRAME argument doesn't necessarily have anything to do with which
3634 frame is being highlighted or un-highlighted; we only use it to find
3635 the appropriate X display info. */
3638 XTframe_rehighlight (frame
)
3639 struct frame
*frame
;
3641 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3645 x_frame_rehighlight (dpyinfo
)
3646 struct x_display_info
*dpyinfo
;
3648 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3650 if (dpyinfo
->x_focus_frame
)
3652 dpyinfo
->x_highlight_frame
3653 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3654 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3655 : dpyinfo
->x_focus_frame
);
3656 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3658 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3659 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3663 dpyinfo
->x_highlight_frame
= 0;
3665 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3668 frame_unhighlight (old_highlight
);
3669 if (dpyinfo
->x_highlight_frame
)
3670 frame_highlight (dpyinfo
->x_highlight_frame
);
3676 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3678 #if 0 /* MAC_TODO */
3679 /* Initialize mode_switch_bit and modifier_meaning. */
3681 x_find_modifier_meanings (dpyinfo
)
3682 struct x_display_info
*dpyinfo
;
3684 int min_code
, max_code
;
3687 XModifierKeymap
*mods
;
3689 dpyinfo
->meta_mod_mask
= 0;
3690 dpyinfo
->shift_lock_mask
= 0;
3691 dpyinfo
->alt_mod_mask
= 0;
3692 dpyinfo
->super_mod_mask
= 0;
3693 dpyinfo
->hyper_mod_mask
= 0;
3696 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3698 min_code
= dpyinfo
->display
->min_keycode
;
3699 max_code
= dpyinfo
->display
->max_keycode
;
3702 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3703 min_code
, max_code
- min_code
+ 1,
3705 mods
= XGetModifierMapping (dpyinfo
->display
);
3707 /* Scan the modifier table to see which modifier bits the Meta and
3708 Alt keysyms are on. */
3710 int row
, col
; /* The row and column in the modifier table. */
3712 for (row
= 3; row
< 8; row
++)
3713 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3716 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3718 /* Zeroes are used for filler. Skip them. */
3722 /* Are any of this keycode's keysyms a meta key? */
3726 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3728 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3734 dpyinfo
->meta_mod_mask
|= (1 << row
);
3739 dpyinfo
->alt_mod_mask
|= (1 << row
);
3744 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3749 dpyinfo
->super_mod_mask
|= (1 << row
);
3753 /* Ignore this if it's not on the lock modifier. */
3754 if ((1 << row
) == LockMask
)
3755 dpyinfo
->shift_lock_mask
= LockMask
;
3763 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3764 if (! dpyinfo
->meta_mod_mask
)
3766 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3767 dpyinfo
->alt_mod_mask
= 0;
3770 /* If some keys are both alt and meta,
3771 make them just meta, not alt. */
3772 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3774 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3777 XFree ((char *) syms
);
3778 XFreeModifiermap (mods
);
3781 #endif /* MAC_TODO */
3783 /* Convert between the modifier bits X uses and the modifier bits
3787 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3788 struct x_display_info
*dpyinfo
;
3789 unsigned short state
;
3791 return (((state
& shiftKey
) ? shift_modifier
: 0)
3792 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3793 | ((state
& cmdKey
) ? meta_modifier
: 0)
3794 | ((state
& optionKey
) ? alt_modifier
: 0));
3797 #if 0 /* MAC_TODO */
3798 static unsigned short
3799 x_emacs_to_x_modifiers (dpyinfo
, state
)
3800 struct x_display_info
*dpyinfo
;
3803 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3804 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3805 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3806 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3807 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3808 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3810 #endif /* MAC_TODO */
3812 /* Convert a keysym to its name. */
3815 x_get_keysym_name (keysym
)
3822 value
= XKeysymToString (keysym
);
3834 /* Mouse clicks and mouse movement. Rah. */
3836 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3838 If the event is a button press, then note that we have grabbed
3842 construct_mouse_click (result
, event
, f
)
3843 struct input_event
*result
;
3849 result
->kind
= MOUSE_CLICK_EVENT
;
3850 result
->code
= 0; /* only one mouse button */
3851 result
->timestamp
= event
->when
;
3852 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3854 mouseLoc
= event
->where
;
3856 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3858 GlobalToLocal (&mouseLoc
);
3859 XSETINT (result
->x
, mouseLoc
.h
);
3860 XSETINT (result
->y
, mouseLoc
.v
);
3862 XSETFRAME (result
->frame_or_window
, f
);
3870 /* Function to report a mouse movement to the mainstream Emacs code.
3871 The input handler calls this.
3873 We have received a mouse movement event, which is given in *event.
3874 If the mouse is over a different glyph than it was last time, tell
3875 the mainstream emacs code by setting mouse_moved. If not, ask for
3876 another motion event, so we can check again the next time it moves. */
3878 static Point last_mouse_motion_position
;
3879 static Lisp_Object last_mouse_motion_frame
;
3882 note_mouse_movement (frame
, pos
)
3886 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3887 #if TARGET_API_MAC_CARBON
3891 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3892 last_mouse_motion_position
= *pos
;
3893 XSETFRAME (last_mouse_motion_frame
, frame
);
3895 #if TARGET_API_MAC_CARBON
3896 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3898 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3901 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3902 /* This case corresponds to LeaveNotify in X11. */
3904 /* If we move outside the frame, then we're certainly no
3905 longer on any text in the frame. */
3906 clear_mouse_face (dpyinfo
);
3907 dpyinfo
->mouse_face_mouse_frame
= 0;
3908 if (!dpyinfo
->grabbed
)
3909 rif
->define_frame_cursor (frame
,
3910 frame
->output_data
.mac
->nontext_cursor
);
3913 /* Has the mouse moved off the glyph it was on at the last sighting? */
3914 else if (pos
->h
< last_mouse_glyph
.left
3915 || pos
->h
>= last_mouse_glyph
.right
3916 || pos
->v
< last_mouse_glyph
.top
3917 || pos
->v
>= last_mouse_glyph
.bottom
)
3919 frame
->mouse_moved
= 1;
3920 last_mouse_scroll_bar
= Qnil
;
3921 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3925 /* This is used for debugging, to turn off note_mouse_highlight. */
3927 int disable_mouse_highlight
;
3931 /************************************************************************
3933 ************************************************************************/
3935 static struct scroll_bar
*x_window_to_scroll_bar ();
3936 static void x_scroll_bar_report_motion ();
3937 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3940 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3943 redo_mouse_highlight ()
3945 if (!NILP (last_mouse_motion_frame
)
3946 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3947 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3948 last_mouse_motion_position
.h
,
3949 last_mouse_motion_position
.v
);
3953 /* Try to determine frame pixel position and size of the glyph under
3954 frame pixel coordinates X/Y on frame F . Return the position and
3955 size in *RECT. Value is non-zero if we could compute these
3959 glyph_rect (f
, x
, y
, rect
)
3966 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3970 struct window
*w
= XWINDOW (window
);
3971 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3972 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3974 for (; r
< end
&& r
->enabled_p
; ++r
)
3975 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3977 /* Found the row at y. */
3978 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3979 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3982 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3983 rect
->bottom
= rect
->top
+ r
->height
;
3987 /* x is to the left of the first glyph in the row. */
3988 /* Shouldn't this be a pixel value?
3989 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3991 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3992 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3996 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3997 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3999 /* x is on a glyph. */
4000 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
4001 rect
->right
= rect
->left
+ g
->pixel_width
;
4005 /* x is to the right of the last glyph in the row. */
4006 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
4007 /* Shouldn't this be a pixel value?
4008 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
4010 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
4015 /* The y is not on any row. */
4019 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4021 /* Record the position of the mouse in last_mouse_glyph. */
4023 remember_mouse_glyph (f1
, gx
, gy
)
4027 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
4029 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
4030 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
4032 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
4033 round down even for negative values. */
4039 /* This was the original code from XTmouse_position, but it seems
4040 to give the position of the glyph diagonally next to the one
4041 the mouse is over. */
4042 gx
= (gx
+ width
- 1) / width
* width
;
4043 gy
= (gy
+ height
- 1) / height
* height
;
4045 gx
= gx
/ width
* width
;
4046 gy
= gy
/ height
* height
;
4049 last_mouse_glyph
.left
= gx
;
4050 last_mouse_glyph
.top
= gy
;
4051 last_mouse_glyph
.right
= gx
+ width
;
4052 last_mouse_glyph
.bottom
= gy
+ height
;
4057 static struct frame
*
4058 mac_focus_frame (dpyinfo
)
4059 struct mac_display_info
*dpyinfo
;
4061 if (dpyinfo
->x_focus_frame
)
4062 return dpyinfo
->x_focus_frame
;
4064 /* Mac version may get events, such as a menu bar click, even when
4065 all the frames are invisible. In this case, we regard the
4066 event came to the selected frame. */
4067 return SELECTED_FRAME ();
4071 /* Return the current position of the mouse.
4072 *fp should be a frame which indicates which display to ask about.
4074 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4075 and *part to the frame, window, and scroll bar part that the mouse
4076 is over. Set *x and *y to the portion and whole of the mouse's
4077 position on the scroll bar.
4079 If the mouse movement started elsewhere, set *fp to the frame the
4080 mouse is on, *bar_window to nil, and *x and *y to the character cell
4083 Set *time to the server time-stamp for the time at which the mouse
4084 was at this position.
4086 Don't store anything if we don't have a valid set of values to report.
4088 This clears the mouse_moved flag, so we can wait for the next mouse
4092 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4095 Lisp_Object
*bar_window
;
4096 enum scroll_bar_part
*part
;
4098 unsigned long *time
;
4101 int ignore1
, ignore2
;
4102 struct frame
*f
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4103 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
4104 Lisp_Object frame
, tail
;
4108 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4109 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4112 /* Clear the mouse-moved flag for every frame on this display. */
4113 FOR_EACH_FRAME (tail
, frame
)
4114 XFRAME (frame
)->mouse_moved
= 0;
4116 last_mouse_scroll_bar
= Qnil
;
4118 SetPortWindowPort (wp
);
4120 GetMouse (&mouse_pos
);
4122 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4123 &last_mouse_glyph
, insist
);
4126 *part
= scroll_bar_handle
;
4128 XSETINT (*x
, mouse_pos
.h
);
4129 XSETINT (*y
, mouse_pos
.v
);
4130 *time
= last_mouse_movement_time
;
4137 /************************************************************************
4139 ************************************************************************/
4141 #ifdef USE_TOOLKIT_SCROLL_BARS
4143 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4144 static OSStatus install_scroll_bar_timer
P_ ((void));
4145 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4146 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4147 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4149 struct input_event
*));
4150 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4152 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4155 struct input_event
*));
4156 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4158 struct input_event
*));
4159 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4160 Point
, unsigned long,
4161 struct input_event
*));
4162 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4165 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4167 static int last_scroll_bar_part
;
4169 static EventLoopTimerRef scroll_bar_timer
;
4171 static int scroll_bar_timer_event_posted_p
;
4173 #define SCROLL_BAR_FIRST_DELAY 0.5
4174 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4177 scroll_bar_timer_callback (timer
, data
)
4178 EventLoopTimerRef timer
;
4181 EventRef event
= NULL
;
4184 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4185 kEventAttributeNone
, &event
);
4190 GetMouse (&mouse_pos
);
4191 LocalToGlobal (&mouse_pos
);
4192 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4193 sizeof (Point
), &mouse_pos
);
4197 UInt32 modifiers
= GetCurrentKeyModifiers ();
4199 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4200 sizeof (UInt32
), &modifiers
);
4203 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4204 kEventPriorityStandard
);
4206 scroll_bar_timer_event_posted_p
= 1;
4209 ReleaseEvent (event
);
4213 install_scroll_bar_timer ()
4215 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4217 if (scroll_bar_timer_callbackUPP
== NULL
)
4218 scroll_bar_timer_callbackUPP
=
4219 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4221 if (scroll_bar_timer
== NULL
)
4222 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4223 kEventDurationForever as delays. */
4225 InstallEventLoopTimer (GetCurrentEventLoop (),
4226 kEventDurationForever
, kEventDurationForever
,
4227 scroll_bar_timer_callbackUPP
, NULL
,
4232 set_scroll_bar_timer (delay
)
4233 EventTimerInterval delay
;
4235 if (scroll_bar_timer
== NULL
)
4236 install_scroll_bar_timer ();
4238 scroll_bar_timer_event_posted_p
= 0;
4240 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4244 control_part_code_to_scroll_bar_part (part_code
)
4245 ControlPartCode part_code
;
4249 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4250 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4251 case kControlPageUpPart
: return scroll_bar_above_handle
;
4252 case kControlPageDownPart
: return scroll_bar_below_handle
;
4253 case kControlIndicatorPart
: return scroll_bar_handle
;
4260 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
)
4261 struct scroll_bar
*bar
;
4263 unsigned long timestamp
;
4264 struct input_event
*bufp
;
4266 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4267 bufp
->frame_or_window
= bar
->window
;
4271 bufp
->timestamp
= timestamp
;
4272 XSETINT (bufp
->x
, 0);
4273 XSETINT (bufp
->y
, 0);
4274 bufp
->modifiers
= 0;
4278 get_control_part_bounds (ch
, part_code
, rect
)
4280 ControlPartCode part_code
;
4283 RgnHandle region
= NewRgn ();
4286 err
= GetControlRegion (ch
, part_code
, region
);
4288 GetRegionBounds (region
, rect
);
4289 DisposeRgn (region
);
4295 x_scroll_bar_handle_press (bar
, part_code
, timestamp
, bufp
)
4296 struct scroll_bar
*bar
;
4297 ControlPartCode part_code
;
4298 unsigned long timestamp
;
4299 struct input_event
*bufp
;
4301 int part
= control_part_code_to_scroll_bar_part (part_code
);
4306 if (part
!= scroll_bar_handle
)
4308 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
);
4309 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4310 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4313 last_scroll_bar_part
= part
;
4314 bar
->dragging
= Qnil
;
4315 tracked_scroll_bar
= bar
;
4319 x_scroll_bar_handle_release (bar
, timestamp
, bufp
)
4320 struct scroll_bar
*bar
;
4321 unsigned long timestamp
;
4322 struct input_event
*bufp
;
4324 if (last_scroll_bar_part
!= scroll_bar_handle
4325 || !GC_NILP (bar
->dragging
))
4326 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, timestamp
, bufp
);
4328 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4329 set_scroll_bar_timer (kEventDurationForever
);
4331 last_scroll_bar_part
= -1;
4332 bar
->dragging
= Qnil
;
4333 tracked_scroll_bar
= NULL
;
4337 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, timestamp
, bufp
)
4339 struct scroll_bar
*bar
;
4341 unsigned long timestamp
;
4342 struct input_event
*bufp
;
4344 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4346 if (last_scroll_bar_part
== scroll_bar_handle
)
4351 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4352 kControlIndicatorPart
, &r
);
4354 if (GC_NILP (bar
->dragging
))
4355 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4357 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4358 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4359 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4364 if (top
> top_range
)
4367 construct_scroll_bar_click (bar
, scroll_bar_handle
, timestamp
, bufp
);
4368 XSETINT (bufp
->x
, top
);
4369 XSETINT (bufp
->y
, top_range
);
4373 ControlPartCode part_code
;
4374 int unhilite_p
= 0, part
;
4376 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4380 part
= control_part_code_to_scroll_bar_part (part_code
);
4382 switch (last_scroll_bar_part
)
4384 case scroll_bar_above_handle
:
4385 case scroll_bar_below_handle
:
4386 if (part
!= scroll_bar_above_handle
4387 && part
!= scroll_bar_below_handle
)
4391 case scroll_bar_up_arrow
:
4392 case scroll_bar_down_arrow
:
4393 if (part
!= scroll_bar_up_arrow
4394 && part
!= scroll_bar_down_arrow
)
4401 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4402 else if (part
!= last_scroll_bar_part
4403 || scroll_bar_timer_event_posted_p
)
4405 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
);
4406 last_scroll_bar_part
= part
;
4407 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4408 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4413 /* Set the thumb size and position of scroll bar BAR. We are currently
4414 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4417 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4418 struct scroll_bar
*bar
;
4419 int portion
, position
, whole
;
4421 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4423 int value
, viewsize
, maximum
;
4425 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4426 value
= 0, viewsize
= 1, maximum
= 0;
4431 maximum
= max (0, whole
- portion
);
4436 SetControl32BitMinimum (ch
, 0);
4437 SetControl32BitMaximum (ch
, maximum
);
4438 SetControl32BitValue (ch
, value
);
4439 SetControlViewSize (ch
, viewsize
);
4444 #endif /* USE_TOOLKIT_SCROLL_BARS */
4448 /************************************************************************
4449 Scroll bars, general
4450 ************************************************************************/
4452 /* Create a scroll bar and return the scroll bar vector for it. W is
4453 the Emacs window on which to create the scroll bar. TOP, LEFT,
4454 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4457 static struct scroll_bar
*
4458 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4460 int top
, left
, width
, height
, disp_top
, disp_height
;
4462 struct frame
*f
= XFRAME (w
->frame
);
4463 struct scroll_bar
*bar
4464 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4472 r
.right
= left
+ width
;
4473 r
.bottom
= disp_top
+ disp_height
;
4475 #if TARGET_API_MAC_CARBON
4476 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4477 kControlScrollBarProc
, (long) bar
);
4479 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4480 scrollBarProc
, (long) bar
);
4482 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4484 XSETWINDOW (bar
->window
, w
);
4485 XSETINT (bar
->top
, top
);
4486 XSETINT (bar
->left
, left
);
4487 XSETINT (bar
->width
, width
);
4488 XSETINT (bar
->height
, height
);
4489 XSETINT (bar
->start
, 0);
4490 XSETINT (bar
->end
, 0);
4491 bar
->dragging
= Qnil
;
4492 #ifdef USE_TOOLKIT_SCROLL_BARS
4493 bar
->track_top
= Qnil
;
4494 bar
->track_height
= Qnil
;
4497 /* Add bar to its frame's list of scroll bars. */
4498 bar
->next
= FRAME_SCROLL_BARS (f
);
4500 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4501 if (!NILP (bar
->next
))
4502 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4509 /* Draw BAR's handle in the proper position.
4511 If the handle is already drawn from START to END, don't bother
4512 redrawing it, unless REBUILD is non-zero; in that case, always
4513 redraw it. (REBUILD is handy for drawing the handle after expose
4516 Normally, we want to constrain the start and end of the handle to
4517 fit inside its rectangle, but if the user is dragging the scroll
4518 bar handle, we want to let them drag it down all the way, so that
4519 the bar's top is as far down as it goes; otherwise, there's no way
4520 to move to the very end of the buffer. */
4522 #ifndef USE_TOOLKIT_SCROLL_BARS
4525 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4526 struct scroll_bar
*bar
;
4530 int dragging
= ! NILP (bar
->dragging
);
4531 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4532 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4533 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4534 int length
= end
- start
;
4536 /* If the display is already accurate, do nothing. */
4538 && start
== XINT (bar
->start
)
4539 && end
== XINT (bar
->end
))
4544 /* Make sure the values are reasonable, and try to preserve the
4545 distance between start and end. */
4548 else if (start
> top_range
)
4550 end
= start
+ length
;
4554 else if (end
> top_range
&& ! dragging
)
4557 /* Store the adjusted setting in the scroll bar. */
4558 XSETINT (bar
->start
, start
);
4559 XSETINT (bar
->end
, end
);
4561 /* Clip the end position, just for display. */
4562 if (end
> top_range
)
4565 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4566 top positions, to make sure the handle is always at least that
4567 many pixels tall. */
4568 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4570 SetControlMinimum (ch
, 0);
4571 /* Don't inadvertently activate deactivated scroll bars */
4572 if (GetControlMaximum (ch
) != -1)
4573 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4575 SetControlValue (ch
, start
);
4576 #if TARGET_API_MAC_CARBON
4577 SetControlViewSize (ch
, end
- start
);
4583 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4585 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4589 x_scroll_bar_remove (bar
)
4590 struct scroll_bar
*bar
;
4592 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4596 /* Destroy the Mac scroll bar control */
4597 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4599 /* Disassociate this scroll bar from its window. */
4600 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4605 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4606 that we are displaying PORTION characters out of a total of WHOLE
4607 characters, starting at POSITION. If WINDOW has no scroll bar,
4610 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4612 int portion
, whole
, position
;
4614 struct frame
*f
= XFRAME (w
->frame
);
4615 struct scroll_bar
*bar
;
4616 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4617 int window_y
, window_height
;
4619 /* Get window dimensions. */
4620 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4622 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4623 height
= window_height
;
4625 /* Compute the left edge of the scroll bar area. */
4626 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4628 /* Compute the width of the scroll bar which might be less than
4629 the width of the area reserved for the scroll bar. */
4630 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4631 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4635 /* Compute the left edge of the scroll bar. */
4636 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4639 sb_left
= left
+ width
- sb_width
;
4641 /* Adjustments according to Inside Macintosh to make it look nice */
4643 disp_height
= height
;
4649 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4655 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4658 /* Does the scroll bar exist yet? */
4659 if (NILP (w
->vertical_scroll_bar
))
4662 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4663 left
, top
, width
, height
, 0);
4665 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4667 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4671 /* It may just need to be moved and resized. */
4674 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4675 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4679 /* If already correctly positioned, do nothing. */
4680 if (!(XINT (bar
->left
) == sb_left
4681 && XINT (bar
->top
) == top
4682 && XINT (bar
->width
) == sb_width
4683 && XINT (bar
->height
) == height
))
4685 /* Clear areas not covered by the scroll bar because it's not as
4686 wide as the area reserved for it . This makes sure a
4687 previous mode line display is cleared after C-x 2 C-x 1, for
4689 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4690 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4691 left
, top
, area_width
, height
, 0);
4694 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4695 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4696 sb_left
- 1, top
, 1, height
, 0);
4700 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4701 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4705 /* Remember new settings. */
4706 XSETINT (bar
->left
, sb_left
);
4707 XSETINT (bar
->top
, top
);
4708 XSETINT (bar
->width
, sb_width
);
4709 XSETINT (bar
->height
, height
);
4710 #ifdef USE_TOOLKIT_SCROLL_BARS
4711 bar
->track_top
= Qnil
;
4712 bar
->track_height
= Qnil
;
4719 #ifdef USE_TOOLKIT_SCROLL_BARS
4720 if (NILP (bar
->track_top
))
4722 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4727 SetControl32BitMinimum (ch
, 0);
4728 SetControl32BitMaximum (ch
, 1);
4729 SetControlViewSize (ch
, 1);
4731 /* Move the scroll bar thumb to the top. */
4732 SetControl32BitValue (ch
, 0);
4733 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4735 /* Move the scroll bar thumb to the bottom. */
4736 SetControl32BitValue (ch
, 1);
4737 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4739 UnionRect (&r0
, &r1
, &r0
);
4740 XSETINT (bar
->track_top
, r0
.top
);
4741 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4746 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4747 #else /* not USE_TOOLKIT_SCROLL_BARS */
4748 /* Set the scroll bar's current state, unless we're currently being
4750 if (NILP (bar
->dragging
))
4752 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4755 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4758 int start
= ((double) position
* top_range
) / whole
;
4759 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4760 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4763 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4767 /* The following three hooks are used when we're doing a thorough
4768 redisplay of the frame. We don't explicitly know which scroll bars
4769 are going to be deleted, because keeping track of when windows go
4770 away is a real pain - "Can you say set-window-configuration, boys
4771 and girls?" Instead, we just assert at the beginning of redisplay
4772 that *all* scroll bars are to be removed, and then save a scroll bar
4773 from the fiery pit when we actually redisplay its window. */
4775 /* Arrange for all scroll bars on FRAME to be removed at the next call
4776 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4777 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4780 XTcondemn_scroll_bars (frame
)
4783 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4784 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4787 bar
= FRAME_SCROLL_BARS (frame
);
4788 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4789 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4790 XSCROLL_BAR (bar
)->prev
= Qnil
;
4791 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4792 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4793 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4798 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4799 Note that WINDOW isn't necessarily condemned at all. */
4802 XTredeem_scroll_bar (window
)
4803 struct window
*window
;
4805 struct scroll_bar
*bar
;
4807 /* We can't redeem this window's scroll bar if it doesn't have one. */
4808 if (NILP (window
->vertical_scroll_bar
))
4811 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4813 /* Unlink it from the condemned list. */
4815 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4817 if (NILP (bar
->prev
))
4819 /* If the prev pointer is nil, it must be the first in one of
4821 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4822 /* It's not condemned. Everything's fine. */
4824 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4825 window
->vertical_scroll_bar
))
4826 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4828 /* If its prev pointer is nil, it must be at the front of
4829 one or the other! */
4833 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4835 if (! NILP (bar
->next
))
4836 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4838 bar
->next
= FRAME_SCROLL_BARS (f
);
4840 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4841 if (! NILP (bar
->next
))
4842 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4846 /* Remove all scroll bars on FRAME that haven't been saved since the
4847 last call to `*condemn_scroll_bars_hook'. */
4850 XTjudge_scroll_bars (f
)
4853 Lisp_Object bar
, next
;
4855 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4857 /* Clear out the condemned list now so we won't try to process any
4858 more events on the hapless scroll bars. */
4859 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4861 for (; ! NILP (bar
); bar
= next
)
4863 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4865 x_scroll_bar_remove (b
);
4868 b
->next
= b
->prev
= Qnil
;
4871 /* Now there should be no references to the condemned scroll bars,
4872 and they should get garbage-collected. */
4876 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4877 is set to something other than NO_EVENT, it is enqueued.
4879 This may be called from a signal handler, so we have to ignore GC
4883 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4884 struct scroll_bar
*bar
;
4885 ControlPartCode part_code
;
4887 struct input_event
*bufp
;
4889 int win_y
, top_range
;
4891 if (! GC_WINDOWP (bar
->window
))
4894 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4895 bufp
->frame_or_window
= bar
->window
;
4898 bar
->dragging
= Qnil
;
4902 case kControlUpButtonPart
:
4903 bufp
->part
= scroll_bar_up_arrow
;
4905 case kControlDownButtonPart
:
4906 bufp
->part
= scroll_bar_down_arrow
;
4908 case kControlPageUpPart
:
4909 bufp
->part
= scroll_bar_above_handle
;
4911 case kControlPageDownPart
:
4912 bufp
->part
= scroll_bar_below_handle
;
4914 #if TARGET_API_MAC_CARBON
4917 case kControlIndicatorPart
:
4919 if (er
->what
== mouseDown
)
4920 bar
->dragging
= make_number (0);
4921 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4922 bufp
->part
= scroll_bar_handle
;
4926 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4927 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4929 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4933 if (! NILP (bar
->dragging
))
4934 win_y
-= XINT (bar
->dragging
);
4938 if (win_y
> top_range
)
4941 XSETINT (bufp
->x
, win_y
);
4942 XSETINT (bufp
->y
, top_range
);
4945 #ifndef USE_TOOLKIT_SCROLL_BARS
4947 /* Handle some mouse motion while someone is dragging the scroll bar.
4949 This may be called from a signal handler, so we have to ignore GC
4953 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4954 struct scroll_bar
*bar
;
4958 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4960 last_mouse_movement_time
= t
;
4963 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4965 /* If we're dragging the bar, display it. */
4966 if (! GC_NILP (bar
->dragging
))
4968 /* Where should the handle be now? */
4969 int new_start
= y_pos
- 24;
4971 if (new_start
!= XINT (bar
->start
))
4973 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4975 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4980 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4982 /* Return information to the user about the current position of the
4983 mouse on the scroll bar. */
4986 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4988 Lisp_Object
*bar_window
;
4989 enum scroll_bar_part
*part
;
4991 unsigned long *time
;
4993 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4994 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4995 #if TARGET_API_MAC_CARBON
4996 WindowPtr wp
= GetControlOwner (ch
);
4998 WindowPtr wp
= (*ch
)->contrlOwner
;
5001 struct frame
*f
= mac_window_to_frame (wp
);
5002 int win_y
, top_range
;
5004 SetPortWindowPort (wp
);
5006 GetMouse (&mouse_pos
);
5008 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5009 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5011 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5015 if (! NILP (bar
->dragging
))
5016 win_y
-= XINT (bar
->dragging
);
5020 if (win_y
> top_range
)
5024 *bar_window
= bar
->window
;
5026 if (! NILP (bar
->dragging
))
5027 *part
= scroll_bar_handle
;
5028 else if (win_y
< XINT (bar
->start
))
5029 *part
= scroll_bar_above_handle
;
5030 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5031 *part
= scroll_bar_handle
;
5033 *part
= scroll_bar_below_handle
;
5035 XSETINT (*x
, win_y
);
5036 XSETINT (*y
, top_range
);
5039 last_mouse_scroll_bar
= Qnil
;
5041 *time
= last_mouse_movement_time
;
5045 /* The screen has been cleared so we may have changed foreground or
5046 background colors, and the scroll bars may need to be redrawn.
5047 Clear out the scroll bars, and ask for expose events, so we can
5051 x_scroll_bar_clear (f
)
5054 XTcondemn_scroll_bars (f
);
5055 XTjudge_scroll_bars (f
);
5059 /***********************************************************************
5061 ***********************************************************************/
5063 /* Set clipping for output in glyph row ROW. W is the window in which
5064 we operate. GC is the graphics context to set clipping in.
5066 ROW may be a text row or, e.g., a mode line. Text rows must be
5067 clipped to the interior of the window dedicated to text display,
5068 mode lines must be clipped to the whole window. */
5071 x_clip_to_row (w
, row
, area
, gc
)
5073 struct glyph_row
*row
;
5077 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5079 int window_x
, window_y
, window_width
;
5081 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5083 clip_rect
.left
= window_x
;
5084 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5085 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5086 clip_rect
.right
= clip_rect
.left
+ window_width
;
5087 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5089 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
5093 /* Draw a hollow box cursor on window W in glyph row ROW. */
5096 x_draw_hollow_cursor (w
, row
)
5098 struct glyph_row
*row
;
5100 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5101 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5102 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5105 struct glyph
*cursor_glyph
;
5108 /* Get the glyph the cursor is on. If we can't tell because
5109 the current matrix is invalid or such, give up. */
5110 cursor_glyph
= get_phys_cursor_glyph (w
);
5111 if (cursor_glyph
== NULL
)
5114 /* Compute frame-relative coordinates for phys cursor. */
5115 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5116 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5117 wd
= w
->phys_cursor_width
;
5119 /* The foreground of cursor_gc is typically the same as the normal
5120 background color, which can cause the cursor box to be invisible. */
5121 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5122 if (dpyinfo
->scratch_cursor_gc
)
5123 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5125 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5126 GCForeground
, &xgcv
);
5127 gc
= dpyinfo
->scratch_cursor_gc
;
5129 /* Set clipping, draw the rectangle, and reset clipping again. */
5130 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5131 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
5132 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5136 /* Draw a bar cursor on window W in glyph row ROW.
5138 Implementation note: One would like to draw a bar cursor with an
5139 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5140 Unfortunately, I didn't find a font yet that has this property set.
5144 x_draw_bar_cursor (w
, row
, width
, kind
)
5146 struct glyph_row
*row
;
5148 enum text_cursor_kinds kind
;
5150 struct frame
*f
= XFRAME (w
->frame
);
5151 struct glyph
*cursor_glyph
;
5153 /* If cursor is out of bounds, don't draw garbage. This can happen
5154 in mini-buffer windows when switching between echo area glyphs
5156 cursor_glyph
= get_phys_cursor_glyph (w
);
5157 if (cursor_glyph
== NULL
)
5160 /* If on an image, draw like a normal cursor. That's usually better
5161 visible than drawing a bar, esp. if the image is large so that
5162 the bar might not be in the window. */
5163 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5165 struct glyph_row
*row
;
5166 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5167 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5171 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5172 Window window
= FRAME_MAC_WINDOW (f
);
5173 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5174 unsigned long mask
= GCForeground
| GCBackground
;
5175 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5178 /* If the glyph's background equals the color we normally draw
5179 the bar cursor in, the bar cursor in its normal color is
5180 invisible. Use the glyph's foreground color instead in this
5181 case, on the assumption that the glyph's colors are chosen so
5182 that the glyph is legible. */
5183 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5184 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5186 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5189 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5192 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5193 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5197 width
= FRAME_CURSOR_WIDTH (f
);
5198 width
= min (cursor_glyph
->pixel_width
, width
);
5200 w
->phys_cursor_width
= width
;
5201 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5203 if (kind
== BAR_CURSOR
)
5204 XFillRectangle (dpy
, window
, gc
,
5205 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5206 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5207 width
, row
->height
);
5209 XFillRectangle (dpy
, window
, gc
,
5210 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5211 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5212 row
->height
- width
),
5213 cursor_glyph
->pixel_width
,
5216 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5221 /* RIF: Define cursor CURSOR on frame F. */
5224 mac_define_frame_cursor (f
, cursor
)
5228 SetThemeCursor (cursor
);
5232 /* RIF: Clear area on frame F. */
5235 mac_clear_frame_area (f
, x
, y
, width
, height
)
5237 int x
, y
, width
, height
;
5239 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5240 x
, y
, width
, height
, 0);
5244 /* RIF: Draw cursor on window W. */
5247 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5249 struct glyph_row
*glyph_row
;
5251 int cursor_type
, cursor_width
;
5256 w
->phys_cursor_type
= cursor_type
;
5257 w
->phys_cursor_on_p
= 1;
5259 if (glyph_row
->exact_window_width_line_p
5260 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5262 glyph_row
->cursor_in_fringe_p
= 1;
5263 draw_fringe_bitmap (w
, glyph_row
, 0);
5266 switch (cursor_type
)
5268 case HOLLOW_BOX_CURSOR
:
5269 x_draw_hollow_cursor (w
, glyph_row
);
5272 case FILLED_BOX_CURSOR
:
5273 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5277 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5281 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5285 w
->phys_cursor_width
= 0;
5297 #if 0 /* MAC_TODO: no icon support yet. */
5299 x_bitmap_icon (f
, icon
)
5305 if (FRAME_W32_WINDOW (f
) == 0)
5309 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5310 else if (STRINGP (icon
))
5311 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5312 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5313 else if (SYMBOLP (icon
))
5317 if (EQ (icon
, intern ("application")))
5318 name
= (LPCTSTR
) IDI_APPLICATION
;
5319 else if (EQ (icon
, intern ("hand")))
5320 name
= (LPCTSTR
) IDI_HAND
;
5321 else if (EQ (icon
, intern ("question")))
5322 name
= (LPCTSTR
) IDI_QUESTION
;
5323 else if (EQ (icon
, intern ("exclamation")))
5324 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5325 else if (EQ (icon
, intern ("asterisk")))
5326 name
= (LPCTSTR
) IDI_ASTERISK
;
5327 else if (EQ (icon
, intern ("winlogo")))
5328 name
= (LPCTSTR
) IDI_WINLOGO
;
5332 hicon
= LoadIcon (NULL
, name
);
5340 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5345 #endif /* MAC_TODO */
5347 /************************************************************************
5349 ************************************************************************/
5351 /* Display Error Handling functions not used on W32. Listing them here
5352 helps diff stay in step when comparing w32term.c with xterm.c.
5354 x_error_catcher (display, error)
5355 x_catch_errors (dpy)
5356 x_catch_errors_unwind (old_val)
5357 x_check_errors (dpy, format)
5358 x_had_errors_p (dpy)
5359 x_clear_errors (dpy)
5360 x_uncatch_errors (dpy, count)
5362 x_connection_signal (signalnum)
5363 x_connection_closed (dpy, error_message)
5364 x_error_quitter (display, error)
5365 x_error_handler (display, error)
5366 x_io_error_quitter (display)
5371 /* Changing the font of the frame. */
5373 /* Give frame F the font named FONTNAME as its default font, and
5374 return the full name of that font. FONTNAME may be a wildcard
5375 pattern; in that case, we choose some font that fits the pattern.
5376 The return value shows which font we chose. */
5379 x_new_font (f
, fontname
)
5381 register char *fontname
;
5383 struct font_info
*fontp
5384 = FS_LOAD_FONT (f
, fontname
);
5389 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
5390 /* This font is already set in frame F. There's nothing more to
5392 return build_string (fontp
->full_name
);
5394 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5395 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5396 FRAME_FONTSET (f
) = -1;
5398 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5399 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5400 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5402 compute_fringe_widths (f
, 1);
5404 /* Compute the scroll bar width in character columns. */
5405 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5407 int wid
= FRAME_COLUMN_WIDTH (f
);
5408 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5409 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5413 int wid
= FRAME_COLUMN_WIDTH (f
);
5414 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5417 /* Now make the frame display the given font. */
5418 if (FRAME_MAC_WINDOW (f
) != 0)
5420 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5422 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5424 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5427 /* Don't change the size of a tip frame; there's no point in
5428 doing it because it's done in Fx_show_tip, and it leads to
5429 problems because the tip frame has no widget. */
5430 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5431 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5434 return build_string (fontp
->full_name
);
5437 /* Give frame F the fontset named FONTSETNAME as its default font, and
5438 return the full name of that fontset. FONTSETNAME may be a wildcard
5439 pattern; in that case, we choose some fontset that fits the pattern.
5440 The return value shows which fontset we chose. */
5443 x_new_fontset (f
, fontsetname
)
5445 Lisp_Object fontsetname
;
5447 int fontset
= fs_query_fontset (fontsetname
, 0);
5450 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
5451 /* This fontset is already set in frame F. There's nothing more
5453 return fontset_name (fontset
);
5454 else if (fontset
== 0)
5455 /* The default fontset can't be the default font. */
5459 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5461 result
= x_new_font (f
, SDATA (fontsetname
));
5463 if (!STRINGP (result
))
5464 /* Can't load ASCII font. */
5468 fontset
= new_fontset_from_font_name (result
);
5470 /* Since x_new_font doesn't update any fontset information, do it now. */
5471 FRAME_FONTSET (f
) = fontset
;
5473 return fontset_name (fontset
);
5477 /***********************************************************************
5478 TODO: W32 Input Methods
5479 ***********************************************************************/
5480 /* Listing missing functions from xterm.c helps diff stay in step.
5482 xim_destroy_callback (xim, client_data, call_data)
5483 xim_open_dpy (dpyinfo, resource_name)
5485 xim_instantiate_callback (display, client_data, call_data)
5486 xim_initialize (dpyinfo, resource_name)
5487 xim_close_dpy (dpyinfo)
5493 mac_get_window_bounds (f
, inner
, outer
)
5495 Rect
*inner
, *outer
;
5497 #if TARGET_API_MAC_CARBON
5498 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5499 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5500 #else /* not TARGET_API_MAC_CARBON */
5501 RgnHandle region
= NewRgn ();
5503 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5504 *inner
= (*region
)->rgnBBox
;
5505 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5506 *outer
= (*region
)->rgnBBox
;
5507 DisposeRgn (region
);
5508 #endif /* not TARGET_API_MAC_CARBON */
5512 /* Calculate the absolute position in frame F
5513 from its current recorded position values and gravity. */
5516 x_calc_absolute_position (f
)
5519 int width_diff
= 0, height_diff
= 0;
5520 int flags
= f
->size_hint_flags
;
5523 /* We have nothing to do if the current position
5524 is already for the top-left corner. */
5525 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5528 /* Find the offsets of the outside upper-left corner of
5529 the inner window, with respect to the outer window. */
5530 mac_get_window_bounds (f
, &inner
, &outer
);
5532 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5533 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5535 /* Treat negative positions as relative to the leftmost bottommost
5536 position that fits on the screen. */
5537 if (flags
& XNegative
)
5538 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5540 - FRAME_PIXEL_WIDTH (f
)
5543 if (flags
& YNegative
)
5544 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5546 - FRAME_PIXEL_HEIGHT (f
)
5549 /* The left_pos and top_pos
5550 are now relative to the top and left screen edges,
5551 so the flags should correspond. */
5552 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5555 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5556 to really change the position, and 0 when calling from
5557 x_make_frame_visible (in that case, XOFF and YOFF are the current
5558 position values). It is -1 when calling from x_set_frame_parameters,
5559 which means, do adjust for borders but don't change the gravity. */
5562 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5564 register int xoff
, yoff
;
5567 if (change_gravity
> 0)
5571 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5573 f
->size_hint_flags
|= XNegative
;
5575 f
->size_hint_flags
|= YNegative
;
5576 f
->win_gravity
= NorthWestGravity
;
5578 x_calc_absolute_position (f
);
5581 x_wm_set_size_hint (f
, (long) 0, 0);
5583 #if TARGET_API_MAC_CARBON
5584 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5585 /* If the title bar is completely outside the screen, adjust the
5587 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5588 kWindowConstrainMoveRegardlessOfFit
5589 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5590 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5593 Rect inner
, outer
, screen_rect
, dummy
;
5594 RgnHandle region
= NewRgn ();
5596 mac_get_window_bounds (f
, &inner
, &outer
);
5597 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5598 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5599 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5600 f
->top_pos
+ f
->y_pixels_diff
, false);
5602 /* If the title bar is completely outside the screen, adjust the
5603 position. The variable `outer' holds the title bar rectangle.
5604 The variable `inner' holds slightly smaller one than `outer',
5605 so that the calculation of overlapping may not become too
5607 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5608 outer
= (*region
)->rgnBBox
;
5609 DisposeRgn (region
);
5611 InsetRect (&inner
, 8, 8);
5612 screen_rect
= qd
.screenBits
.bounds
;
5613 screen_rect
.top
+= GetMBarHeight ();
5615 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5617 if (inner
.right
<= screen_rect
.left
)
5618 f
->left_pos
= screen_rect
.left
;
5619 else if (inner
.left
>= screen_rect
.right
)
5620 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5622 if (inner
.bottom
<= screen_rect
.top
)
5623 f
->top_pos
= screen_rect
.top
;
5624 else if (inner
.top
>= screen_rect
.bottom
)
5625 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5627 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5628 f
->top_pos
+ f
->y_pixels_diff
, false);
5636 /* Call this to change the size of frame F's x-window.
5637 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5638 for this size change and subsequent size changes.
5639 Otherwise we leave the window gravity unchanged. */
5642 x_set_window_size (f
, change_gravity
, cols
, rows
)
5647 int pixelwidth
, pixelheight
;
5651 check_frame_size (f
, &rows
, &cols
);
5652 f
->scroll_bar_actual_width
5653 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5655 compute_fringe_widths (f
, 0);
5657 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5658 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5660 f
->win_gravity
= NorthWestGravity
;
5661 x_wm_set_size_hint (f
, (long) 0, 0);
5663 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5664 #if TARGET_API_MAC_CARBON
5665 if (f
->output_data
.mac
->hourglass_control
)
5666 MoveControl (f
->output_data
.mac
->hourglass_control
,
5667 pixelwidth
- HOURGLASS_WIDTH
, 0);
5670 /* Now, strictly speaking, we can't be sure that this is accurate,
5671 but the window manager will get around to dealing with the size
5672 change request eventually, and we'll hear how it went when the
5673 ConfigureNotify event gets here.
5675 We could just not bother storing any of this information here,
5676 and let the ConfigureNotify event set everything up, but that
5677 might be kind of confusing to the Lisp code, since size changes
5678 wouldn't be reported in the frame parameters until some random
5679 point in the future when the ConfigureNotify event arrives.
5681 We pass 1 for DELAY since we can't run Lisp code inside of
5683 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5684 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5685 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5687 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5688 receive in the ConfigureNotify event; if we get what we asked
5689 for, then the event won't cause the screen to become garbaged, so
5690 we have to make sure to do it here. */
5691 SET_FRAME_GARBAGED (f
);
5693 XFlush (FRAME_X_DISPLAY (f
));
5695 /* If cursor was outside the new size, mark it as off. */
5696 mark_window_cursors_off (XWINDOW (f
->root_window
));
5698 /* Clear out any recollection of where the mouse highlighting was,
5699 since it might be in a place that's outside the new frame size.
5700 Actually checking whether it is outside is a pain in the neck,
5701 so don't try--just let the highlighting be done afresh with new size. */
5702 cancel_mouse_face (f
);
5707 /* Mouse warping. */
5709 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5712 x_set_mouse_position (f
, x
, y
)
5718 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5719 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5721 if (pix_x
< 0) pix_x
= 0;
5722 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5724 if (pix_y
< 0) pix_y
= 0;
5725 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5727 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5731 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5735 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5738 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5739 0, 0, 0, 0, pix_x
, pix_y
);
5745 /* focus shifting, raising and lowering. */
5748 x_focus_on_frame (f
)
5751 #if 0 /* This proves to be unpleasant. */
5755 /* I don't think that the ICCCM allows programs to do things like this
5756 without the interaction of the window manager. Whatever you end up
5757 doing with this code, do it to x_unfocus_frame too. */
5758 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5759 RevertToPointerRoot
, CurrentTime
);
5769 /* Raise frame F. */
5774 if (f
->async_visible
)
5777 SelectWindow (FRAME_MAC_WINDOW (f
));
5782 /* Lower frame F. */
5787 if (f
->async_visible
)
5790 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5796 XTframe_raise_lower (f
, raise_flag
)
5806 /* Change of visibility. */
5808 /* This tries to wait until the frame is really visible.
5809 However, if the window manager asks the user where to position
5810 the frame, this will return before the user finishes doing that.
5811 The frame will not actually be visible at that time,
5812 but it will become visible later when the window manager
5813 finishes with it. */
5816 x_make_frame_visible (f
)
5820 int original_top
, original_left
;
5824 if (! FRAME_VISIBLE_P (f
))
5826 /* We test FRAME_GARBAGED_P here to make sure we don't
5827 call x_set_offset a second time
5828 if we get to x_make_frame_visible a second time
5829 before the window gets really visible. */
5830 if (! FRAME_ICONIFIED_P (f
)
5831 && ! f
->output_data
.mac
->asked_for_visible
)
5832 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5834 f
->output_data
.mac
->asked_for_visible
= 1;
5836 #if TARGET_API_MAC_CARBON
5837 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5839 struct frame
*sf
= SELECTED_FRAME ();
5840 if (!FRAME_MAC_P (sf
))
5841 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5842 kWindowCenterOnMainScreen
);
5844 RepositionWindow (FRAME_MAC_WINDOW (f
),
5845 FRAME_MAC_WINDOW (sf
),
5846 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5847 kWindowCascadeStartAtParentWindowScreen
5849 kWindowCascadeOnParentWindowScreen
5852 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5855 ShowWindow (FRAME_MAC_WINDOW (f
));
5858 XFlush (FRAME_MAC_DISPLAY (f
));
5860 /* Synchronize to ensure Emacs knows the frame is visible
5861 before we do anything else. We do this loop with input not blocked
5862 so that incoming events are handled. */
5867 /* This must come after we set COUNT. */
5870 XSETFRAME (frame
, f
);
5872 /* Wait until the frame is visible. Process X events until a
5873 MapNotify event has been seen, or until we think we won't get a
5874 MapNotify at all.. */
5875 for (count
= input_signal_count
+ 10;
5876 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5878 /* Force processing of queued events. */
5881 /* Machines that do polling rather than SIGIO have been
5882 observed to go into a busy-wait here. So we'll fake an
5883 alarm signal to let the handler know that there's something
5884 to be read. We used to raise a real alarm, but it seems
5885 that the handler isn't always enabled here. This is
5887 if (input_polling_used ())
5889 /* It could be confusing if a real alarm arrives while
5890 processing the fake one. Turn it off and let the
5891 handler reset it. */
5892 extern void poll_for_input_1
P_ ((void));
5893 int old_poll_suppress_count
= poll_suppress_count
;
5894 poll_suppress_count
= 1;
5895 poll_for_input_1 ();
5896 poll_suppress_count
= old_poll_suppress_count
;
5899 /* See if a MapNotify event has been processed. */
5900 FRAME_SAMPLE_VISIBILITY (f
);
5905 /* Change from mapped state to withdrawn state. */
5907 /* Make the frame visible (mapped and not iconified). */
5910 x_make_frame_invisible (f
)
5913 /* Don't keep the highlight on an invisible frame. */
5914 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5915 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5919 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5920 that the current position of the window is user-specified, rather than
5921 program-specified, so that when the window is mapped again, it will be
5922 placed at the same location, without forcing the user to position it
5923 by hand again (they have already done that once for this window.) */
5924 x_wm_set_size_hint (f
, (long) 0, 1);
5926 HideWindow (FRAME_MAC_WINDOW (f
));
5928 /* We can't distinguish this from iconification
5929 just by the event that we get from the server.
5930 So we can't win using the usual strategy of letting
5931 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5932 and synchronize with the server to make sure we agree. */
5934 FRAME_ICONIFIED_P (f
) = 0;
5935 f
->async_visible
= 0;
5936 f
->async_iconified
= 0;
5941 /* Change window state from mapped to iconified. */
5947 /* Don't keep the highlight on an invisible frame. */
5948 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5949 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5952 /* Review: Since window is still visible in dock, still allow updates? */
5953 if (f
->async_iconified
)
5959 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5965 /* Free X resources of frame F. */
5968 x_free_frame_resources (f
)
5971 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5972 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5976 if (wp
!= tip_window
)
5977 remove_window_handler (wp
);
5980 if (wp
== tip_window
)
5981 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5982 closed' event. So we reset tip_window here. */
5985 free_frame_menubar (f
);
5987 if (FRAME_FACE_CACHE (f
))
5988 free_frame_faces (f
);
5992 if (FRAME_SIZE_HINTS (f
))
5993 xfree (FRAME_SIZE_HINTS (f
));
5995 xfree (f
->output_data
.mac
);
5996 f
->output_data
.mac
= NULL
;
5998 if (f
== dpyinfo
->x_focus_frame
)
5999 dpyinfo
->x_focus_frame
= 0;
6000 if (f
== dpyinfo
->x_focus_event_frame
)
6001 dpyinfo
->x_focus_event_frame
= 0;
6002 if (f
== dpyinfo
->x_highlight_frame
)
6003 dpyinfo
->x_highlight_frame
= 0;
6005 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6007 dpyinfo
->mouse_face_beg_row
6008 = dpyinfo
->mouse_face_beg_col
= -1;
6009 dpyinfo
->mouse_face_end_row
6010 = dpyinfo
->mouse_face_end_col
= -1;
6011 dpyinfo
->mouse_face_window
= Qnil
;
6012 dpyinfo
->mouse_face_deferred_gc
= 0;
6013 dpyinfo
->mouse_face_mouse_frame
= 0;
6020 /* Destroy the X window of frame F. */
6023 x_destroy_window (f
)
6026 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6028 x_free_frame_resources (f
);
6030 dpyinfo
->reference_count
--;
6034 /* Setting window manager hints. */
6036 /* Set the normal size hints for the window manager, for frame F.
6037 FLAGS is the flags word to use--or 0 meaning preserve the flags
6038 that the window now has.
6039 If USER_POSITION is nonzero, we set the USPosition
6040 flag (this is useful when FLAGS is 0). */
6042 x_wm_set_size_hint (f
, flags
, user_position
)
6047 int base_width
, base_height
, width_inc
, height_inc
;
6048 int min_rows
= 0, min_cols
= 0;
6049 XSizeHints
*size_hints
;
6051 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6052 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6053 width_inc
= FRAME_COLUMN_WIDTH (f
);
6054 height_inc
= FRAME_LINE_HEIGHT (f
);
6056 check_frame_size (f
, &min_rows
, &min_cols
);
6058 size_hints
= FRAME_SIZE_HINTS (f
);
6059 if (size_hints
== NULL
)
6061 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6062 bzero (size_hints
, sizeof (XSizeHints
));
6065 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6066 size_hints
->width_inc
= width_inc
;
6067 size_hints
->height_inc
= height_inc
;
6068 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6069 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6070 size_hints
->base_width
= base_width
;
6071 size_hints
->base_height
= base_height
;
6074 size_hints
->flags
= flags
;
6075 else if (user_position
)
6077 size_hints
->flags
&= ~ PPosition
;
6078 size_hints
->flags
|= USPosition
;
6082 #if 0 /* MAC_TODO: hide application instead of iconify? */
6083 /* Used for IconicState or NormalState */
6086 x_wm_set_window_state (f
, state
)
6090 #ifdef USE_X_TOOLKIT
6093 XtSetArg (al
[0], XtNinitialState
, state
);
6094 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6095 #else /* not USE_X_TOOLKIT */
6096 Window window
= FRAME_X_WINDOW (f
);
6098 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6099 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6101 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6102 #endif /* not USE_X_TOOLKIT */
6106 x_wm_set_icon_pixmap (f
, pixmap_id
)
6112 #ifndef USE_X_TOOLKIT
6113 Window window
= FRAME_X_WINDOW (f
);
6118 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6119 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6123 /* It seems there is no way to turn off use of an icon pixmap.
6124 The following line does it, only if no icon has yet been created,
6125 for some window managers. But with mwm it crashes.
6126 Some people say it should clear the IconPixmapHint bit in this case,
6127 but that doesn't work, and the X consortium said it isn't the
6128 right thing at all. Since there is no way to win,
6129 best to explicitly give up. */
6131 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6137 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6141 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6142 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6145 #else /* not USE_X_TOOLKIT */
6147 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6148 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6150 #endif /* not USE_X_TOOLKIT */
6153 #endif /* MAC_TODO */
6156 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6160 #if 0 /* MAC_TODO: no icons on Mac */
6161 #ifdef USE_X_TOOLKIT
6162 Window window
= XtWindow (f
->output_data
.x
->widget
);
6164 Window window
= FRAME_X_WINDOW (f
);
6167 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6168 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6169 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6171 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6172 #endif /* MAC_TODO */
6176 /***********************************************************************
6178 ***********************************************************************/
6180 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6183 x_get_font_info (f
, font_idx
)
6187 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6190 /* the global font name table */
6191 char **font_name_table
= NULL
;
6192 int font_name_table_size
= 0;
6193 int font_name_count
= 0;
6195 /* Alist linking character set strings to Mac text encoding and Emacs
6197 static Lisp_Object Vmac_charset_info_alist
;
6200 create_text_encoding_info_alist ()
6202 Lisp_Object result
= Qnil
, rest
;
6204 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6206 Lisp_Object charset_info
= XCAR (rest
);
6207 Lisp_Object charset
, coding_system
, text_encoding
;
6208 Lisp_Object existing_info
;
6210 if (!(CONSP (charset_info
)
6211 && STRINGP (charset
= XCAR (charset_info
))
6212 && CONSP (XCDR (charset_info
))
6213 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6214 && CONSP (XCDR (XCDR (charset_info
)))
6215 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6218 existing_info
= assq_no_quit (text_encoding
, result
);
6219 if (NILP (existing_info
))
6220 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6223 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6224 XSETCDR (XCDR (existing_info
),
6225 Fcons (charset
, XCDR (XCDR (existing_info
))));
6233 decode_mac_font_name (name
, size
, coding_system
)
6236 Lisp_Object coding_system
;
6238 struct coding_system coding
;
6241 for (p
= name
; *p
; p
++)
6242 if (!isascii (*p
) || iscntrl (*p
))
6246 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6250 /* MAC_TODO: Fix encoding system... */
6251 setup_coding_system (coding_system
, &coding
);
6252 coding
.src_multibyte
= 0;
6253 coding
.dst_multibyte
= 1;
6254 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6255 coding
.dst_bytes
= MAX_MULTsize
;
6256 coding
.destination
= (char *) alloca (size
);
6257 coding_decode_c_string(&coding
, name
, strlen(name
), qNil
);
6259 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6260 bcopy (buf
, name
, coding
.produced
);
6261 name
[coding
.produced
] = '\0';
6267 mac_to_x_fontname (name
, size
, style
, charset
)
6273 char foundry
[32], family
[32], cs
[32];
6274 char xf
[256], *result
, *p
;
6276 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) == 3)
6280 strcpy(foundry
, "Apple");
6281 strcpy(family
, name
);
6284 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6285 foundry
, family
, style
& bold
? "bold" : "medium",
6286 style
& italic
? 'i' : 'r', size
, size
* 10,
6287 size
? 75 : 0, size
? 75 : 0, size
* 10, charset
);
6289 result
= (char *) xmalloc (strlen (xf
) + 1);
6290 strcpy (result
, xf
);
6291 for (p
= result
; *p
; p
++)
6297 /* Convert an X font spec to the corresponding mac font name, which
6298 can then be passed to GetFNum after conversion to a Pascal string.
6299 For ordinary Mac fonts, this should just be their names, like
6300 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6301 collection contain their charset designation in their names, like
6302 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6303 names are handled accordingly. */
6305 x_font_name_to_mac_font_name (xf
, mf
, mf_decoded
, style
, cs
)
6306 char *xf
, *mf
, *mf_decoded
;
6310 char foundry
[32], family
[32], weight
[20], slant
[2], *p
;
6311 Lisp_Object charset_info
, coding_system
= Qnil
;
6312 struct coding_system coding
;
6316 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6317 foundry
, family
, weight
, slant
, cs
) != 5 &&
6318 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6319 foundry
, family
, weight
, slant
, cs
) != 5)
6323 if (strcmp (weight
, "bold") == 0)
6328 charset_info
= Fassoc (build_string (cs
), Vmac_charset_info_alist
);
6329 if (!NILP (charset_info
))
6331 strcpy (mf_decoded
, family
);
6332 coding_system
= Fcar (Fcdr (Fcdr (charset_info
)));
6335 sprintf (mf_decoded
, "%s-%s-%s", foundry
, family
, cs
);
6337 for (p
= mf_decoded
; *p
; p
++)
6338 if (!isascii (*p
) || iscntrl (*p
))
6342 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6343 strcpy (mf
, mf_decoded
);
6345 /* MAC_TODO: Fix coding system to use objects */
6348 setup_coding_system (coding_system
, &coding
);
6349 coding
.src_multibyte
= 1;
6350 coding
.dst_multibyte
= 1;
6351 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6352 encode_coding (&coding
, mf_decoded
, mf
,
6353 strlen (mf_decoded
), sizeof (Str32
) - 1);
6354 mf
[coding
.produced
] = '\0';
6361 add_font_name_table_entry (char *font_name
)
6363 if (font_name_table_size
== 0)
6365 font_name_table_size
= 16;
6366 font_name_table
= (char **)
6367 xmalloc (font_name_table_size
* sizeof (char *));
6369 else if (font_name_count
+ 1 >= font_name_table_size
)
6371 font_name_table_size
+= 16;
6372 font_name_table
= (char **)
6373 xrealloc (font_name_table
,
6374 font_name_table_size
* sizeof (char *));
6377 font_name_table
[font_name_count
++] = font_name
;
6380 /* Sets up the table font_name_table to contain the list of all fonts
6381 in the system the first time the table is used so that the Resource
6382 Manager need not be accessed every time this information is
6386 init_font_name_table ()
6388 #if TARGET_API_MAC_CARBON
6389 FMFontFamilyIterator ffi
;
6390 FMFontFamilyInstanceIterator ffii
;
6392 Lisp_Object text_encoding_info_alist
;
6393 struct gcpro gcpro1
;
6395 /* Create a dummy instance iterator here to avoid creating and
6396 destroying it in the loop. */
6397 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6399 /* Create an iterator to enumerate the font families. */
6400 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6403 FMDisposeFontFamilyInstanceIterator (&ffii
);
6407 text_encoding_info_alist
= create_text_encoding_info_alist ();
6409 GCPRO1 (text_encoding_info_alist
);
6411 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6417 TextEncoding encoding
;
6418 TextEncodingBase sc
;
6419 Lisp_Object text_encoding_info
;
6421 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6427 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6429 sc
= GetTextEncodingBase (encoding
);
6430 text_encoding_info
= assq_no_quit (make_number (sc
),
6431 text_encoding_info_alist
);
6432 if (!NILP (text_encoding_info
))
6433 decode_mac_font_name (name
, sizeof (name
),
6434 XCAR (XCDR (text_encoding_info
)));
6436 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6437 text_encoding_info_alist
);
6439 /* Point the instance iterator at the current font family. */
6440 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6443 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6446 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6448 for (; !NILP (rest
); rest
= XCDR (rest
))
6450 char *cs
= SDATA (XCAR (rest
));
6454 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6456 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6458 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6460 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6466 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6475 /* Dispose of the iterators. */
6476 FMDisposeFontFamilyIterator (&ffi
);
6477 FMDisposeFontFamilyInstanceIterator (&ffii
);
6478 #else /* !TARGET_API_MAC_CARBON */
6480 SInt16 fontnum
, old_fontnum
;
6481 int num_mac_fonts
= CountResources('FOND');
6483 Handle font_handle
, font_handle_2
;
6484 short id
, scriptcode
;
6487 struct FontAssoc
*fat
;
6488 struct AsscEntry
*assc_entry
;
6489 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
6490 struct gcpro gcpro1
;
6492 GetPort (&port
); /* save the current font number used */
6493 old_fontnum
= port
->txFont
;
6495 text_encoding_info_alist
= create_text_encoding_info_alist ();
6497 GCPRO1 (text_encoding_info_alist
);
6499 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6501 font_handle
= GetIndResource ('FOND', i
);
6505 GetResInfo (font_handle
, &id
, &type
, name
);
6506 GetFNum (name
, &fontnum
);
6512 scriptcode
= FontToScript (fontnum
);
6513 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
6514 text_encoding_info_alist
);
6515 if (!NILP (text_encoding_info
))
6516 decode_mac_font_name (name
, sizeof (name
),
6517 XCAR (XCDR (text_encoding_info
)));
6519 text_encoding_info
= assq_no_quit (make_number (smRoman
),
6520 text_encoding_info_alist
);
6523 HLock (font_handle
);
6525 if (GetResourceSizeOnDisk (font_handle
)
6526 >= sizeof (struct FamRec
))
6528 fat
= (struct FontAssoc
*) (*font_handle
6529 + sizeof (struct FamRec
));
6531 = (struct AsscEntry
*) (*font_handle
6532 + sizeof (struct FamRec
)
6533 + sizeof (struct FontAssoc
));
6535 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6537 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6539 for (; !NILP (rest
); rest
= XCDR (rest
))
6541 char *cs
= SDATA (XCAR (rest
));
6543 add_font_name_table_entry (mac_to_x_fontname (name
,
6544 assc_entry
->fontSize
,
6545 assc_entry
->fontStyle
,
6551 HUnlock (font_handle
);
6552 font_handle_2
= GetNextFOND (font_handle
);
6553 ReleaseResource (font_handle
);
6554 font_handle
= font_handle_2
;
6556 while (ResError () == noErr
&& font_handle
);
6561 TextFont (old_fontnum
);
6562 #endif /* !TARGET_API_MAC_CARBON */
6567 mac_clear_font_name_table ()
6571 for (i
= 0; i
< font_name_count
; i
++)
6572 xfree (font_name_table
[i
]);
6573 xfree (font_name_table
);
6574 font_name_table
= NULL
;
6575 font_name_table_size
= font_name_count
= 0;
6579 enum xlfd_scalable_field_index
6581 XLFD_SCL_PIXEL_SIZE
,
6582 XLFD_SCL_POINT_SIZE
,
6587 static int xlfd_scalable_fields
[] =
6596 mac_c_string_match (regexp
, string
, nonspecial
, exact
)
6598 const char *string
, *nonspecial
;
6603 if (strcmp (string
, nonspecial
) == 0)
6604 return build_string (string
);
6606 else if (strstr (string
, nonspecial
))
6608 Lisp_Object str
= build_string (string
);
6610 if (fast_string_match (regexp
, str
) >= 0)
6618 mac_do_list_fonts (pattern
, maxnames
)
6623 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6624 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6627 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6628 char *longest_start
, *cur_start
, *nonspecial
;
6629 int longest_len
, exact
;
6631 if (font_name_table
== NULL
) /* Initialize when first used. */
6632 init_font_name_table ();
6634 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6637 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6638 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6639 fonts are scaled according to the specified size. */
6642 field
= xlfd_scalable_fields
;
6650 if ('0' <= *ptr
&& *ptr
<= '9')
6652 *val
= *ptr
++ - '0';
6653 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6654 *val
= *val
* 10 + *ptr
++ - '0';
6661 ptr
= strchr (ptr
, '-');
6664 while (ptr
&& i
< 14);
6666 if (i
== 14 && ptr
== NULL
)
6668 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
6669 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
6670 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
6671 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
6673 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
6674 scl_val
[XLFD_SCL_POINT_SIZE
] =
6675 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6676 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
6678 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
6679 scl_val
[XLFD_SCL_AVGWIDTH
] =
6680 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6681 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
6685 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6690 longest_start
= cur_start
= ptr
;
6694 /* Turn pattern into a regexp and do a regexp match. Also find the
6695 longest substring containing no special characters. */
6696 for (; *pattern
; pattern
++)
6698 if (*pattern
== '?' || *pattern
== '*')
6700 if (ptr
- cur_start
> longest_len
)
6702 longest_start
= cur_start
;
6703 longest_len
= ptr
- cur_start
;
6707 if (*pattern
== '?')
6709 else /* if (*pattern == '*') */
6717 *ptr
++ = tolower (*pattern
);
6720 if (ptr
- cur_start
> longest_len
)
6722 longest_start
= cur_start
;
6723 longest_len
= ptr
- cur_start
;
6729 nonspecial
= xmalloc (longest_len
+ 1);
6730 strncpy (nonspecial
, longest_start
, longest_len
);
6731 nonspecial
[longest_len
] = '\0';
6733 pattern_regex
= build_string (regex
);
6735 for (i
= 0; i
< font_name_count
; i
++)
6737 fontname
= mac_c_string_match (pattern_regex
, font_name_table
[i
],
6739 if (!NILP (fontname
))
6741 font_list
= Fcons (fontname
, font_list
);
6742 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6745 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6746 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
6748 int former_len
= ptr
- font_name_table
[i
];
6750 memcpy (scaled
, font_name_table
[i
], former_len
);
6751 sprintf (scaled
+ former_len
,
6752 "-%d-%d-75-75-m-%d-%s",
6753 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6754 scl_val
[XLFD_SCL_POINT_SIZE
],
6755 scl_val
[XLFD_SCL_AVGWIDTH
],
6756 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
6757 fontname
= mac_c_string_match (pattern_regex
, scaled
,
6759 if (!NILP (fontname
))
6761 font_list
= Fcons (fontname
, font_list
);
6762 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6773 /* Return a list of names of available fonts matching PATTERN on frame F.
6775 Frame F null means we have not yet created any frame on Mac, and
6776 consult the first display in x_display_list. MAXNAMES sets a limit
6777 on how many fonts to match. */
6780 x_list_fonts (f
, pattern
, size
, maxnames
)
6782 Lisp_Object pattern
;
6785 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
6786 struct mac_display_info
*dpyinfo
6787 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
6789 xassert (size
<= 0);
6791 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6792 if (NILP (patterns
))
6793 patterns
= Fcons (pattern
, Qnil
);
6795 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
6797 pattern
= XCAR (patterns
);
6799 if (!STRINGP (pattern
))
6802 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
6803 key
= Fcons (pattern
, make_number (maxnames
));
6805 list
= Fassoc (key
, tem
);
6808 list
= Fcdr_safe (list
);
6809 /* We have a cashed list. Don't have to get the list again. */
6814 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6817 /* MAC_TODO: add code for matching outline fonts here */
6819 /* Now store the result in the cache. */
6820 XSETCAR (XCDR (dpyinfo
->name_list_element
),
6821 Fcons (Fcons (key
, list
),
6822 XCAR (XCDR (dpyinfo
->name_list_element
))));
6825 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6834 /* Check that FONT is valid on frame F. It is if it can be found in F's
6838 x_check_font (f
, font
)
6843 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6845 xassert (font
!= NULL
);
6847 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6848 if (dpyinfo
->font_table
[i
].name
6849 && font
== dpyinfo
->font_table
[i
].font
)
6852 xassert (i
< dpyinfo
->n_fonts
);
6855 #endif /* GLYPH_DEBUG != 0 */
6857 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6858 Note: There are (broken) X fonts out there with invalid XFontStruct
6859 min_bounds contents. For example, handa@etl.go.jp reports that
6860 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6861 have font->min_bounds.width == 0. */
6864 x_font_min_bounds (font
, w
, h
)
6865 MacFontStruct
*font
;
6868 *h
= FONT_HEIGHT (font
);
6869 *w
= font
->min_bounds
.width
;
6873 /* Compute the smallest character width and smallest font height over
6874 all fonts available on frame F. Set the members smallest_char_width
6875 and smallest_font_height in F's x_display_info structure to
6876 the values computed. Value is non-zero if smallest_font_height or
6877 smallest_char_width become smaller than they were before. */
6880 x_compute_min_glyph_bounds (f
)
6884 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6885 MacFontStruct
*font
;
6886 int old_width
= dpyinfo
->smallest_char_width
;
6887 int old_height
= dpyinfo
->smallest_font_height
;
6889 dpyinfo
->smallest_font_height
= 100000;
6890 dpyinfo
->smallest_char_width
= 100000;
6892 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6893 if (dpyinfo
->font_table
[i
].name
)
6895 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6898 font
= (MacFontStruct
*) fontp
->font
;
6899 xassert (font
!= (MacFontStruct
*) ~0);
6900 x_font_min_bounds (font
, &w
, &h
);
6902 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6903 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6906 xassert (dpyinfo
->smallest_char_width
> 0
6907 && dpyinfo
->smallest_font_height
> 0);
6909 return (dpyinfo
->n_fonts
== 1
6910 || dpyinfo
->smallest_char_width
< old_width
6911 || dpyinfo
->smallest_font_height
< old_height
);
6915 /* Determine whether given string is a fully-specified XLFD: all 14
6916 fields are present, none is '*'. */
6919 is_fully_specified_xlfd (char *p
)
6927 for (i
= 0; i
< 13; i
++)
6929 q
= strchr (p
+ 1, '-');
6932 if (q
- p
== 2 && *(p
+ 1) == '*')
6937 if (strchr (p
+ 1, '-') != NULL
)
6940 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6947 const int kDefaultFontSize
= 12;
6950 /* XLoadQueryFont creates and returns an internal representation for a
6951 font in a MacFontStruct struct. There is really no concept
6952 corresponding to "loading" a font on the Mac. But we check its
6953 existence and find the font number and all other information for it
6954 and store them in the returned MacFontStruct. */
6956 static MacFontStruct
*
6957 XLoadQueryFont (Display
*dpy
, char *fontname
)
6959 int i
, size
, point_size
, avgwidth
, is_two_byte_font
, char_width
;
6962 SInt16 old_fontnum
, old_fontsize
;
6964 Str32 mfontname
, mfontname_decoded
, charset
;
6967 #if TARGET_API_MAC_CARBON
6968 TextEncoding encoding
;
6973 MacFontStruct
*font
;
6974 FontInfo the_fontinfo
;
6976 UInt32 old_flags
, new_flags
;
6979 if (is_fully_specified_xlfd (fontname
))
6983 Lisp_Object matched_fonts
;
6985 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6986 if (NILP (matched_fonts
))
6988 name
= SDATA (XCAR (matched_fonts
));
6991 GetPort (&port
); /* save the current font number used */
6992 #if TARGET_API_MAC_CARBON
6993 old_fontnum
= GetPortTextFont (port
);
6994 old_fontsize
= GetPortTextSize (port
);
6995 old_fontface
= GetPortTextFace (port
);
6997 old_fontnum
= port
->txFont
;
6998 old_fontsize
= port
->txSize
;
6999 old_fontface
= port
->txFace
;
7002 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size
, &point_size
, &avgwidth
) != 3)
7008 size
= point_size
/ 10;
7009 else if (avgwidth
> 0)
7010 size
= avgwidth
/ 10;
7013 size
= kDefaultFontSize
;
7015 x_font_name_to_mac_font_name (name
, mfontname
, mfontname_decoded
,
7016 &fontface
, charset
);
7018 #if TARGET_API_MAC_CARBON
7019 fontnum
= FMGetFontFamilyFromName (mfontname
);
7020 if (fontnum
== kInvalidFontFamily
7021 || FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7023 scriptcode
= GetTextEncodingBase (encoding
);
7025 GetFNum (mfontname
, &fontnum
);
7028 scriptcode
= FontToScript (fontnum
);
7031 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7033 font
->mac_fontnum
= fontnum
;
7034 font
->mac_fontsize
= size
;
7035 font
->mac_fontface
= fontface
;
7036 font
->mac_scriptcode
= scriptcode
;
7038 /* Apple Japanese (SJIS) font is listed as both
7039 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7040 (Roman script) in init_font_name_table (). The latter should be
7041 treated as a one-byte font. */
7042 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7043 font
->mac_scriptcode
= smRoman
;
7045 font
->full_name
= mac_to_x_fontname (mfontname_decoded
, size
, fontface
, charset
);
7047 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
7048 font
->mac_scriptcode
== smTradChinese
||
7049 font
->mac_scriptcode
== smSimpChinese
||
7050 font
->mac_scriptcode
== smKorean
;
7054 TextFace (fontface
);
7056 GetFontInfo (&the_fontinfo
);
7058 font
->ascent
= the_fontinfo
.ascent
;
7059 font
->descent
= the_fontinfo
.descent
;
7061 font
->min_byte1
= 0;
7062 if (is_two_byte_font
)
7063 font
->max_byte1
= 1;
7065 font
->max_byte1
= 0;
7066 font
->min_char_or_byte2
= 0x20;
7067 font
->max_char_or_byte2
= 0xff;
7069 if (is_two_byte_font
)
7071 /* Use the width of an "ideographic space" of that font because
7072 the_fontinfo.widMax returns the wrong width for some fonts. */
7073 switch (font
->mac_scriptcode
)
7076 char_width
= StringWidth("\p\x81\x40");
7079 char_width
= StringWidth("\p\xa1\x40");
7082 char_width
= StringWidth("\p\xa1\xa1");
7085 char_width
= StringWidth("\p\xa1\xa1");
7090 /* Do this instead of use the_fontinfo.widMax, which incorrectly
7091 returns 15 for 12-point Monaco! */
7092 char_width
= CharWidth ('m');
7094 if (is_two_byte_font
)
7096 font
->per_char
= NULL
;
7098 if (fontface
& italic
)
7099 font
->max_bounds
.rbearing
= char_width
+ 1;
7101 font
->max_bounds
.rbearing
= char_width
;
7102 font
->max_bounds
.lbearing
= 0;
7103 font
->max_bounds
.width
= char_width
;
7104 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7105 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7107 font
->min_bounds
= font
->max_bounds
;
7111 font
->per_char
= (XCharStruct
*)
7112 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7114 int c
, min_width
, max_width
;
7115 Rect char_bounds
, min_bounds
, max_bounds
;
7118 min_width
= max_width
= char_width
;
7119 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
7120 SetRect (&max_bounds
, 0, 0, 0, 0);
7121 for (c
= 0x20; c
<= 0xff; c
++)
7124 char_width
= CharWidth (ch
);
7125 QDTextBounds (1, &ch
, &char_bounds
);
7126 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
7127 char_width
, char_bounds
);
7128 /* Some Japanese fonts (in SJIS encoding) return 0 as the
7129 character width of 0x7f. */
7132 min_width
= min (min_width
, char_width
);
7133 max_width
= max (max_width
, char_width
);
7135 if (!EmptyRect (&char_bounds
))
7137 SetRect (&min_bounds
,
7138 max (min_bounds
.left
, char_bounds
.left
),
7139 max (min_bounds
.top
, char_bounds
.top
),
7140 min (min_bounds
.right
, char_bounds
.right
),
7141 min (min_bounds
.bottom
, char_bounds
.bottom
));
7142 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7145 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7146 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7147 if (min_width
== max_width
7148 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
7150 /* Fixed width and no overhangs. */
7151 xfree (font
->per_char
);
7152 font
->per_char
= NULL
;
7157 TextFont (old_fontnum
); /* restore previous font number, size and face */
7158 TextSize (old_fontsize
);
7159 TextFace (old_fontface
);
7166 mac_unload_font (dpyinfo
, font
)
7167 struct mac_display_info
*dpyinfo
;
7170 xfree (font
->full_name
);
7172 xfree (font
->per_char
);
7177 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7178 pointer to the structure font_info while allocating it dynamically.
7179 If SIZE is 0, load any size of font.
7180 If loading is failed, return NULL. */
7183 x_load_font (f
, fontname
, size
)
7185 register char *fontname
;
7188 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7189 Lisp_Object font_names
;
7191 /* Get a list of all the fonts that match this name. Once we
7192 have a list of matching fonts, we compare them against the fonts
7193 we already have by comparing names. */
7194 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7196 if (!NILP (font_names
))
7201 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7202 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7203 if (dpyinfo
->font_table
[i
].name
7204 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7205 SDATA (XCAR (tail
)))
7206 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7207 SDATA (XCAR (tail
)))))
7208 return (dpyinfo
->font_table
+ i
);
7213 /* Load the font and add it to the table. */
7216 struct MacFontStruct
*font
;
7217 struct font_info
*fontp
;
7218 unsigned long value
;
7221 fontname
= (char *) SDATA (XCAR (font_names
));
7224 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7229 /* Find a free slot in the font table. */
7230 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7231 if (dpyinfo
->font_table
[i
].name
== NULL
)
7234 /* If no free slot found, maybe enlarge the font table. */
7235 if (i
== dpyinfo
->n_fonts
7236 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7239 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7240 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7242 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7245 fontp
= dpyinfo
->font_table
+ i
;
7246 if (i
== dpyinfo
->n_fonts
)
7249 /* Now fill in the slots of *FONTP. */
7251 bzero (fontp
, sizeof (*fontp
));
7253 fontp
->font_idx
= i
;
7254 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7255 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7257 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7259 /* Fixed width font. */
7260 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7267 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7268 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7270 fontp
->space_width
= pcm
->width
;
7272 fontp
->space_width
= FONT_WIDTH (font
);
7276 int width
= pcm
->width
;
7277 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7278 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7279 width
+= pcm
->width
;
7280 fontp
->average_width
= width
/ 95;
7283 fontp
->average_width
= FONT_WIDTH (font
);
7286 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7287 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7289 fontp
->size
= font
->max_bounds
.width
;
7290 fontp
->height
= FONT_HEIGHT (font
);
7292 /* For some font, ascent and descent in max_bounds field is
7293 larger than the above value. */
7294 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7295 if (max_height
> fontp
->height
)
7296 fontp
->height
= max_height
;
7299 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7301 /* MAC_TODO: The script encoding is irrelevant in unicode? */
7302 /* The slot `encoding' specifies how to map a character
7303 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7304 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7305 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7306 2:0xA020..0xFF7F). For the moment, we don't know which charset
7307 uses this font. So, we set information in fontp->encoding[1]
7308 which is never used by any charset. If mapping can't be
7309 decided, set FONT_ENCODING_NOT_DECIDED. */
7310 if (font
->mac_scriptcode
== smJapanese
)
7311 fontp
->encoding
[1] = 4;
7315 = (font
->max_byte1
== 0
7317 ? (font
->min_char_or_byte2
< 0x80
7318 ? (font
->max_char_or_byte2
< 0x80
7319 ? 0 /* 0x20..0x7F */
7320 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
7321 : 1) /* 0xA0..0xFF */
7323 : (font
->min_byte1
< 0x80
7324 ? (font
->max_byte1
< 0x80
7325 ? (font
->min_char_or_byte2
< 0x80
7326 ? (font
->max_char_or_byte2
< 0x80
7327 ? 0 /* 0x2020..0x7F7F */
7328 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
7329 : 3) /* 0x20A0..0x7FFF */
7330 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
7331 : (font
->min_char_or_byte2
< 0x80
7332 ? (font
->max_char_or_byte2
< 0x80
7333 ? 2 /* 0xA020..0xFF7F */
7334 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
7335 : 1))); /* 0xA0A0..0xFFFF */
7338 fontp
->baseline_offset
7339 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
7340 ? (long) value
: 0);
7341 fontp
->relative_compose
7342 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
7343 ? (long) value
: 0);
7344 fontp
->default_ascent
7345 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
7346 ? (long) value
: 0);
7348 fontp
->baseline_offset
= 0;
7349 fontp
->relative_compose
= 0;
7350 fontp
->default_ascent
= 0;
7353 /* Set global flag fonts_changed_p to non-zero if the font loaded
7354 has a character with a smaller width than any other character
7355 before, or if the font loaded has a smalle>r height than any
7356 other font loaded before. If this happens, it will make a
7357 glyph matrix reallocation necessary. */
7358 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
7365 /* Return a pointer to struct font_info of a font named FONTNAME for
7366 frame F. If no such font is loaded, return NULL. */
7369 x_query_font (f
, fontname
)
7371 register char *fontname
;
7373 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7376 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7377 if (dpyinfo
->font_table
[i
].name
7378 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7379 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7380 return (dpyinfo
->font_table
+ i
);
7385 /* Find a CCL program for a font specified by FONTP, and set the member
7386 `encoder' of the structure. */
7389 x_find_ccl_program (fontp
)
7390 struct font_info
*fontp
;
7392 Lisp_Object list
, elt
;
7394 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7398 && STRINGP (XCAR (elt
))
7399 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7405 struct ccl_program
*ccl
7406 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7408 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7411 fontp
->font_encoder
= ccl
;
7417 /* The Mac Event loop code */
7419 #if !TARGET_API_MAC_CARBON
7421 #include <Quickdraw.h>
7422 #include <Balloons.h>
7423 #include <Devices.h>
7425 #include <Gestalt.h>
7427 #include <Processes.h>
7429 #include <ToolUtils.h>
7430 #include <TextUtils.h>
7431 #include <Dialogs.h>
7434 #include <Resources.h>
7439 #endif /* ! TARGET_API_MAC_CARBON */
7444 #define WINDOW_RESOURCE 128
7445 #define TERM_WINDOW_RESOURCE 129
7447 #define DEFAULT_NUM_COLS 80
7449 #define MIN_DOC_SIZE 64
7450 #define MAX_DOC_SIZE 32767
7453 /* sleep time for WaitNextEvent */
7454 #define WNE_SLEEP_AT_SUSPEND 10
7455 #define WNE_SLEEP_AT_RESUME 1
7457 /* the flag appl_is_suspended is used both for determining the sleep
7458 time to be passed to WaitNextEvent and whether the cursor should be
7459 drawn when updating the display. The cursor is turned off when
7460 Emacs is suspended. Redrawing it is unnecessary and what needs to
7461 be done depends on whether the cursor lies inside or outside the
7462 redraw region. So we might as well skip drawing it when Emacs is
7464 static Boolean app_is_suspended
= false;
7465 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7468 #define EXTRA_STACK_ALLOC (256 * 1024)
7470 #define ARGV_STRING_LIST_ID 129
7471 #define ABOUT_ALERT_ID 128
7472 #define RAM_TOO_LARGE_ALERT_ID 129
7474 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7475 Lisp_Object Qreverse
;
7477 /* True if using command key as meta key. */
7478 Lisp_Object Vmac_command_key_is_meta
;
7480 /* Modifier associated with the option key, or nil for normal behavior. */
7481 Lisp_Object Vmac_option_modifier
;
7483 /* True if the ctrl and meta keys should be reversed. */
7484 Lisp_Object Vmac_reverse_ctrl_meta
;
7486 /* True if the option and command modifiers should be used to emulate
7487 a three button mouse */
7488 Lisp_Object Vmac_emulate_three_button_mouse
;
7490 #if USE_CARBON_EVENTS
7491 /* True if the mouse wheel button (i.e. button 4) should map to
7492 mouse-2, instead of mouse-3. */
7493 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7495 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7496 for processing before Emacs sees it. */
7497 Lisp_Object Vmac_pass_command_to_system
;
7499 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7500 for processing before Emacs sees it. */
7501 Lisp_Object Vmac_pass_control_to_system
;
7503 /* Points to the variable `inev' in the function XTread_socket. It is
7504 used for passing an input event to the function back from a Carbon
7506 static struct input_event
*read_socket_inev
= NULL
;
7509 /* Set in term/mac-win.el to indicate that event loop can now generate
7510 drag and drop events. */
7511 Lisp_Object Qmac_ready_for_drag_n_drop
;
7513 Lisp_Object drag_and_drop_file_list
;
7515 Point saved_menu_event_location
;
7518 static void init_required_apple_events (void);
7520 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7522 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7523 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7524 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7526 #if TARGET_API_MAC_CARBON
7528 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7529 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7530 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7531 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7534 static Lisp_Object Qapplication
, Qabout
;
7535 #if USE_CARBON_EVENTS
7537 extern void init_service_handler ();
7538 static Lisp_Object Qpreferences
, Qservices
, Qpaste
, Qperform
;
7540 /* Window Event Handler */
7541 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7544 OSErr
install_window_handler (WindowPtr
);
7546 extern void init_emacs_passwd_dir ();
7547 extern int emacs_main (int, char **, char **);
7549 extern void initialize_applescript();
7550 extern void terminate_applescript();
7553 #if USE_CARBON_EVENTS
7554 mac_to_emacs_modifiers (UInt32 mods
)
7556 mac_to_emacs_modifiers (EventModifiers mods
)
7559 unsigned int result
= 0;
7560 if (mods
& macShiftKey
)
7561 result
|= shift_modifier
;
7562 if (mods
& macCtrlKey
)
7563 result
|= ctrl_modifier
;
7564 if (mods
& macMetaKey
)
7565 result
|= meta_modifier
;
7566 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7567 result
|= alt_modifier
;
7568 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7569 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7571 result
|= XUINT(val
);
7578 mac_get_emulated_btn ( UInt32 modifiers
)
7581 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7582 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7583 if (modifiers
& cmdKey
)
7584 result
= cmdIs3
? 2 : 1;
7585 else if (modifiers
& optionKey
)
7586 result
= cmdIs3
? 1 : 2;
7591 #if USE_CARBON_EVENTS
7592 /* Obtains the event modifiers from the event ref and then calls
7593 mac_to_emacs_modifiers. */
7595 mac_event_to_emacs_modifiers (EventRef eventRef
)
7598 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7599 sizeof (UInt32
), NULL
, &mods
);
7600 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7601 GetEventClass(eventRef
) == kEventClassMouse
)
7603 mods
&= ~(optionKey
| cmdKey
);
7605 return mac_to_emacs_modifiers (mods
);
7608 /* Given an event ref, return the code to use for the mouse button
7609 code in the emacs input_event. */
7611 mac_get_mouse_btn (EventRef ref
)
7613 EventMouseButton result
= kEventMouseButtonPrimary
;
7614 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7615 sizeof (EventMouseButton
), NULL
, &result
);
7618 case kEventMouseButtonPrimary
:
7619 if (NILP (Vmac_emulate_three_button_mouse
))
7623 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7624 sizeof (UInt32
), NULL
, &mods
);
7625 return mac_get_emulated_btn(mods
);
7627 case kEventMouseButtonSecondary
:
7628 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7629 case kEventMouseButtonTertiary
:
7630 case 4: /* 4 is the number for the mouse wheel button */
7631 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7637 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7638 events. However the click of the mouse wheel is not converted to a
7639 mouseDown or mouseUp event. Likewise for dead key down events.
7640 This calls ConvertEventRef, but then checks to see if it is a mouse
7641 up/down, or a dead key down carbon event that has not been
7642 converted, and if so, converts it by hand (to be picked up in the
7643 XTread_socket loop). */
7644 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7646 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7651 switch (GetEventClass (eventRef
))
7653 case kEventClassMouse
:
7654 switch (GetEventKind (eventRef
))
7656 case kEventMouseDown
:
7657 eventRec
->what
= mouseDown
;
7662 eventRec
->what
= mouseUp
;
7671 case kEventClassKeyboard
:
7672 switch (GetEventKind (eventRef
))
7674 case kEventRawKeyDown
:
7676 unsigned char char_codes
;
7679 eventRec
->what
= keyDown
;
7680 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
7681 NULL
, sizeof (char), NULL
, &char_codes
);
7682 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
7683 NULL
, sizeof (UInt32
), NULL
, &key_code
);
7684 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
7700 /* Need where and when. */
7703 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
7704 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
7705 /* Use two step process because new event modifiers are 32-bit
7706 and old are 16-bit. Currently, only loss is NumLock & Fn. */
7707 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
7708 NULL
, sizeof (UInt32
), NULL
, &mods
);
7709 eventRec
->modifiers
= mods
;
7711 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7722 Handle menubar_handle
;
7723 MenuHandle menu_handle
;
7725 menubar_handle
= GetNewMBar (128);
7726 if(menubar_handle
== NULL
)
7728 SetMenuBar (menubar_handle
);
7731 #if !TARGET_API_MAC_CARBON
7732 menu_handle
= GetMenuHandle (M_APPLE
);
7733 if(menu_handle
!= NULL
)
7734 AppendResMenu (menu_handle
,'DRVR');
7742 do_init_managers (void)
7744 #if !TARGET_API_MAC_CARBON
7745 InitGraf (&qd
.thePort
);
7747 FlushEvents (everyEvent
, 0);
7752 #endif /* !TARGET_API_MAC_CARBON */
7755 #if !TARGET_API_MAC_CARBON
7756 /* set up some extra stack space for use by emacs */
7757 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7759 /* MaxApplZone must be called for AppleScript to execute more
7760 complicated scripts */
7763 #endif /* !TARGET_API_MAC_CARBON */
7767 do_check_ram_size (void)
7769 SInt32 physical_ram_size
, logical_ram_size
;
7771 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7772 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7773 || physical_ram_size
> (1 << VALBITS
)
7774 || logical_ram_size
> (1 << VALBITS
))
7776 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7782 do_window_update (WindowPtr win
)
7784 struct frame
*f
= mac_window_to_frame (win
);
7788 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7790 if (win
!= tip_window
)
7792 if (f
->async_visible
== 0)
7794 f
->async_visible
= 1;
7795 f
->async_iconified
= 0;
7796 SET_FRAME_GARBAGED (f
);
7798 /* An update event is equivalent to MapNotify on X, so report
7799 visibility changes properly. */
7800 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7801 /* Force a redisplay sooner or later to update the
7802 frame titles in case this is the second frame. */
7803 record_asynch_buffer_change ();
7809 #if TARGET_API_MAC_CARBON
7811 RgnHandle region
= NewRgn ();
7813 GetPortVisibleRegion (GetWindowPort (win
), region
);
7814 GetRegionBounds (region
, &r
);
7815 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7816 UpdateControls (win
, region
);
7817 DisposeRgn (region
);
7820 r
= (*win
->visRgn
)->rgnBBox
;
7821 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7822 UpdateControls (win
, win
->visRgn
);
7831 is_emacs_window (WindowPtr win
)
7833 Lisp_Object tail
, frame
;
7838 FOR_EACH_FRAME (tail
, frame
)
7839 if (FRAME_MAC_P (XFRAME (frame
)))
7840 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7849 /* Window-activate events will do the job. */
7851 app_is_suspended
= false;
7852 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7859 /* Window-deactivate events will do the job. */
7861 app_is_suspended
= true;
7862 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7868 do_apple_menu (SInt16 menu_item
)
7870 #if !TARGET_API_MAC_CARBON
7872 SInt16 da_driver_refnum
;
7874 if (menu_item
== I_ABOUT
)
7875 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7878 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7879 da_driver_refnum
= OpenDeskAcc (item_name
);
7881 #endif /* !TARGET_API_MAC_CARBON */
7885 do_menu_choice (SInt32 menu_choice
)
7887 SInt16 menu_id
, menu_item
;
7889 menu_id
= HiWord (menu_choice
);
7890 menu_item
= LoWord (menu_choice
);
7898 do_apple_menu (menu_item
);
7903 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
7904 MenuHandle menu
= GetMenuHandle (menu_id
);
7909 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7910 menubar_selection_callback (f
, refcon
);
7919 /* Handle drags in size box. Based on code contributed by Ben
7920 Mesander and IM - Window Manager A. */
7923 do_grow_window (WindowPtr w
, EventRecord
*e
)
7926 int rows
, columns
, width
, height
;
7927 struct frame
*f
= mac_window_to_frame (w
);
7928 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
7929 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
7930 #if TARGET_API_MAC_CARBON
7936 if (size_hints
->flags
& PMinSize
)
7938 min_width
= size_hints
->min_width
;
7939 min_height
= size_hints
->min_height
;
7941 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7943 #if TARGET_API_MAC_CARBON
7944 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
7946 height
= new_rect
.bottom
- new_rect
.top
;
7947 width
= new_rect
.right
- new_rect
.left
;
7949 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7950 /* see if it really changed size */
7953 height
= HiWord (grow_size
);
7954 width
= LoWord (grow_size
);
7957 if (width
!= FRAME_PIXEL_WIDTH (f
)
7958 || height
!= FRAME_PIXEL_HEIGHT (f
))
7960 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7961 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7963 x_set_window_size (f
, 0, columns
, rows
);
7968 /* Handle clicks in zoom box. Calculation of "standard state" based
7969 on code in IM - Window Manager A and code contributed by Ben
7970 Mesander. The standard state of an Emacs window is 80-characters
7971 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7974 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7977 Rect zoom_rect
, port_rect
;
7979 int w_title_height
, columns
, rows
, width
, height
;
7980 struct frame
*f
= mac_window_to_frame (w
);
7981 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7983 #if TARGET_API_MAC_CARBON
7985 Point standard_size
;
7987 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7988 standard_size
.v
= dpyinfo
->height
;
7990 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7991 zoom_in_or_out
= inZoomIn
;
7994 /* Adjust the standard size according to character boundaries. */
7996 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7997 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7998 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7999 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8000 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8001 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8002 && port_rect
.left
== zoom_rect
.left
8003 && port_rect
.top
== zoom_rect
.top
)
8004 zoom_in_or_out
= inZoomIn
;
8006 zoom_in_or_out
= inZoomOut
;
8009 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8011 #else /* not TARGET_API_MAC_CARBON */
8012 GetPort (&save_port
);
8014 SetPortWindowPort (w
);
8016 /* Clear window to avoid flicker. */
8017 EraseRect (&(w
->portRect
));
8018 if (zoom_in_or_out
== inZoomOut
)
8020 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8021 LocalToGlobal (&top_left
);
8023 /* calculate height of window's title bar */
8024 w_title_height
= top_left
.v
- 1
8025 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8027 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8028 zoom_rect
= qd
.screenBits
.bounds
;
8029 zoom_rect
.top
+= w_title_height
;
8030 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8032 zoom_rect
.right
= zoom_rect
.left
8033 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8035 /* Adjust the standard size according to character boundaries. */
8036 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8038 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8040 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8044 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8046 SetPort (save_port
);
8047 #endif /* not TARGET_API_MAC_CARBON */
8049 /* retrieve window size and update application values */
8050 #if TARGET_API_MAC_CARBON
8051 GetWindowPortBounds (w
, &port_rect
);
8053 port_rect
= w
->portRect
;
8055 height
= port_rect
.bottom
- port_rect
.top
;
8056 width
= port_rect
.right
- port_rect
.left
;
8058 if (width
!= FRAME_PIXEL_WIDTH (f
)
8059 || height
!= FRAME_PIXEL_HEIGHT (f
))
8061 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8062 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8064 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8065 SET_FRAME_GARBAGED (f
);
8066 cancel_mouse_face (f
);
8068 FRAME_PIXEL_WIDTH (f
) = width
;
8069 FRAME_PIXEL_HEIGHT (f
) = height
;
8071 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8074 /* Intialize AppleEvent dispatcher table for the required events. */
8076 init_required_apple_events ()
8081 /* Make sure we have apple events before starting. */
8082 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
8086 if (!(result
& (1 << gestaltAppleEventsPresent
)))
8089 #if TARGET_API_MAC_CARBON
8090 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8091 NewAEEventHandlerUPP
8092 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8095 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8096 NewAEEventHandlerProc
8097 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8103 #if TARGET_API_MAC_CARBON
8104 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8105 NewAEEventHandlerUPP
8106 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8109 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8110 NewAEEventHandlerProc
8111 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8117 #if TARGET_API_MAC_CARBON
8118 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8119 NewAEEventHandlerUPP
8120 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8123 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8124 NewAEEventHandlerProc
8125 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8131 #if TARGET_API_MAC_CARBON
8132 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8133 NewAEEventHandlerUPP
8134 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8137 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8138 NewAEEventHandlerProc
8139 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8147 mac_store_application_menu_event (event
)
8148 #if USE_CARBON_EVENTS
8154 struct input_event buf
;
8155 Lisp_Object frame
, entry
;
8159 XSETFRAME (frame
, mac_focus_frame (&one_mac_display_info
));
8160 buf
.kind
= MENU_BAR_EVENT
;
8161 buf
.frame_or_window
= frame
;
8163 kbd_buffer_store_event (&buf
);
8165 buf
.arg
= Qapplication
;
8166 kbd_buffer_store_event (&buf
);
8168 #if USE_CARBON_EVENTS
8169 switch (GetEventClass (event
))
8172 case kEventClassService
:
8173 buf
.arg
= Qservices
;
8174 kbd_buffer_store_event (&buf
);
8175 switch (GetEventKind (event
))
8177 case kEventServicePaste
:
8181 case kEventServicePerform
:
8184 CFStringRef message
;
8186 err
= GetEventParameter (event
, kEventParamServiceMessageName
,
8187 typeCFStringRef
, NULL
,
8188 sizeof (CFStringRef
), NULL
, &message
);
8190 kbd_buffer_store_event (&buf
);
8191 if (err
== noErr
&& message
)
8192 entry
= intern (SDATA (cfstring_to_lisp (message
)));
8202 #endif /* MAC_OSX */
8203 case kEventClassCommand
:
8207 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
,
8208 NULL
, sizeof (HICommand
), NULL
, &command
);
8209 switch (command
.commandID
)
8211 case kHICommandAbout
:
8215 case kHICommandPreferences
:
8216 entry
= Qpreferences
;
8218 #endif /* MAC_OSX */
8219 case kHICommandQuit
:
8231 #else /* USE_CARBON_EVENTS */
8234 case kHICommandAbout
:
8237 case kHICommandQuit
:
8246 kbd_buffer_store_event (&buf
);
8249 #if USE_CARBON_EVENTS
8250 static pascal OSStatus
8251 mac_handle_command_event (next_handler
, event
, data
)
8252 EventHandlerCallRef next_handler
;
8259 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8260 sizeof (HICommand
), NULL
, &command
);
8262 switch (command
.commandID
)
8264 case kHICommandAbout
:
8266 case kHICommandPreferences
:
8267 #endif /* MAC_OSX */
8268 result
= CallNextEventHandler (next_handler
, event
);
8269 if (result
!= eventNotHandledErr
)
8272 mac_store_application_menu_event (event
);
8279 return eventNotHandledErr
;
8283 init_command_handler ()
8286 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8287 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8289 if (handle_command_eventUPP
== NULL
)
8290 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8291 return InstallApplicationEventHandler (handle_command_eventUPP
,
8292 GetEventTypeCount (specs
), specs
,
8296 static pascal OSStatus
8297 mac_handle_window_event (next_handler
, event
, data
)
8298 EventHandlerCallRef next_handler
;
8305 XSizeHints
*size_hints
;
8307 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8308 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8310 switch (GetEventKind (event
))
8312 case kEventWindowUpdate
:
8313 result
= CallNextEventHandler (next_handler
, event
);
8314 if (result
!= eventNotHandledErr
)
8317 do_window_update (wp
);
8320 case kEventWindowBoundsChanging
:
8321 result
= CallNextEventHandler (next_handler
, event
);
8322 if (result
!= eventNotHandledErr
)
8325 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8326 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8327 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8328 if ((attributes
& kWindowBoundsChangeUserResize
)
8329 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8330 == (PResizeInc
| PBaseSize
| PMinSize
)))
8335 GetEventParameter (event
, kEventParamCurrentBounds
,
8337 NULL
, sizeof (Rect
), NULL
, &bounds
);
8338 width
= bounds
.right
- bounds
.left
;
8339 height
= bounds
.bottom
- bounds
.top
;
8341 if (width
< size_hints
->min_width
)
8342 width
= size_hints
->min_width
;
8344 width
= size_hints
->base_width
8345 + (int) ((width
- size_hints
->base_width
)
8346 / (float) size_hints
->width_inc
+ .5)
8347 * size_hints
->width_inc
;
8349 if (height
< size_hints
->min_height
)
8350 height
= size_hints
->min_height
;
8352 height
= size_hints
->base_height
8353 + (int) ((height
- size_hints
->base_height
)
8354 / (float) size_hints
->height_inc
+ .5)
8355 * size_hints
->height_inc
;
8357 bounds
.right
= bounds
.left
+ width
;
8358 bounds
.bottom
= bounds
.top
+ height
;
8359 SetEventParameter (event
, kEventParamCurrentBounds
,
8360 typeQDRectangle
, sizeof (Rect
), &bounds
);
8366 return eventNotHandledErr
;
8369 static pascal OSStatus
8370 mac_handle_mouse_event (next_handler
, event
, data
)
8371 EventHandlerCallRef next_handler
;
8377 switch (GetEventKind (event
))
8379 case kEventMouseWheelMoved
:
8383 EventMouseWheelAxis axis
;
8387 result
= CallNextEventHandler (next_handler
, event
);
8388 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
8391 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
8392 NULL
, sizeof (WindowRef
), NULL
, &wp
);
8393 f
= mac_window_to_frame (wp
);
8394 if (f
!= mac_focus_frame (&one_mac_display_info
))
8397 GetEventParameter (event
, kEventParamMouseWheelAxis
,
8398 typeMouseWheelAxis
, NULL
,
8399 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
8400 if (axis
!= kEventMouseWheelAxisY
)
8403 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
8404 NULL
, sizeof (SInt32
), NULL
, &delta
);
8405 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
8406 NULL
, sizeof (Point
), NULL
, &point
);
8407 read_socket_inev
->kind
= WHEEL_EVENT
;
8408 read_socket_inev
->code
= 0;
8409 read_socket_inev
->modifiers
=
8410 (mac_event_to_emacs_modifiers (event
)
8411 | ((delta
< 0) ? down_modifier
: up_modifier
));
8412 SetPortWindowPort (wp
);
8413 GlobalToLocal (&point
);
8414 XSETINT (read_socket_inev
->x
, point
.h
);
8415 XSETINT (read_socket_inev
->y
, point
.v
);
8416 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
8417 read_socket_inev
->timestamp
=
8418 EventTimeToTicks (GetEventTime (event
)) * (1000/60);
8428 return eventNotHandledErr
;
8430 #endif /* USE_CARBON_EVENTS */
8434 install_window_handler (window
)
8438 #if USE_CARBON_EVENTS
8439 EventTypeSpec specs_window
[] =
8440 {{kEventClassWindow
, kEventWindowUpdate
},
8441 {kEventClassWindow
, kEventWindowBoundsChanging
}};
8442 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
8443 static EventHandlerUPP handle_window_eventUPP
= NULL
;
8444 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
8446 if (handle_window_eventUPP
== NULL
)
8447 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
8448 if (handle_mouse_eventUPP
== NULL
)
8449 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
8450 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
8451 GetEventTypeCount (specs_window
),
8452 specs_window
, NULL
, NULL
);
8454 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
8455 GetEventTypeCount (specs_mouse
),
8456 specs_mouse
, NULL
, NULL
);
8458 #if TARGET_API_MAC_CARBON
8459 if (mac_do_track_dragUPP
== NULL
)
8460 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8461 if (mac_do_receive_dragUPP
== NULL
)
8462 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8465 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8467 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8473 remove_window_handler (window
)
8476 #if TARGET_API_MAC_CARBON
8477 if (mac_do_track_dragUPP
)
8478 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8479 if (mac_do_receive_dragUPP
)
8480 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8484 /* Open Application Apple Event */
8486 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8492 /* Defined in mac.c. */
8494 path_from_vol_dir_name (char *, int, short, long, char *);
8497 /* Called when we receive an AppleEvent with an ID of
8498 "kAEOpenDocuments". This routine gets the direct parameter,
8499 extracts the FSSpecs in it, and puts their names on a list. */
8500 #pragma options align=mac68k
8501 typedef struct SelectionRange
{
8502 short unused1
; // 0 (not used)
8503 short lineNum
; // line to select (<0 to specify range)
8504 long startRange
; // start of selection range (if line < 0)
8505 long endRange
; // end of selection range (if line < 0)
8506 long unused2
; // 0 (not used)
8507 long theDate
; // modification date/time
8509 #pragma options align=reset
8512 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8517 DescType actual_type
;
8519 SelectionRange position
;
8521 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8523 goto descriptor_error_exit
;
8525 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8527 drag_and_drop_file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8528 make_number (position
.startRange
+ 1),
8529 make_number (position
.endRange
+ 1)),
8530 drag_and_drop_file_list
);
8532 /* Check to see that we got all of the required parameters from the
8533 event descriptor. For an 'odoc' event this should just be the
8535 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8536 &actual_type
, (Ptr
) &keyword
,
8537 sizeof (keyword
), &actual_size
);
8538 /* No error means that we found some unused parameters.
8539 errAEDescNotFound means that there are no more parameters. If we
8540 get an error code other than that, flag it. */
8541 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8543 err
= errAEEventNotHandled
;
8548 /* Got all the parameters we need. Now, go through the direct
8549 object list and parse it up. */
8551 long num_files_to_open
;
8553 err
= AECountItems (&the_desc
, &num_files_to_open
);
8558 /* AE file list is one based so just use that for indexing here. */
8559 for (i
= 1; i
<= num_files_to_open
; i
++)
8561 char unix_path_name
[MAXPATHLEN
];
8565 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8566 &actual_type
, &fref
, sizeof (FSRef
),
8568 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8571 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8576 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8577 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8578 if (err
!= noErr
) continue;
8580 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
8581 sizeof (unix_path_name
) - 1) == noErr
)
8583 /* x-dnd functions expect undecoded filenames. */
8584 drag_and_drop_file_list
=
8585 Fcons (make_unibyte_string (unix_path_name
,
8586 strlen (unix_path_name
)),
8587 drag_and_drop_file_list
);
8593 /* Nuke the coerced file list in any case */
8594 err2
= AEDisposeDesc(&the_desc
);
8596 descriptor_error_exit
:
8597 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8602 #if TARGET_API_MAC_CARBON
8604 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8605 void *handlerRefCon
, DragReference theDrag
)
8607 static int can_accept
;
8610 ItemReference theItem
;
8611 FlavorFlags theFlags
;
8614 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8615 return dragNotAcceptedErr
;
8619 case kDragTrackingEnterHandler
:
8620 CountDragItems (theDrag
, &items
);
8622 for (index
= 1; index
<= items
; index
++)
8624 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8625 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8626 if (result
== noErr
)
8634 case kDragTrackingEnterWindow
:
8637 RgnHandle hilite_rgn
= NewRgn ();
8639 struct frame
*f
= mac_window_to_frame (window
);
8641 GetWindowPortBounds (window
, &r
);
8642 OffsetRect (&r
, -r
.left
, -r
.top
);
8643 RectRgn (hilite_rgn
, &r
);
8644 ShowDragHilite (theDrag
, hilite_rgn
, true);
8645 DisposeRgn (hilite_rgn
);
8646 SetThemeCursor (kThemeCopyArrowCursor
);
8650 case kDragTrackingInWindow
:
8653 case kDragTrackingLeaveWindow
:
8656 struct frame
*f
= mac_window_to_frame (window
);
8658 HideDragHilite (theDrag
);
8659 SetThemeCursor (kThemeArrowCursor
);
8663 case kDragTrackingLeaveHandler
:
8671 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8672 DragReference theDrag
)
8676 FlavorFlags theFlags
;
8679 ItemReference theItem
;
8681 Size size
= sizeof (HFSFlavor
);
8683 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8684 return dragNotAcceptedErr
;
8686 drag_and_drop_file_list
= Qnil
;
8687 GetDragMouse (theDrag
, &mouse
, 0L);
8688 CountDragItems (theDrag
, &items
);
8689 for (index
= 1; index
<= items
; index
++)
8691 /* Only handle file references. */
8692 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8693 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8694 if (result
== noErr
)
8699 char unix_path_name
[MAXPATHLEN
];
8701 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8703 /* Use Carbon routines, otherwise it converts the file name
8704 to /Macintosh HD/..., which is not correct. */
8705 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8706 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8708 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
8709 sizeof (unix_path_name
) - 1) == noErr
)
8711 /* x-dnd functions expect undecoded filenames. */
8712 drag_and_drop_file_list
=
8713 Fcons (make_unibyte_string (unix_path_name
,
8714 strlen (unix_path_name
)),
8715 drag_and_drop_file_list
);
8718 /* If there are items in the list, construct an event and post it to
8719 the queue like an interrupt using kbd_buffer_store_event. */
8720 if (!NILP (drag_and_drop_file_list
))
8722 struct input_event event
;
8724 struct frame
*f
= mac_window_to_frame (window
);
8727 GlobalToLocal (&mouse
);
8728 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8730 event
.kind
= DRAG_N_DROP_EVENT
;
8732 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8733 event
.timestamp
= TickCount () * (1000 / 60);
8734 XSETINT (event
.x
, mouse
.h
);
8735 XSETINT (event
.y
, mouse
.v
);
8736 XSETFRAME (frame
, f
);
8737 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8739 /* Post to the interrupt queue */
8740 kbd_buffer_store_event (&event
);
8741 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8743 ProcessSerialNumber psn
;
8744 GetCurrentProcess (&psn
);
8745 SetFrontProcess (&psn
);
8751 return dragNotAcceptedErr
;
8756 /* Print Document Apple Event */
8758 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8760 return errAEEventNotHandled
;
8765 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8767 #if USE_CARBON_EVENTS
8769 EventRef event
= NULL
;
8770 static const HICommand quit_command
= {kEventAttributeNone
, kHICommandQuit
};
8772 err
= CreateEvent (NULL
, kEventClassCommand
, kEventCommandProcess
, 0,
8773 kEventAttributeUserEvent
, &event
);
8775 err
= SetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
8776 sizeof (HICommand
), &quit_command
);
8778 mac_store_application_menu_event (event
);
8780 ReleaseEvent (event
);
8785 return errAEEventNotHandled
;
8787 mac_store_application_menu_event (kHICommandQuit
);
8796 profiler_exit_proc ()
8798 ProfilerDump ("\pEmacs.prof");
8803 /* These few functions implement Emacs as a normal Mac application
8804 (almost): set up the heap and the Toolbox, handle necessary system
8805 events plus a few simple menu events. They also set up Emacs's
8806 access to functions defined in the rest of this file. Emacs uses
8807 function hooks to perform all its terminal I/O. A complete list of
8808 these functions appear in termhooks.h. For what they do, read the
8809 comments there and see also w32term.c and xterm.c. What's
8810 noticeably missing here is the event loop, which is normally
8811 present in most Mac application. After performing the necessary
8812 Mac initializations, main passes off control to emacs_main
8813 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
8814 (defined further below) to read input. This is where
8815 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
8822 #if __profile__ /* is the profiler on? */
8823 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
8828 /* set creator and type for files created by MSL */
8833 do_init_managers ();
8838 do_check_ram_size ();
8841 init_emacs_passwd_dir ();
8845 initialize_applescript ();
8847 init_required_apple_events ();
8853 /* set up argv array from STR# resource */
8854 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
8858 /* free up AppleScript resources on exit */
8859 atexit (terminate_applescript
);
8861 #if __profile__ /* is the profiler on? */
8862 atexit (profiler_exit_proc
);
8865 /* 3rd param "envp" never used in emacs_main */
8866 (void) emacs_main (argc
, argv
, 0);
8869 /* Never reached - real exit in Fkill_emacs */
8874 /* Table for translating Mac keycode to X keysym values. Contributed
8876 Mapping for special keys is now identical to that in Apple X11
8877 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8878 on the right of the Cmd key on laptops, and fn + `enter' (->
8880 static unsigned char keycode_to_xkeysym_table
[] = {
8881 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8882 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8883 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8885 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8886 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8887 /*0x38*/ 0, 0, 0, 0,
8888 /*0x3C*/ 0, 0, 0, 0,
8890 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8891 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8892 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8893 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8895 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8896 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8897 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8898 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8900 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8901 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8902 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8903 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8905 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8906 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8907 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8908 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8912 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8914 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8915 return *xKeySym
!= 0;
8918 #if !USE_CARBON_EVENTS
8919 static RgnHandle mouse_region
= NULL
;
8922 mac_wait_next_event (er
, sleep_time
, dequeue
)
8927 static EventRecord er_buf
= {nullEvent
};
8928 UInt32 target_tick
, current_tick
;
8929 EventMask event_mask
;
8931 if (mouse_region
== NULL
)
8932 mouse_region
= NewRgn ();
8934 event_mask
= everyEvent
;
8935 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8936 event_mask
-= highLevelEventMask
;
8938 current_tick
= TickCount ();
8939 target_tick
= current_tick
+ sleep_time
;
8941 if (er_buf
.what
== nullEvent
)
8942 while (!WaitNextEvent (event_mask
, &er_buf
,
8943 target_tick
- current_tick
, mouse_region
))
8945 current_tick
= TickCount ();
8946 if (target_tick
<= current_tick
)
8952 er_buf
.what
= nullEvent
;
8955 #endif /* not USE_CARBON_EVENTS */
8957 /* Emacs calls this whenever it wants to read an input event from the
8960 XTread_socket (sd
, expected
, hold_quit
)
8962 struct input_event
*hold_quit
;
8964 struct input_event inev
;
8966 #if USE_CARBON_EVENTS
8968 EventTargetRef toolbox_dispatcher
;
8971 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8973 if (interrupt_input_blocked
)
8975 interrupt_input_pending
= 1;
8979 interrupt_input_pending
= 0;
8982 /* So people can tell when we have read the available input. */
8983 input_signal_count
++;
8985 #if USE_CARBON_EVENTS
8986 toolbox_dispatcher
= GetEventDispatcherTarget ();
8988 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8989 kEventRemoveFromQueue
, &eventRef
))
8990 #else /* !USE_CARBON_EVENTS */
8991 while (mac_wait_next_event (&er
, 0, true))
8992 #endif /* !USE_CARBON_EVENTS */
8997 /* It is necessary to set this (additional) argument slot of an
8998 event to nil because keyboard.c protects incompletely
8999 processed event from being garbage collected by placing them
9000 in the kbd_buffer_gcpro vector. */
9002 inev
.kind
= NO_EVENT
;
9005 #if USE_CARBON_EVENTS
9006 /* Handle new events */
9007 if (!mac_convert_event_ref (eventRef
, &er
))
9009 /* There used to be a handler for the kEventMouseWheelMoved
9010 event here. But as of Mac OS X 10.4, this kind of event
9011 is not directly posted to the main event queue by
9012 two-finger scrolling on the trackpad. Instead, some
9013 private event is posted and it is converted to a wheel
9014 event by the default handler for the application target.
9015 The converted one can be received by a Carbon event
9016 handler installed on a window target. */
9017 read_socket_inev
= &inev
;
9018 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9019 read_socket_inev
= NULL
;
9022 #endif /* USE_CARBON_EVENTS */
9028 WindowPtr window_ptr
;
9029 ControlPartCode part_code
;
9032 #if USE_CARBON_EVENTS
9033 /* This is needed to send mouse events like aqua window
9034 buttons to the correct handler. */
9035 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9036 != eventNotHandledErr
)
9040 if (dpyinfo
->grabbed
&& last_mouse_frame
9041 && FRAME_LIVE_P (last_mouse_frame
))
9043 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9044 part_code
= inContent
;
9048 part_code
= FindWindow (er
.where
, &window_ptr
);
9049 if (tip_window
&& window_ptr
== tip_window
)
9051 HideWindow (tip_window
);
9052 part_code
= FindWindow (er
.where
, &window_ptr
);
9056 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
9062 f
= mac_focus_frame (dpyinfo
);
9063 saved_menu_event_location
= er
.where
;
9064 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9065 XSETFRAME (inev
.frame_or_window
, f
);
9069 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9070 SelectWindow (window_ptr
);
9073 ControlPartCode control_part_code
;
9075 Point mouse_loc
= er
.where
;
9077 ControlKind control_kind
;
9080 f
= mac_window_to_frame (window_ptr
);
9081 /* convert to local coordinates of new window */
9082 SetPortWindowPort (window_ptr
);
9084 GlobalToLocal (&mouse_loc
);
9085 #if TARGET_API_MAC_CARBON
9086 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9087 &control_part_code
);
9090 GetControlKind (ch
, &control_kind
);
9093 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9097 #if USE_CARBON_EVENTS
9098 inev
.code
= mac_get_mouse_btn (eventRef
);
9099 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9101 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9102 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9104 XSETINT (inev
.x
, mouse_loc
.h
);
9105 XSETINT (inev
.y
, mouse_loc
.v
);
9106 inev
.timestamp
= er
.when
* (1000 / 60);
9107 /* ticks to milliseconds */
9109 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9111 #ifndef USE_TOOLKIT_SCROLL_BARS
9112 /* control_part_code becomes kControlNoPart if
9113 a progress indicator is clicked. */
9114 && control_part_code
!= kControlNoPart
9115 #else /* USE_TOOLKIT_SCROLL_BARS */
9117 && control_kind
.kind
== kControlKindScrollBar
9118 #endif /* MAC_OSX */
9119 #endif /* USE_TOOLKIT_SCROLL_BARS */
9122 struct scroll_bar
*bar
;
9124 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9126 bar
= tracked_scroll_bar
;
9127 #ifndef USE_TOOLKIT_SCROLL_BARS
9128 control_part_code
= kControlIndicatorPart
;
9132 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9133 #ifdef USE_TOOLKIT_SCROLL_BARS
9134 /* Make the "Ctrl-Mouse-2 splits window" work
9135 for toolkit scroll bars. */
9136 if (er
.modifiers
& controlKey
)
9137 x_scroll_bar_handle_click (bar
, control_part_code
,
9139 else if (er
.what
== mouseDown
)
9140 x_scroll_bar_handle_press (bar
, control_part_code
,
9141 inev
.timestamp
, &inev
);
9143 x_scroll_bar_handle_release (bar
, inev
.timestamp
,
9145 #else /* not USE_TOOLKIT_SCROLL_BARS */
9146 x_scroll_bar_handle_click (bar
, control_part_code
,
9148 if (er
.what
== mouseDown
9149 && control_part_code
== kControlIndicatorPart
)
9150 tracked_scroll_bar
= bar
;
9152 tracked_scroll_bar
= NULL
;
9153 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9158 int x
= mouse_loc
.h
;
9159 int y
= mouse_loc
.v
;
9161 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9162 if (EQ (window
, f
->tool_bar_window
))
9164 if (er
.what
== mouseDown
)
9165 handle_tool_bar_click (f
, x
, y
, 1, 0);
9167 handle_tool_bar_click (f
, x
, y
, 0,
9173 XSETFRAME (inev
.frame_or_window
, f
);
9174 inev
.kind
= MOUSE_CLICK_EVENT
;
9178 if (er
.what
== mouseDown
)
9180 dpyinfo
->grabbed
|= (1 << inev
.code
);
9181 last_mouse_frame
= f
;
9182 /* Ignore any mouse motion that happened
9183 before this event; any subsequent
9184 mouse-movement Emacs events should reflect
9185 only motion after the ButtonPress. */
9190 last_tool_bar_item
= -1;
9194 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9195 /* If a button is released though it was not
9196 previously pressed, that would be because
9197 of multi-button emulation. */
9198 dpyinfo
->grabbed
= 0;
9200 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9203 #ifdef USE_TOOLKIT_SCROLL_BARS
9204 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9209 inev
.modifiers
|= down_modifier
;
9212 inev
.modifiers
|= up_modifier
;
9219 #if TARGET_API_MAC_CARBON
9220 DragWindow (window_ptr
, er
.where
, NULL
);
9221 #else /* not TARGET_API_MAC_CARBON */
9222 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9223 #endif /* not TARGET_API_MAC_CARBON */
9224 /* Update the frame parameters. */
9226 struct frame
*f
= mac_window_to_frame (window_ptr
);
9228 if (f
&& !f
->async_iconified
)
9229 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9234 if (TrackGoAway (window_ptr
, er
.where
))
9236 inev
.kind
= DELETE_WINDOW_EVENT
;
9237 XSETFRAME (inev
.frame_or_window
,
9238 mac_window_to_frame (window_ptr
));
9242 /* window resize handling added --ben */
9244 do_grow_window (window_ptr
, &er
);
9247 /* window zoom handling added --ben */
9250 if (TrackBox (window_ptr
, er
.where
, part_code
))
9251 do_zoom_window (window_ptr
, part_code
);
9261 #if USE_CARBON_EVENTS
9262 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9263 != eventNotHandledErr
)
9266 do_window_update ((WindowPtr
) er
.message
);
9271 #if USE_CARBON_EVENTS
9272 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9273 != eventNotHandledErr
)
9276 switch ((er
.message
>> 24) & 0x000000FF)
9278 case suspendResumeMessage
:
9279 if ((er
.message
& resumeFlag
) == 1)
9285 case mouseMovedMessage
:
9286 #if !USE_CARBON_EVENTS
9287 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9288 er
.where
.h
+ 1, er
.where
.v
+ 1);
9290 previous_help_echo_string
= help_echo_string
;
9291 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
9294 if (dpyinfo
->grabbed
&& last_mouse_frame
9295 && FRAME_LIVE_P (last_mouse_frame
))
9296 f
= last_mouse_frame
;
9298 f
= dpyinfo
->x_focus_frame
;
9300 if (dpyinfo
->mouse_face_hidden
)
9302 dpyinfo
->mouse_face_hidden
= 0;
9303 clear_mouse_face (dpyinfo
);
9308 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9309 Point mouse_pos
= er
.where
;
9311 SetPortWindowPort (wp
);
9313 GlobalToLocal (&mouse_pos
);
9315 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9316 #ifdef USE_TOOLKIT_SCROLL_BARS
9317 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9318 mouse_pos
, er
.when
* (1000 / 60),
9320 #else /* not USE_TOOLKIT_SCROLL_BARS */
9321 x_scroll_bar_note_movement (tracked_scroll_bar
,
9323 - XINT (tracked_scroll_bar
->top
),
9324 er
.when
* (1000 / 60));
9325 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9328 /* Generate SELECT_WINDOW_EVENTs when needed. */
9329 if (mouse_autoselect_window
)
9333 window
= window_from_coordinates (f
,
9338 /* Window will be selected only when it is
9339 not selected now and last mouse movement
9340 event was not in it. Minibuffer window
9341 will be selected iff it is active. */
9342 if (WINDOWP (window
)
9343 && !EQ (window
, last_window
)
9344 && !EQ (window
, selected_window
))
9346 inev
.kind
= SELECT_WINDOW_EVENT
;
9347 inev
.frame_or_window
= window
;
9352 note_mouse_movement (f
, &mouse_pos
);
9356 /* If the contents of the global variable
9357 help_echo_string has changed, generate a
9359 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
9367 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
9369 #if USE_CARBON_EVENTS
9370 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9371 != eventNotHandledErr
)
9374 if (window_ptr
== tip_window
)
9376 HideWindow (tip_window
);
9380 if (!is_emacs_window (window_ptr
))
9383 if ((er
.modifiers
& activeFlag
) != 0)
9385 /* A window has been activated */
9386 Point mouse_loc
= er
.where
;
9388 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9390 SetPortWindowPort (window_ptr
);
9391 GlobalToLocal (&mouse_loc
);
9392 /* Window-activated event counts as mouse movement,
9393 so update things that depend on mouse position. */
9394 note_mouse_movement (mac_window_to_frame (window_ptr
),
9399 /* A window has been deactivated */
9400 #if USE_TOOLKIT_SCROLL_BARS
9401 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9403 struct input_event event
;
9406 event
.kind
= NO_EVENT
;
9407 x_scroll_bar_handle_release (tracked_scroll_bar
,
9408 er
.when
* (1000 / 60),
9410 if (event
.kind
!= NO_EVENT
)
9412 kbd_buffer_store_event_hold (&event
, hold_quit
);
9417 dpyinfo
->grabbed
= 0;
9419 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9421 f
= mac_window_to_frame (window_ptr
);
9422 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9424 /* If we move outside the frame, then we're
9425 certainly no longer on any text in the
9427 clear_mouse_face (dpyinfo
);
9428 dpyinfo
->mouse_face_mouse_frame
= 0;
9431 /* Generate a nil HELP_EVENT to cancel a help-echo.
9432 Do it only if there's something to cancel.
9433 Otherwise, the startup message is cleared when the
9434 mouse leaves the frame. */
9435 if (any_help_event_p
)
9444 int keycode
= (er
.message
& keyCodeMask
) >> 8;
9447 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9448 /* When using Carbon Events, we need to pass raw keyboard
9449 events to the TSM ourselves. If TSM handles it, it
9450 will pass back noErr, otherwise it will pass back
9451 "eventNotHandledErr" and we can process it
9453 if ((!NILP (Vmac_pass_command_to_system
)
9454 || !(er
.modifiers
& cmdKey
))
9455 && (!NILP (Vmac_pass_control_to_system
)
9456 || !(er
.modifiers
& controlKey
))
9457 && (!NILP (Vmac_command_key_is_meta
)
9458 && NILP (Vmac_option_modifier
)
9459 || !(er
.modifiers
& optionKey
)))
9460 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9461 != eventNotHandledErr
)
9466 if (dpyinfo
->x_focus_frame
== NULL
)
9468 /* Beep if keyboard input occurs when all the frames
9476 static SInt16 last_key_script
= -1;
9477 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
9479 if (last_key_script
!= current_key_script
)
9481 struct input_event event
;
9484 event
.kind
= LANGUAGE_CHANGE_EVENT
;
9486 event
.code
= current_key_script
;
9487 kbd_buffer_store_event (&event
);
9490 last_key_script
= current_key_script
;
9495 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
9497 clear_mouse_face (dpyinfo
);
9498 dpyinfo
->mouse_face_hidden
= 1;
9501 if (keycode_to_xkeysym (keycode
, &xkeysym
))
9503 inev
.code
= 0xff00 | xkeysym
;
9504 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
9508 if (er
.modifiers
& (controlKey
|
9509 (NILP (Vmac_command_key_is_meta
) ? optionKey
9512 /* This code comes from Keyboard Resource,
9513 Appendix C of IM - Text. This is necessary
9514 since shift is ignored in KCHR table
9515 translation when option or command is pressed.
9516 It also does not translate correctly
9517 control-shift chars like C-% so mask off shift
9519 int new_modifiers
= er
.modifiers
& 0xe600;
9520 /* mask off option and command */
9521 int new_keycode
= keycode
| new_modifiers
;
9522 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9523 unsigned long some_state
= 0;
9524 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9525 &some_state
) & 0xff;
9527 else if (!NILP (Vmac_option_modifier
)
9528 && (er
.modifiers
& optionKey
))
9530 /* When using the option key as an emacs modifier,
9531 convert the pressed key code back to one
9532 without the Mac option modifier applied. */
9533 int new_modifiers
= er
.modifiers
& ~optionKey
;
9534 int new_keycode
= keycode
| new_modifiers
;
9535 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9536 unsigned long some_state
= 0;
9537 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9538 &some_state
) & 0xff;
9541 inev
.code
= er
.message
& charCodeMask
;
9542 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9546 #if USE_CARBON_EVENTS
9547 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9549 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9551 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
9552 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9555 case kHighLevelEvent
:
9556 drag_and_drop_file_list
= Qnil
;
9558 AEProcessAppleEvent(&er
);
9560 /* Build a DRAG_N_DROP_EVENT type event as is done in
9561 constuct_drag_n_drop in w32term.c. */
9562 if (!NILP (drag_and_drop_file_list
))
9564 struct frame
*f
= mac_focus_frame (dpyinfo
);
9568 inev
.kind
= DRAG_N_DROP_EVENT
;
9570 inev
.timestamp
= er
.when
* (1000 / 60);
9571 /* ticks to milliseconds */
9572 #if USE_CARBON_EVENTS
9573 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9575 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9578 XSETINT (inev
.x
, 0);
9579 XSETINT (inev
.y
, 0);
9581 XSETFRAME (frame
, f
);
9582 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9585 /* Regardless of whether Emacs was suspended or in the
9586 foreground, ask it to redraw its entire screen.
9587 Otherwise parts of the screen can be left in an
9588 inconsistent state. */
9589 wp
= FRAME_MAC_WINDOW (f
);
9591 #if TARGET_API_MAC_CARBON
9595 GetWindowPortBounds (wp
, &r
);
9596 InvalWindowRect (wp
, &r
);
9598 #else /* not TARGET_API_MAC_CARBON */
9599 InvalRect (&(wp
->portRect
));
9600 #endif /* not TARGET_API_MAC_CARBON */
9606 #if USE_CARBON_EVENTS
9607 ReleaseEvent (eventRef
);
9610 if (inev
.kind
!= NO_EVENT
)
9612 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9617 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9622 XSETFRAME (frame
, f
);
9628 any_help_event_p
= 1;
9629 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9630 help_echo_object
, help_echo_pos
);
9634 help_echo_string
= Qnil
;
9635 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9642 /* If the focus was just given to an autoraising frame,
9644 /* ??? This ought to be able to handle more than one such frame. */
9645 if (pending_autoraise_frame
)
9647 x_raise_frame (pending_autoraise_frame
);
9648 pending_autoraise_frame
= 0;
9656 /* Need to override CodeWarrior's input function so no conversion is
9657 done on newlines Otherwise compiled functions in .elc files will be
9658 read incorrectly. Defined in ...:MSL C:MSL
9659 Common:Source:buffer_io.c. */
9662 __convert_to_newlines (unsigned char * p
, size_t * n
)
9668 __convert_from_newlines (unsigned char * p
, size_t * n
)
9676 make_mac_terminal_frame (struct frame
*f
)
9681 XSETFRAME (frame
, f
);
9683 f
->output_method
= output_mac
;
9684 f
->output_data
.mac
= (struct mac_output
*)
9685 xmalloc (sizeof (struct mac_output
));
9686 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9688 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9690 FRAME_COLS (f
) = 96;
9691 FRAME_LINES (f
) = 4;
9693 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9694 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9696 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9698 f
->output_data
.mac
->cursor_pixel
= 0;
9699 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9700 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9701 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9703 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9704 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9705 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9706 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9707 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9708 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9710 FRAME_FONTSET (f
) = -1;
9711 f
->output_data
.mac
->explicit_parent
= 0;
9714 f
->border_width
= 0;
9716 f
->internal_border_width
= 0;
9721 f
->new_text_cols
= 0;
9722 f
->new_text_lines
= 0;
9724 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9725 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9726 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9730 if (!(FRAME_MAC_WINDOW (f
) =
9731 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9732 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9734 /* so that update events can find this mac_output struct */
9735 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9741 /* Need to be initialized for unshow_buffer in window.c. */
9742 selected_window
= f
->selected_window
;
9744 Fmodify_frame_parameters (frame
,
9745 Fcons (Fcons (Qfont
,
9746 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9747 Fmodify_frame_parameters (frame
,
9748 Fcons (Fcons (Qforeground_color
,
9749 build_string ("black")), Qnil
));
9750 Fmodify_frame_parameters (frame
,
9751 Fcons (Fcons (Qbackground_color
,
9752 build_string ("white")), Qnil
));
9757 /***********************************************************************
9759 ***********************************************************************/
9761 int mac_initialized
= 0;
9764 mac_initialize_display_info ()
9766 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9767 GDHandle main_device_handle
;
9769 bzero (dpyinfo
, sizeof (*dpyinfo
));
9772 dpyinfo
->mac_id_name
9773 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9774 + SCHARS (Vsystem_name
)
9776 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9777 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9779 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9780 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9783 main_device_handle
= LMGetMainDevice();
9785 dpyinfo
->reference_count
= 0;
9786 dpyinfo
->resx
= 75.0;
9787 dpyinfo
->resy
= 75.0;
9788 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9790 /* HasDepth returns true if it is possible to have a 32 bit display,
9791 but this may not be what is actually used. Mac OSX can do better.
9792 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9793 header for CGGetActiveDisplayList says that the first display returned
9794 is the active one, so we use that. */
9796 CGDirectDisplayID disp_id
[1];
9797 CGDisplayCount disp_count
;
9798 CGDisplayErr error_code
;
9800 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
9801 if (error_code
!= 0)
9802 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
9804 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
9807 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
9808 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
9809 gdDevType
, dpyinfo
->color_p
))
9812 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
9813 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
9814 dpyinfo
->grabbed
= 0;
9815 dpyinfo
->root_window
= NULL
;
9816 dpyinfo
->image_cache
= make_image_cache ();
9818 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9819 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9820 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9821 dpyinfo
->mouse_face_window
= Qnil
;
9822 dpyinfo
->mouse_face_overlay
= Qnil
;
9823 dpyinfo
->mouse_face_hidden
= 0;
9828 mac_make_rdb (xrm_option
)
9831 XrmDatabase database
;
9833 database
= xrm_get_preference_database (NULL
);
9835 xrm_merge_string_database (database
, xrm_option
);
9840 struct mac_display_info
*
9841 mac_term_init (display_name
, xrm_option
, resource_name
)
9842 Lisp_Object display_name
;
9844 char *resource_name
;
9846 struct mac_display_info
*dpyinfo
;
9850 if (!mac_initialized
)
9853 mac_initialized
= 1;
9857 error ("Sorry, this version can only handle one display");
9859 mac_initialize_display_info ();
9861 dpyinfo
= &one_mac_display_info
;
9863 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
9865 /* Put this display on the chain. */
9866 dpyinfo
->next
= x_display_list
;
9867 x_display_list
= dpyinfo
;
9869 /* Put it on x_display_name_list. */
9870 x_display_name_list
= Fcons (Fcons (display_name
,
9871 Fcons (Qnil
, dpyinfo
->xrdb
)),
9872 x_display_name_list
);
9873 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9879 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9882 x_delete_display (dpyinfo
)
9883 struct mac_display_info
*dpyinfo
;
9887 /* Discard this display from x_display_name_list and x_display_list.
9888 We can't use Fdelq because that can quit. */
9889 if (! NILP (x_display_name_list
)
9890 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9891 x_display_name_list
= XCDR (x_display_name_list
);
9896 tail
= x_display_name_list
;
9897 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9899 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9901 XSETCDR (tail
, XCDR (XCDR (tail
)));
9908 if (x_display_list
== dpyinfo
)
9909 x_display_list
= dpyinfo
->next
;
9912 struct x_display_info
*tail
;
9914 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9915 if (tail
->next
== dpyinfo
)
9916 tail
->next
= tail
->next
->next
;
9919 /* Free the font names in the font table. */
9920 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9921 if (dpyinfo
->font_table
[i
].name
)
9923 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9924 xfree (dpyinfo
->font_table
[i
].full_name
);
9925 xfree (dpyinfo
->font_table
[i
].name
);
9928 if (dpyinfo
->font_table
->font_encoder
)
9929 xfree (dpyinfo
->font_table
->font_encoder
);
9931 xfree (dpyinfo
->font_table
);
9932 xfree (dpyinfo
->mac_id_name
);
9934 if (x_display_list
== 0)
9936 mac_clear_font_name_table ();
9937 bzero (dpyinfo
, sizeof (*dpyinfo
));
9946 extern int inhibit_window_system
;
9947 extern int noninteractive
;
9948 CFBundleRef appsBundle
;
9951 /* No need to test if already -nw*/
9952 if (inhibit_window_system
|| noninteractive
)
9955 appsBundle
= CFBundleGetMainBundle();
9956 if (appsBundle
!= NULL
)
9958 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
9959 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
9960 /* We found the bundle identifier, now we know we are valid. */
9967 /* MAC_TODO: Have this start the bundled executable */
9969 /* For now, prevent the fatal error by bringing it up in the terminal */
9970 inhibit_window_system
= 1;
9974 MakeMeTheFrontProcess ()
9976 ProcessSerialNumber psn
;
9979 err
= GetCurrentProcess (&psn
);
9981 (void) SetFrontProcess (&psn
);
9984 /***** Code to handle C-g testing *****/
9986 /* Contains the Mac modifier formed from quit_char */
9987 int mac_quit_char_modifiers
= 0;
9988 int mac_quit_char_keycode
;
9989 extern int quit_char
;
9992 mac_determine_quit_char_modifiers()
9994 /* Todo: Determine modifiers from quit_char. */
9995 UInt32 qc_modifiers
= ctrl_modifier
;
9998 mac_quit_char_modifiers
= 0;
9999 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
10000 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
10001 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
10002 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
10006 init_quit_char_handler ()
10008 /* TODO: Let this support keys other the 'g' */
10009 mac_quit_char_keycode
= 5;
10010 /* Look at <architecture/adb_kb_map.h> for details */
10011 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10013 mac_determine_quit_char_modifiers();
10017 quit_char_comp (EventRef inEvent
, void *inCompData
)
10019 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
10021 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
10025 UInt32 keyModifiers
;
10026 GetEventParameter(inEvent
, kEventParamKeyCode
,
10027 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
10028 if (keyCode
!= mac_quit_char_keycode
)
10030 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
10031 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
10032 if (keyModifiers
!= mac_quit_char_modifiers
)
10039 mac_check_for_quit_char ()
10042 static EMACS_TIME last_check_time
= { 0, 0 };
10043 static EMACS_TIME one_second
= { 1, 0 };
10046 /* If windows are not initialized, return immediately (keep it bouncin'). */
10047 if (!mac_quit_char_modifiers
)
10050 /* Don't check if last check is less than a second ago. */
10051 EMACS_GET_TIME (now
);
10052 EMACS_SUB_TIME (t
, now
, last_check_time
);
10053 if (EMACS_TIME_LT (t
, one_second
))
10055 last_check_time
= now
;
10057 /* Redetermine modifiers because they are based on lisp variables */
10058 mac_determine_quit_char_modifiers ();
10060 /* Fill the queue with events */
10062 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
10063 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
10068 struct input_event e
;
10070 /* Use an input_event to emulate what the interrupt handler does. */
10072 e
.kind
= ASCII_KEYSTROKE_EVENT
;
10073 e
.code
= quit_char
;
10075 e
.modifiers
= NULL
;
10076 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
10077 XSETFRAME (e
.frame_or_window
, mac_focus_frame (&one_mac_display_info
));
10078 /* Remove event from queue to prevent looping. */
10079 RemoveEventFromQueue (GetMainEventQueue (), event
);
10080 ReleaseEvent (event
);
10081 kbd_buffer_store_event (&e
);
10084 #endif /* MAC_OSX */
10092 MenuItemIndex menu_index
;
10094 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10095 &menu
, &menu_index
);
10097 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10098 #if USE_CARBON_EVENTS
10099 EnableMenuCommand (NULL
, kHICommandPreferences
);
10100 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10101 &menu
, &menu_index
);
10104 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10105 InsertMenuItemTextWithCFString (menu
, NULL
,
10106 0, kMenuItemAttrSeparator
, 0);
10107 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10108 0, 0, kHICommandAbout
);
10110 #endif /* USE_CARBON_EVENTS */
10111 #else /* !MAC_OSX */
10112 #if USE_CARBON_EVENTS
10113 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10119 /* Set up use of X before we make the first connection. */
10121 extern frame_parm_handler mac_frame_parm_handlers
[];
10123 static struct redisplay_interface x_redisplay_interface
=
10125 mac_frame_parm_handlers
,
10129 x_clear_end_of_line
,
10131 x_after_update_window_line
,
10132 x_update_window_begin
,
10133 x_update_window_end
,
10136 0, /* flush_display_optional */
10137 x_clear_window_mouse_face
,
10138 x_get_glyph_overhangs
,
10139 x_fix_overlapping_area
,
10140 x_draw_fringe_bitmap
,
10141 0, /* define_fringe_bitmap */
10142 0, /* destroy_fringe_bitmap */
10143 mac_per_char_metric
,
10145 mac_compute_glyph_string_overhangs
,
10146 x_draw_glyph_string
,
10147 mac_define_frame_cursor
,
10148 mac_clear_frame_area
,
10149 mac_draw_window_cursor
,
10150 mac_draw_vertical_window_border
,
10151 mac_shift_glyphs_for_insert
10157 rif
= &x_redisplay_interface
;
10159 clear_frame_hook
= x_clear_frame
;
10160 ins_del_lines_hook
= x_ins_del_lines
;
10161 delete_glyphs_hook
= x_delete_glyphs
;
10162 ring_bell_hook
= XTring_bell
;
10163 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10164 set_terminal_modes_hook
= XTset_terminal_modes
;
10165 update_begin_hook
= x_update_begin
;
10166 update_end_hook
= x_update_end
;
10167 set_terminal_window_hook
= XTset_terminal_window
;
10168 read_socket_hook
= XTread_socket
;
10169 frame_up_to_date_hook
= XTframe_up_to_date
;
10170 mouse_position_hook
= XTmouse_position
;
10171 frame_rehighlight_hook
= XTframe_rehighlight
;
10172 frame_raise_lower_hook
= XTframe_raise_lower
;
10174 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10175 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10176 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10177 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10179 scroll_region_ok
= 1; /* we'll scroll partial frames */
10180 char_ins_del_ok
= 1;
10181 line_ins_del_ok
= 1; /* we'll just blt 'em */
10182 fast_clear_end_of_line
= 1; /* X does this well */
10183 memory_below_frame
= 0; /* we don't remember what scrolls
10188 last_tool_bar_item
= -1;
10189 any_help_event_p
= 0;
10191 /* Try to use interrupt input; if we can't, then start polling. */
10192 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10196 #if TARGET_API_MAC_CARBON
10197 init_required_apple_events ();
10199 #if USE_CARBON_EVENTS
10201 init_service_handler ();
10203 init_quit_char_handler ();
10204 #endif /* MAC_OSX */
10206 init_command_handler ();
10209 #endif /* USE_CARBON_EVENTS */
10212 if (!inhibit_window_system
)
10213 MakeMeTheFrontProcess ();
10224 staticpro (&x_error_message_string
);
10225 x_error_message_string
= Qnil
;
10228 Qmodifier_value
= intern ("modifier-value");
10229 Qalt
= intern ("alt");
10230 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10231 Qhyper
= intern ("hyper");
10232 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10233 Qsuper
= intern ("super");
10234 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10236 Qapplication
= intern ("application"); staticpro (&Qapplication
);
10237 Qabout
= intern ("about"); staticpro (&Qabout
);
10239 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10240 Qpreferences
= intern ("preferences"); staticpro (&Qpreferences
);
10241 Qservices
= intern ("services"); staticpro (&Qservices
);
10242 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10243 Qperform
= intern ("perform"); staticpro (&Qperform
);
10247 Fprovide (intern ("mac-carbon"), Qnil
);
10250 staticpro (&Qreverse
);
10251 Qreverse
= intern ("reverse");
10253 staticpro (&x_display_name_list
);
10254 x_display_name_list
= Qnil
;
10256 staticpro (&last_mouse_scroll_bar
);
10257 last_mouse_scroll_bar
= Qnil
;
10259 staticpro (&Qvendor_specific_keysyms
);
10260 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
10262 staticpro (&last_mouse_press_frame
);
10263 last_mouse_press_frame
= Qnil
;
10265 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
10266 staticpro (&Qmac_ready_for_drag_n_drop
);
10268 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10269 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10270 #ifdef USE_TOOLKIT_SCROLL_BARS
10271 Vx_toolkit_scroll_bars
= Qt
;
10273 Vx_toolkit_scroll_bars
= Qnil
;
10276 DEFVAR_BOOL ("x-use-underline-position-properties",
10277 &x_use_underline_position_properties
,
10278 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10279 nil means ignore them. If you encounter fonts with bogus
10280 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10281 to 4.1, set this to nil. */);
10282 x_use_underline_position_properties
= 0;
10284 staticpro (&last_mouse_motion_frame
);
10285 last_mouse_motion_frame
= Qnil
;
10287 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
10288 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
10289 Otherwise the option key is used. */);
10290 Vmac_command_key_is_meta
= Qt
;
10292 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10293 doc
: /* Modifier to use for the Mac alt/option key. The value can
10294 be alt, hyper, or super for the respective modifier. If the value is
10295 nil then the key will act as the normal Mac option modifier. */);
10296 Vmac_option_modifier
= Qnil
;
10298 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
10299 doc
: /* Non-nil means that the control and meta keys are reversed. This is
10300 useful for non-standard keyboard layouts. */);
10301 Vmac_reverse_ctrl_meta
= Qnil
;
10303 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10304 &Vmac_emulate_three_button_mouse
,
10305 doc
: /* t means that when the option-key is held down while pressing the
10306 mouse button, the click will register as mouse-2 and while the
10307 command-key is held down, the click will register as mouse-3.
10308 'reverse means that the the option-key will register for mouse-3
10309 and the command-key will register for mouse-2. nil means that
10310 no emulation should be done and the modifiers should be placed
10311 on the mouse-1 event. */);
10312 Vmac_emulate_three_button_mouse
= Qnil
;
10314 #if USE_CARBON_EVENTS
10315 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
10316 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
10317 the right click will be mouse-3.
10318 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10319 Vmac_wheel_button_is_mouse_2
= Qt
;
10321 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
10322 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10323 Toolbox for processing before Emacs sees it. */);
10324 Vmac_pass_command_to_system
= Qt
;
10326 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
10327 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10328 Toolbox for processing before Emacs sees it. */);
10329 Vmac_pass_control_to_system
= Qt
;
10333 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
10334 doc
: /* If non-nil, allow anti-aliasing.
10335 The text will be rendered using Core Graphics text rendering which
10336 may anti-alias the text. */);
10337 Vmac_use_core_graphics
= Qnil
;
10339 /* Register an entry for `mac-roman' so that it can be used when
10340 creating the terminal frame on Mac OS 9 before loading
10341 term/mac-win.elc. */
10342 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10343 doc
: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10344 Each entry should be of the form:
10346 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10348 where CHARSET-NAME is a string used in font names to identify the
10349 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10350 is a coding system corresponding to TEXT-ENCODING. */);
10351 Vmac_charset_info_alist
=
10352 Fcons (list3 (build_string ("mac-roman"),
10353 make_number (smRoman
), Qnil
), Qnil
);
10356 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10357 (do not change this comment) */