1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
29 #include "blockinput.h"
37 #if TARGET_API_MAC_CARBON
38 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
39 obtain events from the event queue. If set to 0, WaitNextEvent is
41 #define USE_CARBON_EVENTS 1
42 #else /* not TARGET_API_MAC_CARBON */
43 #include <Quickdraw.h>
44 #include <ToolUtils.h>
48 #include <Resources.h>
50 #include <TextUtils.h>
54 #if defined (__MRC__) || (__MSL__ >= 0x6000)
55 #include <ControlDefinitions.h>
61 #endif /* not TARGET_API_MAC_CARBON */
72 #include <sys/param.h>
76 #include "dispextern.h"
78 #include "termhooks.h"
85 #include "intervals.h"
86 #include "composite.h"
89 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
90 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
91 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
92 #define macShiftKey (shiftKey)
93 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
94 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
96 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
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
;
248 #if __MRC__ && !TARGET_API_MAC_CARBON
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 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
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 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
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 MacFontStruct
*font
= s
->font
;
1997 TextFont (font
->mac_fontnum
);
1998 TextSize (font
->mac_fontsize
);
1999 TextFace (font
->mac_fontface
);
2002 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2006 char *buf
= xmalloc (s
->nchars
);
2009 SetRect (&r
, 0, 0, 0, 0);
2012 for (i
= 0; i
< s
->nchars
; ++i
)
2013 buf
[i
] = s
->char2b
[i
].byte2
;
2014 QDTextBounds (s
->nchars
, buf
, &r
);
2019 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2020 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2024 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2027 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2028 struct glyph_string
*s
;
2033 xgcv
.foreground
= s
->gc
->background
;
2034 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2038 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2039 on Mac OS X because:
2040 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2041 into an offscreen graphics world first. So performance gain
2042 cannot be expected.)
2043 - It lowers rendering quality.
2044 - Some fonts leave garbage on cursor movement. */
2046 /* Draw the background of glyph_string S. If S->background_filled_p
2047 is non-zero don't draw it. FORCE_P non-zero means draw the
2048 background even if it wouldn't be drawn normally. This is used
2049 when a string preceding S draws into the background of S, or S
2050 contains the first component of a composition. */
2053 x_draw_glyph_string_background (s
, force_p
)
2054 struct glyph_string
*s
;
2057 /* Nothing to do if background has already been drawn or if it
2058 shouldn't be drawn in the first place. */
2059 if (!s
->background_filled_p
)
2061 int box_line_width
= max (s
->face
->box_line_width
, 0);
2063 #if 0 /* MAC_TODO: stipple */
2066 /* Fill background with a stipple pattern. */
2067 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2068 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2069 s
->y
+ box_line_width
,
2070 s
->background_width
,
2071 s
->height
- 2 * box_line_width
);
2072 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2073 s
->background_filled_p
= 1;
2078 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2079 || s
->font_not_found_p
2080 || s
->extends_to_end_of_line_p
2084 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2085 s
->background_width
,
2086 s
->height
- 2 * box_line_width
);
2087 s
->background_filled_p
= 1;
2093 /* Draw the foreground of glyph string S. */
2096 x_draw_glyph_string_foreground (s
)
2097 struct glyph_string
*s
;
2101 /* If first glyph of S has a left box line, start drawing the text
2102 of S to the right of that box line. */
2103 if (s
->face
->box
!= FACE_NO_BOX
2104 && s
->first_glyph
->left_box_line_p
)
2105 x
= s
->x
+ abs (s
->face
->box_line_width
);
2109 /* Draw characters of S as rectangles if S's font could not be
2111 if (s
->font_not_found_p
)
2113 for (i
= 0; i
< s
->nchars
; ++i
)
2115 struct glyph
*g
= s
->first_glyph
+ i
;
2116 mac_draw_rectangle (s
->display
, s
->window
,
2117 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2119 x
+= g
->pixel_width
;
2124 char *char1b
= (char *) s
->char2b
;
2125 int boff
= s
->font_info
->baseline_offset
;
2127 if (s
->font_info
->vertical_centering
)
2128 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2130 /* If we can use 8-bit functions, condense S->char2b. */
2132 for (i
= 0; i
< s
->nchars
; ++i
)
2133 char1b
[i
] = s
->char2b
[i
].byte2
;
2136 /* Draw text with XDrawString if background has already been
2137 filled. Otherwise, use XDrawImageString. (Note that
2138 XDrawImageString is usually faster than XDrawString.) Always
2139 use XDrawImageString when drawing the cursor so that there is
2140 no chance that characters under a box cursor are invisible. */
2141 if (s
->for_overlaps_p
2142 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2145 /* Draw characters with 16-bit or 8-bit functions. */
2147 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2148 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2150 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2151 s
->ybase
- boff
, char1b
, s
->nchars
);
2157 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2158 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2160 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2161 s
->ybase
- boff
, char1b
, s
->nchars
);
2167 /* Draw the foreground of composite glyph string S. */
2170 x_draw_composite_glyph_string_foreground (s
)
2171 struct glyph_string
*s
;
2175 /* If first glyph of S has a left box line, start drawing the text
2176 of S to the right of that box line. */
2177 if (s
->face
->box
!= FACE_NO_BOX
2178 && s
->first_glyph
->left_box_line_p
)
2179 x
= s
->x
+ abs (s
->face
->box_line_width
);
2183 /* S is a glyph string for a composition. S->gidx is the index of
2184 the first character drawn for glyphs of this composition.
2185 S->gidx == 0 means we are drawing the very first character of
2186 this composition. */
2188 /* Draw a rectangle for the composition if the font for the very
2189 first character of the composition could not be loaded. */
2190 if (s
->font_not_found_p
)
2193 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2194 s
->width
- 1, s
->height
- 1);
2198 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2199 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2200 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2201 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2207 #ifdef USE_X_TOOLKIT
2209 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2212 /* Return the frame on which widget WIDGET is used.. Abort if frame
2213 cannot be determined. */
2215 static struct frame
*
2216 x_frame_of_widget (widget
)
2219 struct x_display_info
*dpyinfo
;
2223 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2225 /* Find the top-level shell of the widget. Note that this function
2226 can be called when the widget is not yet realized, so XtWindow
2227 (widget) == 0. That's the reason we can't simply use
2228 x_any_window_to_frame. */
2229 while (!XtIsTopLevelShell (widget
))
2230 widget
= XtParent (widget
);
2232 /* Look for a frame with that top-level widget. Allocate the color
2233 on that frame to get the right gamma correction value. */
2234 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2235 if (GC_FRAMEP (XCAR (tail
))
2236 && (f
= XFRAME (XCAR (tail
)),
2237 (f
->output_data
.nothing
!= 1
2238 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2239 && f
->output_data
.x
->widget
== widget
)
2246 /* Allocate the color COLOR->pixel on the screen and display of
2247 widget WIDGET in colormap CMAP. If an exact match cannot be
2248 allocated, try the nearest color available. Value is non-zero
2249 if successful. This is called from lwlib. */
2252 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2257 struct frame
*f
= x_frame_of_widget (widget
);
2258 return x_alloc_nearest_color (f
, cmap
, color
);
2262 #endif /* USE_X_TOOLKIT */
2264 #if 0 /* MAC_TODO */
2266 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2267 CMAP. If an exact match can't be allocated, try the nearest color
2268 available. Value is non-zero if successful. Set *COLOR to the
2272 x_alloc_nearest_color (f
, cmap
, color
)
2277 Display
*display
= FRAME_X_DISPLAY (f
);
2278 Screen
*screen
= FRAME_X_SCREEN (f
);
2281 gamma_correct (f
, color
);
2282 rc
= XAllocColor (display
, cmap
, color
);
2285 /* If we got to this point, the colormap is full, so we're going
2286 to try to get the next closest color. The algorithm used is
2287 a least-squares matching, which is what X uses for closest
2288 color matching with StaticColor visuals. */
2290 unsigned long nearest_delta
= ~0;
2291 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2292 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2294 for (i
= 0; i
< ncells
; ++i
)
2296 XQueryColors (display
, cmap
, cells
, ncells
);
2298 for (nearest
= i
= 0; i
< ncells
; ++i
)
2300 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2301 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2302 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2303 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2305 if (delta
< nearest_delta
)
2308 nearest_delta
= delta
;
2312 color
->red
= cells
[nearest
].red
;
2313 color
->green
= cells
[nearest
].green
;
2314 color
->blue
= cells
[nearest
].blue
;
2315 rc
= XAllocColor (display
, cmap
, color
);
2318 #ifdef DEBUG_X_COLORS
2320 register_color (color
->pixel
);
2321 #endif /* DEBUG_X_COLORS */
2327 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2328 It's necessary to do this instead of just using PIXEL directly to
2329 get color reference counts right. */
2332 x_copy_color (f
, pixel
)
2334 unsigned long pixel
;
2338 color
.pixel
= pixel
;
2340 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2341 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2343 #ifdef DEBUG_X_COLORS
2344 register_color (pixel
);
2350 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2351 It's necessary to do this instead of just using PIXEL directly to
2352 get color reference counts right. */
2355 x_copy_dpy_color (dpy
, cmap
, pixel
)
2358 unsigned long pixel
;
2362 color
.pixel
= pixel
;
2364 XQueryColor (dpy
, cmap
, &color
);
2365 XAllocColor (dpy
, cmap
, &color
);
2367 #ifdef DEBUG_X_COLORS
2368 register_color (pixel
);
2373 #endif /* MAC_TODO */
2376 /* Brightness beyond which a color won't have its highlight brightness
2379 Nominally, highlight colors for `3d' faces are calculated by
2380 brightening an object's color by a constant scale factor, but this
2381 doesn't yield good results for dark colors, so for colors who's
2382 brightness is less than this value (on a scale of 0-255) have to
2383 use an additional additive factor.
2385 The value here is set so that the default menu-bar/mode-line color
2386 (grey75) will not have its highlights changed at all. */
2387 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2390 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2391 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2392 If this produces the same color as COLOR, try a color where all RGB
2393 values have DELTA added. Return the allocated color in *COLOR.
2394 DISPLAY is the X display, CMAP is the colormap to operate on.
2395 Value is non-zero if successful. */
2398 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2400 unsigned long *color
;
2407 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2410 /* Change RGB values by specified FACTOR. Avoid overflow! */
2411 xassert (factor
>= 0);
2412 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2413 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2414 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2416 /* Calculate brightness of COLOR. */
2417 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2418 + BLUE_FROM_ULONG (*color
)) / 6;
2420 /* We only boost colors that are darker than
2421 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2422 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2423 /* Make an additive adjustment to NEW, because it's dark enough so
2424 that scaling by FACTOR alone isn't enough. */
2426 /* How far below the limit this color is (0 - 1, 1 being darker). */
2427 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2428 /* The additive adjustment. */
2429 int min_delta
= delta
* dimness
* factor
/ 2;
2432 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2433 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2434 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2436 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2437 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2438 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2442 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2443 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2444 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2446 /* MAC_TODO: Map to palette and retry with delta if same? */
2447 /* MAC_TODO: Free colors (if using palette)? */
2458 /* Set up the foreground color for drawing relief lines of glyph
2459 string S. RELIEF is a pointer to a struct relief containing the GC
2460 with which lines will be drawn. Use a color that is FACTOR or
2461 DELTA lighter or darker than the relief's background which is found
2462 in S->f->output_data.x->relief_background. If such a color cannot
2463 be allocated, use DEFAULT_PIXEL, instead. */
2466 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2468 struct relief
*relief
;
2471 unsigned long default_pixel
;
2474 struct mac_output
*di
= f
->output_data
.mac
;
2475 unsigned long mask
= GCForeground
;
2476 unsigned long pixel
;
2477 unsigned long background
= di
->relief_background
;
2478 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2480 /* MAC_TODO: Free colors (if using palette)? */
2482 /* Allocate new color. */
2483 xgcv
.foreground
= default_pixel
;
2485 if (dpyinfo
->n_planes
!= 1
2486 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2488 relief
->allocated_p
= 1;
2489 xgcv
.foreground
= relief
->pixel
= pixel
;
2492 if (relief
->gc
== 0)
2494 #if 0 /* MAC_TODO: stipple */
2495 xgcv
.stipple
= dpyinfo
->gray
;
2498 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2501 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2505 /* Set up colors for the relief lines around glyph string S. */
2508 x_setup_relief_colors (s
)
2509 struct glyph_string
*s
;
2511 struct mac_output
*di
= s
->f
->output_data
.mac
;
2512 unsigned long color
;
2514 if (s
->face
->use_box_color_for_shadows_p
)
2515 color
= s
->face
->box_color
;
2516 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2518 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2519 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2524 /* Get the background color of the face. */
2525 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2526 color
= xgcv
.background
;
2529 if (di
->white_relief
.gc
== 0
2530 || color
!= di
->relief_background
)
2532 di
->relief_background
= color
;
2533 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2534 WHITE_PIX_DEFAULT (s
->f
));
2535 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2536 BLACK_PIX_DEFAULT (s
->f
));
2541 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2542 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2543 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2544 relief. LEFT_P non-zero means draw a relief on the left side of
2545 the rectangle. RIGHT_P non-zero means draw a relief on the right
2546 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2550 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2551 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2553 int left_x
, top_y
, right_x
, bottom_y
, width
;
2554 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2557 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2558 Window window
= FRAME_MAC_WINDOW (f
);
2563 gc
= f
->output_data
.mac
->white_relief
.gc
;
2565 gc
= f
->output_data
.mac
->black_relief
.gc
;
2566 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2570 for (i
= 0; i
< width
; ++i
)
2571 XDrawLine (dpy
, window
, gc
,
2572 left_x
+ i
* left_p
, top_y
+ i
,
2573 right_x
- i
* right_p
, top_y
+ i
);
2577 for (i
= 0; i
< width
; ++i
)
2578 XDrawLine (dpy
, window
, gc
,
2579 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2581 mac_reset_clipping (dpy
, window
);
2583 gc
= f
->output_data
.mac
->black_relief
.gc
;
2585 gc
= f
->output_data
.mac
->white_relief
.gc
;
2586 mac_set_clip_rectangle (dpy
, window
,
2591 for (i
= 0; i
< width
; ++i
)
2592 XDrawLine (dpy
, window
, gc
,
2593 left_x
+ i
* left_p
, bottom_y
- i
,
2594 right_x
- i
* right_p
, bottom_y
- i
);
2598 for (i
= 0; i
< width
; ++i
)
2599 XDrawLine (dpy
, window
, gc
,
2600 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2602 mac_reset_clipping (dpy
, window
);
2606 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2607 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2608 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2609 left side of the rectangle. RIGHT_P non-zero means draw a line
2610 on the right side of the rectangle. CLIP_RECT is the clipping
2611 rectangle to use when drawing. */
2614 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2615 left_p
, right_p
, clip_rect
)
2616 struct glyph_string
*s
;
2617 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2622 xgcv
.foreground
= s
->face
->box_color
;
2623 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2626 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2627 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2631 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2632 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2635 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2636 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2640 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2641 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2643 mac_reset_clipping (s
->display
, s
->window
);
2647 /* Draw a box around glyph string S. */
2650 x_draw_glyph_string_box (s
)
2651 struct glyph_string
*s
;
2653 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2654 int left_p
, right_p
;
2655 struct glyph
*last_glyph
;
2658 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2659 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2660 : window_box_right (s
->w
, s
->area
));
2662 /* The glyph that may have a right box line. */
2663 last_glyph
= (s
->cmp
|| s
->img
2665 : s
->first_glyph
+ s
->nchars
- 1);
2667 width
= abs (s
->face
->box_line_width
);
2668 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2670 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2672 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2674 bottom_y
= top_y
+ s
->height
- 1;
2676 left_p
= (s
->first_glyph
->left_box_line_p
2677 || (s
->hl
== DRAW_MOUSE_FACE
2679 || s
->prev
->hl
!= s
->hl
)));
2680 right_p
= (last_glyph
->right_box_line_p
2681 || (s
->hl
== DRAW_MOUSE_FACE
2683 || s
->next
->hl
!= s
->hl
)));
2685 get_glyph_string_clip_rect (s
, &clip_rect
);
2687 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2688 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2689 left_p
, right_p
, &clip_rect
);
2692 x_setup_relief_colors (s
);
2693 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2694 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2699 /* Draw foreground of image glyph string S. */
2702 x_draw_image_foreground (s
)
2703 struct glyph_string
*s
;
2706 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2708 /* If first glyph of S has a left box line, start drawing it to the
2709 right of that line. */
2710 if (s
->face
->box
!= FACE_NO_BOX
2711 && s
->first_glyph
->left_box_line_p
2713 x
+= abs (s
->face
->box_line_width
);
2715 /* If there is a margin around the image, adjust x- and y-position
2717 if (s
->slice
.x
== 0)
2718 x
+= s
->img
->hmargin
;
2719 if (s
->slice
.y
== 0)
2720 y
+= s
->img
->vmargin
;
2724 x_set_glyph_string_clipping (s
);
2727 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2728 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2729 s
->slice
.width
, s
->slice
.height
, x
, y
);
2732 mac_copy_area (s
->display
, s
->img
->pixmap
,
2733 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2734 s
->slice
.width
, s
->slice
.height
, x
, y
);
2736 /* When the image has a mask, we can expect that at
2737 least part of a mouse highlight or a block cursor will
2738 be visible. If the image doesn't have a mask, make
2739 a block cursor visible by drawing a rectangle around
2740 the image. I believe it's looking better if we do
2741 nothing here for mouse-face. */
2742 if (s
->hl
== DRAW_CURSOR
)
2744 int r
= s
->img
->relief
;
2746 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2748 s
->slice
.width
+ r
*2 - 1,
2749 s
->slice
.height
+ r
*2 - 1);
2754 /* Draw a rectangle if image could not be loaded. */
2755 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2756 s
->slice
.width
- 1, s
->slice
.height
- 1);
2760 /* Draw a relief around the image glyph string S. */
2763 x_draw_image_relief (s
)
2764 struct glyph_string
*s
;
2766 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2769 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2771 /* If first glyph of S has a left box line, start drawing it to the
2772 right of that line. */
2773 if (s
->face
->box
!= FACE_NO_BOX
2774 && s
->first_glyph
->left_box_line_p
2776 x
+= abs (s
->face
->box_line_width
);
2778 /* If there is a margin around the image, adjust x- and y-position
2780 if (s
->slice
.x
== 0)
2781 x
+= s
->img
->hmargin
;
2782 if (s
->slice
.y
== 0)
2783 y
+= s
->img
->vmargin
;
2785 if (s
->hl
== DRAW_IMAGE_SUNKEN
2786 || s
->hl
== DRAW_IMAGE_RAISED
)
2788 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2789 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2793 thick
= abs (s
->img
->relief
);
2794 raised_p
= s
->img
->relief
> 0;
2799 x1
= x
+ s
->slice
.width
+ thick
- 1;
2800 y1
= y
+ s
->slice
.height
+ thick
- 1;
2802 x_setup_relief_colors (s
);
2803 get_glyph_string_clip_rect (s
, &r
);
2804 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2806 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2808 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2813 #if 0 /* TODO: figure out if we need to do this on Mac. */
2814 /* Draw the foreground of image glyph string S to PIXMAP. */
2817 x_draw_image_foreground_1 (s
, pixmap
)
2818 struct glyph_string
*s
;
2822 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2824 /* If first glyph of S has a left box line, start drawing it to the
2825 right of that line. */
2826 if (s
->face
->box
!= FACE_NO_BOX
2827 && s
->first_glyph
->left_box_line_p
2829 x
+= abs (s
->face
->box_line_width
);
2831 /* If there is a margin around the image, adjust x- and y-position
2833 if (s
->slice
.x
== 0)
2834 x
+= s
->img
->hmargin
;
2835 if (s
->slice
.y
== 0)
2836 y
+= s
->img
->vmargin
;
2841 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2842 s
->img
->mask
, pixmap
, s
->gc
,
2843 s
->slice
.x
, s
->slice
.y
,
2844 s
->slice
.width
, s
->slice
.height
,
2848 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2849 s
->slice
.x
, s
->slice
.y
,
2850 s
->slice
.width
, s
->slice
.height
,
2853 /* When the image has a mask, we can expect that at
2854 least part of a mouse highlight or a block cursor will
2855 be visible. If the image doesn't have a mask, make
2856 a block cursor visible by drawing a rectangle around
2857 the image. I believe it's looking better if we do
2858 nothing here for mouse-face. */
2859 if (s
->hl
== DRAW_CURSOR
)
2861 int r
= s
->img
->relief
;
2863 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2864 s
->slice
.width
+ r
*2 - 1,
2865 s
->slice
.height
+ r
*2 - 1);
2870 /* Draw a rectangle if image could not be loaded. */
2871 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2872 s
->slice
.width
- 1, s
->slice
.height
- 1);
2877 /* Draw part of the background of glyph string S. X, Y, W, and H
2878 give the rectangle to draw. */
2881 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2882 struct glyph_string
*s
;
2885 #if 0 /* MAC_TODO: stipple */
2888 /* Fill background with a stipple pattern. */
2889 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2890 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2891 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2894 #endif /* MAC_TODO */
2895 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2899 /* Draw image glyph string S.
2902 s->x +-------------------------
2905 | +-------------------------
2908 | | +-------------------
2914 x_draw_image_glyph_string (s
)
2915 struct glyph_string
*s
;
2918 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2919 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2923 height
= s
->height
- 2 * box_line_vwidth
;
2926 /* Fill background with face under the image. Do it only if row is
2927 taller than image or if image has a clip mask to reduce
2929 s
->stippled_p
= s
->face
->stipple
!= 0;
2930 if (height
> s
->slice
.height
2934 || s
->img
->pixmap
== 0
2935 || s
->width
!= s
->background_width
)
2938 if (s
->first_glyph
->left_box_line_p
2940 x
+= box_line_hwidth
;
2943 if (s
->slice
.y
== 0)
2944 y
+= box_line_vwidth
;
2946 #if 0 /* TODO: figure out if we need to do this on Mac. */
2949 /* Create a pixmap as large as the glyph string. Fill it
2950 with the background color. Copy the image to it, using
2951 its mask. Copy the temporary pixmap to the display. */
2952 int depth
= one_mac_display_info
.n_planes
;
2954 /* Create a pixmap as large as the glyph string. */
2955 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2956 s
->background_width
,
2959 /* Fill the pixmap with the background color/stipple. */
2960 #if 0 /* TODO: stipple */
2963 /* Fill background with a stipple pattern. */
2964 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2965 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2966 0, 0, s
->background_width
, s
->height
);
2967 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2973 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2975 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2976 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2977 0, 0, s
->background_width
,
2979 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2984 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2986 s
->background_filled_p
= 1;
2989 /* Draw the foreground. */
2990 #if 0 /* TODO: figure out if we need to do this on Mac. */
2993 x_draw_image_foreground_1 (s
, pixmap
);
2994 x_set_glyph_string_clipping (s
);
2995 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
2996 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2997 mac_reset_clipping (s
->display
, s
->window
);
2998 XFreePixmap (s
->display
, pixmap
);
3002 x_draw_image_foreground (s
);
3004 /* If we must draw a relief around the image, do it. */
3006 || s
->hl
== DRAW_IMAGE_RAISED
3007 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3008 x_draw_image_relief (s
);
3012 /* Draw stretch glyph string S. */
3015 x_draw_stretch_glyph_string (s
)
3016 struct glyph_string
*s
;
3018 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3019 s
->stippled_p
= s
->face
->stipple
!= 0;
3021 if (s
->hl
== DRAW_CURSOR
3022 && !x_stretch_cursor_p
)
3024 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3025 as wide as the stretch glyph. */
3026 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3029 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3031 /* Clear rest using the GC of the original non-cursor face. */
3032 if (width
< s
->background_width
)
3034 int x
= s
->x
+ width
, y
= s
->y
;
3035 int w
= s
->background_width
- width
, h
= s
->height
;
3039 if (s
->row
->mouse_face_p
3040 && cursor_in_mouse_face_p (s
->w
))
3042 x_set_mouse_face_gc (s
);
3048 get_glyph_string_clip_rect (s
, &r
);
3049 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3051 #if 0 /* MAC_TODO: stipple */
3052 if (s
->face
->stipple
)
3054 /* Fill background with a stipple pattern. */
3055 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3056 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3057 XSetFillStyle (s
->display
, gc
, FillSolid
);
3060 #endif /* MAC_TODO */
3063 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3064 XSetForeground (s
->display
, gc
, xgcv
.background
);
3065 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3066 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3069 mac_reset_clipping (s
->display
, s
->window
);
3072 else if (!s
->background_filled_p
)
3073 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3076 s
->background_filled_p
= 1;
3080 /* Draw glyph string S. */
3083 x_draw_glyph_string (s
)
3084 struct glyph_string
*s
;
3086 int relief_drawn_p
= 0;
3088 /* If S draws into the background of its successor that does not
3089 draw a cursor, draw the background of the successor first so that
3090 S can draw into it. This makes S->next use XDrawString instead
3091 of XDrawImageString. */
3092 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
3093 && s
->next
->hl
!= DRAW_CURSOR
)
3095 xassert (s
->next
->img
== NULL
);
3096 x_set_glyph_string_gc (s
->next
);
3097 x_set_glyph_string_clipping (s
->next
);
3098 x_draw_glyph_string_background (s
->next
, 1);
3101 /* Set up S->gc, set clipping and draw S. */
3102 x_set_glyph_string_gc (s
);
3104 /* Draw relief (if any) in advance for char/composition so that the
3105 glyph string can be drawn over it. */
3106 if (!s
->for_overlaps_p
3107 && s
->face
->box
!= FACE_NO_BOX
3108 && (s
->first_glyph
->type
== CHAR_GLYPH
3109 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3112 x_set_glyph_string_clipping (s
);
3113 x_draw_glyph_string_background (s
, 1);
3114 x_draw_glyph_string_box (s
);
3115 x_set_glyph_string_clipping (s
);
3119 x_set_glyph_string_clipping (s
);
3121 switch (s
->first_glyph
->type
)
3124 x_draw_image_glyph_string (s
);
3128 x_draw_stretch_glyph_string (s
);
3132 if (s
->for_overlaps_p
)
3133 s
->background_filled_p
= 1;
3135 x_draw_glyph_string_background (s
, 0);
3136 x_draw_glyph_string_foreground (s
);
3139 case COMPOSITE_GLYPH
:
3140 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3141 s
->background_filled_p
= 1;
3143 x_draw_glyph_string_background (s
, 1);
3144 x_draw_composite_glyph_string_foreground (s
);
3151 if (!s
->for_overlaps_p
)
3153 /* Draw underline. */
3154 if (s
->face
->underline_p
)
3156 unsigned long h
= 1;
3157 unsigned long dy
= s
->height
- h
;
3159 if (s
->face
->underline_defaulted_p
)
3160 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3165 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3166 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3167 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3169 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3173 /* Draw overline. */
3174 if (s
->face
->overline_p
)
3176 unsigned long dy
= 0, h
= 1;
3178 if (s
->face
->overline_color_defaulted_p
)
3179 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3184 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3185 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3186 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3188 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3192 /* Draw strike-through. */
3193 if (s
->face
->strike_through_p
)
3195 unsigned long h
= 1;
3196 unsigned long dy
= (s
->height
- h
) / 2;
3198 if (s
->face
->strike_through_color_defaulted_p
)
3199 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3204 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3205 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3206 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3208 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3212 /* Draw relief if not yet drawn. */
3213 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3214 x_draw_glyph_string_box (s
);
3217 /* Reset clipping. */
3218 mac_reset_clipping (s
->display
, s
->window
);
3221 /* Shift display to make room for inserted glyphs. */
3224 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3226 int x
, y
, width
, height
, shift_by
;
3228 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3229 f
->output_data
.mac
->normal_gc
,
3230 x
, y
, width
, height
,
3234 /* Delete N glyphs at the nominal cursor position. Not implemented
3245 /* Clear entire frame. If updating_frame is non-null, clear that
3246 frame. Otherwise clear the selected frame. */
3256 f
= SELECTED_FRAME ();
3258 /* Clearing the frame will erase any cursor, so mark them all as no
3260 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3261 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3262 output_cursor
.x
= -1;
3264 /* We don't set the output cursor here because there will always
3265 follow an explicit cursor_to. */
3267 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3269 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3270 /* We have to clear the scroll bars, too. If we have changed
3271 colors or something like that, then they should be notified. */
3272 x_scroll_bar_clear (f
);
3275 XFlush (FRAME_MAC_DISPLAY (f
));
3281 /* Invert the middle quarter of the frame for .15 sec. */
3283 /* We use the select system call to do the waiting, so we have to make
3284 sure it's available. If it isn't, we just won't do visual bells. */
3286 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3289 /* Subtract the `struct timeval' values X and Y, storing the result in
3290 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3293 timeval_subtract (result
, x
, y
)
3294 struct timeval
*result
, x
, y
;
3296 /* Perform the carry for the later subtraction by updating y. This
3297 is safer because on some systems the tv_sec member is unsigned. */
3298 if (x
.tv_usec
< y
.tv_usec
)
3300 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3301 y
.tv_usec
-= 1000000 * nsec
;
3305 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3307 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3308 y
.tv_usec
+= 1000000 * nsec
;
3312 /* Compute the time remaining to wait. tv_usec is certainly
3314 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3315 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3317 /* Return indication of whether the result should be considered
3319 return x
.tv_sec
< y
.tv_sec
;
3331 struct timeval wakeup
;
3333 EMACS_GET_TIME (wakeup
);
3335 /* Compute time to wait until, propagating carry from usecs. */
3336 wakeup
.tv_usec
+= 150000;
3337 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3338 wakeup
.tv_usec
%= 1000000;
3340 /* Keep waiting until past the time wakeup. */
3343 struct timeval timeout
;
3345 EMACS_GET_TIME (timeout
);
3347 /* In effect, timeout = wakeup - timeout.
3348 Break if result would be negative. */
3349 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3352 /* Try to wait that long--but we might wake up sooner. */
3353 select (0, NULL
, NULL
, NULL
, &timeout
);
3362 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3365 /* Make audible bell. */
3370 struct frame
*f
= SELECTED_FRAME ();
3372 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3380 XFlush (FRAME_MAC_DISPLAY (f
));
3387 /* Specify how many text lines, from the top of the window,
3388 should be affected by insert-lines and delete-lines operations.
3389 This, and those operations, are used only within an update
3390 that is bounded by calls to x_update_begin and x_update_end. */
3393 XTset_terminal_window (n
)
3396 /* This function intentionally left blank. */
3401 /***********************************************************************
3403 ***********************************************************************/
3405 /* Perform an insert-lines or delete-lines operation, inserting N
3406 lines or deleting -N lines at vertical position VPOS. */
3409 x_ins_del_lines (vpos
, n
)
3416 /* Scroll part of the display as described by RUN. */
3419 x_scroll_run (w
, run
)
3423 struct frame
*f
= XFRAME (w
->frame
);
3424 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3426 /* Get frame-relative bounding box of the text display area of W,
3427 without mode lines. Include in this box the left and right
3429 window_box (w
, -1, &x
, &y
, &width
, &height
);
3431 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3432 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3433 bottom_y
= y
+ height
;
3437 /* Scrolling up. Make sure we don't copy part of the mode
3438 line at the bottom. */
3439 if (from_y
+ run
->height
> bottom_y
)
3440 height
= bottom_y
- from_y
;
3442 height
= run
->height
;
3446 /* Scolling down. Make sure we don't copy over the mode line.
3448 if (to_y
+ run
->height
> bottom_y
)
3449 height
= bottom_y
- to_y
;
3451 height
= run
->height
;
3456 /* Cursor off. Will be switched on again in x_update_window_end. */
3460 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3461 f
->output_data
.mac
->normal_gc
,
3471 /***********************************************************************
3473 ***********************************************************************/
3480 x_update_cursor (f
, 1);
3484 frame_unhighlight (f
)
3487 x_update_cursor (f
, 1);
3490 /* The focus has changed. Update the frames as necessary to reflect
3491 the new situation. Note that we can't change the selected frame
3492 here, because the Lisp code we are interrupting might become confused.
3493 Each event gets marked with the frame in which it occurred, so the
3494 Lisp code can tell when the switch took place by examining the events. */
3497 x_new_focus_frame (dpyinfo
, frame
)
3498 struct x_display_info
*dpyinfo
;
3499 struct frame
*frame
;
3501 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3503 if (frame
!= dpyinfo
->x_focus_frame
)
3505 /* Set this before calling other routines, so that they see
3506 the correct value of x_focus_frame. */
3507 dpyinfo
->x_focus_frame
= frame
;
3509 if (old_focus
&& old_focus
->auto_lower
)
3510 x_lower_frame (old_focus
);
3513 selected_frame
= frame
;
3514 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3516 Fselect_window (selected_frame
->selected_window
, Qnil
);
3517 choose_minibuf_frame ();
3520 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3521 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3523 pending_autoraise_frame
= 0;
3526 x_frame_rehighlight (dpyinfo
);
3529 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3532 x_mouse_leave (dpyinfo
)
3533 struct x_display_info
*dpyinfo
;
3535 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3538 /* The focus has changed, or we have redirected a frame's focus to
3539 another frame (this happens when a frame uses a surrogate
3540 mini-buffer frame). Shift the highlight as appropriate.
3542 The FRAME argument doesn't necessarily have anything to do with which
3543 frame is being highlighted or un-highlighted; we only use it to find
3544 the appropriate X display info. */
3547 XTframe_rehighlight (frame
)
3548 struct frame
*frame
;
3550 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3554 x_frame_rehighlight (dpyinfo
)
3555 struct x_display_info
*dpyinfo
;
3557 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3559 if (dpyinfo
->x_focus_frame
)
3561 dpyinfo
->x_highlight_frame
3562 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3563 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3564 : dpyinfo
->x_focus_frame
);
3565 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3567 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3568 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3572 dpyinfo
->x_highlight_frame
= 0;
3574 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3577 frame_unhighlight (old_highlight
);
3578 if (dpyinfo
->x_highlight_frame
)
3579 frame_highlight (dpyinfo
->x_highlight_frame
);
3585 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3587 #if 0 /* MAC_TODO */
3588 /* Initialize mode_switch_bit and modifier_meaning. */
3590 x_find_modifier_meanings (dpyinfo
)
3591 struct x_display_info
*dpyinfo
;
3593 int min_code
, max_code
;
3596 XModifierKeymap
*mods
;
3598 dpyinfo
->meta_mod_mask
= 0;
3599 dpyinfo
->shift_lock_mask
= 0;
3600 dpyinfo
->alt_mod_mask
= 0;
3601 dpyinfo
->super_mod_mask
= 0;
3602 dpyinfo
->hyper_mod_mask
= 0;
3605 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3607 min_code
= dpyinfo
->display
->min_keycode
;
3608 max_code
= dpyinfo
->display
->max_keycode
;
3611 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3612 min_code
, max_code
- min_code
+ 1,
3614 mods
= XGetModifierMapping (dpyinfo
->display
);
3616 /* Scan the modifier table to see which modifier bits the Meta and
3617 Alt keysyms are on. */
3619 int row
, col
; /* The row and column in the modifier table. */
3621 for (row
= 3; row
< 8; row
++)
3622 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3625 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3627 /* Zeroes are used for filler. Skip them. */
3631 /* Are any of this keycode's keysyms a meta key? */
3635 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3637 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3643 dpyinfo
->meta_mod_mask
|= (1 << row
);
3648 dpyinfo
->alt_mod_mask
|= (1 << row
);
3653 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3658 dpyinfo
->super_mod_mask
|= (1 << row
);
3662 /* Ignore this if it's not on the lock modifier. */
3663 if ((1 << row
) == LockMask
)
3664 dpyinfo
->shift_lock_mask
= LockMask
;
3672 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3673 if (! dpyinfo
->meta_mod_mask
)
3675 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3676 dpyinfo
->alt_mod_mask
= 0;
3679 /* If some keys are both alt and meta,
3680 make them just meta, not alt. */
3681 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3683 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3686 XFree ((char *) syms
);
3687 XFreeModifiermap (mods
);
3690 #endif /* MAC_TODO */
3692 /* Convert between the modifier bits X uses and the modifier bits
3696 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3697 struct x_display_info
*dpyinfo
;
3698 unsigned short state
;
3700 return (((state
& shiftKey
) ? shift_modifier
: 0)
3701 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3702 | ((state
& cmdKey
) ? meta_modifier
: 0)
3703 | ((state
& optionKey
) ? alt_modifier
: 0));
3706 #if 0 /* MAC_TODO */
3707 static unsigned short
3708 x_emacs_to_x_modifiers (dpyinfo
, state
)
3709 struct x_display_info
*dpyinfo
;
3712 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3713 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3714 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3715 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3716 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3717 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3719 #endif /* MAC_TODO */
3721 /* Convert a keysym to its name. */
3724 x_get_keysym_name (keysym
)
3731 value
= XKeysymToString (keysym
);
3743 /* Mouse clicks and mouse movement. Rah. */
3745 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3747 If the event is a button press, then note that we have grabbed
3751 construct_mouse_click (result
, event
, f
)
3752 struct input_event
*result
;
3758 result
->kind
= MOUSE_CLICK_EVENT
;
3759 result
->code
= 0; /* only one mouse button */
3760 result
->timestamp
= event
->when
;
3761 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3763 mouseLoc
= event
->where
;
3765 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3767 GlobalToLocal (&mouseLoc
);
3768 XSETINT (result
->x
, mouseLoc
.h
);
3769 XSETINT (result
->y
, mouseLoc
.v
);
3771 XSETFRAME (result
->frame_or_window
, f
);
3779 /* Function to report a mouse movement to the mainstream Emacs code.
3780 The input handler calls this.
3782 We have received a mouse movement event, which is given in *event.
3783 If the mouse is over a different glyph than it was last time, tell
3784 the mainstream emacs code by setting mouse_moved. If not, ask for
3785 another motion event, so we can check again the next time it moves. */
3787 static Point last_mouse_motion_position
;
3788 static Lisp_Object last_mouse_motion_frame
;
3791 note_mouse_movement (frame
, pos
)
3795 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3796 #if TARGET_API_MAC_CARBON
3800 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3801 last_mouse_motion_position
= *pos
;
3802 XSETFRAME (last_mouse_motion_frame
, frame
);
3804 #if TARGET_API_MAC_CARBON
3805 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3807 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3810 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3811 /* This case corresponds to LeaveNotify in X11. */
3813 /* If we move outside the frame, then we're certainly no
3814 longer on any text in the frame. */
3815 clear_mouse_face (dpyinfo
);
3816 dpyinfo
->mouse_face_mouse_frame
= 0;
3817 if (!dpyinfo
->grabbed
)
3818 rif
->define_frame_cursor (frame
,
3819 frame
->output_data
.mac
->nontext_cursor
);
3822 /* Has the mouse moved off the glyph it was on at the last sighting? */
3823 else if (pos
->h
< last_mouse_glyph
.left
3824 || pos
->h
>= last_mouse_glyph
.right
3825 || pos
->v
< last_mouse_glyph
.top
3826 || pos
->v
>= last_mouse_glyph
.bottom
)
3828 frame
->mouse_moved
= 1;
3829 last_mouse_scroll_bar
= Qnil
;
3830 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3834 /* This is used for debugging, to turn off note_mouse_highlight. */
3836 int disable_mouse_highlight
;
3840 /************************************************************************
3842 ************************************************************************/
3844 static struct scroll_bar
*x_window_to_scroll_bar ();
3845 static void x_scroll_bar_report_motion ();
3846 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3849 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3852 redo_mouse_highlight ()
3854 if (!NILP (last_mouse_motion_frame
)
3855 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3856 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3857 last_mouse_motion_position
.h
,
3858 last_mouse_motion_position
.v
);
3862 /* Try to determine frame pixel position and size of the glyph under
3863 frame pixel coordinates X/Y on frame F . Return the position and
3864 size in *RECT. Value is non-zero if we could compute these
3868 glyph_rect (f
, x
, y
, rect
)
3875 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3879 struct window
*w
= XWINDOW (window
);
3880 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3881 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3883 for (; r
< end
&& r
->enabled_p
; ++r
)
3884 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3886 /* Found the row at y. */
3887 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3888 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3891 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3892 rect
->bottom
= rect
->top
+ r
->height
;
3896 /* x is to the left of the first glyph in the row. */
3897 /* Shouldn't this be a pixel value?
3898 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3900 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3901 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3905 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3906 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3908 /* x is on a glyph. */
3909 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3910 rect
->right
= rect
->left
+ g
->pixel_width
;
3914 /* x is to the right of the last glyph in the row. */
3915 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3916 /* Shouldn't this be a pixel value?
3917 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3919 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3924 /* The y is not on any row. */
3928 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3930 /* Record the position of the mouse in last_mouse_glyph. */
3932 remember_mouse_glyph (f1
, gx
, gy
)
3936 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3938 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3939 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3941 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3942 round down even for negative values. */
3948 /* This was the original code from XTmouse_position, but it seems
3949 to give the position of the glyph diagonally next to the one
3950 the mouse is over. */
3951 gx
= (gx
+ width
- 1) / width
* width
;
3952 gy
= (gy
+ height
- 1) / height
* height
;
3954 gx
= gx
/ width
* width
;
3955 gy
= gy
/ height
* height
;
3958 last_mouse_glyph
.left
= gx
;
3959 last_mouse_glyph
.top
= gy
;
3960 last_mouse_glyph
.right
= gx
+ width
;
3961 last_mouse_glyph
.bottom
= gy
+ height
;
3967 front_emacs_window ()
3969 #if TARGET_API_MAC_CARBON
3970 WindowPtr wp
= GetFrontWindowOfClass (kDocumentWindowClass
, true);
3972 while (wp
&& !is_emacs_window (wp
))
3973 wp
= GetNextWindowOfClass (wp
, kDocumentWindowClass
, true);
3975 WindowPtr wp
= FrontWindow ();
3977 while (wp
&& (wp
== tip_window
|| !is_emacs_window (wp
)))
3978 wp
= GetNextWindow (wp
);
3984 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3986 /* Return the current position of the mouse.
3987 *fp should be a frame which indicates which display to ask about.
3989 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3990 and *part to the frame, window, and scroll bar part that the mouse
3991 is over. Set *x and *y to the portion and whole of the mouse's
3992 position on the scroll bar.
3994 If the mouse movement started elsewhere, set *fp to the frame the
3995 mouse is on, *bar_window to nil, and *x and *y to the character cell
3998 Set *time to the server time-stamp for the time at which the mouse
3999 was at this position.
4001 Don't store anything if we don't have a valid set of values to report.
4003 This clears the mouse_moved flag, so we can wait for the next mouse
4007 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4010 Lisp_Object
*bar_window
;
4011 enum scroll_bar_part
*part
;
4013 unsigned long *time
;
4016 int ignore1
, ignore2
;
4017 WindowPtr wp
= front_emacs_window ();
4019 Lisp_Object frame
, tail
;
4021 if (is_emacs_window(wp
))
4022 f
= mac_window_to_frame (wp
);
4026 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4027 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4030 /* Clear the mouse-moved flag for every frame on this display. */
4031 FOR_EACH_FRAME (tail
, frame
)
4032 XFRAME (frame
)->mouse_moved
= 0;
4034 last_mouse_scroll_bar
= Qnil
;
4036 SetPortWindowPort (wp
);
4038 GetMouse (&mouse_pos
);
4040 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4041 &last_mouse_glyph
, insist
);
4044 *part
= scroll_bar_handle
;
4046 XSETINT (*x
, mouse_pos
.h
);
4047 XSETINT (*y
, mouse_pos
.v
);
4048 *time
= last_mouse_movement_time
;
4055 /***********************************************************************
4057 ***********************************************************************/
4059 /* Handle mouse button event on the tool-bar of frame F, at
4060 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4064 mac_handle_tool_bar_click (f
, button_event
)
4066 EventRecord
*button_event
;
4068 int x
= button_event
->where
.h
;
4069 int y
= button_event
->where
.v
;
4071 if (button_event
->what
== mouseDown
)
4072 handle_tool_bar_click (f
, x
, y
, 1, 0);
4074 handle_tool_bar_click (f
, x
, y
, 0,
4075 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f
),
4076 button_event
->modifiers
));
4080 /************************************************************************
4081 Scroll bars, general
4082 ************************************************************************/
4084 /* Create a scroll bar and return the scroll bar vector for it. W is
4085 the Emacs window on which to create the scroll bar. TOP, LEFT,
4086 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4089 static struct scroll_bar
*
4090 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4092 int top
, left
, width
, height
, disp_top
, disp_height
;
4094 struct frame
*f
= XFRAME (w
->frame
);
4095 struct scroll_bar
*bar
4096 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4104 r
.right
= left
+ width
;
4105 r
.bottom
= disp_top
+ disp_height
;
4107 #if TARGET_API_MAC_CARBON
4108 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4109 kControlScrollBarProc
, 0L);
4111 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
4114 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4115 SetControlReference (ch
, (long) bar
);
4117 XSETWINDOW (bar
->window
, w
);
4118 XSETINT (bar
->top
, top
);
4119 XSETINT (bar
->left
, left
);
4120 XSETINT (bar
->width
, width
);
4121 XSETINT (bar
->height
, height
);
4122 XSETINT (bar
->start
, 0);
4123 XSETINT (bar
->end
, 0);
4124 bar
->dragging
= Qnil
;
4126 /* Add bar to its frame's list of scroll bars. */
4127 bar
->next
= FRAME_SCROLL_BARS (f
);
4129 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4130 if (!NILP (bar
->next
))
4131 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4138 /* Draw BAR's handle in the proper position.
4140 If the handle is already drawn from START to END, don't bother
4141 redrawing it, unless REBUILD is non-zero; in that case, always
4142 redraw it. (REBUILD is handy for drawing the handle after expose
4145 Normally, we want to constrain the start and end of the handle to
4146 fit inside its rectangle, but if the user is dragging the scroll
4147 bar handle, we want to let them drag it down all the way, so that
4148 the bar's top is as far down as it goes; otherwise, there's no way
4149 to move to the very end of the buffer. */
4152 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4153 struct scroll_bar
*bar
;
4157 int dragging
= ! NILP (bar
->dragging
);
4158 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4159 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4160 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4161 int length
= end
- start
;
4163 /* If the display is already accurate, do nothing. */
4165 && start
== XINT (bar
->start
)
4166 && end
== XINT (bar
->end
))
4171 /* Make sure the values are reasonable, and try to preserve the
4172 distance between start and end. */
4175 else if (start
> top_range
)
4177 end
= start
+ length
;
4181 else if (end
> top_range
&& ! dragging
)
4184 /* Store the adjusted setting in the scroll bar. */
4185 XSETINT (bar
->start
, start
);
4186 XSETINT (bar
->end
, end
);
4188 /* Clip the end position, just for display. */
4189 if (end
> top_range
)
4192 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4193 top positions, to make sure the handle is always at least that
4194 many pixels tall. */
4195 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4197 SetControlMinimum (ch
, 0);
4198 /* Don't inadvertently activate deactivated scroll bars */
4199 if (GetControlMaximum (ch
) != -1)
4200 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4202 SetControlValue (ch
, start
);
4203 #if TARGET_API_MAC_CARBON
4204 SetControlViewSize (ch
, end
- start
);
4211 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4215 x_scroll_bar_remove (bar
)
4216 struct scroll_bar
*bar
;
4218 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4222 /* Destroy the Mac scroll bar control */
4223 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4225 /* Disassociate this scroll bar from its window. */
4226 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4231 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4232 that we are displaying PORTION characters out of a total of WHOLE
4233 characters, starting at POSITION. If WINDOW has no scroll bar,
4236 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4238 int portion
, whole
, position
;
4240 struct frame
*f
= XFRAME (w
->frame
);
4241 struct scroll_bar
*bar
;
4242 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4243 int window_y
, window_height
;
4245 /* Get window dimensions. */
4246 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4251 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4253 height
= window_height
;
4255 /* Compute the left edge of the scroll bar area. */
4256 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4258 /* Compute the width of the scroll bar which might be less than
4259 the width of the area reserved for the scroll bar. */
4260 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4261 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4265 /* Compute the left edge of the scroll bar. */
4266 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4267 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
4269 sb_left
= left
+ (width
- sb_width
) / 2;
4271 /* Adjustments according to Inside Macintosh to make it look nice */
4273 disp_height
= height
;
4279 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4285 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4288 /* Does the scroll bar exist yet? */
4289 if (NILP (w
->vertical_scroll_bar
))
4292 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4293 left
, top
, width
, height
, 0);
4295 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4297 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4301 /* It may just need to be moved and resized. */
4304 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4305 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4309 /* If already correctly positioned, do nothing. */
4310 if (XINT (bar
->left
) == sb_left
4311 && XINT (bar
->top
) == top
4312 && XINT (bar
->width
) == sb_width
4313 && XINT (bar
->height
) == height
)
4317 /* Clear areas not covered by the scroll bar because it's not as
4318 wide as the area reserved for it . This makes sure a
4319 previous mode line display is cleared after C-x 2 C-x 1, for
4321 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4322 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4323 left
, top
, area_width
, height
, 0);
4326 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4327 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4328 sb_left
- 1, top
, 1, height
, 0);
4332 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4333 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4337 /* Remember new settings. */
4338 XSETINT (bar
->left
, sb_left
);
4339 XSETINT (bar
->top
, top
);
4340 XSETINT (bar
->width
, sb_width
);
4341 XSETINT (bar
->height
, height
);
4347 /* Set the scroll bar's current state, unless we're currently being
4349 if (NILP (bar
->dragging
))
4351 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4354 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4357 int start
= ((double) position
* top_range
) / whole
;
4358 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4359 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4365 /* The following three hooks are used when we're doing a thorough
4366 redisplay of the frame. We don't explicitly know which scroll bars
4367 are going to be deleted, because keeping track of when windows go
4368 away is a real pain - "Can you say set-window-configuration, boys
4369 and girls?" Instead, we just assert at the beginning of redisplay
4370 that *all* scroll bars are to be removed, and then save a scroll bar
4371 from the fiery pit when we actually redisplay its window. */
4373 /* Arrange for all scroll bars on FRAME to be removed at the next call
4374 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4375 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4378 XTcondemn_scroll_bars (frame
)
4381 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4382 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4385 bar
= FRAME_SCROLL_BARS (frame
);
4386 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4387 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4388 XSCROLL_BAR (bar
)->prev
= Qnil
;
4389 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4390 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4391 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4396 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4397 Note that WINDOW isn't necessarily condemned at all. */
4400 XTredeem_scroll_bar (window
)
4401 struct window
*window
;
4403 struct scroll_bar
*bar
;
4405 /* We can't redeem this window's scroll bar if it doesn't have one. */
4406 if (NILP (window
->vertical_scroll_bar
))
4409 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4411 /* Unlink it from the condemned list. */
4413 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4415 if (NILP (bar
->prev
))
4417 /* If the prev pointer is nil, it must be the first in one of
4419 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4420 /* It's not condemned. Everything's fine. */
4422 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4423 window
->vertical_scroll_bar
))
4424 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4426 /* If its prev pointer is nil, it must be at the front of
4427 one or the other! */
4431 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4433 if (! NILP (bar
->next
))
4434 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4436 bar
->next
= FRAME_SCROLL_BARS (f
);
4438 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4439 if (! NILP (bar
->next
))
4440 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4444 /* Remove all scroll bars on FRAME that haven't been saved since the
4445 last call to `*condemn_scroll_bars_hook'. */
4448 XTjudge_scroll_bars (f
)
4451 Lisp_Object bar
, next
;
4453 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4455 /* Clear out the condemned list now so we won't try to process any
4456 more events on the hapless scroll bars. */
4457 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4459 for (; ! NILP (bar
); bar
= next
)
4461 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4463 x_scroll_bar_remove (b
);
4466 b
->next
= b
->prev
= Qnil
;
4469 /* Now there should be no references to the condemned scroll bars,
4470 and they should get garbage-collected. */
4475 activate_scroll_bars (frame
)
4481 bar
= FRAME_SCROLL_BARS (frame
);
4482 while (! NILP (bar
))
4484 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
4485 #if 1 /* TARGET_API_MAC_CARBON */
4486 ActivateControl (ch
);
4488 SetControlMaximum (ch
,
4489 VERTICAL_SCROLL_BAR_TOP_RANGE (frame
,
4490 XINT (XSCROLL_BAR (bar
)
4493 bar
= XSCROLL_BAR (bar
)->next
;
4499 deactivate_scroll_bars (frame
)
4505 bar
= FRAME_SCROLL_BARS (frame
);
4506 while (! NILP (bar
))
4508 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
4509 #if 1 /* TARGET_API_MAC_CARBON */
4510 DeactivateControl (ch
);
4512 SetControlMaximum (ch
, -1);
4514 bar
= XSCROLL_BAR (bar
)->next
;
4518 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4519 is set to something other than NO_EVENT, it is enqueued.
4521 This may be called from a signal handler, so we have to ignore GC
4525 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4526 struct scroll_bar
*bar
;
4529 struct input_event
*bufp
;
4531 int win_y
, top_range
;
4533 if (! GC_WINDOWP (bar
->window
))
4536 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4537 bufp
->frame_or_window
= bar
->window
;
4540 bar
->dragging
= Qnil
;
4544 case kControlUpButtonPart
:
4545 bufp
->part
= scroll_bar_up_arrow
;
4547 case kControlDownButtonPart
:
4548 bufp
->part
= scroll_bar_down_arrow
;
4550 case kControlPageUpPart
:
4551 bufp
->part
= scroll_bar_above_handle
;
4553 case kControlPageDownPart
:
4554 bufp
->part
= scroll_bar_below_handle
;
4556 #if TARGET_API_MAC_CARBON
4559 case kControlIndicatorPart
:
4561 if (er
->what
== mouseDown
)
4562 bar
->dragging
= make_number (0);
4563 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4564 bufp
->part
= scroll_bar_handle
;
4568 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4569 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4571 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4575 if (! NILP (bar
->dragging
))
4576 win_y
-= XINT (bar
->dragging
);
4580 if (win_y
> top_range
)
4583 XSETINT (bufp
->x
, win_y
);
4584 XSETINT (bufp
->y
, top_range
);
4588 /* Handle some mouse motion while someone is dragging the scroll bar.
4590 This may be called from a signal handler, so we have to ignore GC
4594 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4595 struct scroll_bar
*bar
;
4599 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4601 last_mouse_movement_time
= t
;
4604 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4606 /* If we're dragging the bar, display it. */
4607 if (! GC_NILP (bar
->dragging
))
4609 /* Where should the handle be now? */
4610 int new_start
= y_pos
- 24;
4612 if (new_start
!= XINT (bar
->start
))
4614 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4616 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4622 /* Return information to the user about the current position of the
4623 mouse on the scroll bar. */
4626 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4628 Lisp_Object
*bar_window
;
4629 enum scroll_bar_part
*part
;
4631 unsigned long *time
;
4633 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4634 WindowPtr wp
= front_emacs_window ();
4636 struct frame
*f
= mac_window_to_frame (wp
);
4637 int win_y
, top_range
;
4639 SetPortWindowPort (wp
);
4641 GetMouse (&mouse_pos
);
4643 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4644 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4646 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4650 if (! NILP (bar
->dragging
))
4651 win_y
-= XINT (bar
->dragging
);
4655 if (win_y
> top_range
)
4659 *bar_window
= bar
->window
;
4661 if (! NILP (bar
->dragging
))
4662 *part
= scroll_bar_handle
;
4663 else if (win_y
< XINT (bar
->start
))
4664 *part
= scroll_bar_above_handle
;
4665 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
4666 *part
= scroll_bar_handle
;
4668 *part
= scroll_bar_below_handle
;
4670 XSETINT (*x
, win_y
);
4671 XSETINT (*y
, top_range
);
4674 last_mouse_scroll_bar
= Qnil
;
4676 *time
= last_mouse_movement_time
;
4679 /***********************************************************************
4681 ***********************************************************************/
4683 /* Set clipping for output in glyph row ROW. W is the window in which
4684 we operate. GC is the graphics context to set clipping in.
4686 ROW may be a text row or, e.g., a mode line. Text rows must be
4687 clipped to the interior of the window dedicated to text display,
4688 mode lines must be clipped to the whole window. */
4691 x_clip_to_row (w
, row
, area
, gc
)
4693 struct glyph_row
*row
;
4697 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4699 int window_x
, window_y
, window_width
;
4701 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
4703 clip_rect
.left
= window_x
;
4704 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4705 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4706 clip_rect
.right
= clip_rect
.left
+ window_width
;
4707 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4709 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
4713 /* Draw a hollow box cursor on window W in glyph row ROW. */
4716 x_draw_hollow_cursor (w
, row
)
4718 struct glyph_row
*row
;
4720 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4721 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4722 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4725 struct glyph
*cursor_glyph
;
4728 /* Get the glyph the cursor is on. If we can't tell because
4729 the current matrix is invalid or such, give up. */
4730 cursor_glyph
= get_phys_cursor_glyph (w
);
4731 if (cursor_glyph
== NULL
)
4734 /* Compute frame-relative coordinates for phys cursor. */
4735 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
4736 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
4737 wd
= w
->phys_cursor_width
;
4739 /* The foreground of cursor_gc is typically the same as the normal
4740 background color, which can cause the cursor box to be invisible. */
4741 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4742 if (dpyinfo
->scratch_cursor_gc
)
4743 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
4745 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
4746 GCForeground
, &xgcv
);
4747 gc
= dpyinfo
->scratch_cursor_gc
;
4749 /* Set clipping, draw the rectangle, and reset clipping again. */
4750 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4751 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
4752 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4756 /* Draw a bar cursor on window W in glyph row ROW.
4758 Implementation note: One would like to draw a bar cursor with an
4759 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4760 Unfortunately, I didn't find a font yet that has this property set.
4764 x_draw_bar_cursor (w
, row
, width
, kind
)
4766 struct glyph_row
*row
;
4768 enum text_cursor_kinds kind
;
4770 struct frame
*f
= XFRAME (w
->frame
);
4771 struct glyph
*cursor_glyph
;
4773 /* If cursor is out of bounds, don't draw garbage. This can happen
4774 in mini-buffer windows when switching between echo area glyphs
4776 cursor_glyph
= get_phys_cursor_glyph (w
);
4777 if (cursor_glyph
== NULL
)
4780 /* If on an image, draw like a normal cursor. That's usually better
4781 visible than drawing a bar, esp. if the image is large so that
4782 the bar might not be in the window. */
4783 if (cursor_glyph
->type
== IMAGE_GLYPH
)
4785 struct glyph_row
*row
;
4786 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
4787 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
4791 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4792 Window window
= FRAME_MAC_WINDOW (f
);
4793 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
4794 unsigned long mask
= GCForeground
| GCBackground
;
4795 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
4798 /* If the glyph's background equals the color we normally draw
4799 the bar cursor in, the bar cursor in its normal color is
4800 invisible. Use the glyph's foreground color instead in this
4801 case, on the assumption that the glyph's colors are chosen so
4802 that the glyph is legible. */
4803 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
4804 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
4806 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4809 XChangeGC (dpy
, gc
, mask
, &xgcv
);
4812 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
4813 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
4817 width
= FRAME_CURSOR_WIDTH (f
);
4818 width
= min (cursor_glyph
->pixel_width
, width
);
4820 w
->phys_cursor_width
= width
;
4821 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4823 if (kind
== BAR_CURSOR
)
4824 XFillRectangle (dpy
, window
, gc
,
4825 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4826 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
4827 width
, row
->height
);
4829 XFillRectangle (dpy
, window
, gc
,
4830 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4831 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
4832 row
->height
- width
),
4833 cursor_glyph
->pixel_width
,
4836 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4841 /* RIF: Define cursor CURSOR on frame F. */
4844 mac_define_frame_cursor (f
, cursor
)
4848 #if TARGET_API_MAC_CARBON
4849 SetThemeCursor (cursor
);
4851 SetCursor (*cursor
);
4856 /* RIF: Clear area on frame F. */
4859 mac_clear_frame_area (f
, x
, y
, width
, height
)
4861 int x
, y
, width
, height
;
4863 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4864 x
, y
, width
, height
, 0);
4868 /* RIF: Draw cursor on window W. */
4871 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
4873 struct glyph_row
*glyph_row
;
4875 int cursor_type
, cursor_width
;
4880 w
->phys_cursor_type
= cursor_type
;
4881 w
->phys_cursor_on_p
= 1;
4883 if (glyph_row
->exact_window_width_line_p
4884 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
4886 glyph_row
->cursor_in_fringe_p
= 1;
4887 draw_fringe_bitmap (w
, glyph_row
, 0);
4890 switch (cursor_type
)
4892 case HOLLOW_BOX_CURSOR
:
4893 x_draw_hollow_cursor (w
, glyph_row
);
4896 case FILLED_BOX_CURSOR
:
4897 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
4901 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
4905 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
4909 w
->phys_cursor_width
= 0;
4921 #if 0 /* MAC_TODO: no icon support yet. */
4923 x_bitmap_icon (f
, icon
)
4929 if (FRAME_W32_WINDOW (f
) == 0)
4933 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
4934 else if (STRINGP (icon
))
4935 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
4936 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
4937 else if (SYMBOLP (icon
))
4941 if (EQ (icon
, intern ("application")))
4942 name
= (LPCTSTR
) IDI_APPLICATION
;
4943 else if (EQ (icon
, intern ("hand")))
4944 name
= (LPCTSTR
) IDI_HAND
;
4945 else if (EQ (icon
, intern ("question")))
4946 name
= (LPCTSTR
) IDI_QUESTION
;
4947 else if (EQ (icon
, intern ("exclamation")))
4948 name
= (LPCTSTR
) IDI_EXCLAMATION
;
4949 else if (EQ (icon
, intern ("asterisk")))
4950 name
= (LPCTSTR
) IDI_ASTERISK
;
4951 else if (EQ (icon
, intern ("winlogo")))
4952 name
= (LPCTSTR
) IDI_WINLOGO
;
4956 hicon
= LoadIcon (NULL
, name
);
4964 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
4969 #endif /* MAC_TODO */
4971 /************************************************************************
4973 ************************************************************************/
4975 /* Display Error Handling functions not used on W32. Listing them here
4976 helps diff stay in step when comparing w32term.c with xterm.c.
4978 x_error_catcher (display, error)
4979 x_catch_errors (dpy)
4980 x_catch_errors_unwind (old_val)
4981 x_check_errors (dpy, format)
4982 x_had_errors_p (dpy)
4983 x_clear_errors (dpy)
4984 x_uncatch_errors (dpy, count)
4986 x_connection_signal (signalnum)
4987 x_connection_closed (dpy, error_message)
4988 x_error_quitter (display, error)
4989 x_error_handler (display, error)
4990 x_io_error_quitter (display)
4995 /* Changing the font of the frame. */
4997 /* Give frame F the font named FONTNAME as its default font, and
4998 return the full name of that font. FONTNAME may be a wildcard
4999 pattern; in that case, we choose some font that fits the pattern.
5000 The return value shows which font we chose. */
5003 x_new_font (f
, fontname
)
5005 register char *fontname
;
5007 struct font_info
*fontp
5008 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5013 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5014 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5015 FRAME_FONTSET (f
) = -1;
5017 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5018 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5019 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5021 compute_fringe_widths (f
, 1);
5023 /* Compute the scroll bar width in character columns. */
5024 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5026 int wid
= FRAME_COLUMN_WIDTH (f
);
5027 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5028 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5032 int wid
= FRAME_COLUMN_WIDTH (f
);
5033 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5036 /* Now make the frame display the given font. */
5037 if (FRAME_MAC_WINDOW (f
) != 0)
5039 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5041 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5043 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5046 /* Don't change the size of a tip frame; there's no point in
5047 doing it because it's done in Fx_show_tip, and it leads to
5048 problems because the tip frame has no widget. */
5049 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5050 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5053 return build_string (fontp
->full_name
);
5056 /* Give frame F the fontset named FONTSETNAME as its default font, and
5057 return the full name of that fontset. FONTSETNAME may be a wildcard
5058 pattern; in that case, we choose some fontset that fits the pattern.
5059 The return value shows which fontset we chose. */
5062 x_new_fontset (f
, fontsetname
)
5066 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5072 if (FRAME_FONTSET (f
) == fontset
)
5073 /* This fontset is already set in frame F. There's nothing more
5075 return fontset_name (fontset
);
5077 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5079 if (!STRINGP (result
))
5080 /* Can't load ASCII font. */
5083 /* Since x_new_font doesn't update any fontset information, do it now. */
5084 FRAME_FONTSET(f
) = fontset
;
5086 return build_string (fontsetname
);
5090 /***********************************************************************
5091 TODO: W32 Input Methods
5092 ***********************************************************************/
5093 /* Listing missing functions from xterm.c helps diff stay in step.
5095 xim_destroy_callback (xim, client_data, call_data)
5096 xim_open_dpy (dpyinfo, resource_name)
5098 xim_instantiate_callback (display, client_data, call_data)
5099 xim_initialize (dpyinfo, resource_name)
5100 xim_close_dpy (dpyinfo)
5106 mac_get_window_bounds (f
, inner
, outer
)
5108 Rect
*inner
, *outer
;
5110 #if TARGET_API_MAC_CARBON
5111 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5112 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5113 #else /* not TARGET_API_MAC_CARBON */
5114 RgnHandle region
= NewRgn ();
5116 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5117 *inner
= (*region
)->rgnBBox
;
5118 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5119 *outer
= (*region
)->rgnBBox
;
5120 DisposeRgn (region
);
5121 #endif /* not TARGET_API_MAC_CARBON */
5125 /* Calculate the absolute position in frame F
5126 from its current recorded position values and gravity. */
5129 x_calc_absolute_position (f
)
5132 int width_diff
= 0, height_diff
= 0;
5133 int flags
= f
->size_hint_flags
;
5136 /* We have nothing to do if the current position
5137 is already for the top-left corner. */
5138 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5141 /* Find the offsets of the outside upper-left corner of
5142 the inner window, with respect to the outer window. */
5143 mac_get_window_bounds (f
, &inner
, &outer
);
5145 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5146 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5148 /* Treat negative positions as relative to the leftmost bottommost
5149 position that fits on the screen. */
5150 if (flags
& XNegative
)
5151 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5153 - FRAME_PIXEL_WIDTH (f
)
5156 if (flags
& YNegative
)
5157 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5159 - FRAME_PIXEL_HEIGHT (f
)
5162 /* The left_pos and top_pos
5163 are now relative to the top and left screen edges,
5164 so the flags should correspond. */
5165 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5168 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5169 to really change the position, and 0 when calling from
5170 x_make_frame_visible (in that case, XOFF and YOFF are the current
5171 position values). It is -1 when calling from x_set_frame_parameters,
5172 which means, do adjust for borders but don't change the gravity. */
5175 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5177 register int xoff
, yoff
;
5180 if (change_gravity
> 0)
5184 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5186 f
->size_hint_flags
|= XNegative
;
5188 f
->size_hint_flags
|= YNegative
;
5189 f
->win_gravity
= NorthWestGravity
;
5191 x_calc_absolute_position (f
);
5194 x_wm_set_size_hint (f
, (long) 0, 0);
5196 #if TARGET_API_MAC_CARBON
5197 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5198 /* If the title bar is completely outside the screen, adjust the
5200 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5201 kWindowConstrainMoveRegardlessOfFit
5202 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5203 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5206 Rect inner
, outer
, screen_rect
, dummy
;
5207 RgnHandle region
= NewRgn ();
5209 mac_get_window_bounds (f
, &inner
, &outer
);
5210 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5211 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5212 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5213 f
->top_pos
+ f
->y_pixels_diff
, false);
5215 /* If the title bar is completely outside the screen, adjust the
5216 position. The variable `outer' holds the title bar rectangle.
5217 The variable `inner' holds slightly smaller one than `outer',
5218 so that the calculation of overlapping may not become too
5220 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5221 outer
= (*region
)->rgnBBox
;
5222 DisposeRgn (region
);
5224 InsetRect (&inner
, 8, 8);
5225 screen_rect
= qd
.screenBits
.bounds
;
5226 screen_rect
.top
+= GetMBarHeight ();
5228 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5230 if (inner
.right
<= screen_rect
.left
)
5231 f
->left_pos
= screen_rect
.left
;
5232 else if (inner
.left
>= screen_rect
.right
)
5233 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5235 if (inner
.bottom
<= screen_rect
.top
)
5236 f
->top_pos
= screen_rect
.top
;
5237 else if (inner
.top
>= screen_rect
.bottom
)
5238 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5240 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5241 f
->top_pos
+ f
->y_pixels_diff
, false);
5249 /* Call this to change the size of frame F's x-window.
5250 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5251 for this size change and subsequent size changes.
5252 Otherwise we leave the window gravity unchanged. */
5255 x_set_window_size (f
, change_gravity
, cols
, rows
)
5260 int pixelwidth
, pixelheight
;
5264 check_frame_size (f
, &rows
, &cols
);
5265 f
->scroll_bar_actual_width
5266 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5268 compute_fringe_widths (f
, 0);
5270 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5271 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5273 f
->win_gravity
= NorthWestGravity
;
5274 x_wm_set_size_hint (f
, (long) 0, 0);
5276 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5278 /* Now, strictly speaking, we can't be sure that this is accurate,
5279 but the window manager will get around to dealing with the size
5280 change request eventually, and we'll hear how it went when the
5281 ConfigureNotify event gets here.
5283 We could just not bother storing any of this information here,
5284 and let the ConfigureNotify event set everything up, but that
5285 might be kind of confusing to the Lisp code, since size changes
5286 wouldn't be reported in the frame parameters until some random
5287 point in the future when the ConfigureNotify event arrives.
5289 We pass 1 for DELAY since we can't run Lisp code inside of
5291 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5292 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5293 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5295 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5296 receive in the ConfigureNotify event; if we get what we asked
5297 for, then the event won't cause the screen to become garbaged, so
5298 we have to make sure to do it here. */
5299 SET_FRAME_GARBAGED (f
);
5301 XFlush (FRAME_X_DISPLAY (f
));
5303 /* If cursor was outside the new size, mark it as off. */
5304 mark_window_cursors_off (XWINDOW (f
->root_window
));
5306 /* Clear out any recollection of where the mouse highlighting was,
5307 since it might be in a place that's outside the new frame size.
5308 Actually checking whether it is outside is a pain in the neck,
5309 so don't try--just let the highlighting be done afresh with new size. */
5310 cancel_mouse_face (f
);
5315 /* Mouse warping. */
5317 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5320 x_set_mouse_position (f
, x
, y
)
5326 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5327 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5329 if (pix_x
< 0) pix_x
= 0;
5330 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5332 if (pix_y
< 0) pix_y
= 0;
5333 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5335 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5339 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5343 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5346 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5347 0, 0, 0, 0, pix_x
, pix_y
);
5353 /* focus shifting, raising and lowering. */
5356 x_focus_on_frame (f
)
5359 #if 0 /* This proves to be unpleasant. */
5363 /* I don't think that the ICCCM allows programs to do things like this
5364 without the interaction of the window manager. Whatever you end up
5365 doing with this code, do it to x_unfocus_frame too. */
5366 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5367 RevertToPointerRoot
, CurrentTime
);
5377 /* Raise frame F. */
5382 if (f
->async_visible
)
5385 SelectWindow (FRAME_MAC_WINDOW (f
));
5390 /* Lower frame F. */
5395 if (f
->async_visible
)
5398 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5404 XTframe_raise_lower (f
, raise_flag
)
5414 /* Change of visibility. */
5416 /* This tries to wait until the frame is really visible.
5417 However, if the window manager asks the user where to position
5418 the frame, this will return before the user finishes doing that.
5419 The frame will not actually be visible at that time,
5420 but it will become visible later when the window manager
5421 finishes with it. */
5424 x_make_frame_visible (f
)
5428 int original_top
, original_left
;
5432 if (! FRAME_VISIBLE_P (f
))
5434 /* We test FRAME_GARBAGED_P here to make sure we don't
5435 call x_set_offset a second time
5436 if we get to x_make_frame_visible a second time
5437 before the window gets really visible. */
5438 if (! FRAME_ICONIFIED_P (f
)
5439 && ! f
->output_data
.mac
->asked_for_visible
)
5440 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5442 f
->output_data
.mac
->asked_for_visible
= 1;
5444 #if TARGET_API_MAC_CARBON
5445 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5447 struct frame
*sf
= SELECTED_FRAME ();
5448 if (!FRAME_MAC_P (sf
))
5449 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5450 kWindowCenterOnMainScreen
);
5452 RepositionWindow (FRAME_MAC_WINDOW (f
),
5453 FRAME_MAC_WINDOW (sf
),
5454 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5455 kWindowCascadeStartAtParentWindowScreen
5457 kWindowCascadeOnParentWindowScreen
5460 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5463 ShowWindow (FRAME_MAC_WINDOW (f
));
5466 XFlush (FRAME_MAC_DISPLAY (f
));
5468 /* Synchronize to ensure Emacs knows the frame is visible
5469 before we do anything else. We do this loop with input not blocked
5470 so that incoming events are handled. */
5475 /* This must come after we set COUNT. */
5478 XSETFRAME (frame
, f
);
5480 /* Wait until the frame is visible. Process X events until a
5481 MapNotify event has been seen, or until we think we won't get a
5482 MapNotify at all.. */
5483 for (count
= input_signal_count
+ 10;
5484 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5486 /* Force processing of queued events. */
5489 /* Machines that do polling rather than SIGIO have been
5490 observed to go into a busy-wait here. So we'll fake an
5491 alarm signal to let the handler know that there's something
5492 to be read. We used to raise a real alarm, but it seems
5493 that the handler isn't always enabled here. This is
5495 if (input_polling_used ())
5497 /* It could be confusing if a real alarm arrives while
5498 processing the fake one. Turn it off and let the
5499 handler reset it. */
5500 extern void poll_for_input_1
P_ ((void));
5501 int old_poll_suppress_count
= poll_suppress_count
;
5502 poll_suppress_count
= 1;
5503 poll_for_input_1 ();
5504 poll_suppress_count
= old_poll_suppress_count
;
5507 /* See if a MapNotify event has been processed. */
5508 FRAME_SAMPLE_VISIBILITY (f
);
5513 /* Change from mapped state to withdrawn state. */
5515 /* Make the frame visible (mapped and not iconified). */
5518 x_make_frame_invisible (f
)
5521 /* Don't keep the highlight on an invisible frame. */
5522 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5523 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5527 HideWindow (FRAME_MAC_WINDOW (f
));
5529 /* We can't distinguish this from iconification
5530 just by the event that we get from the server.
5531 So we can't win using the usual strategy of letting
5532 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5533 and synchronize with the server to make sure we agree. */
5535 FRAME_ICONIFIED_P (f
) = 0;
5536 f
->async_visible
= 0;
5537 f
->async_iconified
= 0;
5542 /* Change window state from mapped to iconified. */
5548 /* Don't keep the highlight on an invisible frame. */
5549 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5550 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5553 /* Review: Since window is still visible in dock, still allow updates? */
5554 if (f
->async_iconified
)
5560 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5566 /* Free X resources of frame F. */
5569 x_free_frame_resources (f
)
5572 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5573 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5577 if (wp
!= tip_window
)
5578 remove_window_handler (wp
);
5581 if (wp
== tip_window
)
5582 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5583 closed' event. So we reset tip_window here. */
5586 free_frame_menubar (f
);
5588 if (FRAME_FACE_CACHE (f
))
5589 free_frame_faces (f
);
5593 if (FRAME_SIZE_HINTS (f
))
5594 xfree (FRAME_SIZE_HINTS (f
));
5596 xfree (f
->output_data
.mac
);
5597 f
->output_data
.mac
= NULL
;
5599 if (f
== dpyinfo
->x_focus_frame
)
5600 dpyinfo
->x_focus_frame
= 0;
5601 if (f
== dpyinfo
->x_focus_event_frame
)
5602 dpyinfo
->x_focus_event_frame
= 0;
5603 if (f
== dpyinfo
->x_highlight_frame
)
5604 dpyinfo
->x_highlight_frame
= 0;
5606 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5608 dpyinfo
->mouse_face_beg_row
5609 = dpyinfo
->mouse_face_beg_col
= -1;
5610 dpyinfo
->mouse_face_end_row
5611 = dpyinfo
->mouse_face_end_col
= -1;
5612 dpyinfo
->mouse_face_window
= Qnil
;
5613 dpyinfo
->mouse_face_deferred_gc
= 0;
5614 dpyinfo
->mouse_face_mouse_frame
= 0;
5621 /* Destroy the X window of frame F. */
5624 x_destroy_window (f
)
5627 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5629 x_free_frame_resources (f
);
5631 dpyinfo
->reference_count
--;
5635 /* Setting window manager hints. */
5637 /* Set the normal size hints for the window manager, for frame F.
5638 FLAGS is the flags word to use--or 0 meaning preserve the flags
5639 that the window now has.
5640 If USER_POSITION is nonzero, we set the USPosition
5641 flag (this is useful when FLAGS is 0). */
5643 x_wm_set_size_hint (f
, flags
, user_position
)
5648 int base_width
, base_height
, width_inc
, height_inc
;
5649 int min_rows
= 0, min_cols
= 0;
5650 XSizeHints
*size_hints
;
5652 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5653 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5654 width_inc
= FRAME_COLUMN_WIDTH (f
);
5655 height_inc
= FRAME_LINE_HEIGHT (f
);
5657 check_frame_size (f
, &min_rows
, &min_cols
);
5659 size_hints
= FRAME_SIZE_HINTS (f
);
5660 if (size_hints
== NULL
)
5662 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
5663 bzero (size_hints
, sizeof (XSizeHints
));
5666 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
5667 size_hints
->width_inc
= width_inc
;
5668 size_hints
->height_inc
= height_inc
;
5669 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
5670 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
5671 size_hints
->base_width
= base_width
;
5672 size_hints
->base_height
= base_height
;
5675 size_hints
->flags
= flags
;
5676 else if (user_position
)
5678 size_hints
->flags
&= ~ PPosition
;
5679 size_hints
->flags
|= USPosition
;
5683 #if 0 /* MAC_TODO: hide application instead of iconify? */
5684 /* Used for IconicState or NormalState */
5687 x_wm_set_window_state (f
, state
)
5691 #ifdef USE_X_TOOLKIT
5694 XtSetArg (al
[0], XtNinitialState
, state
);
5695 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5696 #else /* not USE_X_TOOLKIT */
5697 Window window
= FRAME_X_WINDOW (f
);
5699 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5700 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5702 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5703 #endif /* not USE_X_TOOLKIT */
5707 x_wm_set_icon_pixmap (f
, pixmap_id
)
5713 #ifndef USE_X_TOOLKIT
5714 Window window
= FRAME_X_WINDOW (f
);
5719 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5720 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5724 /* It seems there is no way to turn off use of an icon pixmap.
5725 The following line does it, only if no icon has yet been created,
5726 for some window managers. But with mwm it crashes.
5727 Some people say it should clear the IconPixmapHint bit in this case,
5728 but that doesn't work, and the X consortium said it isn't the
5729 right thing at all. Since there is no way to win,
5730 best to explicitly give up. */
5732 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5738 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5742 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
5743 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5746 #else /* not USE_X_TOOLKIT */
5748 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5749 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5751 #endif /* not USE_X_TOOLKIT */
5754 #endif /* MAC_TODO */
5757 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5761 #if 0 /* MAC_TODO: no icons on Mac */
5762 #ifdef USE_X_TOOLKIT
5763 Window window
= XtWindow (f
->output_data
.x
->widget
);
5765 Window window
= FRAME_X_WINDOW (f
);
5768 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5769 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5770 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5772 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5773 #endif /* MAC_TODO */
5777 /***********************************************************************
5779 ***********************************************************************/
5781 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5784 x_get_font_info (f
, font_idx
)
5788 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
5791 /* the global font name table */
5792 char **font_name_table
= NULL
;
5793 int font_name_table_size
= 0;
5794 int font_name_count
= 0;
5797 /* compare two strings ignoring case */
5799 stricmp (const char *s
, const char *t
)
5801 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
5804 return tolower (*s
) - tolower (*t
);
5807 /* compare two strings ignoring case and handling wildcard */
5809 wildstrieq (char *s1
, char *s2
)
5811 if (strcmp (s1
, "*") == 0 || strcmp (s2
, "*") == 0)
5814 return stricmp (s1
, s2
) == 0;
5817 /* Assume parameter 1 is fully qualified, no wildcards. */
5819 mac_font_pattern_match (fontname
, pattern
)
5823 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
5824 char *font_name_copy
= (char *) alloca (strlen (fontname
) + 1);
5827 /* Copy fontname so we can modify it during comparison. */
5828 strcpy (font_name_copy
, fontname
);
5833 /* Turn pattern into a regexp and do a regexp match. */
5834 for (; *pattern
; pattern
++)
5836 if (*pattern
== '?')
5838 else if (*pattern
== '*')
5849 return (fast_c_string_match_ignore_case (build_string (regex
),
5850 font_name_copy
) >= 0);
5853 /* Two font specs are considered to match if their foundry, family,
5854 weight, slant, and charset match. */
5856 mac_font_match (char *mf
, char *xf
)
5858 char m_foundry
[50], m_family
[50], m_weight
[20], m_slant
[2], m_charset
[20];
5859 char x_foundry
[50], x_family
[50], x_weight
[20], x_slant
[2], x_charset
[20];
5861 if (sscanf (mf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5862 m_foundry
, m_family
, m_weight
, m_slant
, m_charset
) != 5)
5863 return mac_font_pattern_match (mf
, xf
);
5865 if (sscanf (xf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5866 x_foundry
, x_family
, x_weight
, x_slant
, x_charset
) != 5)
5867 return mac_font_pattern_match (mf
, xf
);
5869 return (wildstrieq (m_foundry
, x_foundry
)
5870 && wildstrieq (m_family
, x_family
)
5871 && wildstrieq (m_weight
, x_weight
)
5872 && wildstrieq (m_slant
, x_slant
)
5873 && wildstrieq (m_charset
, x_charset
))
5874 || mac_font_pattern_match (mf
, xf
);
5878 static Lisp_Object Qbig5
, Qcn_gb
, Qsjis
, Qeuc_kr
;
5881 decode_mac_font_name (name
, size
, scriptcode
)
5884 #if TARGET_API_MAC_CARBON
5890 Lisp_Object coding_system
;
5891 struct coding_system coding
;
5897 coding_system
= Qbig5
;
5900 coding_system
= Qcn_gb
;
5903 coding_system
= Qsjis
;
5906 coding_system
= Qeuc_kr
;
5912 setup_coding_system (coding_system
, &coding
);
5913 coding
.src_multibyte
= 0;
5914 coding
.dst_multibyte
= 1;
5915 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5916 coding
.composing
= COMPOSITION_DISABLED
;
5917 buf
= (char *) alloca (size
);
5919 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
5920 bcopy (buf
, name
, coding
.produced
);
5921 name
[coding
.produced
] = '\0';
5926 mac_to_x_fontname (name
, size
, style
, scriptcode
)
5930 #if TARGET_API_MAC_CARBON
5936 char foundry
[32], family
[32], cs
[32];
5937 char xf
[256], *result
, *p
;
5939 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) != 3)
5941 strcpy(foundry
, "Apple");
5942 strcpy(family
, name
);
5946 case smTradChinese
: /* == kTextEncodingMacChineseTrad */
5947 strcpy(cs
, "big5-0");
5949 case smSimpChinese
: /* == kTextEncodingMacChineseSimp */
5950 strcpy(cs
, "gb2312.1980-0");
5952 case smJapanese
: /* == kTextEncodingMacJapanese */
5953 strcpy(cs
, "jisx0208.1983-sjis");
5956 /* Each Apple Japanese font is entered into the font table
5957 twice: once as a jisx0208.1983-sjis font and once as a
5958 jisx0201.1976-0 font. The latter can be used to display
5959 the ascii charset and katakana-jisx0201 charset. A
5960 negative script code signals that the name of this latter
5961 font is being built. */
5962 strcpy(cs
, "jisx0201.1976-0");
5964 case smKorean
: /* == kTextEncodingMacKorean */
5965 strcpy(cs
, "ksc5601.1989-0");
5967 #if TARGET_API_MAC_CARBON
5968 case kTextEncodingMacCyrillic
:
5969 strcpy(cs
, "mac-cyrillic");
5971 case kTextEncodingMacCentralEurRoman
:
5972 strcpy(cs
, "mac-centraleurroman");
5974 case kTextEncodingMacSymbol
:
5975 case kTextEncodingMacDingbats
:
5976 strcpy(cs
, "adobe-fontspecific");
5980 strcpy(cs
, "mac-roman");
5985 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5986 foundry
, family
, style
& bold
? "bold" : "medium",
5987 style
& italic
? 'i' : 'r', size
, size
* 10, size
* 10, cs
);
5989 result
= (char *) xmalloc (strlen (xf
) + 1);
5990 strcpy (result
, xf
);
5991 for (p
= result
; *p
; p
++)
5997 /* Convert an X font spec to the corresponding mac font name, which
5998 can then be passed to GetFNum after conversion to a Pascal string.
5999 For ordinary Mac fonts, this should just be their names, like
6000 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6001 collection contain their charset designation in their names, like
6002 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6003 names are handled accordingly. */
6005 x_font_name_to_mac_font_name (char *xf
, char *mf
)
6007 char foundry
[32], family
[32], weight
[20], slant
[2], cs
[32];
6008 Lisp_Object coding_system
= Qnil
;
6009 struct coding_system coding
;
6013 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6014 foundry
, family
, weight
, slant
, cs
) != 5 &&
6015 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6016 foundry
, family
, weight
, slant
, cs
) != 5)
6019 if (strcmp (cs
, "big5-0") == 0)
6020 coding_system
= Qbig5
;
6021 else if (strcmp (cs
, "gb2312.1980-0") == 0)
6022 coding_system
= Qcn_gb
;
6023 else if (strcmp (cs
, "jisx0208.1983-sjis") == 0
6024 || strcmp (cs
, "jisx0201.1976-0") == 0)
6025 coding_system
= Qsjis
;
6026 else if (strcmp (cs
, "ksc5601.1989-0") == 0)
6027 coding_system
= Qeuc_kr
;
6028 else if (strcmp (cs
, "mac-roman") == 0
6029 || strcmp (cs
, "mac-cyrillic") == 0
6030 || strcmp (cs
, "mac-centraleurroman") == 0
6031 || strcmp (cs
, "adobe-fontspecific") == 0)
6032 strcpy (mf
, family
);
6034 sprintf (mf
, "%s-%s-%s", foundry
, family
, cs
);
6036 if (!NILP (coding_system
))
6038 setup_coding_system (coding_system
, &coding
);
6039 coding
.src_multibyte
= 1;
6040 coding
.dst_multibyte
= 1;
6041 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6042 encode_coding (&coding
, family
, mf
, strlen (family
), sizeof (Str32
) - 1);
6043 mf
[coding
.produced
] = '\0';
6049 add_font_name_table_entry (char *font_name
)
6051 if (font_name_table_size
== 0)
6053 font_name_table_size
= 16;
6054 font_name_table
= (char **)
6055 xmalloc (font_name_table_size
* sizeof (char *));
6057 else if (font_name_count
+ 1 >= font_name_table_size
)
6059 font_name_table_size
+= 16;
6060 font_name_table
= (char **)
6061 xrealloc (font_name_table
,
6062 font_name_table_size
* sizeof (char *));
6065 font_name_table
[font_name_count
++] = font_name
;
6068 /* Sets up the table font_name_table to contain the list of all fonts
6069 in the system the first time the table is used so that the Resource
6070 Manager need not be accessed every time this information is
6074 init_font_name_table ()
6076 #if TARGET_API_MAC_CARBON
6079 if (Gestalt (gestaltSystemVersion
, &sv
) == noErr
&& sv
>= 0x1000)
6081 FMFontFamilyIterator ffi
;
6082 FMFontFamilyInstanceIterator ffii
;
6085 /* Create a dummy instance iterator here to avoid creating and
6086 destroying it in the loop. */
6087 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6089 /* Create an iterator to enumerate the font families. */
6090 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6093 FMDisposeFontFamilyInstanceIterator (&ffii
);
6097 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6103 TextEncoding encoding
;
6104 TextEncodingBase sc
;
6106 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6112 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6114 sc
= GetTextEncodingBase (encoding
);
6115 decode_mac_font_name (name
, sizeof (name
), sc
);
6117 /* Point the instance iterator at the current font family. */
6118 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6121 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6124 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6125 contained in Apple Japanese (SJIS) font. */
6129 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6131 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6133 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6135 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6140 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6142 if (sc
== smJapanese
)
6147 else if (sc
== -smJapanese
)
6152 /* Dispose of the iterators. */
6153 FMDisposeFontFamilyIterator (&ffi
);
6154 FMDisposeFontFamilyInstanceIterator (&ffii
);
6158 #endif /* TARGET_API_MAC_CARBON */
6160 SInt16 fontnum
, old_fontnum
;
6161 int num_mac_fonts
= CountResources('FOND');
6163 Handle font_handle
, font_handle_2
;
6164 short id
, scriptcode
;
6167 struct FontAssoc
*fat
;
6168 struct AsscEntry
*assc_entry
;
6170 GetPort (&port
); /* save the current font number used */
6171 #if TARGET_API_MAC_CARBON
6172 old_fontnum
= GetPortTextFont (port
);
6174 old_fontnum
= port
->txFont
;
6177 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6179 font_handle
= GetIndResource ('FOND', i
);
6183 GetResInfo (font_handle
, &id
, &type
, name
);
6184 GetFNum (name
, &fontnum
);
6190 scriptcode
= FontToScript (fontnum
);
6191 decode_mac_font_name (name
, sizeof (name
), scriptcode
);
6194 HLock (font_handle
);
6196 if (GetResourceSizeOnDisk (font_handle
)
6197 >= sizeof (struct FamRec
))
6199 fat
= (struct FontAssoc
*) (*font_handle
6200 + sizeof (struct FamRec
));
6202 = (struct AsscEntry
*) (*font_handle
6203 + sizeof (struct FamRec
)
6204 + sizeof (struct FontAssoc
));
6206 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6208 if (font_name_table_size
== 0)
6210 font_name_table_size
= 16;
6211 font_name_table
= (char **)
6212 xmalloc (font_name_table_size
* sizeof (char *));
6214 else if (font_name_count
>= font_name_table_size
)
6216 font_name_table_size
+= 16;
6217 font_name_table
= (char **)
6218 xrealloc (font_name_table
,
6219 font_name_table_size
* sizeof (char *));
6221 font_name_table
[font_name_count
++]
6222 = mac_to_x_fontname (name
,
6223 assc_entry
->fontSize
,
6224 assc_entry
->fontStyle
,
6226 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6227 parts are contained in Apple Japanese (SJIS)
6229 if (smJapanese
== scriptcode
)
6231 font_name_table
[font_name_count
++]
6232 = mac_to_x_fontname (name
,
6233 assc_entry
->fontSize
,
6234 assc_entry
->fontStyle
,
6240 HUnlock (font_handle
);
6241 font_handle_2
= GetNextFOND (font_handle
);
6242 ReleaseResource (font_handle
);
6243 font_handle
= font_handle_2
;
6245 while (ResError () == noErr
&& font_handle
);
6248 TextFont (old_fontnum
);
6249 #if TARGET_API_MAC_CARBON
6251 #endif /* TARGET_API_MAC_CARBON */
6256 mac_clear_font_name_table ()
6260 for (i
= 0; i
< font_name_count
; i
++)
6261 xfree (font_name_table
[i
]);
6262 xfree (font_name_table
);
6263 font_name_table
= NULL
;
6264 font_name_table_size
= font_name_count
= 0;
6268 enum xlfd_scalable_field_index
6270 XLFD_SCL_PIXEL_SIZE
,
6271 XLFD_SCL_POINT_SIZE
,
6276 static int xlfd_scalable_fields
[] =
6285 mac_c_string_match (regexp
, string
, nonspecial
, exact
)
6287 const char *string
, *nonspecial
;
6292 if (strcmp (string
, nonspecial
) == 0)
6293 return build_string (string
);
6295 else if (strstr (string
, nonspecial
))
6297 Lisp_Object str
= build_string (string
);
6299 if (fast_string_match (regexp
, str
) >= 0)
6307 mac_do_list_fonts (pattern
, maxnames
)
6312 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6313 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6316 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6317 char *longest_start
, *cur_start
, *nonspecial
;
6318 int longest_len
, exact
;
6320 if (font_name_table
== NULL
) /* Initialize when first used. */
6321 init_font_name_table ();
6323 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6326 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6327 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6328 fonts are scaled according to the specified size. */
6331 field
= xlfd_scalable_fields
;
6339 if ('1' <= *ptr
&& *ptr
<= '9')
6341 *val
= *ptr
++ - '0';
6342 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6343 *val
= *val
* 10 + *ptr
++ - '0';
6350 ptr
= strchr (ptr
, '-');
6353 while (ptr
&& i
< 14);
6355 if (i
== 14 && ptr
== NULL
)
6357 if (scl_val
[XLFD_SCL_POINT_SIZE
] > 0)
6359 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_POINT_SIZE
] / 10;
6360 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_POINT_SIZE
];
6362 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0)
6364 scl_val
[XLFD_SCL_POINT_SIZE
] =
6365 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10;
6367 else if (scl_val
[XLFD_SCL_AVGWIDTH
] > 0)
6369 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
] / 10;
6370 scl_val
[XLFD_SCL_POINT_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
];
6374 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6379 longest_start
= cur_start
= ptr
;
6383 /* Turn pattern into a regexp and do a regexp match. Also find the
6384 longest substring containing no special characters. */
6385 for (; *pattern
; pattern
++)
6387 if (*pattern
== '?' || *pattern
== '*')
6389 if (ptr
- cur_start
> longest_len
)
6391 longest_start
= cur_start
;
6392 longest_len
= ptr
- cur_start
;
6396 if (*pattern
== '?')
6398 else /* if (*pattern == '*') */
6406 *ptr
++ = tolower (*pattern
);
6409 if (ptr
- cur_start
> longest_len
)
6411 longest_start
= cur_start
;
6412 longest_len
= ptr
- cur_start
;
6418 nonspecial
= xmalloc (longest_len
+ 1);
6419 strncpy (nonspecial
, longest_start
, longest_len
);
6420 nonspecial
[longest_len
] = '\0';
6422 pattern_regex
= build_string (regex
);
6424 for (i
= 0; i
< font_name_count
; i
++)
6426 fontname
= mac_c_string_match (pattern_regex
, font_name_table
[i
],
6428 if (!NILP (fontname
))
6430 font_list
= Fcons (fontname
, font_list
);
6431 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6434 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6435 && (ptr
= strstr (font_name_table
[i
], "-0-0-75-75-m-0-")))
6437 int former_len
= ptr
- font_name_table
[i
];
6439 memcpy (scaled
, font_name_table
[i
], former_len
);
6440 sprintf (scaled
+ former_len
,
6441 "-%d-%d-75-75-m-%d-%s",
6442 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6443 scl_val
[XLFD_SCL_POINT_SIZE
],
6444 scl_val
[XLFD_SCL_AVGWIDTH
],
6445 ptr
+ sizeof ("-0-0-75-75-m-0-") - 1);
6446 fontname
= mac_c_string_match (pattern_regex
, scaled
,
6448 if (!NILP (fontname
))
6450 font_list
= Fcons (fontname
, font_list
);
6451 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6462 /* Return a list of at most MAXNAMES font specs matching the one in
6463 PATTERN. Cache matching fonts for patterns in
6464 dpyinfo->name_list_element to avoid looking them up again by
6465 calling mac_font_pattern_match (slow). Return as many matching
6466 fonts as possible if MAXNAMES = -1. */
6469 x_list_fonts (struct frame
*f
,
6470 Lisp_Object pattern
,
6474 Lisp_Object newlist
= Qnil
, tem
, key
;
6475 struct mac_display_info
*dpyinfo
= f
? FRAME_MAC_DISPLAY_INFO (f
) : NULL
;
6479 tem
= XCDR (dpyinfo
->name_list_element
);
6480 key
= Fcons (pattern
, make_number (maxnames
));
6482 newlist
= Fassoc (key
, tem
);
6483 if (!NILP (newlist
))
6485 newlist
= Fcdr_safe (newlist
);
6491 newlist
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6494 /* MAC_TODO: add code for matching outline fonts here */
6498 XSETCDR (dpyinfo
->name_list_element
,
6499 Fcons (Fcons (key
, newlist
),
6500 XCDR (dpyinfo
->name_list_element
)));
6510 /* Check that FONT is valid on frame F. It is if it can be found in F's
6514 x_check_font (f
, font
)
6519 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6521 xassert (font
!= NULL
);
6523 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6524 if (dpyinfo
->font_table
[i
].name
6525 && font
== dpyinfo
->font_table
[i
].font
)
6528 xassert (i
< dpyinfo
->n_fonts
);
6531 #endif /* GLYPH_DEBUG != 0 */
6533 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6534 Note: There are (broken) X fonts out there with invalid XFontStruct
6535 min_bounds contents. For example, handa@etl.go.jp reports that
6536 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6537 have font->min_bounds.width == 0. */
6540 x_font_min_bounds (font
, w
, h
)
6541 MacFontStruct
*font
;
6544 *h
= FONT_HEIGHT (font
);
6545 *w
= font
->min_bounds
.width
;
6549 /* Compute the smallest character width and smallest font height over
6550 all fonts available on frame F. Set the members smallest_char_width
6551 and smallest_font_height in F's x_display_info structure to
6552 the values computed. Value is non-zero if smallest_font_height or
6553 smallest_char_width become smaller than they were before. */
6556 x_compute_min_glyph_bounds (f
)
6560 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6561 MacFontStruct
*font
;
6562 int old_width
= dpyinfo
->smallest_char_width
;
6563 int old_height
= dpyinfo
->smallest_font_height
;
6565 dpyinfo
->smallest_font_height
= 100000;
6566 dpyinfo
->smallest_char_width
= 100000;
6568 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6569 if (dpyinfo
->font_table
[i
].name
)
6571 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6574 font
= (MacFontStruct
*) fontp
->font
;
6575 xassert (font
!= (MacFontStruct
*) ~0);
6576 x_font_min_bounds (font
, &w
, &h
);
6578 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6579 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6582 xassert (dpyinfo
->smallest_char_width
> 0
6583 && dpyinfo
->smallest_font_height
> 0);
6585 return (dpyinfo
->n_fonts
== 1
6586 || dpyinfo
->smallest_char_width
< old_width
6587 || dpyinfo
->smallest_font_height
< old_height
);
6591 /* Determine whether given string is a fully-specified XLFD: all 14
6592 fields are present, none is '*'. */
6595 is_fully_specified_xlfd (char *p
)
6603 for (i
= 0; i
< 13; i
++)
6605 q
= strchr (p
+ 1, '-');
6608 if (q
- p
== 2 && *(p
+ 1) == '*')
6613 if (strchr (p
+ 1, '-') != NULL
)
6616 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6623 const int kDefaultFontSize
= 9;
6626 /* XLoadQueryFont creates and returns an internal representation for a
6627 font in a MacFontStruct struct. There is really no concept
6628 corresponding to "loading" a font on the Mac. But we check its
6629 existence and find the font number and all other information for it
6630 and store them in the returned MacFontStruct. */
6632 static MacFontStruct
*
6633 XLoadQueryFont (Display
*dpy
, char *fontname
)
6635 int i
, size
, is_two_byte_font
, char_width
;
6638 SInt16 old_fontnum
, old_fontsize
;
6642 Style fontface
= normal
;
6643 MacFontStruct
*font
;
6644 FontInfo the_fontinfo
;
6645 char s_weight
[7], c_slant
;
6647 if (is_fully_specified_xlfd (fontname
))
6651 Lisp_Object matched_fonts
;
6653 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6654 if (NILP (matched_fonts
))
6656 name
= SDATA (XCAR (matched_fonts
));
6659 GetPort (&port
); /* save the current font number used */
6660 #if TARGET_API_MAC_CARBON
6661 old_fontnum
= GetPortTextFont (port
);
6662 old_fontsize
= GetPortTextSize (port
);
6663 old_fontface
= GetPortTextFace (port
);
6665 old_fontnum
= port
->txFont
;
6666 old_fontsize
= port
->txSize
;
6667 old_fontface
= port
->txFace
;
6670 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size
) != 1)
6671 size
= kDefaultFontSize
;
6673 if (sscanf (name
, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight
) == 1)
6674 if (strcmp (s_weight
, "bold") == 0)
6677 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant
) == 1)
6681 x_font_name_to_mac_font_name (name
, mfontname
);
6683 GetFNum (mfontname
, &fontnum
);
6687 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
6689 font
->fontname
= (char *) xmalloc (strlen (name
) + 1);
6690 bcopy (name
, font
->fontname
, strlen (name
) + 1);
6692 font
->mac_fontnum
= fontnum
;
6693 font
->mac_fontsize
= size
;
6694 font
->mac_fontface
= fontface
;
6695 font
->mac_scriptcode
= FontToScript (fontnum
);
6697 /* Apple Japanese (SJIS) font is listed as both
6698 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6699 (Roman script) in init_font_name_table (). The latter should be
6700 treated as a one-byte font. */
6705 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6707 && 0 == strcmp (cs
, "jisx0201.1976-0"))
6708 font
->mac_scriptcode
= smRoman
;
6711 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
6712 font
->mac_scriptcode
== smTradChinese
||
6713 font
->mac_scriptcode
== smSimpChinese
||
6714 font
->mac_scriptcode
== smKorean
;
6718 TextFace (fontface
);
6720 GetFontInfo (&the_fontinfo
);
6722 font
->ascent
= the_fontinfo
.ascent
;
6723 font
->descent
= the_fontinfo
.descent
;
6725 font
->min_byte1
= 0;
6726 if (is_two_byte_font
)
6727 font
->max_byte1
= 1;
6729 font
->max_byte1
= 0;
6730 font
->min_char_or_byte2
= 0x20;
6731 font
->max_char_or_byte2
= 0xff;
6733 if (is_two_byte_font
)
6735 /* Use the width of an "ideographic space" of that font because
6736 the_fontinfo.widMax returns the wrong width for some fonts. */
6737 switch (font
->mac_scriptcode
)
6740 char_width
= StringWidth("\p\x81\x40");
6743 char_width
= StringWidth("\p\xa1\x40");
6746 char_width
= StringWidth("\p\xa1\xa1");
6749 char_width
= StringWidth("\p\xa1\xa1");
6754 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6755 returns 15 for 12-point Monaco! */
6756 char_width
= CharWidth ('m');
6758 if (is_two_byte_font
)
6760 font
->per_char
= NULL
;
6762 if (fontface
& italic
)
6763 font
->max_bounds
.rbearing
= char_width
+ 1;
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
;
6775 font
->per_char
= (XCharStruct
*)
6776 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
6778 int c
, min_width
, max_width
;
6779 Rect char_bounds
, min_bounds
, max_bounds
;
6782 min_width
= max_width
= char_width
;
6783 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
6784 SetRect (&max_bounds
, 0, 0, 0, 0);
6785 for (c
= 0x20; c
<= 0xff; c
++)
6788 char_width
= CharWidth (ch
);
6789 QDTextBounds (1, &ch
, &char_bounds
);
6790 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
6791 char_width
, char_bounds
);
6792 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6793 character width of 0x7f. */
6796 min_width
= min (min_width
, char_width
);
6797 max_width
= max (max_width
, char_width
);
6799 if (!EmptyRect (&char_bounds
))
6801 SetRect (&min_bounds
,
6802 max (min_bounds
.left
, char_bounds
.left
),
6803 max (min_bounds
.top
, char_bounds
.top
),
6804 min (min_bounds
.right
, char_bounds
.right
),
6805 min (min_bounds
.bottom
, char_bounds
.bottom
));
6806 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
6809 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
6810 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
6811 if (min_width
== max_width
6812 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
6814 /* Fixed width and no overhangs. */
6815 xfree (font
->per_char
);
6816 font
->per_char
= NULL
;
6821 TextFont (old_fontnum
); /* restore previous font number, size and face */
6822 TextSize (old_fontsize
);
6823 TextFace (old_fontface
);
6830 mac_unload_font (dpyinfo
, font
)
6831 struct mac_display_info
*dpyinfo
;
6834 xfree (font
->fontname
);
6836 xfree (font
->per_char
);
6841 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6842 pointer to the structure font_info while allocating it dynamically.
6843 If SIZE is 0, load any size of font.
6844 If loading is failed, return NULL. */
6847 x_load_font (f
, fontname
, size
)
6849 register char *fontname
;
6852 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6853 Lisp_Object font_names
;
6855 /* Get a list of all the fonts that match this name. Once we
6856 have a list of matching fonts, we compare them against the fonts
6857 we already have by comparing names. */
6858 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
6860 if (!NILP (font_names
))
6865 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6866 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
6867 if (dpyinfo
->font_table
[i
].name
6868 && (!strcmp (dpyinfo
->font_table
[i
].name
,
6869 SDATA (XCAR (tail
)))
6870 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6871 SDATA (XCAR (tail
)))))
6872 return (dpyinfo
->font_table
+ i
);
6875 /* Load the font and add it to the table. */
6878 struct MacFontStruct
*font
;
6879 struct font_info
*fontp
;
6880 unsigned long value
;
6883 /* If we have found fonts by x_list_font, load one of them. If
6884 not, we still try to load a font by the name given as FONTNAME
6885 because XListFonts (called in x_list_font) of some X server has
6886 a bug of not finding a font even if the font surely exists and
6887 is loadable by XLoadQueryFont. */
6888 if (size
> 0 && !NILP (font_names
))
6889 fontname
= (char *) SDATA (XCAR (font_names
));
6892 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
6897 /* Find a free slot in the font table. */
6898 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6899 if (dpyinfo
->font_table
[i
].name
== NULL
)
6902 /* If no free slot found, maybe enlarge the font table. */
6903 if (i
== dpyinfo
->n_fonts
6904 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
6907 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
6908 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
6910 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
6913 fontp
= dpyinfo
->font_table
+ i
;
6914 if (i
== dpyinfo
->n_fonts
)
6917 /* Now fill in the slots of *FONTP. */
6919 bzero (fontp
, sizeof (*fontp
));
6921 fontp
->font_idx
= i
;
6922 fontp
->name
= (char *) xmalloc (strlen (font
->fontname
) + 1);
6923 bcopy (font
->fontname
, fontp
->name
, strlen (font
->fontname
) + 1);
6925 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
6927 /* Fixed width font. */
6928 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
6935 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
6936 pcm
= mac_per_char_metric (font
, &char2b
, 0);
6938 fontp
->space_width
= pcm
->width
;
6940 fontp
->space_width
= FONT_WIDTH (font
);
6944 int width
= pcm
->width
;
6945 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
6946 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
6947 width
+= pcm
->width
;
6948 fontp
->average_width
= width
/ 95;
6951 fontp
->average_width
= FONT_WIDTH (font
);
6954 fontp
->full_name
= fontp
->name
;
6956 fontp
->size
= font
->max_bounds
.width
;
6957 fontp
->height
= FONT_HEIGHT (font
);
6959 /* For some font, ascent and descent in max_bounds field is
6960 larger than the above value. */
6961 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6962 if (max_height
> fontp
->height
)
6963 fontp
->height
= max_height
;
6966 /* The slot `encoding' specifies how to map a character
6967 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6968 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6969 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6970 2:0xA020..0xFF7F). For the moment, we don't know which charset
6971 uses this font. So, we set information in fontp->encoding[1]
6972 which is never used by any charset. If mapping can't be
6973 decided, set FONT_ENCODING_NOT_DECIDED. */
6974 if (font
->mac_scriptcode
== smJapanese
)
6975 fontp
->encoding
[1] = 4;
6979 = (font
->max_byte1
== 0
6981 ? (font
->min_char_or_byte2
< 0x80
6982 ? (font
->max_char_or_byte2
< 0x80
6983 ? 0 /* 0x20..0x7F */
6984 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6985 : 1) /* 0xA0..0xFF */
6987 : (font
->min_byte1
< 0x80
6988 ? (font
->max_byte1
< 0x80
6989 ? (font
->min_char_or_byte2
< 0x80
6990 ? (font
->max_char_or_byte2
< 0x80
6991 ? 0 /* 0x2020..0x7F7F */
6992 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6993 : 3) /* 0x20A0..0x7FFF */
6994 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6995 : (font
->min_char_or_byte2
< 0x80
6996 ? (font
->max_char_or_byte2
< 0x80
6997 ? 2 /* 0xA020..0xFF7F */
6998 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6999 : 1))); /* 0xA0A0..0xFFFF */
7002 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7003 fontp
->baseline_offset
7004 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
7005 ? (long) value
: 0);
7006 fontp
->relative_compose
7007 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
7008 ? (long) value
: 0);
7009 fontp
->default_ascent
7010 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
7011 ? (long) value
: 0);
7013 fontp
->baseline_offset
= 0;
7014 fontp
->relative_compose
= 0;
7015 fontp
->default_ascent
= 0;
7018 /* Set global flag fonts_changed_p to non-zero if the font loaded
7019 has a character with a smaller width than any other character
7020 before, or if the font loaded has a smalle>r height than any
7021 other font loaded before. If this happens, it will make a
7022 glyph matrix reallocation necessary. */
7023 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
7030 /* Return a pointer to struct font_info of a font named FONTNAME for
7031 frame F. If no such font is loaded, return NULL. */
7034 x_query_font (f
, fontname
)
7036 register char *fontname
;
7038 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7041 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7042 if (dpyinfo
->font_table
[i
].name
7043 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7044 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7045 return (dpyinfo
->font_table
+ i
);
7050 /* Find a CCL program for a font specified by FONTP, and set the member
7051 `encoder' of the structure. */
7054 x_find_ccl_program (fontp
)
7055 struct font_info
*fontp
;
7057 Lisp_Object list
, elt
;
7059 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7063 && STRINGP (XCAR (elt
))
7064 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7070 struct ccl_program
*ccl
7071 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7073 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7076 fontp
->font_encoder
= ccl
;
7082 /* The Mac Event loop code */
7084 #if !TARGET_API_MAC_CARBON
7086 #include <Quickdraw.h>
7087 #include <Balloons.h>
7088 #include <Devices.h>
7090 #include <Gestalt.h>
7092 #include <Processes.h>
7094 #include <ToolUtils.h>
7095 #include <TextUtils.h>
7096 #include <Dialogs.h>
7099 #include <TextEncodingConverter.h>
7100 #include <Resources.h>
7105 #endif /* ! TARGET_API_MAC_CARBON */
7110 #define WINDOW_RESOURCE 128
7111 #define TERM_WINDOW_RESOURCE 129
7113 #define DEFAULT_NUM_COLS 80
7115 #define MIN_DOC_SIZE 64
7116 #define MAX_DOC_SIZE 32767
7118 /* sleep time for WaitNextEvent */
7119 #define WNE_SLEEP_AT_SUSPEND 10
7120 #define WNE_SLEEP_AT_RESUME 1
7122 /* true when cannot handle any Mac OS events */
7123 static int handling_window_update
= 0;
7126 /* the flag appl_is_suspended is used both for determining the sleep
7127 time to be passed to WaitNextEvent and whether the cursor should be
7128 drawn when updating the display. The cursor is turned off when
7129 Emacs is suspended. Redrawing it is unnecessary and what needs to
7130 be done depends on whether the cursor lies inside or outside the
7131 redraw region. So we might as well skip drawing it when Emacs is
7133 static Boolean app_is_suspended
= false;
7134 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7137 #define EXTRA_STACK_ALLOC (256 * 1024)
7139 #define ARGV_STRING_LIST_ID 129
7140 #define ABOUT_ALERT_ID 128
7141 #define RAM_TOO_LARGE_ALERT_ID 129
7143 Boolean terminate_flag
= false;
7145 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7146 Lisp_Object Qreverse
;
7148 /* True if using command key as meta key. */
7149 Lisp_Object Vmac_command_key_is_meta
;
7151 /* Modifier associated with the option key, or nil for normal behavior. */
7152 Lisp_Object Vmac_option_modifier
;
7154 /* True if the ctrl and meta keys should be reversed. */
7155 Lisp_Object Vmac_reverse_ctrl_meta
;
7157 /* True if the option and command modifiers should be used to emulate
7158 a three button mouse */
7159 Lisp_Object Vmac_emulate_three_button_mouse
;
7161 #if USE_CARBON_EVENTS
7162 /* True if the mouse wheel button (i.e. button 4) should map to
7163 mouse-2, instead of mouse-3. */
7164 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7166 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7167 for processing before Emacs sees it. */
7168 Lisp_Object Vmac_pass_command_to_system
;
7170 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7171 for processing before Emacs sees it. */
7172 Lisp_Object Vmac_pass_control_to_system
;
7175 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7176 to this text encoding */
7177 int mac_keyboard_text_encoding
;
7178 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
7180 /* Set in term/mac-win.el to indicate that event loop can now generate
7181 drag and drop events. */
7182 Lisp_Object Qmac_ready_for_drag_n_drop
;
7184 Lisp_Object drag_and_drop_file_list
;
7186 Point saved_menu_event_location
;
7188 #if !TARGET_API_MAC_CARBON
7189 /* Place holder for the default arrow cursor. */
7190 CursPtr arrow_cursor
;
7194 static void init_required_apple_events (void);
7196 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7198 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7199 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7200 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7202 #if TARGET_API_MAC_CARBON
7204 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7205 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7206 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7207 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7210 #if USE_CARBON_EVENTS
7212 /* Preliminary Support for the OSX Services Menu */
7213 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
7214 static void init_service_handler ();
7216 /* Window Event Handler */
7217 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7220 OSErr
install_window_handler (WindowPtr
);
7222 extern void init_emacs_passwd_dir ();
7223 extern int emacs_main (int, char **, char **);
7224 extern void check_alarm ();
7226 extern void initialize_applescript();
7227 extern void terminate_applescript();
7230 #if USE_CARBON_EVENTS
7231 mac_to_emacs_modifiers (UInt32 mods
)
7233 mac_to_emacs_modifiers (EventModifiers mods
)
7236 unsigned int result
= 0;
7237 if (mods
& macShiftKey
)
7238 result
|= shift_modifier
;
7239 if (mods
& macCtrlKey
)
7240 result
|= ctrl_modifier
;
7241 if (mods
& macMetaKey
)
7242 result
|= meta_modifier
;
7243 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7244 result
|= alt_modifier
;
7245 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7246 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7248 result
|= XUINT(val
);
7255 mac_get_emulated_btn ( UInt32 modifiers
)
7258 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7259 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7260 if (modifiers
& cmdKey
)
7261 result
= cmdIs3
? 2 : 1;
7262 else if (modifiers
& optionKey
)
7263 result
= cmdIs3
? 1 : 2;
7268 #if USE_CARBON_EVENTS
7269 /* Obtains the event modifiers from the event ref and then calls
7270 mac_to_emacs_modifiers. */
7272 mac_event_to_emacs_modifiers (EventRef eventRef
)
7275 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7276 sizeof (UInt32
), NULL
, &mods
);
7277 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7278 GetEventClass(eventRef
) == kEventClassMouse
)
7280 mods
&= ~(optionKey
| cmdKey
);
7282 return mac_to_emacs_modifiers (mods
);
7285 /* Given an event ref, return the code to use for the mouse button
7286 code in the emacs input_event. */
7288 mac_get_mouse_btn (EventRef ref
)
7290 EventMouseButton result
= kEventMouseButtonPrimary
;
7291 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7292 sizeof (EventMouseButton
), NULL
, &result
);
7295 case kEventMouseButtonPrimary
:
7296 if (NILP (Vmac_emulate_three_button_mouse
))
7300 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7301 sizeof (UInt32
), NULL
, &mods
);
7302 return mac_get_emulated_btn(mods
);
7304 case kEventMouseButtonSecondary
:
7305 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7306 case kEventMouseButtonTertiary
:
7307 case 4: /* 4 is the number for the mouse wheel button */
7308 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7314 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7315 events. However the click of the mouse wheel is not converted to a
7316 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7317 checks to see if it is a mouse up or down carbon event that has not
7318 been converted, and if so, converts it by hand (to be picked up in
7319 the XTread_socket loop). */
7320 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7322 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7323 /* Do special case for mouse wheel button. */
7324 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
7326 UInt32 kind
= GetEventKind (eventRef
);
7327 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
7329 eventRec
->what
= mouseDown
;
7332 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
7334 eventRec
->what
= mouseUp
;
7339 /* Need where and when. */
7341 GetEventParameter (eventRef
, kEventParamMouseLocation
,
7342 typeQDPoint
, NULL
, sizeof (Point
),
7343 NULL
, &eventRec
->where
);
7344 /* Use two step process because new event modifiers are
7345 32-bit and old are 16-bit. Currently, only loss is
7347 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
7348 typeUInt32
, NULL
, sizeof (UInt32
),
7350 eventRec
->modifiers
= mods
;
7352 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7363 Handle menubar_handle
;
7364 MenuHandle menu_handle
;
7366 menubar_handle
= GetNewMBar (128);
7367 if(menubar_handle
== NULL
)
7369 SetMenuBar (menubar_handle
);
7372 menu_handle
= GetMenuHandle (M_APPLE
);
7373 if(menu_handle
!= NULL
)
7374 AppendResMenu (menu_handle
,'DRVR');
7381 do_init_managers (void)
7383 #if !TARGET_API_MAC_CARBON
7384 InitGraf (&qd
.thePort
);
7386 FlushEvents (everyEvent
, 0);
7391 #endif /* !TARGET_API_MAC_CARBON */
7394 #if !TARGET_API_MAC_CARBON
7395 arrow_cursor
= &qd
.arrow
;
7397 /* set up some extra stack space for use by emacs */
7398 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7400 /* MaxApplZone must be called for AppleScript to execute more
7401 complicated scripts */
7404 #endif /* !TARGET_API_MAC_CARBON */
7408 do_check_ram_size (void)
7410 SInt32 physical_ram_size
, logical_ram_size
;
7412 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7413 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7414 || physical_ram_size
> (1 << VALBITS
)
7415 || logical_ram_size
> (1 << VALBITS
))
7417 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7423 do_window_update (WindowPtr win
)
7425 struct frame
*f
= mac_window_to_frame (win
);
7429 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7431 if (win
!= tip_window
)
7433 if (f
->async_visible
== 0)
7435 f
->async_visible
= 1;
7436 f
->async_iconified
= 0;
7437 SET_FRAME_GARBAGED (f
);
7439 /* An update event is equivalent to MapNotify on X, so report
7440 visibility changes properly. */
7441 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7442 /* Force a redisplay sooner or later to update the
7443 frame titles in case this is the second frame. */
7444 record_asynch_buffer_change ();
7450 handling_window_update
= 1;
7452 #if TARGET_API_MAC_CARBON
7454 RgnHandle region
= NewRgn ();
7456 GetPortVisibleRegion (GetWindowPort (win
), region
);
7457 UpdateControls (win
, region
);
7458 GetRegionBounds (region
, &r
);
7459 DisposeRgn (region
);
7462 UpdateControls (win
, win
->visRgn
);
7463 r
= (*win
->visRgn
)->rgnBBox
;
7465 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7467 handling_window_update
= 0;
7475 is_emacs_window (WindowPtr win
)
7477 Lisp_Object tail
, frame
;
7482 FOR_EACH_FRAME (tail
, frame
)
7483 if (FRAME_MAC_P (XFRAME (frame
)))
7484 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7493 /* Window-activate events will do the job. */
7498 wp
= front_emacs_window ();
7501 f
= mac_window_to_frame (wp
);
7505 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
7506 activate_scroll_bars (f
);
7510 app_is_suspended
= false;
7511 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7518 /* Window-deactivate events will do the job. */
7523 wp
= front_emacs_window ();
7526 f
= mac_window_to_frame (wp
);
7528 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
7530 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
7531 deactivate_scroll_bars (f
);
7535 app_is_suspended
= true;
7536 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7542 do_mouse_moved (mouse_pos
, f
)
7546 WindowPtr wp
= front_emacs_window ();
7547 struct x_display_info
*dpyinfo
;
7551 *f
= mac_window_to_frame (wp
);
7552 dpyinfo
= FRAME_MAC_DISPLAY_INFO (*f
);
7554 if (dpyinfo
->mouse_face_hidden
)
7556 dpyinfo
->mouse_face_hidden
= 0;
7557 clear_mouse_face (dpyinfo
);
7560 SetPortWindowPort (wp
);
7562 GlobalToLocal (&mouse_pos
);
7564 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
7565 x_scroll_bar_note_movement (tracked_scroll_bar
,
7567 - XINT (tracked_scroll_bar
->top
),
7568 TickCount() * (1000 / 60));
7570 note_mouse_movement (*f
, &mouse_pos
);
7576 do_apple_menu (SInt16 menu_item
)
7578 #if !TARGET_API_MAC_CARBON
7580 SInt16 da_driver_refnum
;
7582 if (menu_item
== I_ABOUT
)
7583 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7586 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7587 da_driver_refnum
= OpenDeskAcc (item_name
);
7589 #endif /* !TARGET_API_MAC_CARBON */
7593 do_menu_choice (SInt32 menu_choice
)
7595 SInt16 menu_id
, menu_item
;
7597 menu_id
= HiWord (menu_choice
);
7598 menu_item
= LoWord (menu_choice
);
7606 do_apple_menu (menu_item
);
7611 struct frame
*f
= mac_window_to_frame (front_emacs_window ());
7612 MenuHandle menu
= GetMenuHandle (menu_id
);
7617 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7618 menubar_selection_callback (f
, refcon
);
7627 /* Handle drags in size box. Based on code contributed by Ben
7628 Mesander and IM - Window Manager A. */
7631 do_grow_window (WindowPtr w
, EventRecord
*e
)
7634 int rows
, columns
, width
, height
;
7635 struct frame
*f
= mac_window_to_frame (w
);
7636 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
7637 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
7638 #if TARGET_API_MAC_CARBON
7644 if (size_hints
->flags
& PMinSize
)
7646 min_width
= size_hints
->min_width
;
7647 min_height
= size_hints
->min_height
;
7649 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7651 #if TARGET_API_MAC_CARBON
7652 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
7654 height
= new_rect
.bottom
- new_rect
.top
;
7655 width
= new_rect
.right
- new_rect
.left
;
7657 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7658 /* see if it really changed size */
7661 height
= HiWord (grow_size
);
7662 width
= LoWord (grow_size
);
7665 if (width
!= FRAME_PIXEL_WIDTH (f
)
7666 || height
!= FRAME_PIXEL_HEIGHT (f
))
7668 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7669 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7671 x_set_window_size (f
, 0, columns
, rows
);
7676 /* Handle clicks in zoom box. Calculation of "standard state" based
7677 on code in IM - Window Manager A and code contributed by Ben
7678 Mesander. The standard state of an Emacs window is 80-characters
7679 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7682 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7685 Rect zoom_rect
, port_rect
;
7687 int w_title_height
, columns
, rows
, width
, height
;
7688 struct frame
*f
= mac_window_to_frame (w
);
7690 #if TARGET_API_MAC_CARBON
7692 Point standard_size
;
7694 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7695 standard_size
.v
= FRAME_MAC_DISPLAY_INFO (f
)->height
;
7697 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7698 zoom_in_or_out
= inZoomIn
;
7701 /* Adjust the standard size according to character boundaries. */
7703 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7704 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7705 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7706 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7707 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
7708 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
7709 && port_rect
.left
== zoom_rect
.left
7710 && port_rect
.top
== zoom_rect
.top
)
7711 zoom_in_or_out
= inZoomIn
;
7713 zoom_in_or_out
= inZoomOut
;
7716 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
7718 #else /* not TARGET_API_MAC_CARBON */
7719 GetPort (&save_port
);
7721 SetPortWindowPort (w
);
7723 /* Clear window to avoid flicker. */
7724 EraseRect (&(w
->portRect
));
7725 if (zoom_in_or_out
== inZoomOut
)
7727 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
7728 LocalToGlobal (&top_left
);
7730 /* calculate height of window's title bar */
7731 w_title_height
= top_left
.v
- 1
7732 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
7734 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7735 zoom_rect
= qd
.screenBits
.bounds
;
7736 zoom_rect
.top
+= w_title_height
;
7737 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
7739 zoom_rect
.right
= zoom_rect
.left
7740 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7742 /* Adjust the standard size according to character boundaries. */
7743 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7745 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7747 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
7751 ZoomWindow (w
, zoom_in_or_out
, w
== front_emacs_window ());
7753 SetPort (save_port
);
7754 #endif /* not TARGET_API_MAC_CARBON */
7756 /* retrieve window size and update application values */
7757 #if TARGET_API_MAC_CARBON
7758 GetWindowPortBounds (w
, &port_rect
);
7760 port_rect
= w
->portRect
;
7762 height
= port_rect
.bottom
- port_rect
.top
;
7763 width
= port_rect
.right
- port_rect
.left
;
7765 if (width
!= FRAME_PIXEL_WIDTH (f
)
7766 || height
!= FRAME_PIXEL_HEIGHT (f
))
7768 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7769 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7771 change_frame_size (f
, rows
, columns
, 0, 1, 0);
7772 SET_FRAME_GARBAGED (f
);
7773 cancel_mouse_face (f
);
7775 FRAME_PIXEL_WIDTH (f
) = width
;
7776 FRAME_PIXEL_HEIGHT (f
) = height
;
7778 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
7781 /* Intialize AppleEvent dispatcher table for the required events. */
7783 init_required_apple_events ()
7788 /* Make sure we have apple events before starting. */
7789 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
7793 if (!(result
& (1 << gestaltAppleEventsPresent
)))
7796 #if TARGET_API_MAC_CARBON
7797 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7798 NewAEEventHandlerUPP
7799 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7802 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7803 NewAEEventHandlerProc
7804 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7810 #if TARGET_API_MAC_CARBON
7811 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7812 NewAEEventHandlerUPP
7813 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7816 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7817 NewAEEventHandlerProc
7818 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7824 #if TARGET_API_MAC_CARBON
7825 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7826 NewAEEventHandlerUPP
7827 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7830 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7831 NewAEEventHandlerProc
7832 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7838 #if TARGET_API_MAC_CARBON
7839 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7840 NewAEEventHandlerUPP
7841 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7844 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7845 NewAEEventHandlerProc
7846 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7853 #if USE_CARBON_EVENTS
7856 init_service_handler ()
7858 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
7859 {kEventClassService
, kEventServiceCopy
},
7860 {kEventClassService
, kEventServicePaste
}};
7861 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
7862 3, specs
, NULL
, NULL
);
7866 MAC_TODO: Check to see if this is called by AEProcessDesc...
7869 mac_handle_service_event (EventHandlerCallRef callRef
,
7870 EventRef event
, void *data
)
7872 OSStatus err
= noErr
;
7873 switch (GetEventKind (event
))
7875 case kEventServiceGetTypes
:
7877 CFMutableArrayRef copyTypes
, pasteTypes
;
7879 Boolean selection
= true;
7881 GetEventParameter(event, kEventParamServicePasteTypes,
7882 typeCFMutableArrayRef, NULL,
7883 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7885 GetEventParameter(event
, kEventParamServiceCopyTypes
,
7886 typeCFMutableArrayRef
, NULL
,
7887 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
7888 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
7890 CFArrayAppendValue (copyTypes
, type
);
7891 //CFArrayAppendValue (pasteTypes, type);
7895 case kEventServiceCopy
:
7897 ScrapRef currentScrap
, specificScrap
;
7901 GetCurrentScrap (¤tScrap
);
7903 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
7906 void *buffer
= xmalloc (byteCount
);
7909 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
7910 sizeof (ScrapRef
), NULL
, &specificScrap
);
7912 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
7913 &byteCount
, buffer
);
7915 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
7916 kScrapFlavorMaskNone
, byteCount
, buffer
);
7922 case kEventServicePaste
:
7925 // Get the current location
7927 ScrapRef specificScrap;
7928 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7929 sizeof(ScrapRef), NULL, &specificScrap);
7930 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7932 void * buffer = xmalloc(byteCount);
7933 if (buffer != NULL ) {
7934 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7935 &byteCount, buffer);
7937 // Actually place in the buffer
7939 // Get the current "selection" string here
7952 static pascal OSStatus
7953 mac_handle_window_event (next_handler
, event
, data
)
7954 EventHandlerCallRef next_handler
;
7958 extern Lisp_Object Qcontrol
;
7963 XSizeHints
*size_hints
;
7965 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
7966 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
7968 switch (GetEventKind (event
))
7970 case kEventWindowUpdate
:
7971 result
= CallNextEventHandler (next_handler
, event
);
7972 if (result
!= eventNotHandledErr
)
7975 do_window_update (wp
);
7978 case kEventWindowBoundsChanging
:
7979 result
= CallNextEventHandler (next_handler
, event
);
7980 if (result
!= eventNotHandledErr
)
7983 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
7984 NULL
, sizeof (UInt32
), NULL
, &attributes
);
7985 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
7986 if ((attributes
& kWindowBoundsChangeUserResize
)
7987 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
7988 == (PResizeInc
| PBaseSize
| PMinSize
)))
7993 GetEventParameter (event
, kEventParamCurrentBounds
,
7995 NULL
, sizeof (Rect
), NULL
, &bounds
);
7996 width
= bounds
.right
- bounds
.left
;
7997 height
= bounds
.bottom
- bounds
.top
;
7999 if (width
< size_hints
->min_width
)
8000 width
= size_hints
->min_width
;
8002 width
= size_hints
->base_width
8003 + (int) ((width
- size_hints
->base_width
)
8004 / (float) size_hints
->width_inc
+ .5)
8005 * size_hints
->width_inc
;
8007 if (height
< size_hints
->min_height
)
8008 height
= size_hints
->min_height
;
8010 height
= size_hints
->base_height
8011 + (int) ((height
- size_hints
->base_height
)
8012 / (float) size_hints
->height_inc
+ .5)
8013 * size_hints
->height_inc
;
8015 bounds
.right
= bounds
.left
+ width
;
8016 bounds
.bottom
= bounds
.top
+ height
;
8017 SetEventParameter (event
, kEventParamCurrentBounds
,
8018 typeQDRectangle
, sizeof (Rect
), &bounds
);
8024 return eventNotHandledErr
;
8026 #endif /* USE_CARBON_EVENTS */
8030 install_window_handler (window
)
8034 #if USE_CARBON_EVENTS
8035 EventTypeSpec specs
[] = {{kEventClassWindow
, kEventWindowUpdate
},
8036 {kEventClassWindow
, kEventWindowBoundsChanging
}};
8037 static EventHandlerUPP handle_window_event_UPP
= NULL
;
8039 if (handle_window_event_UPP
== NULL
)
8040 handle_window_event_UPP
= NewEventHandlerUPP (mac_handle_window_event
);
8042 err
= InstallWindowEventHandler (window
, handle_window_event_UPP
,
8043 GetEventTypeCount (specs
), specs
,
8046 #if TARGET_API_MAC_CARBON
8047 if (mac_do_track_dragUPP
== NULL
)
8048 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8049 if (mac_do_receive_dragUPP
== NULL
)
8050 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8053 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8055 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8061 remove_window_handler (window
)
8064 #if TARGET_API_MAC_CARBON
8065 if (mac_do_track_dragUPP
)
8066 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8067 if (mac_do_receive_dragUPP
)
8068 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8072 /* Open Application Apple Event */
8074 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8080 /* Defined in mac.c. */
8082 path_from_vol_dir_name (char *, int, short, long, char *);
8085 /* Called when we receive an AppleEvent with an ID of
8086 "kAEOpenDocuments". This routine gets the direct parameter,
8087 extracts the FSSpecs in it, and puts their names on a list. */
8088 #pragma options align=mac68k
8089 typedef struct SelectionRange
{
8090 short unused1
; // 0 (not used)
8091 short lineNum
; // line to select (<0 to specify range)
8092 long startRange
; // start of selection range (if line < 0)
8093 long endRange
; // end of selection range (if line < 0)
8094 long unused2
; // 0 (not used)
8095 long theDate
; // modification date/time
8097 #pragma options align=reset
8100 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8105 DescType actual_type
;
8107 SelectionRange position
;
8109 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8111 goto descriptor_error_exit
;
8113 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8115 drag_and_drop_file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8116 make_number (position
.startRange
+ 1),
8117 make_number (position
.endRange
+ 1)),
8118 drag_and_drop_file_list
);
8120 /* Check to see that we got all of the required parameters from the
8121 event descriptor. For an 'odoc' event this should just be the
8123 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8124 &actual_type
, (Ptr
) &keyword
,
8125 sizeof (keyword
), &actual_size
);
8126 /* No error means that we found some unused parameters.
8127 errAEDescNotFound means that there are no more parameters. If we
8128 get an error code other than that, flag it. */
8129 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8131 err
= errAEEventNotHandled
;
8136 /* Got all the parameters we need. Now, go through the direct
8137 object list and parse it up. */
8139 long num_files_to_open
;
8141 err
= AECountItems (&the_desc
, &num_files_to_open
);
8146 /* AE file list is one based so just use that for indexing here. */
8147 for (i
= 1; i
<= num_files_to_open
; i
++)
8149 char unix_path_name
[MAXPATHLEN
];
8153 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8154 &actual_type
, &fref
, sizeof (FSRef
),
8156 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8159 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8164 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8165 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8166 if (err
!= noErr
) continue;
8168 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
8169 sizeof (unix_path_name
) - 1) == noErr
)
8171 /* x-dnd functions expect undecoded filenames. */
8172 drag_and_drop_file_list
=
8173 Fcons (make_unibyte_string (unix_path_name
,
8174 strlen (unix_path_name
)),
8175 drag_and_drop_file_list
);
8181 /* Nuke the coerced file list in any case */
8182 err2
= AEDisposeDesc(&the_desc
);
8184 descriptor_error_exit
:
8185 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8190 #if TARGET_API_MAC_CARBON
8192 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8193 void *handlerRefCon
, DragReference theDrag
)
8195 static int can_accept
;
8198 ItemReference theItem
;
8199 FlavorFlags theFlags
;
8202 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8203 return dragNotAcceptedErr
;
8207 case kDragTrackingEnterHandler
:
8208 CountDragItems (theDrag
, &items
);
8210 for (index
= 1; index
<= items
; index
++)
8212 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8213 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8214 if (result
== noErr
)
8222 case kDragTrackingEnterWindow
:
8225 RgnHandle hilite_rgn
= NewRgn ();
8227 struct frame
*f
= mac_window_to_frame (window
);
8229 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
8230 GetWindowPortBounds (window
, &r
);
8231 OffsetRect (&r
, -r
.left
, -r
.top
);
8232 RectRgn (hilite_rgn
, &r
);
8233 ShowDragHilite (theDrag
, hilite_rgn
, true);
8234 DisposeRgn (hilite_rgn
);
8235 SetThemeCursor (kThemeCopyArrowCursor
);
8239 case kDragTrackingInWindow
:
8242 case kDragTrackingLeaveWindow
:
8245 struct frame
*f
= mac_window_to_frame (window
);
8247 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
8248 HideDragHilite (theDrag
);
8249 SetThemeCursor (kThemeArrowCursor
);
8253 case kDragTrackingLeaveHandler
:
8261 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8262 DragReference theDrag
)
8266 FlavorFlags theFlags
;
8269 ItemReference theItem
;
8271 Size size
= sizeof (HFSFlavor
);
8273 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8274 return dragNotAcceptedErr
;
8276 drag_and_drop_file_list
= Qnil
;
8277 GetDragMouse (theDrag
, &mouse
, 0L);
8278 CountDragItems (theDrag
, &items
);
8279 for (index
= 1; index
<= items
; index
++)
8281 /* Only handle file references. */
8282 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8283 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8284 if (result
== noErr
)
8289 char unix_path_name
[MAXPATHLEN
];
8291 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8293 /* Use Carbon routines, otherwise it converts the file name
8294 to /Macintosh HD/..., which is not correct. */
8295 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8296 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8298 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
8299 sizeof (unix_path_name
) - 1) == noErr
)
8301 /* x-dnd functions expect undecoded filenames. */
8302 drag_and_drop_file_list
=
8303 Fcons (make_unibyte_string (unix_path_name
,
8304 strlen (unix_path_name
)),
8305 drag_and_drop_file_list
);
8308 /* If there are items in the list, construct an event and post it to
8309 the queue like an interrupt using kbd_buffer_store_event. */
8310 if (!NILP (drag_and_drop_file_list
))
8312 struct input_event event
;
8314 struct frame
*f
= mac_window_to_frame (window
);
8317 GlobalToLocal (&mouse
);
8318 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8320 event
.kind
= DRAG_N_DROP_EVENT
;
8322 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8323 event
.timestamp
= TickCount () * (1000 / 60);
8324 XSETINT (event
.x
, mouse
.h
);
8325 XSETINT (event
.y
, mouse
.v
);
8326 XSETFRAME (frame
, f
);
8327 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8329 /* Post to the interrupt queue */
8330 kbd_buffer_store_event (&event
);
8331 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8333 ProcessSerialNumber psn
;
8334 GetCurrentProcess (&psn
);
8335 SetFrontProcess (&psn
);
8341 return dragNotAcceptedErr
;
8346 /* Print Document Apple Event */
8348 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8350 return errAEEventNotHandled
;
8355 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8357 /* FixMe: Do we need an unwind-protect or something here? And what
8358 do we do about unsaved files. Currently just forces quit rather
8359 than doing recursive callback to get user input. */
8361 terminate_flag
= true;
8363 /* Fkill_emacs doesn't return. We have to return. (TI) */
8370 profiler_exit_proc ()
8372 ProfilerDump ("\pEmacs.prof");
8377 /* These few functions implement Emacs as a normal Mac application
8378 (almost): set up the heap and the Toolbox, handle necessary
8379 system events plus a few simple menu events. They also set up
8380 Emacs's access to functions defined in the rest of this file.
8381 Emacs uses function hooks to perform all its terminal I/O. A
8382 complete list of these functions appear in termhooks.h. For what
8383 they do, read the comments there and see also w32term.c and
8384 xterm.c. What's noticeably missing here is the event loop, which
8385 is normally present in most Mac application. After performing the
8386 necessary Mac initializations, main passes off control to
8387 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8388 mac_read_socket (defined further below) to read input. This is
8389 where WaitNextEvent is called to process Mac events. This is also
8390 where check_alarm in sysdep.c is called to simulate alarm signals.
8391 This makes the cursor jump back to its correct position after
8392 briefly jumping to that of the matching parenthesis, print useful
8393 hints and prompts in the minibuffer after the user stops typing for
8401 #if __profile__ /* is the profiler on? */
8402 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
8407 /* set creator and type for files created by MSL */
8412 do_init_managers ();
8417 do_check_ram_size ();
8420 init_emacs_passwd_dir ();
8424 initialize_applescript ();
8426 init_required_apple_events ();
8432 /* set up argv array from STR# resource */
8433 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
8437 /* free up AppleScript resources on exit */
8438 atexit (terminate_applescript
);
8440 #if __profile__ /* is the profiler on? */
8441 atexit (profiler_exit_proc
);
8444 /* 3rd param "envp" never used in emacs_main */
8445 (void) emacs_main (argc
, argv
, 0);
8448 /* Never reached - real exit in Fkill_emacs */
8453 /* Table for translating Mac keycode to X keysym values. Contributed
8454 by Sudhir Shenoy. */
8455 static unsigned char keycode_to_xkeysym_table
[] = {
8456 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8457 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8458 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8460 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8461 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8462 /*0x38*/ 0, 0, 0, 0,
8463 /*0x3C*/ 0, 0, 0, 0,
8465 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8466 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8467 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8468 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8470 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8471 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8472 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8473 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8475 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8476 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8477 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8478 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8480 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8481 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8482 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8483 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8487 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8489 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8490 return *xKeySym
!= 0;
8493 #if !USE_CARBON_EVENTS
8494 static RgnHandle mouse_region
= NULL
;
8497 mac_wait_next_event (er
, sleep_time
, dequeue
)
8502 static EventRecord er_buf
= {nullEvent
};
8503 UInt32 target_tick
, current_tick
;
8504 EventMask event_mask
;
8506 if (mouse_region
== NULL
)
8507 mouse_region
= NewRgn ();
8509 event_mask
= everyEvent
;
8510 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8511 event_mask
-= highLevelEventMask
;
8513 current_tick
= TickCount ();
8514 target_tick
= current_tick
+ sleep_time
;
8516 if (er_buf
.what
== nullEvent
)
8517 while (!WaitNextEvent (event_mask
, &er_buf
,
8518 target_tick
- current_tick
, mouse_region
))
8520 current_tick
= TickCount ();
8521 if (target_tick
<= current_tick
)
8527 er_buf
.what
= nullEvent
;
8530 #endif /* not USE_CARBON_EVENTS */
8532 /* Emacs calls this whenever it wants to read an input event from the
8535 XTread_socket (sd
, expected
, hold_quit
)
8537 struct input_event
*hold_quit
;
8539 struct input_event inev
;
8541 #if USE_CARBON_EVENTS
8543 EventTargetRef toolbox_dispatcher
;
8546 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8548 if (interrupt_input_blocked
)
8550 interrupt_input_pending
= 1;
8554 interrupt_input_pending
= 0;
8557 /* So people can tell when we have read the available input. */
8558 input_signal_count
++;
8560 /* Don't poll for events to process (specifically updateEvt) if
8561 window update currently already in progress. A call to redisplay
8562 (in do_window_update) can be preempted by another call to
8563 redisplay, causing blank regions to be left on the screen and the
8564 cursor to be left at strange places. */
8565 if (handling_window_update
)
8572 Fkill_emacs (make_number (1));
8574 #if USE_CARBON_EVENTS
8575 toolbox_dispatcher
= GetEventDispatcherTarget ();
8577 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8578 kEventRemoveFromQueue
, &eventRef
))
8579 #else /* !USE_CARBON_EVENTS */
8580 while (mac_wait_next_event (&er
, 0, true))
8581 #endif /* !USE_CARBON_EVENTS */
8586 /* It is necessary to set this (additional) argument slot of an
8587 event to nil because keyboard.c protects incompletely
8588 processed event from being garbage collected by placing them
8589 in the kbd_buffer_gcpro vector. */
8591 inev
.kind
= NO_EVENT
;
8594 #if USE_CARBON_EVENTS
8595 /* Handle new events */
8596 if (!mac_convert_event_ref (eventRef
, &er
))
8597 switch (GetEventClass (eventRef
))
8599 case kEventClassWindow
:
8600 if (GetEventKind (eventRef
) == kEventWindowBoundsChanged
)
8602 WindowPtr window_ptr
;
8603 GetEventParameter(eventRef
, kEventParamDirectObject
,
8604 typeWindowRef
, NULL
, sizeof(WindowPtr
),
8606 f
= mac_window_to_frame (window_ptr
);
8607 if (f
&& !f
->async_iconified
)
8608 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8609 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8612 case kEventClassMouse
:
8613 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
8617 WindowPtr window_ptr
= front_emacs_window ();
8619 if (!IsValidWindowPtr (window_ptr
))
8625 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
8626 typeSInt32
, NULL
, sizeof (SInt32
),
8628 GetEventParameter(eventRef
, kEventParamMouseLocation
,
8629 typeQDPoint
, NULL
, sizeof (Point
),
8631 inev
.kind
= WHEEL_EVENT
;
8633 inev
.modifiers
= (mac_event_to_emacs_modifiers (eventRef
)
8634 | ((delta
< 0) ? down_modifier
8636 SetPortWindowPort (window_ptr
);
8637 GlobalToLocal (&point
);
8638 XSETINT (inev
.x
, point
.h
);
8639 XSETINT (inev
.y
, point
.v
);
8640 XSETFRAME (inev
.frame_or_window
,
8641 mac_window_to_frame (window_ptr
));
8642 inev
.timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
8645 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8650 /* Send the event to the appropriate receiver. */
8651 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8654 #endif /* USE_CARBON_EVENTS */
8660 WindowPtr window_ptr
;
8664 #if USE_CARBON_EVENTS
8665 /* This is needed to send mouse events like aqua window
8666 buttons to the correct handler. */
8667 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8668 != eventNotHandledErr
)
8672 if (dpyinfo
->grabbed
&& last_mouse_frame
8673 && FRAME_LIVE_P (last_mouse_frame
))
8675 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
8676 part_code
= inContent
;
8680 part_code
= FindWindow (er
.where
, &window_ptr
);
8681 if (tip_window
&& window_ptr
== tip_window
)
8683 HideWindow (tip_window
);
8684 part_code
= FindWindow (er
.where
, &window_ptr
);
8688 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
8694 f
= mac_window_to_frame (front_emacs_window ());
8695 saved_menu_event_location
= er
.where
;
8696 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
8697 XSETFRAME (inev
.frame_or_window
, f
);
8701 if (window_ptr
!= front_emacs_window ())
8702 SelectWindow (window_ptr
);
8705 SInt16 control_part_code
;
8707 Point mouse_loc
= er
.where
;
8709 f
= mac_window_to_frame (window_ptr
);
8710 /* convert to local coordinates of new window */
8711 SetPortWindowPort (window_ptr
);
8713 GlobalToLocal (&mouse_loc
);
8714 #if TARGET_API_MAC_CARBON
8715 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
8716 &control_part_code
);
8718 control_part_code
= FindControl (mouse_loc
, window_ptr
,
8722 #if USE_CARBON_EVENTS
8723 inev
.code
= mac_get_mouse_btn (eventRef
);
8724 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
8726 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
8727 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
8729 XSETINT (inev
.x
, mouse_loc
.h
);
8730 XSETINT (inev
.y
, mouse_loc
.v
);
8731 inev
.timestamp
= er
.when
* (1000 / 60);
8732 /* ticks to milliseconds */
8734 if (dpyinfo
->grabbed
&& tracked_scroll_bar
8735 #if TARGET_API_MAC_CARBON
8738 || control_part_code
!= 0
8742 struct scroll_bar
*bar
;
8744 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
8746 bar
= tracked_scroll_bar
;
8747 control_part_code
= kControlIndicatorPart
;
8750 bar
= (struct scroll_bar
*) GetControlReference (ch
);
8751 x_scroll_bar_handle_click (bar
, control_part_code
,
8753 if (er
.what
== mouseDown
8754 && control_part_code
== kControlIndicatorPart
)
8755 tracked_scroll_bar
= bar
;
8757 tracked_scroll_bar
= NULL
;
8762 int x
= mouse_loc
.h
;
8763 int y
= mouse_loc
.v
;
8765 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
8766 if (EQ (window
, f
->tool_bar_window
))
8768 if (er
.what
== mouseDown
)
8769 handle_tool_bar_click (f
, x
, y
, 1, 0);
8771 handle_tool_bar_click (f
, x
, y
, 0,
8777 XSETFRAME (inev
.frame_or_window
, f
);
8778 inev
.kind
= MOUSE_CLICK_EVENT
;
8782 if (er
.what
== mouseDown
)
8784 dpyinfo
->grabbed
|= (1 << inev
.code
);
8785 last_mouse_frame
= f
;
8786 /* Ignore any mouse motion that happened
8787 before this event; any subsequent
8788 mouse-movement Emacs events should reflect
8789 only motion after the ButtonPress. */
8794 last_tool_bar_item
= -1;
8798 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
8799 /* If a button is released though it was not
8800 previously pressed, that would be because
8801 of multi-button emulation. */
8802 dpyinfo
->grabbed
= 0;
8804 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
8810 inev
.modifiers
|= down_modifier
;
8813 inev
.modifiers
|= up_modifier
;
8820 #if TARGET_API_MAC_CARBON
8821 DragWindow (window_ptr
, er
.where
, NULL
);
8822 #else /* not TARGET_API_MAC_CARBON */
8823 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
8824 #endif /* not TARGET_API_MAC_CARBON */
8825 /* Update the frame parameters. */
8827 struct frame
*f
= mac_window_to_frame (window_ptr
);
8829 if (f
&& !f
->async_iconified
)
8830 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8835 if (TrackGoAway (window_ptr
, er
.where
))
8837 inev
.kind
= DELETE_WINDOW_EVENT
;
8838 XSETFRAME (inev
.frame_or_window
,
8839 mac_window_to_frame (window_ptr
));
8843 /* window resize handling added --ben */
8845 do_grow_window (window_ptr
, &er
);
8848 /* window zoom handling added --ben */
8851 if (TrackBox (window_ptr
, er
.where
, part_code
))
8852 do_zoom_window (window_ptr
, part_code
);
8862 #if USE_CARBON_EVENTS
8863 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8864 != eventNotHandledErr
)
8867 do_window_update ((WindowPtr
) er
.message
);
8872 #if USE_CARBON_EVENTS
8873 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8874 != eventNotHandledErr
)
8877 switch ((er
.message
>> 24) & 0x000000FF)
8879 case suspendResumeMessage
:
8880 if ((er
.message
& resumeFlag
) == 1)
8886 case mouseMovedMessage
:
8887 #if !USE_CARBON_EVENTS
8888 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
8889 er
.where
.h
+ 1, er
.where
.v
+ 1);
8891 previous_help_echo_string
= help_echo_string
;
8892 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
8895 do_mouse_moved (er
.where
, &f
);
8897 /* If the contents of the global variable
8898 help_echo_string has changed, generate a
8900 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
8908 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
8910 #if USE_CARBON_EVENTS
8911 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8912 != eventNotHandledErr
)
8915 if (window_ptr
== tip_window
)
8917 HideWindow (tip_window
);
8921 if (!is_emacs_window (window_ptr
))
8924 f
= mac_window_to_frame (window_ptr
);
8926 if ((er
.modifiers
& activeFlag
) != 0)
8928 /* A window has been activated */
8929 Point mouse_loc
= er
.where
;
8931 x_new_focus_frame (dpyinfo
, f
);
8932 activate_scroll_bars (f
);
8934 SetPortWindowPort (window_ptr
);
8935 GlobalToLocal (&mouse_loc
);
8936 /* Window-activated event counts as mouse movement,
8937 so update things that depend on mouse position. */
8938 note_mouse_movement (mac_window_to_frame (window_ptr
),
8943 /* A window has been deactivated */
8944 dpyinfo
->grabbed
= 0;
8946 if (f
== dpyinfo
->x_focus_frame
)
8948 x_new_focus_frame (dpyinfo
, 0);
8949 deactivate_scroll_bars (f
);
8953 if (f
== dpyinfo
->mouse_face_mouse_frame
)
8955 /* If we move outside the frame, then we're
8956 certainly no longer on any text in the
8958 clear_mouse_face (dpyinfo
);
8959 dpyinfo
->mouse_face_mouse_frame
= 0;
8962 /* Generate a nil HELP_EVENT to cancel a help-echo.
8963 Do it only if there's something to cancel.
8964 Otherwise, the startup message is cleared when the
8965 mouse leaves the frame. */
8966 if (any_help_event_p
)
8975 int keycode
= (er
.message
& keyCodeMask
) >> 8;
8978 #if USE_CARBON_EVENTS && defined (MAC_OSX)
8979 /* When using Carbon Events, we need to pass raw keyboard
8980 events to the TSM ourselves. If TSM handles it, it
8981 will pass back noErr, otherwise it will pass back
8982 "eventNotHandledErr" and we can process it
8984 if ((!NILP (Vmac_pass_command_to_system
)
8985 || !(er
.modifiers
& cmdKey
))
8986 && (!NILP (Vmac_pass_control_to_system
)
8987 || !(er
.modifiers
& controlKey
)))
8988 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8989 != eventNotHandledErr
)
8993 #if TARGET_API_MAC_CARBON
8994 if (!IsValidWindowPtr (front_emacs_window ()))
9003 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
9005 clear_mouse_face (dpyinfo
);
9006 dpyinfo
->mouse_face_hidden
= 1;
9009 if (keycode_to_xkeysym (keycode
, &xkeysym
))
9011 inev
.code
= 0xff00 | xkeysym
;
9012 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
9016 if (er
.modifiers
& (controlKey
|
9017 (NILP (Vmac_command_key_is_meta
) ? optionKey
9020 /* This code comes from Keyboard Resource,
9021 Appendix C of IM - Text. This is necessary
9022 since shift is ignored in KCHR table
9023 translation when option or command is pressed.
9024 It also does not translate correctly
9025 control-shift chars like C-% so mask off shift
9027 int new_modifiers
= er
.modifiers
& 0xe600;
9028 /* mask off option and command */
9029 int new_keycode
= keycode
| new_modifiers
;
9030 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9031 unsigned long some_state
= 0;
9032 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9033 &some_state
) & 0xff;
9034 } else if (!NILP(Vmac_option_modifier
) && (er
.modifiers
& optionKey
))
9036 /* When using the option key as an emacs modifier, convert
9037 the pressed key code back to one without the Mac option
9038 modifier applied. */
9039 int new_modifiers
= er
.modifiers
& ~optionKey
;
9040 int new_keycode
= keycode
| new_modifiers
;
9041 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9042 unsigned long some_state
= 0;
9043 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9044 &some_state
) & 0xff;
9047 inev
.code
= er
.message
& charCodeMask
;
9048 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9052 /* If variable mac-convert-keyboard-input-to-latin-1 is
9053 non-nil, convert non-ASCII characters typed at the Mac
9054 keyboard (presumed to be in the Mac Roman encoding) to
9055 iso-latin-1 encoding before they are passed to Emacs.
9056 This enables the Mac keyboard to be used to enter
9057 non-ASCII iso-latin-1 characters directly. */
9058 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
9059 && inev
.kind
== ASCII_KEYSTROKE_EVENT
&& inev
.code
>= 128)
9061 static TECObjectRef converter
= NULL
;
9062 OSStatus the_err
= noErr
;
9063 OSStatus convert_status
= noErr
;
9065 if (converter
== NULL
)
9067 the_err
= TECCreateConverter (&converter
,
9068 kTextEncodingMacRoman
,
9069 mac_keyboard_text_encoding
);
9070 current_mac_keyboard_text_encoding
9071 = mac_keyboard_text_encoding
;
9073 else if (mac_keyboard_text_encoding
9074 != current_mac_keyboard_text_encoding
)
9076 /* Free the converter for the current encoding
9077 before creating a new one. */
9078 TECDisposeConverter (converter
);
9079 the_err
= TECCreateConverter (&converter
,
9080 kTextEncodingMacRoman
,
9081 mac_keyboard_text_encoding
);
9082 current_mac_keyboard_text_encoding
9083 = mac_keyboard_text_encoding
;
9086 if (the_err
== noErr
)
9088 unsigned char ch
= inev
.code
;
9089 ByteCount actual_input_length
, actual_output_length
;
9090 unsigned char outbuf
[32];
9092 convert_status
= TECConvertText (converter
, &ch
, 1,
9093 &actual_input_length
,
9095 &actual_output_length
);
9096 if (convert_status
== noErr
9097 && actual_input_length
== 1
9098 && actual_output_length
== 1)
9099 inev
.code
= *outbuf
;
9101 /* Reset internal states of the converter object.
9102 If it fails, create another one. */
9103 convert_status
= TECFlushText (converter
, outbuf
,
9105 &actual_output_length
);
9106 if (convert_status
!= noErr
)
9108 TECDisposeConverter (converter
);
9109 TECCreateConverter (&converter
,
9110 kTextEncodingMacRoman
,
9111 mac_keyboard_text_encoding
);
9116 #if USE_CARBON_EVENTS
9117 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9119 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9121 XSETFRAME (inev
.frame_or_window
,
9122 mac_window_to_frame (front_emacs_window ()));
9123 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9126 case kHighLevelEvent
:
9127 drag_and_drop_file_list
= Qnil
;
9129 AEProcessAppleEvent(&er
);
9131 /* Build a DRAG_N_DROP_EVENT type event as is done in
9132 constuct_drag_n_drop in w32term.c. */
9133 if (!NILP (drag_and_drop_file_list
))
9135 struct frame
*f
= NULL
;
9139 wp
= front_emacs_window ();
9143 struct frame
*f
= XFRAME (XCAR (Vframe_list
));
9144 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
9145 wp
= front_emacs_window ();
9149 f
= mac_window_to_frame (wp
);
9151 inev
.kind
= DRAG_N_DROP_EVENT
;
9153 inev
.timestamp
= er
.when
* (1000 / 60);
9154 /* ticks to milliseconds */
9155 #if USE_CARBON_EVENTS
9156 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9158 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9161 XSETINT (inev
.x
, 0);
9162 XSETINT (inev
.y
, 0);
9164 XSETFRAME (frame
, f
);
9165 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9167 /* Regardless of whether Emacs was suspended or in the
9168 foreground, ask it to redraw its entire screen.
9169 Otherwise parts of the screen can be left in an
9170 inconsistent state. */
9172 #if TARGET_API_MAC_CARBON
9176 GetWindowPortBounds (wp
, &r
);
9177 InvalWindowRect (wp
, &r
);
9179 #else /* not TARGET_API_MAC_CARBON */
9180 InvalRect (&(wp
->portRect
));
9181 #endif /* not TARGET_API_MAC_CARBON */
9186 #if USE_CARBON_EVENTS
9187 ReleaseEvent (eventRef
);
9190 if (inev
.kind
!= NO_EVENT
)
9192 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9197 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9202 XSETFRAME (frame
, f
);
9208 any_help_event_p
= 1;
9209 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9210 help_echo_object
, help_echo_pos
);
9214 help_echo_string
= Qnil
;
9215 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9222 /* If the focus was just given to an autoraising frame,
9224 /* ??? This ought to be able to handle more than one such frame. */
9225 if (pending_autoraise_frame
)
9227 x_raise_frame (pending_autoraise_frame
);
9228 pending_autoraise_frame
= 0;
9231 #if !TARGET_API_MAC_CARBON
9232 check_alarm (); /* simulate the handling of a SIGALRM */
9240 /* Need to override CodeWarrior's input function so no conversion is
9241 done on newlines Otherwise compiled functions in .elc files will be
9242 read incorrectly. Defined in ...:MSL C:MSL
9243 Common:Source:buffer_io.c. */
9246 __convert_to_newlines (unsigned char * p
, size_t * n
)
9252 __convert_from_newlines (unsigned char * p
, size_t * n
)
9260 make_mac_terminal_frame (struct frame
*f
)
9265 XSETFRAME (frame
, f
);
9267 f
->output_method
= output_mac
;
9268 f
->output_data
.mac
= (struct mac_output
*)
9269 xmalloc (sizeof (struct mac_output
));
9270 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9272 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9274 FRAME_COLS (f
) = 96;
9275 FRAME_LINES (f
) = 4;
9277 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9278 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9280 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9282 f
->output_data
.mac
->cursor_pixel
= 0;
9283 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9284 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9285 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9287 #if TARGET_API_MAC_CARBON
9288 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9289 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9290 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9291 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9292 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9293 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9295 f
->output_data
.mac
->text_cursor
= GetCursor (iBeamCursor
);
9296 f
->output_data
.mac
->nontext_cursor
= &arrow_cursor
;
9297 f
->output_data
.mac
->modeline_cursor
= &arrow_cursor
;
9298 f
->output_data
.mac
->hand_cursor
= &arrow_cursor
;
9299 f
->output_data
.mac
->hourglass_cursor
= GetCursor (watchCursor
);
9300 f
->output_data
.mac
->horizontal_drag_cursor
= &arrow_cursor
;
9303 FRAME_FONTSET (f
) = -1;
9304 f
->output_data
.mac
->explicit_parent
= 0;
9307 f
->border_width
= 0;
9309 f
->internal_border_width
= 0;
9314 f
->new_text_cols
= 0;
9315 f
->new_text_lines
= 0;
9317 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9318 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9319 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9323 if (!(FRAME_MAC_WINDOW (f
) =
9324 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9325 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9327 /* so that update events can find this mac_output struct */
9328 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9334 /* Need to be initialized for unshow_buffer in window.c. */
9335 selected_window
= f
->selected_window
;
9337 Fmodify_frame_parameters (frame
,
9338 Fcons (Fcons (Qfont
,
9339 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9340 Fmodify_frame_parameters (frame
,
9341 Fcons (Fcons (Qforeground_color
,
9342 build_string ("black")), Qnil
));
9343 Fmodify_frame_parameters (frame
,
9344 Fcons (Fcons (Qbackground_color
,
9345 build_string ("white")), Qnil
));
9350 /***********************************************************************
9352 ***********************************************************************/
9354 int mac_initialized
= 0;
9357 mac_initialize_display_info ()
9359 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9360 GDHandle main_device_handle
;
9362 bzero (dpyinfo
, sizeof (*dpyinfo
));
9365 dpyinfo
->mac_id_name
9366 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9367 + SCHARS (Vsystem_name
)
9369 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9370 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9372 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9373 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9376 main_device_handle
= LMGetMainDevice();
9378 dpyinfo
->reference_count
= 0;
9379 dpyinfo
->resx
= 75.0;
9380 dpyinfo
->resy
= 75.0;
9381 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9383 /* HasDepth returns true if it is possible to have a 32 bit display,
9384 but this may not be what is actually used. Mac OSX can do better.
9385 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9386 header for CGGetActiveDisplayList says that the first display returned
9387 is the active one, so we use that. */
9389 CGDirectDisplayID disp_id
[1];
9390 CGDisplayCount disp_count
;
9391 CGDisplayErr error_code
;
9393 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
9394 if (error_code
!= 0)
9395 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
9397 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
9400 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
9401 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
9402 gdDevType
, dpyinfo
->color_p
))
9405 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
9406 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
9407 dpyinfo
->grabbed
= 0;
9408 dpyinfo
->root_window
= NULL
;
9409 dpyinfo
->image_cache
= make_image_cache ();
9411 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9412 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9413 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9414 dpyinfo
->mouse_face_window
= Qnil
;
9415 dpyinfo
->mouse_face_overlay
= Qnil
;
9416 dpyinfo
->mouse_face_hidden
= 0;
9419 /* Create an xrdb-style database of resources to supercede registry settings.
9420 The database is just a concatenation of C strings, finished by an additional
9421 \0. The string are submitted to some basic normalization, so
9423 [ *]option[ *]:[ *]value...
9429 but any whitespace following value is not removed. */
9432 mac_make_rdb (xrm_option
)
9435 char *buffer
= xmalloc (strlen (xrm_option
) + 2);
9436 char *current
= buffer
;
9439 int before_value
= 0;
9453 if (in_option
&& (ch
== ':'))
9458 else if (before_value
)
9463 else if (!(in_option
|| before_value
))
9474 struct mac_display_info
*
9475 mac_term_init (display_name
, xrm_option
, resource_name
)
9476 Lisp_Object display_name
;
9478 char *resource_name
;
9480 struct mac_display_info
*dpyinfo
;
9484 if (!mac_initialized
)
9487 mac_initialized
= 1;
9491 error ("Sorry, this version can only handle one display");
9493 mac_initialize_display_info ();
9495 dpyinfo
= &one_mac_display_info
;
9497 dpyinfo
->xrdb
= xrm_option
? mac_make_rdb (xrm_option
) : NULL
;
9499 /* Put this display on the chain. */
9500 dpyinfo
->next
= x_display_list
;
9501 x_display_list
= dpyinfo
;
9503 /* Put it on x_display_name_list. */
9504 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
9505 x_display_name_list
);
9506 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9512 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9515 x_delete_display (dpyinfo
)
9516 struct mac_display_info
*dpyinfo
;
9520 /* Discard this display from x_display_name_list and x_display_list.
9521 We can't use Fdelq because that can quit. */
9522 if (! NILP (x_display_name_list
)
9523 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9524 x_display_name_list
= XCDR (x_display_name_list
);
9529 tail
= x_display_name_list
;
9530 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9532 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9534 XSETCDR (tail
, XCDR (XCDR (tail
)));
9541 if (x_display_list
== dpyinfo
)
9542 x_display_list
= dpyinfo
->next
;
9545 struct x_display_info
*tail
;
9547 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9548 if (tail
->next
== dpyinfo
)
9549 tail
->next
= tail
->next
->next
;
9552 /* Free the font names in the font table. */
9553 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9554 if (dpyinfo
->font_table
[i
].name
)
9556 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9557 xfree (dpyinfo
->font_table
[i
].full_name
);
9558 xfree (dpyinfo
->font_table
[i
].name
);
9561 if (dpyinfo
->font_table
->font_encoder
)
9562 xfree (dpyinfo
->font_table
->font_encoder
);
9564 xfree (dpyinfo
->font_table
);
9565 xfree (dpyinfo
->mac_id_name
);
9567 if (x_display_list
== 0)
9569 mac_clear_font_name_table ();
9570 bzero (dpyinfo
, sizeof (*dpyinfo
));
9579 extern int inhibit_window_system
;
9580 extern int noninteractive
;
9581 CFBundleRef appsBundle
;
9584 /* No need to test if already -nw*/
9585 if (inhibit_window_system
|| noninteractive
)
9588 appsBundle
= CFBundleGetMainBundle();
9589 if (appsBundle
!= NULL
)
9591 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
9592 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
9593 /* We found the bundle identifier, now we know we are valid. */
9600 /* MAC_TODO: Have this start the bundled executable */
9602 /* For now, prevent the fatal error by bringing it up in the terminal */
9603 inhibit_window_system
= 1;
9607 MakeMeTheFrontProcess ()
9609 ProcessSerialNumber psn
;
9612 err
= GetCurrentProcess (&psn
);
9614 (void) SetFrontProcess (&psn
);
9617 /***** Code to handle C-g testing *****/
9619 /* Contains the Mac modifier formed from quit_char */
9620 static mac_quit_char_modifiers
= 0;
9621 static mac_quit_char_keycode
;
9622 extern int quit_char
;
9625 mac_determine_quit_char_modifiers()
9627 /* Todo: Determine modifiers from quit_char. */
9628 UInt32 qc_modifiers
= ctrl_modifier
;
9631 mac_quit_char_modifiers
= 0;
9632 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
9633 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
9634 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
9635 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
9639 init_quit_char_handler ()
9641 /* TODO: Let this support keys other the 'g' */
9642 mac_quit_char_keycode
= 5;
9643 /* Look at <architecture/adb_kb_map.h> for details */
9644 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9646 mac_determine_quit_char_modifiers();
9650 quit_char_comp (EventRef inEvent
, void *inCompData
)
9652 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
9654 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
9658 UInt32 keyModifiers
;
9659 GetEventParameter(inEvent
, kEventParamKeyCode
,
9660 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
9661 if (keyCode
!= mac_quit_char_keycode
)
9663 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
9664 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
9665 if (keyModifiers
!= mac_quit_char_modifiers
)
9672 mac_check_for_quit_char ()
9675 static EMACS_TIME last_check_time
= { 0, 0 };
9676 static EMACS_TIME one_second
= { 1, 0 };
9679 /* If windows are not initialized, return immediately (keep it bouncin'). */
9680 if (!mac_quit_char_modifiers
)
9683 /* Don't check if last check is less than a second ago. */
9684 EMACS_GET_TIME (now
);
9685 EMACS_SUB_TIME (t
, now
, last_check_time
);
9686 if (EMACS_TIME_LT (t
, one_second
))
9688 last_check_time
= now
;
9690 /* Redetermine modifiers because they are based on lisp variables */
9691 mac_determine_quit_char_modifiers ();
9693 /* Fill the queue with events */
9695 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
9696 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
9701 struct input_event e
;
9703 /* Use an input_event to emulate what the interrupt handler does. */
9705 e
.kind
= ASCII_KEYSTROKE_EVENT
;
9709 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
9710 XSETFRAME (e
.frame_or_window
, mac_window_to_frame (front_emacs_window ()));
9711 /* Remove event from queue to prevent looping. */
9712 RemoveEventFromQueue (GetMainEventQueue (), event
);
9713 ReleaseEvent (event
);
9714 kbd_buffer_store_event (&e
);
9718 #endif /* MAC_OSX */
9720 /* Set up use of X before we make the first connection. */
9722 extern frame_parm_handler mac_frame_parm_handlers
[];
9724 static struct redisplay_interface x_redisplay_interface
=
9726 mac_frame_parm_handlers
,
9730 x_clear_end_of_line
,
9732 x_after_update_window_line
,
9733 x_update_window_begin
,
9734 x_update_window_end
,
9737 0, /* flush_display_optional */
9738 x_clear_window_mouse_face
,
9739 x_get_glyph_overhangs
,
9740 x_fix_overlapping_area
,
9741 x_draw_fringe_bitmap
,
9742 0, /* define_fringe_bitmap */
9743 0, /* destroy_fringe_bitmap */
9744 mac_per_char_metric
,
9746 mac_compute_glyph_string_overhangs
,
9747 x_draw_glyph_string
,
9748 mac_define_frame_cursor
,
9749 mac_clear_frame_area
,
9750 mac_draw_window_cursor
,
9751 mac_draw_vertical_window_border
,
9752 mac_shift_glyphs_for_insert
9758 rif
= &x_redisplay_interface
;
9760 clear_frame_hook
= x_clear_frame
;
9761 ins_del_lines_hook
= x_ins_del_lines
;
9762 delete_glyphs_hook
= x_delete_glyphs
;
9763 ring_bell_hook
= XTring_bell
;
9764 reset_terminal_modes_hook
= XTreset_terminal_modes
;
9765 set_terminal_modes_hook
= XTset_terminal_modes
;
9766 update_begin_hook
= x_update_begin
;
9767 update_end_hook
= x_update_end
;
9768 set_terminal_window_hook
= XTset_terminal_window
;
9769 read_socket_hook
= XTread_socket
;
9770 frame_up_to_date_hook
= XTframe_up_to_date
;
9771 mouse_position_hook
= XTmouse_position
;
9772 frame_rehighlight_hook
= XTframe_rehighlight
;
9773 frame_raise_lower_hook
= XTframe_raise_lower
;
9775 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
9776 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
9777 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
9778 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
9780 scroll_region_ok
= 1; /* we'll scroll partial frames */
9781 char_ins_del_ok
= 1;
9782 line_ins_del_ok
= 1; /* we'll just blt 'em */
9783 fast_clear_end_of_line
= 1; /* X does this well */
9784 memory_below_frame
= 0; /* we don't remember what scrolls
9789 last_tool_bar_item
= -1;
9790 any_help_event_p
= 0;
9792 /* Try to use interrupt input; if we can't, then start polling. */
9793 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
9795 #ifdef USE_X_TOOLKIT
9796 XtToolkitInitialize ();
9797 Xt_app_con
= XtCreateApplicationContext ();
9798 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
9800 /* Install an asynchronous timer that processes Xt timeout events
9801 every 0.1s. This is necessary because some widget sets use
9802 timeouts internally, for example the LessTif menu bar, or the
9803 Xaw3d scroll bar. When Xt timouts aren't processed, these
9804 widgets don't behave normally. */
9806 EMACS_TIME interval
;
9807 EMACS_SET_SECS_USECS (interval
, 0, 100000);
9808 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
9812 #if USE_TOOLKIT_SCROLL_BARS
9813 xaw3d_arrow_scroll
= False
;
9814 xaw3d_pick_top
= True
;
9818 /* Note that there is no real way portable across R3/R4 to get the
9819 original error handler. */
9820 XSetErrorHandler (x_error_handler
);
9821 XSetIOErrorHandler (x_io_error_quitter
);
9823 /* Disable Window Change signals; they are handled by X events. */
9825 signal (SIGWINCH
, SIG_DFL
);
9826 #endif /* ! defined (SIGWINCH) */
9828 signal (SIGPIPE
, x_connection_signal
);
9833 #if TARGET_API_MAC_CARBON
9834 init_required_apple_events ();
9836 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9837 init_service_handler ();
9839 init_quit_char_handler ();
9842 DisableMenuCommand (NULL
, kHICommandQuit
);
9845 if (!inhibit_window_system
)
9846 MakeMeTheFrontProcess ();
9857 staticpro (&x_error_message_string
);
9858 x_error_message_string
= Qnil
;
9861 Qmodifier_value
= intern ("modifier-value");
9862 Qalt
= intern ("alt");
9863 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
9864 Qhyper
= intern ("hyper");
9865 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
9866 Qsuper
= intern ("super");
9867 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
9870 Fprovide (intern ("mac-carbon"), Qnil
);
9873 staticpro (&Qreverse
);
9874 Qreverse
= intern ("reverse");
9876 staticpro (&x_display_name_list
);
9877 x_display_name_list
= Qnil
;
9879 staticpro (&last_mouse_scroll_bar
);
9880 last_mouse_scroll_bar
= Qnil
;
9882 staticpro (&Qvendor_specific_keysyms
);
9883 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
9885 staticpro (&last_mouse_press_frame
);
9886 last_mouse_press_frame
= Qnil
;
9888 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
9889 staticpro (&Qmac_ready_for_drag_n_drop
);
9891 Qbig5
= intern ("big5");
9894 Qcn_gb
= intern ("cn-gb");
9895 staticpro (&Qcn_gb
);
9897 Qsjis
= intern ("sjis");
9900 Qeuc_kr
= intern ("euc-kr");
9901 staticpro (&Qeuc_kr
);
9903 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
9904 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
9905 x_autoselect_window_p
= 0;
9907 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
9908 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
9909 Vx_toolkit_scroll_bars
= Qt
;
9911 DEFVAR_BOOL ("x-use-underline-position-properties",
9912 &x_use_underline_position_properties
,
9913 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9914 nil means ignore them. If you encounter fonts with bogus
9915 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9916 to 4.1, set this to nil. */);
9917 x_use_underline_position_properties
= 0;
9919 staticpro (&last_mouse_motion_frame
);
9920 last_mouse_motion_frame
= Qnil
;
9922 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
9923 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
9924 Otherwise the option key is used. */);
9925 Vmac_command_key_is_meta
= Qt
;
9927 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
9928 doc
: /* Modifier to use for the Mac alt/option key. The value can
9929 be alt, hyper, or super for the respective modifier. If the value is
9930 nil then the key will act as the normal Mac option modifier. */);
9931 Vmac_option_modifier
= Qnil
;
9933 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
9934 doc
: /* Non-nil means that the control and meta keys are reversed. This is
9935 useful for non-standard keyboard layouts. */);
9936 Vmac_reverse_ctrl_meta
= Qnil
;
9938 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9939 &Vmac_emulate_three_button_mouse
,
9940 doc
: /* t means that when the option-key is held down while pressing the
9941 mouse button, the click will register as mouse-2 and while the
9942 command-key is held down, the click will register as mouse-3.
9943 'reverse means that the the option-key will register for mouse-3
9944 and the command-key will register for mouse-2. nil means that
9945 no emulation should be done and the modifiers should be placed
9946 on the mouse-1 event. */);
9947 Vmac_emulate_three_button_mouse
= Qnil
;
9949 #if USE_CARBON_EVENTS
9950 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
9951 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
9952 the right click will be mouse-3.
9953 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9954 Vmac_wheel_button_is_mouse_2
= Qt
;
9956 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
9957 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9958 Toolbox for processing before Emacs sees it. */);
9959 Vmac_pass_command_to_system
= Qt
;
9961 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9962 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9963 Toolbox for processing before Emacs sees it. */);
9964 Vmac_pass_control_to_system
= Qt
;
9966 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9967 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9968 Toolbox for processing before Emacs sees it. */);
9969 Vmac_pass_control_to_system
= Qt
;
9972 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
9973 doc
: /* If non-nil, allow anti-aliasing.
9974 The text will be rendered using Core Graphics text rendering which
9975 may anti-alias the text. */);
9976 Vmac_use_core_graphics
= Qnil
;
9978 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
9979 doc
: /* One of the Text Encoding Base constant values defined in the
9980 Basic Text Constants section of Inside Macintosh - Text Encoding
9981 Conversion Manager. Its value determines the encoding characters
9982 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9983 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9984 its default value, no conversion takes place. If it is set to
9985 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9986 characters typed on Mac keyboard are first converted into the
9987 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9988 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9989 command, this enables the Mac keyboard to be used to enter non-ASCII
9990 characters directly. */);
9991 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
9994 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9995 (do not change this comment) */