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"
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 MAC_OSX */
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 MAC_OSX */
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)
100 /* Non-nil means Emacs uses toolkit scroll bars. */
102 Lisp_Object Vx_toolkit_scroll_bars
;
104 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
105 Lisp_Object Vmac_use_core_graphics
;
108 /* Non-zero means that a HELP_EVENT has been generated since Emacs
111 static int any_help_event_p
;
113 /* Non-zero means autoselect window with the mouse cursor. */
115 int x_autoselect_window_p
;
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), one for each element of x_display_list and in
133 the same order. NAME is the name of the frame. FONT-LIST-CACHE
134 records previous values returned by x-list-fonts. */
136 Lisp_Object x_display_name_list
;
138 /* This is display since Mac does not support multiple ones. */
139 struct mac_display_info one_mac_display_info
;
141 /* Frame being updated by update_frame. This is declared in term.c.
142 This is set by update_begin and looked at by all the XT functions.
143 It is zero while not inside an update. In that case, the XT
144 functions assume that `selected_frame' is the frame to apply to. */
146 extern struct frame
*updating_frame
;
148 extern int waiting_for_input
;
150 /* This is a frame waiting to be auto-raised, within XTread_socket. */
152 struct frame
*pending_autoraise_frame
;
154 /* Non-zero means user is interacting with a toolkit scroll bar. */
156 static int toolkit_scroll_bar_interaction
;
160 Formerly, we used PointerMotionHintMask (in standard_event_mask)
161 so that we would have to call XQueryPointer after each MotionNotify
162 event to ask for another such event. However, this made mouse tracking
163 slow, and there was a bug that made it eventually stop.
165 Simply asking for MotionNotify all the time seems to work better.
167 In order to avoid asking for motion events and then throwing most
168 of them away or busy-polling the server for mouse positions, we ask
169 the server for pointer motion hints. This means that we get only
170 one event per group of mouse movements. "Groups" are delimited by
171 other kinds of events (focus changes and button clicks, for
172 example), or by XQueryPointer calls; when one of these happens, we
173 get another MotionNotify event the next time the mouse moves. This
174 is at least as efficient as getting motion events when mouse
175 tracking is on, and I suspect only negligibly worse when tracking
178 /* Where the mouse was last time we reported a mouse event. */
180 static Rect last_mouse_glyph
;
181 static Lisp_Object last_mouse_press_frame
;
183 /* The scroll bar in which the last X motion event occurred.
185 If the last X motion event occurred in a scroll bar, we set this so
186 XTmouse_position can know whether to report a scroll bar motion or
189 If the last X motion event didn't occur in a scroll bar, we set
190 this to Qnil, to tell XTmouse_position to return an ordinary motion
193 static Lisp_Object last_mouse_scroll_bar
;
195 /* This is a hack. We would really prefer that XTmouse_position would
196 return the time associated with the position it returns, but there
197 doesn't seem to be any way to wrest the time-stamp from the server
198 along with the position query. So, we just keep track of the time
199 of the last movement we received, and return that in hopes that
200 it's somewhat accurate. */
202 static Time last_mouse_movement_time
;
204 struct scroll_bar
*tracked_scroll_bar
= NULL
;
206 /* Incremented by XTread_socket whenever it really tries to read
210 static int volatile input_signal_count
;
212 static int input_signal_count
;
215 /* Used locally within XTread_socket. */
217 static int x_noop_count
;
219 /* Initial values of argv and argc. */
221 extern char **initial_argv
;
222 extern int initial_argc
;
224 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
226 /* Tells if a window manager is present or not. */
228 extern Lisp_Object Vx_no_window_manager
;
232 /* A mask of extra modifier bits to put into every keyboard char. */
234 extern int extra_keyboard_modifiers
;
236 /* The keysyms to use for the various modifiers. */
238 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qmodifier_value
;
240 static Lisp_Object Qvendor_specific_keysyms
;
243 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
246 extern int inhibit_window_system
;
249 QDGlobals qd
; /* QuickDraw global information structure. */
253 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
254 struct mac_display_info
*mac_display_info_for_display (Display
*);
255 static void x_update_window_end
P_ ((struct window
*, int, int));
256 static void mac_handle_tool_bar_click
P_ ((struct frame
*, EventRecord
*));
257 static int x_io_error_quitter
P_ ((Display
*));
258 int x_catch_errors
P_ ((Display
*));
259 void x_uncatch_errors
P_ ((Display
*, int));
260 void x_lower_frame
P_ ((struct frame
*));
261 void x_scroll_bar_clear
P_ ((struct frame
*));
262 int x_had_errors_p
P_ ((Display
*));
263 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
264 void x_raise_frame
P_ ((struct frame
*));
265 void x_set_window_size
P_ ((struct frame
*, int, int, int));
266 void x_wm_set_window_state
P_ ((struct frame
*, int));
267 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
268 void mac_initialize
P_ ((void));
269 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
270 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
271 static void x_update_end
P_ ((struct frame
*));
272 static void XTframe_up_to_date
P_ ((struct frame
*));
273 static void XTreassert_line_highlight
P_ ((int, int));
274 static void x_change_line_highlight
P_ ((int, int, int, int));
275 static void XTset_terminal_modes
P_ ((void));
276 static void XTreset_terminal_modes
P_ ((void));
277 static void x_clear_frame
P_ ((void));
278 static void frame_highlight
P_ ((struct frame
*));
279 static void frame_unhighlight
P_ ((struct frame
*));
280 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
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 void activate_scroll_bars (FRAME_PTR
);
294 void deactivate_scroll_bars (FRAME_PTR
);
296 static int is_emacs_window (WindowPtr
);
298 int x_bitmap_icon (struct frame
*, Lisp_Object
);
299 void x_make_frame_visible (struct frame
*);
301 extern void window_scroll (Lisp_Object
, int, int, int);
303 /* Defined in macmenu.h. */
304 extern void menubar_selection_callback (FRAME_PTR
, int);
305 extern void set_frame_menubar (FRAME_PTR
, int, int);
307 /* X display function emulation */
310 XFreePixmap (display
, pixmap
)
311 Display
*display
; /* not used */
314 DisposeGWorld (pixmap
);
318 /* Set foreground color for subsequent QuickDraw commands. Assume
319 graphic port has already been set. */
322 mac_set_forecolor (unsigned long color
)
326 fg_color
.red
= RED16_FROM_ULONG (color
);
327 fg_color
.green
= GREEN16_FROM_ULONG (color
);
328 fg_color
.blue
= BLUE16_FROM_ULONG (color
);
330 RGBForeColor (&fg_color
);
334 /* Set background color for subsequent QuickDraw commands. Assume
335 graphic port has already been set. */
338 mac_set_backcolor (unsigned long color
)
342 bg_color
.red
= RED16_FROM_ULONG (color
);
343 bg_color
.green
= GREEN16_FROM_ULONG (color
);
344 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
346 RGBBackColor (&bg_color
);
349 /* Set foreground and background color for subsequent QuickDraw
350 commands. Assume that the graphic port has already been set. */
353 mac_set_colors (GC gc
)
355 mac_set_forecolor (gc
->foreground
);
356 mac_set_backcolor (gc
->background
);
359 /* Mac version of XDrawLine. */
362 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
368 SetPortWindowPort (w
);
377 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
386 GetGWorld (&old_port
, &old_gdh
);
391 LockPixels (GetGWorldPixMap (p
));
394 UnlockPixels (GetGWorldPixMap (p
));
396 SetGWorld (old_port
, old_gdh
);
399 /* Mac version of XClearArea. */
402 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
406 unsigned int width
, height
;
409 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
413 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
414 xgc
.background
= mwp
->x_compatible
.background_pixel
;
416 SetPortWindowPort (w
);
418 mac_set_colors (&xgc
);
419 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
424 /* Mac version of XClearWindow. */
427 XClearWindow (display
, w
)
431 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
434 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
435 xgc
.background
= mwp
->x_compatible
.background_pixel
;
437 SetPortWindowPort (w
);
439 mac_set_colors (&xgc
);
441 #if TARGET_API_MAC_CARBON
445 GetWindowPortBounds (w
, &r
);
448 #else /* not TARGET_API_MAC_CARBON */
449 EraseRect (&(w
->portRect
));
450 #endif /* not TARGET_API_MAC_CARBON */
454 /* Mac replacement for XCopyArea. */
457 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
461 int x
, y
, width
, height
;
462 unsigned short *bits
;
468 bitmap
.rowBytes
= sizeof(unsigned short);
469 bitmap
.baseAddr
= (char *)bits
;
470 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
472 SetPortWindowPort (w
);
475 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
477 #if TARGET_API_MAC_CARBON
478 LockPortBits (GetWindowPort (w
));
479 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
480 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
481 UnlockPortBits (GetWindowPort (w
));
482 #else /* not TARGET_API_MAC_CARBON */
483 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
484 overlay_p
? srcOr
: srcCopy
, 0);
485 #endif /* not TARGET_API_MAC_CARBON */
489 /* Mac replacement for XSetClipRectangles. */
492 mac_set_clip_rectangle (display
, w
, r
)
497 SetPortWindowPort (w
);
503 /* Mac replacement for XSetClipMask. */
506 mac_reset_clipping (display
, w
)
512 SetPortWindowPort (w
);
514 SetRect (&r
, -32767, -32767, 32767, 32767);
519 /* Mac replacement for XCreateBitmapFromBitmapData. */
522 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
527 static unsigned char swap_nibble
[16]
528 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
529 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
530 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
531 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
535 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
536 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
537 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
538 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
539 for (i
= 0; i
< h
; i
++)
541 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
542 for (j
= 0; j
< w1
; j
++)
544 /* Bitswap XBM bytes to match how Mac does things. */
545 unsigned char c
= *bits
++;
546 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
547 | (swap_nibble
[(c
>>4) & 0xf]));;
551 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
556 mac_free_bitmap (bitmap
)
559 xfree (bitmap
->baseAddr
);
564 XCreatePixmap (display
, w
, width
, height
, depth
)
565 Display
*display
; /* not used */
567 unsigned int width
, height
;
574 SetPortWindowPort (w
);
576 SetRect (&r
, 0, 0, width
, height
);
577 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
585 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
586 Display
*display
; /* not used */
589 unsigned int width
, height
;
590 unsigned long fg
, bg
;
591 unsigned int depth
; /* not used */
598 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
602 GetGWorld (&old_port
, &old_gdh
);
603 SetGWorld (pixmap
, NULL
);
604 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
605 mac_set_forecolor (fg
);
606 mac_set_backcolor (bg
);
607 LockPixels (GetGWorldPixMap (pixmap
));
608 #if TARGET_API_MAC_CARBON
609 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
610 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
611 #else /* not TARGET_API_MAC_CARBON */
612 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
613 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
614 #endif /* not TARGET_API_MAC_CARBON */
615 UnlockPixels (GetGWorldPixMap (pixmap
));
616 SetGWorld (old_port
, old_gdh
);
617 mac_free_bitmap (&bitmap
);
623 /* Mac replacement for XFillRectangle. */
626 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
631 unsigned int width
, height
;
635 SetPortWindowPort (w
);
638 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
640 PaintRect (&r
); /* using foreground color of gc */
644 #if 0 /* TODO: figure out if we need to do this on Mac. */
646 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
651 unsigned int width
, height
;
657 GetGWorld (&old_port
, &old_gdh
);
660 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
662 LockPixels (GetGWorldPixMap (p
));
663 PaintRect (&r
); /* using foreground color of gc */
664 UnlockPixels (GetGWorldPixMap (p
));
666 SetGWorld (old_port
, old_gdh
);
671 /* Mac replacement for XDrawRectangle: dest is a window. */
674 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
679 unsigned int width
, height
;
683 SetPortWindowPort (w
);
686 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
688 FrameRect (&r
); /* using foreground color of gc */
692 #if 0 /* TODO: figure out if we need to do this on Mac. */
693 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
696 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
701 unsigned int width
, height
;
707 GetGWorld (&old_port
, &old_gdh
);
710 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
712 LockPixels (GetGWorldPixMap (p
));
713 FrameRect (&r
); /* using foreground color of gc */
714 UnlockPixels (GetGWorldPixMap (p
));
716 SetGWorld (old_port
, old_gdh
);
722 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
729 int nchars
, mode
, bytes_per_char
;
731 SetPortWindowPort (w
);
732 #ifdef MAC_OS_X_VERSION_10_2
733 UInt32 textFlags
, savedFlags
;
734 if (!NILP(Vmac_use_core_graphics
)) {
735 textFlags
= kQDUseCGTextRendering
;
736 savedFlags
= SwapQDTextFlags(textFlags
);
742 TextFont (gc
->font
->mac_fontnum
);
743 TextSize (gc
->font
->mac_fontsize
);
744 TextFace (gc
->font
->mac_fontface
);
748 DrawText (buf
, 0, nchars
* bytes_per_char
);
749 #ifdef MAC_OS_X_VERSION_10_2
750 if (!NILP(Vmac_use_core_graphics
))
751 SwapQDTextFlags(savedFlags
);
756 /* Mac replacement for XDrawString. */
759 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
767 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
771 /* Mac replacement for XDrawString16. */
774 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
782 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
787 /* Mac replacement for XDrawImageString. */
790 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
798 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
802 /* Mac replacement for XDrawString16. */
805 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
813 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
818 /* Mac replacement for XCopyArea: dest must be window. */
821 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
828 unsigned int width
, height
;
833 SetPortWindowPort (dest
);
835 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
836 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
838 ForeColor (blackColor
);
839 BackColor (whiteColor
);
841 LockPixels (GetGWorldPixMap (src
));
842 #if TARGET_API_MAC_CARBON
843 LockPortBits (GetWindowPort (dest
));
844 CopyBits (GetPortBitMapForCopyBits (src
),
845 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
846 &src_r
, &dest_r
, srcCopy
, 0);
847 UnlockPortBits (GetWindowPort (dest
));
848 #else /* not TARGET_API_MAC_CARBON */
849 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
850 &src_r
, &dest_r
, srcCopy
, 0);
851 #endif /* not TARGET_API_MAC_CARBON */
852 UnlockPixels (GetGWorldPixMap (src
));
857 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
858 width
, height
, dest_x
, dest_y
)
864 unsigned int width
, height
;
869 SetPortWindowPort (dest
);
871 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
872 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
874 ForeColor (blackColor
);
875 BackColor (whiteColor
);
877 LockPixels (GetGWorldPixMap (src
));
878 LockPixels (GetGWorldPixMap (mask
));
879 #if TARGET_API_MAC_CARBON
880 LockPortBits (GetWindowPort (dest
));
881 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
882 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
883 &src_r
, &src_r
, &dest_r
);
884 UnlockPortBits (GetWindowPort (dest
));
885 #else /* not TARGET_API_MAC_CARBON */
886 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
887 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
888 #endif /* not TARGET_API_MAC_CARBON */
889 UnlockPixels (GetGWorldPixMap (mask
));
890 UnlockPixels (GetGWorldPixMap (src
));
895 /* Convert a pair of local coordinates to global (screen) coordinates.
896 Assume graphic port has been properly set. */
898 local_to_global_coord (short *h
, short *v
)
912 /* Mac replacement for XCopyArea: used only for scrolling. */
915 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
920 unsigned int width
, height
;
923 #if TARGET_API_MAC_CARBON
925 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
927 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
928 ScrollWindowRect (w
, &src_r
, dest_x
- src_x
, dest_y
- src_y
,
929 kScrollWindowNoOptions
, dummy
);
931 #else /* not TARGET_API_MAC_CARBON */
939 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
940 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
943 /* Need to use global coordinates and screenBits since src and dest
944 areas overlap in general. */
945 local_to_global_coord (&src_r
.left
, &src_r
.top
);
946 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
947 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
948 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
950 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
952 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
953 color mapping in CopyBits. Otherwise, it will be slow. */
954 ForeColor (blackColor
);
955 BackColor (whiteColor
);
956 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
960 #endif /* not TARGET_API_MAC_CARBON */
964 #if 0 /* TODO: figure out if we need to do this on Mac. */
965 /* Mac replacement for XCopyArea: dest must be Pixmap. */
968 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
974 unsigned int width
, height
;
981 GetGWorld (&old_port
, &old_gdh
);
982 SetGWorld (dest
, NULL
);
983 ForeColor (blackColor
);
984 BackColor (whiteColor
);
986 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
987 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
989 LockPixels (GetGWorldPixMap (src
));
990 LockPixels (GetGWorldPixMap (dest
));
991 #if TARGET_API_MAC_CARBON
992 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
993 &src_r
, &dest_r
, srcCopy
, 0);
994 #else /* not TARGET_API_MAC_CARBON */
995 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
996 &src_r
, &dest_r
, srcCopy
, 0);
997 #endif /* not TARGET_API_MAC_CARBON */
998 UnlockPixels (GetGWorldPixMap (dest
));
999 UnlockPixels (GetGWorldPixMap (src
));
1001 SetGWorld (old_port
, old_gdh
);
1006 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
1007 width
, height
, dest_x
, dest_y
)
1009 Pixmap src
, mask
, dest
;
1012 unsigned int width
, height
;
1019 GetGWorld (&old_port
, &old_gdh
);
1020 SetGWorld (dest
, NULL
);
1021 ForeColor (blackColor
);
1022 BackColor (whiteColor
);
1024 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1025 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1027 LockPixels (GetGWorldPixMap (src
));
1028 LockPixels (GetGWorldPixMap (mask
));
1029 LockPixels (GetGWorldPixMap (dest
));
1030 #if TARGET_API_MAC_CARBON
1031 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1032 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
1033 #else /* not TARGET_API_MAC_CARBON */
1034 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1035 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
1036 #endif /* not TARGET_API_MAC_CARBON */
1037 UnlockPixels (GetGWorldPixMap (dest
));
1038 UnlockPixels (GetGWorldPixMap (mask
));
1039 UnlockPixels (GetGWorldPixMap (src
));
1041 SetGWorld (old_port
, old_gdh
);
1046 /* Mac replacement for XChangeGC. */
1049 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1052 if (mask
& GCForeground
)
1053 gc
->foreground
= xgcv
->foreground
;
1054 if (mask
& GCBackground
)
1055 gc
->background
= xgcv
->background
;
1057 gc
->font
= xgcv
->font
;
1061 /* Mac replacement for XCreateGC. */
1064 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1067 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1068 bzero (gc
, sizeof (XGCValues
));
1070 XChangeGC (ignore
, gc
, mask
, xgcv
);
1076 /* Used in xfaces.c. */
1079 XFreeGC (display
, gc
)
1087 /* Mac replacement for XGetGCValues. */
1090 XGetGCValues (void* ignore
, XGCValues
*gc
,
1091 unsigned long mask
, XGCValues
*xgcv
)
1093 XChangeGC (ignore
, xgcv
, mask
, gc
);
1097 /* Mac replacement for XSetForeground. */
1100 XSetForeground (display
, gc
, color
)
1103 unsigned long color
;
1105 gc
->foreground
= color
;
1109 /* Mac replacement for XSetBackground. */
1112 XSetBackground (display
, gc
, color
)
1115 unsigned long color
;
1117 gc
->background
= color
;
1121 /* Mac replacement for XSetWindowBackground. */
1124 XSetWindowBackground (display
, w
, color
)
1127 unsigned long color
;
1129 #if !TARGET_API_MAC_CARBON
1130 AuxWinHandle aw_handle
;
1131 CTabHandle ctab_handle
;
1132 ColorSpecPtr ct_table
;
1137 bg_color
.red
= RED16_FROM_ULONG (color
);
1138 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1139 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1141 #if TARGET_API_MAC_CARBON
1142 SetWindowContentColor (w
, &bg_color
);
1144 if (GetAuxWin (w
, &aw_handle
))
1146 ctab_handle
= (*aw_handle
)->awCTable
;
1147 HandToHand ((Handle
*) &ctab_handle
);
1148 ct_table
= (*ctab_handle
)->ctTable
;
1149 ct_size
= (*ctab_handle
)->ctSize
;
1150 while (ct_size
> -1)
1152 if (ct_table
->value
== 0)
1154 ct_table
->rgb
= bg_color
;
1155 CTabChanged (ctab_handle
);
1156 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1165 /* Mac replacement for XSetFont. */
1168 XSetFont (display
, gc
, font
)
1178 XTextExtents16 (XFontStruct
*font
, XChar2b
*text
, int nchars
,
1179 int *direction
,int *font_ascent
,
1180 int *font_descent
, XCharStruct
*cs
)
1182 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1186 /* x_sync is a no-op on Mac. */
1194 /* Flush display of frame F, or of all frames if F is null. */
1200 #if TARGET_API_MAC_CARBON
1203 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1205 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1211 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1212 Calls to XFlush should be unnecessary because the X output buffer
1213 is flushed automatically as needed by calls to XPending,
1214 XNextEvent, or XWindowEvent according to the XFlush man page.
1215 XTread_socket calls XPending. Removing XFlush improves
1218 #define XFlush(DISPLAY) (void) 0
1221 /* Return the struct mac_display_info corresponding to DPY. There's
1224 struct mac_display_info
*
1225 mac_display_info_for_display (dpy
)
1228 return &one_mac_display_info
;
1233 /***********************************************************************
1234 Starting and ending an update
1235 ***********************************************************************/
1237 /* Start an update of frame F. This function is installed as a hook
1238 for update_begin, i.e. it is called when update_begin is called.
1239 This function is called prior to calls to x_update_window_begin for
1240 each window being updated. */
1246 #if TARGET_API_MAC_CARBON
1247 /* During update of a frame, availability of input events is
1248 periodically checked with ReceiveNextEvent if
1249 redisplay-dont-pause is nil. That normally flushes window buffer
1250 changes for every check, and thus screen update looks waving even
1251 if no input is available. So we disable screen updates during
1252 update of a frame. */
1254 DisableScreenUpdates ();
1260 /* Start update of window W. Set the global variable updated_window
1261 to the window being updated and set output_cursor to the cursor
1265 x_update_window_begin (w
)
1268 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1269 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1272 set_output_cursor (&w
->cursor
);
1276 if (f
== display_info
->mouse_face_mouse_frame
)
1278 /* Don't do highlighting for mouse motion during the update. */
1279 display_info
->mouse_face_defer
= 1;
1281 /* If F needs to be redrawn, simply forget about any prior mouse
1283 if (FRAME_GARBAGED_P (f
))
1284 display_info
->mouse_face_window
= Qnil
;
1286 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1287 their mouse_face_p flag set, which means that they are always
1288 unequal to rows in a desired matrix which never have that
1289 flag set. So, rows containing mouse-face glyphs are never
1290 scrolled, and we don't have to switch the mouse highlight off
1291 here to prevent it from being scrolled. */
1293 /* Can we tell that this update does not affect the window
1294 where the mouse highlight is? If so, no need to turn off.
1295 Likewise, don't do anything if the frame is garbaged;
1296 in that case, the frame's current matrix that we would use
1297 is all wrong, and we will redisplay that line anyway. */
1298 if (!NILP (display_info
->mouse_face_window
)
1299 && w
== XWINDOW (display_info
->mouse_face_window
))
1303 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1304 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1307 if (i
< w
->desired_matrix
->nrows
)
1308 clear_mouse_face (display_info
);
1317 /* Draw a vertical window border from (x,y0) to (x,y1) */
1320 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1324 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1326 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1327 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1331 /* End update of window W (which is equal to updated_window).
1333 Draw vertical borders between horizontally adjacent windows, and
1334 display W's cursor if CURSOR_ON_P is non-zero.
1336 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1337 glyphs in mouse-face were overwritten. In that case we have to
1338 make sure that the mouse-highlight is properly redrawn.
1340 W may be a menu bar pseudo-window in case we don't have X toolkit
1341 support. Such windows don't have a cursor, so don't display it
1345 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1347 int cursor_on_p
, mouse_face_overwritten_p
;
1349 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1351 if (!w
->pseudo_window_p
)
1356 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1358 output_cursor
.x
, output_cursor
.y
);
1360 if (draw_window_fringes (w
, 1))
1361 x_draw_vertical_border (w
);
1366 /* If a row with mouse-face was overwritten, arrange for
1367 XTframe_up_to_date to redisplay the mouse highlight. */
1368 if (mouse_face_overwritten_p
)
1370 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1371 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1372 dpyinfo
->mouse_face_window
= Qnil
;
1376 /* Unhide the caret. This won't actually show the cursor, unless it
1377 was visible before the corresponding call to HideCaret in
1378 x_update_window_begin. */
1379 if (w32_use_visible_system_caret
)
1380 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1383 updated_window
= NULL
;
1387 /* End update of frame F. This function is installed as a hook in
1394 /* Mouse highlight may be displayed again. */
1395 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1398 /* Reset the background color of Mac OS Window to that of the frame after
1399 update so that it is used by Mac Toolbox to clear the update region before
1400 an update event is generated. */
1401 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1403 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
1405 #if TARGET_API_MAC_CARBON
1406 EnableScreenUpdates ();
1408 XFlush (FRAME_MAC_DISPLAY (f
));
1413 /* This function is called from various places in xdisp.c whenever a
1414 complete update has been performed. The global variable
1415 updated_window is not available here. */
1418 XTframe_up_to_date (f
)
1421 if (FRAME_MAC_P (f
))
1423 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1425 if (dpyinfo
->mouse_face_deferred_gc
1426 || f
== dpyinfo
->mouse_face_mouse_frame
)
1429 if (dpyinfo
->mouse_face_mouse_frame
)
1430 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1431 dpyinfo
->mouse_face_mouse_x
,
1432 dpyinfo
->mouse_face_mouse_y
);
1433 dpyinfo
->mouse_face_deferred_gc
= 0;
1440 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1441 arrow bitmaps, or clear the fringes if no bitmaps are required
1442 before DESIRED_ROW is made current. The window being updated is
1443 found in updated_window. This function is called from
1444 update_window_line only if it is known that there are differences
1445 between bitmaps to be drawn between current row and DESIRED_ROW. */
1448 x_after_update_window_line (desired_row
)
1449 struct glyph_row
*desired_row
;
1451 struct window
*w
= updated_window
;
1457 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1458 desired_row
->redraw_fringe_bitmaps_p
= 1;
1460 /* When a window has disappeared, make sure that no rest of
1461 full-width rows stays visible in the internal border. Could
1462 check here if updated_window is the leftmost/rightmost window,
1463 but I guess it's not worth doing since vertically split windows
1464 are almost never used, internal border is rarely set, and the
1465 overhead is very small. */
1466 if (windows_or_buffers_changed
1467 && desired_row
->full_width_p
1468 && (f
= XFRAME (w
->frame
),
1469 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1471 && (height
= desired_row
->visible_height
,
1474 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1475 /* Internal border is drawn below the tool bar. */
1476 if (WINDOWP (f
->tool_bar_window
)
1477 && w
== XWINDOW (f
->tool_bar_window
))
1482 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1483 0, y
, width
, height
, 0);
1484 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1485 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1493 /* Draw the bitmap WHICH in one of the left or right fringes of
1494 window W. ROW is the glyph row for which to display the bitmap; it
1495 determines the vertical position at which the bitmap has to be
1499 x_draw_fringe_bitmap (w
, row
, p
)
1501 struct glyph_row
*row
;
1502 struct draw_fringe_bitmap_params
*p
;
1504 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1505 Display
*display
= FRAME_MAC_DISPLAY (f
);
1506 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1508 GC gc
= f
->output_data
.mac
->normal_gc
;
1509 struct face
*face
= p
->face
;
1512 /* Must clip because of partially visible lines. */
1513 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1516 /* Adjust position of "bottom aligned" bitmap on partially
1517 visible last row. */
1519 int oldVH
= row
->visible_height
;
1520 row
->visible_height
= p
->h
;
1521 row
->y
-= rowY
- p
->y
;
1522 x_clip_to_row (w
, row
, -1, gc
);
1524 row
->visible_height
= oldVH
;
1527 x_clip_to_row (w
, row
, -1, gc
);
1529 if (p
->bx
>= 0 && !p
->overlay_p
)
1532 gcv
.foreground
= face
->background
;
1534 #if 0 /* MAC_TODO: stipple */
1535 /* In case the same realized face is used for fringes and
1536 for something displayed in the text (e.g. face `region' on
1537 mono-displays, the fill style may have been changed to
1538 FillSolid in x_draw_glyph_string_background. */
1540 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1542 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1545 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1547 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1549 #if 0 /* MAC_TODO: stipple */
1551 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1557 unsigned short *bits
= p
->bits
+ p
->dh
;
1559 gcv
.foreground
= (p
->cursor_p
1560 ? (p
->overlay_p
? face
->background
1561 : f
->output_data
.mac
->cursor_pixel
)
1562 : face
->foreground
);
1563 gcv
.background
= face
->background
;
1565 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
,
1566 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1569 mac_reset_clipping (display
, window
);
1573 /* This is called when starting Emacs and when restarting after
1574 suspend. When starting Emacs, no window is mapped. And nothing
1575 must be done to Emacs's own window if it is suspended (though that
1579 XTset_terminal_modes ()
1583 /* This is called when exiting or suspending Emacs. Exiting will make
1584 the windows go away, and suspending requires no action. */
1587 XTreset_terminal_modes ()
1592 /***********************************************************************
1594 ***********************************************************************/
1596 /* Function prototypes of this page. */
1598 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1599 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1602 /* Return a pointer to per-char metric information in FONT of a
1603 character pointed by B which is a pointer to an XChar2b. */
1605 #define PER_CHAR_METRIC(font, b) \
1607 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1608 + (((font)->min_byte1 || (font)->max_byte1) \
1609 ? (((b)->byte1 - (font)->min_byte1) \
1610 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1612 : &((font)->max_bounds))
1615 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1616 is not contained in the font. */
1618 static INLINE XCharStruct
*
1619 x_per_char_metric (font
, char2b
)
1623 /* The result metric information. */
1624 XCharStruct
*pcm
= NULL
;
1626 xassert (font
&& char2b
);
1628 if (font
->per_char
!= NULL
)
1630 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1632 /* min_char_or_byte2 specifies the linear character index
1633 corresponding to the first element of the per_char array,
1634 max_char_or_byte2 is the index of the last character. A
1635 character with non-zero CHAR2B->byte1 is not in the font.
1636 A character with byte2 less than min_char_or_byte2 or
1637 greater max_char_or_byte2 is not in the font. */
1638 if (char2b
->byte1
== 0
1639 && char2b
->byte2
>= font
->min_char_or_byte2
1640 && char2b
->byte2
<= font
->max_char_or_byte2
)
1641 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1645 /* If either min_byte1 or max_byte1 are nonzero, both
1646 min_char_or_byte2 and max_char_or_byte2 are less than
1647 256, and the 2-byte character index values corresponding
1648 to the per_char array element N (counting from 0) are:
1650 byte1 = N/D + min_byte1
1651 byte2 = N\D + min_char_or_byte2
1655 D = max_char_or_byte2 - min_char_or_byte2 + 1
1656 / = integer division
1657 \ = integer modulus */
1658 if (char2b
->byte1
>= font
->min_byte1
1659 && char2b
->byte1
<= font
->max_byte1
1660 && char2b
->byte2
>= font
->min_char_or_byte2
1661 && char2b
->byte2
<= font
->max_char_or_byte2
)
1663 pcm
= (font
->per_char
1664 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1665 * (char2b
->byte1
- font
->min_byte1
))
1666 + (char2b
->byte2
- font
->min_char_or_byte2
));
1672 /* If the per_char pointer is null, all glyphs between the first
1673 and last character indexes inclusive have the same
1674 information, as given by both min_bounds and max_bounds. */
1675 if (char2b
->byte2
>= font
->min_char_or_byte2
1676 && char2b
->byte2
<= font
->max_char_or_byte2
)
1677 pcm
= &font
->max_bounds
;
1680 return ((pcm
== NULL
1681 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1688 static XCharStruct
*
1689 mac_per_char_metric (font
, char2b
, font_type
)
1694 return x_per_char_metric (font
, char2b
);
1698 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1699 the two-byte form of C. Encoding is returned in *CHAR2B. */
1702 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1705 struct font_info
*font_info
;
1708 int charset
= CHAR_CHARSET (c
);
1709 XFontStruct
*font
= font_info
->font
;
1711 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1712 This may be either a program in a special encoder language or a
1714 if (font_info
->font_encoder
)
1716 /* It's a program. */
1717 struct ccl_program
*ccl
= font_info
->font_encoder
;
1719 if (CHARSET_DIMENSION (charset
) == 1)
1721 ccl
->reg
[0] = charset
;
1722 ccl
->reg
[1] = char2b
->byte2
;
1726 ccl
->reg
[0] = charset
;
1727 ccl
->reg
[1] = char2b
->byte1
;
1728 ccl
->reg
[2] = char2b
->byte2
;
1731 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1733 /* We assume that MSBs are appropriately set/reset by CCL
1735 if (font
->max_byte1
== 0) /* 1-byte font */
1736 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1738 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1740 else if (font_info
->encoding
[charset
])
1742 /* Fixed encoding scheme. See fontset.h for the meaning of the
1743 encoding numbers. */
1744 int enc
= font_info
->encoding
[charset
];
1746 if ((enc
== 1 || enc
== 2)
1747 && CHARSET_DIMENSION (charset
) == 2)
1748 char2b
->byte1
|= 0x80;
1750 if (enc
== 1 || enc
== 3)
1751 char2b
->byte2
|= 0x80;
1757 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1758 char2b
->byte1
= sjis1
;
1759 char2b
->byte2
= sjis2
;
1764 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1766 return FONT_TYPE_UNKNOWN
;
1771 /***********************************************************************
1773 ***********************************************************************/
1776 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1777 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1778 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1780 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1781 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1782 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1783 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1784 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1785 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1786 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1787 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1788 unsigned long *, double, int));*/
1789 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1790 double, int, unsigned long));
1791 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1792 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1793 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1794 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1795 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1796 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1798 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1799 int, int, int, int, int, int,
1801 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1802 int, int, int, Rect
*));
1805 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1809 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1814 struct glyph_string
*s
;
1816 if (s
->font
== FRAME_FONT (s
->f
)
1817 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1818 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1820 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1823 /* Cursor on non-default face: must merge. */
1827 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1828 xgcv
.foreground
= s
->face
->background
;
1830 /* If the glyph would be invisible, try a different foreground. */
1831 if (xgcv
.foreground
== xgcv
.background
)
1832 xgcv
.foreground
= s
->face
->foreground
;
1833 if (xgcv
.foreground
== xgcv
.background
)
1834 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1835 if (xgcv
.foreground
== xgcv
.background
)
1836 xgcv
.foreground
= s
->face
->foreground
;
1838 /* Make sure the cursor is distinct from text in this face. */
1839 if (xgcv
.background
== s
->face
->background
1840 && xgcv
.foreground
== s
->face
->foreground
)
1842 xgcv
.background
= s
->face
->foreground
;
1843 xgcv
.foreground
= s
->face
->background
;
1846 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1847 xgcv
.font
= s
->font
;
1848 mask
= GCForeground
| GCBackground
| GCFont
;
1850 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1851 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1854 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1855 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1857 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1862 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1865 x_set_mouse_face_gc (s
)
1866 struct glyph_string
*s
;
1871 /* What face has to be used last for the mouse face? */
1872 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1873 face
= FACE_FROM_ID (s
->f
, face_id
);
1875 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1877 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1878 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1880 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1881 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1882 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1884 /* If font in this face is same as S->font, use it. */
1885 if (s
->font
== s
->face
->font
)
1886 s
->gc
= s
->face
->gc
;
1889 /* Otherwise construct scratch_cursor_gc with values from FACE
1894 xgcv
.background
= s
->face
->background
;
1895 xgcv
.foreground
= s
->face
->foreground
;
1896 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1897 xgcv
.font
= s
->font
;
1898 mask
= GCForeground
| GCBackground
| GCFont
;
1900 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1901 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1904 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1905 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1907 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1910 xassert (s
->gc
!= 0);
1914 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1915 Faces to use in the mode line have already been computed when the
1916 matrix was built, so there isn't much to do, here. */
1919 x_set_mode_line_face_gc (s
)
1920 struct glyph_string
*s
;
1922 s
->gc
= s
->face
->gc
;
1926 /* Set S->gc of glyph string S for drawing that glyph string. Set
1927 S->stippled_p to a non-zero value if the face of S has a stipple
1931 x_set_glyph_string_gc (s
)
1932 struct glyph_string
*s
;
1934 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1936 if (s
->hl
== DRAW_NORMAL_TEXT
)
1938 s
->gc
= s
->face
->gc
;
1939 s
->stippled_p
= s
->face
->stipple
!= 0;
1941 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1943 x_set_mode_line_face_gc (s
);
1944 s
->stippled_p
= s
->face
->stipple
!= 0;
1946 else if (s
->hl
== DRAW_CURSOR
)
1948 x_set_cursor_gc (s
);
1951 else if (s
->hl
== DRAW_MOUSE_FACE
)
1953 x_set_mouse_face_gc (s
);
1954 s
->stippled_p
= s
->face
->stipple
!= 0;
1956 else if (s
->hl
== DRAW_IMAGE_RAISED
1957 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1959 s
->gc
= s
->face
->gc
;
1960 s
->stippled_p
= s
->face
->stipple
!= 0;
1964 s
->gc
= s
->face
->gc
;
1965 s
->stippled_p
= s
->face
->stipple
!= 0;
1968 /* GC must have been set. */
1969 xassert (s
->gc
!= 0);
1973 /* Set clipping for output of glyph string S. S may be part of a mode
1974 line or menu if we don't have X toolkit support. */
1977 x_set_glyph_string_clipping (s
)
1978 struct glyph_string
*s
;
1981 get_glyph_string_clip_rect (s
, &r
);
1982 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
1987 Compute left and right overhang of glyph string S. If S is a glyph
1988 string for a composition, assume overhangs don't exist. */
1991 mac_compute_glyph_string_overhangs (s
)
1992 struct glyph_string
*s
;
1995 /* MAC_TODO: XTextExtents16 does nothing yet... */
1998 && s
->first_glyph
->type
== CHAR_GLYPH
)
2001 int direction
, font_ascent
, font_descent
;
2002 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2003 &font_ascent
, &font_descent
, &cs
);
2004 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2005 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2011 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2014 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2015 struct glyph_string
*s
;
2020 xgcv
.foreground
= s
->gc
->background
;
2021 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2025 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2026 on Mac OS X because:
2027 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2028 into an offscreen graphics world first. So performance gain
2029 cannot be expected.)
2030 - It lowers rendering quality.
2031 - Some fonts leave garbage on cursor movement. */
2033 /* Draw the background of glyph_string S. If S->background_filled_p
2034 is non-zero don't draw it. FORCE_P non-zero means draw the
2035 background even if it wouldn't be drawn normally. This is used
2036 when a string preceding S draws into the background of S, or S
2037 contains the first component of a composition. */
2040 x_draw_glyph_string_background (s
, force_p
)
2041 struct glyph_string
*s
;
2044 /* Nothing to do if background has already been drawn or if it
2045 shouldn't be drawn in the first place. */
2046 if (!s
->background_filled_p
)
2048 int box_line_width
= max (s
->face
->box_line_width
, 0);
2050 #if 0 /* MAC_TODO: stipple */
2053 /* Fill background with a stipple pattern. */
2054 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2055 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2056 s
->y
+ box_line_width
,
2057 s
->background_width
,
2058 s
->height
- 2 * box_line_width
);
2059 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2060 s
->background_filled_p
= 1;
2065 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2066 || s
->font_not_found_p
2067 || s
->extends_to_end_of_line_p
2071 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2072 s
->background_width
,
2073 s
->height
- 2 * box_line_width
);
2074 s
->background_filled_p
= 1;
2080 /* Draw the foreground of glyph string S. */
2083 x_draw_glyph_string_foreground (s
)
2084 struct glyph_string
*s
;
2088 /* If first glyph of S has a left box line, start drawing the text
2089 of S to the right of that box line. */
2090 if (s
->face
->box
!= FACE_NO_BOX
2091 && s
->first_glyph
->left_box_line_p
)
2092 x
= s
->x
+ abs (s
->face
->box_line_width
);
2096 /* Draw characters of S as rectangles if S's font could not be
2098 if (s
->font_not_found_p
)
2100 for (i
= 0; i
< s
->nchars
; ++i
)
2102 struct glyph
*g
= s
->first_glyph
+ i
;
2103 mac_draw_rectangle (s
->display
, s
->window
,
2104 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2106 x
+= g
->pixel_width
;
2111 char *char1b
= (char *) s
->char2b
;
2112 int boff
= s
->font_info
->baseline_offset
;
2114 if (s
->font_info
->vertical_centering
)
2115 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2117 /* If we can use 8-bit functions, condense S->char2b. */
2119 for (i
= 0; i
< s
->nchars
; ++i
)
2120 char1b
[i
] = s
->char2b
[i
].byte2
;
2123 /* Draw text with XDrawString if background has already been
2124 filled. Otherwise, use XDrawImageString. (Note that
2125 XDrawImageString is usually faster than XDrawString.) Always
2126 use XDrawImageString when drawing the cursor so that there is
2127 no chance that characters under a box cursor are invisible. */
2128 if (s
->for_overlaps_p
2129 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2132 /* Draw characters with 16-bit or 8-bit functions. */
2134 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2135 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2137 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2138 s
->ybase
- boff
, char1b
, s
->nchars
);
2144 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2145 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2147 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2148 s
->ybase
- boff
, char1b
, s
->nchars
);
2154 /* Draw the foreground of composite glyph string S. */
2157 x_draw_composite_glyph_string_foreground (s
)
2158 struct glyph_string
*s
;
2162 /* If first glyph of S has a left box line, start drawing the text
2163 of S to the right of that box line. */
2164 if (s
->face
->box
!= FACE_NO_BOX
2165 && s
->first_glyph
->left_box_line_p
)
2166 x
= s
->x
+ abs (s
->face
->box_line_width
);
2170 /* S is a glyph string for a composition. S->gidx is the index of
2171 the first character drawn for glyphs of this composition.
2172 S->gidx == 0 means we are drawing the very first character of
2173 this composition. */
2175 /* Draw a rectangle for the composition if the font for the very
2176 first character of the composition could not be loaded. */
2177 if (s
->font_not_found_p
)
2180 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2181 s
->width
- 1, s
->height
- 1);
2185 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2186 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2187 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2188 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2194 #ifdef USE_X_TOOLKIT
2196 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2199 /* Return the frame on which widget WIDGET is used.. Abort if frame
2200 cannot be determined. */
2202 static struct frame
*
2203 x_frame_of_widget (widget
)
2206 struct x_display_info
*dpyinfo
;
2210 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2212 /* Find the top-level shell of the widget. Note that this function
2213 can be called when the widget is not yet realized, so XtWindow
2214 (widget) == 0. That's the reason we can't simply use
2215 x_any_window_to_frame. */
2216 while (!XtIsTopLevelShell (widget
))
2217 widget
= XtParent (widget
);
2219 /* Look for a frame with that top-level widget. Allocate the color
2220 on that frame to get the right gamma correction value. */
2221 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2222 if (GC_FRAMEP (XCAR (tail
))
2223 && (f
= XFRAME (XCAR (tail
)),
2224 (f
->output_data
.nothing
!= 1
2225 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2226 && f
->output_data
.x
->widget
== widget
)
2233 /* Allocate the color COLOR->pixel on the screen and display of
2234 widget WIDGET in colormap CMAP. If an exact match cannot be
2235 allocated, try the nearest color available. Value is non-zero
2236 if successful. This is called from lwlib. */
2239 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2244 struct frame
*f
= x_frame_of_widget (widget
);
2245 return x_alloc_nearest_color (f
, cmap
, color
);
2249 #endif /* USE_X_TOOLKIT */
2251 #if 0 /* MAC_TODO */
2253 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2254 CMAP. If an exact match can't be allocated, try the nearest color
2255 available. Value is non-zero if successful. Set *COLOR to the
2259 x_alloc_nearest_color (f
, cmap
, color
)
2264 Display
*display
= FRAME_X_DISPLAY (f
);
2265 Screen
*screen
= FRAME_X_SCREEN (f
);
2268 gamma_correct (f
, color
);
2269 rc
= XAllocColor (display
, cmap
, color
);
2272 /* If we got to this point, the colormap is full, so we're going
2273 to try to get the next closest color. The algorithm used is
2274 a least-squares matching, which is what X uses for closest
2275 color matching with StaticColor visuals. */
2277 unsigned long nearest_delta
= ~0;
2278 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2279 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2281 for (i
= 0; i
< ncells
; ++i
)
2283 XQueryColors (display
, cmap
, cells
, ncells
);
2285 for (nearest
= i
= 0; i
< ncells
; ++i
)
2287 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2288 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2289 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2290 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2292 if (delta
< nearest_delta
)
2295 nearest_delta
= delta
;
2299 color
->red
= cells
[nearest
].red
;
2300 color
->green
= cells
[nearest
].green
;
2301 color
->blue
= cells
[nearest
].blue
;
2302 rc
= XAllocColor (display
, cmap
, color
);
2305 #ifdef DEBUG_X_COLORS
2307 register_color (color
->pixel
);
2308 #endif /* DEBUG_X_COLORS */
2314 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2315 It's necessary to do this instead of just using PIXEL directly to
2316 get color reference counts right. */
2319 x_copy_color (f
, pixel
)
2321 unsigned long pixel
;
2325 color
.pixel
= pixel
;
2327 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2328 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2330 #ifdef DEBUG_X_COLORS
2331 register_color (pixel
);
2337 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2338 It's necessary to do this instead of just using PIXEL directly to
2339 get color reference counts right. */
2342 x_copy_dpy_color (dpy
, cmap
, pixel
)
2345 unsigned long pixel
;
2349 color
.pixel
= pixel
;
2351 XQueryColor (dpy
, cmap
, &color
);
2352 XAllocColor (dpy
, cmap
, &color
);
2354 #ifdef DEBUG_X_COLORS
2355 register_color (pixel
);
2360 #endif /* MAC_TODO */
2363 /* Brightness beyond which a color won't have its highlight brightness
2366 Nominally, highlight colors for `3d' faces are calculated by
2367 brightening an object's color by a constant scale factor, but this
2368 doesn't yield good results for dark colors, so for colors who's
2369 brightness is less than this value (on a scale of 0-255) have to
2370 use an additional additive factor.
2372 The value here is set so that the default menu-bar/mode-line color
2373 (grey75) will not have its highlights changed at all. */
2374 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2377 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2378 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2379 If this produces the same color as COLOR, try a color where all RGB
2380 values have DELTA added. Return the allocated color in *COLOR.
2381 DISPLAY is the X display, CMAP is the colormap to operate on.
2382 Value is non-zero if successful. */
2385 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2387 unsigned long *color
;
2394 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2397 /* Change RGB values by specified FACTOR. Avoid overflow! */
2398 xassert (factor
>= 0);
2399 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2400 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2401 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2403 /* Calculate brightness of COLOR. */
2404 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2405 + BLUE_FROM_ULONG (*color
)) / 6;
2407 /* We only boost colors that are darker than
2408 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2409 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2410 /* Make an additive adjustment to NEW, because it's dark enough so
2411 that scaling by FACTOR alone isn't enough. */
2413 /* How far below the limit this color is (0 - 1, 1 being darker). */
2414 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2415 /* The additive adjustment. */
2416 int min_delta
= delta
* dimness
* factor
/ 2;
2419 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2420 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2421 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2423 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2424 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2425 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2429 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2430 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2431 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2433 /* MAC_TODO: Map to palette and retry with delta if same? */
2434 /* MAC_TODO: Free colors (if using palette)? */
2445 /* Set up the foreground color for drawing relief lines of glyph
2446 string S. RELIEF is a pointer to a struct relief containing the GC
2447 with which lines will be drawn. Use a color that is FACTOR or
2448 DELTA lighter or darker than the relief's background which is found
2449 in S->f->output_data.x->relief_background. If such a color cannot
2450 be allocated, use DEFAULT_PIXEL, instead. */
2453 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2455 struct relief
*relief
;
2458 unsigned long default_pixel
;
2461 struct mac_output
*di
= f
->output_data
.mac
;
2462 unsigned long mask
= GCForeground
;
2463 unsigned long pixel
;
2464 unsigned long background
= di
->relief_background
;
2465 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2467 /* MAC_TODO: Free colors (if using palette)? */
2469 /* Allocate new color. */
2470 xgcv
.foreground
= default_pixel
;
2472 if (dpyinfo
->n_planes
!= 1
2473 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2475 relief
->allocated_p
= 1;
2476 xgcv
.foreground
= relief
->pixel
= pixel
;
2479 if (relief
->gc
== 0)
2481 #if 0 /* MAC_TODO: stipple */
2482 xgcv
.stipple
= dpyinfo
->gray
;
2485 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2488 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2492 /* Set up colors for the relief lines around glyph string S. */
2495 x_setup_relief_colors (s
)
2496 struct glyph_string
*s
;
2498 struct mac_output
*di
= s
->f
->output_data
.mac
;
2499 unsigned long color
;
2501 if (s
->face
->use_box_color_for_shadows_p
)
2502 color
= s
->face
->box_color
;
2503 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2505 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2506 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2511 /* Get the background color of the face. */
2512 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2513 color
= xgcv
.background
;
2516 if (di
->white_relief
.gc
== 0
2517 || color
!= di
->relief_background
)
2519 di
->relief_background
= color
;
2520 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2521 WHITE_PIX_DEFAULT (s
->f
));
2522 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2523 BLACK_PIX_DEFAULT (s
->f
));
2528 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2529 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2530 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2531 relief. LEFT_P non-zero means draw a relief on the left side of
2532 the rectangle. RIGHT_P non-zero means draw a relief on the right
2533 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2537 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2538 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2540 int left_x
, top_y
, right_x
, bottom_y
, width
;
2541 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2544 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2545 Window window
= FRAME_MAC_WINDOW (f
);
2550 gc
= f
->output_data
.mac
->white_relief
.gc
;
2552 gc
= f
->output_data
.mac
->black_relief
.gc
;
2553 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2557 for (i
= 0; i
< width
; ++i
)
2558 XDrawLine (dpy
, window
, gc
,
2559 left_x
+ i
* left_p
, top_y
+ i
,
2560 right_x
- i
* right_p
, top_y
+ i
);
2564 for (i
= 0; i
< width
; ++i
)
2565 XDrawLine (dpy
, window
, gc
,
2566 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2568 mac_reset_clipping (dpy
, window
);
2570 gc
= f
->output_data
.mac
->black_relief
.gc
;
2572 gc
= f
->output_data
.mac
->white_relief
.gc
;
2573 mac_set_clip_rectangle (dpy
, window
,
2578 for (i
= 0; i
< width
; ++i
)
2579 XDrawLine (dpy
, window
, gc
,
2580 left_x
+ i
* left_p
, bottom_y
- i
,
2581 right_x
- i
* right_p
, bottom_y
- i
);
2585 for (i
= 0; i
< width
; ++i
)
2586 XDrawLine (dpy
, window
, gc
,
2587 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2589 mac_reset_clipping (dpy
, window
);
2593 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2594 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2595 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2596 left side of the rectangle. RIGHT_P non-zero means draw a line
2597 on the right side of the rectangle. CLIP_RECT is the clipping
2598 rectangle to use when drawing. */
2601 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2602 left_p
, right_p
, clip_rect
)
2603 struct glyph_string
*s
;
2604 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2609 xgcv
.foreground
= s
->face
->box_color
;
2610 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2613 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2614 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2618 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2619 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2622 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2623 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2627 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2628 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2630 mac_reset_clipping (s
->display
, s
->window
);
2634 /* Draw a box around glyph string S. */
2637 x_draw_glyph_string_box (s
)
2638 struct glyph_string
*s
;
2640 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2641 int left_p
, right_p
;
2642 struct glyph
*last_glyph
;
2645 last_x
= window_box_right (s
->w
, s
->area
);
2646 if (s
->row
->full_width_p
2647 && !s
->w
->pseudo_window_p
)
2649 last_x
+= WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s
->w
);
2650 if (s
->area
!= RIGHT_MARGIN_AREA
2651 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s
->w
))
2652 last_x
+= WINDOW_RIGHT_FRINGE_WIDTH (s
->w
);
2655 /* The glyph that may have a right box line. */
2656 last_glyph
= (s
->cmp
|| s
->img
2658 : s
->first_glyph
+ s
->nchars
- 1);
2660 width
= abs (s
->face
->box_line_width
);
2661 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2663 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2665 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2667 bottom_y
= top_y
+ s
->height
- 1;
2669 left_p
= (s
->first_glyph
->left_box_line_p
2670 || (s
->hl
== DRAW_MOUSE_FACE
2672 || s
->prev
->hl
!= s
->hl
)));
2673 right_p
= (last_glyph
->right_box_line_p
2674 || (s
->hl
== DRAW_MOUSE_FACE
2676 || s
->next
->hl
!= s
->hl
)));
2678 get_glyph_string_clip_rect (s
, &clip_rect
);
2680 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2681 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2682 left_p
, right_p
, &clip_rect
);
2685 x_setup_relief_colors (s
);
2686 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2687 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2692 /* Draw foreground of image glyph string S. */
2695 x_draw_image_foreground (s
)
2696 struct glyph_string
*s
;
2699 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2701 /* If first glyph of S has a left box line, start drawing it to the
2702 right of that line. */
2703 if (s
->face
->box
!= FACE_NO_BOX
2704 && s
->first_glyph
->left_box_line_p
2706 x
+= abs (s
->face
->box_line_width
);
2708 /* If there is a margin around the image, adjust x- and y-position
2710 if (s
->slice
.x
== 0)
2711 x
+= s
->img
->hmargin
;
2712 if (s
->slice
.y
== 0)
2713 y
+= s
->img
->vmargin
;
2717 x_set_glyph_string_clipping (s
);
2720 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2721 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2722 s
->slice
.width
, s
->slice
.height
, x
, y
);
2725 mac_copy_area (s
->display
, s
->img
->pixmap
,
2726 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2727 s
->slice
.width
, s
->slice
.height
, x
, y
);
2729 /* When the image has a mask, we can expect that at
2730 least part of a mouse highlight or a block cursor will
2731 be visible. If the image doesn't have a mask, make
2732 a block cursor visible by drawing a rectangle around
2733 the image. I believe it's looking better if we do
2734 nothing here for mouse-face. */
2735 if (s
->hl
== DRAW_CURSOR
)
2737 int r
= s
->img
->relief
;
2739 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2741 s
->slice
.width
+ r
*2 - 1,
2742 s
->slice
.height
+ r
*2 - 1);
2747 /* Draw a rectangle if image could not be loaded. */
2748 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2749 s
->slice
.width
- 1, s
->slice
.height
- 1);
2753 /* Draw a relief around the image glyph string S. */
2756 x_draw_image_relief (s
)
2757 struct glyph_string
*s
;
2759 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2762 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2764 /* If first glyph of S has a left box line, start drawing it to the
2765 right of that line. */
2766 if (s
->face
->box
!= FACE_NO_BOX
2767 && s
->first_glyph
->left_box_line_p
2769 x
+= abs (s
->face
->box_line_width
);
2771 /* If there is a margin around the image, adjust x- and y-position
2773 if (s
->slice
.x
== 0)
2774 x
+= s
->img
->hmargin
;
2775 if (s
->slice
.y
== 0)
2776 y
+= s
->img
->vmargin
;
2778 if (s
->hl
== DRAW_IMAGE_SUNKEN
2779 || s
->hl
== DRAW_IMAGE_RAISED
)
2781 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2782 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2786 thick
= abs (s
->img
->relief
);
2787 raised_p
= s
->img
->relief
> 0;
2792 x1
= x
+ s
->slice
.width
+ thick
- 1;
2793 y1
= y
+ s
->slice
.height
+ thick
- 1;
2795 x_setup_relief_colors (s
);
2796 get_glyph_string_clip_rect (s
, &r
);
2797 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2799 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2801 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2806 #if 0 /* TODO: figure out if we need to do this on Mac. */
2807 /* Draw the foreground of image glyph string S to PIXMAP. */
2810 x_draw_image_foreground_1 (s
, pixmap
)
2811 struct glyph_string
*s
;
2815 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2817 /* If first glyph of S has a left box line, start drawing it to the
2818 right of that line. */
2819 if (s
->face
->box
!= FACE_NO_BOX
2820 && s
->first_glyph
->left_box_line_p
2822 x
+= abs (s
->face
->box_line_width
);
2824 /* If there is a margin around the image, adjust x- and y-position
2826 if (s
->slice
.x
== 0)
2827 x
+= s
->img
->hmargin
;
2828 if (s
->slice
.y
== 0)
2829 y
+= s
->img
->vmargin
;
2834 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2835 s
->img
->mask
, pixmap
, s
->gc
,
2836 s
->slice
.x
, s
->slice
.y
,
2837 s
->slice
.width
, s
->slice
.height
,
2841 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2842 s
->slice
.x
, s
->slice
.y
,
2843 s
->slice
.width
, s
->slice
.height
,
2846 /* When the image has a mask, we can expect that at
2847 least part of a mouse highlight or a block cursor will
2848 be visible. If the image doesn't have a mask, make
2849 a block cursor visible by drawing a rectangle around
2850 the image. I believe it's looking better if we do
2851 nothing here for mouse-face. */
2852 if (s
->hl
== DRAW_CURSOR
)
2854 int r
= s
->img
->relief
;
2856 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2857 s
->slice
.width
+ r
*2 - 1,
2858 s
->slice
.height
+ r
*2 - 1);
2863 /* Draw a rectangle if image could not be loaded. */
2864 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2865 s
->slice
.width
- 1, s
->slice
.height
- 1);
2870 /* Draw part of the background of glyph string S. X, Y, W, and H
2871 give the rectangle to draw. */
2874 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2875 struct glyph_string
*s
;
2878 #if 0 /* MAC_TODO: stipple */
2881 /* Fill background with a stipple pattern. */
2882 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2883 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2884 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2887 #endif /* MAC_TODO */
2888 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2892 /* Draw image glyph string S.
2895 s->x +-------------------------
2898 | +-------------------------
2901 | | +-------------------
2907 x_draw_image_glyph_string (s
)
2908 struct glyph_string
*s
;
2911 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2912 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2916 height
= s
->height
- 2 * box_line_vwidth
;
2919 /* Fill background with face under the image. Do it only if row is
2920 taller than image or if image has a clip mask to reduce
2922 s
->stippled_p
= s
->face
->stipple
!= 0;
2923 if (height
> s
->slice
.height
2927 || s
->img
->pixmap
== 0
2928 || s
->width
!= s
->background_width
)
2931 if (s
->first_glyph
->left_box_line_p
2933 x
+= box_line_hwidth
;
2936 if (s
->slice
.y
== 0)
2937 y
+= box_line_vwidth
;
2939 #if 0 /* TODO: figure out if we need to do this on Mac. */
2942 /* Create a pixmap as large as the glyph string. Fill it
2943 with the background color. Copy the image to it, using
2944 its mask. Copy the temporary pixmap to the display. */
2945 int depth
= one_mac_display_info
.n_planes
;
2947 /* Create a pixmap as large as the glyph string. */
2948 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2949 s
->background_width
,
2952 /* Fill the pixmap with the background color/stipple. */
2953 #if 0 /* TODO: stipple */
2956 /* Fill background with a stipple pattern. */
2957 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2958 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2959 0, 0, s
->background_width
, s
->height
);
2960 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2966 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2968 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2969 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2970 0, 0, s
->background_width
,
2972 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2977 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2979 s
->background_filled_p
= 1;
2982 /* Draw the foreground. */
2983 #if 0 /* TODO: figure out if we need to do this on Mac. */
2986 x_draw_image_foreground_1 (s
, pixmap
);
2987 x_set_glyph_string_clipping (s
);
2988 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
2989 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2990 mac_reset_clipping (s
->display
, s
->window
);
2991 XFreePixmap (s
->display
, pixmap
);
2995 x_draw_image_foreground (s
);
2997 /* If we must draw a relief around the image, do it. */
2999 || s
->hl
== DRAW_IMAGE_RAISED
3000 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3001 x_draw_image_relief (s
);
3005 /* Draw stretch glyph string S. */
3008 x_draw_stretch_glyph_string (s
)
3009 struct glyph_string
*s
;
3011 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3012 s
->stippled_p
= s
->face
->stipple
!= 0;
3014 if (s
->hl
== DRAW_CURSOR
3015 && !x_stretch_cursor_p
)
3017 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3018 as wide as the stretch glyph. */
3019 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3022 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3024 /* Clear rest using the GC of the original non-cursor face. */
3025 if (width
< s
->background_width
)
3027 int x
= s
->x
+ width
, y
= s
->y
;
3028 int w
= s
->background_width
- width
, h
= s
->height
;
3032 if (s
->row
->mouse_face_p
3033 && cursor_in_mouse_face_p (s
->w
))
3035 x_set_mouse_face_gc (s
);
3041 get_glyph_string_clip_rect (s
, &r
);
3042 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3044 #if 0 /* MAC_TODO: stipple */
3045 if (s
->face
->stipple
)
3047 /* Fill background with a stipple pattern. */
3048 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3049 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3050 XSetFillStyle (s
->display
, gc
, FillSolid
);
3053 #endif /* MAC_TODO */
3056 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3057 XSetForeground (s
->display
, gc
, xgcv
.background
);
3058 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3059 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3062 mac_reset_clipping (s
->display
, s
->window
);
3065 else if (!s
->background_filled_p
)
3066 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3069 s
->background_filled_p
= 1;
3073 /* Draw glyph string S. */
3076 x_draw_glyph_string (s
)
3077 struct glyph_string
*s
;
3079 int relief_drawn_p
= 0;
3081 /* If S draws into the background of its successor, draw the
3082 background of the successor first so that S can draw into it.
3083 This makes S->next use XDrawString instead of XDrawImageString. */
3084 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
3086 xassert (s
->next
->img
== NULL
);
3087 x_set_glyph_string_gc (s
->next
);
3088 x_set_glyph_string_clipping (s
->next
);
3089 x_draw_glyph_string_background (s
->next
, 1);
3092 /* Set up S->gc, set clipping and draw S. */
3093 x_set_glyph_string_gc (s
);
3095 /* Draw relief (if any) in advance for char/composition so that the
3096 glyph string can be drawn over it. */
3097 if (!s
->for_overlaps_p
3098 && s
->face
->box
!= FACE_NO_BOX
3099 && (s
->first_glyph
->type
== CHAR_GLYPH
3100 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3103 x_set_glyph_string_clipping (s
);
3104 x_draw_glyph_string_background (s
, 1);
3105 x_draw_glyph_string_box (s
);
3106 x_set_glyph_string_clipping (s
);
3110 x_set_glyph_string_clipping (s
);
3112 switch (s
->first_glyph
->type
)
3115 x_draw_image_glyph_string (s
);
3119 x_draw_stretch_glyph_string (s
);
3123 if (s
->for_overlaps_p
)
3124 s
->background_filled_p
= 1;
3126 x_draw_glyph_string_background (s
, 0);
3127 x_draw_glyph_string_foreground (s
);
3130 case COMPOSITE_GLYPH
:
3131 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3132 s
->background_filled_p
= 1;
3134 x_draw_glyph_string_background (s
, 1);
3135 x_draw_composite_glyph_string_foreground (s
);
3142 if (!s
->for_overlaps_p
)
3144 /* Draw underline. */
3145 if (s
->face
->underline_p
)
3147 unsigned long h
= 1;
3148 unsigned long dy
= s
->height
- h
;
3150 if (s
->face
->underline_defaulted_p
)
3151 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3156 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3157 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3158 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3160 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3164 /* Draw overline. */
3165 if (s
->face
->overline_p
)
3167 unsigned long dy
= 0, h
= 1;
3169 if (s
->face
->overline_color_defaulted_p
)
3170 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3175 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3176 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3177 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3179 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3183 /* Draw strike-through. */
3184 if (s
->face
->strike_through_p
)
3186 unsigned long h
= 1;
3187 unsigned long dy
= (s
->height
- h
) / 2;
3189 if (s
->face
->strike_through_color_defaulted_p
)
3190 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3195 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3196 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3197 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3199 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3203 /* Draw relief if not yet drawn. */
3204 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3205 x_draw_glyph_string_box (s
);
3208 /* Reset clipping. */
3209 mac_reset_clipping (s
->display
, s
->window
);
3212 /* Shift display to make room for inserted glyphs. */
3215 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3217 int x
, y
, width
, height
, shift_by
;
3219 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3220 f
->output_data
.mac
->normal_gc
,
3221 x
, y
, width
, height
,
3225 /* Delete N glyphs at the nominal cursor position. Not implemented
3236 /* Clear entire frame. If updating_frame is non-null, clear that
3237 frame. Otherwise clear the selected frame. */
3247 f
= SELECTED_FRAME ();
3249 /* Clearing the frame will erase any cursor, so mark them all as no
3251 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3252 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3253 output_cursor
.x
= -1;
3255 /* We don't set the output cursor here because there will always
3256 follow an explicit cursor_to. */
3258 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3260 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3261 /* We have to clear the scroll bars, too. If we have changed
3262 colors or something like that, then they should be notified. */
3263 x_scroll_bar_clear (f
);
3266 XFlush (FRAME_MAC_DISPLAY (f
));
3272 /* Invert the middle quarter of the frame for .15 sec. */
3274 /* We use the select system call to do the waiting, so we have to make
3275 sure it's available. If it isn't, we just won't do visual bells. */
3277 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3280 /* Subtract the `struct timeval' values X and Y, storing the result in
3281 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3284 timeval_subtract (result
, x
, y
)
3285 struct timeval
*result
, x
, y
;
3287 /* Perform the carry for the later subtraction by updating y. This
3288 is safer because on some systems the tv_sec member is unsigned. */
3289 if (x
.tv_usec
< y
.tv_usec
)
3291 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3292 y
.tv_usec
-= 1000000 * nsec
;
3296 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3298 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3299 y
.tv_usec
+= 1000000 * nsec
;
3303 /* Compute the time remaining to wait. tv_usec is certainly
3305 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3306 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3308 /* Return indication of whether the result should be considered
3310 return x
.tv_sec
< y
.tv_sec
;
3322 struct timeval wakeup
;
3324 EMACS_GET_TIME (wakeup
);
3326 /* Compute time to wait until, propagating carry from usecs. */
3327 wakeup
.tv_usec
+= 150000;
3328 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3329 wakeup
.tv_usec
%= 1000000;
3331 /* Keep waiting until past the time wakeup. */
3334 struct timeval timeout
;
3336 EMACS_GET_TIME (timeout
);
3338 /* In effect, timeout = wakeup - timeout.
3339 Break if result would be negative. */
3340 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3343 /* Try to wait that long--but we might wake up sooner. */
3344 select (0, NULL
, NULL
, NULL
, &timeout
);
3353 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3356 /* Make audible bell. */
3361 struct frame
*f
= SELECTED_FRAME ();
3363 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3371 XFlush (FRAME_MAC_DISPLAY (f
));
3378 /* Specify how many text lines, from the top of the window,
3379 should be affected by insert-lines and delete-lines operations.
3380 This, and those operations, are used only within an update
3381 that is bounded by calls to x_update_begin and x_update_end. */
3384 XTset_terminal_window (n
)
3387 /* This function intentionally left blank. */
3392 /***********************************************************************
3394 ***********************************************************************/
3396 /* Perform an insert-lines or delete-lines operation, inserting N
3397 lines or deleting -N lines at vertical position VPOS. */
3400 x_ins_del_lines (vpos
, n
)
3407 /* Scroll part of the display as described by RUN. */
3410 x_scroll_run (w
, run
)
3414 struct frame
*f
= XFRAME (w
->frame
);
3415 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3417 /* Get frame-relative bounding box of the text display area of W,
3418 without mode lines. Include in this box the left and right
3420 window_box (w
, -1, &x
, &y
, &width
, &height
);
3422 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3423 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3424 bottom_y
= y
+ height
;
3428 /* Scrolling up. Make sure we don't copy part of the mode
3429 line at the bottom. */
3430 if (from_y
+ run
->height
> bottom_y
)
3431 height
= bottom_y
- from_y
;
3433 height
= run
->height
;
3437 /* Scolling down. Make sure we don't copy over the mode line.
3439 if (to_y
+ run
->height
> bottom_y
)
3440 height
= bottom_y
- to_y
;
3442 height
= run
->height
;
3447 /* Cursor off. Will be switched on again in x_update_window_end. */
3451 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3452 f
->output_data
.mac
->normal_gc
,
3462 /***********************************************************************
3464 ***********************************************************************/
3471 x_update_cursor (f
, 1);
3475 frame_unhighlight (f
)
3478 x_update_cursor (f
, 1);
3481 /* The focus has changed. Update the frames as necessary to reflect
3482 the new situation. Note that we can't change the selected frame
3483 here, because the Lisp code we are interrupting might become confused.
3484 Each event gets marked with the frame in which it occurred, so the
3485 Lisp code can tell when the switch took place by examining the events. */
3488 x_new_focus_frame (dpyinfo
, frame
)
3489 struct x_display_info
*dpyinfo
;
3490 struct frame
*frame
;
3492 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3494 if (frame
!= dpyinfo
->x_focus_frame
)
3496 /* Set this before calling other routines, so that they see
3497 the correct value of x_focus_frame. */
3498 dpyinfo
->x_focus_frame
= frame
;
3500 if (old_focus
&& old_focus
->auto_lower
)
3501 x_lower_frame (old_focus
);
3504 selected_frame
= frame
;
3505 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3507 Fselect_window (selected_frame
->selected_window
, Qnil
);
3508 choose_minibuf_frame ();
3511 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3512 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3514 pending_autoraise_frame
= 0;
3517 x_frame_rehighlight (dpyinfo
);
3520 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3523 x_mouse_leave (dpyinfo
)
3524 struct x_display_info
*dpyinfo
;
3526 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3529 /* The focus has changed, or we have redirected a frame's focus to
3530 another frame (this happens when a frame uses a surrogate
3531 mini-buffer frame). Shift the highlight as appropriate.
3533 The FRAME argument doesn't necessarily have anything to do with which
3534 frame is being highlighted or un-highlighted; we only use it to find
3535 the appropriate X display info. */
3538 XTframe_rehighlight (frame
)
3539 struct frame
*frame
;
3541 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3545 x_frame_rehighlight (dpyinfo
)
3546 struct x_display_info
*dpyinfo
;
3548 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3550 if (dpyinfo
->x_focus_frame
)
3552 dpyinfo
->x_highlight_frame
3553 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3554 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3555 : dpyinfo
->x_focus_frame
);
3556 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3558 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3559 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3563 dpyinfo
->x_highlight_frame
= 0;
3565 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3568 frame_unhighlight (old_highlight
);
3569 if (dpyinfo
->x_highlight_frame
)
3570 frame_highlight (dpyinfo
->x_highlight_frame
);
3576 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3578 #if 0 /* MAC_TODO */
3579 /* Initialize mode_switch_bit and modifier_meaning. */
3581 x_find_modifier_meanings (dpyinfo
)
3582 struct x_display_info
*dpyinfo
;
3584 int min_code
, max_code
;
3587 XModifierKeymap
*mods
;
3589 dpyinfo
->meta_mod_mask
= 0;
3590 dpyinfo
->shift_lock_mask
= 0;
3591 dpyinfo
->alt_mod_mask
= 0;
3592 dpyinfo
->super_mod_mask
= 0;
3593 dpyinfo
->hyper_mod_mask
= 0;
3596 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3598 min_code
= dpyinfo
->display
->min_keycode
;
3599 max_code
= dpyinfo
->display
->max_keycode
;
3602 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3603 min_code
, max_code
- min_code
+ 1,
3605 mods
= XGetModifierMapping (dpyinfo
->display
);
3607 /* Scan the modifier table to see which modifier bits the Meta and
3608 Alt keysyms are on. */
3610 int row
, col
; /* The row and column in the modifier table. */
3612 for (row
= 3; row
< 8; row
++)
3613 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3616 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3618 /* Zeroes are used for filler. Skip them. */
3622 /* Are any of this keycode's keysyms a meta key? */
3626 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3628 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3634 dpyinfo
->meta_mod_mask
|= (1 << row
);
3639 dpyinfo
->alt_mod_mask
|= (1 << row
);
3644 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3649 dpyinfo
->super_mod_mask
|= (1 << row
);
3653 /* Ignore this if it's not on the lock modifier. */
3654 if ((1 << row
) == LockMask
)
3655 dpyinfo
->shift_lock_mask
= LockMask
;
3663 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3664 if (! dpyinfo
->meta_mod_mask
)
3666 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3667 dpyinfo
->alt_mod_mask
= 0;
3670 /* If some keys are both alt and meta,
3671 make them just meta, not alt. */
3672 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3674 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3677 XFree ((char *) syms
);
3678 XFreeModifiermap (mods
);
3681 #endif /* MAC_TODO */
3683 /* Convert between the modifier bits X uses and the modifier bits
3687 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3688 struct x_display_info
*dpyinfo
;
3689 unsigned short state
;
3691 return (((state
& shiftKey
) ? shift_modifier
: 0)
3692 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3693 | ((state
& cmdKey
) ? meta_modifier
: 0)
3694 | ((state
& optionKey
) ? alt_modifier
: 0));
3697 #if 0 /* MAC_TODO */
3698 static unsigned short
3699 x_emacs_to_x_modifiers (dpyinfo
, state
)
3700 struct x_display_info
*dpyinfo
;
3703 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3704 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3705 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3706 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3707 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3708 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3710 #endif /* MAC_TODO */
3712 /* Convert a keysym to its name. */
3715 x_get_keysym_name (keysym
)
3722 value
= XKeysymToString (keysym
);
3734 /* Mouse clicks and mouse movement. Rah. */
3736 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3738 If the event is a button press, then note that we have grabbed
3742 construct_mouse_click (result
, event
, f
)
3743 struct input_event
*result
;
3749 result
->kind
= MOUSE_CLICK_EVENT
;
3750 result
->code
= 0; /* only one mouse button */
3751 result
->timestamp
= event
->when
;
3752 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3754 mouseLoc
= event
->where
;
3756 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3758 GlobalToLocal (&mouseLoc
);
3759 XSETINT (result
->x
, mouseLoc
.h
);
3760 XSETINT (result
->y
, mouseLoc
.v
);
3762 XSETFRAME (result
->frame_or_window
, f
);
3770 /* Function to report a mouse movement to the mainstream Emacs code.
3771 The input handler calls this.
3773 We have received a mouse movement event, which is given in *event.
3774 If the mouse is over a different glyph than it was last time, tell
3775 the mainstream emacs code by setting mouse_moved. If not, ask for
3776 another motion event, so we can check again the next time it moves. */
3778 static Point last_mouse_motion_position
;
3779 static Lisp_Object last_mouse_motion_frame
;
3782 note_mouse_movement (frame
, pos
)
3786 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3787 #if TARGET_API_MAC_CARBON
3791 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3792 last_mouse_motion_position
= *pos
;
3793 XSETFRAME (last_mouse_motion_frame
, frame
);
3795 #if TARGET_API_MAC_CARBON
3796 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3798 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3801 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3802 /* This case corresponds to LeaveNotify in X11. */
3804 /* If we move outside the frame, then we're certainly no
3805 longer on any text in the frame. */
3806 clear_mouse_face (dpyinfo
);
3807 dpyinfo
->mouse_face_mouse_frame
= 0;
3808 if (!dpyinfo
->grabbed
)
3809 rif
->define_frame_cursor (frame
,
3810 frame
->output_data
.mac
->nontext_cursor
);
3813 /* Has the mouse moved off the glyph it was on at the last sighting? */
3814 else if (pos
->h
< last_mouse_glyph
.left
3815 || pos
->h
>= last_mouse_glyph
.right
3816 || pos
->v
< last_mouse_glyph
.top
3817 || pos
->v
>= last_mouse_glyph
.bottom
)
3819 frame
->mouse_moved
= 1;
3820 last_mouse_scroll_bar
= Qnil
;
3821 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3825 /* This is used for debugging, to turn off note_mouse_highlight. */
3827 int disable_mouse_highlight
;
3831 /************************************************************************
3833 ************************************************************************/
3835 static struct scroll_bar
*x_window_to_scroll_bar ();
3836 static void x_scroll_bar_report_motion ();
3837 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3840 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3843 redo_mouse_highlight ()
3845 if (!NILP (last_mouse_motion_frame
)
3846 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3847 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3848 last_mouse_motion_position
.h
,
3849 last_mouse_motion_position
.v
);
3853 /* Try to determine frame pixel position and size of the glyph under
3854 frame pixel coordinates X/Y on frame F . Return the position and
3855 size in *RECT. Value is non-zero if we could compute these
3859 glyph_rect (f
, x
, y
, rect
)
3866 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3870 struct window
*w
= XWINDOW (window
);
3871 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3872 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3874 for (; r
< end
&& r
->enabled_p
; ++r
)
3875 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3877 /* Found the row at y. */
3878 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3879 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3882 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3883 rect
->bottom
= rect
->top
+ r
->height
;
3887 /* x is to the left of the first glyph in the row. */
3888 /* Shouldn't this be a pixel value?
3889 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3891 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3892 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3896 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3897 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3899 /* x is on a glyph. */
3900 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3901 rect
->right
= rect
->left
+ g
->pixel_width
;
3905 /* x is to the right of the last glyph in the row. */
3906 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3907 /* Shouldn't this be a pixel value?
3908 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3910 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3915 /* The y is not on any row. */
3919 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3921 /* Record the position of the mouse in last_mouse_glyph. */
3923 remember_mouse_glyph (f1
, gx
, gy
)
3927 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3929 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3930 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3932 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3933 round down even for negative values. */
3939 /* This was the original code from XTmouse_position, but it seems
3940 to give the position of the glyph diagonally next to the one
3941 the mouse is over. */
3942 gx
= (gx
+ width
- 1) / width
* width
;
3943 gy
= (gy
+ height
- 1) / height
* height
;
3945 gx
= gx
/ width
* width
;
3946 gy
= gy
/ height
* height
;
3949 last_mouse_glyph
.left
= gx
;
3950 last_mouse_glyph
.top
= gy
;
3951 last_mouse_glyph
.right
= gx
+ width
;
3952 last_mouse_glyph
.bottom
= gy
+ height
;
3958 front_emacs_window ()
3960 #if TARGET_API_MAC_CARBON
3961 WindowPtr wp
= GetFrontWindowOfClass (kDocumentWindowClass
, true);
3963 while (wp
&& !is_emacs_window (wp
))
3964 wp
= GetNextWindowOfClass (wp
, kDocumentWindowClass
, true);
3966 WindowPtr wp
= FrontWindow ();
3968 while (wp
&& (wp
== tip_window
|| !is_emacs_window (wp
)))
3969 wp
= GetNextWindow (wp
);
3975 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3977 /* Return the current position of the mouse.
3978 *fp should be a frame which indicates which display to ask about.
3980 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3981 and *part to the frame, window, and scroll bar part that the mouse
3982 is over. Set *x and *y to the portion and whole of the mouse's
3983 position on the scroll bar.
3985 If the mouse movement started elsewhere, set *fp to the frame the
3986 mouse is on, *bar_window to nil, and *x and *y to the character cell
3989 Set *time to the server time-stamp for the time at which the mouse
3990 was at this position.
3992 Don't store anything if we don't have a valid set of values to report.
3994 This clears the mouse_moved flag, so we can wait for the next mouse
3998 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4001 Lisp_Object
*bar_window
;
4002 enum scroll_bar_part
*part
;
4004 unsigned long *time
;
4007 int ignore1
, ignore2
;
4008 WindowPtr wp
= front_emacs_window ();
4010 Lisp_Object frame
, tail
;
4012 if (is_emacs_window(wp
))
4013 f
= mac_window_to_frame (wp
);
4017 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4018 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4021 /* Clear the mouse-moved flag for every frame on this display. */
4022 FOR_EACH_FRAME (tail
, frame
)
4023 XFRAME (frame
)->mouse_moved
= 0;
4025 last_mouse_scroll_bar
= Qnil
;
4027 SetPortWindowPort (wp
);
4029 GetMouse (&mouse_pos
);
4031 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4032 &last_mouse_glyph
, insist
);
4035 *part
= scroll_bar_handle
;
4037 XSETINT (*x
, mouse_pos
.h
);
4038 XSETINT (*y
, mouse_pos
.v
);
4039 *time
= last_mouse_movement_time
;
4046 /***********************************************************************
4048 ***********************************************************************/
4050 /* Handle mouse button event on the tool-bar of frame F, at
4051 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4055 mac_handle_tool_bar_click (f
, button_event
)
4057 EventRecord
*button_event
;
4059 int x
= button_event
->where
.h
;
4060 int y
= button_event
->where
.v
;
4062 if (button_event
->what
== mouseDown
)
4063 handle_tool_bar_click (f
, x
, y
, 1, 0);
4065 handle_tool_bar_click (f
, x
, y
, 0,
4066 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f
),
4067 button_event
->modifiers
));
4071 /************************************************************************
4072 Scroll bars, general
4073 ************************************************************************/
4075 /* Create a scroll bar and return the scroll bar vector for it. W is
4076 the Emacs window on which to create the scroll bar. TOP, LEFT,
4077 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4080 static struct scroll_bar
*
4081 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4083 int top
, left
, width
, height
, disp_top
, disp_height
;
4085 struct frame
*f
= XFRAME (w
->frame
);
4086 struct scroll_bar
*bar
4087 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4095 r
.right
= left
+ width
;
4096 r
.bottom
= disp_top
+ disp_height
;
4098 #if TARGET_API_MAC_CARBON
4099 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4100 kControlScrollBarProc
, 0L);
4102 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
4105 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4106 SetControlReference (ch
, (long) bar
);
4108 XSETWINDOW (bar
->window
, w
);
4109 XSETINT (bar
->top
, top
);
4110 XSETINT (bar
->left
, left
);
4111 XSETINT (bar
->width
, width
);
4112 XSETINT (bar
->height
, height
);
4113 XSETINT (bar
->start
, 0);
4114 XSETINT (bar
->end
, 0);
4115 bar
->dragging
= Qnil
;
4117 /* Add bar to its frame's list of scroll bars. */
4118 bar
->next
= FRAME_SCROLL_BARS (f
);
4120 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4121 if (!NILP (bar
->next
))
4122 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4129 /* Draw BAR's handle in the proper position.
4131 If the handle is already drawn from START to END, don't bother
4132 redrawing it, unless REBUILD is non-zero; in that case, always
4133 redraw it. (REBUILD is handy for drawing the handle after expose
4136 Normally, we want to constrain the start and end of the handle to
4137 fit inside its rectangle, but if the user is dragging the scroll
4138 bar handle, we want to let them drag it down all the way, so that
4139 the bar's top is as far down as it goes; otherwise, there's no way
4140 to move to the very end of the buffer. */
4143 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4144 struct scroll_bar
*bar
;
4148 int dragging
= ! NILP (bar
->dragging
);
4149 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4150 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4151 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4152 int length
= end
- start
;
4154 /* If the display is already accurate, do nothing. */
4156 && start
== XINT (bar
->start
)
4157 && end
== XINT (bar
->end
))
4162 /* Make sure the values are reasonable, and try to preserve the
4163 distance between start and end. */
4166 else if (start
> top_range
)
4168 end
= start
+ length
;
4172 else if (end
> top_range
&& ! dragging
)
4175 /* Store the adjusted setting in the scroll bar. */
4176 XSETINT (bar
->start
, start
);
4177 XSETINT (bar
->end
, end
);
4179 /* Clip the end position, just for display. */
4180 if (end
> top_range
)
4183 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4184 top positions, to make sure the handle is always at least that
4185 many pixels tall. */
4186 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4188 SetControlMinimum (ch
, 0);
4189 /* Don't inadvertently activate deactivated scroll bars */
4190 if (GetControlMaximum (ch
) != -1)
4191 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4193 SetControlValue (ch
, start
);
4194 #if TARGET_API_MAC_CARBON
4195 SetControlViewSize (ch
, end
- start
);
4202 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4206 x_scroll_bar_remove (bar
)
4207 struct scroll_bar
*bar
;
4209 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4213 /* Destroy the Mac scroll bar control */
4214 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4216 /* Disassociate this scroll bar from its window. */
4217 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4222 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4223 that we are displaying PORTION characters out of a total of WHOLE
4224 characters, starting at POSITION. If WINDOW has no scroll bar,
4227 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4229 int portion
, whole
, position
;
4231 struct frame
*f
= XFRAME (w
->frame
);
4232 struct scroll_bar
*bar
;
4233 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4234 int window_y
, window_height
;
4236 /* Get window dimensions. */
4237 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4242 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4244 height
= window_height
;
4246 /* Compute the left edge of the scroll bar area. */
4247 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4249 /* Compute the width of the scroll bar which might be less than
4250 the width of the area reserved for the scroll bar. */
4251 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4252 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4256 /* Compute the left edge of the scroll bar. */
4257 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4258 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
4260 sb_left
= left
+ (width
- sb_width
) / 2;
4262 /* Adjustments according to Inside Macintosh to make it look nice */
4264 disp_height
= height
;
4270 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4276 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4279 /* Does the scroll bar exist yet? */
4280 if (NILP (w
->vertical_scroll_bar
))
4283 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4284 left
, top
, width
, height
, 0);
4286 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4288 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4292 /* It may just need to be moved and resized. */
4295 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4296 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4300 /* If already correctly positioned, do nothing. */
4301 if (XINT (bar
->left
) == sb_left
4302 && XINT (bar
->top
) == top
4303 && XINT (bar
->width
) == sb_width
4304 && XINT (bar
->height
) == height
)
4308 /* Clear areas not covered by the scroll bar because it's not as
4309 wide as the area reserved for it . This makes sure a
4310 previous mode line display is cleared after C-x 2 C-x 1, for
4312 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4313 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4314 left
, top
, area_width
, height
, 0);
4317 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4318 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4319 sb_left
- 1, top
, 1, height
, 0);
4323 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4324 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4328 /* Remember new settings. */
4329 XSETINT (bar
->left
, sb_left
);
4330 XSETINT (bar
->top
, top
);
4331 XSETINT (bar
->width
, sb_width
);
4332 XSETINT (bar
->height
, height
);
4338 /* Set the scroll bar's current state, unless we're currently being
4340 if (NILP (bar
->dragging
))
4342 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4345 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4348 int start
= ((double) position
* top_range
) / whole
;
4349 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4350 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4356 /* The following three hooks are used when we're doing a thorough
4357 redisplay of the frame. We don't explicitly know which scroll bars
4358 are going to be deleted, because keeping track of when windows go
4359 away is a real pain - "Can you say set-window-configuration, boys
4360 and girls?" Instead, we just assert at the beginning of redisplay
4361 that *all* scroll bars are to be removed, and then save a scroll bar
4362 from the fiery pit when we actually redisplay its window. */
4364 /* Arrange for all scroll bars on FRAME to be removed at the next call
4365 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4366 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4369 XTcondemn_scroll_bars (frame
)
4372 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4373 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4376 bar
= FRAME_SCROLL_BARS (frame
);
4377 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4378 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4379 XSCROLL_BAR (bar
)->prev
= Qnil
;
4380 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4381 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4382 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4387 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4388 Note that WINDOW isn't necessarily condemned at all. */
4391 XTredeem_scroll_bar (window
)
4392 struct window
*window
;
4394 struct scroll_bar
*bar
;
4396 /* We can't redeem this window's scroll bar if it doesn't have one. */
4397 if (NILP (window
->vertical_scroll_bar
))
4400 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4402 /* Unlink it from the condemned list. */
4404 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4406 if (NILP (bar
->prev
))
4408 /* If the prev pointer is nil, it must be the first in one of
4410 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4411 /* It's not condemned. Everything's fine. */
4413 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4414 window
->vertical_scroll_bar
))
4415 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4417 /* If its prev pointer is nil, it must be at the front of
4418 one or the other! */
4422 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4424 if (! NILP (bar
->next
))
4425 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4427 bar
->next
= FRAME_SCROLL_BARS (f
);
4429 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4430 if (! NILP (bar
->next
))
4431 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4435 /* Remove all scroll bars on FRAME that haven't been saved since the
4436 last call to `*condemn_scroll_bars_hook'. */
4439 XTjudge_scroll_bars (f
)
4442 Lisp_Object bar
, next
;
4444 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4446 /* Clear out the condemned list now so we won't try to process any
4447 more events on the hapless scroll bars. */
4448 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4450 for (; ! NILP (bar
); bar
= next
)
4452 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4454 x_scroll_bar_remove (b
);
4457 b
->next
= b
->prev
= Qnil
;
4460 /* Now there should be no references to the condemned scroll bars,
4461 and they should get garbage-collected. */
4466 activate_scroll_bars (frame
)
4472 bar
= FRAME_SCROLL_BARS (frame
);
4473 while (! NILP (bar
))
4475 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
4476 #if 1 /* TARGET_API_MAC_CARBON */
4477 ActivateControl (ch
);
4479 SetControlMaximum (ch
,
4480 VERTICAL_SCROLL_BAR_TOP_RANGE (frame
,
4481 XINT (XSCROLL_BAR (bar
)
4484 bar
= XSCROLL_BAR (bar
)->next
;
4490 deactivate_scroll_bars (frame
)
4496 bar
= FRAME_SCROLL_BARS (frame
);
4497 while (! NILP (bar
))
4499 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
4500 #if 1 /* TARGET_API_MAC_CARBON */
4501 DeactivateControl (ch
);
4503 SetControlMaximum (ch
, -1);
4505 bar
= XSCROLL_BAR (bar
)->next
;
4509 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4510 is set to something other than NO_EVENT, it is enqueued.
4512 This may be called from a signal handler, so we have to ignore GC
4516 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4517 struct scroll_bar
*bar
;
4520 struct input_event
*bufp
;
4522 int win_y
, top_range
;
4524 if (! GC_WINDOWP (bar
->window
))
4527 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4528 bufp
->frame_or_window
= bar
->window
;
4531 bar
->dragging
= Qnil
;
4535 case kControlUpButtonPart
:
4536 bufp
->part
= scroll_bar_up_arrow
;
4538 case kControlDownButtonPart
:
4539 bufp
->part
= scroll_bar_down_arrow
;
4541 case kControlPageUpPart
:
4542 bufp
->part
= scroll_bar_above_handle
;
4544 case kControlPageDownPart
:
4545 bufp
->part
= scroll_bar_below_handle
;
4547 #if TARGET_API_MAC_CARBON
4550 case kControlIndicatorPart
:
4552 if (er
->what
== mouseDown
)
4553 bar
->dragging
= make_number (0);
4554 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4555 bufp
->part
= scroll_bar_handle
;
4559 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4560 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4562 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4566 if (! NILP (bar
->dragging
))
4567 win_y
-= XINT (bar
->dragging
);
4571 if (win_y
> top_range
)
4574 XSETINT (bufp
->x
, win_y
);
4575 XSETINT (bufp
->y
, top_range
);
4579 /* Handle some mouse motion while someone is dragging the scroll bar.
4581 This may be called from a signal handler, so we have to ignore GC
4585 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4586 struct scroll_bar
*bar
;
4590 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4592 last_mouse_movement_time
= t
;
4595 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4597 /* If we're dragging the bar, display it. */
4598 if (! GC_NILP (bar
->dragging
))
4600 /* Where should the handle be now? */
4601 int new_start
= y_pos
- 24;
4603 if (new_start
!= XINT (bar
->start
))
4605 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4607 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4613 /* Return information to the user about the current position of the
4614 mouse on the scroll bar. */
4617 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4619 Lisp_Object
*bar_window
;
4620 enum scroll_bar_part
*part
;
4622 unsigned long *time
;
4624 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4625 WindowPtr wp
= front_emacs_window ();
4627 struct frame
*f
= mac_window_to_frame (wp
);
4628 int win_y
, top_range
;
4630 SetPortWindowPort (wp
);
4632 GetMouse (&mouse_pos
);
4634 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4635 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4637 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4641 if (! NILP (bar
->dragging
))
4642 win_y
-= XINT (bar
->dragging
);
4646 if (win_y
> top_range
)
4650 *bar_window
= bar
->window
;
4652 if (! NILP (bar
->dragging
))
4653 *part
= scroll_bar_handle
;
4654 else if (win_y
< XINT (bar
->start
))
4655 *part
= scroll_bar_above_handle
;
4656 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
4657 *part
= scroll_bar_handle
;
4659 *part
= scroll_bar_below_handle
;
4661 XSETINT (*x
, win_y
);
4662 XSETINT (*y
, top_range
);
4665 last_mouse_scroll_bar
= Qnil
;
4667 *time
= last_mouse_movement_time
;
4670 /***********************************************************************
4672 ***********************************************************************/
4674 /* Set clipping for output in glyph row ROW. W is the window in which
4675 we operate. GC is the graphics context to set clipping in.
4677 ROW may be a text row or, e.g., a mode line. Text rows must be
4678 clipped to the interior of the window dedicated to text display,
4679 mode lines must be clipped to the whole window. */
4682 x_clip_to_row (w
, row
, area
, gc
)
4684 struct glyph_row
*row
;
4688 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4690 int window_x
, window_y
, window_width
;
4692 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
4694 clip_rect
.left
= window_x
;
4695 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4696 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4697 clip_rect
.right
= clip_rect
.left
+ window_width
;
4698 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4700 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
4704 /* Draw a hollow box cursor on window W in glyph row ROW. */
4707 x_draw_hollow_cursor (w
, row
)
4709 struct glyph_row
*row
;
4711 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4712 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4713 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4716 struct glyph
*cursor_glyph
;
4719 /* Get the glyph the cursor is on. If we can't tell because
4720 the current matrix is invalid or such, give up. */
4721 cursor_glyph
= get_phys_cursor_glyph (w
);
4722 if (cursor_glyph
== NULL
)
4725 /* Compute the width of the rectangle to draw. If on a stretch
4726 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4727 rectangle as wide as the glyph, but use a canonical character
4729 wd
= cursor_glyph
->pixel_width
- 1;
4730 if (cursor_glyph
->type
== STRETCH_GLYPH
4731 && !x_stretch_cursor_p
)
4732 wd
= min (FRAME_COLUMN_WIDTH (f
), wd
);
4733 w
->phys_cursor_width
= wd
;
4735 /* Compute frame-relative coordinates from window-relative
4737 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
4738 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
);
4740 /* Compute the proper height and ascent of the rectangle, based
4741 on the actual glyph. Using the full height of the row looks
4742 bad when there are tall images on that row. */
4743 h
= max (min (FRAME_LINE_HEIGHT (f
), row
->height
),
4744 cursor_glyph
->ascent
+ cursor_glyph
->descent
);
4745 if (h
< row
->height
)
4746 y
+= row
->ascent
/* - w->phys_cursor_ascent */ + cursor_glyph
->descent
- h
;
4749 /* The foreground of cursor_gc is typically the same as the normal
4750 background color, which can cause the cursor box to be invisible. */
4751 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4752 if (dpyinfo
->scratch_cursor_gc
)
4753 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
4755 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
4756 GCForeground
, &xgcv
);
4757 gc
= dpyinfo
->scratch_cursor_gc
;
4759 /* Set clipping, draw the rectangle, and reset clipping again. */
4760 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4761 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
4762 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4766 /* Draw a bar cursor on window W in glyph row ROW.
4768 Implementation note: One would like to draw a bar cursor with an
4769 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4770 Unfortunately, I didn't find a font yet that has this property set.
4774 x_draw_bar_cursor (w
, row
, width
, kind
)
4776 struct glyph_row
*row
;
4778 enum text_cursor_kinds kind
;
4780 struct frame
*f
= XFRAME (w
->frame
);
4781 struct glyph
*cursor_glyph
;
4783 /* If cursor is out of bounds, don't draw garbage. This can happen
4784 in mini-buffer windows when switching between echo area glyphs
4786 cursor_glyph
= get_phys_cursor_glyph (w
);
4787 if (cursor_glyph
== NULL
)
4790 /* If on an image, draw like a normal cursor. That's usually better
4791 visible than drawing a bar, esp. if the image is large so that
4792 the bar might not be in the window. */
4793 if (cursor_glyph
->type
== IMAGE_GLYPH
)
4795 struct glyph_row
*row
;
4796 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
4797 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
4801 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4802 Window window
= FRAME_MAC_WINDOW (f
);
4803 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
4804 unsigned long mask
= GCForeground
| GCBackground
;
4805 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
4808 /* If the glyph's background equals the color we normally draw
4809 the bar cursor in, the bar cursor in its normal color is
4810 invisible. Use the glyph's foreground color instead in this
4811 case, on the assumption that the glyph's colors are chosen so
4812 that the glyph is legible. */
4813 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
4814 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
4816 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4819 XChangeGC (dpy
, gc
, mask
, &xgcv
);
4822 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
4823 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
4827 width
= FRAME_CURSOR_WIDTH (f
);
4828 width
= min (cursor_glyph
->pixel_width
, width
);
4830 w
->phys_cursor_width
= width
;
4831 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4833 if (kind
== BAR_CURSOR
)
4834 XFillRectangle (dpy
, window
, gc
,
4835 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4836 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
4837 width
, row
->height
);
4839 XFillRectangle (dpy
, window
, gc
,
4840 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4841 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
4842 row
->height
- width
),
4843 cursor_glyph
->pixel_width
,
4846 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4851 /* RIF: Define cursor CURSOR on frame F. */
4854 mac_define_frame_cursor (f
, cursor
)
4858 #if TARGET_API_MAC_CARBON
4859 SetThemeCursor (cursor
);
4861 SetCursor (*cursor
);
4866 /* RIF: Clear area on frame F. */
4869 mac_clear_frame_area (f
, x
, y
, width
, height
)
4871 int x
, y
, width
, height
;
4873 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4874 x
, y
, width
, height
, 0);
4878 /* RIF: Draw cursor on window W. */
4881 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
4883 struct glyph_row
*glyph_row
;
4885 int cursor_type
, cursor_width
;
4890 w
->phys_cursor_type
= cursor_type
;
4891 w
->phys_cursor_on_p
= 1;
4893 if (glyph_row
->exact_window_width_line_p
4894 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
4896 glyph_row
->cursor_in_fringe_p
= 1;
4897 draw_fringe_bitmap (w
, glyph_row
, 0);
4900 switch (cursor_type
)
4902 case HOLLOW_BOX_CURSOR
:
4903 x_draw_hollow_cursor (w
, glyph_row
);
4906 case FILLED_BOX_CURSOR
:
4907 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
4911 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
4915 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
4919 w
->phys_cursor_width
= 0;
4931 #if 0 /* MAC_TODO: no icon support yet. */
4933 x_bitmap_icon (f
, icon
)
4939 if (FRAME_W32_WINDOW (f
) == 0)
4943 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
4944 else if (STRINGP (icon
))
4945 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
4946 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
4947 else if (SYMBOLP (icon
))
4951 if (EQ (icon
, intern ("application")))
4952 name
= (LPCTSTR
) IDI_APPLICATION
;
4953 else if (EQ (icon
, intern ("hand")))
4954 name
= (LPCTSTR
) IDI_HAND
;
4955 else if (EQ (icon
, intern ("question")))
4956 name
= (LPCTSTR
) IDI_QUESTION
;
4957 else if (EQ (icon
, intern ("exclamation")))
4958 name
= (LPCTSTR
) IDI_EXCLAMATION
;
4959 else if (EQ (icon
, intern ("asterisk")))
4960 name
= (LPCTSTR
) IDI_ASTERISK
;
4961 else if (EQ (icon
, intern ("winlogo")))
4962 name
= (LPCTSTR
) IDI_WINLOGO
;
4966 hicon
= LoadIcon (NULL
, name
);
4974 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
4979 #endif /* MAC_TODO */
4981 /************************************************************************
4983 ************************************************************************/
4985 /* Display Error Handling functions not used on W32. Listing them here
4986 helps diff stay in step when comparing w32term.c with xterm.c.
4988 x_error_catcher (display, error)
4989 x_catch_errors (dpy)
4990 x_catch_errors_unwind (old_val)
4991 x_check_errors (dpy, format)
4992 x_had_errors_p (dpy)
4993 x_clear_errors (dpy)
4994 x_uncatch_errors (dpy, count)
4996 x_connection_signal (signalnum)
4997 x_connection_closed (dpy, error_message)
4998 x_error_quitter (display, error)
4999 x_error_handler (display, error)
5000 x_io_error_quitter (display)
5005 /* Changing the font of the frame. */
5007 /* Give frame F the font named FONTNAME as its default font, and
5008 return the full name of that font. FONTNAME may be a wildcard
5009 pattern; in that case, we choose some font that fits the pattern.
5010 The return value shows which font we chose. */
5013 x_new_font (f
, fontname
)
5015 register char *fontname
;
5017 struct font_info
*fontp
5018 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5023 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5024 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5025 FRAME_FONTSET (f
) = -1;
5027 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5028 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5029 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5031 compute_fringe_widths (f
, 1);
5033 /* Compute the scroll bar width in character columns. */
5034 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5036 int wid
= FRAME_COLUMN_WIDTH (f
);
5037 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5038 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5042 int wid
= FRAME_COLUMN_WIDTH (f
);
5043 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5046 /* Now make the frame display the given font. */
5047 if (FRAME_MAC_WINDOW (f
) != 0)
5049 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5051 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5053 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5056 /* Don't change the size of a tip frame; there's no point in
5057 doing it because it's done in Fx_show_tip, and it leads to
5058 problems because the tip frame has no widget. */
5059 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5060 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5063 return build_string (fontp
->full_name
);
5066 /* Give frame F the fontset named FONTSETNAME as its default font, and
5067 return the full name of that fontset. FONTSETNAME may be a wildcard
5068 pattern; in that case, we choose some fontset that fits the pattern.
5069 The return value shows which fontset we chose. */
5072 x_new_fontset (f
, fontsetname
)
5076 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5082 if (FRAME_FONTSET (f
) == fontset
)
5083 /* This fontset is already set in frame F. There's nothing more
5085 return fontset_name (fontset
);
5087 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5089 if (!STRINGP (result
))
5090 /* Can't load ASCII font. */
5093 /* Since x_new_font doesn't update any fontset information, do it now. */
5094 FRAME_FONTSET(f
) = fontset
;
5096 return build_string (fontsetname
);
5100 /***********************************************************************
5101 TODO: W32 Input Methods
5102 ***********************************************************************/
5103 /* Listing missing functions from xterm.c helps diff stay in step.
5105 xim_destroy_callback (xim, client_data, call_data)
5106 xim_open_dpy (dpyinfo, resource_name)
5108 xim_instantiate_callback (display, client_data, call_data)
5109 xim_initialize (dpyinfo, resource_name)
5110 xim_close_dpy (dpyinfo)
5116 mac_get_window_bounds (f
, inner
, outer
)
5118 Rect
*inner
, *outer
;
5120 #if TARGET_API_MAC_CARBON
5121 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5122 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5123 #else /* not TARGET_API_MAC_CARBON */
5124 RgnHandle region
= NewRgn ();
5126 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5127 *inner
= (*region
)->rgnBBox
;
5128 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5129 *outer
= (*region
)->rgnBBox
;
5130 DisposeRgn (region
);
5131 #endif /* not TARGET_API_MAC_CARBON */
5135 /* Calculate the absolute position in frame F
5136 from its current recorded position values and gravity. */
5139 x_calc_absolute_position (f
)
5142 int width_diff
= 0, height_diff
= 0;
5143 int flags
= f
->size_hint_flags
;
5146 /* We have nothing to do if the current position
5147 is already for the top-left corner. */
5148 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5151 /* Find the offsets of the outside upper-left corner of
5152 the inner window, with respect to the outer window. */
5153 mac_get_window_bounds (f
, &inner
, &outer
);
5155 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5156 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5158 /* Treat negative positions as relative to the leftmost bottommost
5159 position that fits on the screen. */
5160 if (flags
& XNegative
)
5161 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5163 - FRAME_PIXEL_WIDTH (f
)
5166 if (flags
& YNegative
)
5167 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5169 - FRAME_PIXEL_HEIGHT (f
)
5172 /* The left_pos and top_pos
5173 are now relative to the top and left screen edges,
5174 so the flags should correspond. */
5175 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5178 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5179 to really change the position, and 0 when calling from
5180 x_make_frame_visible (in that case, XOFF and YOFF are the current
5181 position values). It is -1 when calling from x_set_frame_parameters,
5182 which means, do adjust for borders but don't change the gravity. */
5185 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5187 register int xoff
, yoff
;
5190 if (change_gravity
> 0)
5194 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5196 f
->size_hint_flags
|= XNegative
;
5198 f
->size_hint_flags
|= YNegative
;
5199 f
->win_gravity
= NorthWestGravity
;
5201 x_calc_absolute_position (f
);
5204 x_wm_set_size_hint (f
, (long) 0, 0);
5206 #if TARGET_API_MAC_CARBON
5207 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5208 /* If the title bar is completely outside the screen, adjust the
5210 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5211 kWindowConstrainMoveRegardlessOfFit
5212 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5213 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5216 Rect inner
, outer
, screen_rect
, dummy
;
5217 RgnHandle region
= NewRgn ();
5219 mac_get_window_bounds (f
, &inner
, &outer
);
5220 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5221 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5222 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5223 f
->top_pos
+ f
->y_pixels_diff
, false);
5225 /* If the title bar is completely outside the screen, adjust the
5226 position. The variable `outer' holds the title bar rectangle.
5227 The variable `inner' holds slightly smaller one than `outer',
5228 so that the calculation of overlapping may not become too
5230 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5231 outer
= (*region
)->rgnBBox
;
5232 DisposeRgn (region
);
5234 InsetRect (&inner
, 8, 8);
5235 screen_rect
= qd
.screenBits
.bounds
;
5236 screen_rect
.top
+= GetMBarHeight ();
5238 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5240 if (inner
.right
<= screen_rect
.left
)
5241 f
->left_pos
= screen_rect
.left
;
5242 else if (inner
.left
>= screen_rect
.right
)
5243 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5245 if (inner
.bottom
<= screen_rect
.top
)
5246 f
->top_pos
= screen_rect
.top
;
5247 else if (inner
.top
>= screen_rect
.bottom
)
5248 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5250 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5251 f
->top_pos
+ f
->y_pixels_diff
, false);
5259 /* Call this to change the size of frame F's x-window.
5260 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5261 for this size change and subsequent size changes.
5262 Otherwise we leave the window gravity unchanged. */
5265 x_set_window_size (f
, change_gravity
, cols
, rows
)
5270 int pixelwidth
, pixelheight
;
5274 check_frame_size (f
, &rows
, &cols
);
5275 f
->scroll_bar_actual_width
5276 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5278 compute_fringe_widths (f
, 0);
5280 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5281 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5283 f
->win_gravity
= NorthWestGravity
;
5284 x_wm_set_size_hint (f
, (long) 0, 0);
5286 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5288 /* Now, strictly speaking, we can't be sure that this is accurate,
5289 but the window manager will get around to dealing with the size
5290 change request eventually, and we'll hear how it went when the
5291 ConfigureNotify event gets here.
5293 We could just not bother storing any of this information here,
5294 and let the ConfigureNotify event set everything up, but that
5295 might be kind of confusing to the Lisp code, since size changes
5296 wouldn't be reported in the frame parameters until some random
5297 point in the future when the ConfigureNotify event arrives.
5299 We pass 1 for DELAY since we can't run Lisp code inside of
5301 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5302 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5303 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5305 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5306 receive in the ConfigureNotify event; if we get what we asked
5307 for, then the event won't cause the screen to become garbaged, so
5308 we have to make sure to do it here. */
5309 SET_FRAME_GARBAGED (f
);
5311 XFlush (FRAME_X_DISPLAY (f
));
5313 /* If cursor was outside the new size, mark it as off. */
5314 mark_window_cursors_off (XWINDOW (f
->root_window
));
5316 /* Clear out any recollection of where the mouse highlighting was,
5317 since it might be in a place that's outside the new frame size.
5318 Actually checking whether it is outside is a pain in the neck,
5319 so don't try--just let the highlighting be done afresh with new size. */
5320 cancel_mouse_face (f
);
5325 /* Mouse warping. */
5327 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5330 x_set_mouse_position (f
, x
, y
)
5336 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5337 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5339 if (pix_x
< 0) pix_x
= 0;
5340 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5342 if (pix_y
< 0) pix_y
= 0;
5343 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5345 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5349 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5353 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5356 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5357 0, 0, 0, 0, pix_x
, pix_y
);
5363 /* focus shifting, raising and lowering. */
5366 x_focus_on_frame (f
)
5369 #if 0 /* This proves to be unpleasant. */
5373 /* I don't think that the ICCCM allows programs to do things like this
5374 without the interaction of the window manager. Whatever you end up
5375 doing with this code, do it to x_unfocus_frame too. */
5376 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5377 RevertToPointerRoot
, CurrentTime
);
5387 /* Raise frame F. */
5392 if (f
->async_visible
)
5395 SelectWindow (FRAME_MAC_WINDOW (f
));
5400 /* Lower frame F. */
5405 if (f
->async_visible
)
5408 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5414 XTframe_raise_lower (f
, raise_flag
)
5424 /* Change of visibility. */
5426 /* This tries to wait until the frame is really visible.
5427 However, if the window manager asks the user where to position
5428 the frame, this will return before the user finishes doing that.
5429 The frame will not actually be visible at that time,
5430 but it will become visible later when the window manager
5431 finishes with it. */
5434 x_make_frame_visible (f
)
5438 int original_top
, original_left
;
5442 if (! FRAME_VISIBLE_P (f
))
5444 /* We test FRAME_GARBAGED_P here to make sure we don't
5445 call x_set_offset a second time
5446 if we get to x_make_frame_visible a second time
5447 before the window gets really visible. */
5448 if (! FRAME_ICONIFIED_P (f
)
5449 && ! f
->output_data
.mac
->asked_for_visible
)
5450 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5452 f
->output_data
.mac
->asked_for_visible
= 1;
5454 #if TARGET_API_MAC_CARBON
5455 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5457 struct frame
*sf
= SELECTED_FRAME ();
5458 if (!FRAME_MAC_P (sf
))
5459 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5460 kWindowCenterOnMainScreen
);
5462 RepositionWindow (FRAME_MAC_WINDOW (f
),
5463 FRAME_MAC_WINDOW (sf
),
5464 #ifdef MAC_OS_X_VERSION_10_2
5465 kWindowCascadeStartAtParentWindowScreen
5467 kWindowCascadeOnParentWindowScreen
5470 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5473 ShowWindow (FRAME_MAC_WINDOW (f
));
5476 XFlush (FRAME_MAC_DISPLAY (f
));
5478 /* Synchronize to ensure Emacs knows the frame is visible
5479 before we do anything else. We do this loop with input not blocked
5480 so that incoming events are handled. */
5485 /* This must come after we set COUNT. */
5488 XSETFRAME (frame
, f
);
5490 /* Wait until the frame is visible. Process X events until a
5491 MapNotify event has been seen, or until we think we won't get a
5492 MapNotify at all.. */
5493 for (count
= input_signal_count
+ 10;
5494 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5496 /* Force processing of queued events. */
5499 /* Machines that do polling rather than SIGIO have been
5500 observed to go into a busy-wait here. So we'll fake an
5501 alarm signal to let the handler know that there's something
5502 to be read. We used to raise a real alarm, but it seems
5503 that the handler isn't always enabled here. This is
5505 if (input_polling_used ())
5507 /* It could be confusing if a real alarm arrives while
5508 processing the fake one. Turn it off and let the
5509 handler reset it. */
5510 extern void poll_for_input_1
P_ ((void));
5511 int old_poll_suppress_count
= poll_suppress_count
;
5512 poll_suppress_count
= 1;
5513 poll_for_input_1 ();
5514 poll_suppress_count
= old_poll_suppress_count
;
5517 /* See if a MapNotify event has been processed. */
5518 FRAME_SAMPLE_VISIBILITY (f
);
5523 /* Change from mapped state to withdrawn state. */
5525 /* Make the frame visible (mapped and not iconified). */
5528 x_make_frame_invisible (f
)
5531 /* Don't keep the highlight on an invisible frame. */
5532 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5533 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5537 HideWindow (FRAME_MAC_WINDOW (f
));
5539 /* We can't distinguish this from iconification
5540 just by the event that we get from the server.
5541 So we can't win using the usual strategy of letting
5542 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5543 and synchronize with the server to make sure we agree. */
5545 FRAME_ICONIFIED_P (f
) = 0;
5546 f
->async_visible
= 0;
5547 f
->async_iconified
= 0;
5552 /* Change window state from mapped to iconified. */
5558 /* Don't keep the highlight on an invisible frame. */
5559 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5560 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5563 /* Review: Since window is still visible in dock, still allow updates? */
5564 if (f
->async_iconified
)
5570 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5576 /* Free X resources of frame F. */
5579 x_free_frame_resources (f
)
5582 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5583 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5588 if (wp
== tip_window
)
5589 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5590 closed' event. So we reset tip_window here. */
5593 free_frame_menubar (f
);
5595 if (FRAME_FACE_CACHE (f
))
5596 free_frame_faces (f
);
5600 if (FRAME_SIZE_HINTS (f
))
5601 xfree (FRAME_SIZE_HINTS (f
));
5603 xfree (f
->output_data
.mac
);
5604 f
->output_data
.mac
= NULL
;
5606 if (f
== dpyinfo
->x_focus_frame
)
5607 dpyinfo
->x_focus_frame
= 0;
5608 if (f
== dpyinfo
->x_focus_event_frame
)
5609 dpyinfo
->x_focus_event_frame
= 0;
5610 if (f
== dpyinfo
->x_highlight_frame
)
5611 dpyinfo
->x_highlight_frame
= 0;
5613 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5615 dpyinfo
->mouse_face_beg_row
5616 = dpyinfo
->mouse_face_beg_col
= -1;
5617 dpyinfo
->mouse_face_end_row
5618 = dpyinfo
->mouse_face_end_col
= -1;
5619 dpyinfo
->mouse_face_window
= Qnil
;
5620 dpyinfo
->mouse_face_deferred_gc
= 0;
5621 dpyinfo
->mouse_face_mouse_frame
= 0;
5628 /* Destroy the X window of frame F. */
5631 x_destroy_window (f
)
5634 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5636 x_free_frame_resources (f
);
5638 dpyinfo
->reference_count
--;
5642 /* Setting window manager hints. */
5644 /* Set the normal size hints for the window manager, for frame F.
5645 FLAGS is the flags word to use--or 0 meaning preserve the flags
5646 that the window now has.
5647 If USER_POSITION is nonzero, we set the USPosition
5648 flag (this is useful when FLAGS is 0). */
5650 x_wm_set_size_hint (f
, flags
, user_position
)
5655 int base_width
, base_height
, width_inc
, height_inc
;
5656 int min_rows
= 0, min_cols
= 0;
5657 XSizeHints
*size_hints
;
5659 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5660 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5661 width_inc
= FRAME_COLUMN_WIDTH (f
);
5662 height_inc
= FRAME_LINE_HEIGHT (f
);
5664 check_frame_size (f
, &min_rows
, &min_cols
);
5666 size_hints
= FRAME_SIZE_HINTS (f
);
5667 if (size_hints
== NULL
)
5669 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
5670 bzero (size_hints
, sizeof (XSizeHints
));
5673 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
5674 size_hints
->width_inc
= width_inc
;
5675 size_hints
->height_inc
= height_inc
;
5676 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
5677 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
5678 size_hints
->base_width
= base_width
;
5679 size_hints
->base_height
= base_height
;
5682 size_hints
->flags
= flags
;
5683 else if (user_position
)
5685 size_hints
->flags
&= ~ PPosition
;
5686 size_hints
->flags
|= USPosition
;
5690 #if 0 /* MAC_TODO: hide application instead of iconify? */
5691 /* Used for IconicState or NormalState */
5694 x_wm_set_window_state (f
, state
)
5698 #ifdef USE_X_TOOLKIT
5701 XtSetArg (al
[0], XtNinitialState
, state
);
5702 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5703 #else /* not USE_X_TOOLKIT */
5704 Window window
= FRAME_X_WINDOW (f
);
5706 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5707 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5709 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5710 #endif /* not USE_X_TOOLKIT */
5714 x_wm_set_icon_pixmap (f
, pixmap_id
)
5720 #ifndef USE_X_TOOLKIT
5721 Window window
= FRAME_X_WINDOW (f
);
5726 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5727 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5731 /* It seems there is no way to turn off use of an icon pixmap.
5732 The following line does it, only if no icon has yet been created,
5733 for some window managers. But with mwm it crashes.
5734 Some people say it should clear the IconPixmapHint bit in this case,
5735 but that doesn't work, and the X consortium said it isn't the
5736 right thing at all. Since there is no way to win,
5737 best to explicitly give up. */
5739 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5745 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5749 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
5750 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5753 #else /* not USE_X_TOOLKIT */
5755 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5756 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5758 #endif /* not USE_X_TOOLKIT */
5761 #endif /* MAC_TODO */
5764 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5768 #if 0 /* MAC_TODO: no icons on Mac */
5769 #ifdef USE_X_TOOLKIT
5770 Window window
= XtWindow (f
->output_data
.x
->widget
);
5772 Window window
= FRAME_X_WINDOW (f
);
5775 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5776 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5777 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5779 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5780 #endif /* MAC_TODO */
5784 /***********************************************************************
5786 ***********************************************************************/
5788 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5791 x_get_font_info (f
, font_idx
)
5795 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
5798 /* the global font name table */
5799 char **font_name_table
= NULL
;
5800 int font_name_table_size
= 0;
5801 int font_name_count
= 0;
5804 /* compare two strings ignoring case */
5806 stricmp (const char *s
, const char *t
)
5808 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
5811 return tolower (*s
) - tolower (*t
);
5814 /* compare two strings ignoring case and handling wildcard */
5816 wildstrieq (char *s1
, char *s2
)
5818 if (strcmp (s1
, "*") == 0 || strcmp (s2
, "*") == 0)
5821 return stricmp (s1
, s2
) == 0;
5824 /* Assume parameter 1 is fully qualified, no wildcards. */
5826 mac_font_pattern_match (fontname
, pattern
)
5830 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
5831 char *font_name_copy
= (char *) alloca (strlen (fontname
) + 1);
5834 /* Copy fontname so we can modify it during comparison. */
5835 strcpy (font_name_copy
, fontname
);
5840 /* Turn pattern into a regexp and do a regexp match. */
5841 for (; *pattern
; pattern
++)
5843 if (*pattern
== '?')
5845 else if (*pattern
== '*')
5856 return (fast_c_string_match_ignore_case (build_string (regex
),
5857 font_name_copy
) >= 0);
5860 /* Two font specs are considered to match if their foundry, family,
5861 weight, slant, and charset match. */
5863 mac_font_match (char *mf
, char *xf
)
5865 char m_foundry
[50], m_family
[50], m_weight
[20], m_slant
[2], m_charset
[20];
5866 char x_foundry
[50], x_family
[50], x_weight
[20], x_slant
[2], x_charset
[20];
5868 if (sscanf (mf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5869 m_foundry
, m_family
, m_weight
, m_slant
, m_charset
) != 5)
5870 return mac_font_pattern_match (mf
, xf
);
5872 if (sscanf (xf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5873 x_foundry
, x_family
, x_weight
, x_slant
, x_charset
) != 5)
5874 return mac_font_pattern_match (mf
, xf
);
5876 return (wildstrieq (m_foundry
, x_foundry
)
5877 && wildstrieq (m_family
, x_family
)
5878 && wildstrieq (m_weight
, x_weight
)
5879 && wildstrieq (m_slant
, x_slant
)
5880 && wildstrieq (m_charset
, x_charset
))
5881 || mac_font_pattern_match (mf
, xf
);
5885 static Lisp_Object Qbig5
, Qcn_gb
, Qsjis
, Qeuc_kr
;
5888 decode_mac_font_name (name
, size
, scriptcode
)
5891 #if TARGET_API_MAC_CARBON
5897 Lisp_Object coding_system
;
5898 struct coding_system coding
;
5904 coding_system
= Qbig5
;
5907 coding_system
= Qcn_gb
;
5910 coding_system
= Qsjis
;
5913 coding_system
= Qeuc_kr
;
5919 setup_coding_system (coding_system
, &coding
);
5920 coding
.src_multibyte
= 0;
5921 coding
.dst_multibyte
= 1;
5922 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5923 coding
.composing
= COMPOSITION_DISABLED
;
5924 buf
= (char *) alloca (size
);
5926 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
5927 bcopy (buf
, name
, coding
.produced
);
5928 name
[coding
.produced
] = '\0';
5933 mac_to_x_fontname (name
, size
, style
, scriptcode
)
5937 #if TARGET_API_MAC_CARBON
5943 char foundry
[32], family
[32], cs
[32];
5944 char xf
[256], *result
, *p
;
5946 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) != 3)
5948 strcpy(foundry
, "Apple");
5949 strcpy(family
, name
);
5953 case smTradChinese
: /* == kTextEncodingMacChineseTrad */
5954 strcpy(cs
, "big5-0");
5956 case smSimpChinese
: /* == kTextEncodingMacChineseSimp */
5957 strcpy(cs
, "gb2312.1980-0");
5959 case smJapanese
: /* == kTextEncodingMacJapanese */
5960 strcpy(cs
, "jisx0208.1983-sjis");
5963 /* Each Apple Japanese font is entered into the font table
5964 twice: once as a jisx0208.1983-sjis font and once as a
5965 jisx0201.1976-0 font. The latter can be used to display
5966 the ascii charset and katakana-jisx0201 charset. A
5967 negative script code signals that the name of this latter
5968 font is being built. */
5969 strcpy(cs
, "jisx0201.1976-0");
5971 case smKorean
: /* == kTextEncodingMacKorean */
5972 strcpy(cs
, "ksc5601.1989-0");
5974 #if TARGET_API_MAC_CARBON
5975 case kTextEncodingMacCyrillic
:
5976 strcpy(cs
, "mac-cyrillic");
5978 case kTextEncodingMacCentralEurRoman
:
5979 strcpy(cs
, "mac-centraleurroman");
5981 case kTextEncodingMacSymbol
:
5982 case kTextEncodingMacDingbats
:
5983 strcpy(cs
, "adobe-fontspecific");
5987 strcpy(cs
, "mac-roman");
5992 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5993 foundry
, family
, style
& bold
? "bold" : "medium",
5994 style
& italic
? 'i' : 'r', size
, size
* 10, size
* 10, cs
);
5996 result
= (char *) xmalloc (strlen (xf
) + 1);
5997 strcpy (result
, xf
);
5998 for (p
= result
; *p
; p
++)
6004 /* Convert an X font spec to the corresponding mac font name, which
6005 can then be passed to GetFNum after conversion to a Pascal string.
6006 For ordinary Mac fonts, this should just be their names, like
6007 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6008 collection contain their charset designation in their names, like
6009 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6010 names are handled accordingly. */
6012 x_font_name_to_mac_font_name (char *xf
, char *mf
)
6014 char foundry
[32], family
[32], weight
[20], slant
[2], cs
[32];
6015 Lisp_Object coding_system
= Qnil
;
6016 struct coding_system coding
;
6020 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6021 foundry
, family
, weight
, slant
, cs
) != 5 &&
6022 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6023 foundry
, family
, weight
, slant
, cs
) != 5)
6026 if (strcmp (cs
, "big5-0") == 0)
6027 coding_system
= Qbig5
;
6028 else if (strcmp (cs
, "gb2312.1980-0") == 0)
6029 coding_system
= Qcn_gb
;
6030 else if (strcmp (cs
, "jisx0208.1983-sjis") == 0
6031 || strcmp (cs
, "jisx0201.1976-0") == 0)
6032 coding_system
= Qsjis
;
6033 else if (strcmp (cs
, "ksc5601.1989-0") == 0)
6034 coding_system
= Qeuc_kr
;
6035 else if (strcmp (cs
, "mac-roman") == 0
6036 || strcmp (cs
, "mac-cyrillic") == 0
6037 || strcmp (cs
, "mac-centraleurroman") == 0
6038 || strcmp (cs
, "adobe-fontspecific") == 0)
6039 strcpy (mf
, family
);
6041 sprintf (mf
, "%s-%s-%s", foundry
, family
, cs
);
6043 if (!NILP (coding_system
))
6045 setup_coding_system (coding_system
, &coding
);
6046 coding
.src_multibyte
= 1;
6047 coding
.dst_multibyte
= 1;
6048 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6049 encode_coding (&coding
, family
, mf
, strlen (family
), sizeof (Str32
) - 1);
6050 mf
[coding
.produced
] = '\0';
6056 add_font_name_table_entry (char *font_name
)
6058 if (font_name_table_size
== 0)
6060 font_name_table_size
= 16;
6061 font_name_table
= (char **)
6062 xmalloc (font_name_table_size
* sizeof (char *));
6064 else if (font_name_count
+ 1 >= font_name_table_size
)
6066 font_name_table_size
+= 16;
6067 font_name_table
= (char **)
6068 xrealloc (font_name_table
,
6069 font_name_table_size
* sizeof (char *));
6072 font_name_table
[font_name_count
++] = font_name
;
6075 /* Sets up the table font_name_table to contain the list of all fonts
6076 in the system the first time the table is used so that the Resource
6077 Manager need not be accessed every time this information is
6081 init_font_name_table ()
6083 #if TARGET_API_MAC_CARBON
6086 if (Gestalt (gestaltSystemVersion
, &sv
) == noErr
&& sv
>= 0x1000)
6088 FMFontFamilyIterator ffi
;
6089 FMFontFamilyInstanceIterator ffii
;
6092 /* Create a dummy instance iterator here to avoid creating and
6093 destroying it in the loop. */
6094 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6096 /* Create an iterator to enumerate the font families. */
6097 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6100 FMDisposeFontFamilyInstanceIterator (&ffii
);
6104 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6110 TextEncoding encoding
;
6111 TextEncodingBase sc
;
6113 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6119 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6121 sc
= GetTextEncodingBase (encoding
);
6122 decode_mac_font_name (name
, sizeof (name
), sc
);
6124 /* Point the instance iterator at the current font family. */
6125 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6128 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6131 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6132 contained in Apple Japanese (SJIS) font. */
6136 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6138 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6140 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6142 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6147 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6149 if (sc
== smJapanese
)
6154 else if (sc
== -smJapanese
)
6159 /* Dispose of the iterators. */
6160 FMDisposeFontFamilyIterator (&ffi
);
6161 FMDisposeFontFamilyInstanceIterator (&ffii
);
6165 #endif /* TARGET_API_MAC_CARBON */
6167 SInt16 fontnum
, old_fontnum
;
6168 int num_mac_fonts
= CountResources('FOND');
6170 Handle font_handle
, font_handle_2
;
6171 short id
, scriptcode
;
6174 struct FontAssoc
*fat
;
6175 struct AsscEntry
*assc_entry
;
6177 GetPort (&port
); /* save the current font number used */
6178 #if TARGET_API_MAC_CARBON
6179 old_fontnum
= GetPortTextFont (port
);
6181 old_fontnum
= port
->txFont
;
6184 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6186 font_handle
= GetIndResource ('FOND', i
);
6190 GetResInfo (font_handle
, &id
, &type
, name
);
6191 GetFNum (name
, &fontnum
);
6197 scriptcode
= FontToScript (fontnum
);
6198 decode_mac_font_name (name
, sizeof (name
), scriptcode
);
6201 HLock (font_handle
);
6203 if (GetResourceSizeOnDisk (font_handle
)
6204 >= sizeof (struct FamRec
))
6206 fat
= (struct FontAssoc
*) (*font_handle
6207 + sizeof (struct FamRec
));
6209 = (struct AsscEntry
*) (*font_handle
6210 + sizeof (struct FamRec
)
6211 + sizeof (struct FontAssoc
));
6213 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6215 if (font_name_table_size
== 0)
6217 font_name_table_size
= 16;
6218 font_name_table
= (char **)
6219 xmalloc (font_name_table_size
* sizeof (char *));
6221 else if (font_name_count
>= font_name_table_size
)
6223 font_name_table_size
+= 16;
6224 font_name_table
= (char **)
6225 xrealloc (font_name_table
,
6226 font_name_table_size
* sizeof (char *));
6228 font_name_table
[font_name_count
++]
6229 = mac_to_x_fontname (name
,
6230 assc_entry
->fontSize
,
6231 assc_entry
->fontStyle
,
6233 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6234 parts are contained in Apple Japanese (SJIS)
6236 if (smJapanese
== scriptcode
)
6238 font_name_table
[font_name_count
++]
6239 = mac_to_x_fontname (name
,
6240 assc_entry
->fontSize
,
6241 assc_entry
->fontStyle
,
6247 HUnlock (font_handle
);
6248 font_handle_2
= GetNextFOND (font_handle
);
6249 ReleaseResource (font_handle
);
6250 font_handle
= font_handle_2
;
6252 while (ResError () == noErr
&& font_handle
);
6255 TextFont (old_fontnum
);
6256 #if TARGET_API_MAC_CARBON
6258 #endif /* TARGET_API_MAC_CARBON */
6263 mac_clear_font_name_table ()
6267 for (i
= 0; i
< font_name_count
; i
++)
6268 xfree (font_name_table
[i
]);
6269 xfree (font_name_table
);
6270 font_name_table
= NULL
;
6271 font_name_table_size
= font_name_count
= 0;
6275 enum xlfd_scalable_field_index
6277 XLFD_SCL_PIXEL_SIZE
,
6278 XLFD_SCL_POINT_SIZE
,
6283 static int xlfd_scalable_fields
[] =
6292 mac_c_string_match (regexp
, string
, nonspecial
, exact
)
6294 const char *string
, *nonspecial
;
6299 if (strcmp (string
, nonspecial
) == 0)
6300 return build_string (string
);
6302 else if (strstr (string
, nonspecial
))
6304 Lisp_Object str
= build_string (string
);
6306 if (fast_string_match (regexp
, str
) >= 0)
6314 mac_do_list_fonts (pattern
, maxnames
)
6319 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6320 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6323 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6324 char *longest_start
, *cur_start
, *nonspecial
;
6325 int longest_len
, exact
;
6327 if (font_name_table
== NULL
) /* Initialize when first used. */
6328 init_font_name_table ();
6330 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6333 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6334 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6335 fonts are scaled according to the specified size. */
6338 field
= xlfd_scalable_fields
;
6346 if ('1' <= *ptr
&& *ptr
<= '9')
6348 *val
= *ptr
++ - '0';
6349 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6350 *val
= *val
* 10 + *ptr
++ - '0';
6357 ptr
= strchr (ptr
, '-');
6360 while (ptr
&& i
< 14);
6362 if (i
== 14 && ptr
== NULL
)
6364 if (scl_val
[XLFD_SCL_POINT_SIZE
] > 0)
6366 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_POINT_SIZE
] / 10;
6367 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_POINT_SIZE
];
6369 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0)
6371 scl_val
[XLFD_SCL_POINT_SIZE
] =
6372 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10;
6374 else if (scl_val
[XLFD_SCL_AVGWIDTH
] > 0)
6376 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
] / 10;
6377 scl_val
[XLFD_SCL_POINT_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
];
6381 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6386 longest_start
= cur_start
= ptr
;
6390 /* Turn pattern into a regexp and do a regexp match. Also find the
6391 longest substring containing no special characters. */
6392 for (; *pattern
; pattern
++)
6394 if (*pattern
== '?' || *pattern
== '*')
6396 if (ptr
- cur_start
> longest_len
)
6398 longest_start
= cur_start
;
6399 longest_len
= ptr
- cur_start
;
6403 if (*pattern
== '?')
6405 else /* if (*pattern == '*') */
6413 *ptr
++ = tolower (*pattern
);
6416 if (ptr
- cur_start
> longest_len
)
6418 longest_start
= cur_start
;
6419 longest_len
= ptr
- cur_start
;
6425 nonspecial
= xmalloc (longest_len
+ 1);
6426 strncpy (nonspecial
, longest_start
, longest_len
);
6427 nonspecial
[longest_len
] = '\0';
6429 pattern_regex
= build_string (regex
);
6431 for (i
= 0; i
< font_name_count
; i
++)
6433 fontname
= mac_c_string_match (pattern_regex
, font_name_table
[i
],
6435 if (!NILP (fontname
))
6437 font_list
= Fcons (fontname
, font_list
);
6438 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6441 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6442 && (ptr
= strstr (font_name_table
[i
], "-0-0-75-75-m-0-")))
6444 int former_len
= ptr
- font_name_table
[i
];
6446 memcpy (scaled
, font_name_table
[i
], former_len
);
6447 sprintf (scaled
+ former_len
,
6448 "-%d-%d-75-75-m-%d-%s",
6449 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6450 scl_val
[XLFD_SCL_POINT_SIZE
],
6451 scl_val
[XLFD_SCL_AVGWIDTH
],
6452 ptr
+ sizeof ("-0-0-75-75-m-0-") - 1);
6453 fontname
= mac_c_string_match (pattern_regex
, scaled
,
6455 if (!NILP (fontname
))
6457 font_list
= Fcons (fontname
, font_list
);
6458 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6469 /* Return a list of at most MAXNAMES font specs matching the one in
6470 PATTERN. Cache matching fonts for patterns in
6471 dpyinfo->name_list_element to avoid looking them up again by
6472 calling mac_font_pattern_match (slow). Return as many matching
6473 fonts as possible if MAXNAMES = -1. */
6476 x_list_fonts (struct frame
*f
,
6477 Lisp_Object pattern
,
6481 Lisp_Object newlist
= Qnil
, tem
, key
;
6482 struct mac_display_info
*dpyinfo
= f
? FRAME_MAC_DISPLAY_INFO (f
) : NULL
;
6486 tem
= XCDR (dpyinfo
->name_list_element
);
6487 key
= Fcons (pattern
, make_number (maxnames
));
6489 newlist
= Fassoc (key
, tem
);
6490 if (!NILP (newlist
))
6492 newlist
= Fcdr_safe (newlist
);
6498 newlist
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6501 /* MAC_TODO: add code for matching outline fonts here */
6505 XSETCDR (dpyinfo
->name_list_element
,
6506 Fcons (Fcons (key
, newlist
),
6507 XCDR (dpyinfo
->name_list_element
)));
6517 /* Check that FONT is valid on frame F. It is if it can be found in F's
6521 x_check_font (f
, font
)
6526 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6528 xassert (font
!= NULL
);
6530 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6531 if (dpyinfo
->font_table
[i
].name
6532 && font
== dpyinfo
->font_table
[i
].font
)
6535 xassert (i
< dpyinfo
->n_fonts
);
6538 #endif /* GLYPH_DEBUG != 0 */
6540 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6541 Note: There are (broken) X fonts out there with invalid XFontStruct
6542 min_bounds contents. For example, handa@etl.go.jp reports that
6543 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6544 have font->min_bounds.width == 0. */
6547 x_font_min_bounds (font
, w
, h
)
6548 MacFontStruct
*font
;
6551 *h
= FONT_HEIGHT (font
);
6552 *w
= font
->min_bounds
.width
;
6556 /* Compute the smallest character width and smallest font height over
6557 all fonts available on frame F. Set the members smallest_char_width
6558 and smallest_font_height in F's x_display_info structure to
6559 the values computed. Value is non-zero if smallest_font_height or
6560 smallest_char_width become smaller than they were before. */
6563 x_compute_min_glyph_bounds (f
)
6567 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6568 MacFontStruct
*font
;
6569 int old_width
= dpyinfo
->smallest_char_width
;
6570 int old_height
= dpyinfo
->smallest_font_height
;
6572 dpyinfo
->smallest_font_height
= 100000;
6573 dpyinfo
->smallest_char_width
= 100000;
6575 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6576 if (dpyinfo
->font_table
[i
].name
)
6578 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6581 font
= (MacFontStruct
*) fontp
->font
;
6582 xassert (font
!= (MacFontStruct
*) ~0);
6583 x_font_min_bounds (font
, &w
, &h
);
6585 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6586 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6589 xassert (dpyinfo
->smallest_char_width
> 0
6590 && dpyinfo
->smallest_font_height
> 0);
6592 return (dpyinfo
->n_fonts
== 1
6593 || dpyinfo
->smallest_char_width
< old_width
6594 || dpyinfo
->smallest_font_height
< old_height
);
6598 /* Determine whether given string is a fully-specified XLFD: all 14
6599 fields are present, none is '*'. */
6602 is_fully_specified_xlfd (char *p
)
6610 for (i
= 0; i
< 13; i
++)
6612 q
= strchr (p
+ 1, '-');
6615 if (q
- p
== 2 && *(p
+ 1) == '*')
6620 if (strchr (p
+ 1, '-') != NULL
)
6623 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6630 const int kDefaultFontSize
= 9;
6633 /* XLoadQueryFont creates and returns an internal representation for a
6634 font in a MacFontStruct struct. There is really no concept
6635 corresponding to "loading" a font on the Mac. But we check its
6636 existence and find the font number and all other information for it
6637 and store them in the returned MacFontStruct. */
6639 static MacFontStruct
*
6640 XLoadQueryFont (Display
*dpy
, char *fontname
)
6642 int i
, size
, is_two_byte_font
, char_width
;
6645 SInt16 old_fontnum
, old_fontsize
;
6649 Style fontface
= normal
;
6650 MacFontStruct
*font
;
6651 FontInfo the_fontinfo
;
6652 char s_weight
[7], c_slant
;
6654 if (is_fully_specified_xlfd (fontname
))
6658 Lisp_Object matched_fonts
;
6660 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6661 if (NILP (matched_fonts
))
6663 name
= SDATA (XCAR (matched_fonts
));
6666 GetPort (&port
); /* save the current font number used */
6667 #if TARGET_API_MAC_CARBON
6668 old_fontnum
= GetPortTextFont (port
);
6669 old_fontsize
= GetPortTextSize (port
);
6670 old_fontface
= GetPortTextFace (port
);
6672 old_fontnum
= port
->txFont
;
6673 old_fontsize
= port
->txSize
;
6674 old_fontface
= port
->txFace
;
6677 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size
) != 1)
6678 size
= kDefaultFontSize
;
6680 if (sscanf (name
, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight
) == 1)
6681 if (strcmp (s_weight
, "bold") == 0)
6684 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant
) == 1)
6688 x_font_name_to_mac_font_name (name
, mfontname
);
6690 GetFNum (mfontname
, &fontnum
);
6694 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
6696 font
->fontname
= (char *) xmalloc (strlen (name
) + 1);
6697 bcopy (name
, font
->fontname
, strlen (name
) + 1);
6699 font
->mac_fontnum
= fontnum
;
6700 font
->mac_fontsize
= size
;
6701 font
->mac_fontface
= fontface
;
6702 font
->mac_scriptcode
= FontToScript (fontnum
);
6704 /* Apple Japanese (SJIS) font is listed as both
6705 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6706 (Roman script) in init_font_name_table (). The latter should be
6707 treated as a one-byte font. */
6712 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6714 && 0 == strcmp (cs
, "jisx0201.1976-0"))
6715 font
->mac_scriptcode
= smRoman
;
6718 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
6719 font
->mac_scriptcode
== smTradChinese
||
6720 font
->mac_scriptcode
== smSimpChinese
||
6721 font
->mac_scriptcode
== smKorean
;
6725 TextFace (fontface
);
6727 GetFontInfo (&the_fontinfo
);
6729 font
->ascent
= the_fontinfo
.ascent
;
6730 font
->descent
= the_fontinfo
.descent
;
6732 font
->min_byte1
= 0;
6733 if (is_two_byte_font
)
6734 font
->max_byte1
= 1;
6736 font
->max_byte1
= 0;
6737 font
->min_char_or_byte2
= 0x20;
6738 font
->max_char_or_byte2
= 0xff;
6740 if (is_two_byte_font
)
6742 /* Use the width of an "ideographic space" of that font because
6743 the_fontinfo.widMax returns the wrong width for some fonts. */
6744 switch (font
->mac_scriptcode
)
6747 char_width
= StringWidth("\p\x81\x40");
6750 char_width
= StringWidth("\p\xa1\x40");
6753 char_width
= StringWidth("\p\xa1\xa1");
6756 char_width
= StringWidth("\p\xa1\xa1");
6761 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6762 returns 15 for 12-point Monaco! */
6763 char_width
= CharWidth ('m');
6765 font
->max_bounds
.rbearing
= char_width
;
6766 font
->max_bounds
.lbearing
= 0;
6767 font
->max_bounds
.width
= char_width
;
6768 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
6769 font
->max_bounds
.descent
= the_fontinfo
.descent
;
6771 font
->min_bounds
= font
->max_bounds
;
6773 if (is_two_byte_font
|| CharWidth ('m') == CharWidth ('i'))
6774 font
->per_char
= NULL
;
6777 font
->per_char
= (XCharStruct
*)
6778 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
6780 int c
, min_width
, max_width
;
6782 min_width
= max_width
= char_width
;
6783 for (c
= 0x20; c
<= 0xff; c
++)
6785 font
->per_char
[c
- 0x20] = font
->max_bounds
;
6786 char_width
= CharWidth (c
);
6787 font
->per_char
[c
- 0x20].width
= char_width
;
6788 font
->per_char
[c
- 0x20].rbearing
= char_width
;
6789 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6790 character width of 0x7f. */
6793 min_width
= min (min_width
, char_width
);
6794 max_width
= max (max_width
, char_width
);
6797 font
->min_bounds
.width
= min_width
;
6798 font
->max_bounds
.width
= max_width
;
6802 TextFont (old_fontnum
); /* restore previous font number, size and face */
6803 TextSize (old_fontsize
);
6804 TextFace (old_fontface
);
6811 mac_unload_font (dpyinfo
, font
)
6812 struct mac_display_info
*dpyinfo
;
6815 xfree (font
->fontname
);
6817 xfree (font
->per_char
);
6822 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6823 pointer to the structure font_info while allocating it dynamically.
6824 If SIZE is 0, load any size of font.
6825 If loading is failed, return NULL. */
6828 x_load_font (f
, fontname
, size
)
6830 register char *fontname
;
6833 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6834 Lisp_Object font_names
;
6836 /* Get a list of all the fonts that match this name. Once we
6837 have a list of matching fonts, we compare them against the fonts
6838 we already have by comparing names. */
6839 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
6841 if (!NILP (font_names
))
6846 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6847 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
6848 if (dpyinfo
->font_table
[i
].name
6849 && (!strcmp (dpyinfo
->font_table
[i
].name
,
6850 SDATA (XCAR (tail
)))
6851 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6852 SDATA (XCAR (tail
)))))
6853 return (dpyinfo
->font_table
+ i
);
6856 /* Load the font and add it to the table. */
6859 struct MacFontStruct
*font
;
6860 struct font_info
*fontp
;
6861 unsigned long value
;
6864 /* If we have found fonts by x_list_font, load one of them. If
6865 not, we still try to load a font by the name given as FONTNAME
6866 because XListFonts (called in x_list_font) of some X server has
6867 a bug of not finding a font even if the font surely exists and
6868 is loadable by XLoadQueryFont. */
6869 if (size
> 0 && !NILP (font_names
))
6870 fontname
= (char *) SDATA (XCAR (font_names
));
6873 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
6878 /* Find a free slot in the font table. */
6879 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6880 if (dpyinfo
->font_table
[i
].name
== NULL
)
6883 /* If no free slot found, maybe enlarge the font table. */
6884 if (i
== dpyinfo
->n_fonts
6885 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
6888 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
6889 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
6891 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
6894 fontp
= dpyinfo
->font_table
+ i
;
6895 if (i
== dpyinfo
->n_fonts
)
6898 /* Now fill in the slots of *FONTP. */
6900 bzero (fontp
, sizeof (*fontp
));
6902 fontp
->font_idx
= i
;
6903 fontp
->name
= (char *) xmalloc (strlen (font
->fontname
) + 1);
6904 bcopy (font
->fontname
, fontp
->name
, strlen (font
->fontname
) + 1);
6906 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
6908 /* Fixed width font. */
6909 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
6916 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
6917 pcm
= mac_per_char_metric (font
, &char2b
, 0);
6919 fontp
->space_width
= pcm
->width
;
6921 fontp
->space_width
= FONT_WIDTH (font
);
6925 int width
= pcm
->width
;
6926 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
6927 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
6928 width
+= pcm
->width
;
6929 fontp
->average_width
= width
/ 95;
6932 fontp
->average_width
= FONT_WIDTH (font
);
6935 fontp
->full_name
= fontp
->name
;
6937 fontp
->size
= font
->max_bounds
.width
;
6938 fontp
->height
= FONT_HEIGHT (font
);
6940 /* For some font, ascent and descent in max_bounds field is
6941 larger than the above value. */
6942 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6943 if (max_height
> fontp
->height
)
6944 fontp
->height
= max_height
;
6947 /* The slot `encoding' specifies how to map a character
6948 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6949 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6950 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6951 2:0xA020..0xFF7F). For the moment, we don't know which charset
6952 uses this font. So, we set information in fontp->encoding[1]
6953 which is never used by any charset. If mapping can't be
6954 decided, set FONT_ENCODING_NOT_DECIDED. */
6955 if (font
->mac_scriptcode
== smJapanese
)
6956 fontp
->encoding
[1] = 4;
6960 = (font
->max_byte1
== 0
6962 ? (font
->min_char_or_byte2
< 0x80
6963 ? (font
->max_char_or_byte2
< 0x80
6964 ? 0 /* 0x20..0x7F */
6965 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6966 : 1) /* 0xA0..0xFF */
6968 : (font
->min_byte1
< 0x80
6969 ? (font
->max_byte1
< 0x80
6970 ? (font
->min_char_or_byte2
< 0x80
6971 ? (font
->max_char_or_byte2
< 0x80
6972 ? 0 /* 0x2020..0x7F7F */
6973 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6974 : 3) /* 0x20A0..0x7FFF */
6975 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6976 : (font
->min_char_or_byte2
< 0x80
6977 ? (font
->max_char_or_byte2
< 0x80
6978 ? 2 /* 0xA020..0xFF7F */
6979 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6980 : 1))); /* 0xA0A0..0xFFFF */
6983 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6984 fontp
->baseline_offset
6985 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6986 ? (long) value
: 0);
6987 fontp
->relative_compose
6988 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6989 ? (long) value
: 0);
6990 fontp
->default_ascent
6991 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6992 ? (long) value
: 0);
6994 fontp
->baseline_offset
= 0;
6995 fontp
->relative_compose
= 0;
6996 fontp
->default_ascent
= 0;
6999 /* Set global flag fonts_changed_p to non-zero if the font loaded
7000 has a character with a smaller width than any other character
7001 before, or if the font loaded has a smalle>r height than any
7002 other font loaded before. If this happens, it will make a
7003 glyph matrix reallocation necessary. */
7004 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
7011 /* Return a pointer to struct font_info of a font named FONTNAME for
7012 frame F. If no such font is loaded, return NULL. */
7015 x_query_font (f
, fontname
)
7017 register char *fontname
;
7019 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7022 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7023 if (dpyinfo
->font_table
[i
].name
7024 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7025 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7026 return (dpyinfo
->font_table
+ i
);
7031 /* Find a CCL program for a font specified by FONTP, and set the member
7032 `encoder' of the structure. */
7035 x_find_ccl_program (fontp
)
7036 struct font_info
*fontp
;
7038 Lisp_Object list
, elt
;
7040 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7044 && STRINGP (XCAR (elt
))
7045 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7051 struct ccl_program
*ccl
7052 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7054 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7057 fontp
->font_encoder
= ccl
;
7063 /* The Mac Event loop code */
7067 #include <Quickdraw.h>
7068 #include <Balloons.h>
7069 #include <Devices.h>
7071 #include <Gestalt.h>
7073 #include <Processes.h>
7075 #include <ToolUtils.h>
7076 #include <TextUtils.h>
7077 #include <Dialogs.h>
7080 #include <TextEncodingConverter.h>
7081 #include <Resources.h>
7086 #endif /* ! MAC_OSX */
7091 #define WINDOW_RESOURCE 128
7092 #define TERM_WINDOW_RESOURCE 129
7094 #define DEFAULT_NUM_COLS 80
7096 #define MIN_DOC_SIZE 64
7097 #define MAX_DOC_SIZE 32767
7099 /* sleep time for WaitNextEvent */
7100 #define WNE_SLEEP_AT_SUSPEND 10
7101 #define WNE_SLEEP_AT_RESUME 1
7103 /* true when cannot handle any Mac OS events */
7104 static int handling_window_update
= 0;
7107 /* the flag appl_is_suspended is used both for determining the sleep
7108 time to be passed to WaitNextEvent and whether the cursor should be
7109 drawn when updating the display. The cursor is turned off when
7110 Emacs is suspended. Redrawing it is unnecessary and what needs to
7111 be done depends on whether the cursor lies inside or outside the
7112 redraw region. So we might as well skip drawing it when Emacs is
7114 static Boolean app_is_suspended
= false;
7115 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7118 #define EXTRA_STACK_ALLOC (256 * 1024)
7120 #define ARGV_STRING_LIST_ID 129
7121 #define ABOUT_ALERT_ID 128
7122 #define RAM_TOO_LARGE_ALERT_ID 129
7124 Boolean terminate_flag
= false;
7126 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7127 Lisp_Object Qreverse
;
7129 /* True if using command key as meta key. */
7130 Lisp_Object Vmac_command_key_is_meta
;
7132 /* Modifier associated with the option key, or nil for normal behavior. */
7133 Lisp_Object Vmac_option_modifier
;
7135 /* True if the ctrl and meta keys should be reversed. */
7136 Lisp_Object Vmac_reverse_ctrl_meta
;
7138 /* True if the option and command modifiers should be used to emulate
7139 a three button mouse */
7140 Lisp_Object Vmac_emulate_three_button_mouse
;
7142 #if USE_CARBON_EVENTS
7143 /* True if the mouse wheel button (i.e. button 4) should map to
7144 mouse-2, instead of mouse-3. */
7145 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7147 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7148 for processing before Emacs sees it. */
7149 Lisp_Object Vmac_pass_command_to_system
;
7151 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7152 for processing before Emacs sees it. */
7153 Lisp_Object Vmac_pass_control_to_system
;
7156 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7157 to this text encoding */
7158 int mac_keyboard_text_encoding
;
7159 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
7161 /* Set in term/mac-win.el to indicate that event loop can now generate
7162 drag and drop events. */
7163 Lisp_Object Qmac_ready_for_drag_n_drop
;
7165 Lisp_Object drag_and_drop_file_list
;
7167 Point saved_menu_event_location
;
7169 #if !TARGET_API_MAC_CARBON
7170 /* Place holder for the default arrow cursor. */
7171 CursPtr arrow_cursor
;
7175 static void init_required_apple_events (void);
7177 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7179 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7180 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7181 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7183 #if TARGET_API_MAC_CARBON
7185 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7186 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7189 #if USE_CARBON_EVENTS
7190 /* Preliminary Support for the OSX Services Menu */
7191 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
7192 static void init_service_handler ();
7193 /* Window Event Handler */
7194 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7197 OSErr
install_window_handler (WindowPtr
);
7199 extern void init_emacs_passwd_dir ();
7200 extern int emacs_main (int, char **, char **);
7201 extern void check_alarm ();
7203 extern void initialize_applescript();
7204 extern void terminate_applescript();
7207 #if USE_CARBON_EVENTS
7208 mac_to_emacs_modifiers (UInt32 mods
)
7210 mac_to_emacs_modifiers (EventModifiers mods
)
7213 unsigned int result
= 0;
7214 if (mods
& macShiftKey
)
7215 result
|= shift_modifier
;
7216 if (mods
& macCtrlKey
)
7217 result
|= ctrl_modifier
;
7218 if (mods
& macMetaKey
)
7219 result
|= meta_modifier
;
7220 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7221 result
|= alt_modifier
;
7222 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7223 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7225 result
|= XUINT(val
);
7232 mac_get_emulated_btn ( UInt32 modifiers
)
7235 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7236 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7237 if (modifiers
& cmdKey
)
7238 result
= cmdIs3
? 2 : 1;
7239 else if (modifiers
& optionKey
)
7240 result
= cmdIs3
? 1 : 2;
7245 #if USE_CARBON_EVENTS
7246 /* Obtains the event modifiers from the event ref and then calls
7247 mac_to_emacs_modifiers. */
7249 mac_event_to_emacs_modifiers (EventRef eventRef
)
7252 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7253 sizeof (UInt32
), NULL
, &mods
);
7254 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7255 GetEventClass(eventRef
) == kEventClassMouse
)
7257 mods
&= ~(optionKey
| cmdKey
);
7259 return mac_to_emacs_modifiers (mods
);
7262 /* Given an event ref, return the code to use for the mouse button
7263 code in the emacs input_event. */
7265 mac_get_mouse_btn (EventRef ref
)
7267 EventMouseButton result
= kEventMouseButtonPrimary
;
7268 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7269 sizeof (EventMouseButton
), NULL
, &result
);
7272 case kEventMouseButtonPrimary
:
7273 if (NILP (Vmac_emulate_three_button_mouse
))
7277 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7278 sizeof (UInt32
), NULL
, &mods
);
7279 return mac_get_emulated_btn(mods
);
7281 case kEventMouseButtonSecondary
:
7282 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7283 case kEventMouseButtonTertiary
:
7284 case 4: /* 4 is the number for the mouse wheel button */
7285 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7291 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7292 events. However the click of the mouse wheel is not converted to a
7293 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7294 checks to see if it is a mouse up or down carbon event that has not
7295 been converted, and if so, converts it by hand (to be picked up in
7296 the XTread_socket loop). */
7297 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7299 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7300 /* Do special case for mouse wheel button. */
7301 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
7303 UInt32 kind
= GetEventKind (eventRef
);
7304 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
7306 eventRec
->what
= mouseDown
;
7309 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
7311 eventRec
->what
= mouseUp
;
7316 /* Need where and when. */
7318 GetEventParameter (eventRef
, kEventParamMouseLocation
,
7319 typeQDPoint
, NULL
, sizeof (Point
),
7320 NULL
, &eventRec
->where
);
7321 /* Use two step process because new event modifiers are
7322 32-bit and old are 16-bit. Currently, only loss is
7324 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
7325 typeUInt32
, NULL
, sizeof (UInt32
),
7327 eventRec
->modifiers
= mods
;
7329 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7340 Handle menubar_handle
;
7341 MenuHandle menu_handle
;
7343 menubar_handle
= GetNewMBar (128);
7344 if(menubar_handle
== NULL
)
7346 SetMenuBar (menubar_handle
);
7349 menu_handle
= GetMenuHandle (M_APPLE
);
7350 if(menu_handle
!= NULL
)
7351 AppendResMenu (menu_handle
,'DRVR');
7358 do_init_managers (void)
7360 #if !TARGET_API_MAC_CARBON
7361 InitGraf (&qd
.thePort
);
7363 FlushEvents (everyEvent
, 0);
7368 #endif /* !TARGET_API_MAC_CARBON */
7371 #if !TARGET_API_MAC_CARBON
7372 arrow_cursor
= &qd
.arrow
;
7374 /* set up some extra stack space for use by emacs */
7375 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7377 /* MaxApplZone must be called for AppleScript to execute more
7378 complicated scripts */
7381 #endif /* !TARGET_API_MAC_CARBON */
7385 do_check_ram_size (void)
7387 SInt32 physical_ram_size
, logical_ram_size
;
7389 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7390 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7391 || physical_ram_size
> (1 << VALBITS
)
7392 || logical_ram_size
> (1 << VALBITS
))
7394 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7400 do_window_update (WindowPtr win
)
7402 struct frame
*f
= mac_window_to_frame (win
);
7406 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7408 if (win
!= tip_window
)
7410 if (f
->async_visible
== 0)
7412 f
->async_visible
= 1;
7413 f
->async_iconified
= 0;
7414 SET_FRAME_GARBAGED (f
);
7416 /* An update event is equivalent to MapNotify on X, so report
7417 visibility changes properly. */
7418 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7419 /* Force a redisplay sooner or later to update the
7420 frame titles in case this is the second frame. */
7421 record_asynch_buffer_change ();
7427 handling_window_update
= 1;
7429 #if TARGET_API_MAC_CARBON
7431 RgnHandle region
= NewRgn ();
7433 GetPortVisibleRegion (GetWindowPort (win
), region
);
7434 UpdateControls (win
, region
);
7435 GetRegionBounds (region
, &r
);
7436 DisposeRgn (region
);
7439 UpdateControls (win
, win
->visRgn
);
7440 r
= (*win
->visRgn
)->rgnBBox
;
7442 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7444 handling_window_update
= 0;
7452 is_emacs_window (WindowPtr win
)
7454 Lisp_Object tail
, frame
;
7459 FOR_EACH_FRAME (tail
, frame
)
7460 if (FRAME_MAC_P (XFRAME (frame
)))
7461 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7470 /* Window-activate events will do the job. */
7475 wp
= front_emacs_window ();
7478 f
= mac_window_to_frame (wp
);
7482 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
7483 activate_scroll_bars (f
);
7487 app_is_suspended
= false;
7488 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7495 /* Window-deactivate events will do the job. */
7500 wp
= front_emacs_window ();
7503 f
= mac_window_to_frame (wp
);
7505 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
7507 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
7508 deactivate_scroll_bars (f
);
7512 app_is_suspended
= true;
7513 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7519 do_mouse_moved (mouse_pos
, f
)
7523 WindowPtr wp
= front_emacs_window ();
7524 struct x_display_info
*dpyinfo
;
7528 *f
= mac_window_to_frame (wp
);
7529 dpyinfo
= FRAME_MAC_DISPLAY_INFO (*f
);
7531 if (dpyinfo
->mouse_face_hidden
)
7533 dpyinfo
->mouse_face_hidden
= 0;
7534 clear_mouse_face (dpyinfo
);
7537 SetPortWindowPort (wp
);
7539 GlobalToLocal (&mouse_pos
);
7541 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
7542 x_scroll_bar_note_movement (tracked_scroll_bar
,
7544 - XINT (tracked_scroll_bar
->top
),
7545 TickCount() * (1000 / 60));
7547 note_mouse_movement (*f
, &mouse_pos
);
7553 do_apple_menu (SInt16 menu_item
)
7555 #if !TARGET_API_MAC_CARBON
7557 SInt16 da_driver_refnum
;
7559 if (menu_item
== I_ABOUT
)
7560 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7563 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7564 da_driver_refnum
= OpenDeskAcc (item_name
);
7566 #endif /* !TARGET_API_MAC_CARBON */
7570 do_menu_choice (SInt32 menu_choice
)
7572 SInt16 menu_id
, menu_item
;
7574 menu_id
= HiWord (menu_choice
);
7575 menu_item
= LoWord (menu_choice
);
7583 do_apple_menu (menu_item
);
7588 struct frame
*f
= mac_window_to_frame (front_emacs_window ());
7589 MenuHandle menu
= GetMenuHandle (menu_id
);
7594 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7595 menubar_selection_callback (f
, refcon
);
7604 /* Handle drags in size box. Based on code contributed by Ben
7605 Mesander and IM - Window Manager A. */
7608 do_grow_window (WindowPtr w
, EventRecord
*e
)
7611 int rows
, columns
, width
, height
;
7612 struct frame
*f
= mac_window_to_frame (w
);
7613 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
7614 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
7615 #if TARGET_API_MAC_CARBON
7621 if (size_hints
->flags
& PMinSize
)
7623 min_width
= size_hints
->min_width
;
7624 min_height
= size_hints
->min_height
;
7626 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7628 #if TARGET_API_MAC_CARBON
7629 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
7631 height
= new_rect
.bottom
- new_rect
.top
;
7632 width
= new_rect
.right
- new_rect
.left
;
7634 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7635 /* see if it really changed size */
7638 height
= HiWord (grow_size
);
7639 width
= LoWord (grow_size
);
7642 if (width
!= FRAME_PIXEL_WIDTH (f
)
7643 || height
!= FRAME_PIXEL_HEIGHT (f
))
7645 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7646 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7648 x_set_window_size (f
, 0, columns
, rows
);
7653 /* Handle clicks in zoom box. Calculation of "standard state" based
7654 on code in IM - Window Manager A and code contributed by Ben
7655 Mesander. The standard state of an Emacs window is 80-characters
7656 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7659 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7662 Rect zoom_rect
, port_rect
;
7664 int w_title_height
, columns
, rows
, width
, height
;
7665 struct frame
*f
= mac_window_to_frame (w
);
7667 #if TARGET_API_MAC_CARBON
7669 Point standard_size
;
7671 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7672 standard_size
.v
= FRAME_MAC_DISPLAY_INFO (f
)->height
;
7674 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7675 zoom_in_or_out
= inZoomIn
;
7678 /* Adjust the standard size according to character boundaries. */
7680 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7681 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7682 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7683 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7684 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
7685 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
7686 && port_rect
.left
== zoom_rect
.left
7687 && port_rect
.top
== zoom_rect
.top
)
7688 zoom_in_or_out
= inZoomIn
;
7690 zoom_in_or_out
= inZoomOut
;
7693 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
7695 #else /* not TARGET_API_MAC_CARBON */
7696 GetPort (&save_port
);
7698 SetPortWindowPort (w
);
7700 /* Clear window to avoid flicker. */
7701 EraseRect (&(w
->portRect
));
7702 if (zoom_in_or_out
== inZoomOut
)
7704 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
7705 LocalToGlobal (&top_left
);
7707 /* calculate height of window's title bar */
7708 w_title_height
= top_left
.v
- 1
7709 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
7711 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7712 zoom_rect
= qd
.screenBits
.bounds
;
7713 zoom_rect
.top
+= w_title_height
;
7714 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
7716 zoom_rect
.right
= zoom_rect
.left
7717 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7719 /* Adjust the standard size according to character boundaries. */
7720 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7722 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7724 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
7728 ZoomWindow (w
, zoom_in_or_out
, w
== front_emacs_window ());
7730 SetPort (save_port
);
7731 #endif /* not TARGET_API_MAC_CARBON */
7733 /* retrieve window size and update application values */
7734 #if TARGET_API_MAC_CARBON
7735 GetWindowPortBounds (w
, &port_rect
);
7737 port_rect
= w
->portRect
;
7739 height
= port_rect
.bottom
- port_rect
.top
;
7740 width
= port_rect
.right
- port_rect
.left
;
7742 if (width
!= FRAME_PIXEL_WIDTH (f
)
7743 || height
!= FRAME_PIXEL_HEIGHT (f
))
7745 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7746 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7748 change_frame_size (f
, rows
, columns
, 0, 1, 0);
7749 SET_FRAME_GARBAGED (f
);
7750 cancel_mouse_face (f
);
7752 FRAME_PIXEL_WIDTH (f
) = width
;
7753 FRAME_PIXEL_HEIGHT (f
) = height
;
7755 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
7758 /* Intialize AppleEvent dispatcher table for the required events. */
7760 init_required_apple_events ()
7765 /* Make sure we have apple events before starting. */
7766 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
7770 if (!(result
& (1 << gestaltAppleEventsPresent
)))
7773 #if TARGET_API_MAC_CARBON
7774 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7775 NewAEEventHandlerUPP
7776 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7779 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7780 NewAEEventHandlerProc
7781 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7787 #if TARGET_API_MAC_CARBON
7788 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7789 NewAEEventHandlerUPP
7790 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7793 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7794 NewAEEventHandlerProc
7795 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7801 #if TARGET_API_MAC_CARBON
7802 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7803 NewAEEventHandlerUPP
7804 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7807 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7808 NewAEEventHandlerProc
7809 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7815 #if TARGET_API_MAC_CARBON
7816 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7817 NewAEEventHandlerUPP
7818 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7821 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7822 NewAEEventHandlerProc
7823 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7830 #if USE_CARBON_EVENTS
7833 init_service_handler ()
7835 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
7836 {kEventClassService
, kEventServiceCopy
},
7837 {kEventClassService
, kEventServicePaste
}};
7838 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
7839 3, specs
, NULL
, NULL
);
7843 MAC_TODO: Check to see if this is called by AEProcessDesc...
7846 mac_handle_service_event (EventHandlerCallRef callRef
,
7847 EventRef event
, void *data
)
7849 OSStatus err
= noErr
;
7850 switch (GetEventKind (event
))
7852 case kEventServiceGetTypes
:
7854 CFMutableArrayRef copyTypes
, pasteTypes
;
7856 Boolean selection
= true;
7858 GetEventParameter(event, kEventParamServicePasteTypes,
7859 typeCFMutableArrayRef, NULL,
7860 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7862 GetEventParameter(event
, kEventParamServiceCopyTypes
,
7863 typeCFMutableArrayRef
, NULL
,
7864 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
7865 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
7867 CFArrayAppendValue (copyTypes
, type
);
7868 //CFArrayAppendValue (pasteTypes, type);
7872 case kEventServiceCopy
:
7874 ScrapRef currentScrap
, specificScrap
;
7878 GetCurrentScrap (¤tScrap
);
7880 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
7883 void *buffer
= xmalloc (byteCount
);
7886 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
7887 sizeof (ScrapRef
), NULL
, &specificScrap
);
7889 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
7890 &byteCount
, buffer
);
7892 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
7893 kScrapFlavorMaskNone
, byteCount
, buffer
);
7899 case kEventServicePaste
:
7902 // Get the current location
7904 ScrapRef specificScrap;
7905 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7906 sizeof(ScrapRef), NULL, &specificScrap);
7907 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7909 void * buffer = xmalloc(byteCount);
7910 if (buffer != NULL ) {
7911 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7912 &byteCount, buffer);
7914 // Actually place in the buffer
7916 // Get the current "selection" string here
7929 static pascal OSStatus
7930 mac_handle_window_event (next_handler
, event
, data
)
7931 EventHandlerCallRef next_handler
;
7935 extern Lisp_Object Qcontrol
;
7940 XSizeHints
*size_hints
;
7942 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
7943 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
7945 switch (GetEventKind (event
))
7947 case kEventWindowUpdate
:
7948 result
= CallNextEventHandler (next_handler
, event
);
7949 if (result
!= eventNotHandledErr
)
7952 do_window_update (wp
);
7955 case kEventWindowBoundsChanging
:
7956 result
= CallNextEventHandler (next_handler
, event
);
7957 if (result
!= eventNotHandledErr
)
7960 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
7961 NULL
, sizeof (UInt32
), NULL
, &attributes
);
7962 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
7963 if ((attributes
& kWindowBoundsChangeUserResize
)
7964 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
7965 == (PResizeInc
| PBaseSize
| PMinSize
)))
7970 GetEventParameter (event
, kEventParamCurrentBounds
,
7972 NULL
, sizeof (Rect
), NULL
, &bounds
);
7973 width
= bounds
.right
- bounds
.left
;
7974 height
= bounds
.bottom
- bounds
.top
;
7976 if (width
< size_hints
->min_width
)
7977 width
= size_hints
->min_width
;
7979 width
= size_hints
->base_width
7980 + (int) ((width
- size_hints
->base_width
)
7981 / (float) size_hints
->width_inc
+ .5)
7982 * size_hints
->width_inc
;
7984 if (height
< size_hints
->min_height
)
7985 height
= size_hints
->min_height
;
7987 height
= size_hints
->base_height
7988 + (int) ((height
- size_hints
->base_height
)
7989 / (float) size_hints
->height_inc
+ .5)
7990 * size_hints
->height_inc
;
7992 bounds
.right
= bounds
.left
+ width
;
7993 bounds
.bottom
= bounds
.top
+ height
;
7994 SetEventParameter (event
, kEventParamCurrentBounds
,
7995 typeQDRectangle
, sizeof (Rect
), &bounds
);
8001 return eventNotHandledErr
;
8003 #endif /* USE_CARBON_EVENTS */
8007 install_window_handler (window
)
8011 #if USE_CARBON_EVENTS
8012 EventTypeSpec specs
[] = {{kEventClassWindow
, kEventWindowUpdate
},
8013 {kEventClassWindow
, kEventWindowBoundsChanging
}};
8014 static EventHandlerUPP handle_window_event_UPP
= NULL
;
8016 if (handle_window_event_UPP
== NULL
)
8017 handle_window_event_UPP
= NewEventHandlerUPP (mac_handle_window_event
);
8019 err
= InstallWindowEventHandler (window
, handle_window_event_UPP
,
8020 GetEventTypeCount (specs
), specs
,
8023 #if TARGET_API_MAC_CARBON
8025 err
= InstallTrackingHandler (mac_do_track_drag
, window
, NULL
);
8027 err
= InstallReceiveHandler (mac_do_receive_drag
, window
, NULL
);
8033 /* Open Application Apple Event */
8035 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8041 /* Defined in mac.c. */
8043 path_from_vol_dir_name (char *, int, short, long, char *);
8046 /* Called when we receive an AppleEvent with an ID of
8047 "kAEOpenDocuments". This routine gets the direct parameter,
8048 extracts the FSSpecs in it, and puts their names on a list. */
8049 #pragma options align=mac68k
8050 typedef struct SelectionRange
{
8051 short unused1
; // 0 (not used)
8052 short lineNum
; // line to select (<0 to specify range)
8053 long startRange
; // start of selection range (if line < 0)
8054 long endRange
; // end of selection range (if line < 0)
8055 long unused2
; // 0 (not used)
8056 long theDate
; // modification date/time
8058 #pragma options align=reset
8061 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8066 DescType actual_type
;
8068 SelectionRange position
;
8070 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8072 goto descriptor_error_exit
;
8074 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8076 drag_and_drop_file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8077 make_number (position
.startRange
+ 1),
8078 make_number (position
.endRange
+ 1)),
8079 drag_and_drop_file_list
);
8081 /* Check to see that we got all of the required parameters from the
8082 event descriptor. For an 'odoc' event this should just be the
8084 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8085 &actual_type
, (Ptr
) &keyword
,
8086 sizeof (keyword
), &actual_size
);
8087 /* No error means that we found some unused parameters.
8088 errAEDescNotFound means that there are no more parameters. If we
8089 get an error code other than that, flag it. */
8090 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8092 err
= errAEEventNotHandled
;
8097 /* Got all the parameters we need. Now, go through the direct
8098 object list and parse it up. */
8100 long num_files_to_open
;
8102 err
= AECountItems (&the_desc
, &num_files_to_open
);
8107 /* AE file list is one based so just use that for indexing here. */
8108 for (i
= 1; i
<= num_files_to_open
; i
++)
8112 char unix_path_name
[MAXPATHLEN
];
8114 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8115 &actual_type
, &fref
, sizeof (FSRef
),
8117 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8120 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8124 Str255 path_name
, unix_path_name
;
8126 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8127 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8128 if (err
!= noErr
) continue;
8130 if (path_from_vol_dir_name (path_name
, 255, fs
.vRefNum
, fs
.parID
,
8132 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
8134 /* x-dnd functions expect undecoded filenames. */
8135 drag_and_drop_file_list
=
8136 Fcons (make_unibyte_string (unix_path_name
,
8137 strlen (unix_path_name
)),
8138 drag_and_drop_file_list
);
8144 /* Nuke the coerced file list in any case */
8145 err2
= AEDisposeDesc(&the_desc
);
8147 descriptor_error_exit
:
8148 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8153 #if TARGET_API_MAC_CARBON
8155 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8156 void *handlerRefCon
, DragReference theDrag
)
8158 static int can_accept
;
8161 ItemReference theItem
;
8162 FlavorFlags theFlags
;
8165 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8166 return dragNotAcceptedErr
;
8170 case kDragTrackingEnterHandler
:
8171 CountDragItems (theDrag
, &items
);
8173 for (index
= 1; index
<= items
; index
++)
8175 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8176 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8177 if (result
== noErr
)
8185 case kDragTrackingEnterWindow
:
8188 RgnHandle hilite_rgn
= NewRgn ();
8190 struct frame
*f
= mac_window_to_frame (window
);
8192 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
8193 GetWindowPortBounds (window
, &r
);
8194 OffsetRect (&r
, -r
.left
, -r
.top
);
8195 RectRgn (hilite_rgn
, &r
);
8196 ShowDragHilite (theDrag
, hilite_rgn
, true);
8197 DisposeRgn (hilite_rgn
);
8198 SetThemeCursor (kThemeCopyArrowCursor
);
8202 case kDragTrackingInWindow
:
8205 case kDragTrackingLeaveWindow
:
8208 struct frame
*f
= mac_window_to_frame (window
);
8210 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
8211 HideDragHilite (theDrag
);
8212 SetThemeCursor (kThemeArrowCursor
);
8216 case kDragTrackingLeaveHandler
:
8224 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8225 DragReference theDrag
)
8229 FlavorFlags theFlags
;
8232 ItemReference theItem
;
8234 Size size
= sizeof (HFSFlavor
);
8236 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8237 return dragNotAcceptedErr
;
8239 drag_and_drop_file_list
= Qnil
;
8240 GetDragMouse (theDrag
, &mouse
, 0L);
8241 CountDragItems (theDrag
, &items
);
8242 for (index
= 1; index
<= items
; index
++)
8244 /* Only handle file references. */
8245 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8246 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8247 if (result
== noErr
)
8251 char unix_path_name
[MAXPATHLEN
];
8253 Str255 path_name
, unix_path_name
;
8255 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8257 /* Use Carbon routines, otherwise it converts the file name
8258 to /Macintosh HD/..., which is not correct. */
8259 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8260 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8262 if (path_from_vol_dir_name (path_name
, 255, data
.fileSpec
.vRefNum
,
8263 data
.fileSpec
.parID
, data
.fileSpec
.name
) &&
8264 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
8266 /* x-dnd functions expect undecoded filenames. */
8267 drag_and_drop_file_list
=
8268 Fcons (make_unibyte_string (unix_path_name
,
8269 strlen (unix_path_name
)),
8270 drag_and_drop_file_list
);
8273 /* If there are items in the list, construct an event and post it to
8274 the queue like an interrupt using kbd_buffer_store_event. */
8275 if (!NILP (drag_and_drop_file_list
))
8277 struct input_event event
;
8279 struct frame
*f
= mac_window_to_frame (window
);
8282 GlobalToLocal (&mouse
);
8283 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8285 event
.kind
= DRAG_N_DROP_EVENT
;
8287 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8288 event
.timestamp
= TickCount () * (1000 / 60);
8289 XSETINT (event
.x
, mouse
.h
);
8290 XSETINT (event
.y
, mouse
.v
);
8291 XSETFRAME (frame
, f
);
8292 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8294 /* Post to the interrupt queue */
8295 kbd_buffer_store_event (&event
);
8296 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8298 ProcessSerialNumber psn
;
8299 GetCurrentProcess (&psn
);
8300 SetFrontProcess (&psn
);
8306 return dragNotAcceptedErr
;
8311 /* Print Document Apple Event */
8313 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8315 return errAEEventNotHandled
;
8320 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8322 /* FixMe: Do we need an unwind-protect or something here? And what
8323 do we do about unsaved files. Currently just forces quit rather
8324 than doing recursive callback to get user input. */
8326 terminate_flag
= true;
8328 /* Fkill_emacs doesn't return. We have to return. (TI) */
8335 profiler_exit_proc ()
8337 ProfilerDump ("\pEmacs.prof");
8342 /* These few functions implement Emacs as a normal Mac application
8343 (almost): set up the heap and the Toolbox, handle necessary
8344 system events plus a few simple menu events. They also set up
8345 Emacs's access to functions defined in the rest of this file.
8346 Emacs uses function hooks to perform all its terminal I/O. A
8347 complete list of these functions appear in termhooks.h. For what
8348 they do, read the comments there and see also w32term.c and
8349 xterm.c. What's noticeably missing here is the event loop, which
8350 is normally present in most Mac application. After performing the
8351 necessary Mac initializations, main passes off control to
8352 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8353 mac_read_socket (defined further below) to read input. This is
8354 where WaitNextEvent is called to process Mac events. This is also
8355 where check_alarm in sysdep.c is called to simulate alarm signals.
8356 This makes the cursor jump back to its correct position after
8357 briefly jumping to that of the matching parenthesis, print useful
8358 hints and prompts in the minibuffer after the user stops typing for
8361 #if !TARGET_API_MAC_CARBON
8366 #if __profile__ /* is the profiler on? */
8367 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
8372 /* set creator and type for files created by MSL */
8377 do_init_managers ();
8382 do_check_ram_size ();
8385 init_emacs_passwd_dir ();
8389 initialize_applescript ();
8391 init_required_apple_events ();
8397 /* set up argv array from STR# resource */
8398 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
8402 /* free up AppleScript resources on exit */
8403 atexit (terminate_applescript
);
8405 #if __profile__ /* is the profiler on? */
8406 atexit (profiler_exit_proc
);
8409 /* 3rd param "envp" never used in emacs_main */
8410 (void) emacs_main (argc
, argv
, 0);
8413 /* Never reached - real exit in Fkill_emacs */
8418 /* Table for translating Mac keycode to X keysym values. Contributed
8419 by Sudhir Shenoy. */
8420 static unsigned char keycode_to_xkeysym_table
[] = {
8421 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8422 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8423 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8425 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8426 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8427 /*0x38*/ 0, 0, 0, 0,
8428 /*0x3C*/ 0, 0, 0, 0,
8430 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8431 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8432 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8433 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8435 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8436 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8437 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8438 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8440 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8441 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8442 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8443 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8445 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8446 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8447 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8448 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8452 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8454 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8455 return *xKeySym
!= 0;
8458 #if !USE_CARBON_EVENTS
8459 static RgnHandle mouse_region
= NULL
;
8462 mac_wait_next_event (er
, sleep_time
, dequeue
)
8467 static EventRecord er_buf
= {nullEvent
};
8468 UInt32 target_tick
, current_tick
;
8469 EventMask event_mask
;
8471 if (mouse_region
== NULL
)
8472 mouse_region
= NewRgn ();
8474 event_mask
= everyEvent
;
8475 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8476 event_mask
-= highLevelEventMask
;
8478 current_tick
= TickCount ();
8479 target_tick
= current_tick
+ sleep_time
;
8481 if (er_buf
.what
== nullEvent
)
8482 while (!WaitNextEvent (event_mask
, &er_buf
,
8483 target_tick
- current_tick
, mouse_region
))
8485 current_tick
= TickCount ();
8486 if (target_tick
<= current_tick
)
8492 er_buf
.what
= nullEvent
;
8495 #endif /* not USE_CARBON_EVENTS */
8497 /* Emacs calls this whenever it wants to read an input event from the
8500 XTread_socket (sd
, expected
, hold_quit
)
8502 struct input_event
*hold_quit
;
8504 struct input_event inev
;
8506 #if USE_CARBON_EVENTS
8508 EventTargetRef toolbox_dispatcher
;
8511 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8513 if (interrupt_input_blocked
)
8515 interrupt_input_pending
= 1;
8519 interrupt_input_pending
= 0;
8522 /* So people can tell when we have read the available input. */
8523 input_signal_count
++;
8525 /* Don't poll for events to process (specifically updateEvt) if
8526 window update currently already in progress. A call to redisplay
8527 (in do_window_update) can be preempted by another call to
8528 redisplay, causing blank regions to be left on the screen and the
8529 cursor to be left at strange places. */
8530 if (handling_window_update
)
8537 Fkill_emacs (make_number (1));
8539 #if USE_CARBON_EVENTS
8540 toolbox_dispatcher
= GetEventDispatcherTarget ();
8542 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8543 kEventRemoveFromQueue
, &eventRef
))
8544 #else /* !USE_CARBON_EVENTS */
8545 while (mac_wait_next_event (&er
, 0, true))
8546 #endif /* !USE_CARBON_EVENTS */
8551 /* It is necessary to set this (additional) argument slot of an
8552 event to nil because keyboard.c protects incompletely
8553 processed event from being garbage collected by placing them
8554 in the kbd_buffer_gcpro vector. */
8556 inev
.kind
= NO_EVENT
;
8559 #if USE_CARBON_EVENTS
8560 /* Handle new events */
8561 if (!mac_convert_event_ref (eventRef
, &er
))
8562 switch (GetEventClass (eventRef
))
8564 case kEventClassWindow
:
8565 if (GetEventKind (eventRef
) == kEventWindowBoundsChanged
)
8567 WindowPtr window_ptr
;
8568 GetEventParameter(eventRef
, kEventParamDirectObject
,
8569 typeWindowRef
, NULL
, sizeof(WindowPtr
),
8571 f
= mac_window_to_frame (window_ptr
);
8572 if (f
&& !f
->async_iconified
)
8573 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8574 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8577 case kEventClassMouse
:
8578 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
8582 WindowPtr window_ptr
= front_emacs_window ();
8584 if (!IsValidWindowPtr (window_ptr
))
8590 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
8591 typeSInt32
, NULL
, sizeof (SInt32
),
8593 GetEventParameter(eventRef
, kEventParamMouseLocation
,
8594 typeQDPoint
, NULL
, sizeof (Point
),
8596 inev
.kind
= WHEEL_EVENT
;
8598 inev
.modifiers
= (mac_event_to_emacs_modifiers (eventRef
)
8599 | ((delta
< 0) ? down_modifier
8601 SetPortWindowPort (window_ptr
);
8602 GlobalToLocal (&point
);
8603 XSETINT (inev
.x
, point
.h
);
8604 XSETINT (inev
.y
, point
.v
);
8605 XSETFRAME (inev
.frame_or_window
,
8606 mac_window_to_frame (window_ptr
));
8607 inev
.timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
8610 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8615 /* Send the event to the appropriate receiver. */
8616 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8619 #endif /* USE_CARBON_EVENTS */
8625 WindowPtr window_ptr
;
8629 #if USE_CARBON_EVENTS
8630 /* This is needed to send mouse events like aqua window
8631 buttons to the correct handler. */
8632 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8633 != eventNotHandledErr
)
8637 if (dpyinfo
->grabbed
&& last_mouse_frame
8638 && FRAME_LIVE_P (last_mouse_frame
))
8640 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
8641 part_code
= inContent
;
8645 part_code
= FindWindow (er
.where
, &window_ptr
);
8646 if (tip_window
&& window_ptr
== tip_window
)
8648 HideWindow (tip_window
);
8649 part_code
= FindWindow (er
.where
, &window_ptr
);
8653 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
8659 f
= mac_window_to_frame (front_emacs_window ());
8660 saved_menu_event_location
= er
.where
;
8661 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
8662 XSETFRAME (inev
.frame_or_window
, f
);
8666 if (window_ptr
!= front_emacs_window ())
8667 SelectWindow (window_ptr
);
8670 SInt16 control_part_code
;
8672 Point mouse_loc
= er
.where
;
8674 f
= mac_window_to_frame (window_ptr
);
8675 /* convert to local coordinates of new window */
8676 SetPortWindowPort (window_ptr
);
8678 GlobalToLocal (&mouse_loc
);
8679 #if TARGET_API_MAC_CARBON
8680 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
8681 &control_part_code
);
8683 control_part_code
= FindControl (mouse_loc
, window_ptr
,
8687 #if USE_CARBON_EVENTS
8688 inev
.code
= mac_get_mouse_btn (eventRef
);
8689 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
8691 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
8692 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
8694 XSETINT (inev
.x
, mouse_loc
.h
);
8695 XSETINT (inev
.y
, mouse_loc
.v
);
8696 inev
.timestamp
= er
.when
* (1000 / 60);
8697 /* ticks to milliseconds */
8699 if (dpyinfo
->grabbed
&& tracked_scroll_bar
8700 #if TARGET_API_MAC_CARBON
8703 || control_part_code
!= 0
8707 struct scroll_bar
*bar
;
8709 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
8711 bar
= tracked_scroll_bar
;
8712 control_part_code
= kControlIndicatorPart
;
8715 bar
= (struct scroll_bar
*) GetControlReference (ch
);
8716 x_scroll_bar_handle_click (bar
, control_part_code
,
8718 if (er
.what
== mouseDown
8719 && control_part_code
== kControlIndicatorPart
)
8720 tracked_scroll_bar
= bar
;
8722 tracked_scroll_bar
= NULL
;
8727 int x
= mouse_loc
.h
;
8728 int y
= mouse_loc
.v
;
8730 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
8731 if (EQ (window
, f
->tool_bar_window
))
8733 if (er
.what
== mouseDown
)
8734 handle_tool_bar_click (f
, x
, y
, 1, 0);
8736 handle_tool_bar_click (f
, x
, y
, 0,
8742 XSETFRAME (inev
.frame_or_window
, f
);
8743 inev
.kind
= MOUSE_CLICK_EVENT
;
8747 if (er
.what
== mouseDown
)
8749 dpyinfo
->grabbed
|= (1 << inev
.code
);
8750 last_mouse_frame
= f
;
8751 /* Ignore any mouse motion that happened
8752 before this event; any subsequent
8753 mouse-movement Emacs events should reflect
8754 only motion after the ButtonPress. */
8759 last_tool_bar_item
= -1;
8763 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
8764 /* If a button is released though it was not
8765 previously pressed, that would be because
8766 of multi-button emulation. */
8767 dpyinfo
->grabbed
= 0;
8769 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
8775 inev
.modifiers
|= down_modifier
;
8778 inev
.modifiers
|= up_modifier
;
8785 #if TARGET_API_MAC_CARBON
8786 DragWindow (window_ptr
, er
.where
, NULL
);
8787 #else /* not TARGET_API_MAC_CARBON */
8788 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
8789 #endif /* not TARGET_API_MAC_CARBON */
8790 /* Update the frame parameters. */
8792 struct frame
*f
= mac_window_to_frame (window_ptr
);
8794 if (f
&& !f
->async_iconified
)
8795 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8800 if (TrackGoAway (window_ptr
, er
.where
))
8802 inev
.kind
= DELETE_WINDOW_EVENT
;
8803 XSETFRAME (inev
.frame_or_window
,
8804 mac_window_to_frame (window_ptr
));
8808 /* window resize handling added --ben */
8810 do_grow_window (window_ptr
, &er
);
8813 /* window zoom handling added --ben */
8816 if (TrackBox (window_ptr
, er
.where
, part_code
))
8817 do_zoom_window (window_ptr
, part_code
);
8827 #if USE_CARBON_EVENTS
8828 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8829 != eventNotHandledErr
)
8832 do_window_update ((WindowPtr
) er
.message
);
8837 #if USE_CARBON_EVENTS
8838 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8839 != eventNotHandledErr
)
8842 switch ((er
.message
>> 24) & 0x000000FF)
8844 case suspendResumeMessage
:
8845 if ((er
.message
& resumeFlag
) == 1)
8851 case mouseMovedMessage
:
8852 #if !USE_CARBON_EVENTS
8853 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
8854 er
.where
.h
+ 1, er
.where
.v
+ 1);
8856 previous_help_echo_string
= help_echo_string
;
8857 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
8860 do_mouse_moved (er
.where
, &f
);
8862 /* If the contents of the global variable
8863 help_echo_string has changed, generate a
8865 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
8873 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
8875 #if USE_CARBON_EVENTS
8876 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8877 != eventNotHandledErr
)
8880 if (window_ptr
== tip_window
)
8882 HideWindow (tip_window
);
8886 if (!is_emacs_window (window_ptr
))
8889 f
= mac_window_to_frame (window_ptr
);
8891 if ((er
.modifiers
& activeFlag
) != 0)
8893 /* A window has been activated */
8894 Point mouse_loc
= er
.where
;
8896 x_new_focus_frame (dpyinfo
, f
);
8897 activate_scroll_bars (f
);
8899 SetPortWindowPort (window_ptr
);
8900 GlobalToLocal (&mouse_loc
);
8901 /* Window-activated event counts as mouse movement,
8902 so update things that depend on mouse position. */
8903 note_mouse_movement (mac_window_to_frame (window_ptr
),
8908 /* A window has been deactivated */
8909 dpyinfo
->grabbed
= 0;
8911 if (f
== dpyinfo
->x_focus_frame
)
8913 x_new_focus_frame (dpyinfo
, 0);
8914 deactivate_scroll_bars (f
);
8918 if (f
== dpyinfo
->mouse_face_mouse_frame
)
8920 /* If we move outside the frame, then we're
8921 certainly no longer on any text in the
8923 clear_mouse_face (dpyinfo
);
8924 dpyinfo
->mouse_face_mouse_frame
= 0;
8927 /* Generate a nil HELP_EVENT to cancel a help-echo.
8928 Do it only if there's something to cancel.
8929 Otherwise, the startup message is cleared when the
8930 mouse leaves the frame. */
8931 if (any_help_event_p
)
8940 int keycode
= (er
.message
& keyCodeMask
) >> 8;
8943 #if USE_CARBON_EVENTS
8944 /* When using Carbon Events, we need to pass raw keyboard
8945 events to the TSM ourselves. If TSM handles it, it
8946 will pass back noErr, otherwise it will pass back
8947 "eventNotHandledErr" and we can process it
8949 if ((!NILP (Vmac_pass_command_to_system
)
8950 || !(er
.modifiers
& cmdKey
))
8951 && (!NILP (Vmac_pass_control_to_system
)
8952 || !(er
.modifiers
& controlKey
)))
8953 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8954 != eventNotHandledErr
)
8958 #if TARGET_API_MAC_CARBON
8959 if (!IsValidWindowPtr (front_emacs_window ()))
8968 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
8970 clear_mouse_face (dpyinfo
);
8971 dpyinfo
->mouse_face_hidden
= 1;
8974 if (keycode_to_xkeysym (keycode
, &xkeysym
))
8976 inev
.code
= 0xff00 | xkeysym
;
8977 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
8981 if (er
.modifiers
& (controlKey
|
8982 (NILP (Vmac_command_key_is_meta
) ? optionKey
8985 /* This code comes from Keyboard Resource,
8986 Appendix C of IM - Text. This is necessary
8987 since shift is ignored in KCHR table
8988 translation when option or command is pressed.
8989 It also does not translate correctly
8990 control-shift chars like C-% so mask off shift
8992 int new_modifiers
= er
.modifiers
& 0xe600;
8993 /* mask off option and command */
8994 int new_keycode
= keycode
| new_modifiers
;
8995 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
8996 unsigned long some_state
= 0;
8997 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
8998 &some_state
) & 0xff;
8999 } else if (!NILP(Vmac_option_modifier
) && (er
.modifiers
& optionKey
))
9001 /* When using the option key as an emacs modifier, convert
9002 the pressed key code back to one without the Mac option
9003 modifier applied. */
9004 int new_modifiers
= er
.modifiers
& ~optionKey
;
9005 int new_keycode
= keycode
| new_modifiers
;
9006 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9007 unsigned long some_state
= 0;
9008 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9009 &some_state
) & 0xff;
9012 inev
.code
= er
.message
& charCodeMask
;
9013 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9017 /* If variable mac-convert-keyboard-input-to-latin-1 is
9018 non-nil, convert non-ASCII characters typed at the Mac
9019 keyboard (presumed to be in the Mac Roman encoding) to
9020 iso-latin-1 encoding before they are passed to Emacs.
9021 This enables the Mac keyboard to be used to enter
9022 non-ASCII iso-latin-1 characters directly. */
9023 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
9024 && inev
.kind
== ASCII_KEYSTROKE_EVENT
&& inev
.code
>= 128)
9026 static TECObjectRef converter
= NULL
;
9027 OSStatus the_err
= noErr
;
9028 OSStatus convert_status
= noErr
;
9030 if (converter
== NULL
)
9032 the_err
= TECCreateConverter (&converter
,
9033 kTextEncodingMacRoman
,
9034 mac_keyboard_text_encoding
);
9035 current_mac_keyboard_text_encoding
9036 = mac_keyboard_text_encoding
;
9038 else if (mac_keyboard_text_encoding
9039 != current_mac_keyboard_text_encoding
)
9041 /* Free the converter for the current encoding
9042 before creating a new one. */
9043 TECDisposeConverter (converter
);
9044 the_err
= TECCreateConverter (&converter
,
9045 kTextEncodingMacRoman
,
9046 mac_keyboard_text_encoding
);
9047 current_mac_keyboard_text_encoding
9048 = mac_keyboard_text_encoding
;
9051 if (the_err
== noErr
)
9053 unsigned char ch
= inev
.code
;
9054 ByteCount actual_input_length
, actual_output_length
;
9055 unsigned char outbuf
[32];
9057 convert_status
= TECConvertText (converter
, &ch
, 1,
9058 &actual_input_length
,
9060 &actual_output_length
);
9061 if (convert_status
== noErr
9062 && actual_input_length
== 1
9063 && actual_output_length
== 1)
9064 inev
.code
= *outbuf
;
9066 /* Reset internal states of the converter object.
9067 If it fails, create another one. */
9068 convert_status
= TECFlushText (converter
, outbuf
,
9070 &actual_output_length
);
9071 if (convert_status
!= noErr
)
9073 TECDisposeConverter (converter
);
9074 TECCreateConverter (&converter
,
9075 kTextEncodingMacRoman
,
9076 mac_keyboard_text_encoding
);
9081 #if USE_CARBON_EVENTS
9082 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9084 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9086 XSETFRAME (inev
.frame_or_window
,
9087 mac_window_to_frame (front_emacs_window ()));
9088 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9091 case kHighLevelEvent
:
9092 drag_and_drop_file_list
= Qnil
;
9094 AEProcessAppleEvent(&er
);
9096 /* Build a DRAG_N_DROP_EVENT type event as is done in
9097 constuct_drag_n_drop in w32term.c. */
9098 if (!NILP (drag_and_drop_file_list
))
9100 struct frame
*f
= NULL
;
9104 wp
= front_emacs_window ();
9108 struct frame
*f
= XFRAME (XCAR (Vframe_list
));
9109 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
9110 wp
= front_emacs_window ();
9114 f
= mac_window_to_frame (wp
);
9116 inev
.kind
= DRAG_N_DROP_EVENT
;
9118 inev
.timestamp
= er
.when
* (1000 / 60);
9119 /* ticks to milliseconds */
9120 #if USE_CARBON_EVENTS
9121 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9123 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9126 XSETINT (inev
.x
, 0);
9127 XSETINT (inev
.y
, 0);
9129 XSETFRAME (frame
, f
);
9130 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9132 /* Regardless of whether Emacs was suspended or in the
9133 foreground, ask it to redraw its entire screen.
9134 Otherwise parts of the screen can be left in an
9135 inconsistent state. */
9137 #if TARGET_API_MAC_CARBON
9141 GetWindowPortBounds (wp
, &r
);
9142 InvalWindowRect (wp
, &r
);
9144 #else /* not TARGET_API_MAC_CARBON */
9145 InvalRect (&(wp
->portRect
));
9146 #endif /* not TARGET_API_MAC_CARBON */
9151 #if USE_CARBON_EVENTS
9152 ReleaseEvent (eventRef
);
9155 if (inev
.kind
!= NO_EVENT
)
9157 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9162 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9167 XSETFRAME (frame
, f
);
9173 any_help_event_p
= 1;
9174 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9175 help_echo_object
, help_echo_pos
);
9179 help_echo_string
= Qnil
;
9180 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9187 /* If the focus was just given to an autoraising frame,
9189 /* ??? This ought to be able to handle more than one such frame. */
9190 if (pending_autoraise_frame
)
9192 x_raise_frame (pending_autoraise_frame
);
9193 pending_autoraise_frame
= 0;
9196 #if !TARGET_API_MAC_CARBON
9197 check_alarm (); /* simulate the handling of a SIGALRM */
9205 /* Need to override CodeWarrior's input function so no conversion is
9206 done on newlines Otherwise compiled functions in .elc files will be
9207 read incorrectly. Defined in ...:MSL C:MSL
9208 Common:Source:buffer_io.c. */
9211 __convert_to_newlines (unsigned char * p
, size_t * n
)
9217 __convert_from_newlines (unsigned char * p
, size_t * n
)
9225 make_mac_terminal_frame (struct frame
*f
)
9230 XSETFRAME (frame
, f
);
9232 f
->output_method
= output_mac
;
9233 f
->output_data
.mac
= (struct mac_output
*)
9234 xmalloc (sizeof (struct mac_output
));
9235 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9237 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9239 FRAME_COLS (f
) = 96;
9240 FRAME_LINES (f
) = 4;
9242 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9243 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9245 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9247 f
->output_data
.mac
->cursor_pixel
= 0;
9248 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9249 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9250 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9252 f
->output_data
.mac
->text_cursor
= GetCursor (iBeamCursor
);
9253 f
->output_data
.mac
->nontext_cursor
= &arrow_cursor
;
9254 f
->output_data
.mac
->modeline_cursor
= &arrow_cursor
;
9255 f
->output_data
.mac
->hand_cursor
= &arrow_cursor
;
9256 f
->output_data
.mac
->hourglass_cursor
= GetCursor (watchCursor
);
9257 f
->output_data
.mac
->horizontal_drag_cursor
= &arrow_cursor
;
9259 FRAME_FONTSET (f
) = -1;
9260 f
->output_data
.mac
->explicit_parent
= 0;
9263 f
->border_width
= 0;
9265 f
->internal_border_width
= 0;
9270 f
->new_text_cols
= 0;
9271 f
->new_text_lines
= 0;
9273 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9274 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9275 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9279 if (!(FRAME_MAC_WINDOW (f
) =
9280 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9281 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9283 /* so that update events can find this mac_output struct */
9284 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9290 /* Need to be initialized for unshow_buffer in window.c. */
9291 selected_window
= f
->selected_window
;
9293 Fmodify_frame_parameters (frame
,
9294 Fcons (Fcons (Qfont
,
9295 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9296 Fmodify_frame_parameters (frame
,
9297 Fcons (Fcons (Qforeground_color
,
9298 build_string ("black")), Qnil
));
9299 Fmodify_frame_parameters (frame
,
9300 Fcons (Fcons (Qbackground_color
,
9301 build_string ("white")), Qnil
));
9306 /***********************************************************************
9308 ***********************************************************************/
9310 int mac_initialized
= 0;
9313 mac_initialize_display_info ()
9315 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9316 GDHandle main_device_handle
;
9318 bzero (dpyinfo
, sizeof (*dpyinfo
));
9321 dpyinfo
->mac_id_name
9322 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9323 + SCHARS (Vsystem_name
)
9325 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9326 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9328 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9329 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9332 main_device_handle
= LMGetMainDevice();
9334 dpyinfo
->reference_count
= 0;
9335 dpyinfo
->resx
= 75.0;
9336 dpyinfo
->resy
= 75.0;
9337 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9339 /* HasDepth returns true if it is possible to have a 32 bit display,
9340 but this may not be what is actually used. Mac OSX can do better.
9341 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9342 header for CGGetActiveDisplayList says that the first display returned
9343 is the active one, so we use that. */
9345 CGDirectDisplayID disp_id
[1];
9346 CGDisplayCount disp_count
;
9347 CGDisplayErr error_code
;
9349 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
9350 if (error_code
!= 0)
9351 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
9353 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
9356 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
9357 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
9358 gdDevType
, dpyinfo
->color_p
))
9361 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
9362 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
9363 dpyinfo
->grabbed
= 0;
9364 dpyinfo
->root_window
= NULL
;
9365 dpyinfo
->image_cache
= make_image_cache ();
9367 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9368 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9369 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9370 dpyinfo
->mouse_face_window
= Qnil
;
9371 dpyinfo
->mouse_face_overlay
= Qnil
;
9372 dpyinfo
->mouse_face_hidden
= 0;
9375 /* Create an xrdb-style database of resources to supercede registry settings.
9376 The database is just a concatenation of C strings, finished by an additional
9377 \0. The string are submitted to some basic normalization, so
9379 [ *]option[ *]:[ *]value...
9385 but any whitespace following value is not removed. */
9388 mac_make_rdb (xrm_option
)
9391 char *buffer
= xmalloc (strlen (xrm_option
) + 2);
9392 char *current
= buffer
;
9395 int before_value
= 0;
9409 if (in_option
&& (ch
== ':'))
9414 else if (before_value
)
9419 else if (!(in_option
|| before_value
))
9430 struct mac_display_info
*
9431 mac_term_init (display_name
, xrm_option
, resource_name
)
9432 Lisp_Object display_name
;
9434 char *resource_name
;
9436 struct mac_display_info
*dpyinfo
;
9440 if (!mac_initialized
)
9443 mac_initialized
= 1;
9447 error ("Sorry, this version can only handle one display");
9449 mac_initialize_display_info ();
9451 dpyinfo
= &one_mac_display_info
;
9453 dpyinfo
->xrdb
= xrm_option
? mac_make_rdb (xrm_option
) : NULL
;
9455 /* Put this display on the chain. */
9456 dpyinfo
->next
= x_display_list
;
9457 x_display_list
= dpyinfo
;
9459 /* Put it on x_display_name_list. */
9460 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
9461 x_display_name_list
);
9462 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9468 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9471 x_delete_display (dpyinfo
)
9472 struct mac_display_info
*dpyinfo
;
9476 /* Discard this display from x_display_name_list and x_display_list.
9477 We can't use Fdelq because that can quit. */
9478 if (! NILP (x_display_name_list
)
9479 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9480 x_display_name_list
= XCDR (x_display_name_list
);
9485 tail
= x_display_name_list
;
9486 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9488 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9490 XSETCDR (tail
, XCDR (XCDR (tail
)));
9497 if (x_display_list
== dpyinfo
)
9498 x_display_list
= dpyinfo
->next
;
9501 struct x_display_info
*tail
;
9503 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9504 if (tail
->next
== dpyinfo
)
9505 tail
->next
= tail
->next
->next
;
9508 /* Free the font names in the font table. */
9509 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9510 if (dpyinfo
->font_table
[i
].name
)
9512 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9513 xfree (dpyinfo
->font_table
[i
].full_name
);
9514 xfree (dpyinfo
->font_table
[i
].name
);
9517 if (dpyinfo
->font_table
->font_encoder
)
9518 xfree (dpyinfo
->font_table
->font_encoder
);
9520 xfree (dpyinfo
->font_table
);
9521 xfree (dpyinfo
->mac_id_name
);
9523 if (x_display_list
== 0)
9525 mac_clear_font_name_table ();
9526 bzero (dpyinfo
, sizeof (*dpyinfo
));
9535 extern int inhibit_window_system
;
9536 extern int noninteractive
;
9537 CFBundleRef appsBundle
;
9540 /* No need to test if already -nw*/
9541 if (inhibit_window_system
|| noninteractive
)
9544 appsBundle
= CFBundleGetMainBundle();
9545 if (appsBundle
!= NULL
)
9547 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
9548 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
9549 /* We found the bundle identifier, now we know we are valid. */
9556 /* MAC_TODO: Have this start the bundled executable */
9558 /* For now, prevent the fatal error by bringing it up in the terminal */
9559 inhibit_window_system
= 1;
9563 MakeMeTheFrontProcess ()
9565 ProcessSerialNumber psn
;
9568 err
= GetCurrentProcess (&psn
);
9570 (void) SetFrontProcess (&psn
);
9573 /***** Code to handle C-g testing *****/
9575 /* Contains the Mac modifier formed from quit_char */
9576 static mac_quit_char_modifiers
= 0;
9577 static mac_quit_char_keycode
;
9578 extern int quit_char
;
9581 mac_determine_quit_char_modifiers()
9583 /* Todo: Determine modifiers from quit_char. */
9584 UInt32 qc_modifiers
= ctrl_modifier
;
9587 mac_quit_char_modifiers
= 0;
9588 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
9589 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
9590 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
9591 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
9595 init_quit_char_handler ()
9597 /* TODO: Let this support keys other the 'g' */
9598 mac_quit_char_keycode
= 5;
9599 /* Look at <architecture/adb_kb_map.h> for details */
9600 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9602 mac_determine_quit_char_modifiers();
9606 quit_char_comp (EventRef inEvent
, void *inCompData
)
9608 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
9610 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
9614 UInt32 keyModifiers
;
9615 GetEventParameter(inEvent
, kEventParamKeyCode
,
9616 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
9617 if (keyCode
!= mac_quit_char_keycode
)
9619 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
9620 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
9621 if (keyModifiers
!= mac_quit_char_modifiers
)
9628 mac_check_for_quit_char ()
9631 static EMACS_TIME last_check_time
= { 0, 0 };
9632 static EMACS_TIME one_second
= { 1, 0 };
9635 /* If windows are not initialized, return immediately (keep it bouncin'). */
9636 if (!mac_quit_char_modifiers
)
9639 /* Don't check if last check is less than a second ago. */
9640 EMACS_GET_TIME (now
);
9641 EMACS_SUB_TIME (t
, now
, last_check_time
);
9642 if (EMACS_TIME_LT (t
, one_second
))
9644 last_check_time
= now
;
9646 /* Redetermine modifiers because they are based on lisp variables */
9647 mac_determine_quit_char_modifiers ();
9649 /* Fill the queue with events */
9651 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
9652 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
9657 struct input_event e
;
9659 /* Use an input_event to emulate what the interrupt handler does. */
9661 e
.kind
= ASCII_KEYSTROKE_EVENT
;
9665 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
9666 XSETFRAME (e
.frame_or_window
, mac_window_to_frame (front_emacs_window ()));
9667 /* Remove event from queue to prevent looping. */
9668 RemoveEventFromQueue (GetMainEventQueue (), event
);
9669 ReleaseEvent (event
);
9670 kbd_buffer_store_event (&e
);
9674 #endif /* MAC_OSX */
9676 /* Set up use of X before we make the first connection. */
9678 extern frame_parm_handler mac_frame_parm_handlers
[];
9680 static struct redisplay_interface x_redisplay_interface
=
9682 mac_frame_parm_handlers
,
9686 x_clear_end_of_line
,
9688 x_after_update_window_line
,
9689 x_update_window_begin
,
9690 x_update_window_end
,
9693 0, /* flush_display_optional */
9694 x_clear_window_mouse_face
,
9695 x_get_glyph_overhangs
,
9696 x_fix_overlapping_area
,
9697 x_draw_fringe_bitmap
,
9698 0, /* define_fringe_bitmap */
9699 0, /* destroy_fringe_bitmap */
9700 mac_per_char_metric
,
9702 NULL
, /* mac_compute_glyph_string_overhangs */
9703 x_draw_glyph_string
,
9704 mac_define_frame_cursor
,
9705 mac_clear_frame_area
,
9706 mac_draw_window_cursor
,
9707 mac_draw_vertical_window_border
,
9708 mac_shift_glyphs_for_insert
9714 rif
= &x_redisplay_interface
;
9716 clear_frame_hook
= x_clear_frame
;
9717 ins_del_lines_hook
= x_ins_del_lines
;
9718 delete_glyphs_hook
= x_delete_glyphs
;
9719 ring_bell_hook
= XTring_bell
;
9720 reset_terminal_modes_hook
= XTreset_terminal_modes
;
9721 set_terminal_modes_hook
= XTset_terminal_modes
;
9722 update_begin_hook
= x_update_begin
;
9723 update_end_hook
= x_update_end
;
9724 set_terminal_window_hook
= XTset_terminal_window
;
9725 read_socket_hook
= XTread_socket
;
9726 frame_up_to_date_hook
= XTframe_up_to_date
;
9727 mouse_position_hook
= XTmouse_position
;
9728 frame_rehighlight_hook
= XTframe_rehighlight
;
9729 frame_raise_lower_hook
= XTframe_raise_lower
;
9731 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
9732 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
9733 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
9734 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
9736 scroll_region_ok
= 1; /* we'll scroll partial frames */
9737 char_ins_del_ok
= 1;
9738 line_ins_del_ok
= 1; /* we'll just blt 'em */
9739 fast_clear_end_of_line
= 1; /* X does this well */
9740 memory_below_frame
= 0; /* we don't remember what scrolls
9745 last_tool_bar_item
= -1;
9746 any_help_event_p
= 0;
9748 /* Try to use interrupt input; if we can't, then start polling. */
9749 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
9751 #ifdef USE_X_TOOLKIT
9752 XtToolkitInitialize ();
9753 Xt_app_con
= XtCreateApplicationContext ();
9754 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
9756 /* Install an asynchronous timer that processes Xt timeout events
9757 every 0.1s. This is necessary because some widget sets use
9758 timeouts internally, for example the LessTif menu bar, or the
9759 Xaw3d scroll bar. When Xt timouts aren't processed, these
9760 widgets don't behave normally. */
9762 EMACS_TIME interval
;
9763 EMACS_SET_SECS_USECS (interval
, 0, 100000);
9764 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
9768 #if USE_TOOLKIT_SCROLL_BARS
9769 xaw3d_arrow_scroll
= False
;
9770 xaw3d_pick_top
= True
;
9774 /* Note that there is no real way portable across R3/R4 to get the
9775 original error handler. */
9776 XSetErrorHandler (x_error_handler
);
9777 XSetIOErrorHandler (x_io_error_quitter
);
9779 /* Disable Window Change signals; they are handled by X events. */
9781 signal (SIGWINCH
, SIG_DFL
);
9782 #endif /* ! defined (SIGWINCH) */
9784 signal (SIGPIPE
, x_connection_signal
);
9789 #if TARGET_API_MAC_CARBON
9790 init_required_apple_events ();
9792 #if USE_CARBON_EVENTS
9793 init_service_handler ();
9795 init_quit_char_handler ();
9798 DisableMenuCommand (NULL
, kHICommandQuit
);
9800 if (!inhibit_window_system
)
9801 MakeMeTheFrontProcess ();
9811 staticpro (&x_error_message_string
);
9812 x_error_message_string
= Qnil
;
9815 Qmodifier_value
= intern ("modifier-value");
9816 Qalt
= intern ("alt");
9817 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
9818 Qhyper
= intern ("hyper");
9819 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
9820 Qsuper
= intern ("super");
9821 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
9824 Fprovide (intern ("mac-carbon"), Qnil
);
9827 staticpro (&Qreverse
);
9828 Qreverse
= intern ("reverse");
9830 staticpro (&x_display_name_list
);
9831 x_display_name_list
= Qnil
;
9833 staticpro (&last_mouse_scroll_bar
);
9834 last_mouse_scroll_bar
= Qnil
;
9836 staticpro (&Qvendor_specific_keysyms
);
9837 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
9839 staticpro (&last_mouse_press_frame
);
9840 last_mouse_press_frame
= Qnil
;
9842 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
9843 staticpro (&Qmac_ready_for_drag_n_drop
);
9845 Qbig5
= intern ("big5");
9848 Qcn_gb
= intern ("cn-gb");
9849 staticpro (&Qcn_gb
);
9851 Qsjis
= intern ("sjis");
9854 Qeuc_kr
= intern ("euc-kr");
9855 staticpro (&Qeuc_kr
);
9857 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
9858 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
9859 x_autoselect_window_p
= 0;
9861 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
9862 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
9863 Vx_toolkit_scroll_bars
= Qt
;
9865 DEFVAR_BOOL ("x-use-underline-position-properties",
9866 &x_use_underline_position_properties
,
9867 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9868 nil means ignore them. If you encounter fonts with bogus
9869 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9870 to 4.1, set this to nil. */);
9871 x_use_underline_position_properties
= 0;
9873 staticpro (&last_mouse_motion_frame
);
9874 last_mouse_motion_frame
= Qnil
;
9876 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
9877 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
9878 Otherwise the option key is used. */);
9879 Vmac_command_key_is_meta
= Qt
;
9881 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
9882 doc
: /* Modifier to use for the Mac alt/option key. The value can
9883 be alt, hyper, or super for the respective modifier. If the value is
9884 nil then the key will act as the normal Mac option modifier. */);
9885 Vmac_option_modifier
= Qnil
;
9887 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
9888 doc
: /* Non-nil means that the control and meta keys are reversed. This is
9889 useful for non-standard keyboard layouts. */);
9890 Vmac_reverse_ctrl_meta
= Qnil
;
9892 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9893 &Vmac_emulate_three_button_mouse
,
9894 doc
: /* t means that when the option-key is held down while pressing the
9895 mouse button, the click will register as mouse-2 and while the
9896 command-key is held down, the click will register as mouse-3.
9897 'reverse means that the the option-key will register for mouse-3
9898 and the command-key will register for mouse-2. nil means that
9899 not emulation should be done and the modifiers should be placed
9900 on the mouse-1 event. */);
9901 Vmac_emulate_three_button_mouse
= Qnil
;
9903 #if USE_CARBON_EVENTS
9904 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
9905 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
9906 the right click will be mouse-3.
9907 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9908 Vmac_wheel_button_is_mouse_2
= Qt
;
9910 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
9911 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9912 Toolbox for processing before Emacs sees it. */);
9913 Vmac_pass_command_to_system
= Qt
;
9915 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9916 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9917 Toolbox for processing before Emacs sees it. */);
9918 Vmac_pass_control_to_system
= Qt
;
9920 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9921 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9922 Toolbox for processing before Emacs sees it. */);
9923 Vmac_pass_control_to_system
= Qt
;
9926 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
9927 doc
: /* If non-nil, allow anti-aliasing.
9928 The text will be rendered using Core Graphics text rendering which
9929 may anti-alias the text. */);
9930 Vmac_use_core_graphics
= Qnil
;
9932 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
9933 doc
: /* One of the Text Encoding Base constant values defined in the
9934 Basic Text Constants section of Inside Macintosh - Text Encoding
9935 Conversion Manager. Its value determines the encoding characters
9936 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9937 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9938 its default value, no conversion takes place. If it is set to
9939 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9940 characters typed on Mac keyboard are first converted into the
9941 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9942 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9943 command, this enables the Mac keyboard to be used to enter non-ASCII
9944 characters directly. */);
9945 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
9948 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9949 (do not change this comment) */