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"
89 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
90 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
91 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
92 #define macShiftKey (shiftKey)
93 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
94 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
96 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
98 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
101 /* Non-nil means Emacs uses toolkit scroll bars. */
103 Lisp_Object Vx_toolkit_scroll_bars
;
105 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
106 Lisp_Object Vmac_use_core_graphics
;
109 /* Non-zero means that a HELP_EVENT has been generated since Emacs
112 static int any_help_event_p
;
114 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
115 static Lisp_Object last_window
;
117 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
119 int x_use_underline_position_properties
;
121 /* Non-zero means draw block and hollow cursor as wide as the glyph
122 under it. For example, if a block cursor is over a tab, it will be
123 drawn as wide as that tab on the display. */
126 /* This is a chain of structures for all the X displays currently in
129 struct x_display_info
*x_display_list
;
131 /* This is a list of cons cells, each of the form (NAME
132 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
133 x_display_list and in the same order. NAME is the name of the
134 frame. FONT-LIST-CACHE records previous values returned by
135 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
136 equivalent, which is implemented with a Lisp object, for the
139 Lisp_Object x_display_name_list
;
141 /* This is display since Mac does not support multiple ones. */
142 struct mac_display_info one_mac_display_info
;
144 /* Frame being updated by update_frame. This is declared in term.c.
145 This is set by update_begin and looked at by all the XT functions.
146 It is zero while not inside an update. In that case, the XT
147 functions assume that `selected_frame' is the frame to apply to. */
149 extern struct frame
*updating_frame
;
151 extern int waiting_for_input
;
153 /* This is a frame waiting to be auto-raised, within XTread_socket. */
155 struct frame
*pending_autoraise_frame
;
159 Formerly, we used PointerMotionHintMask (in standard_event_mask)
160 so that we would have to call XQueryPointer after each MotionNotify
161 event to ask for another such event. However, this made mouse tracking
162 slow, and there was a bug that made it eventually stop.
164 Simply asking for MotionNotify all the time seems to work better.
166 In order to avoid asking for motion events and then throwing most
167 of them away or busy-polling the server for mouse positions, we ask
168 the server for pointer motion hints. This means that we get only
169 one event per group of mouse movements. "Groups" are delimited by
170 other kinds of events (focus changes and button clicks, for
171 example), or by XQueryPointer calls; when one of these happens, we
172 get another MotionNotify event the next time the mouse moves. This
173 is at least as efficient as getting motion events when mouse
174 tracking is on, and I suspect only negligibly worse when tracking
177 /* Where the mouse was last time we reported a mouse event. */
179 static Rect last_mouse_glyph
;
180 static Lisp_Object last_mouse_press_frame
;
182 /* The scroll bar in which the last X motion event occurred.
184 If the last X motion event occurred in a scroll bar, we set this so
185 XTmouse_position can know whether to report a scroll bar motion or
188 If the last X motion event didn't occur in a scroll bar, we set
189 this to Qnil, to tell XTmouse_position to return an ordinary motion
192 static Lisp_Object last_mouse_scroll_bar
;
194 /* This is a hack. We would really prefer that XTmouse_position would
195 return the time associated with the position it returns, but there
196 doesn't seem to be any way to wrest the time-stamp from the server
197 along with the position query. So, we just keep track of the time
198 of the last movement we received, and return that in hopes that
199 it's somewhat accurate. */
201 static Time last_mouse_movement_time
;
203 struct scroll_bar
*tracked_scroll_bar
= NULL
;
205 /* Incremented by XTread_socket whenever it really tries to read
209 static int volatile input_signal_count
;
211 static int input_signal_count
;
214 /* Used locally within XTread_socket. */
216 static int x_noop_count
;
218 /* Initial values of argv and argc. */
220 extern char **initial_argv
;
221 extern int initial_argc
;
223 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
225 /* Tells if a window manager is present or not. */
227 extern Lisp_Object Vx_no_window_manager
;
231 /* A mask of extra modifier bits to put into every keyboard char. */
233 extern int extra_keyboard_modifiers
;
235 /* The keysyms to use for the various modifiers. */
237 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qmodifier_value
;
239 static Lisp_Object Qvendor_specific_keysyms
;
242 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
245 extern int inhibit_window_system
;
247 #if __MRC__ && !TARGET_API_MAC_CARBON
248 QDGlobals qd
; /* QuickDraw global information structure. */
252 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
253 struct mac_display_info
*mac_display_info_for_display (Display
*);
254 static void x_update_window_end
P_ ((struct window
*, int, int));
255 static int x_io_error_quitter
P_ ((Display
*));
256 int x_catch_errors
P_ ((Display
*));
257 void x_uncatch_errors
P_ ((Display
*, int));
258 void x_lower_frame
P_ ((struct frame
*));
259 void x_scroll_bar_clear
P_ ((struct frame
*));
260 int x_had_errors_p
P_ ((Display
*));
261 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
262 void x_raise_frame
P_ ((struct frame
*));
263 void x_set_window_size
P_ ((struct frame
*, int, int, int));
264 void x_wm_set_window_state
P_ ((struct frame
*, int));
265 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
266 void mac_initialize
P_ ((void));
267 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
268 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
269 static void x_update_end
P_ ((struct frame
*));
270 static void XTframe_up_to_date
P_ ((struct frame
*));
271 static void XTset_terminal_modes
P_ ((void));
272 static void XTreset_terminal_modes
P_ ((void));
273 static void x_clear_frame
P_ ((void));
274 static void frame_highlight
P_ ((struct frame
*));
275 static void frame_unhighlight
P_ ((struct frame
*));
276 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
277 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
278 struct frame
*, struct input_event
*));
279 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
280 EventRecord
*, struct input_event
*));
281 static void XTframe_rehighlight
P_ ((struct frame
*));
282 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
283 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
284 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
285 enum text_cursor_kinds
));
287 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
288 static void x_flush
P_ ((struct frame
*f
));
289 static void x_update_begin
P_ ((struct frame
*));
290 static void x_update_window_begin
P_ ((struct window
*));
291 static void x_after_update_window_line
P_ ((struct glyph_row
*));
293 static int is_emacs_window (WindowPtr
);
295 int x_bitmap_icon (struct frame
*, Lisp_Object
);
296 void x_make_frame_visible (struct frame
*);
298 extern void window_scroll (Lisp_Object
, int, int, int);
300 /* Defined in macmenu.h. */
301 extern void menubar_selection_callback (FRAME_PTR
, int);
302 extern void set_frame_menubar (FRAME_PTR
, int, int);
304 /* X display function emulation */
307 XFreePixmap (display
, pixmap
)
308 Display
*display
; /* not used */
311 DisposeGWorld (pixmap
);
315 /* Set foreground color for subsequent QuickDraw commands. Assume
316 graphic port has already been set. */
319 mac_set_forecolor (unsigned long color
)
323 fg_color
.red
= RED16_FROM_ULONG (color
);
324 fg_color
.green
= GREEN16_FROM_ULONG (color
);
325 fg_color
.blue
= BLUE16_FROM_ULONG (color
);
327 RGBForeColor (&fg_color
);
331 /* Set background color for subsequent QuickDraw commands. Assume
332 graphic port has already been set. */
335 mac_set_backcolor (unsigned long color
)
339 bg_color
.red
= RED16_FROM_ULONG (color
);
340 bg_color
.green
= GREEN16_FROM_ULONG (color
);
341 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
343 RGBBackColor (&bg_color
);
346 /* Set foreground and background color for subsequent QuickDraw
347 commands. Assume that the graphic port has already been set. */
350 mac_set_colors (gc
, bg_save
)
355 GetBackColor (bg_save
);
356 mac_set_forecolor (gc
->foreground
);
357 mac_set_backcolor (gc
->background
);
360 /* Mac version of XDrawLine. */
363 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
371 SetPortWindowPort (w
);
373 mac_set_colors (gc
, &old_bg
);
378 RGBBackColor (&old_bg
);
382 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
391 GetGWorld (&old_port
, &old_gdh
);
394 mac_set_colors (gc
, NULL
);
396 LockPixels (GetGWorldPixMap (p
));
399 UnlockPixels (GetGWorldPixMap (p
));
401 SetGWorld (old_port
, old_gdh
);
404 /* Mac version of XClearArea. */
407 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
411 unsigned int width
, height
;
414 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
419 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
420 xgc
.background
= mwp
->x_compatible
.background_pixel
;
422 SetPortWindowPort (w
);
424 mac_set_colors (&xgc
, &old_bg
);
425 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
429 RGBBackColor (&old_bg
);
432 /* Mac version of XClearWindow. */
435 XClearWindow (display
, w
)
439 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
442 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
443 xgc
.background
= mwp
->x_compatible
.background_pixel
;
445 SetPortWindowPort (w
);
447 mac_set_colors (&xgc
, NULL
);
449 #if TARGET_API_MAC_CARBON
453 GetWindowPortBounds (w
, &r
);
456 #else /* not TARGET_API_MAC_CARBON */
457 EraseRect (&(w
->portRect
));
458 #endif /* not TARGET_API_MAC_CARBON */
462 /* Mac replacement for XCopyArea. */
465 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
469 int x
, y
, width
, height
;
470 unsigned short *bits
;
477 bitmap
.rowBytes
= sizeof(unsigned short);
478 bitmap
.baseAddr
= (char *)bits
;
479 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
481 SetPortWindowPort (w
);
483 mac_set_colors (gc
, &old_bg
);
484 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
486 #if TARGET_API_MAC_CARBON
487 LockPortBits (GetWindowPort (w
));
488 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
489 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
490 UnlockPortBits (GetWindowPort (w
));
491 #else /* not TARGET_API_MAC_CARBON */
492 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
493 overlay_p
? srcOr
: srcCopy
, 0);
494 #endif /* not TARGET_API_MAC_CARBON */
496 RGBBackColor (&old_bg
);
500 /* Mac replacement for XSetClipRectangles. */
503 mac_set_clip_rectangle (display
, w
, r
)
508 SetPortWindowPort (w
);
514 /* Mac replacement for XSetClipMask. */
517 mac_reset_clipping (display
, w
)
523 SetPortWindowPort (w
);
525 SetRect (&r
, -32767, -32767, 32767, 32767);
530 /* Mac replacement for XCreateBitmapFromBitmapData. */
533 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
538 static unsigned char swap_nibble
[16]
539 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
540 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
541 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
542 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
546 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
547 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
548 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
549 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
550 for (i
= 0; i
< h
; i
++)
552 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
553 for (j
= 0; j
< w1
; j
++)
555 /* Bitswap XBM bytes to match how Mac does things. */
556 unsigned char c
= *bits
++;
557 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
558 | (swap_nibble
[(c
>>4) & 0xf]));;
562 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
567 mac_free_bitmap (bitmap
)
570 xfree (bitmap
->baseAddr
);
575 XCreatePixmap (display
, w
, width
, height
, depth
)
576 Display
*display
; /* not used */
578 unsigned int width
, height
;
585 SetPortWindowPort (w
);
587 SetRect (&r
, 0, 0, width
, height
);
588 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
596 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
597 Display
*display
; /* not used */
600 unsigned int width
, height
;
601 unsigned long fg
, bg
;
602 unsigned int depth
; /* not used */
609 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
613 GetGWorld (&old_port
, &old_gdh
);
614 SetGWorld (pixmap
, NULL
);
615 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
616 mac_set_forecolor (fg
);
617 mac_set_backcolor (bg
);
618 LockPixels (GetGWorldPixMap (pixmap
));
619 #if TARGET_API_MAC_CARBON
620 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
621 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
622 #else /* not TARGET_API_MAC_CARBON */
623 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
624 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
625 #endif /* not TARGET_API_MAC_CARBON */
626 UnlockPixels (GetGWorldPixMap (pixmap
));
627 SetGWorld (old_port
, old_gdh
);
628 mac_free_bitmap (&bitmap
);
634 /* Mac replacement for XFillRectangle. */
637 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
642 unsigned int width
, height
;
647 SetPortWindowPort (w
);
649 mac_set_colors (gc
, &old_bg
);
650 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
652 PaintRect (&r
); /* using foreground color of gc */
654 RGBBackColor (&old_bg
);
658 #if 0 /* TODO: figure out if we need to do this on Mac. */
660 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
665 unsigned int width
, height
;
671 GetGWorld (&old_port
, &old_gdh
);
673 mac_set_colors (gc
, NULL
);
674 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
676 LockPixels (GetGWorldPixMap (p
));
677 PaintRect (&r
); /* using foreground color of gc */
678 UnlockPixels (GetGWorldPixMap (p
));
680 SetGWorld (old_port
, old_gdh
);
685 /* Mac replacement for XDrawRectangle: dest is a window. */
688 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
693 unsigned int width
, height
;
698 SetPortWindowPort (w
);
700 mac_set_colors (gc
, &old_bg
);
701 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
703 FrameRect (&r
); /* using foreground color of gc */
705 RGBBackColor (&old_bg
);
709 #if 0 /* TODO: figure out if we need to do this on Mac. */
710 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
713 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
718 unsigned int width
, height
;
724 GetGWorld (&old_port
, &old_gdh
);
726 mac_set_colors (gc
, NULL
);
727 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
729 LockPixels (GetGWorldPixMap (p
));
730 FrameRect (&r
); /* using foreground color of gc */
731 UnlockPixels (GetGWorldPixMap (p
));
733 SetGWorld (old_port
, old_gdh
);
739 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
746 int nchars
, mode
, bytes_per_char
;
750 SetPortWindowPort (w
);
751 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
752 UInt32 textFlags
, savedFlags
;
753 if (!NILP(Vmac_use_core_graphics
)) {
754 textFlags
= kQDUseCGTextRendering
;
755 savedFlags
= SwapQDTextFlags(textFlags
);
759 mac_set_colors (gc
, &old_bg
);
761 TextFont (gc
->font
->mac_fontnum
);
762 TextSize (gc
->font
->mac_fontsize
);
763 TextFace (gc
->font
->mac_fontface
);
767 DrawText (buf
, 0, nchars
* bytes_per_char
);
769 RGBBackColor (&old_bg
);
770 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
771 if (!NILP(Vmac_use_core_graphics
))
772 SwapQDTextFlags(savedFlags
);
777 /* Mac replacement for XDrawString. */
780 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
788 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
792 /* Mac replacement for XDrawString16. */
795 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
803 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
808 /* Mac replacement for XDrawImageString. */
811 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
819 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
823 /* Mac replacement for XDrawString16. */
826 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
834 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
839 /* Mac replacement for XCopyArea: dest must be window. */
842 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
849 unsigned int width
, height
;
854 SetPortWindowPort (dest
);
856 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
857 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
859 ForeColor (blackColor
);
860 BackColor (whiteColor
);
862 LockPixels (GetGWorldPixMap (src
));
863 #if TARGET_API_MAC_CARBON
864 LockPortBits (GetWindowPort (dest
));
865 CopyBits (GetPortBitMapForCopyBits (src
),
866 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
867 &src_r
, &dest_r
, srcCopy
, 0);
868 UnlockPortBits (GetWindowPort (dest
));
869 #else /* not TARGET_API_MAC_CARBON */
870 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
871 &src_r
, &dest_r
, srcCopy
, 0);
872 #endif /* not TARGET_API_MAC_CARBON */
873 UnlockPixels (GetGWorldPixMap (src
));
878 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
879 width
, height
, dest_x
, dest_y
)
885 unsigned int width
, height
;
890 SetPortWindowPort (dest
);
892 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
893 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
895 ForeColor (blackColor
);
896 BackColor (whiteColor
);
898 LockPixels (GetGWorldPixMap (src
));
899 LockPixels (GetGWorldPixMap (mask
));
900 #if TARGET_API_MAC_CARBON
901 LockPortBits (GetWindowPort (dest
));
902 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
903 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
904 &src_r
, &src_r
, &dest_r
);
905 UnlockPortBits (GetWindowPort (dest
));
906 #else /* not TARGET_API_MAC_CARBON */
907 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
908 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
909 #endif /* not TARGET_API_MAC_CARBON */
910 UnlockPixels (GetGWorldPixMap (mask
));
911 UnlockPixels (GetGWorldPixMap (src
));
916 /* Convert a pair of local coordinates to global (screen) coordinates.
917 Assume graphic port has been properly set. */
919 local_to_global_coord (short *h
, short *v
)
933 /* Mac replacement for XCopyArea: used only for scrolling. */
936 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
941 unsigned int width
, height
;
944 #if TARGET_API_MAC_CARBON
946 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
948 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
949 ScrollWindowRect (w
, &src_r
, dest_x
- src_x
, dest_y
- src_y
,
950 kScrollWindowNoOptions
, dummy
);
952 #else /* not TARGET_API_MAC_CARBON */
957 mac_set_colors (gc
, NULL
);
960 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
961 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
964 /* Need to use global coordinates and screenBits since src and dest
965 areas overlap in general. */
966 local_to_global_coord (&src_r
.left
, &src_r
.top
);
967 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
968 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
969 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
971 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
973 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
974 color mapping in CopyBits. Otherwise, it will be slow. */
975 ForeColor (blackColor
);
976 BackColor (whiteColor
);
977 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
979 mac_set_colors (gc
, NULL
);
981 #endif /* not TARGET_API_MAC_CARBON */
985 #if 0 /* TODO: figure out if we need to do this on Mac. */
986 /* Mac replacement for XCopyArea: dest must be Pixmap. */
989 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
995 unsigned int width
, height
;
1002 GetGWorld (&old_port
, &old_gdh
);
1003 SetGWorld (dest
, NULL
);
1004 ForeColor (blackColor
);
1005 BackColor (whiteColor
);
1007 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1008 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1010 LockPixels (GetGWorldPixMap (src
));
1011 LockPixels (GetGWorldPixMap (dest
));
1012 #if TARGET_API_MAC_CARBON
1013 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
1014 &src_r
, &dest_r
, srcCopy
, 0);
1015 #else /* not TARGET_API_MAC_CARBON */
1016 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
1017 &src_r
, &dest_r
, srcCopy
, 0);
1018 #endif /* not TARGET_API_MAC_CARBON */
1019 UnlockPixels (GetGWorldPixMap (dest
));
1020 UnlockPixels (GetGWorldPixMap (src
));
1022 SetGWorld (old_port
, old_gdh
);
1027 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
1028 width
, height
, dest_x
, dest_y
)
1030 Pixmap src
, mask
, dest
;
1033 unsigned int width
, height
;
1040 GetGWorld (&old_port
, &old_gdh
);
1041 SetGWorld (dest
, NULL
);
1042 ForeColor (blackColor
);
1043 BackColor (whiteColor
);
1045 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1046 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1048 LockPixels (GetGWorldPixMap (src
));
1049 LockPixels (GetGWorldPixMap (mask
));
1050 LockPixels (GetGWorldPixMap (dest
));
1051 #if TARGET_API_MAC_CARBON
1052 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1053 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
1054 #else /* not TARGET_API_MAC_CARBON */
1055 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1056 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
1057 #endif /* not TARGET_API_MAC_CARBON */
1058 UnlockPixels (GetGWorldPixMap (dest
));
1059 UnlockPixels (GetGWorldPixMap (mask
));
1060 UnlockPixels (GetGWorldPixMap (src
));
1062 SetGWorld (old_port
, old_gdh
);
1067 /* Mac replacement for XChangeGC. */
1070 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1073 if (mask
& GCForeground
)
1074 gc
->foreground
= xgcv
->foreground
;
1075 if (mask
& GCBackground
)
1076 gc
->background
= xgcv
->background
;
1078 gc
->font
= xgcv
->font
;
1082 /* Mac replacement for XCreateGC. */
1085 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1088 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1089 bzero (gc
, sizeof (XGCValues
));
1091 XChangeGC (ignore
, gc
, mask
, xgcv
);
1097 /* Used in xfaces.c. */
1100 XFreeGC (display
, gc
)
1108 /* Mac replacement for XGetGCValues. */
1111 XGetGCValues (void* ignore
, XGCValues
*gc
,
1112 unsigned long mask
, XGCValues
*xgcv
)
1114 XChangeGC (ignore
, xgcv
, mask
, gc
);
1118 /* Mac replacement for XSetForeground. */
1121 XSetForeground (display
, gc
, color
)
1124 unsigned long color
;
1126 gc
->foreground
= color
;
1130 /* Mac replacement for XSetBackground. */
1133 XSetBackground (display
, gc
, color
)
1136 unsigned long color
;
1138 gc
->background
= color
;
1142 /* Mac replacement for XSetWindowBackground. */
1145 XSetWindowBackground (display
, w
, color
)
1148 unsigned long color
;
1150 #if !TARGET_API_MAC_CARBON
1151 AuxWinHandle aw_handle
;
1152 CTabHandle ctab_handle
;
1153 ColorSpecPtr ct_table
;
1158 bg_color
.red
= RED16_FROM_ULONG (color
);
1159 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1160 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1162 #if TARGET_API_MAC_CARBON
1163 SetWindowContentColor (w
, &bg_color
);
1165 if (GetAuxWin (w
, &aw_handle
))
1167 ctab_handle
= (*aw_handle
)->awCTable
;
1168 HandToHand ((Handle
*) &ctab_handle
);
1169 ct_table
= (*ctab_handle
)->ctTable
;
1170 ct_size
= (*ctab_handle
)->ctSize
;
1171 while (ct_size
> -1)
1173 if (ct_table
->value
== 0)
1175 ct_table
->rgb
= bg_color
;
1176 CTabChanged (ctab_handle
);
1177 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1186 /* Mac replacement for XSetFont. */
1189 XSetFont (display
, gc
, font
)
1198 /* x_sync is a no-op on Mac. */
1206 /* Flush display of frame F, or of all frames if F is null. */
1212 #if TARGET_API_MAC_CARBON
1215 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1217 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1223 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1224 Calls to XFlush should be unnecessary because the X output buffer
1225 is flushed automatically as needed by calls to XPending,
1226 XNextEvent, or XWindowEvent according to the XFlush man page.
1227 XTread_socket calls XPending. Removing XFlush improves
1230 #define XFlush(DISPLAY) (void) 0
1233 /* Return the struct mac_display_info corresponding to DPY. There's
1236 struct mac_display_info
*
1237 mac_display_info_for_display (dpy
)
1240 return &one_mac_display_info
;
1245 /***********************************************************************
1246 Starting and ending an update
1247 ***********************************************************************/
1249 /* Start an update of frame F. This function is installed as a hook
1250 for update_begin, i.e. it is called when update_begin is called.
1251 This function is called prior to calls to x_update_window_begin for
1252 each window being updated. */
1258 #if TARGET_API_MAC_CARBON
1259 /* During update of a frame, availability of input events is
1260 periodically checked with ReceiveNextEvent if
1261 redisplay-dont-pause is nil. That normally flushes window buffer
1262 changes for every check, and thus screen update looks waving even
1263 if no input is available. So we disable screen updates during
1264 update of a frame. */
1266 DisableScreenUpdates ();
1272 /* Start update of window W. Set the global variable updated_window
1273 to the window being updated and set output_cursor to the cursor
1277 x_update_window_begin (w
)
1280 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1281 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1284 set_output_cursor (&w
->cursor
);
1288 if (f
== display_info
->mouse_face_mouse_frame
)
1290 /* Don't do highlighting for mouse motion during the update. */
1291 display_info
->mouse_face_defer
= 1;
1293 /* If F needs to be redrawn, simply forget about any prior mouse
1295 if (FRAME_GARBAGED_P (f
))
1296 display_info
->mouse_face_window
= Qnil
;
1298 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1299 their mouse_face_p flag set, which means that they are always
1300 unequal to rows in a desired matrix which never have that
1301 flag set. So, rows containing mouse-face glyphs are never
1302 scrolled, and we don't have to switch the mouse highlight off
1303 here to prevent it from being scrolled. */
1305 /* Can we tell that this update does not affect the window
1306 where the mouse highlight is? If so, no need to turn off.
1307 Likewise, don't do anything if the frame is garbaged;
1308 in that case, the frame's current matrix that we would use
1309 is all wrong, and we will redisplay that line anyway. */
1310 if (!NILP (display_info
->mouse_face_window
)
1311 && w
== XWINDOW (display_info
->mouse_face_window
))
1315 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1316 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1319 if (i
< w
->desired_matrix
->nrows
)
1320 clear_mouse_face (display_info
);
1329 /* Draw a vertical window border from (x,y0) to (x,y1) */
1332 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1336 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1338 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1339 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1343 /* End update of window W (which is equal to updated_window).
1345 Draw vertical borders between horizontally adjacent windows, and
1346 display W's cursor if CURSOR_ON_P is non-zero.
1348 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1349 glyphs in mouse-face were overwritten. In that case we have to
1350 make sure that the mouse-highlight is properly redrawn.
1352 W may be a menu bar pseudo-window in case we don't have X toolkit
1353 support. Such windows don't have a cursor, so don't display it
1357 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1359 int cursor_on_p
, mouse_face_overwritten_p
;
1361 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1363 if (!w
->pseudo_window_p
)
1368 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1370 output_cursor
.x
, output_cursor
.y
);
1372 if (draw_window_fringes (w
, 1))
1373 x_draw_vertical_border (w
);
1378 /* If a row with mouse-face was overwritten, arrange for
1379 XTframe_up_to_date to redisplay the mouse highlight. */
1380 if (mouse_face_overwritten_p
)
1382 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1383 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1384 dpyinfo
->mouse_face_window
= Qnil
;
1388 /* Unhide the caret. This won't actually show the cursor, unless it
1389 was visible before the corresponding call to HideCaret in
1390 x_update_window_begin. */
1391 if (w32_use_visible_system_caret
)
1392 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1395 updated_window
= NULL
;
1399 /* End update of frame F. This function is installed as a hook in
1406 /* Mouse highlight may be displayed again. */
1407 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1410 #if TARGET_API_MAC_CARBON
1411 EnableScreenUpdates ();
1413 XFlush (FRAME_MAC_DISPLAY (f
));
1418 /* This function is called from various places in xdisp.c whenever a
1419 complete update has been performed. The global variable
1420 updated_window is not available here. */
1423 XTframe_up_to_date (f
)
1426 if (FRAME_MAC_P (f
))
1428 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1430 if (dpyinfo
->mouse_face_deferred_gc
1431 || f
== dpyinfo
->mouse_face_mouse_frame
)
1434 if (dpyinfo
->mouse_face_mouse_frame
)
1435 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1436 dpyinfo
->mouse_face_mouse_x
,
1437 dpyinfo
->mouse_face_mouse_y
);
1438 dpyinfo
->mouse_face_deferred_gc
= 0;
1445 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1446 arrow bitmaps, or clear the fringes if no bitmaps are required
1447 before DESIRED_ROW is made current. The window being updated is
1448 found in updated_window. This function is called from
1449 update_window_line only if it is known that there are differences
1450 between bitmaps to be drawn between current row and DESIRED_ROW. */
1453 x_after_update_window_line (desired_row
)
1454 struct glyph_row
*desired_row
;
1456 struct window
*w
= updated_window
;
1462 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1463 desired_row
->redraw_fringe_bitmaps_p
= 1;
1465 /* When a window has disappeared, make sure that no rest of
1466 full-width rows stays visible in the internal border. Could
1467 check here if updated_window is the leftmost/rightmost window,
1468 but I guess it's not worth doing since vertically split windows
1469 are almost never used, internal border is rarely set, and the
1470 overhead is very small. */
1471 if (windows_or_buffers_changed
1472 && desired_row
->full_width_p
1473 && (f
= XFRAME (w
->frame
),
1474 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1476 && (height
= desired_row
->visible_height
,
1479 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1480 /* Internal border is drawn below the tool bar. */
1481 if (WINDOWP (f
->tool_bar_window
)
1482 && w
== XWINDOW (f
->tool_bar_window
))
1487 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1488 0, y
, width
, height
, 0);
1489 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1490 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1498 /* Draw the bitmap WHICH in one of the left or right fringes of
1499 window W. ROW is the glyph row for which to display the bitmap; it
1500 determines the vertical position at which the bitmap has to be
1504 x_draw_fringe_bitmap (w
, row
, p
)
1506 struct glyph_row
*row
;
1507 struct draw_fringe_bitmap_params
*p
;
1509 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1510 Display
*display
= FRAME_MAC_DISPLAY (f
);
1511 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1513 GC gc
= f
->output_data
.mac
->normal_gc
;
1514 struct face
*face
= p
->face
;
1517 /* Must clip because of partially visible lines. */
1518 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1521 /* Adjust position of "bottom aligned" bitmap on partially
1522 visible last row. */
1524 int oldVH
= row
->visible_height
;
1525 row
->visible_height
= p
->h
;
1526 row
->y
-= rowY
- p
->y
;
1527 x_clip_to_row (w
, row
, -1, gc
);
1529 row
->visible_height
= oldVH
;
1532 x_clip_to_row (w
, row
, -1, gc
);
1534 if (p
->bx
>= 0 && !p
->overlay_p
)
1537 gcv
.foreground
= face
->background
;
1539 #if 0 /* MAC_TODO: stipple */
1540 /* In case the same realized face is used for fringes and
1541 for something displayed in the text (e.g. face `region' on
1542 mono-displays, the fill style may have been changed to
1543 FillSolid in x_draw_glyph_string_background. */
1545 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1547 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1550 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1552 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1554 #if 0 /* MAC_TODO: stipple */
1556 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1562 unsigned short *bits
= p
->bits
+ p
->dh
;
1564 gcv
.foreground
= (p
->cursor_p
1565 ? (p
->overlay_p
? face
->background
1566 : f
->output_data
.mac
->cursor_pixel
)
1567 : face
->foreground
);
1568 gcv
.background
= face
->background
;
1570 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
,
1571 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1574 mac_reset_clipping (display
, window
);
1578 /* This is called when starting Emacs and when restarting after
1579 suspend. When starting Emacs, no window is mapped. And nothing
1580 must be done to Emacs's own window if it is suspended (though that
1584 XTset_terminal_modes ()
1588 /* This is called when exiting or suspending Emacs. Exiting will make
1589 the windows go away, and suspending requires no action. */
1592 XTreset_terminal_modes ()
1597 /***********************************************************************
1599 ***********************************************************************/
1601 /* Function prototypes of this page. */
1603 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1604 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1607 /* Return a pointer to per-char metric information in FONT of a
1608 character pointed by B which is a pointer to an XChar2b. */
1610 #define PER_CHAR_METRIC(font, b) \
1612 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1613 + (((font)->min_byte1 || (font)->max_byte1) \
1614 ? (((b)->byte1 - (font)->min_byte1) \
1615 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1617 : &((font)->max_bounds))
1620 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1621 is not contained in the font. */
1623 static INLINE XCharStruct
*
1624 x_per_char_metric (font
, char2b
)
1628 /* The result metric information. */
1629 XCharStruct
*pcm
= NULL
;
1631 xassert (font
&& char2b
);
1633 if (font
->per_char
!= NULL
)
1635 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1637 /* min_char_or_byte2 specifies the linear character index
1638 corresponding to the first element of the per_char array,
1639 max_char_or_byte2 is the index of the last character. A
1640 character with non-zero CHAR2B->byte1 is not in the font.
1641 A character with byte2 less than min_char_or_byte2 or
1642 greater max_char_or_byte2 is not in the font. */
1643 if (char2b
->byte1
== 0
1644 && char2b
->byte2
>= font
->min_char_or_byte2
1645 && char2b
->byte2
<= font
->max_char_or_byte2
)
1646 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1650 /* If either min_byte1 or max_byte1 are nonzero, both
1651 min_char_or_byte2 and max_char_or_byte2 are less than
1652 256, and the 2-byte character index values corresponding
1653 to the per_char array element N (counting from 0) are:
1655 byte1 = N/D + min_byte1
1656 byte2 = N\D + min_char_or_byte2
1660 D = max_char_or_byte2 - min_char_or_byte2 + 1
1661 / = integer division
1662 \ = integer modulus */
1663 if (char2b
->byte1
>= font
->min_byte1
1664 && char2b
->byte1
<= font
->max_byte1
1665 && char2b
->byte2
>= font
->min_char_or_byte2
1666 && char2b
->byte2
<= font
->max_char_or_byte2
)
1668 pcm
= (font
->per_char
1669 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1670 * (char2b
->byte1
- font
->min_byte1
))
1671 + (char2b
->byte2
- font
->min_char_or_byte2
));
1677 /* If the per_char pointer is null, all glyphs between the first
1678 and last character indexes inclusive have the same
1679 information, as given by both min_bounds and max_bounds. */
1680 if (char2b
->byte2
>= font
->min_char_or_byte2
1681 && char2b
->byte2
<= font
->max_char_or_byte2
)
1682 pcm
= &font
->max_bounds
;
1685 return ((pcm
== NULL
1686 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1693 static XCharStruct
*
1694 mac_per_char_metric (font
, char2b
, font_type
)
1699 return x_per_char_metric (font
, char2b
);
1703 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1704 the two-byte form of C. Encoding is returned in *CHAR2B. */
1707 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1710 struct font_info
*font_info
;
1713 int charset
= CHAR_CHARSET (c
);
1714 XFontStruct
*font
= font_info
->font
;
1716 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1717 This may be either a program in a special encoder language or a
1719 if (font_info
->font_encoder
)
1721 /* It's a program. */
1722 struct ccl_program
*ccl
= font_info
->font_encoder
;
1724 if (CHARSET_DIMENSION (charset
) == 1)
1726 ccl
->reg
[0] = charset
;
1727 ccl
->reg
[1] = char2b
->byte2
;
1731 ccl
->reg
[0] = charset
;
1732 ccl
->reg
[1] = char2b
->byte1
;
1733 ccl
->reg
[2] = char2b
->byte2
;
1736 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1738 /* We assume that MSBs are appropriately set/reset by CCL
1740 if (font
->max_byte1
== 0) /* 1-byte font */
1741 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1743 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1745 else if (font_info
->encoding
[charset
])
1747 /* Fixed encoding scheme. See fontset.h for the meaning of the
1748 encoding numbers. */
1749 int enc
= font_info
->encoding
[charset
];
1751 if ((enc
== 1 || enc
== 2)
1752 && CHARSET_DIMENSION (charset
) == 2)
1753 char2b
->byte1
|= 0x80;
1755 if (enc
== 1 || enc
== 3)
1756 char2b
->byte2
|= 0x80;
1762 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1763 char2b
->byte1
= sjis1
;
1764 char2b
->byte2
= sjis2
;
1769 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1771 return FONT_TYPE_UNKNOWN
;
1776 /***********************************************************************
1778 ***********************************************************************/
1781 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1782 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1783 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1785 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1786 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1787 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1788 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1789 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1790 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1791 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1792 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1793 unsigned long *, double, int));*/
1794 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1795 double, int, unsigned long));
1796 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1797 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1798 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1799 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1800 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1801 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1803 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1804 int, int, int, int, int, int,
1806 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1807 int, int, int, Rect
*));
1810 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1814 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1819 struct glyph_string
*s
;
1821 if (s
->font
== FRAME_FONT (s
->f
)
1822 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1823 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1825 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1828 /* Cursor on non-default face: must merge. */
1832 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1833 xgcv
.foreground
= s
->face
->background
;
1835 /* If the glyph would be invisible, try a different foreground. */
1836 if (xgcv
.foreground
== xgcv
.background
)
1837 xgcv
.foreground
= s
->face
->foreground
;
1838 if (xgcv
.foreground
== xgcv
.background
)
1839 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1840 if (xgcv
.foreground
== xgcv
.background
)
1841 xgcv
.foreground
= s
->face
->foreground
;
1843 /* Make sure the cursor is distinct from text in this face. */
1844 if (xgcv
.background
== s
->face
->background
1845 && xgcv
.foreground
== s
->face
->foreground
)
1847 xgcv
.background
= s
->face
->foreground
;
1848 xgcv
.foreground
= s
->face
->background
;
1851 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1852 xgcv
.font
= s
->font
;
1853 mask
= GCForeground
| GCBackground
| GCFont
;
1855 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1856 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1859 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1860 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1862 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1867 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1870 x_set_mouse_face_gc (s
)
1871 struct glyph_string
*s
;
1876 /* What face has to be used last for the mouse face? */
1877 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1878 face
= FACE_FROM_ID (s
->f
, face_id
);
1880 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1882 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1883 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1885 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1886 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1887 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1889 /* If font in this face is same as S->font, use it. */
1890 if (s
->font
== s
->face
->font
)
1891 s
->gc
= s
->face
->gc
;
1894 /* Otherwise construct scratch_cursor_gc with values from FACE
1899 xgcv
.background
= s
->face
->background
;
1900 xgcv
.foreground
= s
->face
->foreground
;
1901 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1902 xgcv
.font
= s
->font
;
1903 mask
= GCForeground
| GCBackground
| GCFont
;
1905 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1906 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1909 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1910 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1912 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1915 xassert (s
->gc
!= 0);
1919 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1920 Faces to use in the mode line have already been computed when the
1921 matrix was built, so there isn't much to do, here. */
1924 x_set_mode_line_face_gc (s
)
1925 struct glyph_string
*s
;
1927 s
->gc
= s
->face
->gc
;
1931 /* Set S->gc of glyph string S for drawing that glyph string. Set
1932 S->stippled_p to a non-zero value if the face of S has a stipple
1936 x_set_glyph_string_gc (s
)
1937 struct glyph_string
*s
;
1939 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1941 if (s
->hl
== DRAW_NORMAL_TEXT
)
1943 s
->gc
= s
->face
->gc
;
1944 s
->stippled_p
= s
->face
->stipple
!= 0;
1946 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1948 x_set_mode_line_face_gc (s
);
1949 s
->stippled_p
= s
->face
->stipple
!= 0;
1951 else if (s
->hl
== DRAW_CURSOR
)
1953 x_set_cursor_gc (s
);
1956 else if (s
->hl
== DRAW_MOUSE_FACE
)
1958 x_set_mouse_face_gc (s
);
1959 s
->stippled_p
= s
->face
->stipple
!= 0;
1961 else if (s
->hl
== DRAW_IMAGE_RAISED
1962 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1964 s
->gc
= s
->face
->gc
;
1965 s
->stippled_p
= s
->face
->stipple
!= 0;
1969 s
->gc
= s
->face
->gc
;
1970 s
->stippled_p
= s
->face
->stipple
!= 0;
1973 /* GC must have been set. */
1974 xassert (s
->gc
!= 0);
1978 /* Set clipping for output of glyph string S. S may be part of a mode
1979 line or menu if we don't have X toolkit support. */
1982 x_set_glyph_string_clipping (s
)
1983 struct glyph_string
*s
;
1986 get_glyph_string_clip_rect (s
, &r
);
1987 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
1992 Compute left and right overhang of glyph string S. If S is a glyph
1993 string for a composition, assume overhangs don't exist. */
1996 mac_compute_glyph_string_overhangs (s
)
1997 struct glyph_string
*s
;
2000 MacFontStruct
*font
= s
->font
;
2002 TextFont (font
->mac_fontnum
);
2003 TextSize (font
->mac_fontsize
);
2004 TextFace (font
->mac_fontface
);
2007 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2011 char *buf
= xmalloc (s
->nchars
);
2014 SetRect (&r
, 0, 0, 0, 0);
2017 for (i
= 0; i
< s
->nchars
; ++i
)
2018 buf
[i
] = s
->char2b
[i
].byte2
;
2019 QDTextBounds (s
->nchars
, buf
, &r
);
2024 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2025 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2029 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2032 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2033 struct glyph_string
*s
;
2038 xgcv
.foreground
= s
->gc
->background
;
2039 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2043 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2044 on Mac OS X because:
2045 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2046 into an offscreen graphics world first. So performance gain
2047 cannot be expected.)
2048 - It lowers rendering quality.
2049 - Some fonts leave garbage on cursor movement. */
2051 /* Draw the background of glyph_string S. If S->background_filled_p
2052 is non-zero don't draw it. FORCE_P non-zero means draw the
2053 background even if it wouldn't be drawn normally. This is used
2054 when a string preceding S draws into the background of S, or S
2055 contains the first component of a composition. */
2058 x_draw_glyph_string_background (s
, force_p
)
2059 struct glyph_string
*s
;
2062 /* Nothing to do if background has already been drawn or if it
2063 shouldn't be drawn in the first place. */
2064 if (!s
->background_filled_p
)
2066 int box_line_width
= max (s
->face
->box_line_width
, 0);
2068 #if 0 /* MAC_TODO: stipple */
2071 /* Fill background with a stipple pattern. */
2072 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2073 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2074 s
->y
+ box_line_width
,
2075 s
->background_width
,
2076 s
->height
- 2 * box_line_width
);
2077 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2078 s
->background_filled_p
= 1;
2083 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2084 || s
->font_not_found_p
2085 || s
->extends_to_end_of_line_p
2089 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2090 s
->background_width
,
2091 s
->height
- 2 * box_line_width
);
2092 s
->background_filled_p
= 1;
2098 /* Draw the foreground of glyph string S. */
2101 x_draw_glyph_string_foreground (s
)
2102 struct glyph_string
*s
;
2106 /* If first glyph of S has a left box line, start drawing the text
2107 of S to the right of that box line. */
2108 if (s
->face
->box
!= FACE_NO_BOX
2109 && s
->first_glyph
->left_box_line_p
)
2110 x
= s
->x
+ abs (s
->face
->box_line_width
);
2114 /* Draw characters of S as rectangles if S's font could not be
2116 if (s
->font_not_found_p
)
2118 for (i
= 0; i
< s
->nchars
; ++i
)
2120 struct glyph
*g
= s
->first_glyph
+ i
;
2121 mac_draw_rectangle (s
->display
, s
->window
,
2122 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2124 x
+= g
->pixel_width
;
2129 char *char1b
= (char *) s
->char2b
;
2130 int boff
= s
->font_info
->baseline_offset
;
2132 if (s
->font_info
->vertical_centering
)
2133 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2135 /* If we can use 8-bit functions, condense S->char2b. */
2137 for (i
= 0; i
< s
->nchars
; ++i
)
2138 char1b
[i
] = s
->char2b
[i
].byte2
;
2141 /* Draw text with XDrawString if background has already been
2142 filled. Otherwise, use XDrawImageString. (Note that
2143 XDrawImageString is usually faster than XDrawString.) Always
2144 use XDrawImageString when drawing the cursor so that there is
2145 no chance that characters under a box cursor are invisible. */
2146 if (s
->for_overlaps_p
2147 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2150 /* Draw characters with 16-bit or 8-bit functions. */
2152 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2153 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2155 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2156 s
->ybase
- boff
, char1b
, s
->nchars
);
2162 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2163 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2165 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2166 s
->ybase
- boff
, char1b
, s
->nchars
);
2172 /* Draw the foreground of composite glyph string S. */
2175 x_draw_composite_glyph_string_foreground (s
)
2176 struct glyph_string
*s
;
2180 /* If first glyph of S has a left box line, start drawing the text
2181 of S to the right of that box line. */
2182 if (s
->face
->box
!= FACE_NO_BOX
2183 && s
->first_glyph
->left_box_line_p
)
2184 x
= s
->x
+ abs (s
->face
->box_line_width
);
2188 /* S is a glyph string for a composition. S->gidx is the index of
2189 the first character drawn for glyphs of this composition.
2190 S->gidx == 0 means we are drawing the very first character of
2191 this composition. */
2193 /* Draw a rectangle for the composition if the font for the very
2194 first character of the composition could not be loaded. */
2195 if (s
->font_not_found_p
)
2198 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2199 s
->width
- 1, s
->height
- 1);
2203 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2204 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2205 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2206 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2212 #ifdef USE_X_TOOLKIT
2214 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2217 /* Return the frame on which widget WIDGET is used.. Abort if frame
2218 cannot be determined. */
2220 static struct frame
*
2221 x_frame_of_widget (widget
)
2224 struct x_display_info
*dpyinfo
;
2228 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2230 /* Find the top-level shell of the widget. Note that this function
2231 can be called when the widget is not yet realized, so XtWindow
2232 (widget) == 0. That's the reason we can't simply use
2233 x_any_window_to_frame. */
2234 while (!XtIsTopLevelShell (widget
))
2235 widget
= XtParent (widget
);
2237 /* Look for a frame with that top-level widget. Allocate the color
2238 on that frame to get the right gamma correction value. */
2239 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2240 if (GC_FRAMEP (XCAR (tail
))
2241 && (f
= XFRAME (XCAR (tail
)),
2242 (f
->output_data
.nothing
!= 1
2243 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2244 && f
->output_data
.x
->widget
== widget
)
2251 /* Allocate the color COLOR->pixel on the screen and display of
2252 widget WIDGET in colormap CMAP. If an exact match cannot be
2253 allocated, try the nearest color available. Value is non-zero
2254 if successful. This is called from lwlib. */
2257 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2262 struct frame
*f
= x_frame_of_widget (widget
);
2263 return x_alloc_nearest_color (f
, cmap
, color
);
2267 #endif /* USE_X_TOOLKIT */
2269 #if 0 /* MAC_TODO */
2271 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2272 CMAP. If an exact match can't be allocated, try the nearest color
2273 available. Value is non-zero if successful. Set *COLOR to the
2277 x_alloc_nearest_color (f
, cmap
, color
)
2282 Display
*display
= FRAME_X_DISPLAY (f
);
2283 Screen
*screen
= FRAME_X_SCREEN (f
);
2286 gamma_correct (f
, color
);
2287 rc
= XAllocColor (display
, cmap
, color
);
2290 /* If we got to this point, the colormap is full, so we're going
2291 to try to get the next closest color. The algorithm used is
2292 a least-squares matching, which is what X uses for closest
2293 color matching with StaticColor visuals. */
2295 unsigned long nearest_delta
= ~0;
2296 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2297 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2299 for (i
= 0; i
< ncells
; ++i
)
2301 XQueryColors (display
, cmap
, cells
, ncells
);
2303 for (nearest
= i
= 0; i
< ncells
; ++i
)
2305 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2306 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2307 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2308 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2310 if (delta
< nearest_delta
)
2313 nearest_delta
= delta
;
2317 color
->red
= cells
[nearest
].red
;
2318 color
->green
= cells
[nearest
].green
;
2319 color
->blue
= cells
[nearest
].blue
;
2320 rc
= XAllocColor (display
, cmap
, color
);
2323 #ifdef DEBUG_X_COLORS
2325 register_color (color
->pixel
);
2326 #endif /* DEBUG_X_COLORS */
2332 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2333 It's necessary to do this instead of just using PIXEL directly to
2334 get color reference counts right. */
2337 x_copy_color (f
, pixel
)
2339 unsigned long pixel
;
2343 color
.pixel
= pixel
;
2345 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2346 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2348 #ifdef DEBUG_X_COLORS
2349 register_color (pixel
);
2355 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2356 It's necessary to do this instead of just using PIXEL directly to
2357 get color reference counts right. */
2360 x_copy_dpy_color (dpy
, cmap
, pixel
)
2363 unsigned long pixel
;
2367 color
.pixel
= pixel
;
2369 XQueryColor (dpy
, cmap
, &color
);
2370 XAllocColor (dpy
, cmap
, &color
);
2372 #ifdef DEBUG_X_COLORS
2373 register_color (pixel
);
2378 #endif /* MAC_TODO */
2381 /* Brightness beyond which a color won't have its highlight brightness
2384 Nominally, highlight colors for `3d' faces are calculated by
2385 brightening an object's color by a constant scale factor, but this
2386 doesn't yield good results for dark colors, so for colors who's
2387 brightness is less than this value (on a scale of 0-255) have to
2388 use an additional additive factor.
2390 The value here is set so that the default menu-bar/mode-line color
2391 (grey75) will not have its highlights changed at all. */
2392 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2395 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2396 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2397 If this produces the same color as COLOR, try a color where all RGB
2398 values have DELTA added. Return the allocated color in *COLOR.
2399 DISPLAY is the X display, CMAP is the colormap to operate on.
2400 Value is non-zero if successful. */
2403 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2405 unsigned long *color
;
2412 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2415 /* Change RGB values by specified FACTOR. Avoid overflow! */
2416 xassert (factor
>= 0);
2417 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2418 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2419 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2421 /* Calculate brightness of COLOR. */
2422 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2423 + BLUE_FROM_ULONG (*color
)) / 6;
2425 /* We only boost colors that are darker than
2426 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2427 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2428 /* Make an additive adjustment to NEW, because it's dark enough so
2429 that scaling by FACTOR alone isn't enough. */
2431 /* How far below the limit this color is (0 - 1, 1 being darker). */
2432 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2433 /* The additive adjustment. */
2434 int min_delta
= delta
* dimness
* factor
/ 2;
2437 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2438 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2439 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2441 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2442 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2443 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2447 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2448 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2449 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2451 /* MAC_TODO: Map to palette and retry with delta if same? */
2452 /* MAC_TODO: Free colors (if using palette)? */
2463 /* Set up the foreground color for drawing relief lines of glyph
2464 string S. RELIEF is a pointer to a struct relief containing the GC
2465 with which lines will be drawn. Use a color that is FACTOR or
2466 DELTA lighter or darker than the relief's background which is found
2467 in S->f->output_data.x->relief_background. If such a color cannot
2468 be allocated, use DEFAULT_PIXEL, instead. */
2471 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2473 struct relief
*relief
;
2476 unsigned long default_pixel
;
2479 struct mac_output
*di
= f
->output_data
.mac
;
2480 unsigned long mask
= GCForeground
;
2481 unsigned long pixel
;
2482 unsigned long background
= di
->relief_background
;
2483 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2485 /* MAC_TODO: Free colors (if using palette)? */
2487 /* Allocate new color. */
2488 xgcv
.foreground
= default_pixel
;
2490 if (dpyinfo
->n_planes
!= 1
2491 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2493 relief
->allocated_p
= 1;
2494 xgcv
.foreground
= relief
->pixel
= pixel
;
2497 if (relief
->gc
== 0)
2499 #if 0 /* MAC_TODO: stipple */
2500 xgcv
.stipple
= dpyinfo
->gray
;
2503 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2506 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2510 /* Set up colors for the relief lines around glyph string S. */
2513 x_setup_relief_colors (s
)
2514 struct glyph_string
*s
;
2516 struct mac_output
*di
= s
->f
->output_data
.mac
;
2517 unsigned long color
;
2519 if (s
->face
->use_box_color_for_shadows_p
)
2520 color
= s
->face
->box_color
;
2521 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2523 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2524 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2529 /* Get the background color of the face. */
2530 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2531 color
= xgcv
.background
;
2534 if (di
->white_relief
.gc
== 0
2535 || color
!= di
->relief_background
)
2537 di
->relief_background
= color
;
2538 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2539 WHITE_PIX_DEFAULT (s
->f
));
2540 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2541 BLACK_PIX_DEFAULT (s
->f
));
2546 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2547 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2548 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2549 relief. LEFT_P non-zero means draw a relief on the left side of
2550 the rectangle. RIGHT_P non-zero means draw a relief on the right
2551 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2555 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2556 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2558 int left_x
, top_y
, right_x
, bottom_y
, width
;
2559 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2562 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2563 Window window
= FRAME_MAC_WINDOW (f
);
2568 gc
= f
->output_data
.mac
->white_relief
.gc
;
2570 gc
= f
->output_data
.mac
->black_relief
.gc
;
2571 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2575 for (i
= 0; i
< width
; ++i
)
2576 XDrawLine (dpy
, window
, gc
,
2577 left_x
+ i
* left_p
, top_y
+ i
,
2578 right_x
- i
* right_p
, top_y
+ i
);
2582 for (i
= 0; i
< width
; ++i
)
2583 XDrawLine (dpy
, window
, gc
,
2584 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2586 mac_reset_clipping (dpy
, window
);
2588 gc
= f
->output_data
.mac
->black_relief
.gc
;
2590 gc
= f
->output_data
.mac
->white_relief
.gc
;
2591 mac_set_clip_rectangle (dpy
, window
,
2596 for (i
= 0; i
< width
; ++i
)
2597 XDrawLine (dpy
, window
, gc
,
2598 left_x
+ i
* left_p
, bottom_y
- i
,
2599 right_x
- i
* right_p
, bottom_y
- i
);
2603 for (i
= 0; i
< width
; ++i
)
2604 XDrawLine (dpy
, window
, gc
,
2605 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2607 mac_reset_clipping (dpy
, window
);
2611 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2612 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2613 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2614 left side of the rectangle. RIGHT_P non-zero means draw a line
2615 on the right side of the rectangle. CLIP_RECT is the clipping
2616 rectangle to use when drawing. */
2619 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2620 left_p
, right_p
, clip_rect
)
2621 struct glyph_string
*s
;
2622 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2627 xgcv
.foreground
= s
->face
->box_color
;
2628 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2631 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2632 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2636 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2637 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2640 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2641 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2645 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2646 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2648 mac_reset_clipping (s
->display
, s
->window
);
2652 /* Draw a box around glyph string S. */
2655 x_draw_glyph_string_box (s
)
2656 struct glyph_string
*s
;
2658 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2659 int left_p
, right_p
;
2660 struct glyph
*last_glyph
;
2663 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2664 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2665 : window_box_right (s
->w
, s
->area
));
2667 /* The glyph that may have a right box line. */
2668 last_glyph
= (s
->cmp
|| s
->img
2670 : s
->first_glyph
+ s
->nchars
- 1);
2672 width
= abs (s
->face
->box_line_width
);
2673 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2675 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2677 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2679 bottom_y
= top_y
+ s
->height
- 1;
2681 left_p
= (s
->first_glyph
->left_box_line_p
2682 || (s
->hl
== DRAW_MOUSE_FACE
2684 || s
->prev
->hl
!= s
->hl
)));
2685 right_p
= (last_glyph
->right_box_line_p
2686 || (s
->hl
== DRAW_MOUSE_FACE
2688 || s
->next
->hl
!= s
->hl
)));
2690 get_glyph_string_clip_rect (s
, &clip_rect
);
2692 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2693 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2694 left_p
, right_p
, &clip_rect
);
2697 x_setup_relief_colors (s
);
2698 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2699 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2704 /* Draw foreground of image glyph string S. */
2707 x_draw_image_foreground (s
)
2708 struct glyph_string
*s
;
2711 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2713 /* If first glyph of S has a left box line, start drawing it to the
2714 right of that line. */
2715 if (s
->face
->box
!= FACE_NO_BOX
2716 && s
->first_glyph
->left_box_line_p
2718 x
+= abs (s
->face
->box_line_width
);
2720 /* If there is a margin around the image, adjust x- and y-position
2722 if (s
->slice
.x
== 0)
2723 x
+= s
->img
->hmargin
;
2724 if (s
->slice
.y
== 0)
2725 y
+= s
->img
->vmargin
;
2729 x_set_glyph_string_clipping (s
);
2732 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2733 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2734 s
->slice
.width
, s
->slice
.height
, x
, y
);
2737 mac_copy_area (s
->display
, s
->img
->pixmap
,
2738 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2739 s
->slice
.width
, s
->slice
.height
, x
, y
);
2741 /* When the image has a mask, we can expect that at
2742 least part of a mouse highlight or a block cursor will
2743 be visible. If the image doesn't have a mask, make
2744 a block cursor visible by drawing a rectangle around
2745 the image. I believe it's looking better if we do
2746 nothing here for mouse-face. */
2747 if (s
->hl
== DRAW_CURSOR
)
2749 int r
= s
->img
->relief
;
2751 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2753 s
->slice
.width
+ r
*2 - 1,
2754 s
->slice
.height
+ r
*2 - 1);
2759 /* Draw a rectangle if image could not be loaded. */
2760 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2761 s
->slice
.width
- 1, s
->slice
.height
- 1);
2765 /* Draw a relief around the image glyph string S. */
2768 x_draw_image_relief (s
)
2769 struct glyph_string
*s
;
2771 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2774 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2776 /* If first glyph of S has a left box line, start drawing it to the
2777 right of that line. */
2778 if (s
->face
->box
!= FACE_NO_BOX
2779 && s
->first_glyph
->left_box_line_p
2781 x
+= abs (s
->face
->box_line_width
);
2783 /* If there is a margin around the image, adjust x- and y-position
2785 if (s
->slice
.x
== 0)
2786 x
+= s
->img
->hmargin
;
2787 if (s
->slice
.y
== 0)
2788 y
+= s
->img
->vmargin
;
2790 if (s
->hl
== DRAW_IMAGE_SUNKEN
2791 || s
->hl
== DRAW_IMAGE_RAISED
)
2793 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2794 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2798 thick
= abs (s
->img
->relief
);
2799 raised_p
= s
->img
->relief
> 0;
2804 x1
= x
+ s
->slice
.width
+ thick
- 1;
2805 y1
= y
+ s
->slice
.height
+ thick
- 1;
2807 x_setup_relief_colors (s
);
2808 get_glyph_string_clip_rect (s
, &r
);
2809 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2811 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2813 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2818 #if 0 /* TODO: figure out if we need to do this on Mac. */
2819 /* Draw the foreground of image glyph string S to PIXMAP. */
2822 x_draw_image_foreground_1 (s
, pixmap
)
2823 struct glyph_string
*s
;
2827 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2829 /* If first glyph of S has a left box line, start drawing it to the
2830 right of that line. */
2831 if (s
->face
->box
!= FACE_NO_BOX
2832 && s
->first_glyph
->left_box_line_p
2834 x
+= abs (s
->face
->box_line_width
);
2836 /* If there is a margin around the image, adjust x- and y-position
2838 if (s
->slice
.x
== 0)
2839 x
+= s
->img
->hmargin
;
2840 if (s
->slice
.y
== 0)
2841 y
+= s
->img
->vmargin
;
2846 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2847 s
->img
->mask
, pixmap
, s
->gc
,
2848 s
->slice
.x
, s
->slice
.y
,
2849 s
->slice
.width
, s
->slice
.height
,
2853 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2854 s
->slice
.x
, s
->slice
.y
,
2855 s
->slice
.width
, s
->slice
.height
,
2858 /* When the image has a mask, we can expect that at
2859 least part of a mouse highlight or a block cursor will
2860 be visible. If the image doesn't have a mask, make
2861 a block cursor visible by drawing a rectangle around
2862 the image. I believe it's looking better if we do
2863 nothing here for mouse-face. */
2864 if (s
->hl
== DRAW_CURSOR
)
2866 int r
= s
->img
->relief
;
2868 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2869 s
->slice
.width
+ r
*2 - 1,
2870 s
->slice
.height
+ r
*2 - 1);
2875 /* Draw a rectangle if image could not be loaded. */
2876 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2877 s
->slice
.width
- 1, s
->slice
.height
- 1);
2882 /* Draw part of the background of glyph string S. X, Y, W, and H
2883 give the rectangle to draw. */
2886 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2887 struct glyph_string
*s
;
2890 #if 0 /* MAC_TODO: stipple */
2893 /* Fill background with a stipple pattern. */
2894 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2895 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2896 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2899 #endif /* MAC_TODO */
2900 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2904 /* Draw image glyph string S.
2907 s->x +-------------------------
2910 | +-------------------------
2913 | | +-------------------
2919 x_draw_image_glyph_string (s
)
2920 struct glyph_string
*s
;
2923 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2924 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2928 height
= s
->height
- 2 * box_line_vwidth
;
2931 /* Fill background with face under the image. Do it only if row is
2932 taller than image or if image has a clip mask to reduce
2934 s
->stippled_p
= s
->face
->stipple
!= 0;
2935 if (height
> s
->slice
.height
2939 || s
->img
->pixmap
== 0
2940 || s
->width
!= s
->background_width
)
2943 if (s
->first_glyph
->left_box_line_p
2945 x
+= box_line_hwidth
;
2948 if (s
->slice
.y
== 0)
2949 y
+= box_line_vwidth
;
2951 #if 0 /* TODO: figure out if we need to do this on Mac. */
2954 /* Create a pixmap as large as the glyph string. Fill it
2955 with the background color. Copy the image to it, using
2956 its mask. Copy the temporary pixmap to the display. */
2957 int depth
= one_mac_display_info
.n_planes
;
2959 /* Create a pixmap as large as the glyph string. */
2960 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2961 s
->background_width
,
2964 /* Fill the pixmap with the background color/stipple. */
2965 #if 0 /* TODO: stipple */
2968 /* Fill background with a stipple pattern. */
2969 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2970 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2971 0, 0, s
->background_width
, s
->height
);
2972 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2978 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2980 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2981 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2982 0, 0, s
->background_width
,
2984 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2989 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2991 s
->background_filled_p
= 1;
2994 /* Draw the foreground. */
2995 #if 0 /* TODO: figure out if we need to do this on Mac. */
2998 x_draw_image_foreground_1 (s
, pixmap
);
2999 x_set_glyph_string_clipping (s
);
3000 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
3001 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3002 mac_reset_clipping (s
->display
, s
->window
);
3003 XFreePixmap (s
->display
, pixmap
);
3007 x_draw_image_foreground (s
);
3009 /* If we must draw a relief around the image, do it. */
3011 || s
->hl
== DRAW_IMAGE_RAISED
3012 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3013 x_draw_image_relief (s
);
3017 /* Draw stretch glyph string S. */
3020 x_draw_stretch_glyph_string (s
)
3021 struct glyph_string
*s
;
3023 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3024 s
->stippled_p
= s
->face
->stipple
!= 0;
3026 if (s
->hl
== DRAW_CURSOR
3027 && !x_stretch_cursor_p
)
3029 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3030 as wide as the stretch glyph. */
3031 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3034 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3036 /* Clear rest using the GC of the original non-cursor face. */
3037 if (width
< s
->background_width
)
3039 int x
= s
->x
+ width
, y
= s
->y
;
3040 int w
= s
->background_width
- width
, h
= s
->height
;
3044 if (s
->row
->mouse_face_p
3045 && cursor_in_mouse_face_p (s
->w
))
3047 x_set_mouse_face_gc (s
);
3053 get_glyph_string_clip_rect (s
, &r
);
3054 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3056 #if 0 /* MAC_TODO: stipple */
3057 if (s
->face
->stipple
)
3059 /* Fill background with a stipple pattern. */
3060 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3061 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3062 XSetFillStyle (s
->display
, gc
, FillSolid
);
3065 #endif /* MAC_TODO */
3068 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3069 XSetForeground (s
->display
, gc
, xgcv
.background
);
3070 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3071 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3074 mac_reset_clipping (s
->display
, s
->window
);
3077 else if (!s
->background_filled_p
)
3078 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3081 s
->background_filled_p
= 1;
3085 /* Draw glyph string S. */
3088 x_draw_glyph_string (s
)
3089 struct glyph_string
*s
;
3091 int relief_drawn_p
= 0;
3093 /* If S draws into the background of its successor that does not
3094 draw a cursor, draw the background of the successor first so that
3095 S can draw into it. This makes S->next use XDrawString instead
3096 of XDrawImageString. */
3097 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
3098 && s
->next
->hl
!= DRAW_CURSOR
)
3100 xassert (s
->next
->img
== NULL
);
3101 x_set_glyph_string_gc (s
->next
);
3102 x_set_glyph_string_clipping (s
->next
);
3103 x_draw_glyph_string_background (s
->next
, 1);
3106 /* Set up S->gc, set clipping and draw S. */
3107 x_set_glyph_string_gc (s
);
3109 /* Draw relief (if any) in advance for char/composition so that the
3110 glyph string can be drawn over it. */
3111 if (!s
->for_overlaps_p
3112 && s
->face
->box
!= FACE_NO_BOX
3113 && (s
->first_glyph
->type
== CHAR_GLYPH
3114 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3117 x_set_glyph_string_clipping (s
);
3118 x_draw_glyph_string_background (s
, 1);
3119 x_draw_glyph_string_box (s
);
3120 x_set_glyph_string_clipping (s
);
3124 x_set_glyph_string_clipping (s
);
3126 switch (s
->first_glyph
->type
)
3129 x_draw_image_glyph_string (s
);
3133 x_draw_stretch_glyph_string (s
);
3137 if (s
->for_overlaps_p
)
3138 s
->background_filled_p
= 1;
3140 x_draw_glyph_string_background (s
, 0);
3141 x_draw_glyph_string_foreground (s
);
3144 case COMPOSITE_GLYPH
:
3145 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3146 s
->background_filled_p
= 1;
3148 x_draw_glyph_string_background (s
, 1);
3149 x_draw_composite_glyph_string_foreground (s
);
3156 if (!s
->for_overlaps_p
)
3158 /* Draw underline. */
3159 if (s
->face
->underline_p
)
3161 unsigned long h
= 1;
3162 unsigned long dy
= s
->height
- h
;
3164 if (s
->face
->underline_defaulted_p
)
3165 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3170 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3171 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3172 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3174 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3178 /* Draw overline. */
3179 if (s
->face
->overline_p
)
3181 unsigned long dy
= 0, h
= 1;
3183 if (s
->face
->overline_color_defaulted_p
)
3184 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3189 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3190 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3191 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3193 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3197 /* Draw strike-through. */
3198 if (s
->face
->strike_through_p
)
3200 unsigned long h
= 1;
3201 unsigned long dy
= (s
->height
- h
) / 2;
3203 if (s
->face
->strike_through_color_defaulted_p
)
3204 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3209 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3210 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3211 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3213 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3217 /* Draw relief if not yet drawn. */
3218 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3219 x_draw_glyph_string_box (s
);
3222 /* Reset clipping. */
3223 mac_reset_clipping (s
->display
, s
->window
);
3226 /* Shift display to make room for inserted glyphs. */
3229 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3231 int x
, y
, width
, height
, shift_by
;
3233 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3234 f
->output_data
.mac
->normal_gc
,
3235 x
, y
, width
, height
,
3239 /* Delete N glyphs at the nominal cursor position. Not implemented
3250 /* Clear entire frame. If updating_frame is non-null, clear that
3251 frame. Otherwise clear the selected frame. */
3261 f
= SELECTED_FRAME ();
3263 /* Clearing the frame will erase any cursor, so mark them all as no
3265 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3266 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3267 output_cursor
.x
= -1;
3269 /* We don't set the output cursor here because there will always
3270 follow an explicit cursor_to. */
3272 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3274 /* We have to clear the scroll bars, too. If we have changed
3275 colors or something like that, then they should be notified. */
3276 x_scroll_bar_clear (f
);
3278 XFlush (FRAME_MAC_DISPLAY (f
));
3284 /* Invert the middle quarter of the frame for .15 sec. */
3286 /* We use the select system call to do the waiting, so we have to make
3287 sure it's available. If it isn't, we just won't do visual bells. */
3289 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3292 /* Subtract the `struct timeval' values X and Y, storing the result in
3293 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3296 timeval_subtract (result
, x
, y
)
3297 struct timeval
*result
, x
, y
;
3299 /* Perform the carry for the later subtraction by updating y. This
3300 is safer because on some systems the tv_sec member is unsigned. */
3301 if (x
.tv_usec
< y
.tv_usec
)
3303 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3304 y
.tv_usec
-= 1000000 * nsec
;
3308 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3310 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3311 y
.tv_usec
+= 1000000 * nsec
;
3315 /* Compute the time remaining to wait. tv_usec is certainly
3317 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3318 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3320 /* Return indication of whether the result should be considered
3322 return x
.tv_sec
< y
.tv_sec
;
3334 struct timeval wakeup
;
3336 EMACS_GET_TIME (wakeup
);
3338 /* Compute time to wait until, propagating carry from usecs. */
3339 wakeup
.tv_usec
+= 150000;
3340 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3341 wakeup
.tv_usec
%= 1000000;
3343 /* Keep waiting until past the time wakeup. */
3346 struct timeval timeout
;
3348 EMACS_GET_TIME (timeout
);
3350 /* In effect, timeout = wakeup - timeout.
3351 Break if result would be negative. */
3352 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3355 /* Try to wait that long--but we might wake up sooner. */
3356 select (0, NULL
, NULL
, NULL
, &timeout
);
3365 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3368 /* Make audible bell. */
3373 struct frame
*f
= SELECTED_FRAME ();
3375 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3383 XFlush (FRAME_MAC_DISPLAY (f
));
3390 /* Specify how many text lines, from the top of the window,
3391 should be affected by insert-lines and delete-lines operations.
3392 This, and those operations, are used only within an update
3393 that is bounded by calls to x_update_begin and x_update_end. */
3396 XTset_terminal_window (n
)
3399 /* This function intentionally left blank. */
3404 /***********************************************************************
3406 ***********************************************************************/
3408 /* Perform an insert-lines or delete-lines operation, inserting N
3409 lines or deleting -N lines at vertical position VPOS. */
3412 x_ins_del_lines (vpos
, n
)
3419 /* Scroll part of the display as described by RUN. */
3422 x_scroll_run (w
, run
)
3426 struct frame
*f
= XFRAME (w
->frame
);
3427 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3429 /* Get frame-relative bounding box of the text display area of W,
3430 without mode lines. Include in this box the left and right
3432 window_box (w
, -1, &x
, &y
, &width
, &height
);
3434 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3435 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3436 bottom_y
= y
+ height
;
3440 /* Scrolling up. Make sure we don't copy part of the mode
3441 line at the bottom. */
3442 if (from_y
+ run
->height
> bottom_y
)
3443 height
= bottom_y
- from_y
;
3445 height
= run
->height
;
3449 /* Scolling down. Make sure we don't copy over the mode line.
3451 if (to_y
+ run
->height
> bottom_y
)
3452 height
= bottom_y
- to_y
;
3454 height
= run
->height
;
3459 /* Cursor off. Will be switched on again in x_update_window_end. */
3463 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3464 f
->output_data
.mac
->normal_gc
,
3474 /***********************************************************************
3476 ***********************************************************************/
3484 ControlRef root_control
;
3487 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3489 ActivateControl (root_control
);
3491 x_update_cursor (f
, 1);
3495 frame_unhighlight (f
)
3499 ControlRef root_control
;
3502 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3504 DeactivateControl (root_control
);
3506 x_update_cursor (f
, 1);
3509 /* The focus has changed. Update the frames as necessary to reflect
3510 the new situation. Note that we can't change the selected frame
3511 here, because the Lisp code we are interrupting might become confused.
3512 Each event gets marked with the frame in which it occurred, so the
3513 Lisp code can tell when the switch took place by examining the events. */
3516 x_new_focus_frame (dpyinfo
, frame
)
3517 struct x_display_info
*dpyinfo
;
3518 struct frame
*frame
;
3520 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3522 if (frame
!= dpyinfo
->x_focus_frame
)
3524 /* Set this before calling other routines, so that they see
3525 the correct value of x_focus_frame. */
3526 dpyinfo
->x_focus_frame
= frame
;
3528 if (old_focus
&& old_focus
->auto_lower
)
3529 x_lower_frame (old_focus
);
3532 selected_frame
= frame
;
3533 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3535 Fselect_window (selected_frame
->selected_window
, Qnil
);
3536 choose_minibuf_frame ();
3539 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3540 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3542 pending_autoraise_frame
= 0;
3545 x_frame_rehighlight (dpyinfo
);
3548 /* Handle FocusIn and FocusOut state changes for FRAME.
3549 If FRAME has focus and there exists more than one frame, puts
3550 a FOCUS_IN_EVENT into *BUFP. */
3553 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3555 struct mac_display_info
*dpyinfo
;
3556 struct frame
*frame
;
3557 struct input_event
*bufp
;
3559 if (type
== activeFlag
)
3561 if (dpyinfo
->x_focus_event_frame
!= frame
)
3563 x_new_focus_frame (dpyinfo
, frame
);
3564 dpyinfo
->x_focus_event_frame
= frame
;
3566 /* Don't stop displaying the initial startup message
3567 for a switch-frame event we don't need. */
3568 if (GC_NILP (Vterminal_frame
)
3569 && GC_CONSP (Vframe_list
)
3570 && !GC_NILP (XCDR (Vframe_list
)))
3572 bufp
->kind
= FOCUS_IN_EVENT
;
3573 XSETFRAME (bufp
->frame_or_window
, frame
);
3579 if (dpyinfo
->x_focus_event_frame
== frame
)
3581 dpyinfo
->x_focus_event_frame
= 0;
3582 x_new_focus_frame (dpyinfo
, 0);
3587 /* The focus may have changed. Figure out if it is a real focus change,
3588 by checking both FocusIn/Out and Enter/LeaveNotify events.
3590 Returns FOCUS_IN_EVENT event in *BUFP. */
3593 x_detect_focus_change (dpyinfo
, event
, bufp
)
3594 struct mac_display_info
*dpyinfo
;
3596 struct input_event
*bufp
;
3598 struct frame
*frame
;
3600 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3604 /* On Mac, this is only called from focus events, so no switch needed. */
3605 mac_focus_changed ((event
->modifiers
& activeFlag
),
3606 dpyinfo
, frame
, bufp
);
3610 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3613 x_mouse_leave (dpyinfo
)
3614 struct x_display_info
*dpyinfo
;
3616 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3619 /* The focus has changed, or we have redirected a frame's focus to
3620 another frame (this happens when a frame uses a surrogate
3621 mini-buffer frame). Shift the highlight as appropriate.
3623 The FRAME argument doesn't necessarily have anything to do with which
3624 frame is being highlighted or un-highlighted; we only use it to find
3625 the appropriate X display info. */
3628 XTframe_rehighlight (frame
)
3629 struct frame
*frame
;
3631 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3635 x_frame_rehighlight (dpyinfo
)
3636 struct x_display_info
*dpyinfo
;
3638 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3640 if (dpyinfo
->x_focus_frame
)
3642 dpyinfo
->x_highlight_frame
3643 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3644 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3645 : dpyinfo
->x_focus_frame
);
3646 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3648 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3649 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3653 dpyinfo
->x_highlight_frame
= 0;
3655 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3658 frame_unhighlight (old_highlight
);
3659 if (dpyinfo
->x_highlight_frame
)
3660 frame_highlight (dpyinfo
->x_highlight_frame
);
3666 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3668 #if 0 /* MAC_TODO */
3669 /* Initialize mode_switch_bit and modifier_meaning. */
3671 x_find_modifier_meanings (dpyinfo
)
3672 struct x_display_info
*dpyinfo
;
3674 int min_code
, max_code
;
3677 XModifierKeymap
*mods
;
3679 dpyinfo
->meta_mod_mask
= 0;
3680 dpyinfo
->shift_lock_mask
= 0;
3681 dpyinfo
->alt_mod_mask
= 0;
3682 dpyinfo
->super_mod_mask
= 0;
3683 dpyinfo
->hyper_mod_mask
= 0;
3686 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3688 min_code
= dpyinfo
->display
->min_keycode
;
3689 max_code
= dpyinfo
->display
->max_keycode
;
3692 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3693 min_code
, max_code
- min_code
+ 1,
3695 mods
= XGetModifierMapping (dpyinfo
->display
);
3697 /* Scan the modifier table to see which modifier bits the Meta and
3698 Alt keysyms are on. */
3700 int row
, col
; /* The row and column in the modifier table. */
3702 for (row
= 3; row
< 8; row
++)
3703 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3706 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3708 /* Zeroes are used for filler. Skip them. */
3712 /* Are any of this keycode's keysyms a meta key? */
3716 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3718 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3724 dpyinfo
->meta_mod_mask
|= (1 << row
);
3729 dpyinfo
->alt_mod_mask
|= (1 << row
);
3734 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3739 dpyinfo
->super_mod_mask
|= (1 << row
);
3743 /* Ignore this if it's not on the lock modifier. */
3744 if ((1 << row
) == LockMask
)
3745 dpyinfo
->shift_lock_mask
= LockMask
;
3753 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3754 if (! dpyinfo
->meta_mod_mask
)
3756 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3757 dpyinfo
->alt_mod_mask
= 0;
3760 /* If some keys are both alt and meta,
3761 make them just meta, not alt. */
3762 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3764 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3767 XFree ((char *) syms
);
3768 XFreeModifiermap (mods
);
3771 #endif /* MAC_TODO */
3773 /* Convert between the modifier bits X uses and the modifier bits
3777 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3778 struct x_display_info
*dpyinfo
;
3779 unsigned short state
;
3781 return (((state
& shiftKey
) ? shift_modifier
: 0)
3782 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3783 | ((state
& cmdKey
) ? meta_modifier
: 0)
3784 | ((state
& optionKey
) ? alt_modifier
: 0));
3787 #if 0 /* MAC_TODO */
3788 static unsigned short
3789 x_emacs_to_x_modifiers (dpyinfo
, state
)
3790 struct x_display_info
*dpyinfo
;
3793 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3794 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3795 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3796 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3797 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3798 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3800 #endif /* MAC_TODO */
3802 /* Convert a keysym to its name. */
3805 x_get_keysym_name (keysym
)
3812 value
= XKeysymToString (keysym
);
3824 /* Mouse clicks and mouse movement. Rah. */
3826 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3828 If the event is a button press, then note that we have grabbed
3832 construct_mouse_click (result
, event
, f
)
3833 struct input_event
*result
;
3839 result
->kind
= MOUSE_CLICK_EVENT
;
3840 result
->code
= 0; /* only one mouse button */
3841 result
->timestamp
= event
->when
;
3842 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3844 mouseLoc
= event
->where
;
3846 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3848 GlobalToLocal (&mouseLoc
);
3849 XSETINT (result
->x
, mouseLoc
.h
);
3850 XSETINT (result
->y
, mouseLoc
.v
);
3852 XSETFRAME (result
->frame_or_window
, f
);
3860 /* Function to report a mouse movement to the mainstream Emacs code.
3861 The input handler calls this.
3863 We have received a mouse movement event, which is given in *event.
3864 If the mouse is over a different glyph than it was last time, tell
3865 the mainstream emacs code by setting mouse_moved. If not, ask for
3866 another motion event, so we can check again the next time it moves. */
3868 static Point last_mouse_motion_position
;
3869 static Lisp_Object last_mouse_motion_frame
;
3872 note_mouse_movement (frame
, pos
)
3876 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3877 #if TARGET_API_MAC_CARBON
3881 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3882 last_mouse_motion_position
= *pos
;
3883 XSETFRAME (last_mouse_motion_frame
, frame
);
3885 #if TARGET_API_MAC_CARBON
3886 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3888 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3891 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3892 /* This case corresponds to LeaveNotify in X11. */
3894 /* If we move outside the frame, then we're certainly no
3895 longer on any text in the frame. */
3896 clear_mouse_face (dpyinfo
);
3897 dpyinfo
->mouse_face_mouse_frame
= 0;
3898 if (!dpyinfo
->grabbed
)
3899 rif
->define_frame_cursor (frame
,
3900 frame
->output_data
.mac
->nontext_cursor
);
3903 /* Has the mouse moved off the glyph it was on at the last sighting? */
3904 else if (pos
->h
< last_mouse_glyph
.left
3905 || pos
->h
>= last_mouse_glyph
.right
3906 || pos
->v
< last_mouse_glyph
.top
3907 || pos
->v
>= last_mouse_glyph
.bottom
)
3909 frame
->mouse_moved
= 1;
3910 last_mouse_scroll_bar
= Qnil
;
3911 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3915 /* This is used for debugging, to turn off note_mouse_highlight. */
3917 int disable_mouse_highlight
;
3921 /************************************************************************
3923 ************************************************************************/
3925 static struct scroll_bar
*x_window_to_scroll_bar ();
3926 static void x_scroll_bar_report_motion ();
3927 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3930 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3933 redo_mouse_highlight ()
3935 if (!NILP (last_mouse_motion_frame
)
3936 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3937 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3938 last_mouse_motion_position
.h
,
3939 last_mouse_motion_position
.v
);
3943 /* Try to determine frame pixel position and size of the glyph under
3944 frame pixel coordinates X/Y on frame F . Return the position and
3945 size in *RECT. Value is non-zero if we could compute these
3949 glyph_rect (f
, x
, y
, rect
)
3956 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3960 struct window
*w
= XWINDOW (window
);
3961 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3962 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3964 for (; r
< end
&& r
->enabled_p
; ++r
)
3965 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3967 /* Found the row at y. */
3968 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3969 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3972 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3973 rect
->bottom
= rect
->top
+ r
->height
;
3977 /* x is to the left of the first glyph in the row. */
3978 /* Shouldn't this be a pixel value?
3979 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3981 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3982 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3986 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3987 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3989 /* x is on a glyph. */
3990 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3991 rect
->right
= rect
->left
+ g
->pixel_width
;
3995 /* x is to the right of the last glyph in the row. */
3996 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3997 /* Shouldn't this be a pixel value?
3998 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
4000 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
4005 /* The y is not on any row. */
4009 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4011 /* Record the position of the mouse in last_mouse_glyph. */
4013 remember_mouse_glyph (f1
, gx
, gy
)
4017 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
4019 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
4020 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
4022 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
4023 round down even for negative values. */
4029 /* This was the original code from XTmouse_position, but it seems
4030 to give the position of the glyph diagonally next to the one
4031 the mouse is over. */
4032 gx
= (gx
+ width
- 1) / width
* width
;
4033 gy
= (gy
+ height
- 1) / height
* height
;
4035 gx
= gx
/ width
* width
;
4036 gy
= gy
/ height
* height
;
4039 last_mouse_glyph
.left
= gx
;
4040 last_mouse_glyph
.top
= gy
;
4041 last_mouse_glyph
.right
= gx
+ width
;
4042 last_mouse_glyph
.bottom
= gy
+ height
;
4047 static struct frame
*
4048 mac_focus_frame (dpyinfo
)
4049 struct mac_display_info
*dpyinfo
;
4051 if (dpyinfo
->x_focus_frame
)
4052 return dpyinfo
->x_focus_frame
;
4054 /* Mac version may get events, such as a menu bar click, even when
4055 all the frames are invisible. In this case, we regard the
4056 event came to the selected frame. */
4057 return SELECTED_FRAME ();
4061 /* Return the current position of the mouse.
4062 *fp should be a frame which indicates which display to ask about.
4064 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4065 and *part to the frame, window, and scroll bar part that the mouse
4066 is over. Set *x and *y to the portion and whole of the mouse's
4067 position on the scroll bar.
4069 If the mouse movement started elsewhere, set *fp to the frame the
4070 mouse is on, *bar_window to nil, and *x and *y to the character cell
4073 Set *time to the server time-stamp for the time at which the mouse
4074 was at this position.
4076 Don't store anything if we don't have a valid set of values to report.
4078 This clears the mouse_moved flag, so we can wait for the next mouse
4082 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4085 Lisp_Object
*bar_window
;
4086 enum scroll_bar_part
*part
;
4088 unsigned long *time
;
4091 int ignore1
, ignore2
;
4092 struct frame
*f
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4093 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
4094 Lisp_Object frame
, tail
;
4098 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4099 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4102 /* Clear the mouse-moved flag for every frame on this display. */
4103 FOR_EACH_FRAME (tail
, frame
)
4104 XFRAME (frame
)->mouse_moved
= 0;
4106 last_mouse_scroll_bar
= Qnil
;
4108 SetPortWindowPort (wp
);
4110 GetMouse (&mouse_pos
);
4112 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4113 &last_mouse_glyph
, insist
);
4116 *part
= scroll_bar_handle
;
4118 XSETINT (*x
, mouse_pos
.h
);
4119 XSETINT (*y
, mouse_pos
.v
);
4120 *time
= last_mouse_movement_time
;
4127 /************************************************************************
4129 ************************************************************************/
4131 #ifdef USE_TOOLKIT_SCROLL_BARS
4133 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4134 static OSStatus install_scroll_bar_timer
P_ ((void));
4135 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4136 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4137 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4139 struct input_event
*));
4140 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4142 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4145 struct input_event
*));
4146 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4148 struct input_event
*));
4149 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4150 Point
, unsigned long,
4151 struct input_event
*));
4152 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4155 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4157 static int last_scroll_bar_part
;
4159 static EventLoopTimerRef scroll_bar_timer
;
4161 static int scroll_bar_timer_event_posted_p
;
4163 #define SCROLL_BAR_FIRST_DELAY 0.5
4164 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4167 scroll_bar_timer_callback (timer
, data
)
4168 EventLoopTimerRef timer
;
4171 EventRef event
= NULL
;
4174 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4175 kEventAttributeNone
, &event
);
4180 GetMouse (&mouse_pos
);
4181 LocalToGlobal (&mouse_pos
);
4182 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4183 sizeof (Point
), &mouse_pos
);
4187 UInt32 modifiers
= GetCurrentKeyModifiers ();
4189 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4190 sizeof (UInt32
), &modifiers
);
4193 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4194 kEventPriorityStandard
);
4196 scroll_bar_timer_event_posted_p
= 1;
4199 ReleaseEvent (event
);
4203 install_scroll_bar_timer ()
4205 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4207 if (scroll_bar_timer_callbackUPP
== NULL
)
4208 scroll_bar_timer_callbackUPP
=
4209 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4211 if (scroll_bar_timer
== NULL
)
4212 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4213 kEventDurationForever as delays. */
4215 InstallEventLoopTimer (GetCurrentEventLoop (),
4216 kEventDurationForever
, kEventDurationForever
,
4217 scroll_bar_timer_callbackUPP
, NULL
,
4222 set_scroll_bar_timer (delay
)
4223 EventTimerInterval delay
;
4225 if (scroll_bar_timer
== NULL
)
4226 install_scroll_bar_timer ();
4228 scroll_bar_timer_event_posted_p
= 0;
4230 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4234 control_part_code_to_scroll_bar_part (part_code
)
4235 ControlPartCode part_code
;
4239 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4240 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4241 case kControlPageUpPart
: return scroll_bar_above_handle
;
4242 case kControlPageDownPart
: return scroll_bar_below_handle
;
4243 case kControlIndicatorPart
: return scroll_bar_handle
;
4250 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
)
4251 struct scroll_bar
*bar
;
4253 unsigned long timestamp
;
4254 struct input_event
*bufp
;
4256 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4257 bufp
->frame_or_window
= bar
->window
;
4261 bufp
->timestamp
= timestamp
;
4262 XSETINT (bufp
->x
, 0);
4263 XSETINT (bufp
->y
, 0);
4264 bufp
->modifiers
= 0;
4268 get_control_part_bounds (ch
, part_code
, rect
)
4270 ControlPartCode part_code
;
4273 RgnHandle region
= NewRgn ();
4276 err
= GetControlRegion (ch
, part_code
, region
);
4278 GetRegionBounds (region
, rect
);
4279 DisposeRgn (region
);
4285 x_scroll_bar_handle_press (bar
, part_code
, timestamp
, bufp
)
4286 struct scroll_bar
*bar
;
4287 ControlPartCode part_code
;
4288 unsigned long timestamp
;
4289 struct input_event
*bufp
;
4291 int part
= control_part_code_to_scroll_bar_part (part_code
);
4296 if (part
!= scroll_bar_handle
)
4298 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
);
4299 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4300 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4303 last_scroll_bar_part
= part
;
4304 bar
->dragging
= Qnil
;
4305 tracked_scroll_bar
= bar
;
4309 x_scroll_bar_handle_release (bar
, timestamp
, bufp
)
4310 struct scroll_bar
*bar
;
4311 unsigned long timestamp
;
4312 struct input_event
*bufp
;
4314 if (last_scroll_bar_part
!= scroll_bar_handle
4315 || !GC_NILP (bar
->dragging
))
4316 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, timestamp
, bufp
);
4318 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4319 set_scroll_bar_timer (kEventDurationForever
);
4321 last_scroll_bar_part
= -1;
4322 bar
->dragging
= Qnil
;
4323 tracked_scroll_bar
= NULL
;
4327 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, timestamp
, bufp
)
4329 struct scroll_bar
*bar
;
4331 unsigned long timestamp
;
4332 struct input_event
*bufp
;
4334 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4336 if (last_scroll_bar_part
== scroll_bar_handle
)
4341 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4342 kControlIndicatorPart
, &r
);
4344 if (GC_NILP (bar
->dragging
))
4345 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4347 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4348 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4349 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4354 if (top
> top_range
)
4357 construct_scroll_bar_click (bar
, scroll_bar_handle
, timestamp
, bufp
);
4358 XSETINT (bufp
->x
, top
);
4359 XSETINT (bufp
->y
, top_range
);
4363 ControlPartCode part_code
;
4364 int unhilite_p
= 0, part
;
4366 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4370 part
= control_part_code_to_scroll_bar_part (part_code
);
4372 switch (last_scroll_bar_part
)
4374 case scroll_bar_above_handle
:
4375 case scroll_bar_below_handle
:
4376 if (part
!= scroll_bar_above_handle
4377 && part
!= scroll_bar_below_handle
)
4381 case scroll_bar_up_arrow
:
4382 case scroll_bar_down_arrow
:
4383 if (part
!= scroll_bar_up_arrow
4384 && part
!= scroll_bar_down_arrow
)
4391 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4392 else if (part
!= last_scroll_bar_part
4393 || scroll_bar_timer_event_posted_p
)
4395 construct_scroll_bar_click (bar
, part
, timestamp
, bufp
);
4396 last_scroll_bar_part
= part
;
4397 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4398 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4403 /* Set the thumb size and position of scroll bar BAR. We are currently
4404 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4407 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4408 struct scroll_bar
*bar
;
4409 int portion
, position
, whole
;
4411 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4413 int value
, viewsize
, maximum
;
4415 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4416 value
= 0, viewsize
= 1, maximum
= 0;
4421 maximum
= max (0, whole
- portion
);
4426 SetControl32BitMinimum (ch
, 0);
4427 SetControl32BitMaximum (ch
, maximum
);
4428 SetControl32BitValue (ch
, value
);
4429 SetControlViewSize (ch
, viewsize
);
4434 #endif /* USE_TOOLKIT_SCROLL_BARS */
4438 /************************************************************************
4439 Scroll bars, general
4440 ************************************************************************/
4442 /* Create a scroll bar and return the scroll bar vector for it. W is
4443 the Emacs window on which to create the scroll bar. TOP, LEFT,
4444 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4447 static struct scroll_bar
*
4448 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4450 int top
, left
, width
, height
, disp_top
, disp_height
;
4452 struct frame
*f
= XFRAME (w
->frame
);
4453 struct scroll_bar
*bar
4454 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4462 r
.right
= left
+ width
;
4463 r
.bottom
= disp_top
+ disp_height
;
4465 #if TARGET_API_MAC_CARBON
4466 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4467 kControlScrollBarProc
, (long) bar
);
4469 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4470 scrollBarProc
, (long) bar
);
4472 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4474 XSETWINDOW (bar
->window
, w
);
4475 XSETINT (bar
->top
, top
);
4476 XSETINT (bar
->left
, left
);
4477 XSETINT (bar
->width
, width
);
4478 XSETINT (bar
->height
, height
);
4479 XSETINT (bar
->start
, 0);
4480 XSETINT (bar
->end
, 0);
4481 bar
->dragging
= Qnil
;
4482 #ifdef USE_TOOLKIT_SCROLL_BARS
4483 bar
->track_top
= Qnil
;
4484 bar
->track_height
= Qnil
;
4487 /* Add bar to its frame's list of scroll bars. */
4488 bar
->next
= FRAME_SCROLL_BARS (f
);
4490 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4491 if (!NILP (bar
->next
))
4492 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4499 /* Draw BAR's handle in the proper position.
4501 If the handle is already drawn from START to END, don't bother
4502 redrawing it, unless REBUILD is non-zero; in that case, always
4503 redraw it. (REBUILD is handy for drawing the handle after expose
4506 Normally, we want to constrain the start and end of the handle to
4507 fit inside its rectangle, but if the user is dragging the scroll
4508 bar handle, we want to let them drag it down all the way, so that
4509 the bar's top is as far down as it goes; otherwise, there's no way
4510 to move to the very end of the buffer. */
4512 #ifndef USE_TOOLKIT_SCROLL_BARS
4515 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4516 struct scroll_bar
*bar
;
4520 int dragging
= ! NILP (bar
->dragging
);
4521 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4522 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4523 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4524 int length
= end
- start
;
4526 /* If the display is already accurate, do nothing. */
4528 && start
== XINT (bar
->start
)
4529 && end
== XINT (bar
->end
))
4534 /* Make sure the values are reasonable, and try to preserve the
4535 distance between start and end. */
4538 else if (start
> top_range
)
4540 end
= start
+ length
;
4544 else if (end
> top_range
&& ! dragging
)
4547 /* Store the adjusted setting in the scroll bar. */
4548 XSETINT (bar
->start
, start
);
4549 XSETINT (bar
->end
, end
);
4551 /* Clip the end position, just for display. */
4552 if (end
> top_range
)
4555 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4556 top positions, to make sure the handle is always at least that
4557 many pixels tall. */
4558 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4560 SetControlMinimum (ch
, 0);
4561 /* Don't inadvertently activate deactivated scroll bars */
4562 if (GetControlMaximum (ch
) != -1)
4563 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4565 SetControlValue (ch
, start
);
4566 #if TARGET_API_MAC_CARBON
4567 SetControlViewSize (ch
, end
- start
);
4573 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4575 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4579 x_scroll_bar_remove (bar
)
4580 struct scroll_bar
*bar
;
4582 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4586 /* Destroy the Mac scroll bar control */
4587 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4589 /* Disassociate this scroll bar from its window. */
4590 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4595 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4596 that we are displaying PORTION characters out of a total of WHOLE
4597 characters, starting at POSITION. If WINDOW has no scroll bar,
4600 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4602 int portion
, whole
, position
;
4604 struct frame
*f
= XFRAME (w
->frame
);
4605 struct scroll_bar
*bar
;
4606 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4607 int window_y
, window_height
;
4609 /* Get window dimensions. */
4610 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4612 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4613 height
= window_height
;
4615 /* Compute the left edge of the scroll bar area. */
4616 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4618 /* Compute the width of the scroll bar which might be less than
4619 the width of the area reserved for the scroll bar. */
4620 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4621 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4625 /* Compute the left edge of the scroll bar. */
4626 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4629 sb_left
= left
+ width
- sb_width
;
4631 /* Adjustments according to Inside Macintosh to make it look nice */
4633 disp_height
= height
;
4639 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4645 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4648 /* Does the scroll bar exist yet? */
4649 if (NILP (w
->vertical_scroll_bar
))
4652 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4653 left
, top
, width
, height
, 0);
4655 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4657 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4661 /* It may just need to be moved and resized. */
4664 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4665 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4669 /* If already correctly positioned, do nothing. */
4670 if (!(XINT (bar
->left
) == sb_left
4671 && XINT (bar
->top
) == top
4672 && XINT (bar
->width
) == sb_width
4673 && XINT (bar
->height
) == height
))
4675 /* Clear areas not covered by the scroll bar because it's not as
4676 wide as the area reserved for it . This makes sure a
4677 previous mode line display is cleared after C-x 2 C-x 1, for
4679 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4680 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4681 left
, top
, area_width
, height
, 0);
4684 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4685 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4686 sb_left
- 1, top
, 1, height
, 0);
4690 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4691 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4695 /* Remember new settings. */
4696 XSETINT (bar
->left
, sb_left
);
4697 XSETINT (bar
->top
, top
);
4698 XSETINT (bar
->width
, sb_width
);
4699 XSETINT (bar
->height
, height
);
4700 #ifdef USE_TOOLKIT_SCROLL_BARS
4701 bar
->track_top
= Qnil
;
4702 bar
->track_height
= Qnil
;
4709 #ifdef USE_TOOLKIT_SCROLL_BARS
4710 if (NILP (bar
->track_top
))
4712 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4717 SetControl32BitMinimum (ch
, 0);
4718 SetControl32BitMaximum (ch
, 1);
4719 SetControlViewSize (ch
, 1);
4721 /* Move the scroll bar thumb to the top. */
4722 SetControl32BitValue (ch
, 0);
4723 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4725 /* Move the scroll bar thumb to the bottom. */
4726 SetControl32BitValue (ch
, 1);
4727 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4729 UnionRect (&r0
, &r1
, &r0
);
4730 XSETINT (bar
->track_top
, r0
.top
);
4731 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4736 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4737 #else /* not USE_TOOLKIT_SCROLL_BARS */
4738 /* Set the scroll bar's current state, unless we're currently being
4740 if (NILP (bar
->dragging
))
4742 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4745 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4748 int start
= ((double) position
* top_range
) / whole
;
4749 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4750 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4753 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4757 /* The following three hooks are used when we're doing a thorough
4758 redisplay of the frame. We don't explicitly know which scroll bars
4759 are going to be deleted, because keeping track of when windows go
4760 away is a real pain - "Can you say set-window-configuration, boys
4761 and girls?" Instead, we just assert at the beginning of redisplay
4762 that *all* scroll bars are to be removed, and then save a scroll bar
4763 from the fiery pit when we actually redisplay its window. */
4765 /* Arrange for all scroll bars on FRAME to be removed at the next call
4766 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4767 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4770 XTcondemn_scroll_bars (frame
)
4773 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4774 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4777 bar
= FRAME_SCROLL_BARS (frame
);
4778 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4779 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4780 XSCROLL_BAR (bar
)->prev
= Qnil
;
4781 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4782 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4783 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4788 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4789 Note that WINDOW isn't necessarily condemned at all. */
4792 XTredeem_scroll_bar (window
)
4793 struct window
*window
;
4795 struct scroll_bar
*bar
;
4797 /* We can't redeem this window's scroll bar if it doesn't have one. */
4798 if (NILP (window
->vertical_scroll_bar
))
4801 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4803 /* Unlink it from the condemned list. */
4805 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4807 if (NILP (bar
->prev
))
4809 /* If the prev pointer is nil, it must be the first in one of
4811 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4812 /* It's not condemned. Everything's fine. */
4814 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4815 window
->vertical_scroll_bar
))
4816 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4818 /* If its prev pointer is nil, it must be at the front of
4819 one or the other! */
4823 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4825 if (! NILP (bar
->next
))
4826 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4828 bar
->next
= FRAME_SCROLL_BARS (f
);
4830 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4831 if (! NILP (bar
->next
))
4832 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4836 /* Remove all scroll bars on FRAME that haven't been saved since the
4837 last call to `*condemn_scroll_bars_hook'. */
4840 XTjudge_scroll_bars (f
)
4843 Lisp_Object bar
, next
;
4845 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4847 /* Clear out the condemned list now so we won't try to process any
4848 more events on the hapless scroll bars. */
4849 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4851 for (; ! NILP (bar
); bar
= next
)
4853 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4855 x_scroll_bar_remove (b
);
4858 b
->next
= b
->prev
= Qnil
;
4861 /* Now there should be no references to the condemned scroll bars,
4862 and they should get garbage-collected. */
4866 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4867 is set to something other than NO_EVENT, it is enqueued.
4869 This may be called from a signal handler, so we have to ignore GC
4873 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4874 struct scroll_bar
*bar
;
4875 ControlPartCode part_code
;
4877 struct input_event
*bufp
;
4879 int win_y
, top_range
;
4881 if (! GC_WINDOWP (bar
->window
))
4884 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4885 bufp
->frame_or_window
= bar
->window
;
4888 bar
->dragging
= Qnil
;
4892 case kControlUpButtonPart
:
4893 bufp
->part
= scroll_bar_up_arrow
;
4895 case kControlDownButtonPart
:
4896 bufp
->part
= scroll_bar_down_arrow
;
4898 case kControlPageUpPart
:
4899 bufp
->part
= scroll_bar_above_handle
;
4901 case kControlPageDownPart
:
4902 bufp
->part
= scroll_bar_below_handle
;
4904 #if TARGET_API_MAC_CARBON
4907 case kControlIndicatorPart
:
4909 if (er
->what
== mouseDown
)
4910 bar
->dragging
= make_number (0);
4911 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4912 bufp
->part
= scroll_bar_handle
;
4916 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4917 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4919 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4923 if (! NILP (bar
->dragging
))
4924 win_y
-= XINT (bar
->dragging
);
4928 if (win_y
> top_range
)
4931 XSETINT (bufp
->x
, win_y
);
4932 XSETINT (bufp
->y
, top_range
);
4935 #ifndef USE_TOOLKIT_SCROLL_BARS
4937 /* Handle some mouse motion while someone is dragging the scroll bar.
4939 This may be called from a signal handler, so we have to ignore GC
4943 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4944 struct scroll_bar
*bar
;
4948 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4950 last_mouse_movement_time
= t
;
4953 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4955 /* If we're dragging the bar, display it. */
4956 if (! GC_NILP (bar
->dragging
))
4958 /* Where should the handle be now? */
4959 int new_start
= y_pos
- 24;
4961 if (new_start
!= XINT (bar
->start
))
4963 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4965 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4970 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4972 /* Return information to the user about the current position of the
4973 mouse on the scroll bar. */
4976 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4978 Lisp_Object
*bar_window
;
4979 enum scroll_bar_part
*part
;
4981 unsigned long *time
;
4983 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4984 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4985 #if TARGET_API_MAC_CARBON
4986 WindowPtr wp
= GetControlOwner (ch
);
4988 WindowPtr wp
= (*ch
)->contrlOwner
;
4991 struct frame
*f
= mac_window_to_frame (wp
);
4992 int win_y
, top_range
;
4994 SetPortWindowPort (wp
);
4996 GetMouse (&mouse_pos
);
4998 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4999 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5001 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5005 if (! NILP (bar
->dragging
))
5006 win_y
-= XINT (bar
->dragging
);
5010 if (win_y
> top_range
)
5014 *bar_window
= bar
->window
;
5016 if (! NILP (bar
->dragging
))
5017 *part
= scroll_bar_handle
;
5018 else if (win_y
< XINT (bar
->start
))
5019 *part
= scroll_bar_above_handle
;
5020 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5021 *part
= scroll_bar_handle
;
5023 *part
= scroll_bar_below_handle
;
5025 XSETINT (*x
, win_y
);
5026 XSETINT (*y
, top_range
);
5029 last_mouse_scroll_bar
= Qnil
;
5031 *time
= last_mouse_movement_time
;
5035 /* The screen has been cleared so we may have changed foreground or
5036 background colors, and the scroll bars may need to be redrawn.
5037 Clear out the scroll bars, and ask for expose events, so we can
5041 x_scroll_bar_clear (f
)
5044 XTcondemn_scroll_bars (f
);
5045 XTjudge_scroll_bars (f
);
5049 /***********************************************************************
5051 ***********************************************************************/
5053 /* Set clipping for output in glyph row ROW. W is the window in which
5054 we operate. GC is the graphics context to set clipping in.
5056 ROW may be a text row or, e.g., a mode line. Text rows must be
5057 clipped to the interior of the window dedicated to text display,
5058 mode lines must be clipped to the whole window. */
5061 x_clip_to_row (w
, row
, area
, gc
)
5063 struct glyph_row
*row
;
5067 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5069 int window_x
, window_y
, window_width
;
5071 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5073 clip_rect
.left
= window_x
;
5074 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5075 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5076 clip_rect
.right
= clip_rect
.left
+ window_width
;
5077 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5079 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
5083 /* Draw a hollow box cursor on window W in glyph row ROW. */
5086 x_draw_hollow_cursor (w
, row
)
5088 struct glyph_row
*row
;
5090 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5091 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5092 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5095 struct glyph
*cursor_glyph
;
5098 /* Get the glyph the cursor is on. If we can't tell because
5099 the current matrix is invalid or such, give up. */
5100 cursor_glyph
= get_phys_cursor_glyph (w
);
5101 if (cursor_glyph
== NULL
)
5104 /* Compute frame-relative coordinates for phys cursor. */
5105 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5106 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5107 wd
= w
->phys_cursor_width
;
5109 /* The foreground of cursor_gc is typically the same as the normal
5110 background color, which can cause the cursor box to be invisible. */
5111 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5112 if (dpyinfo
->scratch_cursor_gc
)
5113 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5115 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5116 GCForeground
, &xgcv
);
5117 gc
= dpyinfo
->scratch_cursor_gc
;
5119 /* Set clipping, draw the rectangle, and reset clipping again. */
5120 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5121 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
5122 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5126 /* Draw a bar cursor on window W in glyph row ROW.
5128 Implementation note: One would like to draw a bar cursor with an
5129 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5130 Unfortunately, I didn't find a font yet that has this property set.
5134 x_draw_bar_cursor (w
, row
, width
, kind
)
5136 struct glyph_row
*row
;
5138 enum text_cursor_kinds kind
;
5140 struct frame
*f
= XFRAME (w
->frame
);
5141 struct glyph
*cursor_glyph
;
5143 /* If cursor is out of bounds, don't draw garbage. This can happen
5144 in mini-buffer windows when switching between echo area glyphs
5146 cursor_glyph
= get_phys_cursor_glyph (w
);
5147 if (cursor_glyph
== NULL
)
5150 /* If on an image, draw like a normal cursor. That's usually better
5151 visible than drawing a bar, esp. if the image is large so that
5152 the bar might not be in the window. */
5153 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5155 struct glyph_row
*row
;
5156 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5157 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5161 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5162 Window window
= FRAME_MAC_WINDOW (f
);
5163 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5164 unsigned long mask
= GCForeground
| GCBackground
;
5165 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5168 /* If the glyph's background equals the color we normally draw
5169 the bar cursor in, the bar cursor in its normal color is
5170 invisible. Use the glyph's foreground color instead in this
5171 case, on the assumption that the glyph's colors are chosen so
5172 that the glyph is legible. */
5173 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5174 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5176 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5179 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5182 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5183 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5187 width
= FRAME_CURSOR_WIDTH (f
);
5188 width
= min (cursor_glyph
->pixel_width
, width
);
5190 w
->phys_cursor_width
= width
;
5191 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5193 if (kind
== BAR_CURSOR
)
5194 XFillRectangle (dpy
, window
, gc
,
5195 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5196 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5197 width
, row
->height
);
5199 XFillRectangle (dpy
, window
, gc
,
5200 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5201 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5202 row
->height
- width
),
5203 cursor_glyph
->pixel_width
,
5206 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5211 /* RIF: Define cursor CURSOR on frame F. */
5214 mac_define_frame_cursor (f
, cursor
)
5218 SetThemeCursor (cursor
);
5222 /* RIF: Clear area on frame F. */
5225 mac_clear_frame_area (f
, x
, y
, width
, height
)
5227 int x
, y
, width
, height
;
5229 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5230 x
, y
, width
, height
, 0);
5234 /* RIF: Draw cursor on window W. */
5237 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5239 struct glyph_row
*glyph_row
;
5241 int cursor_type
, cursor_width
;
5246 w
->phys_cursor_type
= cursor_type
;
5247 w
->phys_cursor_on_p
= 1;
5249 if (glyph_row
->exact_window_width_line_p
5250 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5252 glyph_row
->cursor_in_fringe_p
= 1;
5253 draw_fringe_bitmap (w
, glyph_row
, 0);
5256 switch (cursor_type
)
5258 case HOLLOW_BOX_CURSOR
:
5259 x_draw_hollow_cursor (w
, glyph_row
);
5262 case FILLED_BOX_CURSOR
:
5263 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5267 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5271 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5275 w
->phys_cursor_width
= 0;
5287 #if 0 /* MAC_TODO: no icon support yet. */
5289 x_bitmap_icon (f
, icon
)
5295 if (FRAME_W32_WINDOW (f
) == 0)
5299 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5300 else if (STRINGP (icon
))
5301 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5302 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5303 else if (SYMBOLP (icon
))
5307 if (EQ (icon
, intern ("application")))
5308 name
= (LPCTSTR
) IDI_APPLICATION
;
5309 else if (EQ (icon
, intern ("hand")))
5310 name
= (LPCTSTR
) IDI_HAND
;
5311 else if (EQ (icon
, intern ("question")))
5312 name
= (LPCTSTR
) IDI_QUESTION
;
5313 else if (EQ (icon
, intern ("exclamation")))
5314 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5315 else if (EQ (icon
, intern ("asterisk")))
5316 name
= (LPCTSTR
) IDI_ASTERISK
;
5317 else if (EQ (icon
, intern ("winlogo")))
5318 name
= (LPCTSTR
) IDI_WINLOGO
;
5322 hicon
= LoadIcon (NULL
, name
);
5330 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5335 #endif /* MAC_TODO */
5337 /************************************************************************
5339 ************************************************************************/
5341 /* Display Error Handling functions not used on W32. Listing them here
5342 helps diff stay in step when comparing w32term.c with xterm.c.
5344 x_error_catcher (display, error)
5345 x_catch_errors (dpy)
5346 x_catch_errors_unwind (old_val)
5347 x_check_errors (dpy, format)
5348 x_had_errors_p (dpy)
5349 x_clear_errors (dpy)
5350 x_uncatch_errors (dpy, count)
5352 x_connection_signal (signalnum)
5353 x_connection_closed (dpy, error_message)
5354 x_error_quitter (display, error)
5355 x_error_handler (display, error)
5356 x_io_error_quitter (display)
5361 /* Changing the font of the frame. */
5363 /* Give frame F the font named FONTNAME as its default font, and
5364 return the full name of that font. FONTNAME may be a wildcard
5365 pattern; in that case, we choose some font that fits the pattern.
5366 The return value shows which font we chose. */
5369 x_new_font (f
, fontname
)
5371 register char *fontname
;
5373 struct font_info
*fontp
5374 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5379 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5380 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5381 FRAME_FONTSET (f
) = -1;
5383 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5384 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5385 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5387 compute_fringe_widths (f
, 1);
5389 /* Compute the scroll bar width in character columns. */
5390 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5392 int wid
= FRAME_COLUMN_WIDTH (f
);
5393 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5394 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5398 int wid
= FRAME_COLUMN_WIDTH (f
);
5399 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5402 /* Now make the frame display the given font. */
5403 if (FRAME_MAC_WINDOW (f
) != 0)
5405 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5407 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5409 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5412 /* Don't change the size of a tip frame; there's no point in
5413 doing it because it's done in Fx_show_tip, and it leads to
5414 problems because the tip frame has no widget. */
5415 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5416 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5419 return build_string (fontp
->full_name
);
5422 /* Give frame F the fontset named FONTSETNAME as its default font, and
5423 return the full name of that fontset. FONTSETNAME may be a wildcard
5424 pattern; in that case, we choose some fontset that fits the pattern.
5425 The return value shows which fontset we chose. */
5428 x_new_fontset (f
, fontsetname
)
5432 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5438 if (FRAME_FONTSET (f
) == fontset
)
5439 /* This fontset is already set in frame F. There's nothing more
5441 return fontset_name (fontset
);
5443 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5445 if (!STRINGP (result
))
5446 /* Can't load ASCII font. */
5449 /* Since x_new_font doesn't update any fontset information, do it now. */
5450 FRAME_FONTSET (f
) = fontset
;
5452 return build_string (fontsetname
);
5456 /***********************************************************************
5457 TODO: W32 Input Methods
5458 ***********************************************************************/
5459 /* Listing missing functions from xterm.c helps diff stay in step.
5461 xim_destroy_callback (xim, client_data, call_data)
5462 xim_open_dpy (dpyinfo, resource_name)
5464 xim_instantiate_callback (display, client_data, call_data)
5465 xim_initialize (dpyinfo, resource_name)
5466 xim_close_dpy (dpyinfo)
5472 mac_get_window_bounds (f
, inner
, outer
)
5474 Rect
*inner
, *outer
;
5476 #if TARGET_API_MAC_CARBON
5477 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5478 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5479 #else /* not TARGET_API_MAC_CARBON */
5480 RgnHandle region
= NewRgn ();
5482 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5483 *inner
= (*region
)->rgnBBox
;
5484 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5485 *outer
= (*region
)->rgnBBox
;
5486 DisposeRgn (region
);
5487 #endif /* not TARGET_API_MAC_CARBON */
5491 /* Calculate the absolute position in frame F
5492 from its current recorded position values and gravity. */
5495 x_calc_absolute_position (f
)
5498 int width_diff
= 0, height_diff
= 0;
5499 int flags
= f
->size_hint_flags
;
5502 /* We have nothing to do if the current position
5503 is already for the top-left corner. */
5504 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5507 /* Find the offsets of the outside upper-left corner of
5508 the inner window, with respect to the outer window. */
5509 mac_get_window_bounds (f
, &inner
, &outer
);
5511 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5512 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5514 /* Treat negative positions as relative to the leftmost bottommost
5515 position that fits on the screen. */
5516 if (flags
& XNegative
)
5517 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5519 - FRAME_PIXEL_WIDTH (f
)
5522 if (flags
& YNegative
)
5523 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5525 - FRAME_PIXEL_HEIGHT (f
)
5528 /* The left_pos and top_pos
5529 are now relative to the top and left screen edges,
5530 so the flags should correspond. */
5531 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5534 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5535 to really change the position, and 0 when calling from
5536 x_make_frame_visible (in that case, XOFF and YOFF are the current
5537 position values). It is -1 when calling from x_set_frame_parameters,
5538 which means, do adjust for borders but don't change the gravity. */
5541 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5543 register int xoff
, yoff
;
5546 if (change_gravity
> 0)
5550 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5552 f
->size_hint_flags
|= XNegative
;
5554 f
->size_hint_flags
|= YNegative
;
5555 f
->win_gravity
= NorthWestGravity
;
5557 x_calc_absolute_position (f
);
5560 x_wm_set_size_hint (f
, (long) 0, 0);
5562 #if TARGET_API_MAC_CARBON
5563 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5564 /* If the title bar is completely outside the screen, adjust the
5566 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5567 kWindowConstrainMoveRegardlessOfFit
5568 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5569 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5572 Rect inner
, outer
, screen_rect
, dummy
;
5573 RgnHandle region
= NewRgn ();
5575 mac_get_window_bounds (f
, &inner
, &outer
);
5576 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5577 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5578 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5579 f
->top_pos
+ f
->y_pixels_diff
, false);
5581 /* If the title bar is completely outside the screen, adjust the
5582 position. The variable `outer' holds the title bar rectangle.
5583 The variable `inner' holds slightly smaller one than `outer',
5584 so that the calculation of overlapping may not become too
5586 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5587 outer
= (*region
)->rgnBBox
;
5588 DisposeRgn (region
);
5590 InsetRect (&inner
, 8, 8);
5591 screen_rect
= qd
.screenBits
.bounds
;
5592 screen_rect
.top
+= GetMBarHeight ();
5594 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5596 if (inner
.right
<= screen_rect
.left
)
5597 f
->left_pos
= screen_rect
.left
;
5598 else if (inner
.left
>= screen_rect
.right
)
5599 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5601 if (inner
.bottom
<= screen_rect
.top
)
5602 f
->top_pos
= screen_rect
.top
;
5603 else if (inner
.top
>= screen_rect
.bottom
)
5604 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5606 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5607 f
->top_pos
+ f
->y_pixels_diff
, false);
5615 /* Call this to change the size of frame F's x-window.
5616 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5617 for this size change and subsequent size changes.
5618 Otherwise we leave the window gravity unchanged. */
5621 x_set_window_size (f
, change_gravity
, cols
, rows
)
5626 int pixelwidth
, pixelheight
;
5630 check_frame_size (f
, &rows
, &cols
);
5631 f
->scroll_bar_actual_width
5632 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5634 compute_fringe_widths (f
, 0);
5636 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5637 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5639 f
->win_gravity
= NorthWestGravity
;
5640 x_wm_set_size_hint (f
, (long) 0, 0);
5642 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5643 #if TARGET_API_MAC_CARBON
5644 if (f
->output_data
.mac
->hourglass_control
)
5645 MoveControl (f
->output_data
.mac
->hourglass_control
,
5646 pixelwidth
- HOURGLASS_WIDTH
, 0);
5649 /* Now, strictly speaking, we can't be sure that this is accurate,
5650 but the window manager will get around to dealing with the size
5651 change request eventually, and we'll hear how it went when the
5652 ConfigureNotify event gets here.
5654 We could just not bother storing any of this information here,
5655 and let the ConfigureNotify event set everything up, but that
5656 might be kind of confusing to the Lisp code, since size changes
5657 wouldn't be reported in the frame parameters until some random
5658 point in the future when the ConfigureNotify event arrives.
5660 We pass 1 for DELAY since we can't run Lisp code inside of
5662 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5663 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5664 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5666 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5667 receive in the ConfigureNotify event; if we get what we asked
5668 for, then the event won't cause the screen to become garbaged, so
5669 we have to make sure to do it here. */
5670 SET_FRAME_GARBAGED (f
);
5672 XFlush (FRAME_X_DISPLAY (f
));
5674 /* If cursor was outside the new size, mark it as off. */
5675 mark_window_cursors_off (XWINDOW (f
->root_window
));
5677 /* Clear out any recollection of where the mouse highlighting was,
5678 since it might be in a place that's outside the new frame size.
5679 Actually checking whether it is outside is a pain in the neck,
5680 so don't try--just let the highlighting be done afresh with new size. */
5681 cancel_mouse_face (f
);
5686 /* Mouse warping. */
5688 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5691 x_set_mouse_position (f
, x
, y
)
5697 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5698 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5700 if (pix_x
< 0) pix_x
= 0;
5701 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5703 if (pix_y
< 0) pix_y
= 0;
5704 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5706 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5710 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5714 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5717 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5718 0, 0, 0, 0, pix_x
, pix_y
);
5724 /* focus shifting, raising and lowering. */
5727 x_focus_on_frame (f
)
5730 #if 0 /* This proves to be unpleasant. */
5734 /* I don't think that the ICCCM allows programs to do things like this
5735 without the interaction of the window manager. Whatever you end up
5736 doing with this code, do it to x_unfocus_frame too. */
5737 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5738 RevertToPointerRoot
, CurrentTime
);
5748 /* Raise frame F. */
5753 if (f
->async_visible
)
5756 SelectWindow (FRAME_MAC_WINDOW (f
));
5761 /* Lower frame F. */
5766 if (f
->async_visible
)
5769 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5775 XTframe_raise_lower (f
, raise_flag
)
5785 /* Change of visibility. */
5787 /* This tries to wait until the frame is really visible.
5788 However, if the window manager asks the user where to position
5789 the frame, this will return before the user finishes doing that.
5790 The frame will not actually be visible at that time,
5791 but it will become visible later when the window manager
5792 finishes with it. */
5795 x_make_frame_visible (f
)
5799 int original_top
, original_left
;
5803 if (! FRAME_VISIBLE_P (f
))
5805 /* We test FRAME_GARBAGED_P here to make sure we don't
5806 call x_set_offset a second time
5807 if we get to x_make_frame_visible a second time
5808 before the window gets really visible. */
5809 if (! FRAME_ICONIFIED_P (f
)
5810 && ! f
->output_data
.mac
->asked_for_visible
)
5811 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5813 f
->output_data
.mac
->asked_for_visible
= 1;
5815 #if TARGET_API_MAC_CARBON
5816 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5818 struct frame
*sf
= SELECTED_FRAME ();
5819 if (!FRAME_MAC_P (sf
))
5820 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5821 kWindowCenterOnMainScreen
);
5823 RepositionWindow (FRAME_MAC_WINDOW (f
),
5824 FRAME_MAC_WINDOW (sf
),
5825 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5826 kWindowCascadeStartAtParentWindowScreen
5828 kWindowCascadeOnParentWindowScreen
5831 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5834 ShowWindow (FRAME_MAC_WINDOW (f
));
5837 XFlush (FRAME_MAC_DISPLAY (f
));
5839 /* Synchronize to ensure Emacs knows the frame is visible
5840 before we do anything else. We do this loop with input not blocked
5841 so that incoming events are handled. */
5846 /* This must come after we set COUNT. */
5849 XSETFRAME (frame
, f
);
5851 /* Wait until the frame is visible. Process X events until a
5852 MapNotify event has been seen, or until we think we won't get a
5853 MapNotify at all.. */
5854 for (count
= input_signal_count
+ 10;
5855 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5857 /* Force processing of queued events. */
5860 /* Machines that do polling rather than SIGIO have been
5861 observed to go into a busy-wait here. So we'll fake an
5862 alarm signal to let the handler know that there's something
5863 to be read. We used to raise a real alarm, but it seems
5864 that the handler isn't always enabled here. This is
5866 if (input_polling_used ())
5868 /* It could be confusing if a real alarm arrives while
5869 processing the fake one. Turn it off and let the
5870 handler reset it. */
5871 extern void poll_for_input_1
P_ ((void));
5872 int old_poll_suppress_count
= poll_suppress_count
;
5873 poll_suppress_count
= 1;
5874 poll_for_input_1 ();
5875 poll_suppress_count
= old_poll_suppress_count
;
5878 /* See if a MapNotify event has been processed. */
5879 FRAME_SAMPLE_VISIBILITY (f
);
5884 /* Change from mapped state to withdrawn state. */
5886 /* Make the frame visible (mapped and not iconified). */
5889 x_make_frame_invisible (f
)
5892 /* Don't keep the highlight on an invisible frame. */
5893 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5894 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5898 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5899 that the current position of the window is user-specified, rather than
5900 program-specified, so that when the window is mapped again, it will be
5901 placed at the same location, without forcing the user to position it
5902 by hand again (they have already done that once for this window.) */
5903 x_wm_set_size_hint (f
, (long) 0, 1);
5905 HideWindow (FRAME_MAC_WINDOW (f
));
5907 /* We can't distinguish this from iconification
5908 just by the event that we get from the server.
5909 So we can't win using the usual strategy of letting
5910 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5911 and synchronize with the server to make sure we agree. */
5913 FRAME_ICONIFIED_P (f
) = 0;
5914 f
->async_visible
= 0;
5915 f
->async_iconified
= 0;
5920 /* Change window state from mapped to iconified. */
5926 /* Don't keep the highlight on an invisible frame. */
5927 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5928 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5931 /* Review: Since window is still visible in dock, still allow updates? */
5932 if (f
->async_iconified
)
5938 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5944 /* Free X resources of frame F. */
5947 x_free_frame_resources (f
)
5950 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5951 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5955 if (wp
!= tip_window
)
5956 remove_window_handler (wp
);
5959 if (wp
== tip_window
)
5960 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5961 closed' event. So we reset tip_window here. */
5964 free_frame_menubar (f
);
5966 if (FRAME_FACE_CACHE (f
))
5967 free_frame_faces (f
);
5971 if (FRAME_SIZE_HINTS (f
))
5972 xfree (FRAME_SIZE_HINTS (f
));
5974 xfree (f
->output_data
.mac
);
5975 f
->output_data
.mac
= NULL
;
5977 if (f
== dpyinfo
->x_focus_frame
)
5978 dpyinfo
->x_focus_frame
= 0;
5979 if (f
== dpyinfo
->x_focus_event_frame
)
5980 dpyinfo
->x_focus_event_frame
= 0;
5981 if (f
== dpyinfo
->x_highlight_frame
)
5982 dpyinfo
->x_highlight_frame
= 0;
5984 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5986 dpyinfo
->mouse_face_beg_row
5987 = dpyinfo
->mouse_face_beg_col
= -1;
5988 dpyinfo
->mouse_face_end_row
5989 = dpyinfo
->mouse_face_end_col
= -1;
5990 dpyinfo
->mouse_face_window
= Qnil
;
5991 dpyinfo
->mouse_face_deferred_gc
= 0;
5992 dpyinfo
->mouse_face_mouse_frame
= 0;
5999 /* Destroy the X window of frame F. */
6002 x_destroy_window (f
)
6005 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6007 x_free_frame_resources (f
);
6009 dpyinfo
->reference_count
--;
6013 /* Setting window manager hints. */
6015 /* Set the normal size hints for the window manager, for frame F.
6016 FLAGS is the flags word to use--or 0 meaning preserve the flags
6017 that the window now has.
6018 If USER_POSITION is nonzero, we set the USPosition
6019 flag (this is useful when FLAGS is 0). */
6021 x_wm_set_size_hint (f
, flags
, user_position
)
6026 int base_width
, base_height
, width_inc
, height_inc
;
6027 int min_rows
= 0, min_cols
= 0;
6028 XSizeHints
*size_hints
;
6030 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6031 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6032 width_inc
= FRAME_COLUMN_WIDTH (f
);
6033 height_inc
= FRAME_LINE_HEIGHT (f
);
6035 check_frame_size (f
, &min_rows
, &min_cols
);
6037 size_hints
= FRAME_SIZE_HINTS (f
);
6038 if (size_hints
== NULL
)
6040 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6041 bzero (size_hints
, sizeof (XSizeHints
));
6044 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6045 size_hints
->width_inc
= width_inc
;
6046 size_hints
->height_inc
= height_inc
;
6047 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6048 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6049 size_hints
->base_width
= base_width
;
6050 size_hints
->base_height
= base_height
;
6053 size_hints
->flags
= flags
;
6054 else if (user_position
)
6056 size_hints
->flags
&= ~ PPosition
;
6057 size_hints
->flags
|= USPosition
;
6061 #if 0 /* MAC_TODO: hide application instead of iconify? */
6062 /* Used for IconicState or NormalState */
6065 x_wm_set_window_state (f
, state
)
6069 #ifdef USE_X_TOOLKIT
6072 XtSetArg (al
[0], XtNinitialState
, state
);
6073 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6074 #else /* not USE_X_TOOLKIT */
6075 Window window
= FRAME_X_WINDOW (f
);
6077 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6078 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6080 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6081 #endif /* not USE_X_TOOLKIT */
6085 x_wm_set_icon_pixmap (f
, pixmap_id
)
6091 #ifndef USE_X_TOOLKIT
6092 Window window
= FRAME_X_WINDOW (f
);
6097 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6098 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6102 /* It seems there is no way to turn off use of an icon pixmap.
6103 The following line does it, only if no icon has yet been created,
6104 for some window managers. But with mwm it crashes.
6105 Some people say it should clear the IconPixmapHint bit in this case,
6106 but that doesn't work, and the X consortium said it isn't the
6107 right thing at all. Since there is no way to win,
6108 best to explicitly give up. */
6110 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6116 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6120 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6121 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6124 #else /* not USE_X_TOOLKIT */
6126 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6127 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6129 #endif /* not USE_X_TOOLKIT */
6132 #endif /* MAC_TODO */
6135 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6139 #if 0 /* MAC_TODO: no icons on Mac */
6140 #ifdef USE_X_TOOLKIT
6141 Window window
= XtWindow (f
->output_data
.x
->widget
);
6143 Window window
= FRAME_X_WINDOW (f
);
6146 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6147 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6148 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6150 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6151 #endif /* MAC_TODO */
6155 /***********************************************************************
6157 ***********************************************************************/
6159 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6162 x_get_font_info (f
, font_idx
)
6166 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6169 /* the global font name table */
6170 char **font_name_table
= NULL
;
6171 int font_name_table_size
= 0;
6172 int font_name_count
= 0;
6174 /* Alist linking character set strings to Mac text encoding and Emacs
6176 static Lisp_Object Vmac_charset_info_alist
;
6179 create_text_encoding_info_alist ()
6181 Lisp_Object result
= Qnil
, rest
;
6183 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6185 Lisp_Object charset_info
= XCAR (rest
);
6186 Lisp_Object charset
, coding_system
, text_encoding
;
6187 Lisp_Object existing_info
;
6189 if (!(CONSP (charset_info
)
6190 && STRINGP (charset
= XCAR (charset_info
))
6191 && CONSP (XCDR (charset_info
))
6192 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6193 && CONSP (XCDR (XCDR (charset_info
)))
6194 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6197 existing_info
= assq_no_quit (text_encoding
, result
);
6198 if (NILP (existing_info
))
6199 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6202 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6203 XSETCDR (XCDR (existing_info
),
6204 Fcons (charset
, XCDR (XCDR (existing_info
))));
6212 decode_mac_font_name (name
, size
, coding_system
)
6215 Lisp_Object coding_system
;
6217 struct coding_system coding
;
6220 for (p
= name
; *p
; p
++)
6221 if (!isascii (*p
) || iscntrl (*p
))
6225 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6228 setup_coding_system (coding_system
, &coding
);
6229 coding
.src_multibyte
= 0;
6230 coding
.dst_multibyte
= 1;
6231 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6232 coding
.composing
= COMPOSITION_DISABLED
;
6233 buf
= (char *) alloca (size
);
6235 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6236 bcopy (buf
, name
, coding
.produced
);
6237 name
[coding
.produced
] = '\0';
6242 mac_to_x_fontname (name
, size
, style
, charset
)
6248 char foundry
[32], family
[32], cs
[32];
6249 char xf
[256], *result
, *p
;
6251 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) == 3)
6255 strcpy(foundry
, "Apple");
6256 strcpy(family
, name
);
6259 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6260 foundry
, family
, style
& bold
? "bold" : "medium",
6261 style
& italic
? 'i' : 'r', size
, size
* 10,
6262 size
? 75 : 0, size
? 75 : 0, size
* 10, charset
);
6264 result
= (char *) xmalloc (strlen (xf
) + 1);
6265 strcpy (result
, xf
);
6266 for (p
= result
; *p
; p
++)
6272 /* Convert an X font spec to the corresponding mac font name, which
6273 can then be passed to GetFNum after conversion to a Pascal string.
6274 For ordinary Mac fonts, this should just be their names, like
6275 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6276 collection contain their charset designation in their names, like
6277 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6278 names are handled accordingly. */
6280 x_font_name_to_mac_font_name (xf
, mf
, mf_decoded
, style
, cs
)
6281 char *xf
, *mf
, *mf_decoded
;
6285 char foundry
[32], family
[32], weight
[20], slant
[2], *p
;
6286 Lisp_Object charset_info
, coding_system
= Qnil
;
6287 struct coding_system coding
;
6291 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6292 foundry
, family
, weight
, slant
, cs
) != 5 &&
6293 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6294 foundry
, family
, weight
, slant
, cs
) != 5)
6298 if (strcmp (weight
, "bold") == 0)
6303 charset_info
= Fassoc (build_string (cs
), Vmac_charset_info_alist
);
6304 if (!NILP (charset_info
))
6306 strcpy (mf_decoded
, family
);
6307 coding_system
= Fcar (Fcdr (Fcdr (charset_info
)));
6310 sprintf (mf_decoded
, "%s-%s-%s", foundry
, family
, cs
);
6312 for (p
= mf_decoded
; *p
; p
++)
6313 if (!isascii (*p
) || iscntrl (*p
))
6317 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6318 strcpy (mf
, mf_decoded
);
6321 setup_coding_system (coding_system
, &coding
);
6322 coding
.src_multibyte
= 1;
6323 coding
.dst_multibyte
= 1;
6324 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6325 encode_coding (&coding
, mf_decoded
, mf
,
6326 strlen (mf_decoded
), sizeof (Str32
) - 1);
6327 mf
[coding
.produced
] = '\0';
6333 add_font_name_table_entry (char *font_name
)
6335 if (font_name_table_size
== 0)
6337 font_name_table_size
= 16;
6338 font_name_table
= (char **)
6339 xmalloc (font_name_table_size
* sizeof (char *));
6341 else if (font_name_count
+ 1 >= font_name_table_size
)
6343 font_name_table_size
+= 16;
6344 font_name_table
= (char **)
6345 xrealloc (font_name_table
,
6346 font_name_table_size
* sizeof (char *));
6349 font_name_table
[font_name_count
++] = font_name
;
6352 /* Sets up the table font_name_table to contain the list of all fonts
6353 in the system the first time the table is used so that the Resource
6354 Manager need not be accessed every time this information is
6358 init_font_name_table ()
6360 #if TARGET_API_MAC_CARBON
6361 FMFontFamilyIterator ffi
;
6362 FMFontFamilyInstanceIterator ffii
;
6364 Lisp_Object text_encoding_info_alist
;
6365 struct gcpro gcpro1
;
6367 /* Create a dummy instance iterator here to avoid creating and
6368 destroying it in the loop. */
6369 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6371 /* Create an iterator to enumerate the font families. */
6372 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6375 FMDisposeFontFamilyInstanceIterator (&ffii
);
6379 text_encoding_info_alist
= create_text_encoding_info_alist ();
6381 GCPRO1 (text_encoding_info_alist
);
6383 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6389 TextEncoding encoding
;
6390 TextEncodingBase sc
;
6391 Lisp_Object text_encoding_info
;
6393 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6399 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6401 sc
= GetTextEncodingBase (encoding
);
6402 text_encoding_info
= assq_no_quit (make_number (sc
),
6403 text_encoding_info_alist
);
6404 if (!NILP (text_encoding_info
))
6405 decode_mac_font_name (name
, sizeof (name
),
6406 XCAR (XCDR (text_encoding_info
)));
6408 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6409 text_encoding_info_alist
);
6411 /* Point the instance iterator at the current font family. */
6412 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6415 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6418 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6420 for (; !NILP (rest
); rest
= XCDR (rest
))
6422 char *cs
= SDATA (XCAR (rest
));
6426 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6428 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6430 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6432 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6438 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6447 /* Dispose of the iterators. */
6448 FMDisposeFontFamilyIterator (&ffi
);
6449 FMDisposeFontFamilyInstanceIterator (&ffii
);
6450 #else /* !TARGET_API_MAC_CARBON */
6452 SInt16 fontnum
, old_fontnum
;
6453 int num_mac_fonts
= CountResources('FOND');
6455 Handle font_handle
, font_handle_2
;
6456 short id
, scriptcode
;
6459 struct FontAssoc
*fat
;
6460 struct AsscEntry
*assc_entry
;
6461 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
6462 struct gcpro gcpro1
;
6464 GetPort (&port
); /* save the current font number used */
6465 old_fontnum
= port
->txFont
;
6467 text_encoding_info_alist
= create_text_encoding_info_alist ();
6469 GCPRO1 (text_encoding_info_alist
);
6471 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6473 font_handle
= GetIndResource ('FOND', i
);
6477 GetResInfo (font_handle
, &id
, &type
, name
);
6478 GetFNum (name
, &fontnum
);
6484 scriptcode
= FontToScript (fontnum
);
6485 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
6486 text_encoding_info_alist
);
6487 if (!NILP (text_encoding_info
))
6488 decode_mac_font_name (name
, sizeof (name
),
6489 XCAR (XCDR (text_encoding_info
)));
6491 text_encoding_info
= assq_no_quit (make_number (smRoman
),
6492 text_encoding_info_alist
);
6495 HLock (font_handle
);
6497 if (GetResourceSizeOnDisk (font_handle
)
6498 >= sizeof (struct FamRec
))
6500 fat
= (struct FontAssoc
*) (*font_handle
6501 + sizeof (struct FamRec
));
6503 = (struct AsscEntry
*) (*font_handle
6504 + sizeof (struct FamRec
)
6505 + sizeof (struct FontAssoc
));
6507 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6509 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6511 for (; !NILP (rest
); rest
= XCDR (rest
))
6513 char *cs
= SDATA (XCAR (rest
));
6515 add_font_name_table_entry (mac_to_x_fontname (name
,
6516 assc_entry
->fontSize
,
6517 assc_entry
->fontStyle
,
6523 HUnlock (font_handle
);
6524 font_handle_2
= GetNextFOND (font_handle
);
6525 ReleaseResource (font_handle
);
6526 font_handle
= font_handle_2
;
6528 while (ResError () == noErr
&& font_handle
);
6533 TextFont (old_fontnum
);
6534 #endif /* !TARGET_API_MAC_CARBON */
6539 mac_clear_font_name_table ()
6543 for (i
= 0; i
< font_name_count
; i
++)
6544 xfree (font_name_table
[i
]);
6545 xfree (font_name_table
);
6546 font_name_table
= NULL
;
6547 font_name_table_size
= font_name_count
= 0;
6551 enum xlfd_scalable_field_index
6553 XLFD_SCL_PIXEL_SIZE
,
6554 XLFD_SCL_POINT_SIZE
,
6559 static int xlfd_scalable_fields
[] =
6568 mac_c_string_match (regexp
, string
, nonspecial
, exact
)
6570 const char *string
, *nonspecial
;
6575 if (strcmp (string
, nonspecial
) == 0)
6576 return build_string (string
);
6578 else if (strstr (string
, nonspecial
))
6580 Lisp_Object str
= build_string (string
);
6582 if (fast_string_match (regexp
, str
) >= 0)
6590 mac_do_list_fonts (pattern
, maxnames
)
6595 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6596 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6599 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6600 char *longest_start
, *cur_start
, *nonspecial
;
6601 int longest_len
, exact
;
6603 if (font_name_table
== NULL
) /* Initialize when first used. */
6604 init_font_name_table ();
6606 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6609 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6610 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6611 fonts are scaled according to the specified size. */
6614 field
= xlfd_scalable_fields
;
6622 if ('0' <= *ptr
&& *ptr
<= '9')
6624 *val
= *ptr
++ - '0';
6625 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6626 *val
= *val
* 10 + *ptr
++ - '0';
6633 ptr
= strchr (ptr
, '-');
6636 while (ptr
&& i
< 14);
6638 if (i
== 14 && ptr
== NULL
)
6640 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
6641 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
6642 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
6643 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
6645 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
6646 scl_val
[XLFD_SCL_POINT_SIZE
] =
6647 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6648 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
6650 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
6651 scl_val
[XLFD_SCL_AVGWIDTH
] =
6652 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6653 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
6657 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6662 longest_start
= cur_start
= ptr
;
6666 /* Turn pattern into a regexp and do a regexp match. Also find the
6667 longest substring containing no special characters. */
6668 for (; *pattern
; pattern
++)
6670 if (*pattern
== '?' || *pattern
== '*')
6672 if (ptr
- cur_start
> longest_len
)
6674 longest_start
= cur_start
;
6675 longest_len
= ptr
- cur_start
;
6679 if (*pattern
== '?')
6681 else /* if (*pattern == '*') */
6689 *ptr
++ = tolower (*pattern
);
6692 if (ptr
- cur_start
> longest_len
)
6694 longest_start
= cur_start
;
6695 longest_len
= ptr
- cur_start
;
6701 nonspecial
= xmalloc (longest_len
+ 1);
6702 strncpy (nonspecial
, longest_start
, longest_len
);
6703 nonspecial
[longest_len
] = '\0';
6705 pattern_regex
= build_string (regex
);
6707 for (i
= 0; i
< font_name_count
; i
++)
6709 fontname
= mac_c_string_match (pattern_regex
, font_name_table
[i
],
6711 if (!NILP (fontname
))
6713 font_list
= Fcons (fontname
, font_list
);
6714 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6717 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6718 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
6720 int former_len
= ptr
- font_name_table
[i
];
6722 memcpy (scaled
, font_name_table
[i
], former_len
);
6723 sprintf (scaled
+ former_len
,
6724 "-%d-%d-75-75-m-%d-%s",
6725 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6726 scl_val
[XLFD_SCL_POINT_SIZE
],
6727 scl_val
[XLFD_SCL_AVGWIDTH
],
6728 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
6729 fontname
= mac_c_string_match (pattern_regex
, scaled
,
6731 if (!NILP (fontname
))
6733 font_list
= Fcons (fontname
, font_list
);
6734 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6745 /* Return a list of names of available fonts matching PATTERN on frame F.
6747 Frame F null means we have not yet created any frame on Mac, and
6748 consult the first display in x_display_list. MAXNAMES sets a limit
6749 on how many fonts to match. */
6752 x_list_fonts (f
, pattern
, size
, maxnames
)
6754 Lisp_Object pattern
;
6757 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
6758 struct mac_display_info
*dpyinfo
6759 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
6761 xassert (size
<= 0);
6763 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6764 if (NILP (patterns
))
6765 patterns
= Fcons (pattern
, Qnil
);
6767 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
6769 pattern
= XCAR (patterns
);
6771 if (!STRINGP (pattern
))
6774 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
6775 key
= Fcons (pattern
, make_number (maxnames
));
6777 list
= Fassoc (key
, tem
);
6780 list
= Fcdr_safe (list
);
6781 /* We have a cashed list. Don't have to get the list again. */
6786 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6789 /* MAC_TODO: add code for matching outline fonts here */
6791 /* Now store the result in the cache. */
6792 XSETCAR (XCDR (dpyinfo
->name_list_element
),
6793 Fcons (Fcons (key
, list
),
6794 XCAR (XCDR (dpyinfo
->name_list_element
))));
6797 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6806 /* Check that FONT is valid on frame F. It is if it can be found in F's
6810 x_check_font (f
, font
)
6815 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6817 xassert (font
!= NULL
);
6819 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6820 if (dpyinfo
->font_table
[i
].name
6821 && font
== dpyinfo
->font_table
[i
].font
)
6824 xassert (i
< dpyinfo
->n_fonts
);
6827 #endif /* GLYPH_DEBUG != 0 */
6829 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6830 Note: There are (broken) X fonts out there with invalid XFontStruct
6831 min_bounds contents. For example, handa@etl.go.jp reports that
6832 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6833 have font->min_bounds.width == 0. */
6836 x_font_min_bounds (font
, w
, h
)
6837 MacFontStruct
*font
;
6840 *h
= FONT_HEIGHT (font
);
6841 *w
= font
->min_bounds
.width
;
6845 /* Compute the smallest character width and smallest font height over
6846 all fonts available on frame F. Set the members smallest_char_width
6847 and smallest_font_height in F's x_display_info structure to
6848 the values computed. Value is non-zero if smallest_font_height or
6849 smallest_char_width become smaller than they were before. */
6852 x_compute_min_glyph_bounds (f
)
6856 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6857 MacFontStruct
*font
;
6858 int old_width
= dpyinfo
->smallest_char_width
;
6859 int old_height
= dpyinfo
->smallest_font_height
;
6861 dpyinfo
->smallest_font_height
= 100000;
6862 dpyinfo
->smallest_char_width
= 100000;
6864 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6865 if (dpyinfo
->font_table
[i
].name
)
6867 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6870 font
= (MacFontStruct
*) fontp
->font
;
6871 xassert (font
!= (MacFontStruct
*) ~0);
6872 x_font_min_bounds (font
, &w
, &h
);
6874 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6875 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6878 xassert (dpyinfo
->smallest_char_width
> 0
6879 && dpyinfo
->smallest_font_height
> 0);
6881 return (dpyinfo
->n_fonts
== 1
6882 || dpyinfo
->smallest_char_width
< old_width
6883 || dpyinfo
->smallest_font_height
< old_height
);
6887 /* Determine whether given string is a fully-specified XLFD: all 14
6888 fields are present, none is '*'. */
6891 is_fully_specified_xlfd (char *p
)
6899 for (i
= 0; i
< 13; i
++)
6901 q
= strchr (p
+ 1, '-');
6904 if (q
- p
== 2 && *(p
+ 1) == '*')
6909 if (strchr (p
+ 1, '-') != NULL
)
6912 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6919 const int kDefaultFontSize
= 12;
6922 /* XLoadQueryFont creates and returns an internal representation for a
6923 font in a MacFontStruct struct. There is really no concept
6924 corresponding to "loading" a font on the Mac. But we check its
6925 existence and find the font number and all other information for it
6926 and store them in the returned MacFontStruct. */
6928 static MacFontStruct
*
6929 XLoadQueryFont (Display
*dpy
, char *fontname
)
6931 int i
, size
, point_size
, avgwidth
, is_two_byte_font
, char_width
;
6934 SInt16 old_fontnum
, old_fontsize
;
6936 Str32 mfontname
, mfontname_decoded
, charset
;
6939 #if TARGET_API_MAC_CARBON
6940 TextEncoding encoding
;
6945 MacFontStruct
*font
;
6946 FontInfo the_fontinfo
;
6948 UInt32 old_flags
, new_flags
;
6951 if (is_fully_specified_xlfd (fontname
))
6955 Lisp_Object matched_fonts
;
6957 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6958 if (NILP (matched_fonts
))
6960 name
= SDATA (XCAR (matched_fonts
));
6963 GetPort (&port
); /* save the current font number used */
6964 #if TARGET_API_MAC_CARBON
6965 old_fontnum
= GetPortTextFont (port
);
6966 old_fontsize
= GetPortTextSize (port
);
6967 old_fontface
= GetPortTextFace (port
);
6969 old_fontnum
= port
->txFont
;
6970 old_fontsize
= port
->txSize
;
6971 old_fontface
= port
->txFace
;
6974 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size
, &point_size
, &avgwidth
) != 3)
6980 size
= point_size
/ 10;
6981 else if (avgwidth
> 0)
6982 size
= avgwidth
/ 10;
6985 size
= kDefaultFontSize
;
6987 x_font_name_to_mac_font_name (name
, mfontname
, mfontname_decoded
,
6988 &fontface
, charset
);
6990 #if TARGET_API_MAC_CARBON
6991 fontnum
= FMGetFontFamilyFromName (mfontname
);
6992 if (fontnum
== kInvalidFontFamily
6993 || FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
6995 scriptcode
= GetTextEncodingBase (encoding
);
6997 GetFNum (mfontname
, &fontnum
);
7000 scriptcode
= FontToScript (fontnum
);
7003 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7005 font
->mac_fontnum
= fontnum
;
7006 font
->mac_fontsize
= size
;
7007 font
->mac_fontface
= fontface
;
7008 font
->mac_scriptcode
= scriptcode
;
7010 /* Apple Japanese (SJIS) font is listed as both
7011 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7012 (Roman script) in init_font_name_table (). The latter should be
7013 treated as a one-byte font. */
7014 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7015 font
->mac_scriptcode
= smRoman
;
7017 font
->full_name
= mac_to_x_fontname (mfontname_decoded
, size
, fontface
, charset
);
7019 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
7020 font
->mac_scriptcode
== smTradChinese
||
7021 font
->mac_scriptcode
== smSimpChinese
||
7022 font
->mac_scriptcode
== smKorean
;
7026 TextFace (fontface
);
7028 GetFontInfo (&the_fontinfo
);
7030 font
->ascent
= the_fontinfo
.ascent
;
7031 font
->descent
= the_fontinfo
.descent
;
7033 font
->min_byte1
= 0;
7034 if (is_two_byte_font
)
7035 font
->max_byte1
= 1;
7037 font
->max_byte1
= 0;
7038 font
->min_char_or_byte2
= 0x20;
7039 font
->max_char_or_byte2
= 0xff;
7041 if (is_two_byte_font
)
7043 /* Use the width of an "ideographic space" of that font because
7044 the_fontinfo.widMax returns the wrong width for some fonts. */
7045 switch (font
->mac_scriptcode
)
7048 char_width
= StringWidth("\p\x81\x40");
7051 char_width
= StringWidth("\p\xa1\x40");
7054 char_width
= StringWidth("\p\xa1\xa1");
7057 char_width
= StringWidth("\p\xa1\xa1");
7062 /* Do this instead of use the_fontinfo.widMax, which incorrectly
7063 returns 15 for 12-point Monaco! */
7064 char_width
= CharWidth ('m');
7066 if (is_two_byte_font
)
7068 font
->per_char
= NULL
;
7070 if (fontface
& italic
)
7071 font
->max_bounds
.rbearing
= char_width
+ 1;
7073 font
->max_bounds
.rbearing
= char_width
;
7074 font
->max_bounds
.lbearing
= 0;
7075 font
->max_bounds
.width
= char_width
;
7076 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7077 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7079 font
->min_bounds
= font
->max_bounds
;
7083 font
->per_char
= (XCharStruct
*)
7084 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7086 int c
, min_width
, max_width
;
7087 Rect char_bounds
, min_bounds
, max_bounds
;
7090 min_width
= max_width
= char_width
;
7091 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
7092 SetRect (&max_bounds
, 0, 0, 0, 0);
7093 for (c
= 0x20; c
<= 0xff; c
++)
7096 char_width
= CharWidth (ch
);
7097 QDTextBounds (1, &ch
, &char_bounds
);
7098 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
7099 char_width
, char_bounds
);
7100 /* Some Japanese fonts (in SJIS encoding) return 0 as the
7101 character width of 0x7f. */
7104 min_width
= min (min_width
, char_width
);
7105 max_width
= max (max_width
, char_width
);
7107 if (!EmptyRect (&char_bounds
))
7109 SetRect (&min_bounds
,
7110 max (min_bounds
.left
, char_bounds
.left
),
7111 max (min_bounds
.top
, char_bounds
.top
),
7112 min (min_bounds
.right
, char_bounds
.right
),
7113 min (min_bounds
.bottom
, char_bounds
.bottom
));
7114 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7117 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7118 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7119 if (min_width
== max_width
7120 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
7122 /* Fixed width and no overhangs. */
7123 xfree (font
->per_char
);
7124 font
->per_char
= NULL
;
7129 TextFont (old_fontnum
); /* restore previous font number, size and face */
7130 TextSize (old_fontsize
);
7131 TextFace (old_fontface
);
7138 mac_unload_font (dpyinfo
, font
)
7139 struct mac_display_info
*dpyinfo
;
7142 xfree (font
->full_name
);
7144 xfree (font
->per_char
);
7149 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7150 pointer to the structure font_info while allocating it dynamically.
7151 If SIZE is 0, load any size of font.
7152 If loading is failed, return NULL. */
7155 x_load_font (f
, fontname
, size
)
7157 register char *fontname
;
7160 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7161 Lisp_Object font_names
;
7163 /* Get a list of all the fonts that match this name. Once we
7164 have a list of matching fonts, we compare them against the fonts
7165 we already have by comparing names. */
7166 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7168 if (!NILP (font_names
))
7173 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7174 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7175 if (dpyinfo
->font_table
[i
].name
7176 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7177 SDATA (XCAR (tail
)))
7178 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7179 SDATA (XCAR (tail
)))))
7180 return (dpyinfo
->font_table
+ i
);
7185 /* Load the font and add it to the table. */
7188 struct MacFontStruct
*font
;
7189 struct font_info
*fontp
;
7190 unsigned long value
;
7193 fontname
= (char *) SDATA (XCAR (font_names
));
7196 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7201 /* Find a free slot in the font table. */
7202 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7203 if (dpyinfo
->font_table
[i
].name
== NULL
)
7206 /* If no free slot found, maybe enlarge the font table. */
7207 if (i
== dpyinfo
->n_fonts
7208 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7211 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7212 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7214 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7217 fontp
= dpyinfo
->font_table
+ i
;
7218 if (i
== dpyinfo
->n_fonts
)
7221 /* Now fill in the slots of *FONTP. */
7223 bzero (fontp
, sizeof (*fontp
));
7225 fontp
->font_idx
= i
;
7226 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7227 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7229 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7231 /* Fixed width font. */
7232 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7239 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7240 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7242 fontp
->space_width
= pcm
->width
;
7244 fontp
->space_width
= FONT_WIDTH (font
);
7248 int width
= pcm
->width
;
7249 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7250 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7251 width
+= pcm
->width
;
7252 fontp
->average_width
= width
/ 95;
7255 fontp
->average_width
= FONT_WIDTH (font
);
7258 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7259 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7261 fontp
->size
= font
->max_bounds
.width
;
7262 fontp
->height
= FONT_HEIGHT (font
);
7264 /* For some font, ascent and descent in max_bounds field is
7265 larger than the above value. */
7266 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7267 if (max_height
> fontp
->height
)
7268 fontp
->height
= max_height
;
7271 /* The slot `encoding' specifies how to map a character
7272 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7273 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7274 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7275 2:0xA020..0xFF7F). For the moment, we don't know which charset
7276 uses this font. So, we set information in fontp->encoding[1]
7277 which is never used by any charset. If mapping can't be
7278 decided, set FONT_ENCODING_NOT_DECIDED. */
7279 if (font
->mac_scriptcode
== smJapanese
)
7280 fontp
->encoding
[1] = 4;
7284 = (font
->max_byte1
== 0
7286 ? (font
->min_char_or_byte2
< 0x80
7287 ? (font
->max_char_or_byte2
< 0x80
7288 ? 0 /* 0x20..0x7F */
7289 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
7290 : 1) /* 0xA0..0xFF */
7292 : (font
->min_byte1
< 0x80
7293 ? (font
->max_byte1
< 0x80
7294 ? (font
->min_char_or_byte2
< 0x80
7295 ? (font
->max_char_or_byte2
< 0x80
7296 ? 0 /* 0x2020..0x7F7F */
7297 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
7298 : 3) /* 0x20A0..0x7FFF */
7299 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
7300 : (font
->min_char_or_byte2
< 0x80
7301 ? (font
->max_char_or_byte2
< 0x80
7302 ? 2 /* 0xA020..0xFF7F */
7303 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
7304 : 1))); /* 0xA0A0..0xFFFF */
7307 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7308 fontp
->baseline_offset
7309 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
7310 ? (long) value
: 0);
7311 fontp
->relative_compose
7312 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
7313 ? (long) value
: 0);
7314 fontp
->default_ascent
7315 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
7316 ? (long) value
: 0);
7318 fontp
->baseline_offset
= 0;
7319 fontp
->relative_compose
= 0;
7320 fontp
->default_ascent
= 0;
7323 /* Set global flag fonts_changed_p to non-zero if the font loaded
7324 has a character with a smaller width than any other character
7325 before, or if the font loaded has a smalle>r height than any
7326 other font loaded before. If this happens, it will make a
7327 glyph matrix reallocation necessary. */
7328 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
7335 /* Return a pointer to struct font_info of a font named FONTNAME for
7336 frame F. If no such font is loaded, return NULL. */
7339 x_query_font (f
, fontname
)
7341 register char *fontname
;
7343 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7346 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7347 if (dpyinfo
->font_table
[i
].name
7348 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7349 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7350 return (dpyinfo
->font_table
+ i
);
7355 /* Find a CCL program for a font specified by FONTP, and set the member
7356 `encoder' of the structure. */
7359 x_find_ccl_program (fontp
)
7360 struct font_info
*fontp
;
7362 Lisp_Object list
, elt
;
7364 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7368 && STRINGP (XCAR (elt
))
7369 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7375 struct ccl_program
*ccl
7376 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7378 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7381 fontp
->font_encoder
= ccl
;
7387 /* The Mac Event loop code */
7389 #if !TARGET_API_MAC_CARBON
7391 #include <Quickdraw.h>
7392 #include <Balloons.h>
7393 #include <Devices.h>
7395 #include <Gestalt.h>
7397 #include <Processes.h>
7399 #include <ToolUtils.h>
7400 #include <TextUtils.h>
7401 #include <Dialogs.h>
7404 #include <Resources.h>
7409 #endif /* ! TARGET_API_MAC_CARBON */
7414 #define WINDOW_RESOURCE 128
7415 #define TERM_WINDOW_RESOURCE 129
7417 #define DEFAULT_NUM_COLS 80
7419 #define MIN_DOC_SIZE 64
7420 #define MAX_DOC_SIZE 32767
7423 /* sleep time for WaitNextEvent */
7424 #define WNE_SLEEP_AT_SUSPEND 10
7425 #define WNE_SLEEP_AT_RESUME 1
7427 /* the flag appl_is_suspended is used both for determining the sleep
7428 time to be passed to WaitNextEvent and whether the cursor should be
7429 drawn when updating the display. The cursor is turned off when
7430 Emacs is suspended. Redrawing it is unnecessary and what needs to
7431 be done depends on whether the cursor lies inside or outside the
7432 redraw region. So we might as well skip drawing it when Emacs is
7434 static Boolean app_is_suspended
= false;
7435 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7438 #define EXTRA_STACK_ALLOC (256 * 1024)
7440 #define ARGV_STRING_LIST_ID 129
7441 #define ABOUT_ALERT_ID 128
7442 #define RAM_TOO_LARGE_ALERT_ID 129
7444 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7445 Lisp_Object Qreverse
;
7447 /* True if using command key as meta key. */
7448 Lisp_Object Vmac_command_key_is_meta
;
7450 /* Modifier associated with the option key, or nil for normal behavior. */
7451 Lisp_Object Vmac_option_modifier
;
7453 /* True if the ctrl and meta keys should be reversed. */
7454 Lisp_Object Vmac_reverse_ctrl_meta
;
7456 /* True if the option and command modifiers should be used to emulate
7457 a three button mouse */
7458 Lisp_Object Vmac_emulate_three_button_mouse
;
7460 #if USE_CARBON_EVENTS
7461 /* True if the mouse wheel button (i.e. button 4) should map to
7462 mouse-2, instead of mouse-3. */
7463 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7465 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7466 for processing before Emacs sees it. */
7467 Lisp_Object Vmac_pass_command_to_system
;
7469 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7470 for processing before Emacs sees it. */
7471 Lisp_Object Vmac_pass_control_to_system
;
7474 /* Set in term/mac-win.el to indicate that event loop can now generate
7475 drag and drop events. */
7476 Lisp_Object Qmac_ready_for_drag_n_drop
;
7478 Lisp_Object drag_and_drop_file_list
;
7480 Point saved_menu_event_location
;
7483 static void init_required_apple_events (void);
7485 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7487 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7488 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7489 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7491 #if TARGET_API_MAC_CARBON
7493 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7494 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7495 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7496 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7499 static Lisp_Object Qapplication
, Qabout
;
7500 #if USE_CARBON_EVENTS
7502 extern void init_service_handler ();
7503 static Lisp_Object Qpreferences
, Qservices
, Qpaste
, Qperform
;
7505 /* Window Event Handler */
7506 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7509 OSErr
install_window_handler (WindowPtr
);
7511 extern void init_emacs_passwd_dir ();
7512 extern int emacs_main (int, char **, char **);
7514 extern void initialize_applescript();
7515 extern void terminate_applescript();
7518 #if USE_CARBON_EVENTS
7519 mac_to_emacs_modifiers (UInt32 mods
)
7521 mac_to_emacs_modifiers (EventModifiers mods
)
7524 unsigned int result
= 0;
7525 if (mods
& macShiftKey
)
7526 result
|= shift_modifier
;
7527 if (mods
& macCtrlKey
)
7528 result
|= ctrl_modifier
;
7529 if (mods
& macMetaKey
)
7530 result
|= meta_modifier
;
7531 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7532 result
|= alt_modifier
;
7533 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7534 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7536 result
|= XUINT(val
);
7543 mac_get_emulated_btn ( UInt32 modifiers
)
7546 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7547 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7548 if (modifiers
& cmdKey
)
7549 result
= cmdIs3
? 2 : 1;
7550 else if (modifiers
& optionKey
)
7551 result
= cmdIs3
? 1 : 2;
7556 #if USE_CARBON_EVENTS
7557 /* Obtains the event modifiers from the event ref and then calls
7558 mac_to_emacs_modifiers. */
7560 mac_event_to_emacs_modifiers (EventRef eventRef
)
7563 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7564 sizeof (UInt32
), NULL
, &mods
);
7565 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7566 GetEventClass(eventRef
) == kEventClassMouse
)
7568 mods
&= ~(optionKey
| cmdKey
);
7570 return mac_to_emacs_modifiers (mods
);
7573 /* Given an event ref, return the code to use for the mouse button
7574 code in the emacs input_event. */
7576 mac_get_mouse_btn (EventRef ref
)
7578 EventMouseButton result
= kEventMouseButtonPrimary
;
7579 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7580 sizeof (EventMouseButton
), NULL
, &result
);
7583 case kEventMouseButtonPrimary
:
7584 if (NILP (Vmac_emulate_three_button_mouse
))
7588 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7589 sizeof (UInt32
), NULL
, &mods
);
7590 return mac_get_emulated_btn(mods
);
7592 case kEventMouseButtonSecondary
:
7593 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7594 case kEventMouseButtonTertiary
:
7595 case 4: /* 4 is the number for the mouse wheel button */
7596 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7602 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7603 events. However the click of the mouse wheel is not converted to a
7604 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7605 checks to see if it is a mouse up or down carbon event that has not
7606 been converted, and if so, converts it by hand (to be picked up in
7607 the XTread_socket loop). */
7608 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7610 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7611 /* Do special case for mouse wheel button. */
7612 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
7614 UInt32 kind
= GetEventKind (eventRef
);
7615 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
7617 eventRec
->what
= mouseDown
;
7620 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
7622 eventRec
->what
= mouseUp
;
7627 /* Need where and when. */
7629 GetEventParameter (eventRef
, kEventParamMouseLocation
,
7630 typeQDPoint
, NULL
, sizeof (Point
),
7631 NULL
, &eventRec
->where
);
7632 /* Use two step process because new event modifiers are
7633 32-bit and old are 16-bit. Currently, only loss is
7635 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
7636 typeUInt32
, NULL
, sizeof (UInt32
),
7638 eventRec
->modifiers
= mods
;
7640 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7651 Handle menubar_handle
;
7652 MenuHandle menu_handle
;
7654 menubar_handle
= GetNewMBar (128);
7655 if(menubar_handle
== NULL
)
7657 SetMenuBar (menubar_handle
);
7660 #if !TARGET_API_MAC_CARBON
7661 menu_handle
= GetMenuHandle (M_APPLE
);
7662 if(menu_handle
!= NULL
)
7663 AppendResMenu (menu_handle
,'DRVR');
7671 do_init_managers (void)
7673 #if !TARGET_API_MAC_CARBON
7674 InitGraf (&qd
.thePort
);
7676 FlushEvents (everyEvent
, 0);
7681 #endif /* !TARGET_API_MAC_CARBON */
7684 #if !TARGET_API_MAC_CARBON
7685 /* set up some extra stack space for use by emacs */
7686 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7688 /* MaxApplZone must be called for AppleScript to execute more
7689 complicated scripts */
7692 #endif /* !TARGET_API_MAC_CARBON */
7696 do_check_ram_size (void)
7698 SInt32 physical_ram_size
, logical_ram_size
;
7700 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7701 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7702 || physical_ram_size
> (1 << VALBITS
)
7703 || logical_ram_size
> (1 << VALBITS
))
7705 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7711 do_window_update (WindowPtr win
)
7713 struct frame
*f
= mac_window_to_frame (win
);
7717 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7719 if (win
!= tip_window
)
7721 if (f
->async_visible
== 0)
7723 f
->async_visible
= 1;
7724 f
->async_iconified
= 0;
7725 SET_FRAME_GARBAGED (f
);
7727 /* An update event is equivalent to MapNotify on X, so report
7728 visibility changes properly. */
7729 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7730 /* Force a redisplay sooner or later to update the
7731 frame titles in case this is the second frame. */
7732 record_asynch_buffer_change ();
7738 #if TARGET_API_MAC_CARBON
7740 RgnHandle region
= NewRgn ();
7742 GetPortVisibleRegion (GetWindowPort (win
), region
);
7743 GetRegionBounds (region
, &r
);
7744 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7745 UpdateControls (win
, region
);
7746 DisposeRgn (region
);
7749 r
= (*win
->visRgn
)->rgnBBox
;
7750 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7751 UpdateControls (win
, win
->visRgn
);
7760 is_emacs_window (WindowPtr win
)
7762 Lisp_Object tail
, frame
;
7767 FOR_EACH_FRAME (tail
, frame
)
7768 if (FRAME_MAC_P (XFRAME (frame
)))
7769 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7778 /* Window-activate events will do the job. */
7780 app_is_suspended
= false;
7781 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7788 /* Window-deactivate events will do the job. */
7790 app_is_suspended
= true;
7791 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7797 do_apple_menu (SInt16 menu_item
)
7799 #if !TARGET_API_MAC_CARBON
7801 SInt16 da_driver_refnum
;
7803 if (menu_item
== I_ABOUT
)
7804 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7807 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7808 da_driver_refnum
= OpenDeskAcc (item_name
);
7810 #endif /* !TARGET_API_MAC_CARBON */
7814 do_menu_choice (SInt32 menu_choice
)
7816 SInt16 menu_id
, menu_item
;
7818 menu_id
= HiWord (menu_choice
);
7819 menu_item
= LoWord (menu_choice
);
7827 do_apple_menu (menu_item
);
7832 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
7833 MenuHandle menu
= GetMenuHandle (menu_id
);
7838 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7839 menubar_selection_callback (f
, refcon
);
7848 /* Handle drags in size box. Based on code contributed by Ben
7849 Mesander and IM - Window Manager A. */
7852 do_grow_window (WindowPtr w
, EventRecord
*e
)
7855 int rows
, columns
, width
, height
;
7856 struct frame
*f
= mac_window_to_frame (w
);
7857 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
7858 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
7859 #if TARGET_API_MAC_CARBON
7865 if (size_hints
->flags
& PMinSize
)
7867 min_width
= size_hints
->min_width
;
7868 min_height
= size_hints
->min_height
;
7870 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7872 #if TARGET_API_MAC_CARBON
7873 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
7875 height
= new_rect
.bottom
- new_rect
.top
;
7876 width
= new_rect
.right
- new_rect
.left
;
7878 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7879 /* see if it really changed size */
7882 height
= HiWord (grow_size
);
7883 width
= LoWord (grow_size
);
7886 if (width
!= FRAME_PIXEL_WIDTH (f
)
7887 || height
!= FRAME_PIXEL_HEIGHT (f
))
7889 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7890 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7892 x_set_window_size (f
, 0, columns
, rows
);
7897 /* Handle clicks in zoom box. Calculation of "standard state" based
7898 on code in IM - Window Manager A and code contributed by Ben
7899 Mesander. The standard state of an Emacs window is 80-characters
7900 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7903 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7906 Rect zoom_rect
, port_rect
;
7908 int w_title_height
, columns
, rows
, width
, height
;
7909 struct frame
*f
= mac_window_to_frame (w
);
7910 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7912 #if TARGET_API_MAC_CARBON
7914 Point standard_size
;
7916 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7917 standard_size
.v
= dpyinfo
->height
;
7919 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7920 zoom_in_or_out
= inZoomIn
;
7923 /* Adjust the standard size according to character boundaries. */
7925 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7926 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7927 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7928 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7929 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
7930 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
7931 && port_rect
.left
== zoom_rect
.left
7932 && port_rect
.top
== zoom_rect
.top
)
7933 zoom_in_or_out
= inZoomIn
;
7935 zoom_in_or_out
= inZoomOut
;
7938 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
7940 #else /* not TARGET_API_MAC_CARBON */
7941 GetPort (&save_port
);
7943 SetPortWindowPort (w
);
7945 /* Clear window to avoid flicker. */
7946 EraseRect (&(w
->portRect
));
7947 if (zoom_in_or_out
== inZoomOut
)
7949 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
7950 LocalToGlobal (&top_left
);
7952 /* calculate height of window's title bar */
7953 w_title_height
= top_left
.v
- 1
7954 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
7956 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7957 zoom_rect
= qd
.screenBits
.bounds
;
7958 zoom_rect
.top
+= w_title_height
;
7959 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
7961 zoom_rect
.right
= zoom_rect
.left
7962 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7964 /* Adjust the standard size according to character boundaries. */
7965 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7967 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7969 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
7973 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
7975 SetPort (save_port
);
7976 #endif /* not TARGET_API_MAC_CARBON */
7978 /* retrieve window size and update application values */
7979 #if TARGET_API_MAC_CARBON
7980 GetWindowPortBounds (w
, &port_rect
);
7982 port_rect
= w
->portRect
;
7984 height
= port_rect
.bottom
- port_rect
.top
;
7985 width
= port_rect
.right
- port_rect
.left
;
7987 if (width
!= FRAME_PIXEL_WIDTH (f
)
7988 || height
!= FRAME_PIXEL_HEIGHT (f
))
7990 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7991 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7993 change_frame_size (f
, rows
, columns
, 0, 1, 0);
7994 SET_FRAME_GARBAGED (f
);
7995 cancel_mouse_face (f
);
7997 FRAME_PIXEL_WIDTH (f
) = width
;
7998 FRAME_PIXEL_HEIGHT (f
) = height
;
8000 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8003 /* Intialize AppleEvent dispatcher table for the required events. */
8005 init_required_apple_events ()
8010 /* Make sure we have apple events before starting. */
8011 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
8015 if (!(result
& (1 << gestaltAppleEventsPresent
)))
8018 #if TARGET_API_MAC_CARBON
8019 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8020 NewAEEventHandlerUPP
8021 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8024 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8025 NewAEEventHandlerProc
8026 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8032 #if TARGET_API_MAC_CARBON
8033 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8034 NewAEEventHandlerUPP
8035 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8038 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8039 NewAEEventHandlerProc
8040 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8046 #if TARGET_API_MAC_CARBON
8047 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8048 NewAEEventHandlerUPP
8049 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8052 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8053 NewAEEventHandlerProc
8054 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8060 #if TARGET_API_MAC_CARBON
8061 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8062 NewAEEventHandlerUPP
8063 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8066 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8067 NewAEEventHandlerProc
8068 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8076 mac_store_application_menu_event (event
)
8077 #if USE_CARBON_EVENTS
8083 struct input_event buf
;
8084 Lisp_Object frame
, entry
;
8088 XSETFRAME (frame
, mac_focus_frame (&one_mac_display_info
));
8089 buf
.kind
= MENU_BAR_EVENT
;
8090 buf
.frame_or_window
= frame
;
8092 kbd_buffer_store_event (&buf
);
8094 buf
.arg
= Qapplication
;
8095 kbd_buffer_store_event (&buf
);
8097 #if USE_CARBON_EVENTS
8098 switch (GetEventClass (event
))
8101 case kEventClassService
:
8102 buf
.arg
= Qservices
;
8103 kbd_buffer_store_event (&buf
);
8104 switch (GetEventKind (event
))
8106 case kEventServicePaste
:
8110 case kEventServicePerform
:
8113 CFStringRef message
;
8115 err
= GetEventParameter (event
, kEventParamServiceMessageName
,
8116 typeCFStringRef
, NULL
,
8117 sizeof (CFStringRef
), NULL
, &message
);
8119 kbd_buffer_store_event (&buf
);
8120 if (err
== noErr
&& message
)
8121 entry
= intern (SDATA (cfstring_to_lisp (message
)));
8131 #endif /* MAC_OSX */
8132 case kEventClassCommand
:
8136 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
,
8137 NULL
, sizeof (HICommand
), NULL
, &command
);
8138 switch (command
.commandID
)
8140 case kHICommandAbout
:
8144 case kHICommandPreferences
:
8145 entry
= Qpreferences
;
8147 #endif /* MAC_OSX */
8148 case kHICommandQuit
:
8160 #else /* USE_CARBON_EVENTS */
8163 case kHICommandAbout
:
8166 case kHICommandQuit
:
8175 kbd_buffer_store_event (&buf
);
8178 #if USE_CARBON_EVENTS
8179 static pascal OSStatus
8180 mac_handle_command_event (next_handler
, event
, data
)
8181 EventHandlerCallRef next_handler
;
8188 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8189 sizeof (HICommand
), NULL
, &command
);
8191 switch (command
.commandID
)
8193 case kHICommandAbout
:
8195 case kHICommandPreferences
:
8196 #endif /* MAC_OSX */
8197 result
= CallNextEventHandler (next_handler
, event
);
8198 if (result
!= eventNotHandledErr
)
8201 mac_store_application_menu_event (event
);
8208 return eventNotHandledErr
;
8212 init_command_handler (window
)
8216 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8217 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8219 if (handle_command_eventUPP
== NULL
)
8220 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8221 return InstallApplicationEventHandler (handle_command_eventUPP
,
8222 GetEventTypeCount (specs
), specs
,
8226 static pascal OSStatus
8227 mac_handle_window_event (next_handler
, event
, data
)
8228 EventHandlerCallRef next_handler
;
8235 XSizeHints
*size_hints
;
8237 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8238 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8240 switch (GetEventKind (event
))
8242 case kEventWindowUpdate
:
8243 result
= CallNextEventHandler (next_handler
, event
);
8244 if (result
!= eventNotHandledErr
)
8247 do_window_update (wp
);
8250 case kEventWindowBoundsChanging
:
8251 result
= CallNextEventHandler (next_handler
, event
);
8252 if (result
!= eventNotHandledErr
)
8255 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8256 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8257 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8258 if ((attributes
& kWindowBoundsChangeUserResize
)
8259 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8260 == (PResizeInc
| PBaseSize
| PMinSize
)))
8265 GetEventParameter (event
, kEventParamCurrentBounds
,
8267 NULL
, sizeof (Rect
), NULL
, &bounds
);
8268 width
= bounds
.right
- bounds
.left
;
8269 height
= bounds
.bottom
- bounds
.top
;
8271 if (width
< size_hints
->min_width
)
8272 width
= size_hints
->min_width
;
8274 width
= size_hints
->base_width
8275 + (int) ((width
- size_hints
->base_width
)
8276 / (float) size_hints
->width_inc
+ .5)
8277 * size_hints
->width_inc
;
8279 if (height
< size_hints
->min_height
)
8280 height
= size_hints
->min_height
;
8282 height
= size_hints
->base_height
8283 + (int) ((height
- size_hints
->base_height
)
8284 / (float) size_hints
->height_inc
+ .5)
8285 * size_hints
->height_inc
;
8287 bounds
.right
= bounds
.left
+ width
;
8288 bounds
.bottom
= bounds
.top
+ height
;
8289 SetEventParameter (event
, kEventParamCurrentBounds
,
8290 typeQDRectangle
, sizeof (Rect
), &bounds
);
8296 return eventNotHandledErr
;
8298 #endif /* USE_CARBON_EVENTS */
8302 install_window_handler (window
)
8306 #if USE_CARBON_EVENTS
8307 EventTypeSpec specs
[] = {{kEventClassWindow
, kEventWindowUpdate
},
8308 {kEventClassWindow
, kEventWindowBoundsChanging
}};
8309 static EventHandlerUPP handle_window_event_UPP
= NULL
;
8311 if (handle_window_event_UPP
== NULL
)
8312 handle_window_event_UPP
= NewEventHandlerUPP (mac_handle_window_event
);
8314 err
= InstallWindowEventHandler (window
, handle_window_event_UPP
,
8315 GetEventTypeCount (specs
), specs
,
8318 #if TARGET_API_MAC_CARBON
8319 if (mac_do_track_dragUPP
== NULL
)
8320 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8321 if (mac_do_receive_dragUPP
== NULL
)
8322 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8325 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8327 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8333 remove_window_handler (window
)
8336 #if TARGET_API_MAC_CARBON
8337 if (mac_do_track_dragUPP
)
8338 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8339 if (mac_do_receive_dragUPP
)
8340 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8344 /* Open Application Apple Event */
8346 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8352 /* Defined in mac.c. */
8354 path_from_vol_dir_name (char *, int, short, long, char *);
8357 /* Called when we receive an AppleEvent with an ID of
8358 "kAEOpenDocuments". This routine gets the direct parameter,
8359 extracts the FSSpecs in it, and puts their names on a list. */
8360 #pragma options align=mac68k
8361 typedef struct SelectionRange
{
8362 short unused1
; // 0 (not used)
8363 short lineNum
; // line to select (<0 to specify range)
8364 long startRange
; // start of selection range (if line < 0)
8365 long endRange
; // end of selection range (if line < 0)
8366 long unused2
; // 0 (not used)
8367 long theDate
; // modification date/time
8369 #pragma options align=reset
8372 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8377 DescType actual_type
;
8379 SelectionRange position
;
8381 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8383 goto descriptor_error_exit
;
8385 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8387 drag_and_drop_file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8388 make_number (position
.startRange
+ 1),
8389 make_number (position
.endRange
+ 1)),
8390 drag_and_drop_file_list
);
8392 /* Check to see that we got all of the required parameters from the
8393 event descriptor. For an 'odoc' event this should just be the
8395 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8396 &actual_type
, (Ptr
) &keyword
,
8397 sizeof (keyword
), &actual_size
);
8398 /* No error means that we found some unused parameters.
8399 errAEDescNotFound means that there are no more parameters. If we
8400 get an error code other than that, flag it. */
8401 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8403 err
= errAEEventNotHandled
;
8408 /* Got all the parameters we need. Now, go through the direct
8409 object list and parse it up. */
8411 long num_files_to_open
;
8413 err
= AECountItems (&the_desc
, &num_files_to_open
);
8418 /* AE file list is one based so just use that for indexing here. */
8419 for (i
= 1; i
<= num_files_to_open
; i
++)
8421 char unix_path_name
[MAXPATHLEN
];
8425 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8426 &actual_type
, &fref
, sizeof (FSRef
),
8428 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8431 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8436 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8437 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8438 if (err
!= noErr
) continue;
8440 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
8441 sizeof (unix_path_name
) - 1) == noErr
)
8443 /* x-dnd functions expect undecoded filenames. */
8444 drag_and_drop_file_list
=
8445 Fcons (make_unibyte_string (unix_path_name
,
8446 strlen (unix_path_name
)),
8447 drag_and_drop_file_list
);
8453 /* Nuke the coerced file list in any case */
8454 err2
= AEDisposeDesc(&the_desc
);
8456 descriptor_error_exit
:
8457 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8462 #if TARGET_API_MAC_CARBON
8464 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8465 void *handlerRefCon
, DragReference theDrag
)
8467 static int can_accept
;
8470 ItemReference theItem
;
8471 FlavorFlags theFlags
;
8474 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8475 return dragNotAcceptedErr
;
8479 case kDragTrackingEnterHandler
:
8480 CountDragItems (theDrag
, &items
);
8482 for (index
= 1; index
<= items
; index
++)
8484 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8485 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8486 if (result
== noErr
)
8494 case kDragTrackingEnterWindow
:
8497 RgnHandle hilite_rgn
= NewRgn ();
8499 struct frame
*f
= mac_window_to_frame (window
);
8501 GetWindowPortBounds (window
, &r
);
8502 OffsetRect (&r
, -r
.left
, -r
.top
);
8503 RectRgn (hilite_rgn
, &r
);
8504 ShowDragHilite (theDrag
, hilite_rgn
, true);
8505 DisposeRgn (hilite_rgn
);
8506 SetThemeCursor (kThemeCopyArrowCursor
);
8510 case kDragTrackingInWindow
:
8513 case kDragTrackingLeaveWindow
:
8516 struct frame
*f
= mac_window_to_frame (window
);
8518 HideDragHilite (theDrag
);
8519 SetThemeCursor (kThemeArrowCursor
);
8523 case kDragTrackingLeaveHandler
:
8531 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8532 DragReference theDrag
)
8536 FlavorFlags theFlags
;
8539 ItemReference theItem
;
8541 Size size
= sizeof (HFSFlavor
);
8543 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8544 return dragNotAcceptedErr
;
8546 drag_and_drop_file_list
= Qnil
;
8547 GetDragMouse (theDrag
, &mouse
, 0L);
8548 CountDragItems (theDrag
, &items
);
8549 for (index
= 1; index
<= items
; index
++)
8551 /* Only handle file references. */
8552 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8553 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8554 if (result
== noErr
)
8559 char unix_path_name
[MAXPATHLEN
];
8561 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8563 /* Use Carbon routines, otherwise it converts the file name
8564 to /Macintosh HD/..., which is not correct. */
8565 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8566 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8568 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
8569 sizeof (unix_path_name
) - 1) == noErr
)
8571 /* x-dnd functions expect undecoded filenames. */
8572 drag_and_drop_file_list
=
8573 Fcons (make_unibyte_string (unix_path_name
,
8574 strlen (unix_path_name
)),
8575 drag_and_drop_file_list
);
8578 /* If there are items in the list, construct an event and post it to
8579 the queue like an interrupt using kbd_buffer_store_event. */
8580 if (!NILP (drag_and_drop_file_list
))
8582 struct input_event event
;
8584 struct frame
*f
= mac_window_to_frame (window
);
8587 GlobalToLocal (&mouse
);
8588 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8590 event
.kind
= DRAG_N_DROP_EVENT
;
8592 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8593 event
.timestamp
= TickCount () * (1000 / 60);
8594 XSETINT (event
.x
, mouse
.h
);
8595 XSETINT (event
.y
, mouse
.v
);
8596 XSETFRAME (frame
, f
);
8597 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8599 /* Post to the interrupt queue */
8600 kbd_buffer_store_event (&event
);
8601 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8603 ProcessSerialNumber psn
;
8604 GetCurrentProcess (&psn
);
8605 SetFrontProcess (&psn
);
8611 return dragNotAcceptedErr
;
8616 /* Print Document Apple Event */
8618 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8620 return errAEEventNotHandled
;
8625 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8627 #if USE_CARBON_EVENTS
8629 EventRef event
= NULL
;
8630 static const HICommand quit_command
= {kEventAttributeNone
, kHICommandQuit
};
8632 err
= CreateEvent (NULL
, kEventClassCommand
, kEventCommandProcess
, 0,
8633 kEventAttributeUserEvent
, &event
);
8635 err
= SetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
8636 sizeof (HICommand
), &quit_command
);
8638 mac_store_application_menu_event (event
);
8640 ReleaseEvent (event
);
8645 return errAEEventNotHandled
;
8647 mac_store_application_menu_event (kHICommandQuit
);
8656 profiler_exit_proc ()
8658 ProfilerDump ("\pEmacs.prof");
8663 /* These few functions implement Emacs as a normal Mac application
8664 (almost): set up the heap and the Toolbox, handle necessary system
8665 events plus a few simple menu events. They also set up Emacs's
8666 access to functions defined in the rest of this file. Emacs uses
8667 function hooks to perform all its terminal I/O. A complete list of
8668 these functions appear in termhooks.h. For what they do, read the
8669 comments there and see also w32term.c and xterm.c. What's
8670 noticeably missing here is the event loop, which is normally
8671 present in most Mac application. After performing the necessary
8672 Mac initializations, main passes off control to emacs_main
8673 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
8674 (defined further below) to read input. This is where
8675 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
8682 #if __profile__ /* is the profiler on? */
8683 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
8688 /* set creator and type for files created by MSL */
8693 do_init_managers ();
8698 do_check_ram_size ();
8701 init_emacs_passwd_dir ();
8705 initialize_applescript ();
8707 init_required_apple_events ();
8713 /* set up argv array from STR# resource */
8714 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
8718 /* free up AppleScript resources on exit */
8719 atexit (terminate_applescript
);
8721 #if __profile__ /* is the profiler on? */
8722 atexit (profiler_exit_proc
);
8725 /* 3rd param "envp" never used in emacs_main */
8726 (void) emacs_main (argc
, argv
, 0);
8729 /* Never reached - real exit in Fkill_emacs */
8734 /* Table for translating Mac keycode to X keysym values. Contributed
8736 Mapping for special keys is now identical to that in Apple X11
8737 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8738 on the right of the Cmd key on laptops, and fn + `enter' (->
8740 static unsigned char keycode_to_xkeysym_table
[] = {
8741 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8742 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8743 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8745 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8746 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8747 /*0x38*/ 0, 0, 0, 0,
8748 /*0x3C*/ 0, 0, 0, 0,
8750 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8751 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8752 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8753 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8755 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8756 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8757 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8758 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8760 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8761 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8762 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8763 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8765 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8766 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8767 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8768 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8772 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8774 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8775 return *xKeySym
!= 0;
8778 #if !USE_CARBON_EVENTS
8779 static RgnHandle mouse_region
= NULL
;
8782 mac_wait_next_event (er
, sleep_time
, dequeue
)
8787 static EventRecord er_buf
= {nullEvent
};
8788 UInt32 target_tick
, current_tick
;
8789 EventMask event_mask
;
8791 if (mouse_region
== NULL
)
8792 mouse_region
= NewRgn ();
8794 event_mask
= everyEvent
;
8795 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8796 event_mask
-= highLevelEventMask
;
8798 current_tick
= TickCount ();
8799 target_tick
= current_tick
+ sleep_time
;
8801 if (er_buf
.what
== nullEvent
)
8802 while (!WaitNextEvent (event_mask
, &er_buf
,
8803 target_tick
- current_tick
, mouse_region
))
8805 current_tick
= TickCount ();
8806 if (target_tick
<= current_tick
)
8812 er_buf
.what
= nullEvent
;
8815 #endif /* not USE_CARBON_EVENTS */
8817 /* Emacs calls this whenever it wants to read an input event from the
8820 XTread_socket (sd
, expected
, hold_quit
)
8822 struct input_event
*hold_quit
;
8824 struct input_event inev
;
8826 #if USE_CARBON_EVENTS
8828 EventTargetRef toolbox_dispatcher
;
8831 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8833 if (interrupt_input_blocked
)
8835 interrupt_input_pending
= 1;
8839 interrupt_input_pending
= 0;
8842 /* So people can tell when we have read the available input. */
8843 input_signal_count
++;
8845 #if USE_CARBON_EVENTS
8846 toolbox_dispatcher
= GetEventDispatcherTarget ();
8848 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8849 kEventRemoveFromQueue
, &eventRef
))
8850 #else /* !USE_CARBON_EVENTS */
8851 while (mac_wait_next_event (&er
, 0, true))
8852 #endif /* !USE_CARBON_EVENTS */
8857 /* It is necessary to set this (additional) argument slot of an
8858 event to nil because keyboard.c protects incompletely
8859 processed event from being garbage collected by placing them
8860 in the kbd_buffer_gcpro vector. */
8862 inev
.kind
= NO_EVENT
;
8865 #if USE_CARBON_EVENTS
8866 /* Handle new events */
8867 if (!mac_convert_event_ref (eventRef
, &er
))
8868 switch (GetEventClass (eventRef
))
8870 case kEventClassWindow
:
8871 if (GetEventKind (eventRef
) == kEventWindowBoundsChanged
)
8873 WindowPtr window_ptr
;
8874 GetEventParameter(eventRef
, kEventParamDirectObject
,
8875 typeWindowRef
, NULL
, sizeof(WindowPtr
),
8877 f
= mac_window_to_frame (window_ptr
);
8878 if (f
&& !f
->async_iconified
)
8879 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8880 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8883 case kEventClassMouse
:
8884 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
8888 struct frame
*f
= mac_focus_frame (dpyinfo
);
8889 WindowPtr window_ptr
;
8892 if (dpyinfo
->x_focus_frame
== NULL
)
8894 /* Beep if wheel move occurs when all the frames
8901 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
8902 typeSInt32
, NULL
, sizeof (SInt32
),
8904 GetEventParameter(eventRef
, kEventParamMouseLocation
,
8905 typeQDPoint
, NULL
, sizeof (Point
),
8907 inev
.kind
= WHEEL_EVENT
;
8909 inev
.modifiers
= (mac_event_to_emacs_modifiers (eventRef
)
8910 | ((delta
< 0) ? down_modifier
8912 window_ptr
= FRAME_MAC_WINDOW (f
);
8913 SetPortWindowPort (window_ptr
);
8914 GlobalToLocal (&point
);
8915 XSETINT (inev
.x
, point
.h
);
8916 XSETINT (inev
.y
, point
.v
);
8917 XSETFRAME (inev
.frame_or_window
,
8918 mac_window_to_frame (window_ptr
));
8919 inev
.timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
8922 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8927 /* Send the event to the appropriate receiver. */
8928 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8931 #endif /* USE_CARBON_EVENTS */
8937 WindowPtr window_ptr
;
8938 ControlPartCode part_code
;
8941 #if USE_CARBON_EVENTS
8942 /* This is needed to send mouse events like aqua window
8943 buttons to the correct handler. */
8944 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8945 != eventNotHandledErr
)
8949 if (dpyinfo
->grabbed
&& last_mouse_frame
8950 && FRAME_LIVE_P (last_mouse_frame
))
8952 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
8953 part_code
= inContent
;
8957 part_code
= FindWindow (er
.where
, &window_ptr
);
8958 if (tip_window
&& window_ptr
== tip_window
)
8960 HideWindow (tip_window
);
8961 part_code
= FindWindow (er
.where
, &window_ptr
);
8965 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
8971 f
= mac_focus_frame (dpyinfo
);
8972 saved_menu_event_location
= er
.where
;
8973 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
8974 XSETFRAME (inev
.frame_or_window
, f
);
8978 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
8979 SelectWindow (window_ptr
);
8982 ControlPartCode control_part_code
;
8984 Point mouse_loc
= er
.where
;
8986 ControlKind control_kind
;
8989 f
= mac_window_to_frame (window_ptr
);
8990 /* convert to local coordinates of new window */
8991 SetPortWindowPort (window_ptr
);
8993 GlobalToLocal (&mouse_loc
);
8994 #if TARGET_API_MAC_CARBON
8995 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
8996 &control_part_code
);
8999 GetControlKind (ch
, &control_kind
);
9002 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9006 #if USE_CARBON_EVENTS
9007 inev
.code
= mac_get_mouse_btn (eventRef
);
9008 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9010 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9011 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9013 XSETINT (inev
.x
, mouse_loc
.h
);
9014 XSETINT (inev
.y
, mouse_loc
.v
);
9015 inev
.timestamp
= er
.when
* (1000 / 60);
9016 /* ticks to milliseconds */
9018 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9020 #ifndef USE_TOOLKIT_SCROLL_BARS
9021 /* control_part_code becomes kControlNoPart if
9022 a progress indicator is clicked. */
9023 && control_part_code
!= kControlNoPart
9024 #else /* USE_TOOLKIT_SCROLL_BARS */
9026 && control_kind
.kind
== kControlKindScrollBar
9027 #endif /* MAC_OSX */
9028 #endif /* USE_TOOLKIT_SCROLL_BARS */
9031 struct scroll_bar
*bar
;
9033 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9035 bar
= tracked_scroll_bar
;
9036 #ifndef USE_TOOLKIT_SCROLL_BARS
9037 control_part_code
= kControlIndicatorPart
;
9041 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9042 #ifdef USE_TOOLKIT_SCROLL_BARS
9043 /* Make the "Ctrl-Mouse-2 splits window" work
9044 for toolkit scroll bars. */
9045 if (er
.modifiers
& controlKey
)
9046 x_scroll_bar_handle_click (bar
, control_part_code
,
9048 else if (er
.what
== mouseDown
)
9049 x_scroll_bar_handle_press (bar
, control_part_code
,
9050 inev
.timestamp
, &inev
);
9052 x_scroll_bar_handle_release (bar
, inev
.timestamp
,
9054 #else /* not USE_TOOLKIT_SCROLL_BARS */
9055 x_scroll_bar_handle_click (bar
, control_part_code
,
9057 if (er
.what
== mouseDown
9058 && control_part_code
== kControlIndicatorPart
)
9059 tracked_scroll_bar
= bar
;
9061 tracked_scroll_bar
= NULL
;
9062 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9067 int x
= mouse_loc
.h
;
9068 int y
= mouse_loc
.v
;
9070 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9071 if (EQ (window
, f
->tool_bar_window
))
9073 if (er
.what
== mouseDown
)
9074 handle_tool_bar_click (f
, x
, y
, 1, 0);
9076 handle_tool_bar_click (f
, x
, y
, 0,
9082 XSETFRAME (inev
.frame_or_window
, f
);
9083 inev
.kind
= MOUSE_CLICK_EVENT
;
9087 if (er
.what
== mouseDown
)
9089 dpyinfo
->grabbed
|= (1 << inev
.code
);
9090 last_mouse_frame
= f
;
9091 /* Ignore any mouse motion that happened
9092 before this event; any subsequent
9093 mouse-movement Emacs events should reflect
9094 only motion after the ButtonPress. */
9099 last_tool_bar_item
= -1;
9103 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9104 /* If a button is released though it was not
9105 previously pressed, that would be because
9106 of multi-button emulation. */
9107 dpyinfo
->grabbed
= 0;
9109 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9112 #ifdef USE_TOOLKIT_SCROLL_BARS
9113 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9118 inev
.modifiers
|= down_modifier
;
9121 inev
.modifiers
|= up_modifier
;
9128 #if TARGET_API_MAC_CARBON
9129 DragWindow (window_ptr
, er
.where
, NULL
);
9130 #else /* not TARGET_API_MAC_CARBON */
9131 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9132 #endif /* not TARGET_API_MAC_CARBON */
9133 /* Update the frame parameters. */
9135 struct frame
*f
= mac_window_to_frame (window_ptr
);
9137 if (f
&& !f
->async_iconified
)
9138 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9143 if (TrackGoAway (window_ptr
, er
.where
))
9145 inev
.kind
= DELETE_WINDOW_EVENT
;
9146 XSETFRAME (inev
.frame_or_window
,
9147 mac_window_to_frame (window_ptr
));
9151 /* window resize handling added --ben */
9153 do_grow_window (window_ptr
, &er
);
9156 /* window zoom handling added --ben */
9159 if (TrackBox (window_ptr
, er
.where
, part_code
))
9160 do_zoom_window (window_ptr
, part_code
);
9170 #if USE_CARBON_EVENTS
9171 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9172 != eventNotHandledErr
)
9175 do_window_update ((WindowPtr
) er
.message
);
9180 #if USE_CARBON_EVENTS
9181 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9182 != eventNotHandledErr
)
9185 switch ((er
.message
>> 24) & 0x000000FF)
9187 case suspendResumeMessage
:
9188 if ((er
.message
& resumeFlag
) == 1)
9194 case mouseMovedMessage
:
9195 #if !USE_CARBON_EVENTS
9196 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9197 er
.where
.h
+ 1, er
.where
.v
+ 1);
9199 previous_help_echo_string
= help_echo_string
;
9200 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
9203 if (dpyinfo
->grabbed
&& last_mouse_frame
9204 && FRAME_LIVE_P (last_mouse_frame
))
9205 f
= last_mouse_frame
;
9207 f
= dpyinfo
->x_focus_frame
;
9209 if (dpyinfo
->mouse_face_hidden
)
9211 dpyinfo
->mouse_face_hidden
= 0;
9212 clear_mouse_face (dpyinfo
);
9217 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9218 Point mouse_pos
= er
.where
;
9220 SetPortWindowPort (wp
);
9222 GlobalToLocal (&mouse_pos
);
9224 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9225 #ifdef USE_TOOLKIT_SCROLL_BARS
9226 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9227 mouse_pos
, er
.when
* (1000 / 60),
9229 #else /* not USE_TOOLKIT_SCROLL_BARS */
9230 x_scroll_bar_note_movement (tracked_scroll_bar
,
9232 - XINT (tracked_scroll_bar
->top
),
9233 er
.when
* (1000 / 60));
9234 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9237 /* Generate SELECT_WINDOW_EVENTs when needed. */
9238 if (mouse_autoselect_window
)
9242 window
= window_from_coordinates (f
,
9247 /* Window will be selected only when it is
9248 not selected now and last mouse movement
9249 event was not in it. Minibuffer window
9250 will be selected iff it is active. */
9251 if (WINDOWP (window
)
9252 && !EQ (window
, last_window
)
9253 && !EQ (window
, selected_window
))
9255 inev
.kind
= SELECT_WINDOW_EVENT
;
9256 inev
.frame_or_window
= window
;
9261 note_mouse_movement (f
, &mouse_pos
);
9265 /* If the contents of the global variable
9266 help_echo_string has changed, generate a
9268 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
9276 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
9278 #if USE_CARBON_EVENTS
9279 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9280 != eventNotHandledErr
)
9283 if (window_ptr
== tip_window
)
9285 HideWindow (tip_window
);
9289 if (!is_emacs_window (window_ptr
))
9292 if ((er
.modifiers
& activeFlag
) != 0)
9294 /* A window has been activated */
9295 Point mouse_loc
= er
.where
;
9297 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9299 SetPortWindowPort (window_ptr
);
9300 GlobalToLocal (&mouse_loc
);
9301 /* Window-activated event counts as mouse movement,
9302 so update things that depend on mouse position. */
9303 note_mouse_movement (mac_window_to_frame (window_ptr
),
9308 /* A window has been deactivated */
9309 #if USE_TOOLKIT_SCROLL_BARS
9310 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9312 struct input_event event
;
9315 event
.kind
= NO_EVENT
;
9316 x_scroll_bar_handle_release (tracked_scroll_bar
,
9317 er
.when
* (1000 / 60),
9319 if (event
.kind
!= NO_EVENT
)
9321 kbd_buffer_store_event_hold (&event
, hold_quit
);
9326 dpyinfo
->grabbed
= 0;
9328 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9330 f
= mac_window_to_frame (window_ptr
);
9331 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9333 /* If we move outside the frame, then we're
9334 certainly no longer on any text in the
9336 clear_mouse_face (dpyinfo
);
9337 dpyinfo
->mouse_face_mouse_frame
= 0;
9340 /* Generate a nil HELP_EVENT to cancel a help-echo.
9341 Do it only if there's something to cancel.
9342 Otherwise, the startup message is cleared when the
9343 mouse leaves the frame. */
9344 if (any_help_event_p
)
9353 int keycode
= (er
.message
& keyCodeMask
) >> 8;
9356 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9357 /* When using Carbon Events, we need to pass raw keyboard
9358 events to the TSM ourselves. If TSM handles it, it
9359 will pass back noErr, otherwise it will pass back
9360 "eventNotHandledErr" and we can process it
9362 if ((!NILP (Vmac_pass_command_to_system
)
9363 || !(er
.modifiers
& cmdKey
))
9364 && (!NILP (Vmac_pass_control_to_system
)
9365 || !(er
.modifiers
& controlKey
)))
9366 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9367 != eventNotHandledErr
)
9372 if (dpyinfo
->x_focus_frame
== NULL
)
9374 /* Beep if keyboard input occurs when all the frames
9382 static SInt16 last_key_script
= -1;
9383 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
9385 if (last_key_script
!= current_key_script
)
9387 struct input_event event
;
9390 event
.kind
= LANGUAGE_CHANGE_EVENT
;
9392 event
.code
= current_key_script
;
9393 kbd_buffer_store_event (&event
);
9396 last_key_script
= current_key_script
;
9401 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
9403 clear_mouse_face (dpyinfo
);
9404 dpyinfo
->mouse_face_hidden
= 1;
9407 if (keycode_to_xkeysym (keycode
, &xkeysym
))
9409 inev
.code
= 0xff00 | xkeysym
;
9410 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
9414 if (er
.modifiers
& (controlKey
|
9415 (NILP (Vmac_command_key_is_meta
) ? optionKey
9418 /* This code comes from Keyboard Resource,
9419 Appendix C of IM - Text. This is necessary
9420 since shift is ignored in KCHR table
9421 translation when option or command is pressed.
9422 It also does not translate correctly
9423 control-shift chars like C-% so mask off shift
9425 int new_modifiers
= er
.modifiers
& 0xe600;
9426 /* mask off option and command */
9427 int new_keycode
= keycode
| new_modifiers
;
9428 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9429 unsigned long some_state
= 0;
9430 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9431 &some_state
) & 0xff;
9433 else if (!NILP (Vmac_option_modifier
)
9434 && (er
.modifiers
& optionKey
))
9436 /* When using the option key as an emacs modifier,
9437 convert the pressed key code back to one
9438 without the Mac option modifier applied. */
9439 int new_modifiers
= er
.modifiers
& ~optionKey
;
9440 int new_keycode
= keycode
| new_modifiers
;
9441 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9442 unsigned long some_state
= 0;
9443 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9444 &some_state
) & 0xff;
9447 inev
.code
= er
.message
& charCodeMask
;
9448 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9452 #if USE_CARBON_EVENTS
9453 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9455 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9457 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
9458 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9461 case kHighLevelEvent
:
9462 drag_and_drop_file_list
= Qnil
;
9464 AEProcessAppleEvent(&er
);
9466 /* Build a DRAG_N_DROP_EVENT type event as is done in
9467 constuct_drag_n_drop in w32term.c. */
9468 if (!NILP (drag_and_drop_file_list
))
9470 struct frame
*f
= mac_focus_frame (dpyinfo
);
9474 inev
.kind
= DRAG_N_DROP_EVENT
;
9476 inev
.timestamp
= er
.when
* (1000 / 60);
9477 /* ticks to milliseconds */
9478 #if USE_CARBON_EVENTS
9479 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9481 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9484 XSETINT (inev
.x
, 0);
9485 XSETINT (inev
.y
, 0);
9487 XSETFRAME (frame
, f
);
9488 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9491 /* Regardless of whether Emacs was suspended or in the
9492 foreground, ask it to redraw its entire screen.
9493 Otherwise parts of the screen can be left in an
9494 inconsistent state. */
9495 wp
= FRAME_MAC_WINDOW (f
);
9497 #if TARGET_API_MAC_CARBON
9501 GetWindowPortBounds (wp
, &r
);
9502 InvalWindowRect (wp
, &r
);
9504 #else /* not TARGET_API_MAC_CARBON */
9505 InvalRect (&(wp
->portRect
));
9506 #endif /* not TARGET_API_MAC_CARBON */
9512 #if USE_CARBON_EVENTS
9513 ReleaseEvent (eventRef
);
9516 if (inev
.kind
!= NO_EVENT
)
9518 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9523 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9528 XSETFRAME (frame
, f
);
9534 any_help_event_p
= 1;
9535 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9536 help_echo_object
, help_echo_pos
);
9540 help_echo_string
= Qnil
;
9541 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9548 /* If the focus was just given to an autoraising frame,
9550 /* ??? This ought to be able to handle more than one such frame. */
9551 if (pending_autoraise_frame
)
9553 x_raise_frame (pending_autoraise_frame
);
9554 pending_autoraise_frame
= 0;
9562 /* Need to override CodeWarrior's input function so no conversion is
9563 done on newlines Otherwise compiled functions in .elc files will be
9564 read incorrectly. Defined in ...:MSL C:MSL
9565 Common:Source:buffer_io.c. */
9568 __convert_to_newlines (unsigned char * p
, size_t * n
)
9574 __convert_from_newlines (unsigned char * p
, size_t * n
)
9582 make_mac_terminal_frame (struct frame
*f
)
9587 XSETFRAME (frame
, f
);
9589 f
->output_method
= output_mac
;
9590 f
->output_data
.mac
= (struct mac_output
*)
9591 xmalloc (sizeof (struct mac_output
));
9592 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9594 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9596 FRAME_COLS (f
) = 96;
9597 FRAME_LINES (f
) = 4;
9599 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9600 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9602 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9604 f
->output_data
.mac
->cursor_pixel
= 0;
9605 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9606 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9607 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9609 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9610 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9611 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9612 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9613 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9614 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9616 FRAME_FONTSET (f
) = -1;
9617 f
->output_data
.mac
->explicit_parent
= 0;
9620 f
->border_width
= 0;
9622 f
->internal_border_width
= 0;
9627 f
->new_text_cols
= 0;
9628 f
->new_text_lines
= 0;
9630 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9631 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9632 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9636 if (!(FRAME_MAC_WINDOW (f
) =
9637 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9638 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9640 /* so that update events can find this mac_output struct */
9641 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9647 /* Need to be initialized for unshow_buffer in window.c. */
9648 selected_window
= f
->selected_window
;
9650 Fmodify_frame_parameters (frame
,
9651 Fcons (Fcons (Qfont
,
9652 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9653 Fmodify_frame_parameters (frame
,
9654 Fcons (Fcons (Qforeground_color
,
9655 build_string ("black")), Qnil
));
9656 Fmodify_frame_parameters (frame
,
9657 Fcons (Fcons (Qbackground_color
,
9658 build_string ("white")), Qnil
));
9663 /***********************************************************************
9665 ***********************************************************************/
9667 int mac_initialized
= 0;
9670 mac_initialize_display_info ()
9672 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9673 GDHandle main_device_handle
;
9675 bzero (dpyinfo
, sizeof (*dpyinfo
));
9678 dpyinfo
->mac_id_name
9679 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9680 + SCHARS (Vsystem_name
)
9682 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9683 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9685 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9686 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9689 main_device_handle
= LMGetMainDevice();
9691 dpyinfo
->reference_count
= 0;
9692 dpyinfo
->resx
= 75.0;
9693 dpyinfo
->resy
= 75.0;
9694 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9696 /* HasDepth returns true if it is possible to have a 32 bit display,
9697 but this may not be what is actually used. Mac OSX can do better.
9698 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9699 header for CGGetActiveDisplayList says that the first display returned
9700 is the active one, so we use that. */
9702 CGDirectDisplayID disp_id
[1];
9703 CGDisplayCount disp_count
;
9704 CGDisplayErr error_code
;
9706 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
9707 if (error_code
!= 0)
9708 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
9710 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
9713 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
9714 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
9715 gdDevType
, dpyinfo
->color_p
))
9718 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
9719 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
9720 dpyinfo
->grabbed
= 0;
9721 dpyinfo
->root_window
= NULL
;
9722 dpyinfo
->image_cache
= make_image_cache ();
9724 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9725 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9726 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9727 dpyinfo
->mouse_face_window
= Qnil
;
9728 dpyinfo
->mouse_face_overlay
= Qnil
;
9729 dpyinfo
->mouse_face_hidden
= 0;
9734 mac_make_rdb (xrm_option
)
9737 XrmDatabase database
;
9739 database
= xrm_get_preference_database (NULL
);
9741 xrm_merge_string_database (database
, xrm_option
);
9746 struct mac_display_info
*
9747 mac_term_init (display_name
, xrm_option
, resource_name
)
9748 Lisp_Object display_name
;
9750 char *resource_name
;
9752 struct mac_display_info
*dpyinfo
;
9756 if (!mac_initialized
)
9759 mac_initialized
= 1;
9763 error ("Sorry, this version can only handle one display");
9765 mac_initialize_display_info ();
9767 dpyinfo
= &one_mac_display_info
;
9769 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
9771 /* Put this display on the chain. */
9772 dpyinfo
->next
= x_display_list
;
9773 x_display_list
= dpyinfo
;
9775 /* Put it on x_display_name_list. */
9776 x_display_name_list
= Fcons (Fcons (display_name
,
9777 Fcons (Qnil
, dpyinfo
->xrdb
)),
9778 x_display_name_list
);
9779 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9785 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9788 x_delete_display (dpyinfo
)
9789 struct mac_display_info
*dpyinfo
;
9793 /* Discard this display from x_display_name_list and x_display_list.
9794 We can't use Fdelq because that can quit. */
9795 if (! NILP (x_display_name_list
)
9796 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9797 x_display_name_list
= XCDR (x_display_name_list
);
9802 tail
= x_display_name_list
;
9803 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9805 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9807 XSETCDR (tail
, XCDR (XCDR (tail
)));
9814 if (x_display_list
== dpyinfo
)
9815 x_display_list
= dpyinfo
->next
;
9818 struct x_display_info
*tail
;
9820 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9821 if (tail
->next
== dpyinfo
)
9822 tail
->next
= tail
->next
->next
;
9825 /* Free the font names in the font table. */
9826 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9827 if (dpyinfo
->font_table
[i
].name
)
9829 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9830 xfree (dpyinfo
->font_table
[i
].full_name
);
9831 xfree (dpyinfo
->font_table
[i
].name
);
9834 if (dpyinfo
->font_table
->font_encoder
)
9835 xfree (dpyinfo
->font_table
->font_encoder
);
9837 xfree (dpyinfo
->font_table
);
9838 xfree (dpyinfo
->mac_id_name
);
9840 if (x_display_list
== 0)
9842 mac_clear_font_name_table ();
9843 bzero (dpyinfo
, sizeof (*dpyinfo
));
9852 extern int inhibit_window_system
;
9853 extern int noninteractive
;
9854 CFBundleRef appsBundle
;
9857 /* No need to test if already -nw*/
9858 if (inhibit_window_system
|| noninteractive
)
9861 appsBundle
= CFBundleGetMainBundle();
9862 if (appsBundle
!= NULL
)
9864 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
9865 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
9866 /* We found the bundle identifier, now we know we are valid. */
9873 /* MAC_TODO: Have this start the bundled executable */
9875 /* For now, prevent the fatal error by bringing it up in the terminal */
9876 inhibit_window_system
= 1;
9880 MakeMeTheFrontProcess ()
9882 ProcessSerialNumber psn
;
9885 err
= GetCurrentProcess (&psn
);
9887 (void) SetFrontProcess (&psn
);
9890 /***** Code to handle C-g testing *****/
9892 /* Contains the Mac modifier formed from quit_char */
9893 static mac_quit_char_modifiers
= 0;
9894 static mac_quit_char_keycode
;
9895 extern int quit_char
;
9898 mac_determine_quit_char_modifiers()
9900 /* Todo: Determine modifiers from quit_char. */
9901 UInt32 qc_modifiers
= ctrl_modifier
;
9904 mac_quit_char_modifiers
= 0;
9905 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
9906 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
9907 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
9908 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
9912 init_quit_char_handler ()
9914 /* TODO: Let this support keys other the 'g' */
9915 mac_quit_char_keycode
= 5;
9916 /* Look at <architecture/adb_kb_map.h> for details */
9917 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9919 mac_determine_quit_char_modifiers();
9923 quit_char_comp (EventRef inEvent
, void *inCompData
)
9925 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
9927 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
9931 UInt32 keyModifiers
;
9932 GetEventParameter(inEvent
, kEventParamKeyCode
,
9933 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
9934 if (keyCode
!= mac_quit_char_keycode
)
9936 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
9937 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
9938 if (keyModifiers
!= mac_quit_char_modifiers
)
9945 mac_check_for_quit_char ()
9948 static EMACS_TIME last_check_time
= { 0, 0 };
9949 static EMACS_TIME one_second
= { 1, 0 };
9952 /* If windows are not initialized, return immediately (keep it bouncin'). */
9953 if (!mac_quit_char_modifiers
)
9956 /* Don't check if last check is less than a second ago. */
9957 EMACS_GET_TIME (now
);
9958 EMACS_SUB_TIME (t
, now
, last_check_time
);
9959 if (EMACS_TIME_LT (t
, one_second
))
9961 last_check_time
= now
;
9963 /* Redetermine modifiers because they are based on lisp variables */
9964 mac_determine_quit_char_modifiers ();
9966 /* Fill the queue with events */
9968 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
9969 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
9974 struct input_event e
;
9976 /* Use an input_event to emulate what the interrupt handler does. */
9978 e
.kind
= ASCII_KEYSTROKE_EVENT
;
9982 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
9983 XSETFRAME (e
.frame_or_window
, mac_focus_frame (&one_mac_display_info
));
9984 /* Remove event from queue to prevent looping. */
9985 RemoveEventFromQueue (GetMainEventQueue (), event
);
9986 ReleaseEvent (event
);
9987 kbd_buffer_store_event (&e
);
9990 #endif /* MAC_OSX */
9998 MenuItemIndex menu_index
;
10000 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10001 &menu
, &menu_index
);
10003 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10004 #if USE_CARBON_EVENTS
10005 EnableMenuCommand (NULL
, kHICommandPreferences
);
10006 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10007 &menu
, &menu_index
);
10010 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10011 InsertMenuItemTextWithCFString (menu
, NULL
,
10012 0, kMenuItemAttrSeparator
, 0);
10013 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10014 0, 0, kHICommandAbout
);
10016 #endif /* USE_CARBON_EVENTS */
10017 #else /* !MAC_OSX */
10018 #if USE_CARBON_EVENTS
10019 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10025 /* Set up use of X before we make the first connection. */
10027 extern frame_parm_handler mac_frame_parm_handlers
[];
10029 static struct redisplay_interface x_redisplay_interface
=
10031 mac_frame_parm_handlers
,
10035 x_clear_end_of_line
,
10037 x_after_update_window_line
,
10038 x_update_window_begin
,
10039 x_update_window_end
,
10042 0, /* flush_display_optional */
10043 x_clear_window_mouse_face
,
10044 x_get_glyph_overhangs
,
10045 x_fix_overlapping_area
,
10046 x_draw_fringe_bitmap
,
10047 0, /* define_fringe_bitmap */
10048 0, /* destroy_fringe_bitmap */
10049 mac_per_char_metric
,
10051 mac_compute_glyph_string_overhangs
,
10052 x_draw_glyph_string
,
10053 mac_define_frame_cursor
,
10054 mac_clear_frame_area
,
10055 mac_draw_window_cursor
,
10056 mac_draw_vertical_window_border
,
10057 mac_shift_glyphs_for_insert
10063 rif
= &x_redisplay_interface
;
10065 clear_frame_hook
= x_clear_frame
;
10066 ins_del_lines_hook
= x_ins_del_lines
;
10067 delete_glyphs_hook
= x_delete_glyphs
;
10068 ring_bell_hook
= XTring_bell
;
10069 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10070 set_terminal_modes_hook
= XTset_terminal_modes
;
10071 update_begin_hook
= x_update_begin
;
10072 update_end_hook
= x_update_end
;
10073 set_terminal_window_hook
= XTset_terminal_window
;
10074 read_socket_hook
= XTread_socket
;
10075 frame_up_to_date_hook
= XTframe_up_to_date
;
10076 mouse_position_hook
= XTmouse_position
;
10077 frame_rehighlight_hook
= XTframe_rehighlight
;
10078 frame_raise_lower_hook
= XTframe_raise_lower
;
10080 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10081 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10082 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10083 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10085 scroll_region_ok
= 1; /* we'll scroll partial frames */
10086 char_ins_del_ok
= 1;
10087 line_ins_del_ok
= 1; /* we'll just blt 'em */
10088 fast_clear_end_of_line
= 1; /* X does this well */
10089 memory_below_frame
= 0; /* we don't remember what scrolls
10094 last_tool_bar_item
= -1;
10095 any_help_event_p
= 0;
10097 /* Try to use interrupt input; if we can't, then start polling. */
10098 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10102 #if TARGET_API_MAC_CARBON
10103 init_required_apple_events ();
10105 #if USE_CARBON_EVENTS
10107 init_service_handler ();
10109 init_quit_char_handler ();
10110 #endif /* MAC_OSX */
10112 init_command_handler ();
10115 #endif /* USE_CARBON_EVENTS */
10118 if (!inhibit_window_system
)
10119 MakeMeTheFrontProcess ();
10130 staticpro (&x_error_message_string
);
10131 x_error_message_string
= Qnil
;
10134 Qmodifier_value
= intern ("modifier-value");
10135 Qalt
= intern ("alt");
10136 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10137 Qhyper
= intern ("hyper");
10138 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10139 Qsuper
= intern ("super");
10140 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10142 Qapplication
= intern ("application"); staticpro (&Qapplication
);
10143 Qabout
= intern ("about"); staticpro (&Qabout
);
10145 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10146 Qpreferences
= intern ("preferences"); staticpro (&Qpreferences
);
10147 Qservices
= intern ("services"); staticpro (&Qservices
);
10148 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10149 Qperform
= intern ("perform"); staticpro (&Qperform
);
10153 Fprovide (intern ("mac-carbon"), Qnil
);
10156 staticpro (&Qreverse
);
10157 Qreverse
= intern ("reverse");
10159 staticpro (&x_display_name_list
);
10160 x_display_name_list
= Qnil
;
10162 staticpro (&last_mouse_scroll_bar
);
10163 last_mouse_scroll_bar
= Qnil
;
10165 staticpro (&Qvendor_specific_keysyms
);
10166 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
10168 staticpro (&last_mouse_press_frame
);
10169 last_mouse_press_frame
= Qnil
;
10171 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
10172 staticpro (&Qmac_ready_for_drag_n_drop
);
10174 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10175 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10176 #ifdef USE_TOOLKIT_SCROLL_BARS
10177 Vx_toolkit_scroll_bars
= Qt
;
10179 Vx_toolkit_scroll_bars
= Qnil
;
10182 DEFVAR_BOOL ("x-use-underline-position-properties",
10183 &x_use_underline_position_properties
,
10184 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10185 nil means ignore them. If you encounter fonts with bogus
10186 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10187 to 4.1, set this to nil. */);
10188 x_use_underline_position_properties
= 0;
10190 staticpro (&last_mouse_motion_frame
);
10191 last_mouse_motion_frame
= Qnil
;
10193 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
10194 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
10195 Otherwise the option key is used. */);
10196 Vmac_command_key_is_meta
= Qt
;
10198 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10199 doc
: /* Modifier to use for the Mac alt/option key. The value can
10200 be alt, hyper, or super for the respective modifier. If the value is
10201 nil then the key will act as the normal Mac option modifier. */);
10202 Vmac_option_modifier
= Qnil
;
10204 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
10205 doc
: /* Non-nil means that the control and meta keys are reversed. This is
10206 useful for non-standard keyboard layouts. */);
10207 Vmac_reverse_ctrl_meta
= Qnil
;
10209 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10210 &Vmac_emulate_three_button_mouse
,
10211 doc
: /* t means that when the option-key is held down while pressing the
10212 mouse button, the click will register as mouse-2 and while the
10213 command-key is held down, the click will register as mouse-3.
10214 'reverse means that the the option-key will register for mouse-3
10215 and the command-key will register for mouse-2. nil means that
10216 no emulation should be done and the modifiers should be placed
10217 on the mouse-1 event. */);
10218 Vmac_emulate_three_button_mouse
= Qnil
;
10220 #if USE_CARBON_EVENTS
10221 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
10222 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
10223 the right click will be mouse-3.
10224 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10225 Vmac_wheel_button_is_mouse_2
= Qt
;
10227 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
10228 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10229 Toolbox for processing before Emacs sees it. */);
10230 Vmac_pass_command_to_system
= Qt
;
10232 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
10233 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10234 Toolbox for processing before Emacs sees it. */);
10235 Vmac_pass_control_to_system
= Qt
;
10239 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
10240 doc
: /* If non-nil, allow anti-aliasing.
10241 The text will be rendered using Core Graphics text rendering which
10242 may anti-alias the text. */);
10243 Vmac_use_core_graphics
= Qnil
;
10245 /* Register an entry for `mac-roman' so that it can be used when
10246 creating the terminal frame on Mac OS 9 before loading
10247 term/mac-win.elc. */
10248 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10249 doc
: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10250 Each entry should be of the form:
10252 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10254 where CHARSET-NAME is a string used in font names to identify the
10255 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10256 is a coding system corresponding to TEXT-ENCODING. */);
10257 Vmac_charset_info_alist
=
10258 Fcons (list3 (build_string ("mac-roman"),
10259 make_number (smRoman
), Qnil
), Qnil
);
10262 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10263 (do not change this comment) */