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 static int is_emacs_window (WindowPtr
);
295 int x_bitmap_icon (struct frame
*, Lisp_Object
);
296 void x_make_frame_visible (struct frame
*);
298 extern void window_scroll (Lisp_Object
, int, int, int);
300 /* Defined in macmenu.h. */
301 extern void menubar_selection_callback (FRAME_PTR
, int);
302 extern void set_frame_menubar (FRAME_PTR
, int, int);
304 /* X display function emulation */
307 XFreePixmap (display
, pixmap
)
308 Display
*display
; /* not used */
311 DisposeGWorld (pixmap
);
315 /* Set foreground color for subsequent QuickDraw commands. Assume
316 graphic port has already been set. */
319 mac_set_forecolor (unsigned long color
)
323 fg_color
.red
= RED16_FROM_ULONG (color
);
324 fg_color
.green
= GREEN16_FROM_ULONG (color
);
325 fg_color
.blue
= BLUE16_FROM_ULONG (color
);
327 RGBForeColor (&fg_color
);
331 /* Set background color for subsequent QuickDraw commands. Assume
332 graphic port has already been set. */
335 mac_set_backcolor (unsigned long color
)
339 bg_color
.red
= RED16_FROM_ULONG (color
);
340 bg_color
.green
= GREEN16_FROM_ULONG (color
);
341 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
343 RGBBackColor (&bg_color
);
346 /* Set foreground and background color for subsequent QuickDraw
347 commands. Assume that the graphic port has already been set. */
350 mac_set_colors (gc
, bg_save
)
355 GetBackColor (bg_save
);
356 mac_set_forecolor (gc
->foreground
);
357 mac_set_backcolor (gc
->background
);
360 /* Mac version of XDrawLine. */
363 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
371 SetPortWindowPort (w
);
373 mac_set_colors (gc
, &old_bg
);
378 RGBBackColor (&old_bg
);
382 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
391 GetGWorld (&old_port
, &old_gdh
);
394 mac_set_colors (gc
, NULL
);
396 LockPixels (GetGWorldPixMap (p
));
399 UnlockPixels (GetGWorldPixMap (p
));
401 SetGWorld (old_port
, old_gdh
);
404 /* Mac version of XClearArea. */
407 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
411 unsigned int width
, height
;
414 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
419 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
420 xgc
.background
= mwp
->x_compatible
.background_pixel
;
422 SetPortWindowPort (w
);
424 mac_set_colors (&xgc
, &old_bg
);
425 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
429 RGBBackColor (&old_bg
);
432 /* Mac version of XClearWindow. */
435 XClearWindow (display
, w
)
439 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
442 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
443 xgc
.background
= mwp
->x_compatible
.background_pixel
;
445 SetPortWindowPort (w
);
447 mac_set_colors (&xgc
, NULL
);
449 #if TARGET_API_MAC_CARBON
453 GetWindowPortBounds (w
, &r
);
456 #else /* not TARGET_API_MAC_CARBON */
457 EraseRect (&(w
->portRect
));
458 #endif /* not TARGET_API_MAC_CARBON */
462 /* Mac replacement for XCopyArea. */
465 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
469 int x
, y
, width
, height
;
470 unsigned short *bits
;
477 bitmap
.rowBytes
= sizeof(unsigned short);
478 bitmap
.baseAddr
= (char *)bits
;
479 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
481 SetPortWindowPort (w
);
483 mac_set_colors (gc
, &old_bg
);
484 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
486 #if TARGET_API_MAC_CARBON
487 LockPortBits (GetWindowPort (w
));
488 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
489 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
490 UnlockPortBits (GetWindowPort (w
));
491 #else /* not TARGET_API_MAC_CARBON */
492 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
493 overlay_p
? srcOr
: srcCopy
, 0);
494 #endif /* not TARGET_API_MAC_CARBON */
496 RGBBackColor (&old_bg
);
500 /* Mac replacement for XSetClipRectangles. */
503 mac_set_clip_rectangle (display
, w
, r
)
508 SetPortWindowPort (w
);
514 /* Mac replacement for XSetClipMask. */
517 mac_reset_clipping (display
, w
)
523 SetPortWindowPort (w
);
525 SetRect (&r
, -32767, -32767, 32767, 32767);
530 /* Mac replacement for XCreateBitmapFromBitmapData. */
533 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
538 static unsigned char swap_nibble
[16]
539 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
540 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
541 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
542 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
546 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
547 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
548 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
549 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
550 for (i
= 0; i
< h
; i
++)
552 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
553 for (j
= 0; j
< w1
; j
++)
555 /* Bitswap XBM bytes to match how Mac does things. */
556 unsigned char c
= *bits
++;
557 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
558 | (swap_nibble
[(c
>>4) & 0xf]));;
562 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
567 mac_free_bitmap (bitmap
)
570 xfree (bitmap
->baseAddr
);
575 XCreatePixmap (display
, w
, width
, height
, depth
)
576 Display
*display
; /* not used */
578 unsigned int width
, height
;
585 SetPortWindowPort (w
);
587 SetRect (&r
, 0, 0, width
, height
);
588 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
596 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
597 Display
*display
; /* not used */
600 unsigned int width
, height
;
601 unsigned long fg
, bg
;
602 unsigned int depth
; /* not used */
609 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
613 GetGWorld (&old_port
, &old_gdh
);
614 SetGWorld (pixmap
, NULL
);
615 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
616 mac_set_forecolor (fg
);
617 mac_set_backcolor (bg
);
618 LockPixels (GetGWorldPixMap (pixmap
));
619 #if TARGET_API_MAC_CARBON
620 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
621 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
622 #else /* not TARGET_API_MAC_CARBON */
623 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
624 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
625 #endif /* not TARGET_API_MAC_CARBON */
626 UnlockPixels (GetGWorldPixMap (pixmap
));
627 SetGWorld (old_port
, old_gdh
);
628 mac_free_bitmap (&bitmap
);
634 /* Mac replacement for XFillRectangle. */
637 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
642 unsigned int width
, height
;
647 SetPortWindowPort (w
);
649 mac_set_colors (gc
, &old_bg
);
650 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
652 PaintRect (&r
); /* using foreground color of gc */
654 RGBBackColor (&old_bg
);
658 #if 0 /* TODO: figure out if we need to do this on Mac. */
660 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
665 unsigned int width
, height
;
671 GetGWorld (&old_port
, &old_gdh
);
673 mac_set_colors (gc
, NULL
);
674 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
676 LockPixels (GetGWorldPixMap (p
));
677 PaintRect (&r
); /* using foreground color of gc */
678 UnlockPixels (GetGWorldPixMap (p
));
680 SetGWorld (old_port
, old_gdh
);
685 /* Mac replacement for XDrawRectangle: dest is a window. */
688 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
693 unsigned int width
, height
;
698 SetPortWindowPort (w
);
700 mac_set_colors (gc
, &old_bg
);
701 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
703 FrameRect (&r
); /* using foreground color of gc */
705 RGBBackColor (&old_bg
);
709 #if 0 /* TODO: figure out if we need to do this on Mac. */
710 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
713 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
718 unsigned int width
, height
;
724 GetGWorld (&old_port
, &old_gdh
);
726 mac_set_colors (gc
, NULL
);
727 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
729 LockPixels (GetGWorldPixMap (p
));
730 FrameRect (&r
); /* using foreground color of gc */
731 UnlockPixels (GetGWorldPixMap (p
));
733 SetGWorld (old_port
, old_gdh
);
739 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
746 int nchars
, mode
, bytes_per_char
;
750 SetPortWindowPort (w
);
751 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
752 UInt32 textFlags
, savedFlags
;
753 if (!NILP(Vmac_use_core_graphics
)) {
754 textFlags
= kQDUseCGTextRendering
;
755 savedFlags
= SwapQDTextFlags(textFlags
);
759 mac_set_colors (gc
, &old_bg
);
761 TextFont (gc
->font
->mac_fontnum
);
762 TextSize (gc
->font
->mac_fontsize
);
763 TextFace (gc
->font
->mac_fontface
);
767 DrawText (buf
, 0, nchars
* bytes_per_char
);
769 RGBBackColor (&old_bg
);
770 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
771 if (!NILP(Vmac_use_core_graphics
))
772 SwapQDTextFlags(savedFlags
);
777 /* Mac replacement for XDrawString. */
780 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
788 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
792 /* Mac replacement for XDrawString16. */
795 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
803 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
808 /* Mac replacement for XDrawImageString. */
811 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
819 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
823 /* Mac replacement for XDrawString16. */
826 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
834 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
839 /* Mac replacement for XCopyArea: dest must be window. */
842 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
849 unsigned int width
, height
;
854 SetPortWindowPort (dest
);
856 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
857 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
859 ForeColor (blackColor
);
860 BackColor (whiteColor
);
862 LockPixels (GetGWorldPixMap (src
));
863 #if TARGET_API_MAC_CARBON
864 LockPortBits (GetWindowPort (dest
));
865 CopyBits (GetPortBitMapForCopyBits (src
),
866 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
867 &src_r
, &dest_r
, srcCopy
, 0);
868 UnlockPortBits (GetWindowPort (dest
));
869 #else /* not TARGET_API_MAC_CARBON */
870 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
871 &src_r
, &dest_r
, srcCopy
, 0);
872 #endif /* not TARGET_API_MAC_CARBON */
873 UnlockPixels (GetGWorldPixMap (src
));
878 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
879 width
, height
, dest_x
, dest_y
)
885 unsigned int width
, height
;
890 SetPortWindowPort (dest
);
892 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
893 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
895 ForeColor (blackColor
);
896 BackColor (whiteColor
);
898 LockPixels (GetGWorldPixMap (src
));
899 LockPixels (GetGWorldPixMap (mask
));
900 #if TARGET_API_MAC_CARBON
901 LockPortBits (GetWindowPort (dest
));
902 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
903 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
904 &src_r
, &src_r
, &dest_r
);
905 UnlockPortBits (GetWindowPort (dest
));
906 #else /* not TARGET_API_MAC_CARBON */
907 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
908 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
909 #endif /* not TARGET_API_MAC_CARBON */
910 UnlockPixels (GetGWorldPixMap (mask
));
911 UnlockPixels (GetGWorldPixMap (src
));
916 /* Convert a pair of local coordinates to global (screen) coordinates.
917 Assume graphic port has been properly set. */
919 local_to_global_coord (short *h
, short *v
)
933 /* Mac replacement for XCopyArea: used only for scrolling. */
936 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
941 unsigned int width
, height
;
944 #if TARGET_API_MAC_CARBON
946 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
948 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
949 ScrollWindowRect (w
, &src_r
, dest_x
- src_x
, dest_y
- src_y
,
950 kScrollWindowNoOptions
, dummy
);
952 #else /* not TARGET_API_MAC_CARBON */
957 mac_set_colors (gc
, NULL
);
960 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
961 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
964 /* Need to use global coordinates and screenBits since src and dest
965 areas overlap in general. */
966 local_to_global_coord (&src_r
.left
, &src_r
.top
);
967 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
968 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
969 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
971 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
973 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
974 color mapping in CopyBits. Otherwise, it will be slow. */
975 ForeColor (blackColor
);
976 BackColor (whiteColor
);
977 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
979 mac_set_colors (gc
, NULL
);
981 #endif /* not TARGET_API_MAC_CARBON */
985 #if 0 /* TODO: figure out if we need to do this on Mac. */
986 /* Mac replacement for XCopyArea: dest must be Pixmap. */
989 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
995 unsigned int width
, height
;
1002 GetGWorld (&old_port
, &old_gdh
);
1003 SetGWorld (dest
, NULL
);
1004 ForeColor (blackColor
);
1005 BackColor (whiteColor
);
1007 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1008 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1010 LockPixels (GetGWorldPixMap (src
));
1011 LockPixels (GetGWorldPixMap (dest
));
1012 #if TARGET_API_MAC_CARBON
1013 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
1014 &src_r
, &dest_r
, srcCopy
, 0);
1015 #else /* not TARGET_API_MAC_CARBON */
1016 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
1017 &src_r
, &dest_r
, srcCopy
, 0);
1018 #endif /* not TARGET_API_MAC_CARBON */
1019 UnlockPixels (GetGWorldPixMap (dest
));
1020 UnlockPixels (GetGWorldPixMap (src
));
1022 SetGWorld (old_port
, old_gdh
);
1027 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
1028 width
, height
, dest_x
, dest_y
)
1030 Pixmap src
, mask
, dest
;
1033 unsigned int width
, height
;
1040 GetGWorld (&old_port
, &old_gdh
);
1041 SetGWorld (dest
, NULL
);
1042 ForeColor (blackColor
);
1043 BackColor (whiteColor
);
1045 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1046 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1048 LockPixels (GetGWorldPixMap (src
));
1049 LockPixels (GetGWorldPixMap (mask
));
1050 LockPixels (GetGWorldPixMap (dest
));
1051 #if TARGET_API_MAC_CARBON
1052 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1053 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
1054 #else /* not TARGET_API_MAC_CARBON */
1055 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1056 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
1057 #endif /* not TARGET_API_MAC_CARBON */
1058 UnlockPixels (GetGWorldPixMap (dest
));
1059 UnlockPixels (GetGWorldPixMap (mask
));
1060 UnlockPixels (GetGWorldPixMap (src
));
1062 SetGWorld (old_port
, old_gdh
);
1067 /* Mac replacement for XChangeGC. */
1070 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1073 if (mask
& GCForeground
)
1074 gc
->foreground
= xgcv
->foreground
;
1075 if (mask
& GCBackground
)
1076 gc
->background
= xgcv
->background
;
1078 gc
->font
= xgcv
->font
;
1082 /* Mac replacement for XCreateGC. */
1085 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1088 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1089 bzero (gc
, sizeof (XGCValues
));
1091 XChangeGC (ignore
, gc
, mask
, xgcv
);
1097 /* Used in xfaces.c. */
1100 XFreeGC (display
, gc
)
1108 /* Mac replacement for XGetGCValues. */
1111 XGetGCValues (void* ignore
, XGCValues
*gc
,
1112 unsigned long mask
, XGCValues
*xgcv
)
1114 XChangeGC (ignore
, xgcv
, mask
, gc
);
1118 /* Mac replacement for XSetForeground. */
1121 XSetForeground (display
, gc
, color
)
1124 unsigned long color
;
1126 gc
->foreground
= color
;
1130 /* Mac replacement for XSetBackground. */
1133 XSetBackground (display
, gc
, color
)
1136 unsigned long color
;
1138 gc
->background
= color
;
1142 /* Mac replacement for XSetWindowBackground. */
1145 XSetWindowBackground (display
, w
, color
)
1148 unsigned long color
;
1150 #if !TARGET_API_MAC_CARBON
1151 AuxWinHandle aw_handle
;
1152 CTabHandle ctab_handle
;
1153 ColorSpecPtr ct_table
;
1158 bg_color
.red
= RED16_FROM_ULONG (color
);
1159 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1160 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1162 #if TARGET_API_MAC_CARBON
1163 SetWindowContentColor (w
, &bg_color
);
1165 if (GetAuxWin (w
, &aw_handle
))
1167 ctab_handle
= (*aw_handle
)->awCTable
;
1168 HandToHand ((Handle
*) &ctab_handle
);
1169 ct_table
= (*ctab_handle
)->ctTable
;
1170 ct_size
= (*ctab_handle
)->ctSize
;
1171 while (ct_size
> -1)
1173 if (ct_table
->value
== 0)
1175 ct_table
->rgb
= bg_color
;
1176 CTabChanged (ctab_handle
);
1177 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1186 /* Mac replacement for XSetFont. */
1189 XSetFont (display
, gc
, font
)
1199 XTextExtents16 (XFontStruct
*font
, XChar2b
*text
, int nchars
,
1200 int *direction
,int *font_ascent
,
1201 int *font_descent
, XCharStruct
*cs
)
1203 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1207 /* x_sync is a no-op on Mac. */
1215 /* Flush display of frame F, or of all frames if F is null. */
1221 #if TARGET_API_MAC_CARBON
1224 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1226 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1232 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1233 Calls to XFlush should be unnecessary because the X output buffer
1234 is flushed automatically as needed by calls to XPending,
1235 XNextEvent, or XWindowEvent according to the XFlush man page.
1236 XTread_socket calls XPending. Removing XFlush improves
1239 #define XFlush(DISPLAY) (void) 0
1242 /* Return the struct mac_display_info corresponding to DPY. There's
1245 struct mac_display_info
*
1246 mac_display_info_for_display (dpy
)
1249 return &one_mac_display_info
;
1254 /***********************************************************************
1255 Starting and ending an update
1256 ***********************************************************************/
1258 /* Start an update of frame F. This function is installed as a hook
1259 for update_begin, i.e. it is called when update_begin is called.
1260 This function is called prior to calls to x_update_window_begin for
1261 each window being updated. */
1267 #if TARGET_API_MAC_CARBON
1268 /* During update of a frame, availability of input events is
1269 periodically checked with ReceiveNextEvent if
1270 redisplay-dont-pause is nil. That normally flushes window buffer
1271 changes for every check, and thus screen update looks waving even
1272 if no input is available. So we disable screen updates during
1273 update of a frame. */
1275 DisableScreenUpdates ();
1281 /* Start update of window W. Set the global variable updated_window
1282 to the window being updated and set output_cursor to the cursor
1286 x_update_window_begin (w
)
1289 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1290 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1293 set_output_cursor (&w
->cursor
);
1297 if (f
== display_info
->mouse_face_mouse_frame
)
1299 /* Don't do highlighting for mouse motion during the update. */
1300 display_info
->mouse_face_defer
= 1;
1302 /* If F needs to be redrawn, simply forget about any prior mouse
1304 if (FRAME_GARBAGED_P (f
))
1305 display_info
->mouse_face_window
= Qnil
;
1307 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1308 their mouse_face_p flag set, which means that they are always
1309 unequal to rows in a desired matrix which never have that
1310 flag set. So, rows containing mouse-face glyphs are never
1311 scrolled, and we don't have to switch the mouse highlight off
1312 here to prevent it from being scrolled. */
1314 /* Can we tell that this update does not affect the window
1315 where the mouse highlight is? If so, no need to turn off.
1316 Likewise, don't do anything if the frame is garbaged;
1317 in that case, the frame's current matrix that we would use
1318 is all wrong, and we will redisplay that line anyway. */
1319 if (!NILP (display_info
->mouse_face_window
)
1320 && w
== XWINDOW (display_info
->mouse_face_window
))
1324 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1325 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1328 if (i
< w
->desired_matrix
->nrows
)
1329 clear_mouse_face (display_info
);
1338 /* Draw a vertical window border from (x,y0) to (x,y1) */
1341 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1345 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1347 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1348 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1352 /* End update of window W (which is equal to updated_window).
1354 Draw vertical borders between horizontally adjacent windows, and
1355 display W's cursor if CURSOR_ON_P is non-zero.
1357 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1358 glyphs in mouse-face were overwritten. In that case we have to
1359 make sure that the mouse-highlight is properly redrawn.
1361 W may be a menu bar pseudo-window in case we don't have X toolkit
1362 support. Such windows don't have a cursor, so don't display it
1366 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1368 int cursor_on_p
, mouse_face_overwritten_p
;
1370 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1372 if (!w
->pseudo_window_p
)
1377 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1379 output_cursor
.x
, output_cursor
.y
);
1381 if (draw_window_fringes (w
, 1))
1382 x_draw_vertical_border (w
);
1387 /* If a row with mouse-face was overwritten, arrange for
1388 XTframe_up_to_date to redisplay the mouse highlight. */
1389 if (mouse_face_overwritten_p
)
1391 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1392 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1393 dpyinfo
->mouse_face_window
= Qnil
;
1397 /* Unhide the caret. This won't actually show the cursor, unless it
1398 was visible before the corresponding call to HideCaret in
1399 x_update_window_begin. */
1400 if (w32_use_visible_system_caret
)
1401 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1404 updated_window
= NULL
;
1408 /* End update of frame F. This function is installed as a hook in
1415 /* Mouse highlight may be displayed again. */
1416 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1419 #if TARGET_API_MAC_CARBON
1420 EnableScreenUpdates ();
1422 XFlush (FRAME_MAC_DISPLAY (f
));
1427 /* This function is called from various places in xdisp.c whenever a
1428 complete update has been performed. The global variable
1429 updated_window is not available here. */
1432 XTframe_up_to_date (f
)
1435 if (FRAME_MAC_P (f
))
1437 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1439 if (dpyinfo
->mouse_face_deferred_gc
1440 || f
== dpyinfo
->mouse_face_mouse_frame
)
1443 if (dpyinfo
->mouse_face_mouse_frame
)
1444 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1445 dpyinfo
->mouse_face_mouse_x
,
1446 dpyinfo
->mouse_face_mouse_y
);
1447 dpyinfo
->mouse_face_deferred_gc
= 0;
1454 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1455 arrow bitmaps, or clear the fringes if no bitmaps are required
1456 before DESIRED_ROW is made current. The window being updated is
1457 found in updated_window. This function is called from
1458 update_window_line only if it is known that there are differences
1459 between bitmaps to be drawn between current row and DESIRED_ROW. */
1462 x_after_update_window_line (desired_row
)
1463 struct glyph_row
*desired_row
;
1465 struct window
*w
= updated_window
;
1471 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1472 desired_row
->redraw_fringe_bitmaps_p
= 1;
1474 /* When a window has disappeared, make sure that no rest of
1475 full-width rows stays visible in the internal border. Could
1476 check here if updated_window is the leftmost/rightmost window,
1477 but I guess it's not worth doing since vertically split windows
1478 are almost never used, internal border is rarely set, and the
1479 overhead is very small. */
1480 if (windows_or_buffers_changed
1481 && desired_row
->full_width_p
1482 && (f
= XFRAME (w
->frame
),
1483 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1485 && (height
= desired_row
->visible_height
,
1488 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1489 /* Internal border is drawn below the tool bar. */
1490 if (WINDOWP (f
->tool_bar_window
)
1491 && w
== XWINDOW (f
->tool_bar_window
))
1496 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1497 0, y
, width
, height
, 0);
1498 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1499 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1507 /* Draw the bitmap WHICH in one of the left or right fringes of
1508 window W. ROW is the glyph row for which to display the bitmap; it
1509 determines the vertical position at which the bitmap has to be
1513 x_draw_fringe_bitmap (w
, row
, p
)
1515 struct glyph_row
*row
;
1516 struct draw_fringe_bitmap_params
*p
;
1518 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1519 Display
*display
= FRAME_MAC_DISPLAY (f
);
1520 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1522 GC gc
= f
->output_data
.mac
->normal_gc
;
1523 struct face
*face
= p
->face
;
1526 /* Must clip because of partially visible lines. */
1527 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1530 /* Adjust position of "bottom aligned" bitmap on partially
1531 visible last row. */
1533 int oldVH
= row
->visible_height
;
1534 row
->visible_height
= p
->h
;
1535 row
->y
-= rowY
- p
->y
;
1536 x_clip_to_row (w
, row
, -1, gc
);
1538 row
->visible_height
= oldVH
;
1541 x_clip_to_row (w
, row
, -1, gc
);
1543 if (p
->bx
>= 0 && !p
->overlay_p
)
1546 gcv
.foreground
= face
->background
;
1548 #if 0 /* MAC_TODO: stipple */
1549 /* In case the same realized face is used for fringes and
1550 for something displayed in the text (e.g. face `region' on
1551 mono-displays, the fill style may have been changed to
1552 FillSolid in x_draw_glyph_string_background. */
1554 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1556 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1559 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1561 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1563 #if 0 /* MAC_TODO: stipple */
1565 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1571 unsigned short *bits
= p
->bits
+ p
->dh
;
1573 gcv
.foreground
= (p
->cursor_p
1574 ? (p
->overlay_p
? face
->background
1575 : f
->output_data
.mac
->cursor_pixel
)
1576 : face
->foreground
);
1577 gcv
.background
= face
->background
;
1579 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
,
1580 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1583 mac_reset_clipping (display
, window
);
1587 /* This is called when starting Emacs and when restarting after
1588 suspend. When starting Emacs, no window is mapped. And nothing
1589 must be done to Emacs's own window if it is suspended (though that
1593 XTset_terminal_modes ()
1597 /* This is called when exiting or suspending Emacs. Exiting will make
1598 the windows go away, and suspending requires no action. */
1601 XTreset_terminal_modes ()
1606 /***********************************************************************
1608 ***********************************************************************/
1610 /* Function prototypes of this page. */
1612 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1613 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1616 /* Return a pointer to per-char metric information in FONT of a
1617 character pointed by B which is a pointer to an XChar2b. */
1619 #define PER_CHAR_METRIC(font, b) \
1621 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1622 + (((font)->min_byte1 || (font)->max_byte1) \
1623 ? (((b)->byte1 - (font)->min_byte1) \
1624 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1626 : &((font)->max_bounds))
1629 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1630 is not contained in the font. */
1632 static INLINE XCharStruct
*
1633 x_per_char_metric (font
, char2b
)
1637 /* The result metric information. */
1638 XCharStruct
*pcm
= NULL
;
1640 xassert (font
&& char2b
);
1642 if (font
->per_char
!= NULL
)
1644 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1646 /* min_char_or_byte2 specifies the linear character index
1647 corresponding to the first element of the per_char array,
1648 max_char_or_byte2 is the index of the last character. A
1649 character with non-zero CHAR2B->byte1 is not in the font.
1650 A character with byte2 less than min_char_or_byte2 or
1651 greater max_char_or_byte2 is not in the font. */
1652 if (char2b
->byte1
== 0
1653 && char2b
->byte2
>= font
->min_char_or_byte2
1654 && char2b
->byte2
<= font
->max_char_or_byte2
)
1655 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1659 /* If either min_byte1 or max_byte1 are nonzero, both
1660 min_char_or_byte2 and max_char_or_byte2 are less than
1661 256, and the 2-byte character index values corresponding
1662 to the per_char array element N (counting from 0) are:
1664 byte1 = N/D + min_byte1
1665 byte2 = N\D + min_char_or_byte2
1669 D = max_char_or_byte2 - min_char_or_byte2 + 1
1670 / = integer division
1671 \ = integer modulus */
1672 if (char2b
->byte1
>= font
->min_byte1
1673 && char2b
->byte1
<= font
->max_byte1
1674 && char2b
->byte2
>= font
->min_char_or_byte2
1675 && char2b
->byte2
<= font
->max_char_or_byte2
)
1677 pcm
= (font
->per_char
1678 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1679 * (char2b
->byte1
- font
->min_byte1
))
1680 + (char2b
->byte2
- font
->min_char_or_byte2
));
1686 /* If the per_char pointer is null, all glyphs between the first
1687 and last character indexes inclusive have the same
1688 information, as given by both min_bounds and max_bounds. */
1689 if (char2b
->byte2
>= font
->min_char_or_byte2
1690 && char2b
->byte2
<= font
->max_char_or_byte2
)
1691 pcm
= &font
->max_bounds
;
1694 return ((pcm
== NULL
1695 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1702 static XCharStruct
*
1703 mac_per_char_metric (font
, char2b
, font_type
)
1708 return x_per_char_metric (font
, char2b
);
1712 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1713 the two-byte form of C. Encoding is returned in *CHAR2B. */
1716 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1719 struct font_info
*font_info
;
1722 int charset
= CHAR_CHARSET (c
);
1723 XFontStruct
*font
= font_info
->font
;
1725 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1726 This may be either a program in a special encoder language or a
1728 if (font_info
->font_encoder
)
1730 /* It's a program. */
1731 struct ccl_program
*ccl
= font_info
->font_encoder
;
1733 if (CHARSET_DIMENSION (charset
) == 1)
1735 ccl
->reg
[0] = charset
;
1736 ccl
->reg
[1] = char2b
->byte2
;
1740 ccl
->reg
[0] = charset
;
1741 ccl
->reg
[1] = char2b
->byte1
;
1742 ccl
->reg
[2] = char2b
->byte2
;
1745 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1747 /* We assume that MSBs are appropriately set/reset by CCL
1749 if (font
->max_byte1
== 0) /* 1-byte font */
1750 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1752 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1754 else if (font_info
->encoding
[charset
])
1756 /* Fixed encoding scheme. See fontset.h for the meaning of the
1757 encoding numbers. */
1758 int enc
= font_info
->encoding
[charset
];
1760 if ((enc
== 1 || enc
== 2)
1761 && CHARSET_DIMENSION (charset
) == 2)
1762 char2b
->byte1
|= 0x80;
1764 if (enc
== 1 || enc
== 3)
1765 char2b
->byte2
|= 0x80;
1771 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1772 char2b
->byte1
= sjis1
;
1773 char2b
->byte2
= sjis2
;
1778 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1780 return FONT_TYPE_UNKNOWN
;
1785 /***********************************************************************
1787 ***********************************************************************/
1790 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1791 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1792 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1794 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1795 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1796 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1797 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1798 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1799 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1800 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1801 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1802 unsigned long *, double, int));*/
1803 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1804 double, int, unsigned long));
1805 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1806 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1807 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1808 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1809 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1810 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1812 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1813 int, int, int, int, int, int,
1815 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1816 int, int, int, Rect
*));
1819 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1823 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1828 struct glyph_string
*s
;
1830 if (s
->font
== FRAME_FONT (s
->f
)
1831 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1832 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1834 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1837 /* Cursor on non-default face: must merge. */
1841 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1842 xgcv
.foreground
= s
->face
->background
;
1844 /* If the glyph would be invisible, try a different foreground. */
1845 if (xgcv
.foreground
== xgcv
.background
)
1846 xgcv
.foreground
= s
->face
->foreground
;
1847 if (xgcv
.foreground
== xgcv
.background
)
1848 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1849 if (xgcv
.foreground
== xgcv
.background
)
1850 xgcv
.foreground
= s
->face
->foreground
;
1852 /* Make sure the cursor is distinct from text in this face. */
1853 if (xgcv
.background
== s
->face
->background
1854 && xgcv
.foreground
== s
->face
->foreground
)
1856 xgcv
.background
= s
->face
->foreground
;
1857 xgcv
.foreground
= s
->face
->background
;
1860 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1861 xgcv
.font
= s
->font
;
1862 mask
= GCForeground
| GCBackground
| GCFont
;
1864 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1865 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1868 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1869 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1871 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1876 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1879 x_set_mouse_face_gc (s
)
1880 struct glyph_string
*s
;
1885 /* What face has to be used last for the mouse face? */
1886 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1887 face
= FACE_FROM_ID (s
->f
, face_id
);
1889 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1891 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1892 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1894 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1895 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1896 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1898 /* If font in this face is same as S->font, use it. */
1899 if (s
->font
== s
->face
->font
)
1900 s
->gc
= s
->face
->gc
;
1903 /* Otherwise construct scratch_cursor_gc with values from FACE
1908 xgcv
.background
= s
->face
->background
;
1909 xgcv
.foreground
= s
->face
->foreground
;
1910 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1911 xgcv
.font
= s
->font
;
1912 mask
= GCForeground
| GCBackground
| GCFont
;
1914 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1915 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1918 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1919 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1921 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1924 xassert (s
->gc
!= 0);
1928 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1929 Faces to use in the mode line have already been computed when the
1930 matrix was built, so there isn't much to do, here. */
1933 x_set_mode_line_face_gc (s
)
1934 struct glyph_string
*s
;
1936 s
->gc
= s
->face
->gc
;
1940 /* Set S->gc of glyph string S for drawing that glyph string. Set
1941 S->stippled_p to a non-zero value if the face of S has a stipple
1945 x_set_glyph_string_gc (s
)
1946 struct glyph_string
*s
;
1948 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1950 if (s
->hl
== DRAW_NORMAL_TEXT
)
1952 s
->gc
= s
->face
->gc
;
1953 s
->stippled_p
= s
->face
->stipple
!= 0;
1955 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1957 x_set_mode_line_face_gc (s
);
1958 s
->stippled_p
= s
->face
->stipple
!= 0;
1960 else if (s
->hl
== DRAW_CURSOR
)
1962 x_set_cursor_gc (s
);
1965 else if (s
->hl
== DRAW_MOUSE_FACE
)
1967 x_set_mouse_face_gc (s
);
1968 s
->stippled_p
= s
->face
->stipple
!= 0;
1970 else if (s
->hl
== DRAW_IMAGE_RAISED
1971 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1973 s
->gc
= s
->face
->gc
;
1974 s
->stippled_p
= s
->face
->stipple
!= 0;
1978 s
->gc
= s
->face
->gc
;
1979 s
->stippled_p
= s
->face
->stipple
!= 0;
1982 /* GC must have been set. */
1983 xassert (s
->gc
!= 0);
1987 /* Set clipping for output of glyph string S. S may be part of a mode
1988 line or menu if we don't have X toolkit support. */
1991 x_set_glyph_string_clipping (s
)
1992 struct glyph_string
*s
;
1995 get_glyph_string_clip_rect (s
, &r
);
1996 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
2001 Compute left and right overhang of glyph string S. If S is a glyph
2002 string for a composition, assume overhangs don't exist. */
2005 mac_compute_glyph_string_overhangs (s
)
2006 struct glyph_string
*s
;
2009 MacFontStruct
*font
= s
->font
;
2011 TextFont (font
->mac_fontnum
);
2012 TextSize (font
->mac_fontsize
);
2013 TextFace (font
->mac_fontface
);
2016 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2020 char *buf
= xmalloc (s
->nchars
);
2023 SetRect (&r
, 0, 0, 0, 0);
2026 for (i
= 0; i
< s
->nchars
; ++i
)
2027 buf
[i
] = s
->char2b
[i
].byte2
;
2028 QDTextBounds (s
->nchars
, buf
, &r
);
2033 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2034 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2038 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2041 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2042 struct glyph_string
*s
;
2047 xgcv
.foreground
= s
->gc
->background
;
2048 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2052 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2053 on Mac OS X because:
2054 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2055 into an offscreen graphics world first. So performance gain
2056 cannot be expected.)
2057 - It lowers rendering quality.
2058 - Some fonts leave garbage on cursor movement. */
2060 /* Draw the background of glyph_string S. If S->background_filled_p
2061 is non-zero don't draw it. FORCE_P non-zero means draw the
2062 background even if it wouldn't be drawn normally. This is used
2063 when a string preceding S draws into the background of S, or S
2064 contains the first component of a composition. */
2067 x_draw_glyph_string_background (s
, force_p
)
2068 struct glyph_string
*s
;
2071 /* Nothing to do if background has already been drawn or if it
2072 shouldn't be drawn in the first place. */
2073 if (!s
->background_filled_p
)
2075 int box_line_width
= max (s
->face
->box_line_width
, 0);
2077 #if 0 /* MAC_TODO: stipple */
2080 /* Fill background with a stipple pattern. */
2081 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2082 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2083 s
->y
+ box_line_width
,
2084 s
->background_width
,
2085 s
->height
- 2 * box_line_width
);
2086 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2087 s
->background_filled_p
= 1;
2092 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2093 || s
->font_not_found_p
2094 || s
->extends_to_end_of_line_p
2098 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2099 s
->background_width
,
2100 s
->height
- 2 * box_line_width
);
2101 s
->background_filled_p
= 1;
2107 /* Draw the foreground of glyph string S. */
2110 x_draw_glyph_string_foreground (s
)
2111 struct glyph_string
*s
;
2115 /* If first glyph of S has a left box line, start drawing the text
2116 of S to the right of that box line. */
2117 if (s
->face
->box
!= FACE_NO_BOX
2118 && s
->first_glyph
->left_box_line_p
)
2119 x
= s
->x
+ abs (s
->face
->box_line_width
);
2123 /* Draw characters of S as rectangles if S's font could not be
2125 if (s
->font_not_found_p
)
2127 for (i
= 0; i
< s
->nchars
; ++i
)
2129 struct glyph
*g
= s
->first_glyph
+ i
;
2130 mac_draw_rectangle (s
->display
, s
->window
,
2131 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2133 x
+= g
->pixel_width
;
2138 char *char1b
= (char *) s
->char2b
;
2139 int boff
= s
->font_info
->baseline_offset
;
2141 if (s
->font_info
->vertical_centering
)
2142 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2144 /* If we can use 8-bit functions, condense S->char2b. */
2146 for (i
= 0; i
< s
->nchars
; ++i
)
2147 char1b
[i
] = s
->char2b
[i
].byte2
;
2150 /* Draw text with XDrawString if background has already been
2151 filled. Otherwise, use XDrawImageString. (Note that
2152 XDrawImageString is usually faster than XDrawString.) Always
2153 use XDrawImageString when drawing the cursor so that there is
2154 no chance that characters under a box cursor are invisible. */
2155 if (s
->for_overlaps_p
2156 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2159 /* Draw characters with 16-bit or 8-bit functions. */
2161 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2162 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2164 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2165 s
->ybase
- boff
, char1b
, s
->nchars
);
2171 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2172 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2174 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2175 s
->ybase
- boff
, char1b
, s
->nchars
);
2181 /* Draw the foreground of composite glyph string S. */
2184 x_draw_composite_glyph_string_foreground (s
)
2185 struct glyph_string
*s
;
2189 /* If first glyph of S has a left box line, start drawing the text
2190 of S to the right of that box line. */
2191 if (s
->face
->box
!= FACE_NO_BOX
2192 && s
->first_glyph
->left_box_line_p
)
2193 x
= s
->x
+ abs (s
->face
->box_line_width
);
2197 /* S is a glyph string for a composition. S->gidx is the index of
2198 the first character drawn for glyphs of this composition.
2199 S->gidx == 0 means we are drawing the very first character of
2200 this composition. */
2202 /* Draw a rectangle for the composition if the font for the very
2203 first character of the composition could not be loaded. */
2204 if (s
->font_not_found_p
)
2207 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2208 s
->width
- 1, s
->height
- 1);
2212 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2213 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2214 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2215 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2221 #ifdef USE_X_TOOLKIT
2223 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2226 /* Return the frame on which widget WIDGET is used.. Abort if frame
2227 cannot be determined. */
2229 static struct frame
*
2230 x_frame_of_widget (widget
)
2233 struct x_display_info
*dpyinfo
;
2237 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2239 /* Find the top-level shell of the widget. Note that this function
2240 can be called when the widget is not yet realized, so XtWindow
2241 (widget) == 0. That's the reason we can't simply use
2242 x_any_window_to_frame. */
2243 while (!XtIsTopLevelShell (widget
))
2244 widget
= XtParent (widget
);
2246 /* Look for a frame with that top-level widget. Allocate the color
2247 on that frame to get the right gamma correction value. */
2248 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2249 if (GC_FRAMEP (XCAR (tail
))
2250 && (f
= XFRAME (XCAR (tail
)),
2251 (f
->output_data
.nothing
!= 1
2252 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2253 && f
->output_data
.x
->widget
== widget
)
2260 /* Allocate the color COLOR->pixel on the screen and display of
2261 widget WIDGET in colormap CMAP. If an exact match cannot be
2262 allocated, try the nearest color available. Value is non-zero
2263 if successful. This is called from lwlib. */
2266 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2271 struct frame
*f
= x_frame_of_widget (widget
);
2272 return x_alloc_nearest_color (f
, cmap
, color
);
2276 #endif /* USE_X_TOOLKIT */
2278 #if 0 /* MAC_TODO */
2280 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2281 CMAP. If an exact match can't be allocated, try the nearest color
2282 available. Value is non-zero if successful. Set *COLOR to the
2286 x_alloc_nearest_color (f
, cmap
, color
)
2291 Display
*display
= FRAME_X_DISPLAY (f
);
2292 Screen
*screen
= FRAME_X_SCREEN (f
);
2295 gamma_correct (f
, color
);
2296 rc
= XAllocColor (display
, cmap
, color
);
2299 /* If we got to this point, the colormap is full, so we're going
2300 to try to get the next closest color. The algorithm used is
2301 a least-squares matching, which is what X uses for closest
2302 color matching with StaticColor visuals. */
2304 unsigned long nearest_delta
= ~0;
2305 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2306 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2308 for (i
= 0; i
< ncells
; ++i
)
2310 XQueryColors (display
, cmap
, cells
, ncells
);
2312 for (nearest
= i
= 0; i
< ncells
; ++i
)
2314 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2315 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2316 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2317 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2319 if (delta
< nearest_delta
)
2322 nearest_delta
= delta
;
2326 color
->red
= cells
[nearest
].red
;
2327 color
->green
= cells
[nearest
].green
;
2328 color
->blue
= cells
[nearest
].blue
;
2329 rc
= XAllocColor (display
, cmap
, color
);
2332 #ifdef DEBUG_X_COLORS
2334 register_color (color
->pixel
);
2335 #endif /* DEBUG_X_COLORS */
2341 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2342 It's necessary to do this instead of just using PIXEL directly to
2343 get color reference counts right. */
2346 x_copy_color (f
, pixel
)
2348 unsigned long pixel
;
2352 color
.pixel
= pixel
;
2354 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2355 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2357 #ifdef DEBUG_X_COLORS
2358 register_color (pixel
);
2364 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2365 It's necessary to do this instead of just using PIXEL directly to
2366 get color reference counts right. */
2369 x_copy_dpy_color (dpy
, cmap
, pixel
)
2372 unsigned long pixel
;
2376 color
.pixel
= pixel
;
2378 XQueryColor (dpy
, cmap
, &color
);
2379 XAllocColor (dpy
, cmap
, &color
);
2381 #ifdef DEBUG_X_COLORS
2382 register_color (pixel
);
2387 #endif /* MAC_TODO */
2390 /* Brightness beyond which a color won't have its highlight brightness
2393 Nominally, highlight colors for `3d' faces are calculated by
2394 brightening an object's color by a constant scale factor, but this
2395 doesn't yield good results for dark colors, so for colors who's
2396 brightness is less than this value (on a scale of 0-255) have to
2397 use an additional additive factor.
2399 The value here is set so that the default menu-bar/mode-line color
2400 (grey75) will not have its highlights changed at all. */
2401 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2404 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2405 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2406 If this produces the same color as COLOR, try a color where all RGB
2407 values have DELTA added. Return the allocated color in *COLOR.
2408 DISPLAY is the X display, CMAP is the colormap to operate on.
2409 Value is non-zero if successful. */
2412 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2414 unsigned long *color
;
2421 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2424 /* Change RGB values by specified FACTOR. Avoid overflow! */
2425 xassert (factor
>= 0);
2426 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2427 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2428 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2430 /* Calculate brightness of COLOR. */
2431 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2432 + BLUE_FROM_ULONG (*color
)) / 6;
2434 /* We only boost colors that are darker than
2435 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2436 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2437 /* Make an additive adjustment to NEW, because it's dark enough so
2438 that scaling by FACTOR alone isn't enough. */
2440 /* How far below the limit this color is (0 - 1, 1 being darker). */
2441 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2442 /* The additive adjustment. */
2443 int min_delta
= delta
* dimness
* factor
/ 2;
2446 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2447 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2448 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2450 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2451 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2452 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2456 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2457 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2458 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2460 /* MAC_TODO: Map to palette and retry with delta if same? */
2461 /* MAC_TODO: Free colors (if using palette)? */
2472 /* Set up the foreground color for drawing relief lines of glyph
2473 string S. RELIEF is a pointer to a struct relief containing the GC
2474 with which lines will be drawn. Use a color that is FACTOR or
2475 DELTA lighter or darker than the relief's background which is found
2476 in S->f->output_data.x->relief_background. If such a color cannot
2477 be allocated, use DEFAULT_PIXEL, instead. */
2480 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2482 struct relief
*relief
;
2485 unsigned long default_pixel
;
2488 struct mac_output
*di
= f
->output_data
.mac
;
2489 unsigned long mask
= GCForeground
;
2490 unsigned long pixel
;
2491 unsigned long background
= di
->relief_background
;
2492 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2494 /* MAC_TODO: Free colors (if using palette)? */
2496 /* Allocate new color. */
2497 xgcv
.foreground
= default_pixel
;
2499 if (dpyinfo
->n_planes
!= 1
2500 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2502 relief
->allocated_p
= 1;
2503 xgcv
.foreground
= relief
->pixel
= pixel
;
2506 if (relief
->gc
== 0)
2508 #if 0 /* MAC_TODO: stipple */
2509 xgcv
.stipple
= dpyinfo
->gray
;
2512 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2515 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2519 /* Set up colors for the relief lines around glyph string S. */
2522 x_setup_relief_colors (s
)
2523 struct glyph_string
*s
;
2525 struct mac_output
*di
= s
->f
->output_data
.mac
;
2526 unsigned long color
;
2528 if (s
->face
->use_box_color_for_shadows_p
)
2529 color
= s
->face
->box_color
;
2530 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2532 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2533 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2538 /* Get the background color of the face. */
2539 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2540 color
= xgcv
.background
;
2543 if (di
->white_relief
.gc
== 0
2544 || color
!= di
->relief_background
)
2546 di
->relief_background
= color
;
2547 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2548 WHITE_PIX_DEFAULT (s
->f
));
2549 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2550 BLACK_PIX_DEFAULT (s
->f
));
2555 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2556 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2557 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2558 relief. LEFT_P non-zero means draw a relief on the left side of
2559 the rectangle. RIGHT_P non-zero means draw a relief on the right
2560 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2564 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2565 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2567 int left_x
, top_y
, right_x
, bottom_y
, width
;
2568 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2571 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2572 Window window
= FRAME_MAC_WINDOW (f
);
2577 gc
= f
->output_data
.mac
->white_relief
.gc
;
2579 gc
= f
->output_data
.mac
->black_relief
.gc
;
2580 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2584 for (i
= 0; i
< width
; ++i
)
2585 XDrawLine (dpy
, window
, gc
,
2586 left_x
+ i
* left_p
, top_y
+ i
,
2587 right_x
- i
* right_p
, top_y
+ i
);
2591 for (i
= 0; i
< width
; ++i
)
2592 XDrawLine (dpy
, window
, gc
,
2593 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2595 mac_reset_clipping (dpy
, window
);
2597 gc
= f
->output_data
.mac
->black_relief
.gc
;
2599 gc
= f
->output_data
.mac
->white_relief
.gc
;
2600 mac_set_clip_rectangle (dpy
, window
,
2605 for (i
= 0; i
< width
; ++i
)
2606 XDrawLine (dpy
, window
, gc
,
2607 left_x
+ i
* left_p
, bottom_y
- i
,
2608 right_x
- i
* right_p
, bottom_y
- i
);
2612 for (i
= 0; i
< width
; ++i
)
2613 XDrawLine (dpy
, window
, gc
,
2614 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2616 mac_reset_clipping (dpy
, window
);
2620 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2621 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2622 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2623 left side of the rectangle. RIGHT_P non-zero means draw a line
2624 on the right side of the rectangle. CLIP_RECT is the clipping
2625 rectangle to use when drawing. */
2628 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2629 left_p
, right_p
, clip_rect
)
2630 struct glyph_string
*s
;
2631 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2636 xgcv
.foreground
= s
->face
->box_color
;
2637 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2640 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2641 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2645 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2646 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2649 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2650 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2654 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2655 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2657 mac_reset_clipping (s
->display
, s
->window
);
2661 /* Draw a box around glyph string S. */
2664 x_draw_glyph_string_box (s
)
2665 struct glyph_string
*s
;
2667 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2668 int left_p
, right_p
;
2669 struct glyph
*last_glyph
;
2672 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2673 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2674 : window_box_right (s
->w
, s
->area
));
2676 /* The glyph that may have a right box line. */
2677 last_glyph
= (s
->cmp
|| s
->img
2679 : s
->first_glyph
+ s
->nchars
- 1);
2681 width
= abs (s
->face
->box_line_width
);
2682 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2684 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2686 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2688 bottom_y
= top_y
+ s
->height
- 1;
2690 left_p
= (s
->first_glyph
->left_box_line_p
2691 || (s
->hl
== DRAW_MOUSE_FACE
2693 || s
->prev
->hl
!= s
->hl
)));
2694 right_p
= (last_glyph
->right_box_line_p
2695 || (s
->hl
== DRAW_MOUSE_FACE
2697 || s
->next
->hl
!= s
->hl
)));
2699 get_glyph_string_clip_rect (s
, &clip_rect
);
2701 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2702 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2703 left_p
, right_p
, &clip_rect
);
2706 x_setup_relief_colors (s
);
2707 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2708 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2713 /* Draw foreground of image glyph string S. */
2716 x_draw_image_foreground (s
)
2717 struct glyph_string
*s
;
2720 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2722 /* If first glyph of S has a left box line, start drawing it to the
2723 right of that line. */
2724 if (s
->face
->box
!= FACE_NO_BOX
2725 && s
->first_glyph
->left_box_line_p
2727 x
+= abs (s
->face
->box_line_width
);
2729 /* If there is a margin around the image, adjust x- and y-position
2731 if (s
->slice
.x
== 0)
2732 x
+= s
->img
->hmargin
;
2733 if (s
->slice
.y
== 0)
2734 y
+= s
->img
->vmargin
;
2738 x_set_glyph_string_clipping (s
);
2741 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2742 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2743 s
->slice
.width
, s
->slice
.height
, x
, y
);
2746 mac_copy_area (s
->display
, s
->img
->pixmap
,
2747 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2748 s
->slice
.width
, s
->slice
.height
, x
, y
);
2750 /* When the image has a mask, we can expect that at
2751 least part of a mouse highlight or a block cursor will
2752 be visible. If the image doesn't have a mask, make
2753 a block cursor visible by drawing a rectangle around
2754 the image. I believe it's looking better if we do
2755 nothing here for mouse-face. */
2756 if (s
->hl
== DRAW_CURSOR
)
2758 int r
= s
->img
->relief
;
2760 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2762 s
->slice
.width
+ r
*2 - 1,
2763 s
->slice
.height
+ r
*2 - 1);
2768 /* Draw a rectangle if image could not be loaded. */
2769 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2770 s
->slice
.width
- 1, s
->slice
.height
- 1);
2774 /* Draw a relief around the image glyph string S. */
2777 x_draw_image_relief (s
)
2778 struct glyph_string
*s
;
2780 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2783 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2785 /* If first glyph of S has a left box line, start drawing it to the
2786 right of that line. */
2787 if (s
->face
->box
!= FACE_NO_BOX
2788 && s
->first_glyph
->left_box_line_p
2790 x
+= abs (s
->face
->box_line_width
);
2792 /* If there is a margin around the image, adjust x- and y-position
2794 if (s
->slice
.x
== 0)
2795 x
+= s
->img
->hmargin
;
2796 if (s
->slice
.y
== 0)
2797 y
+= s
->img
->vmargin
;
2799 if (s
->hl
== DRAW_IMAGE_SUNKEN
2800 || s
->hl
== DRAW_IMAGE_RAISED
)
2802 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2803 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2807 thick
= abs (s
->img
->relief
);
2808 raised_p
= s
->img
->relief
> 0;
2813 x1
= x
+ s
->slice
.width
+ thick
- 1;
2814 y1
= y
+ s
->slice
.height
+ thick
- 1;
2816 x_setup_relief_colors (s
);
2817 get_glyph_string_clip_rect (s
, &r
);
2818 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2820 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2822 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2827 #if 0 /* TODO: figure out if we need to do this on Mac. */
2828 /* Draw the foreground of image glyph string S to PIXMAP. */
2831 x_draw_image_foreground_1 (s
, pixmap
)
2832 struct glyph_string
*s
;
2836 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2838 /* If first glyph of S has a left box line, start drawing it to the
2839 right of that line. */
2840 if (s
->face
->box
!= FACE_NO_BOX
2841 && s
->first_glyph
->left_box_line_p
2843 x
+= abs (s
->face
->box_line_width
);
2845 /* If there is a margin around the image, adjust x- and y-position
2847 if (s
->slice
.x
== 0)
2848 x
+= s
->img
->hmargin
;
2849 if (s
->slice
.y
== 0)
2850 y
+= s
->img
->vmargin
;
2855 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2856 s
->img
->mask
, pixmap
, s
->gc
,
2857 s
->slice
.x
, s
->slice
.y
,
2858 s
->slice
.width
, s
->slice
.height
,
2862 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2863 s
->slice
.x
, s
->slice
.y
,
2864 s
->slice
.width
, s
->slice
.height
,
2867 /* When the image has a mask, we can expect that at
2868 least part of a mouse highlight or a block cursor will
2869 be visible. If the image doesn't have a mask, make
2870 a block cursor visible by drawing a rectangle around
2871 the image. I believe it's looking better if we do
2872 nothing here for mouse-face. */
2873 if (s
->hl
== DRAW_CURSOR
)
2875 int r
= s
->img
->relief
;
2877 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2878 s
->slice
.width
+ r
*2 - 1,
2879 s
->slice
.height
+ r
*2 - 1);
2884 /* Draw a rectangle if image could not be loaded. */
2885 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2886 s
->slice
.width
- 1, s
->slice
.height
- 1);
2891 /* Draw part of the background of glyph string S. X, Y, W, and H
2892 give the rectangle to draw. */
2895 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2896 struct glyph_string
*s
;
2899 #if 0 /* MAC_TODO: stipple */
2902 /* Fill background with a stipple pattern. */
2903 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2904 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2905 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2908 #endif /* MAC_TODO */
2909 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2913 /* Draw image glyph string S.
2916 s->x +-------------------------
2919 | +-------------------------
2922 | | +-------------------
2928 x_draw_image_glyph_string (s
)
2929 struct glyph_string
*s
;
2932 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2933 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2937 height
= s
->height
- 2 * box_line_vwidth
;
2940 /* Fill background with face under the image. Do it only if row is
2941 taller than image or if image has a clip mask to reduce
2943 s
->stippled_p
= s
->face
->stipple
!= 0;
2944 if (height
> s
->slice
.height
2948 || s
->img
->pixmap
== 0
2949 || s
->width
!= s
->background_width
)
2952 if (s
->first_glyph
->left_box_line_p
2954 x
+= box_line_hwidth
;
2957 if (s
->slice
.y
== 0)
2958 y
+= box_line_vwidth
;
2960 #if 0 /* TODO: figure out if we need to do this on Mac. */
2963 /* Create a pixmap as large as the glyph string. Fill it
2964 with the background color. Copy the image to it, using
2965 its mask. Copy the temporary pixmap to the display. */
2966 int depth
= one_mac_display_info
.n_planes
;
2968 /* Create a pixmap as large as the glyph string. */
2969 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2970 s
->background_width
,
2973 /* Fill the pixmap with the background color/stipple. */
2974 #if 0 /* TODO: stipple */
2977 /* Fill background with a stipple pattern. */
2978 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2979 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2980 0, 0, s
->background_width
, s
->height
);
2981 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2987 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2989 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2990 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2991 0, 0, s
->background_width
,
2993 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2998 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3000 s
->background_filled_p
= 1;
3003 /* Draw the foreground. */
3004 #if 0 /* TODO: figure out if we need to do this on Mac. */
3007 x_draw_image_foreground_1 (s
, pixmap
);
3008 x_set_glyph_string_clipping (s
);
3009 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
3010 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3011 mac_reset_clipping (s
->display
, s
->window
);
3012 XFreePixmap (s
->display
, pixmap
);
3016 x_draw_image_foreground (s
);
3018 /* If we must draw a relief around the image, do it. */
3020 || s
->hl
== DRAW_IMAGE_RAISED
3021 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3022 x_draw_image_relief (s
);
3026 /* Draw stretch glyph string S. */
3029 x_draw_stretch_glyph_string (s
)
3030 struct glyph_string
*s
;
3032 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3033 s
->stippled_p
= s
->face
->stipple
!= 0;
3035 if (s
->hl
== DRAW_CURSOR
3036 && !x_stretch_cursor_p
)
3038 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3039 as wide as the stretch glyph. */
3040 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3043 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3045 /* Clear rest using the GC of the original non-cursor face. */
3046 if (width
< s
->background_width
)
3048 int x
= s
->x
+ width
, y
= s
->y
;
3049 int w
= s
->background_width
- width
, h
= s
->height
;
3053 if (s
->row
->mouse_face_p
3054 && cursor_in_mouse_face_p (s
->w
))
3056 x_set_mouse_face_gc (s
);
3062 get_glyph_string_clip_rect (s
, &r
);
3063 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3065 #if 0 /* MAC_TODO: stipple */
3066 if (s
->face
->stipple
)
3068 /* Fill background with a stipple pattern. */
3069 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3070 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3071 XSetFillStyle (s
->display
, gc
, FillSolid
);
3074 #endif /* MAC_TODO */
3077 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3078 XSetForeground (s
->display
, gc
, xgcv
.background
);
3079 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3080 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3083 mac_reset_clipping (s
->display
, s
->window
);
3086 else if (!s
->background_filled_p
)
3087 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3090 s
->background_filled_p
= 1;
3094 /* Draw glyph string S. */
3097 x_draw_glyph_string (s
)
3098 struct glyph_string
*s
;
3100 int relief_drawn_p
= 0;
3102 /* If S draws into the background of its successor that does not
3103 draw a cursor, draw the background of the successor first so that
3104 S can draw into it. This makes S->next use XDrawString instead
3105 of XDrawImageString. */
3106 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
3107 && s
->next
->hl
!= DRAW_CURSOR
)
3109 xassert (s
->next
->img
== NULL
);
3110 x_set_glyph_string_gc (s
->next
);
3111 x_set_glyph_string_clipping (s
->next
);
3112 x_draw_glyph_string_background (s
->next
, 1);
3115 /* Set up S->gc, set clipping and draw S. */
3116 x_set_glyph_string_gc (s
);
3118 /* Draw relief (if any) in advance for char/composition so that the
3119 glyph string can be drawn over it. */
3120 if (!s
->for_overlaps_p
3121 && s
->face
->box
!= FACE_NO_BOX
3122 && (s
->first_glyph
->type
== CHAR_GLYPH
3123 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3126 x_set_glyph_string_clipping (s
);
3127 x_draw_glyph_string_background (s
, 1);
3128 x_draw_glyph_string_box (s
);
3129 x_set_glyph_string_clipping (s
);
3133 x_set_glyph_string_clipping (s
);
3135 switch (s
->first_glyph
->type
)
3138 x_draw_image_glyph_string (s
);
3142 x_draw_stretch_glyph_string (s
);
3146 if (s
->for_overlaps_p
)
3147 s
->background_filled_p
= 1;
3149 x_draw_glyph_string_background (s
, 0);
3150 x_draw_glyph_string_foreground (s
);
3153 case COMPOSITE_GLYPH
:
3154 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3155 s
->background_filled_p
= 1;
3157 x_draw_glyph_string_background (s
, 1);
3158 x_draw_composite_glyph_string_foreground (s
);
3165 if (!s
->for_overlaps_p
)
3167 /* Draw underline. */
3168 if (s
->face
->underline_p
)
3170 unsigned long h
= 1;
3171 unsigned long dy
= s
->height
- h
;
3173 if (s
->face
->underline_defaulted_p
)
3174 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3179 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3180 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3181 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3183 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3187 /* Draw overline. */
3188 if (s
->face
->overline_p
)
3190 unsigned long dy
= 0, h
= 1;
3192 if (s
->face
->overline_color_defaulted_p
)
3193 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3198 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3199 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3200 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3202 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3206 /* Draw strike-through. */
3207 if (s
->face
->strike_through_p
)
3209 unsigned long h
= 1;
3210 unsigned long dy
= (s
->height
- h
) / 2;
3212 if (s
->face
->strike_through_color_defaulted_p
)
3213 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3218 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3219 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3220 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3222 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3226 /* Draw relief if not yet drawn. */
3227 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3228 x_draw_glyph_string_box (s
);
3231 /* Reset clipping. */
3232 mac_reset_clipping (s
->display
, s
->window
);
3235 /* Shift display to make room for inserted glyphs. */
3238 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3240 int x
, y
, width
, height
, shift_by
;
3242 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3243 f
->output_data
.mac
->normal_gc
,
3244 x
, y
, width
, height
,
3248 /* Delete N glyphs at the nominal cursor position. Not implemented
3259 /* Clear entire frame. If updating_frame is non-null, clear that
3260 frame. Otherwise clear the selected frame. */
3270 f
= SELECTED_FRAME ();
3272 /* Clearing the frame will erase any cursor, so mark them all as no
3274 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3275 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3276 output_cursor
.x
= -1;
3278 /* We don't set the output cursor here because there will always
3279 follow an explicit cursor_to. */
3281 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3283 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3284 /* We have to clear the scroll bars, too. If we have changed
3285 colors or something like that, then they should be notified. */
3286 x_scroll_bar_clear (f
);
3289 XFlush (FRAME_MAC_DISPLAY (f
));
3295 /* Invert the middle quarter of the frame for .15 sec. */
3297 /* We use the select system call to do the waiting, so we have to make
3298 sure it's available. If it isn't, we just won't do visual bells. */
3300 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3303 /* Subtract the `struct timeval' values X and Y, storing the result in
3304 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3307 timeval_subtract (result
, x
, y
)
3308 struct timeval
*result
, x
, y
;
3310 /* Perform the carry for the later subtraction by updating y. This
3311 is safer because on some systems the tv_sec member is unsigned. */
3312 if (x
.tv_usec
< y
.tv_usec
)
3314 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3315 y
.tv_usec
-= 1000000 * nsec
;
3319 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3321 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3322 y
.tv_usec
+= 1000000 * nsec
;
3326 /* Compute the time remaining to wait. tv_usec is certainly
3328 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3329 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3331 /* Return indication of whether the result should be considered
3333 return x
.tv_sec
< y
.tv_sec
;
3345 struct timeval wakeup
;
3347 EMACS_GET_TIME (wakeup
);
3349 /* Compute time to wait until, propagating carry from usecs. */
3350 wakeup
.tv_usec
+= 150000;
3351 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3352 wakeup
.tv_usec
%= 1000000;
3354 /* Keep waiting until past the time wakeup. */
3357 struct timeval timeout
;
3359 EMACS_GET_TIME (timeout
);
3361 /* In effect, timeout = wakeup - timeout.
3362 Break if result would be negative. */
3363 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3366 /* Try to wait that long--but we might wake up sooner. */
3367 select (0, NULL
, NULL
, NULL
, &timeout
);
3376 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3379 /* Make audible bell. */
3384 struct frame
*f
= SELECTED_FRAME ();
3386 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3394 XFlush (FRAME_MAC_DISPLAY (f
));
3401 /* Specify how many text lines, from the top of the window,
3402 should be affected by insert-lines and delete-lines operations.
3403 This, and those operations, are used only within an update
3404 that is bounded by calls to x_update_begin and x_update_end. */
3407 XTset_terminal_window (n
)
3410 /* This function intentionally left blank. */
3415 /***********************************************************************
3417 ***********************************************************************/
3419 /* Perform an insert-lines or delete-lines operation, inserting N
3420 lines or deleting -N lines at vertical position VPOS. */
3423 x_ins_del_lines (vpos
, n
)
3430 /* Scroll part of the display as described by RUN. */
3433 x_scroll_run (w
, run
)
3437 struct frame
*f
= XFRAME (w
->frame
);
3438 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3440 /* Get frame-relative bounding box of the text display area of W,
3441 without mode lines. Include in this box the left and right
3443 window_box (w
, -1, &x
, &y
, &width
, &height
);
3445 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3446 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3447 bottom_y
= y
+ height
;
3451 /* Scrolling up. Make sure we don't copy part of the mode
3452 line at the bottom. */
3453 if (from_y
+ run
->height
> bottom_y
)
3454 height
= bottom_y
- from_y
;
3456 height
= run
->height
;
3460 /* Scolling down. Make sure we don't copy over the mode line.
3462 if (to_y
+ run
->height
> bottom_y
)
3463 height
= bottom_y
- to_y
;
3465 height
= run
->height
;
3470 /* Cursor off. Will be switched on again in x_update_window_end. */
3474 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3475 f
->output_data
.mac
->normal_gc
,
3485 /***********************************************************************
3487 ***********************************************************************/
3494 x_update_cursor (f
, 1);
3498 frame_unhighlight (f
)
3501 x_update_cursor (f
, 1);
3504 /* The focus has changed. Update the frames as necessary to reflect
3505 the new situation. Note that we can't change the selected frame
3506 here, because the Lisp code we are interrupting might become confused.
3507 Each event gets marked with the frame in which it occurred, so the
3508 Lisp code can tell when the switch took place by examining the events. */
3511 x_new_focus_frame (dpyinfo
, frame
)
3512 struct x_display_info
*dpyinfo
;
3513 struct frame
*frame
;
3515 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3517 if (frame
!= dpyinfo
->x_focus_frame
)
3519 /* Set this before calling other routines, so that they see
3520 the correct value of x_focus_frame. */
3521 dpyinfo
->x_focus_frame
= frame
;
3523 if (old_focus
&& old_focus
->auto_lower
)
3524 x_lower_frame (old_focus
);
3527 selected_frame
= frame
;
3528 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3530 Fselect_window (selected_frame
->selected_window
, Qnil
);
3531 choose_minibuf_frame ();
3534 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3535 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3537 pending_autoraise_frame
= 0;
3540 x_frame_rehighlight (dpyinfo
);
3543 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3546 x_mouse_leave (dpyinfo
)
3547 struct x_display_info
*dpyinfo
;
3549 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3552 /* The focus has changed, or we have redirected a frame's focus to
3553 another frame (this happens when a frame uses a surrogate
3554 mini-buffer frame). Shift the highlight as appropriate.
3556 The FRAME argument doesn't necessarily have anything to do with which
3557 frame is being highlighted or un-highlighted; we only use it to find
3558 the appropriate X display info. */
3561 XTframe_rehighlight (frame
)
3562 struct frame
*frame
;
3564 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3568 x_frame_rehighlight (dpyinfo
)
3569 struct x_display_info
*dpyinfo
;
3571 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3573 if (dpyinfo
->x_focus_frame
)
3575 dpyinfo
->x_highlight_frame
3576 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3577 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3578 : dpyinfo
->x_focus_frame
);
3579 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3581 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3582 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3586 dpyinfo
->x_highlight_frame
= 0;
3588 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3591 frame_unhighlight (old_highlight
);
3592 if (dpyinfo
->x_highlight_frame
)
3593 frame_highlight (dpyinfo
->x_highlight_frame
);
3599 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3601 #if 0 /* MAC_TODO */
3602 /* Initialize mode_switch_bit and modifier_meaning. */
3604 x_find_modifier_meanings (dpyinfo
)
3605 struct x_display_info
*dpyinfo
;
3607 int min_code
, max_code
;
3610 XModifierKeymap
*mods
;
3612 dpyinfo
->meta_mod_mask
= 0;
3613 dpyinfo
->shift_lock_mask
= 0;
3614 dpyinfo
->alt_mod_mask
= 0;
3615 dpyinfo
->super_mod_mask
= 0;
3616 dpyinfo
->hyper_mod_mask
= 0;
3619 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3621 min_code
= dpyinfo
->display
->min_keycode
;
3622 max_code
= dpyinfo
->display
->max_keycode
;
3625 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3626 min_code
, max_code
- min_code
+ 1,
3628 mods
= XGetModifierMapping (dpyinfo
->display
);
3630 /* Scan the modifier table to see which modifier bits the Meta and
3631 Alt keysyms are on. */
3633 int row
, col
; /* The row and column in the modifier table. */
3635 for (row
= 3; row
< 8; row
++)
3636 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3639 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3641 /* Zeroes are used for filler. Skip them. */
3645 /* Are any of this keycode's keysyms a meta key? */
3649 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3651 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3657 dpyinfo
->meta_mod_mask
|= (1 << row
);
3662 dpyinfo
->alt_mod_mask
|= (1 << row
);
3667 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3672 dpyinfo
->super_mod_mask
|= (1 << row
);
3676 /* Ignore this if it's not on the lock modifier. */
3677 if ((1 << row
) == LockMask
)
3678 dpyinfo
->shift_lock_mask
= LockMask
;
3686 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3687 if (! dpyinfo
->meta_mod_mask
)
3689 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3690 dpyinfo
->alt_mod_mask
= 0;
3693 /* If some keys are both alt and meta,
3694 make them just meta, not alt. */
3695 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3697 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3700 XFree ((char *) syms
);
3701 XFreeModifiermap (mods
);
3704 #endif /* MAC_TODO */
3706 /* Convert between the modifier bits X uses and the modifier bits
3710 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3711 struct x_display_info
*dpyinfo
;
3712 unsigned short state
;
3714 return (((state
& shiftKey
) ? shift_modifier
: 0)
3715 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3716 | ((state
& cmdKey
) ? meta_modifier
: 0)
3717 | ((state
& optionKey
) ? alt_modifier
: 0));
3720 #if 0 /* MAC_TODO */
3721 static unsigned short
3722 x_emacs_to_x_modifiers (dpyinfo
, state
)
3723 struct x_display_info
*dpyinfo
;
3726 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3727 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3728 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3729 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3730 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3731 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3733 #endif /* MAC_TODO */
3735 /* Convert a keysym to its name. */
3738 x_get_keysym_name (keysym
)
3745 value
= XKeysymToString (keysym
);
3757 /* Mouse clicks and mouse movement. Rah. */
3759 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3761 If the event is a button press, then note that we have grabbed
3765 construct_mouse_click (result
, event
, f
)
3766 struct input_event
*result
;
3772 result
->kind
= MOUSE_CLICK_EVENT
;
3773 result
->code
= 0; /* only one mouse button */
3774 result
->timestamp
= event
->when
;
3775 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3777 mouseLoc
= event
->where
;
3779 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3781 GlobalToLocal (&mouseLoc
);
3782 XSETINT (result
->x
, mouseLoc
.h
);
3783 XSETINT (result
->y
, mouseLoc
.v
);
3785 XSETFRAME (result
->frame_or_window
, f
);
3793 /* Function to report a mouse movement to the mainstream Emacs code.
3794 The input handler calls this.
3796 We have received a mouse movement event, which is given in *event.
3797 If the mouse is over a different glyph than it was last time, tell
3798 the mainstream emacs code by setting mouse_moved. If not, ask for
3799 another motion event, so we can check again the next time it moves. */
3801 static Point last_mouse_motion_position
;
3802 static Lisp_Object last_mouse_motion_frame
;
3805 note_mouse_movement (frame
, pos
)
3809 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3810 #if TARGET_API_MAC_CARBON
3814 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3815 last_mouse_motion_position
= *pos
;
3816 XSETFRAME (last_mouse_motion_frame
, frame
);
3818 #if TARGET_API_MAC_CARBON
3819 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3821 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3824 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3825 /* This case corresponds to LeaveNotify in X11. */
3827 /* If we move outside the frame, then we're certainly no
3828 longer on any text in the frame. */
3829 clear_mouse_face (dpyinfo
);
3830 dpyinfo
->mouse_face_mouse_frame
= 0;
3831 if (!dpyinfo
->grabbed
)
3832 rif
->define_frame_cursor (frame
,
3833 frame
->output_data
.mac
->nontext_cursor
);
3836 /* Has the mouse moved off the glyph it was on at the last sighting? */
3837 else if (pos
->h
< last_mouse_glyph
.left
3838 || pos
->h
>= last_mouse_glyph
.right
3839 || pos
->v
< last_mouse_glyph
.top
3840 || pos
->v
>= last_mouse_glyph
.bottom
)
3842 frame
->mouse_moved
= 1;
3843 last_mouse_scroll_bar
= Qnil
;
3844 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3848 /* This is used for debugging, to turn off note_mouse_highlight. */
3850 int disable_mouse_highlight
;
3854 /************************************************************************
3856 ************************************************************************/
3858 static struct scroll_bar
*x_window_to_scroll_bar ();
3859 static void x_scroll_bar_report_motion ();
3860 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3863 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3866 redo_mouse_highlight ()
3868 if (!NILP (last_mouse_motion_frame
)
3869 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3870 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3871 last_mouse_motion_position
.h
,
3872 last_mouse_motion_position
.v
);
3876 /* Try to determine frame pixel position and size of the glyph under
3877 frame pixel coordinates X/Y on frame F . Return the position and
3878 size in *RECT. Value is non-zero if we could compute these
3882 glyph_rect (f
, x
, y
, rect
)
3889 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3893 struct window
*w
= XWINDOW (window
);
3894 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3895 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3897 for (; r
< end
&& r
->enabled_p
; ++r
)
3898 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3900 /* Found the row at y. */
3901 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3902 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3905 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3906 rect
->bottom
= rect
->top
+ r
->height
;
3910 /* x is to the left of the first glyph in the row. */
3911 /* Shouldn't this be a pixel value?
3912 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3914 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3915 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3919 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3920 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3922 /* x is on a glyph. */
3923 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3924 rect
->right
= rect
->left
+ g
->pixel_width
;
3928 /* x is to the right of the last glyph in the row. */
3929 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3930 /* Shouldn't this be a pixel value?
3931 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3933 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3938 /* The y is not on any row. */
3942 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3944 /* Record the position of the mouse in last_mouse_glyph. */
3946 remember_mouse_glyph (f1
, gx
, gy
)
3950 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3952 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3953 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3955 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3956 round down even for negative values. */
3962 /* This was the original code from XTmouse_position, but it seems
3963 to give the position of the glyph diagonally next to the one
3964 the mouse is over. */
3965 gx
= (gx
+ width
- 1) / width
* width
;
3966 gy
= (gy
+ height
- 1) / height
* height
;
3968 gx
= gx
/ width
* width
;
3969 gy
= gy
/ height
* height
;
3972 last_mouse_glyph
.left
= gx
;
3973 last_mouse_glyph
.top
= gy
;
3974 last_mouse_glyph
.right
= gx
+ width
;
3975 last_mouse_glyph
.bottom
= gy
+ height
;
3981 front_emacs_window ()
3983 #if TARGET_API_MAC_CARBON
3984 WindowPtr wp
= GetFrontWindowOfClass (kDocumentWindowClass
, true);
3986 while (wp
&& !is_emacs_window (wp
))
3987 wp
= GetNextWindowOfClass (wp
, kDocumentWindowClass
, true);
3989 WindowPtr wp
= FrontWindow ();
3991 while (wp
&& (wp
== tip_window
|| !is_emacs_window (wp
)))
3992 wp
= GetNextWindow (wp
);
3998 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
4000 /* Return the current position of the mouse.
4001 *fp should be a frame which indicates which display to ask about.
4003 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4004 and *part to the frame, window, and scroll bar part that the mouse
4005 is over. Set *x and *y to the portion and whole of the mouse's
4006 position on the scroll bar.
4008 If the mouse movement started elsewhere, set *fp to the frame the
4009 mouse is on, *bar_window to nil, and *x and *y to the character cell
4012 Set *time to the server time-stamp for the time at which the mouse
4013 was at this position.
4015 Don't store anything if we don't have a valid set of values to report.
4017 This clears the mouse_moved flag, so we can wait for the next mouse
4021 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4024 Lisp_Object
*bar_window
;
4025 enum scroll_bar_part
*part
;
4027 unsigned long *time
;
4030 int ignore1
, ignore2
;
4031 WindowPtr wp
= front_emacs_window ();
4033 Lisp_Object frame
, tail
;
4035 if (is_emacs_window(wp
))
4036 f
= mac_window_to_frame (wp
);
4040 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4041 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4044 /* Clear the mouse-moved flag for every frame on this display. */
4045 FOR_EACH_FRAME (tail
, frame
)
4046 XFRAME (frame
)->mouse_moved
= 0;
4048 last_mouse_scroll_bar
= Qnil
;
4050 SetPortWindowPort (wp
);
4052 GetMouse (&mouse_pos
);
4054 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4055 &last_mouse_glyph
, insist
);
4058 *part
= scroll_bar_handle
;
4060 XSETINT (*x
, mouse_pos
.h
);
4061 XSETINT (*y
, mouse_pos
.v
);
4062 *time
= last_mouse_movement_time
;
4069 /***********************************************************************
4071 ***********************************************************************/
4073 /* Handle mouse button event on the tool-bar of frame F, at
4074 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4078 mac_handle_tool_bar_click (f
, button_event
)
4080 EventRecord
*button_event
;
4082 int x
= button_event
->where
.h
;
4083 int y
= button_event
->where
.v
;
4085 if (button_event
->what
== mouseDown
)
4086 handle_tool_bar_click (f
, x
, y
, 1, 0);
4088 handle_tool_bar_click (f
, x
, y
, 0,
4089 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f
),
4090 button_event
->modifiers
));
4094 /************************************************************************
4095 Scroll bars, general
4096 ************************************************************************/
4098 /* Create a scroll bar and return the scroll bar vector for it. W is
4099 the Emacs window on which to create the scroll bar. TOP, LEFT,
4100 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4103 static struct scroll_bar
*
4104 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4106 int top
, left
, width
, height
, disp_top
, disp_height
;
4108 struct frame
*f
= XFRAME (w
->frame
);
4109 struct scroll_bar
*bar
4110 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4118 r
.right
= left
+ width
;
4119 r
.bottom
= disp_top
+ disp_height
;
4121 #if TARGET_API_MAC_CARBON
4122 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4123 kControlScrollBarProc
, 0L);
4125 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
4128 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4129 SetControlReference (ch
, (long) bar
);
4131 XSETWINDOW (bar
->window
, w
);
4132 XSETINT (bar
->top
, top
);
4133 XSETINT (bar
->left
, left
);
4134 XSETINT (bar
->width
, width
);
4135 XSETINT (bar
->height
, height
);
4136 XSETINT (bar
->start
, 0);
4137 XSETINT (bar
->end
, 0);
4138 bar
->dragging
= Qnil
;
4140 /* Add bar to its frame's list of scroll bars. */
4141 bar
->next
= FRAME_SCROLL_BARS (f
);
4143 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4144 if (!NILP (bar
->next
))
4145 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4152 /* Draw BAR's handle in the proper position.
4154 If the handle is already drawn from START to END, don't bother
4155 redrawing it, unless REBUILD is non-zero; in that case, always
4156 redraw it. (REBUILD is handy for drawing the handle after expose
4159 Normally, we want to constrain the start and end of the handle to
4160 fit inside its rectangle, but if the user is dragging the scroll
4161 bar handle, we want to let them drag it down all the way, so that
4162 the bar's top is as far down as it goes; otherwise, there's no way
4163 to move to the very end of the buffer. */
4166 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4167 struct scroll_bar
*bar
;
4171 int dragging
= ! NILP (bar
->dragging
);
4172 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4173 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4174 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4175 int length
= end
- start
;
4177 /* If the display is already accurate, do nothing. */
4179 && start
== XINT (bar
->start
)
4180 && end
== XINT (bar
->end
))
4185 /* Make sure the values are reasonable, and try to preserve the
4186 distance between start and end. */
4189 else if (start
> top_range
)
4191 end
= start
+ length
;
4195 else if (end
> top_range
&& ! dragging
)
4198 /* Store the adjusted setting in the scroll bar. */
4199 XSETINT (bar
->start
, start
);
4200 XSETINT (bar
->end
, end
);
4202 /* Clip the end position, just for display. */
4203 if (end
> top_range
)
4206 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4207 top positions, to make sure the handle is always at least that
4208 many pixels tall. */
4209 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4211 SetControlMinimum (ch
, 0);
4212 /* Don't inadvertently activate deactivated scroll bars */
4213 if (GetControlMaximum (ch
) != -1)
4214 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4216 SetControlValue (ch
, start
);
4217 #if TARGET_API_MAC_CARBON
4218 SetControlViewSize (ch
, end
- start
);
4225 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4229 x_scroll_bar_remove (bar
)
4230 struct scroll_bar
*bar
;
4232 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4236 /* Destroy the Mac scroll bar control */
4237 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4239 /* Disassociate this scroll bar from its window. */
4240 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4245 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4246 that we are displaying PORTION characters out of a total of WHOLE
4247 characters, starting at POSITION. If WINDOW has no scroll bar,
4250 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4252 int portion
, whole
, position
;
4254 struct frame
*f
= XFRAME (w
->frame
);
4255 struct scroll_bar
*bar
;
4256 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4257 int window_y
, window_height
;
4259 /* Get window dimensions. */
4260 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4265 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4267 height
= window_height
;
4269 /* Compute the left edge of the scroll bar area. */
4270 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4272 /* Compute the width of the scroll bar which might be less than
4273 the width of the area reserved for the scroll bar. */
4274 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4275 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4279 /* Compute the left edge of the scroll bar. */
4280 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4281 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
4283 sb_left
= left
+ (width
- sb_width
) / 2;
4285 /* Adjustments according to Inside Macintosh to make it look nice */
4287 disp_height
= height
;
4293 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4299 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4302 /* Does the scroll bar exist yet? */
4303 if (NILP (w
->vertical_scroll_bar
))
4306 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4307 left
, top
, width
, height
, 0);
4309 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4311 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4315 /* It may just need to be moved and resized. */
4318 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4319 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4323 /* If already correctly positioned, do nothing. */
4324 if (XINT (bar
->left
) == sb_left
4325 && XINT (bar
->top
) == top
4326 && XINT (bar
->width
) == sb_width
4327 && XINT (bar
->height
) == height
)
4331 /* Clear areas not covered by the scroll bar because it's not as
4332 wide as the area reserved for it . This makes sure a
4333 previous mode line display is cleared after C-x 2 C-x 1, for
4335 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4336 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4337 left
, top
, area_width
, height
, 0);
4340 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4341 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4342 sb_left
- 1, top
, 1, height
, 0);
4346 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4347 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4351 /* Remember new settings. */
4352 XSETINT (bar
->left
, sb_left
);
4353 XSETINT (bar
->top
, top
);
4354 XSETINT (bar
->width
, sb_width
);
4355 XSETINT (bar
->height
, height
);
4361 /* Set the scroll bar's current state, unless we're currently being
4363 if (NILP (bar
->dragging
))
4365 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4368 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4371 int start
= ((double) position
* top_range
) / whole
;
4372 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4373 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4379 /* The following three hooks are used when we're doing a thorough
4380 redisplay of the frame. We don't explicitly know which scroll bars
4381 are going to be deleted, because keeping track of when windows go
4382 away is a real pain - "Can you say set-window-configuration, boys
4383 and girls?" Instead, we just assert at the beginning of redisplay
4384 that *all* scroll bars are to be removed, and then save a scroll bar
4385 from the fiery pit when we actually redisplay its window. */
4387 /* Arrange for all scroll bars on FRAME to be removed at the next call
4388 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4389 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4392 XTcondemn_scroll_bars (frame
)
4395 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4396 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4399 bar
= FRAME_SCROLL_BARS (frame
);
4400 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4401 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4402 XSCROLL_BAR (bar
)->prev
= Qnil
;
4403 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4404 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4405 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4410 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4411 Note that WINDOW isn't necessarily condemned at all. */
4414 XTredeem_scroll_bar (window
)
4415 struct window
*window
;
4417 struct scroll_bar
*bar
;
4419 /* We can't redeem this window's scroll bar if it doesn't have one. */
4420 if (NILP (window
->vertical_scroll_bar
))
4423 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4425 /* Unlink it from the condemned list. */
4427 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4429 if (NILP (bar
->prev
))
4431 /* If the prev pointer is nil, it must be the first in one of
4433 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4434 /* It's not condemned. Everything's fine. */
4436 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4437 window
->vertical_scroll_bar
))
4438 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4440 /* If its prev pointer is nil, it must be at the front of
4441 one or the other! */
4445 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4447 if (! NILP (bar
->next
))
4448 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4450 bar
->next
= FRAME_SCROLL_BARS (f
);
4452 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4453 if (! NILP (bar
->next
))
4454 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4458 /* Remove all scroll bars on FRAME that haven't been saved since the
4459 last call to `*condemn_scroll_bars_hook'. */
4462 XTjudge_scroll_bars (f
)
4465 Lisp_Object bar
, next
;
4467 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4469 /* Clear out the condemned list now so we won't try to process any
4470 more events on the hapless scroll bars. */
4471 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4473 for (; ! NILP (bar
); bar
= next
)
4475 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4477 x_scroll_bar_remove (b
);
4480 b
->next
= b
->prev
= Qnil
;
4483 /* Now there should be no references to the condemned scroll bars,
4484 and they should get garbage-collected. */
4488 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4489 is set to something other than NO_EVENT, it is enqueued.
4491 This may be called from a signal handler, so we have to ignore GC
4495 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4496 struct scroll_bar
*bar
;
4499 struct input_event
*bufp
;
4501 int win_y
, top_range
;
4503 if (! GC_WINDOWP (bar
->window
))
4506 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4507 bufp
->frame_or_window
= bar
->window
;
4510 bar
->dragging
= Qnil
;
4514 case kControlUpButtonPart
:
4515 bufp
->part
= scroll_bar_up_arrow
;
4517 case kControlDownButtonPart
:
4518 bufp
->part
= scroll_bar_down_arrow
;
4520 case kControlPageUpPart
:
4521 bufp
->part
= scroll_bar_above_handle
;
4523 case kControlPageDownPart
:
4524 bufp
->part
= scroll_bar_below_handle
;
4526 #if TARGET_API_MAC_CARBON
4529 case kControlIndicatorPart
:
4531 if (er
->what
== mouseDown
)
4532 bar
->dragging
= make_number (0);
4533 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4534 bufp
->part
= scroll_bar_handle
;
4538 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4539 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4541 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4545 if (! NILP (bar
->dragging
))
4546 win_y
-= XINT (bar
->dragging
);
4550 if (win_y
> top_range
)
4553 XSETINT (bufp
->x
, win_y
);
4554 XSETINT (bufp
->y
, top_range
);
4558 /* Handle some mouse motion while someone is dragging the scroll bar.
4560 This may be called from a signal handler, so we have to ignore GC
4564 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4565 struct scroll_bar
*bar
;
4569 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4571 last_mouse_movement_time
= t
;
4574 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4576 /* If we're dragging the bar, display it. */
4577 if (! GC_NILP (bar
->dragging
))
4579 /* Where should the handle be now? */
4580 int new_start
= y_pos
- 24;
4582 if (new_start
!= XINT (bar
->start
))
4584 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4586 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4592 /* Return information to the user about the current position of the
4593 mouse on the scroll bar. */
4596 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4598 Lisp_Object
*bar_window
;
4599 enum scroll_bar_part
*part
;
4601 unsigned long *time
;
4603 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4604 WindowPtr wp
= front_emacs_window ();
4606 struct frame
*f
= mac_window_to_frame (wp
);
4607 int win_y
, top_range
;
4609 SetPortWindowPort (wp
);
4611 GetMouse (&mouse_pos
);
4613 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4614 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4616 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4620 if (! NILP (bar
->dragging
))
4621 win_y
-= XINT (bar
->dragging
);
4625 if (win_y
> top_range
)
4629 *bar_window
= bar
->window
;
4631 if (! NILP (bar
->dragging
))
4632 *part
= scroll_bar_handle
;
4633 else if (win_y
< XINT (bar
->start
))
4634 *part
= scroll_bar_above_handle
;
4635 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
4636 *part
= scroll_bar_handle
;
4638 *part
= scroll_bar_below_handle
;
4640 XSETINT (*x
, win_y
);
4641 XSETINT (*y
, top_range
);
4644 last_mouse_scroll_bar
= Qnil
;
4646 *time
= last_mouse_movement_time
;
4649 /***********************************************************************
4651 ***********************************************************************/
4653 /* Set clipping for output in glyph row ROW. W is the window in which
4654 we operate. GC is the graphics context to set clipping in.
4656 ROW may be a text row or, e.g., a mode line. Text rows must be
4657 clipped to the interior of the window dedicated to text display,
4658 mode lines must be clipped to the whole window. */
4661 x_clip_to_row (w
, row
, area
, gc
)
4663 struct glyph_row
*row
;
4667 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4669 int window_x
, window_y
, window_width
;
4671 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
4673 clip_rect
.left
= window_x
;
4674 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4675 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4676 clip_rect
.right
= clip_rect
.left
+ window_width
;
4677 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4679 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
4683 /* Draw a hollow box cursor on window W in glyph row ROW. */
4686 x_draw_hollow_cursor (w
, row
)
4688 struct glyph_row
*row
;
4690 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4691 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4692 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4695 struct glyph
*cursor_glyph
;
4698 /* Get the glyph the cursor is on. If we can't tell because
4699 the current matrix is invalid or such, give up. */
4700 cursor_glyph
= get_phys_cursor_glyph (w
);
4701 if (cursor_glyph
== NULL
)
4704 /* Compute frame-relative coordinates for phys cursor. */
4705 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
4706 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
4707 wd
= w
->phys_cursor_width
;
4709 /* The foreground of cursor_gc is typically the same as the normal
4710 background color, which can cause the cursor box to be invisible. */
4711 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4712 if (dpyinfo
->scratch_cursor_gc
)
4713 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
4715 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
4716 GCForeground
, &xgcv
);
4717 gc
= dpyinfo
->scratch_cursor_gc
;
4719 /* Set clipping, draw the rectangle, and reset clipping again. */
4720 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4721 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
4722 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4726 /* Draw a bar cursor on window W in glyph row ROW.
4728 Implementation note: One would like to draw a bar cursor with an
4729 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4730 Unfortunately, I didn't find a font yet that has this property set.
4734 x_draw_bar_cursor (w
, row
, width
, kind
)
4736 struct glyph_row
*row
;
4738 enum text_cursor_kinds kind
;
4740 struct frame
*f
= XFRAME (w
->frame
);
4741 struct glyph
*cursor_glyph
;
4743 /* If cursor is out of bounds, don't draw garbage. This can happen
4744 in mini-buffer windows when switching between echo area glyphs
4746 cursor_glyph
= get_phys_cursor_glyph (w
);
4747 if (cursor_glyph
== NULL
)
4750 /* If on an image, draw like a normal cursor. That's usually better
4751 visible than drawing a bar, esp. if the image is large so that
4752 the bar might not be in the window. */
4753 if (cursor_glyph
->type
== IMAGE_GLYPH
)
4755 struct glyph_row
*row
;
4756 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
4757 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
4761 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4762 Window window
= FRAME_MAC_WINDOW (f
);
4763 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
4764 unsigned long mask
= GCForeground
| GCBackground
;
4765 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
4768 /* If the glyph's background equals the color we normally draw
4769 the bar cursor in, the bar cursor in its normal color is
4770 invisible. Use the glyph's foreground color instead in this
4771 case, on the assumption that the glyph's colors are chosen so
4772 that the glyph is legible. */
4773 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
4774 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
4776 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4779 XChangeGC (dpy
, gc
, mask
, &xgcv
);
4782 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
4783 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
4787 width
= FRAME_CURSOR_WIDTH (f
);
4788 width
= min (cursor_glyph
->pixel_width
, width
);
4790 w
->phys_cursor_width
= width
;
4791 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4793 if (kind
== BAR_CURSOR
)
4794 XFillRectangle (dpy
, window
, gc
,
4795 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4796 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
4797 width
, row
->height
);
4799 XFillRectangle (dpy
, window
, gc
,
4800 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4801 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
4802 row
->height
- width
),
4803 cursor_glyph
->pixel_width
,
4806 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4811 /* RIF: Define cursor CURSOR on frame F. */
4814 mac_define_frame_cursor (f
, cursor
)
4818 SetThemeCursor (cursor
);
4822 /* RIF: Clear area on frame F. */
4825 mac_clear_frame_area (f
, x
, y
, width
, height
)
4827 int x
, y
, width
, height
;
4829 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4830 x
, y
, width
, height
, 0);
4834 /* RIF: Draw cursor on window W. */
4837 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
4839 struct glyph_row
*glyph_row
;
4841 int cursor_type
, cursor_width
;
4846 w
->phys_cursor_type
= cursor_type
;
4847 w
->phys_cursor_on_p
= 1;
4849 if (glyph_row
->exact_window_width_line_p
4850 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
4852 glyph_row
->cursor_in_fringe_p
= 1;
4853 draw_fringe_bitmap (w
, glyph_row
, 0);
4856 switch (cursor_type
)
4858 case HOLLOW_BOX_CURSOR
:
4859 x_draw_hollow_cursor (w
, glyph_row
);
4862 case FILLED_BOX_CURSOR
:
4863 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
4867 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
4871 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
4875 w
->phys_cursor_width
= 0;
4887 #if 0 /* MAC_TODO: no icon support yet. */
4889 x_bitmap_icon (f
, icon
)
4895 if (FRAME_W32_WINDOW (f
) == 0)
4899 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
4900 else if (STRINGP (icon
))
4901 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
4902 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
4903 else if (SYMBOLP (icon
))
4907 if (EQ (icon
, intern ("application")))
4908 name
= (LPCTSTR
) IDI_APPLICATION
;
4909 else if (EQ (icon
, intern ("hand")))
4910 name
= (LPCTSTR
) IDI_HAND
;
4911 else if (EQ (icon
, intern ("question")))
4912 name
= (LPCTSTR
) IDI_QUESTION
;
4913 else if (EQ (icon
, intern ("exclamation")))
4914 name
= (LPCTSTR
) IDI_EXCLAMATION
;
4915 else if (EQ (icon
, intern ("asterisk")))
4916 name
= (LPCTSTR
) IDI_ASTERISK
;
4917 else if (EQ (icon
, intern ("winlogo")))
4918 name
= (LPCTSTR
) IDI_WINLOGO
;
4922 hicon
= LoadIcon (NULL
, name
);
4930 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
4935 #endif /* MAC_TODO */
4937 /************************************************************************
4939 ************************************************************************/
4941 /* Display Error Handling functions not used on W32. Listing them here
4942 helps diff stay in step when comparing w32term.c with xterm.c.
4944 x_error_catcher (display, error)
4945 x_catch_errors (dpy)
4946 x_catch_errors_unwind (old_val)
4947 x_check_errors (dpy, format)
4948 x_had_errors_p (dpy)
4949 x_clear_errors (dpy)
4950 x_uncatch_errors (dpy, count)
4952 x_connection_signal (signalnum)
4953 x_connection_closed (dpy, error_message)
4954 x_error_quitter (display, error)
4955 x_error_handler (display, error)
4956 x_io_error_quitter (display)
4961 /* Changing the font of the frame. */
4963 /* Give frame F the font named FONTNAME as its default font, and
4964 return the full name of that font. FONTNAME may be a wildcard
4965 pattern; in that case, we choose some font that fits the pattern.
4966 The return value shows which font we chose. */
4969 x_new_font (f
, fontname
)
4971 register char *fontname
;
4973 struct font_info
*fontp
4974 = FS_LOAD_FONT (f
, 0, fontname
, -1);
4979 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4980 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
4981 FRAME_FONTSET (f
) = -1;
4983 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
4984 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
4985 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
4987 compute_fringe_widths (f
, 1);
4989 /* Compute the scroll bar width in character columns. */
4990 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
4992 int wid
= FRAME_COLUMN_WIDTH (f
);
4993 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
4994 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
4998 int wid
= FRAME_COLUMN_WIDTH (f
);
4999 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5002 /* Now make the frame display the given font. */
5003 if (FRAME_MAC_WINDOW (f
) != 0)
5005 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5007 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5009 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5012 /* Don't change the size of a tip frame; there's no point in
5013 doing it because it's done in Fx_show_tip, and it leads to
5014 problems because the tip frame has no widget. */
5015 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5016 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5019 return build_string (fontp
->full_name
);
5022 /* Give frame F the fontset named FONTSETNAME as its default font, and
5023 return the full name of that fontset. FONTSETNAME may be a wildcard
5024 pattern; in that case, we choose some fontset that fits the pattern.
5025 The return value shows which fontset we chose. */
5028 x_new_fontset (f
, fontsetname
)
5032 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5038 if (FRAME_FONTSET (f
) == fontset
)
5039 /* This fontset is already set in frame F. There's nothing more
5041 return fontset_name (fontset
);
5043 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5045 if (!STRINGP (result
))
5046 /* Can't load ASCII font. */
5049 /* Since x_new_font doesn't update any fontset information, do it now. */
5050 FRAME_FONTSET(f
) = fontset
;
5052 return build_string (fontsetname
);
5056 /***********************************************************************
5057 TODO: W32 Input Methods
5058 ***********************************************************************/
5059 /* Listing missing functions from xterm.c helps diff stay in step.
5061 xim_destroy_callback (xim, client_data, call_data)
5062 xim_open_dpy (dpyinfo, resource_name)
5064 xim_instantiate_callback (display, client_data, call_data)
5065 xim_initialize (dpyinfo, resource_name)
5066 xim_close_dpy (dpyinfo)
5072 mac_get_window_bounds (f
, inner
, outer
)
5074 Rect
*inner
, *outer
;
5076 #if TARGET_API_MAC_CARBON
5077 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5078 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5079 #else /* not TARGET_API_MAC_CARBON */
5080 RgnHandle region
= NewRgn ();
5082 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5083 *inner
= (*region
)->rgnBBox
;
5084 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5085 *outer
= (*region
)->rgnBBox
;
5086 DisposeRgn (region
);
5087 #endif /* not TARGET_API_MAC_CARBON */
5091 /* Calculate the absolute position in frame F
5092 from its current recorded position values and gravity. */
5095 x_calc_absolute_position (f
)
5098 int width_diff
= 0, height_diff
= 0;
5099 int flags
= f
->size_hint_flags
;
5102 /* We have nothing to do if the current position
5103 is already for the top-left corner. */
5104 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5107 /* Find the offsets of the outside upper-left corner of
5108 the inner window, with respect to the outer window. */
5109 mac_get_window_bounds (f
, &inner
, &outer
);
5111 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5112 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5114 /* Treat negative positions as relative to the leftmost bottommost
5115 position that fits on the screen. */
5116 if (flags
& XNegative
)
5117 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5119 - FRAME_PIXEL_WIDTH (f
)
5122 if (flags
& YNegative
)
5123 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5125 - FRAME_PIXEL_HEIGHT (f
)
5128 /* The left_pos and top_pos
5129 are now relative to the top and left screen edges,
5130 so the flags should correspond. */
5131 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5134 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5135 to really change the position, and 0 when calling from
5136 x_make_frame_visible (in that case, XOFF and YOFF are the current
5137 position values). It is -1 when calling from x_set_frame_parameters,
5138 which means, do adjust for borders but don't change the gravity. */
5141 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5143 register int xoff
, yoff
;
5146 if (change_gravity
> 0)
5150 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5152 f
->size_hint_flags
|= XNegative
;
5154 f
->size_hint_flags
|= YNegative
;
5155 f
->win_gravity
= NorthWestGravity
;
5157 x_calc_absolute_position (f
);
5160 x_wm_set_size_hint (f
, (long) 0, 0);
5162 #if TARGET_API_MAC_CARBON
5163 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5164 /* If the title bar is completely outside the screen, adjust the
5166 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5167 kWindowConstrainMoveRegardlessOfFit
5168 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5169 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5172 Rect inner
, outer
, screen_rect
, dummy
;
5173 RgnHandle region
= NewRgn ();
5175 mac_get_window_bounds (f
, &inner
, &outer
);
5176 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5177 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5178 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5179 f
->top_pos
+ f
->y_pixels_diff
, false);
5181 /* If the title bar is completely outside the screen, adjust the
5182 position. The variable `outer' holds the title bar rectangle.
5183 The variable `inner' holds slightly smaller one than `outer',
5184 so that the calculation of overlapping may not become too
5186 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5187 outer
= (*region
)->rgnBBox
;
5188 DisposeRgn (region
);
5190 InsetRect (&inner
, 8, 8);
5191 screen_rect
= qd
.screenBits
.bounds
;
5192 screen_rect
.top
+= GetMBarHeight ();
5194 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5196 if (inner
.right
<= screen_rect
.left
)
5197 f
->left_pos
= screen_rect
.left
;
5198 else if (inner
.left
>= screen_rect
.right
)
5199 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5201 if (inner
.bottom
<= screen_rect
.top
)
5202 f
->top_pos
= screen_rect
.top
;
5203 else if (inner
.top
>= screen_rect
.bottom
)
5204 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5206 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5207 f
->top_pos
+ f
->y_pixels_diff
, false);
5215 /* Call this to change the size of frame F's x-window.
5216 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5217 for this size change and subsequent size changes.
5218 Otherwise we leave the window gravity unchanged. */
5221 x_set_window_size (f
, change_gravity
, cols
, rows
)
5226 int pixelwidth
, pixelheight
;
5230 check_frame_size (f
, &rows
, &cols
);
5231 f
->scroll_bar_actual_width
5232 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5234 compute_fringe_widths (f
, 0);
5236 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5237 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5239 f
->win_gravity
= NorthWestGravity
;
5240 x_wm_set_size_hint (f
, (long) 0, 0);
5242 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5243 #if TARGET_API_MAC_CARBON
5244 if (f
->output_data
.mac
->hourglass_control
)
5245 MoveControl (f
->output_data
.mac
->hourglass_control
,
5246 pixelwidth
- HOURGLASS_WIDTH
, 0);
5249 /* Now, strictly speaking, we can't be sure that this is accurate,
5250 but the window manager will get around to dealing with the size
5251 change request eventually, and we'll hear how it went when the
5252 ConfigureNotify event gets here.
5254 We could just not bother storing any of this information here,
5255 and let the ConfigureNotify event set everything up, but that
5256 might be kind of confusing to the Lisp code, since size changes
5257 wouldn't be reported in the frame parameters until some random
5258 point in the future when the ConfigureNotify event arrives.
5260 We pass 1 for DELAY since we can't run Lisp code inside of
5262 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5263 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5264 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5266 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5267 receive in the ConfigureNotify event; if we get what we asked
5268 for, then the event won't cause the screen to become garbaged, so
5269 we have to make sure to do it here. */
5270 SET_FRAME_GARBAGED (f
);
5272 XFlush (FRAME_X_DISPLAY (f
));
5274 /* If cursor was outside the new size, mark it as off. */
5275 mark_window_cursors_off (XWINDOW (f
->root_window
));
5277 /* Clear out any recollection of where the mouse highlighting was,
5278 since it might be in a place that's outside the new frame size.
5279 Actually checking whether it is outside is a pain in the neck,
5280 so don't try--just let the highlighting be done afresh with new size. */
5281 cancel_mouse_face (f
);
5286 /* Mouse warping. */
5288 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5291 x_set_mouse_position (f
, x
, y
)
5297 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5298 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5300 if (pix_x
< 0) pix_x
= 0;
5301 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5303 if (pix_y
< 0) pix_y
= 0;
5304 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5306 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5310 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5314 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5317 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5318 0, 0, 0, 0, pix_x
, pix_y
);
5324 /* focus shifting, raising and lowering. */
5327 x_focus_on_frame (f
)
5330 #if 0 /* This proves to be unpleasant. */
5334 /* I don't think that the ICCCM allows programs to do things like this
5335 without the interaction of the window manager. Whatever you end up
5336 doing with this code, do it to x_unfocus_frame too. */
5337 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5338 RevertToPointerRoot
, CurrentTime
);
5348 /* Raise frame F. */
5353 if (f
->async_visible
)
5356 SelectWindow (FRAME_MAC_WINDOW (f
));
5361 /* Lower frame F. */
5366 if (f
->async_visible
)
5369 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5375 XTframe_raise_lower (f
, raise_flag
)
5385 /* Change of visibility. */
5387 /* This tries to wait until the frame is really visible.
5388 However, if the window manager asks the user where to position
5389 the frame, this will return before the user finishes doing that.
5390 The frame will not actually be visible at that time,
5391 but it will become visible later when the window manager
5392 finishes with it. */
5395 x_make_frame_visible (f
)
5399 int original_top
, original_left
;
5403 if (! FRAME_VISIBLE_P (f
))
5405 /* We test FRAME_GARBAGED_P here to make sure we don't
5406 call x_set_offset a second time
5407 if we get to x_make_frame_visible a second time
5408 before the window gets really visible. */
5409 if (! FRAME_ICONIFIED_P (f
)
5410 && ! f
->output_data
.mac
->asked_for_visible
)
5411 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5413 f
->output_data
.mac
->asked_for_visible
= 1;
5415 #if TARGET_API_MAC_CARBON
5416 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5418 struct frame
*sf
= SELECTED_FRAME ();
5419 if (!FRAME_MAC_P (sf
))
5420 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5421 kWindowCenterOnMainScreen
);
5423 RepositionWindow (FRAME_MAC_WINDOW (f
),
5424 FRAME_MAC_WINDOW (sf
),
5425 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5426 kWindowCascadeStartAtParentWindowScreen
5428 kWindowCascadeOnParentWindowScreen
5431 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5434 ShowWindow (FRAME_MAC_WINDOW (f
));
5437 XFlush (FRAME_MAC_DISPLAY (f
));
5439 /* Synchronize to ensure Emacs knows the frame is visible
5440 before we do anything else. We do this loop with input not blocked
5441 so that incoming events are handled. */
5446 /* This must come after we set COUNT. */
5449 XSETFRAME (frame
, f
);
5451 /* Wait until the frame is visible. Process X events until a
5452 MapNotify event has been seen, or until we think we won't get a
5453 MapNotify at all.. */
5454 for (count
= input_signal_count
+ 10;
5455 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5457 /* Force processing of queued events. */
5460 /* Machines that do polling rather than SIGIO have been
5461 observed to go into a busy-wait here. So we'll fake an
5462 alarm signal to let the handler know that there's something
5463 to be read. We used to raise a real alarm, but it seems
5464 that the handler isn't always enabled here. This is
5466 if (input_polling_used ())
5468 /* It could be confusing if a real alarm arrives while
5469 processing the fake one. Turn it off and let the
5470 handler reset it. */
5471 extern void poll_for_input_1
P_ ((void));
5472 int old_poll_suppress_count
= poll_suppress_count
;
5473 poll_suppress_count
= 1;
5474 poll_for_input_1 ();
5475 poll_suppress_count
= old_poll_suppress_count
;
5478 /* See if a MapNotify event has been processed. */
5479 FRAME_SAMPLE_VISIBILITY (f
);
5484 /* Change from mapped state to withdrawn state. */
5486 /* Make the frame visible (mapped and not iconified). */
5489 x_make_frame_invisible (f
)
5492 /* Don't keep the highlight on an invisible frame. */
5493 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5494 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5498 HideWindow (FRAME_MAC_WINDOW (f
));
5500 /* We can't distinguish this from iconification
5501 just by the event that we get from the server.
5502 So we can't win using the usual strategy of letting
5503 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5504 and synchronize with the server to make sure we agree. */
5506 FRAME_ICONIFIED_P (f
) = 0;
5507 f
->async_visible
= 0;
5508 f
->async_iconified
= 0;
5513 /* Change window state from mapped to iconified. */
5519 /* Don't keep the highlight on an invisible frame. */
5520 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5521 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5524 /* Review: Since window is still visible in dock, still allow updates? */
5525 if (f
->async_iconified
)
5531 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5537 /* Free X resources of frame F. */
5540 x_free_frame_resources (f
)
5543 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5544 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5548 if (wp
!= tip_window
)
5549 remove_window_handler (wp
);
5552 if (wp
== tip_window
)
5553 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5554 closed' event. So we reset tip_window here. */
5557 free_frame_menubar (f
);
5559 if (FRAME_FACE_CACHE (f
))
5560 free_frame_faces (f
);
5564 if (FRAME_SIZE_HINTS (f
))
5565 xfree (FRAME_SIZE_HINTS (f
));
5567 xfree (f
->output_data
.mac
);
5568 f
->output_data
.mac
= NULL
;
5570 if (f
== dpyinfo
->x_focus_frame
)
5571 dpyinfo
->x_focus_frame
= 0;
5572 if (f
== dpyinfo
->x_focus_event_frame
)
5573 dpyinfo
->x_focus_event_frame
= 0;
5574 if (f
== dpyinfo
->x_highlight_frame
)
5575 dpyinfo
->x_highlight_frame
= 0;
5577 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5579 dpyinfo
->mouse_face_beg_row
5580 = dpyinfo
->mouse_face_beg_col
= -1;
5581 dpyinfo
->mouse_face_end_row
5582 = dpyinfo
->mouse_face_end_col
= -1;
5583 dpyinfo
->mouse_face_window
= Qnil
;
5584 dpyinfo
->mouse_face_deferred_gc
= 0;
5585 dpyinfo
->mouse_face_mouse_frame
= 0;
5592 /* Destroy the X window of frame F. */
5595 x_destroy_window (f
)
5598 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5600 x_free_frame_resources (f
);
5602 dpyinfo
->reference_count
--;
5606 /* Setting window manager hints. */
5608 /* Set the normal size hints for the window manager, for frame F.
5609 FLAGS is the flags word to use--or 0 meaning preserve the flags
5610 that the window now has.
5611 If USER_POSITION is nonzero, we set the USPosition
5612 flag (this is useful when FLAGS is 0). */
5614 x_wm_set_size_hint (f
, flags
, user_position
)
5619 int base_width
, base_height
, width_inc
, height_inc
;
5620 int min_rows
= 0, min_cols
= 0;
5621 XSizeHints
*size_hints
;
5623 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5624 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5625 width_inc
= FRAME_COLUMN_WIDTH (f
);
5626 height_inc
= FRAME_LINE_HEIGHT (f
);
5628 check_frame_size (f
, &min_rows
, &min_cols
);
5630 size_hints
= FRAME_SIZE_HINTS (f
);
5631 if (size_hints
== NULL
)
5633 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
5634 bzero (size_hints
, sizeof (XSizeHints
));
5637 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
5638 size_hints
->width_inc
= width_inc
;
5639 size_hints
->height_inc
= height_inc
;
5640 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
5641 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
5642 size_hints
->base_width
= base_width
;
5643 size_hints
->base_height
= base_height
;
5646 size_hints
->flags
= flags
;
5647 else if (user_position
)
5649 size_hints
->flags
&= ~ PPosition
;
5650 size_hints
->flags
|= USPosition
;
5654 #if 0 /* MAC_TODO: hide application instead of iconify? */
5655 /* Used for IconicState or NormalState */
5658 x_wm_set_window_state (f
, state
)
5662 #ifdef USE_X_TOOLKIT
5665 XtSetArg (al
[0], XtNinitialState
, state
);
5666 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5667 #else /* not USE_X_TOOLKIT */
5668 Window window
= FRAME_X_WINDOW (f
);
5670 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5671 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5673 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5674 #endif /* not USE_X_TOOLKIT */
5678 x_wm_set_icon_pixmap (f
, pixmap_id
)
5684 #ifndef USE_X_TOOLKIT
5685 Window window
= FRAME_X_WINDOW (f
);
5690 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5691 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5695 /* It seems there is no way to turn off use of an icon pixmap.
5696 The following line does it, only if no icon has yet been created,
5697 for some window managers. But with mwm it crashes.
5698 Some people say it should clear the IconPixmapHint bit in this case,
5699 but that doesn't work, and the X consortium said it isn't the
5700 right thing at all. Since there is no way to win,
5701 best to explicitly give up. */
5703 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5709 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5713 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
5714 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5717 #else /* not USE_X_TOOLKIT */
5719 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5720 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5722 #endif /* not USE_X_TOOLKIT */
5725 #endif /* MAC_TODO */
5728 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5732 #if 0 /* MAC_TODO: no icons on Mac */
5733 #ifdef USE_X_TOOLKIT
5734 Window window
= XtWindow (f
->output_data
.x
->widget
);
5736 Window window
= FRAME_X_WINDOW (f
);
5739 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5740 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5741 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5743 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5744 #endif /* MAC_TODO */
5748 /***********************************************************************
5750 ***********************************************************************/
5752 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5755 x_get_font_info (f
, font_idx
)
5759 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
5762 /* the global font name table */
5763 char **font_name_table
= NULL
;
5764 int font_name_table_size
= 0;
5765 int font_name_count
= 0;
5768 /* compare two strings ignoring case */
5770 stricmp (const char *s
, const char *t
)
5772 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
5775 return tolower (*s
) - tolower (*t
);
5778 /* compare two strings ignoring case and handling wildcard */
5780 wildstrieq (char *s1
, char *s2
)
5782 if (strcmp (s1
, "*") == 0 || strcmp (s2
, "*") == 0)
5785 return stricmp (s1
, s2
) == 0;
5788 /* Assume parameter 1 is fully qualified, no wildcards. */
5790 mac_font_pattern_match (fontname
, pattern
)
5794 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
5795 char *font_name_copy
= (char *) alloca (strlen (fontname
) + 1);
5798 /* Copy fontname so we can modify it during comparison. */
5799 strcpy (font_name_copy
, fontname
);
5804 /* Turn pattern into a regexp and do a regexp match. */
5805 for (; *pattern
; pattern
++)
5807 if (*pattern
== '?')
5809 else if (*pattern
== '*')
5820 return (fast_c_string_match_ignore_case (build_string (regex
),
5821 font_name_copy
) >= 0);
5824 /* Two font specs are considered to match if their foundry, family,
5825 weight, slant, and charset match. */
5827 mac_font_match (char *mf
, char *xf
)
5829 char m_foundry
[50], m_family
[50], m_weight
[20], m_slant
[2], m_charset
[20];
5830 char x_foundry
[50], x_family
[50], x_weight
[20], x_slant
[2], x_charset
[20];
5832 if (sscanf (mf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5833 m_foundry
, m_family
, m_weight
, m_slant
, m_charset
) != 5)
5834 return mac_font_pattern_match (mf
, xf
);
5836 if (sscanf (xf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5837 x_foundry
, x_family
, x_weight
, x_slant
, x_charset
) != 5)
5838 return mac_font_pattern_match (mf
, xf
);
5840 return (wildstrieq (m_foundry
, x_foundry
)
5841 && wildstrieq (m_family
, x_family
)
5842 && wildstrieq (m_weight
, x_weight
)
5843 && wildstrieq (m_slant
, x_slant
)
5844 && wildstrieq (m_charset
, x_charset
))
5845 || mac_font_pattern_match (mf
, xf
);
5849 static Lisp_Object Qbig5
, Qcn_gb
, Qsjis
, Qeuc_kr
;
5852 decode_mac_font_name (name
, size
, scriptcode
)
5855 #if TARGET_API_MAC_CARBON
5861 Lisp_Object coding_system
;
5862 struct coding_system coding
;
5868 coding_system
= Qbig5
;
5871 coding_system
= Qcn_gb
;
5874 coding_system
= Qsjis
;
5877 coding_system
= Qeuc_kr
;
5883 setup_coding_system (coding_system
, &coding
);
5884 coding
.src_multibyte
= 0;
5885 coding
.dst_multibyte
= 1;
5886 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5887 coding
.composing
= COMPOSITION_DISABLED
;
5888 buf
= (char *) alloca (size
);
5890 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
5891 bcopy (buf
, name
, coding
.produced
);
5892 name
[coding
.produced
] = '\0';
5897 mac_to_x_fontname (name
, size
, style
, scriptcode
)
5901 #if TARGET_API_MAC_CARBON
5907 char foundry
[32], family
[32], cs
[32];
5908 char xf
[256], *result
, *p
;
5910 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) != 3)
5912 strcpy(foundry
, "Apple");
5913 strcpy(family
, name
);
5917 case smTradChinese
: /* == kTextEncodingMacChineseTrad */
5918 strcpy(cs
, "big5-0");
5920 case smSimpChinese
: /* == kTextEncodingMacChineseSimp */
5921 strcpy(cs
, "gb2312.1980-0");
5923 case smJapanese
: /* == kTextEncodingMacJapanese */
5924 strcpy(cs
, "jisx0208.1983-sjis");
5927 /* Each Apple Japanese font is entered into the font table
5928 twice: once as a jisx0208.1983-sjis font and once as a
5929 jisx0201.1976-0 font. The latter can be used to display
5930 the ascii charset and katakana-jisx0201 charset. A
5931 negative script code signals that the name of this latter
5932 font is being built. */
5933 strcpy(cs
, "jisx0201.1976-0");
5935 case smKorean
: /* == kTextEncodingMacKorean */
5936 strcpy(cs
, "ksc5601.1989-0");
5938 #if TARGET_API_MAC_CARBON
5939 case kTextEncodingMacCyrillic
:
5940 strcpy(cs
, "mac-cyrillic");
5942 case kTextEncodingMacCentralEurRoman
:
5943 strcpy(cs
, "mac-centraleurroman");
5945 case kTextEncodingMacSymbol
:
5946 case kTextEncodingMacDingbats
:
5947 strcpy(cs
, "adobe-fontspecific");
5951 strcpy(cs
, "mac-roman");
5956 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5957 foundry
, family
, style
& bold
? "bold" : "medium",
5958 style
& italic
? 'i' : 'r', size
, size
* 10, size
* 10, cs
);
5960 result
= (char *) xmalloc (strlen (xf
) + 1);
5961 strcpy (result
, xf
);
5962 for (p
= result
; *p
; p
++)
5968 /* Convert an X font spec to the corresponding mac font name, which
5969 can then be passed to GetFNum after conversion to a Pascal string.
5970 For ordinary Mac fonts, this should just be their names, like
5971 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5972 collection contain their charset designation in their names, like
5973 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5974 names are handled accordingly. */
5976 x_font_name_to_mac_font_name (char *xf
, char *mf
)
5978 char foundry
[32], family
[32], weight
[20], slant
[2], cs
[32];
5979 Lisp_Object coding_system
= Qnil
;
5980 struct coding_system coding
;
5984 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5985 foundry
, family
, weight
, slant
, cs
) != 5 &&
5986 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5987 foundry
, family
, weight
, slant
, cs
) != 5)
5990 if (strcmp (cs
, "big5-0") == 0)
5991 coding_system
= Qbig5
;
5992 else if (strcmp (cs
, "gb2312.1980-0") == 0)
5993 coding_system
= Qcn_gb
;
5994 else if (strcmp (cs
, "jisx0208.1983-sjis") == 0
5995 || strcmp (cs
, "jisx0201.1976-0") == 0)
5996 coding_system
= Qsjis
;
5997 else if (strcmp (cs
, "ksc5601.1989-0") == 0)
5998 coding_system
= Qeuc_kr
;
5999 else if (strcmp (cs
, "mac-roman") == 0
6000 || strcmp (cs
, "mac-cyrillic") == 0
6001 || strcmp (cs
, "mac-centraleurroman") == 0
6002 || strcmp (cs
, "adobe-fontspecific") == 0)
6003 strcpy (mf
, family
);
6005 sprintf (mf
, "%s-%s-%s", foundry
, family
, cs
);
6007 if (!NILP (coding_system
))
6009 setup_coding_system (coding_system
, &coding
);
6010 coding
.src_multibyte
= 1;
6011 coding
.dst_multibyte
= 1;
6012 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6013 encode_coding (&coding
, family
, mf
, strlen (family
), sizeof (Str32
) - 1);
6014 mf
[coding
.produced
] = '\0';
6020 add_font_name_table_entry (char *font_name
)
6022 if (font_name_table_size
== 0)
6024 font_name_table_size
= 16;
6025 font_name_table
= (char **)
6026 xmalloc (font_name_table_size
* sizeof (char *));
6028 else if (font_name_count
+ 1 >= font_name_table_size
)
6030 font_name_table_size
+= 16;
6031 font_name_table
= (char **)
6032 xrealloc (font_name_table
,
6033 font_name_table_size
* sizeof (char *));
6036 font_name_table
[font_name_count
++] = font_name
;
6039 /* Sets up the table font_name_table to contain the list of all fonts
6040 in the system the first time the table is used so that the Resource
6041 Manager need not be accessed every time this information is
6045 init_font_name_table ()
6047 #if TARGET_API_MAC_CARBON
6050 if (Gestalt (gestaltSystemVersion
, &sv
) == noErr
&& sv
>= 0x1000)
6052 FMFontFamilyIterator ffi
;
6053 FMFontFamilyInstanceIterator ffii
;
6056 /* Create a dummy instance iterator here to avoid creating and
6057 destroying it in the loop. */
6058 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6060 /* Create an iterator to enumerate the font families. */
6061 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6064 FMDisposeFontFamilyInstanceIterator (&ffii
);
6068 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6074 TextEncoding encoding
;
6075 TextEncodingBase sc
;
6077 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6083 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6085 sc
= GetTextEncodingBase (encoding
);
6086 decode_mac_font_name (name
, sizeof (name
), sc
);
6088 /* Point the instance iterator at the current font family. */
6089 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6092 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6095 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6096 contained in Apple Japanese (SJIS) font. */
6100 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6102 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6104 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6106 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6111 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6113 if (sc
== smJapanese
)
6118 else if (sc
== -smJapanese
)
6123 /* Dispose of the iterators. */
6124 FMDisposeFontFamilyIterator (&ffi
);
6125 FMDisposeFontFamilyInstanceIterator (&ffii
);
6129 #endif /* TARGET_API_MAC_CARBON */
6131 SInt16 fontnum
, old_fontnum
;
6132 int num_mac_fonts
= CountResources('FOND');
6134 Handle font_handle
, font_handle_2
;
6135 short id
, scriptcode
;
6138 struct FontAssoc
*fat
;
6139 struct AsscEntry
*assc_entry
;
6141 GetPort (&port
); /* save the current font number used */
6142 #if TARGET_API_MAC_CARBON
6143 old_fontnum
= GetPortTextFont (port
);
6145 old_fontnum
= port
->txFont
;
6148 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6150 font_handle
= GetIndResource ('FOND', i
);
6154 GetResInfo (font_handle
, &id
, &type
, name
);
6155 GetFNum (name
, &fontnum
);
6161 scriptcode
= FontToScript (fontnum
);
6162 decode_mac_font_name (name
, sizeof (name
), scriptcode
);
6165 HLock (font_handle
);
6167 if (GetResourceSizeOnDisk (font_handle
)
6168 >= sizeof (struct FamRec
))
6170 fat
= (struct FontAssoc
*) (*font_handle
6171 + sizeof (struct FamRec
));
6173 = (struct AsscEntry
*) (*font_handle
6174 + sizeof (struct FamRec
)
6175 + sizeof (struct FontAssoc
));
6177 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6179 if (font_name_table_size
== 0)
6181 font_name_table_size
= 16;
6182 font_name_table
= (char **)
6183 xmalloc (font_name_table_size
* sizeof (char *));
6185 else if (font_name_count
>= font_name_table_size
)
6187 font_name_table_size
+= 16;
6188 font_name_table
= (char **)
6189 xrealloc (font_name_table
,
6190 font_name_table_size
* sizeof (char *));
6192 font_name_table
[font_name_count
++]
6193 = mac_to_x_fontname (name
,
6194 assc_entry
->fontSize
,
6195 assc_entry
->fontStyle
,
6197 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6198 parts are contained in Apple Japanese (SJIS)
6200 if (smJapanese
== scriptcode
)
6202 font_name_table
[font_name_count
++]
6203 = mac_to_x_fontname (name
,
6204 assc_entry
->fontSize
,
6205 assc_entry
->fontStyle
,
6211 HUnlock (font_handle
);
6212 font_handle_2
= GetNextFOND (font_handle
);
6213 ReleaseResource (font_handle
);
6214 font_handle
= font_handle_2
;
6216 while (ResError () == noErr
&& font_handle
);
6219 TextFont (old_fontnum
);
6220 #if TARGET_API_MAC_CARBON
6222 #endif /* TARGET_API_MAC_CARBON */
6227 mac_clear_font_name_table ()
6231 for (i
= 0; i
< font_name_count
; i
++)
6232 xfree (font_name_table
[i
]);
6233 xfree (font_name_table
);
6234 font_name_table
= NULL
;
6235 font_name_table_size
= font_name_count
= 0;
6239 enum xlfd_scalable_field_index
6241 XLFD_SCL_PIXEL_SIZE
,
6242 XLFD_SCL_POINT_SIZE
,
6247 static int xlfd_scalable_fields
[] =
6256 mac_c_string_match (regexp
, string
, nonspecial
, exact
)
6258 const char *string
, *nonspecial
;
6263 if (strcmp (string
, nonspecial
) == 0)
6264 return build_string (string
);
6266 else if (strstr (string
, nonspecial
))
6268 Lisp_Object str
= build_string (string
);
6270 if (fast_string_match (regexp
, str
) >= 0)
6278 mac_do_list_fonts (pattern
, maxnames
)
6283 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6284 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6287 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6288 char *longest_start
, *cur_start
, *nonspecial
;
6289 int longest_len
, exact
;
6291 if (font_name_table
== NULL
) /* Initialize when first used. */
6292 init_font_name_table ();
6294 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6297 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6298 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6299 fonts are scaled according to the specified size. */
6302 field
= xlfd_scalable_fields
;
6310 if ('1' <= *ptr
&& *ptr
<= '9')
6312 *val
= *ptr
++ - '0';
6313 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6314 *val
= *val
* 10 + *ptr
++ - '0';
6321 ptr
= strchr (ptr
, '-');
6324 while (ptr
&& i
< 14);
6326 if (i
== 14 && ptr
== NULL
)
6328 if (scl_val
[XLFD_SCL_POINT_SIZE
] > 0)
6330 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_POINT_SIZE
] / 10;
6331 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_POINT_SIZE
];
6333 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0)
6335 scl_val
[XLFD_SCL_POINT_SIZE
] =
6336 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10;
6338 else if (scl_val
[XLFD_SCL_AVGWIDTH
] > 0)
6340 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
] / 10;
6341 scl_val
[XLFD_SCL_POINT_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
];
6345 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6350 longest_start
= cur_start
= ptr
;
6354 /* Turn pattern into a regexp and do a regexp match. Also find the
6355 longest substring containing no special characters. */
6356 for (; *pattern
; pattern
++)
6358 if (*pattern
== '?' || *pattern
== '*')
6360 if (ptr
- cur_start
> longest_len
)
6362 longest_start
= cur_start
;
6363 longest_len
= ptr
- cur_start
;
6367 if (*pattern
== '?')
6369 else /* if (*pattern == '*') */
6377 *ptr
++ = tolower (*pattern
);
6380 if (ptr
- cur_start
> longest_len
)
6382 longest_start
= cur_start
;
6383 longest_len
= ptr
- cur_start
;
6389 nonspecial
= xmalloc (longest_len
+ 1);
6390 strncpy (nonspecial
, longest_start
, longest_len
);
6391 nonspecial
[longest_len
] = '\0';
6393 pattern_regex
= build_string (regex
);
6395 for (i
= 0; i
< font_name_count
; i
++)
6397 fontname
= mac_c_string_match (pattern_regex
, font_name_table
[i
],
6399 if (!NILP (fontname
))
6401 font_list
= Fcons (fontname
, font_list
);
6402 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6405 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6406 && (ptr
= strstr (font_name_table
[i
], "-0-0-75-75-m-0-")))
6408 int former_len
= ptr
- font_name_table
[i
];
6410 memcpy (scaled
, font_name_table
[i
], former_len
);
6411 sprintf (scaled
+ former_len
,
6412 "-%d-%d-75-75-m-%d-%s",
6413 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6414 scl_val
[XLFD_SCL_POINT_SIZE
],
6415 scl_val
[XLFD_SCL_AVGWIDTH
],
6416 ptr
+ sizeof ("-0-0-75-75-m-0-") - 1);
6417 fontname
= mac_c_string_match (pattern_regex
, scaled
,
6419 if (!NILP (fontname
))
6421 font_list
= Fcons (fontname
, font_list
);
6422 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6433 /* Return a list of at most MAXNAMES font specs matching the one in
6434 PATTERN. Cache matching fonts for patterns in
6435 dpyinfo->name_list_element to avoid looking them up again by
6436 calling mac_font_pattern_match (slow). Return as many matching
6437 fonts as possible if MAXNAMES = -1. */
6440 x_list_fonts (struct frame
*f
,
6441 Lisp_Object pattern
,
6445 Lisp_Object newlist
= Qnil
, tem
, key
;
6446 struct mac_display_info
*dpyinfo
= f
? FRAME_MAC_DISPLAY_INFO (f
) : NULL
;
6450 tem
= XCDR (dpyinfo
->name_list_element
);
6451 key
= Fcons (pattern
, make_number (maxnames
));
6453 newlist
= Fassoc (key
, tem
);
6454 if (!NILP (newlist
))
6456 newlist
= Fcdr_safe (newlist
);
6462 newlist
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6465 /* MAC_TODO: add code for matching outline fonts here */
6469 XSETCDR (dpyinfo
->name_list_element
,
6470 Fcons (Fcons (key
, newlist
),
6471 XCDR (dpyinfo
->name_list_element
)));
6481 /* Check that FONT is valid on frame F. It is if it can be found in F's
6485 x_check_font (f
, font
)
6490 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6492 xassert (font
!= NULL
);
6494 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6495 if (dpyinfo
->font_table
[i
].name
6496 && font
== dpyinfo
->font_table
[i
].font
)
6499 xassert (i
< dpyinfo
->n_fonts
);
6502 #endif /* GLYPH_DEBUG != 0 */
6504 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6505 Note: There are (broken) X fonts out there with invalid XFontStruct
6506 min_bounds contents. For example, handa@etl.go.jp reports that
6507 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6508 have font->min_bounds.width == 0. */
6511 x_font_min_bounds (font
, w
, h
)
6512 MacFontStruct
*font
;
6515 *h
= FONT_HEIGHT (font
);
6516 *w
= font
->min_bounds
.width
;
6520 /* Compute the smallest character width and smallest font height over
6521 all fonts available on frame F. Set the members smallest_char_width
6522 and smallest_font_height in F's x_display_info structure to
6523 the values computed. Value is non-zero if smallest_font_height or
6524 smallest_char_width become smaller than they were before. */
6527 x_compute_min_glyph_bounds (f
)
6531 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6532 MacFontStruct
*font
;
6533 int old_width
= dpyinfo
->smallest_char_width
;
6534 int old_height
= dpyinfo
->smallest_font_height
;
6536 dpyinfo
->smallest_font_height
= 100000;
6537 dpyinfo
->smallest_char_width
= 100000;
6539 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6540 if (dpyinfo
->font_table
[i
].name
)
6542 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6545 font
= (MacFontStruct
*) fontp
->font
;
6546 xassert (font
!= (MacFontStruct
*) ~0);
6547 x_font_min_bounds (font
, &w
, &h
);
6549 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6550 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6553 xassert (dpyinfo
->smallest_char_width
> 0
6554 && dpyinfo
->smallest_font_height
> 0);
6556 return (dpyinfo
->n_fonts
== 1
6557 || dpyinfo
->smallest_char_width
< old_width
6558 || dpyinfo
->smallest_font_height
< old_height
);
6562 /* Determine whether given string is a fully-specified XLFD: all 14
6563 fields are present, none is '*'. */
6566 is_fully_specified_xlfd (char *p
)
6574 for (i
= 0; i
< 13; i
++)
6576 q
= strchr (p
+ 1, '-');
6579 if (q
- p
== 2 && *(p
+ 1) == '*')
6584 if (strchr (p
+ 1, '-') != NULL
)
6587 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6594 const int kDefaultFontSize
= 9;
6597 /* XLoadQueryFont creates and returns an internal representation for a
6598 font in a MacFontStruct struct. There is really no concept
6599 corresponding to "loading" a font on the Mac. But we check its
6600 existence and find the font number and all other information for it
6601 and store them in the returned MacFontStruct. */
6603 static MacFontStruct
*
6604 XLoadQueryFont (Display
*dpy
, char *fontname
)
6606 int i
, size
, is_two_byte_font
, char_width
;
6609 SInt16 old_fontnum
, old_fontsize
;
6613 Style fontface
= normal
;
6614 MacFontStruct
*font
;
6615 FontInfo the_fontinfo
;
6616 char s_weight
[7], c_slant
;
6618 if (is_fully_specified_xlfd (fontname
))
6622 Lisp_Object matched_fonts
;
6624 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6625 if (NILP (matched_fonts
))
6627 name
= SDATA (XCAR (matched_fonts
));
6630 GetPort (&port
); /* save the current font number used */
6631 #if TARGET_API_MAC_CARBON
6632 old_fontnum
= GetPortTextFont (port
);
6633 old_fontsize
= GetPortTextSize (port
);
6634 old_fontface
= GetPortTextFace (port
);
6636 old_fontnum
= port
->txFont
;
6637 old_fontsize
= port
->txSize
;
6638 old_fontface
= port
->txFace
;
6641 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size
) != 1)
6642 size
= kDefaultFontSize
;
6644 if (sscanf (name
, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight
) == 1)
6645 if (strcmp (s_weight
, "bold") == 0)
6648 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant
) == 1)
6652 x_font_name_to_mac_font_name (name
, mfontname
);
6654 GetFNum (mfontname
, &fontnum
);
6658 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
6660 font
->fontname
= (char *) xmalloc (strlen (name
) + 1);
6661 bcopy (name
, font
->fontname
, strlen (name
) + 1);
6663 font
->mac_fontnum
= fontnum
;
6664 font
->mac_fontsize
= size
;
6665 font
->mac_fontface
= fontface
;
6666 font
->mac_scriptcode
= FontToScript (fontnum
);
6668 /* Apple Japanese (SJIS) font is listed as both
6669 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6670 (Roman script) in init_font_name_table (). The latter should be
6671 treated as a one-byte font. */
6676 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6678 && 0 == strcmp (cs
, "jisx0201.1976-0"))
6679 font
->mac_scriptcode
= smRoman
;
6682 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
6683 font
->mac_scriptcode
== smTradChinese
||
6684 font
->mac_scriptcode
== smSimpChinese
||
6685 font
->mac_scriptcode
== smKorean
;
6689 TextFace (fontface
);
6691 GetFontInfo (&the_fontinfo
);
6693 font
->ascent
= the_fontinfo
.ascent
;
6694 font
->descent
= the_fontinfo
.descent
;
6696 font
->min_byte1
= 0;
6697 if (is_two_byte_font
)
6698 font
->max_byte1
= 1;
6700 font
->max_byte1
= 0;
6701 font
->min_char_or_byte2
= 0x20;
6702 font
->max_char_or_byte2
= 0xff;
6704 if (is_two_byte_font
)
6706 /* Use the width of an "ideographic space" of that font because
6707 the_fontinfo.widMax returns the wrong width for some fonts. */
6708 switch (font
->mac_scriptcode
)
6711 char_width
= StringWidth("\p\x81\x40");
6714 char_width
= StringWidth("\p\xa1\x40");
6717 char_width
= StringWidth("\p\xa1\xa1");
6720 char_width
= StringWidth("\p\xa1\xa1");
6725 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6726 returns 15 for 12-point Monaco! */
6727 char_width
= CharWidth ('m');
6729 if (is_two_byte_font
)
6731 font
->per_char
= NULL
;
6733 if (fontface
& italic
)
6734 font
->max_bounds
.rbearing
= char_width
+ 1;
6736 font
->max_bounds
.rbearing
= char_width
;
6737 font
->max_bounds
.lbearing
= 0;
6738 font
->max_bounds
.width
= char_width
;
6739 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
6740 font
->max_bounds
.descent
= the_fontinfo
.descent
;
6742 font
->min_bounds
= font
->max_bounds
;
6746 font
->per_char
= (XCharStruct
*)
6747 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
6749 int c
, min_width
, max_width
;
6750 Rect char_bounds
, min_bounds
, max_bounds
;
6753 min_width
= max_width
= char_width
;
6754 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
6755 SetRect (&max_bounds
, 0, 0, 0, 0);
6756 for (c
= 0x20; c
<= 0xff; c
++)
6759 char_width
= CharWidth (ch
);
6760 QDTextBounds (1, &ch
, &char_bounds
);
6761 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
6762 char_width
, char_bounds
);
6763 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6764 character width of 0x7f. */
6767 min_width
= min (min_width
, char_width
);
6768 max_width
= max (max_width
, char_width
);
6770 if (!EmptyRect (&char_bounds
))
6772 SetRect (&min_bounds
,
6773 max (min_bounds
.left
, char_bounds
.left
),
6774 max (min_bounds
.top
, char_bounds
.top
),
6775 min (min_bounds
.right
, char_bounds
.right
),
6776 min (min_bounds
.bottom
, char_bounds
.bottom
));
6777 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
6780 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
6781 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
6782 if (min_width
== max_width
6783 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
6785 /* Fixed width and no overhangs. */
6786 xfree (font
->per_char
);
6787 font
->per_char
= NULL
;
6792 TextFont (old_fontnum
); /* restore previous font number, size and face */
6793 TextSize (old_fontsize
);
6794 TextFace (old_fontface
);
6801 mac_unload_font (dpyinfo
, font
)
6802 struct mac_display_info
*dpyinfo
;
6805 xfree (font
->fontname
);
6807 xfree (font
->per_char
);
6812 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6813 pointer to the structure font_info while allocating it dynamically.
6814 If SIZE is 0, load any size of font.
6815 If loading is failed, return NULL. */
6818 x_load_font (f
, fontname
, size
)
6820 register char *fontname
;
6823 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6824 Lisp_Object font_names
;
6826 /* Get a list of all the fonts that match this name. Once we
6827 have a list of matching fonts, we compare them against the fonts
6828 we already have by comparing names. */
6829 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
6831 if (!NILP (font_names
))
6836 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6837 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
6838 if (dpyinfo
->font_table
[i
].name
6839 && (!strcmp (dpyinfo
->font_table
[i
].name
,
6840 SDATA (XCAR (tail
)))
6841 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6842 SDATA (XCAR (tail
)))))
6843 return (dpyinfo
->font_table
+ i
);
6846 /* Load the font and add it to the table. */
6849 struct MacFontStruct
*font
;
6850 struct font_info
*fontp
;
6851 unsigned long value
;
6854 /* If we have found fonts by x_list_font, load one of them. If
6855 not, we still try to load a font by the name given as FONTNAME
6856 because XListFonts (called in x_list_font) of some X server has
6857 a bug of not finding a font even if the font surely exists and
6858 is loadable by XLoadQueryFont. */
6859 if (size
> 0 && !NILP (font_names
))
6860 fontname
= (char *) SDATA (XCAR (font_names
));
6863 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
6868 /* Find a free slot in the font table. */
6869 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6870 if (dpyinfo
->font_table
[i
].name
== NULL
)
6873 /* If no free slot found, maybe enlarge the font table. */
6874 if (i
== dpyinfo
->n_fonts
6875 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
6878 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
6879 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
6881 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
6884 fontp
= dpyinfo
->font_table
+ i
;
6885 if (i
== dpyinfo
->n_fonts
)
6888 /* Now fill in the slots of *FONTP. */
6890 bzero (fontp
, sizeof (*fontp
));
6892 fontp
->font_idx
= i
;
6893 fontp
->name
= (char *) xmalloc (strlen (font
->fontname
) + 1);
6894 bcopy (font
->fontname
, fontp
->name
, strlen (font
->fontname
) + 1);
6896 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
6898 /* Fixed width font. */
6899 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
6906 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
6907 pcm
= mac_per_char_metric (font
, &char2b
, 0);
6909 fontp
->space_width
= pcm
->width
;
6911 fontp
->space_width
= FONT_WIDTH (font
);
6915 int width
= pcm
->width
;
6916 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
6917 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
6918 width
+= pcm
->width
;
6919 fontp
->average_width
= width
/ 95;
6922 fontp
->average_width
= FONT_WIDTH (font
);
6925 fontp
->full_name
= fontp
->name
;
6927 fontp
->size
= font
->max_bounds
.width
;
6928 fontp
->height
= FONT_HEIGHT (font
);
6930 /* For some font, ascent and descent in max_bounds field is
6931 larger than the above value. */
6932 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6933 if (max_height
> fontp
->height
)
6934 fontp
->height
= max_height
;
6937 /* The slot `encoding' specifies how to map a character
6938 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6939 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6940 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6941 2:0xA020..0xFF7F). For the moment, we don't know which charset
6942 uses this font. So, we set information in fontp->encoding[1]
6943 which is never used by any charset. If mapping can't be
6944 decided, set FONT_ENCODING_NOT_DECIDED. */
6945 if (font
->mac_scriptcode
== smJapanese
)
6946 fontp
->encoding
[1] = 4;
6950 = (font
->max_byte1
== 0
6952 ? (font
->min_char_or_byte2
< 0x80
6953 ? (font
->max_char_or_byte2
< 0x80
6954 ? 0 /* 0x20..0x7F */
6955 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6956 : 1) /* 0xA0..0xFF */
6958 : (font
->min_byte1
< 0x80
6959 ? (font
->max_byte1
< 0x80
6960 ? (font
->min_char_or_byte2
< 0x80
6961 ? (font
->max_char_or_byte2
< 0x80
6962 ? 0 /* 0x2020..0x7F7F */
6963 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6964 : 3) /* 0x20A0..0x7FFF */
6965 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6966 : (font
->min_char_or_byte2
< 0x80
6967 ? (font
->max_char_or_byte2
< 0x80
6968 ? 2 /* 0xA020..0xFF7F */
6969 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6970 : 1))); /* 0xA0A0..0xFFFF */
6973 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6974 fontp
->baseline_offset
6975 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6976 ? (long) value
: 0);
6977 fontp
->relative_compose
6978 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6979 ? (long) value
: 0);
6980 fontp
->default_ascent
6981 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6982 ? (long) value
: 0);
6984 fontp
->baseline_offset
= 0;
6985 fontp
->relative_compose
= 0;
6986 fontp
->default_ascent
= 0;
6989 /* Set global flag fonts_changed_p to non-zero if the font loaded
6990 has a character with a smaller width than any other character
6991 before, or if the font loaded has a smalle>r height than any
6992 other font loaded before. If this happens, it will make a
6993 glyph matrix reallocation necessary. */
6994 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
7001 /* Return a pointer to struct font_info of a font named FONTNAME for
7002 frame F. If no such font is loaded, return NULL. */
7005 x_query_font (f
, fontname
)
7007 register char *fontname
;
7009 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7012 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7013 if (dpyinfo
->font_table
[i
].name
7014 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7015 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7016 return (dpyinfo
->font_table
+ i
);
7021 /* Find a CCL program for a font specified by FONTP, and set the member
7022 `encoder' of the structure. */
7025 x_find_ccl_program (fontp
)
7026 struct font_info
*fontp
;
7028 Lisp_Object list
, elt
;
7030 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7034 && STRINGP (XCAR (elt
))
7035 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7041 struct ccl_program
*ccl
7042 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7044 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7047 fontp
->font_encoder
= ccl
;
7053 /* The Mac Event loop code */
7055 #if !TARGET_API_MAC_CARBON
7057 #include <Quickdraw.h>
7058 #include <Balloons.h>
7059 #include <Devices.h>
7061 #include <Gestalt.h>
7063 #include <Processes.h>
7065 #include <ToolUtils.h>
7066 #include <TextUtils.h>
7067 #include <Dialogs.h>
7070 #include <TextEncodingConverter.h>
7071 #include <Resources.h>
7076 #endif /* ! TARGET_API_MAC_CARBON */
7081 #define WINDOW_RESOURCE 128
7082 #define TERM_WINDOW_RESOURCE 129
7084 #define DEFAULT_NUM_COLS 80
7086 #define MIN_DOC_SIZE 64
7087 #define MAX_DOC_SIZE 32767
7089 /* sleep time for WaitNextEvent */
7090 #define WNE_SLEEP_AT_SUSPEND 10
7091 #define WNE_SLEEP_AT_RESUME 1
7093 /* true when cannot handle any Mac OS events */
7094 static int handling_window_update
= 0;
7097 /* the flag appl_is_suspended is used both for determining the sleep
7098 time to be passed to WaitNextEvent and whether the cursor should be
7099 drawn when updating the display. The cursor is turned off when
7100 Emacs is suspended. Redrawing it is unnecessary and what needs to
7101 be done depends on whether the cursor lies inside or outside the
7102 redraw region. So we might as well skip drawing it when Emacs is
7104 static Boolean app_is_suspended
= false;
7105 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7108 #define EXTRA_STACK_ALLOC (256 * 1024)
7110 #define ARGV_STRING_LIST_ID 129
7111 #define ABOUT_ALERT_ID 128
7112 #define RAM_TOO_LARGE_ALERT_ID 129
7114 Boolean terminate_flag
= false;
7116 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7117 Lisp_Object Qreverse
;
7119 /* True if using command key as meta key. */
7120 Lisp_Object Vmac_command_key_is_meta
;
7122 /* Modifier associated with the option key, or nil for normal behavior. */
7123 Lisp_Object Vmac_option_modifier
;
7125 /* True if the ctrl and meta keys should be reversed. */
7126 Lisp_Object Vmac_reverse_ctrl_meta
;
7128 /* True if the option and command modifiers should be used to emulate
7129 a three button mouse */
7130 Lisp_Object Vmac_emulate_three_button_mouse
;
7132 #if USE_CARBON_EVENTS
7133 /* True if the mouse wheel button (i.e. button 4) should map to
7134 mouse-2, instead of mouse-3. */
7135 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7137 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7138 for processing before Emacs sees it. */
7139 Lisp_Object Vmac_pass_command_to_system
;
7141 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7142 for processing before Emacs sees it. */
7143 Lisp_Object Vmac_pass_control_to_system
;
7146 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7147 to this text encoding */
7148 int mac_keyboard_text_encoding
;
7149 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
7151 /* Set in term/mac-win.el to indicate that event loop can now generate
7152 drag and drop events. */
7153 Lisp_Object Qmac_ready_for_drag_n_drop
;
7155 Lisp_Object drag_and_drop_file_list
;
7157 Point saved_menu_event_location
;
7160 static void init_required_apple_events (void);
7162 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7164 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7165 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7166 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7168 #if TARGET_API_MAC_CARBON
7170 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7171 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7172 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7173 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7176 #if USE_CARBON_EVENTS
7178 /* Preliminary Support for the OSX Services Menu */
7179 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
7180 static void init_service_handler ();
7182 /* Window Event Handler */
7183 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7186 OSErr
install_window_handler (WindowPtr
);
7188 extern void init_emacs_passwd_dir ();
7189 extern int emacs_main (int, char **, char **);
7190 extern void check_alarm ();
7192 extern void initialize_applescript();
7193 extern void terminate_applescript();
7196 #if USE_CARBON_EVENTS
7197 mac_to_emacs_modifiers (UInt32 mods
)
7199 mac_to_emacs_modifiers (EventModifiers mods
)
7202 unsigned int result
= 0;
7203 if (mods
& macShiftKey
)
7204 result
|= shift_modifier
;
7205 if (mods
& macCtrlKey
)
7206 result
|= ctrl_modifier
;
7207 if (mods
& macMetaKey
)
7208 result
|= meta_modifier
;
7209 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7210 result
|= alt_modifier
;
7211 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7212 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7214 result
|= XUINT(val
);
7221 mac_get_emulated_btn ( UInt32 modifiers
)
7224 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7225 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7226 if (modifiers
& cmdKey
)
7227 result
= cmdIs3
? 2 : 1;
7228 else if (modifiers
& optionKey
)
7229 result
= cmdIs3
? 1 : 2;
7234 #if USE_CARBON_EVENTS
7235 /* Obtains the event modifiers from the event ref and then calls
7236 mac_to_emacs_modifiers. */
7238 mac_event_to_emacs_modifiers (EventRef eventRef
)
7241 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7242 sizeof (UInt32
), NULL
, &mods
);
7243 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7244 GetEventClass(eventRef
) == kEventClassMouse
)
7246 mods
&= ~(optionKey
| cmdKey
);
7248 return mac_to_emacs_modifiers (mods
);
7251 /* Given an event ref, return the code to use for the mouse button
7252 code in the emacs input_event. */
7254 mac_get_mouse_btn (EventRef ref
)
7256 EventMouseButton result
= kEventMouseButtonPrimary
;
7257 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7258 sizeof (EventMouseButton
), NULL
, &result
);
7261 case kEventMouseButtonPrimary
:
7262 if (NILP (Vmac_emulate_three_button_mouse
))
7266 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7267 sizeof (UInt32
), NULL
, &mods
);
7268 return mac_get_emulated_btn(mods
);
7270 case kEventMouseButtonSecondary
:
7271 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7272 case kEventMouseButtonTertiary
:
7273 case 4: /* 4 is the number for the mouse wheel button */
7274 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7280 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7281 events. However the click of the mouse wheel is not converted to a
7282 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7283 checks to see if it is a mouse up or down carbon event that has not
7284 been converted, and if so, converts it by hand (to be picked up in
7285 the XTread_socket loop). */
7286 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7288 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7289 /* Do special case for mouse wheel button. */
7290 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
7292 UInt32 kind
= GetEventKind (eventRef
);
7293 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
7295 eventRec
->what
= mouseDown
;
7298 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
7300 eventRec
->what
= mouseUp
;
7305 /* Need where and when. */
7307 GetEventParameter (eventRef
, kEventParamMouseLocation
,
7308 typeQDPoint
, NULL
, sizeof (Point
),
7309 NULL
, &eventRec
->where
);
7310 /* Use two step process because new event modifiers are
7311 32-bit and old are 16-bit. Currently, only loss is
7313 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
7314 typeUInt32
, NULL
, sizeof (UInt32
),
7316 eventRec
->modifiers
= mods
;
7318 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7329 Handle menubar_handle
;
7330 MenuHandle menu_handle
;
7332 menubar_handle
= GetNewMBar (128);
7333 if(menubar_handle
== NULL
)
7335 SetMenuBar (menubar_handle
);
7338 menu_handle
= GetMenuHandle (M_APPLE
);
7339 if(menu_handle
!= NULL
)
7340 AppendResMenu (menu_handle
,'DRVR');
7347 do_init_managers (void)
7349 #if !TARGET_API_MAC_CARBON
7350 InitGraf (&qd
.thePort
);
7352 FlushEvents (everyEvent
, 0);
7357 #endif /* !TARGET_API_MAC_CARBON */
7360 #if !TARGET_API_MAC_CARBON
7361 /* set up some extra stack space for use by emacs */
7362 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7364 /* MaxApplZone must be called for AppleScript to execute more
7365 complicated scripts */
7368 #endif /* !TARGET_API_MAC_CARBON */
7372 do_check_ram_size (void)
7374 SInt32 physical_ram_size
, logical_ram_size
;
7376 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7377 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7378 || physical_ram_size
> (1 << VALBITS
)
7379 || logical_ram_size
> (1 << VALBITS
))
7381 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7387 do_window_update (WindowPtr win
)
7389 struct frame
*f
= mac_window_to_frame (win
);
7393 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7395 if (win
!= tip_window
)
7397 if (f
->async_visible
== 0)
7399 f
->async_visible
= 1;
7400 f
->async_iconified
= 0;
7401 SET_FRAME_GARBAGED (f
);
7403 /* An update event is equivalent to MapNotify on X, so report
7404 visibility changes properly. */
7405 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7406 /* Force a redisplay sooner or later to update the
7407 frame titles in case this is the second frame. */
7408 record_asynch_buffer_change ();
7414 handling_window_update
= 1;
7416 #if TARGET_API_MAC_CARBON
7418 RgnHandle region
= NewRgn ();
7420 GetPortVisibleRegion (GetWindowPort (win
), region
);
7421 GetRegionBounds (region
, &r
);
7422 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7423 UpdateControls (win
, region
);
7424 DisposeRgn (region
);
7427 r
= (*win
->visRgn
)->rgnBBox
;
7428 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7429 UpdateControls (win
, win
->visRgn
);
7432 handling_window_update
= 0;
7440 is_emacs_window (WindowPtr win
)
7442 Lisp_Object tail
, frame
;
7447 FOR_EACH_FRAME (tail
, frame
)
7448 if (FRAME_MAC_P (XFRAME (frame
)))
7449 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7458 /* Window-activate events will do the job. */
7463 wp
= front_emacs_window ();
7466 f
= mac_window_to_frame (wp
);
7470 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
7471 activate_scroll_bars (f
);
7475 app_is_suspended
= false;
7476 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7483 /* Window-deactivate events will do the job. */
7488 wp
= front_emacs_window ();
7491 f
= mac_window_to_frame (wp
);
7493 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
7495 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
7496 deactivate_scroll_bars (f
);
7500 app_is_suspended
= true;
7501 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7507 do_mouse_moved (mouse_pos
, f
)
7511 WindowPtr wp
= front_emacs_window ();
7512 struct x_display_info
*dpyinfo
;
7516 *f
= mac_window_to_frame (wp
);
7517 dpyinfo
= FRAME_MAC_DISPLAY_INFO (*f
);
7519 if (dpyinfo
->mouse_face_hidden
)
7521 dpyinfo
->mouse_face_hidden
= 0;
7522 clear_mouse_face (dpyinfo
);
7525 SetPortWindowPort (wp
);
7527 GlobalToLocal (&mouse_pos
);
7529 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
7530 x_scroll_bar_note_movement (tracked_scroll_bar
,
7532 - XINT (tracked_scroll_bar
->top
),
7533 TickCount() * (1000 / 60));
7535 note_mouse_movement (*f
, &mouse_pos
);
7541 do_apple_menu (SInt16 menu_item
)
7543 #if !TARGET_API_MAC_CARBON
7545 SInt16 da_driver_refnum
;
7547 if (menu_item
== I_ABOUT
)
7548 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7551 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7552 da_driver_refnum
= OpenDeskAcc (item_name
);
7554 #endif /* !TARGET_API_MAC_CARBON */
7558 do_menu_choice (SInt32 menu_choice
)
7560 SInt16 menu_id
, menu_item
;
7562 menu_id
= HiWord (menu_choice
);
7563 menu_item
= LoWord (menu_choice
);
7571 do_apple_menu (menu_item
);
7576 struct frame
*f
= mac_window_to_frame (front_emacs_window ());
7577 MenuHandle menu
= GetMenuHandle (menu_id
);
7582 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7583 menubar_selection_callback (f
, refcon
);
7592 /* Handle drags in size box. Based on code contributed by Ben
7593 Mesander and IM - Window Manager A. */
7596 do_grow_window (WindowPtr w
, EventRecord
*e
)
7599 int rows
, columns
, width
, height
;
7600 struct frame
*f
= mac_window_to_frame (w
);
7601 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
7602 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
7603 #if TARGET_API_MAC_CARBON
7609 if (size_hints
->flags
& PMinSize
)
7611 min_width
= size_hints
->min_width
;
7612 min_height
= size_hints
->min_height
;
7614 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7616 #if TARGET_API_MAC_CARBON
7617 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
7619 height
= new_rect
.bottom
- new_rect
.top
;
7620 width
= new_rect
.right
- new_rect
.left
;
7622 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7623 /* see if it really changed size */
7626 height
= HiWord (grow_size
);
7627 width
= LoWord (grow_size
);
7630 if (width
!= FRAME_PIXEL_WIDTH (f
)
7631 || height
!= FRAME_PIXEL_HEIGHT (f
))
7633 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7634 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7636 x_set_window_size (f
, 0, columns
, rows
);
7641 /* Handle clicks in zoom box. Calculation of "standard state" based
7642 on code in IM - Window Manager A and code contributed by Ben
7643 Mesander. The standard state of an Emacs window is 80-characters
7644 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7647 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7650 Rect zoom_rect
, port_rect
;
7652 int w_title_height
, columns
, rows
, width
, height
;
7653 struct frame
*f
= mac_window_to_frame (w
);
7655 #if TARGET_API_MAC_CARBON
7657 Point standard_size
;
7659 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7660 standard_size
.v
= FRAME_MAC_DISPLAY_INFO (f
)->height
;
7662 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7663 zoom_in_or_out
= inZoomIn
;
7666 /* Adjust the standard size according to character boundaries. */
7668 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7669 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7670 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7671 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7672 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
7673 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
7674 && port_rect
.left
== zoom_rect
.left
7675 && port_rect
.top
== zoom_rect
.top
)
7676 zoom_in_or_out
= inZoomIn
;
7678 zoom_in_or_out
= inZoomOut
;
7681 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
7683 #else /* not TARGET_API_MAC_CARBON */
7684 GetPort (&save_port
);
7686 SetPortWindowPort (w
);
7688 /* Clear window to avoid flicker. */
7689 EraseRect (&(w
->portRect
));
7690 if (zoom_in_or_out
== inZoomOut
)
7692 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
7693 LocalToGlobal (&top_left
);
7695 /* calculate height of window's title bar */
7696 w_title_height
= top_left
.v
- 1
7697 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
7699 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7700 zoom_rect
= qd
.screenBits
.bounds
;
7701 zoom_rect
.top
+= w_title_height
;
7702 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
7704 zoom_rect
.right
= zoom_rect
.left
7705 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7707 /* Adjust the standard size according to character boundaries. */
7708 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7710 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7712 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
7716 ZoomWindow (w
, zoom_in_or_out
, w
== front_emacs_window ());
7718 SetPort (save_port
);
7719 #endif /* not TARGET_API_MAC_CARBON */
7721 /* retrieve window size and update application values */
7722 #if TARGET_API_MAC_CARBON
7723 GetWindowPortBounds (w
, &port_rect
);
7725 port_rect
= w
->portRect
;
7727 height
= port_rect
.bottom
- port_rect
.top
;
7728 width
= port_rect
.right
- port_rect
.left
;
7730 if (width
!= FRAME_PIXEL_WIDTH (f
)
7731 || height
!= FRAME_PIXEL_HEIGHT (f
))
7733 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7734 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7736 change_frame_size (f
, rows
, columns
, 0, 1, 0);
7737 SET_FRAME_GARBAGED (f
);
7738 cancel_mouse_face (f
);
7740 FRAME_PIXEL_WIDTH (f
) = width
;
7741 FRAME_PIXEL_HEIGHT (f
) = height
;
7743 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
7746 /* Intialize AppleEvent dispatcher table for the required events. */
7748 init_required_apple_events ()
7753 /* Make sure we have apple events before starting. */
7754 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
7758 if (!(result
& (1 << gestaltAppleEventsPresent
)))
7761 #if TARGET_API_MAC_CARBON
7762 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7763 NewAEEventHandlerUPP
7764 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7767 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7768 NewAEEventHandlerProc
7769 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7775 #if TARGET_API_MAC_CARBON
7776 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7777 NewAEEventHandlerUPP
7778 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7781 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7782 NewAEEventHandlerProc
7783 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7789 #if TARGET_API_MAC_CARBON
7790 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7791 NewAEEventHandlerUPP
7792 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7795 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7796 NewAEEventHandlerProc
7797 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7803 #if TARGET_API_MAC_CARBON
7804 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7805 NewAEEventHandlerUPP
7806 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7809 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7810 NewAEEventHandlerProc
7811 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7818 #if USE_CARBON_EVENTS
7821 init_service_handler ()
7823 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
7824 {kEventClassService
, kEventServiceCopy
},
7825 {kEventClassService
, kEventServicePaste
}};
7826 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
7827 3, specs
, NULL
, NULL
);
7831 MAC_TODO: Check to see if this is called by AEProcessDesc...
7834 mac_handle_service_event (EventHandlerCallRef callRef
,
7835 EventRef event
, void *data
)
7837 OSStatus err
= noErr
;
7838 switch (GetEventKind (event
))
7840 case kEventServiceGetTypes
:
7842 CFMutableArrayRef copyTypes
, pasteTypes
;
7844 Boolean selection
= true;
7846 GetEventParameter(event, kEventParamServicePasteTypes,
7847 typeCFMutableArrayRef, NULL,
7848 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7850 GetEventParameter(event
, kEventParamServiceCopyTypes
,
7851 typeCFMutableArrayRef
, NULL
,
7852 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
7853 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
7855 CFArrayAppendValue (copyTypes
, type
);
7856 //CFArrayAppendValue (pasteTypes, type);
7860 case kEventServiceCopy
:
7862 ScrapRef currentScrap
, specificScrap
;
7866 GetCurrentScrap (¤tScrap
);
7868 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
7871 void *buffer
= xmalloc (byteCount
);
7874 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
7875 sizeof (ScrapRef
), NULL
, &specificScrap
);
7877 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
7878 &byteCount
, buffer
);
7880 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
7881 kScrapFlavorMaskNone
, byteCount
, buffer
);
7887 case kEventServicePaste
:
7890 // Get the current location
7892 ScrapRef specificScrap;
7893 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7894 sizeof(ScrapRef), NULL, &specificScrap);
7895 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7897 void * buffer = xmalloc(byteCount);
7898 if (buffer != NULL ) {
7899 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7900 &byteCount, buffer);
7902 // Actually place in the buffer
7904 // Get the current "selection" string here
7917 static pascal OSStatus
7918 mac_handle_window_event (next_handler
, event
, data
)
7919 EventHandlerCallRef next_handler
;
7926 XSizeHints
*size_hints
;
7928 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
7929 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
7931 switch (GetEventKind (event
))
7933 case kEventWindowUpdate
:
7934 result
= CallNextEventHandler (next_handler
, event
);
7935 if (result
!= eventNotHandledErr
)
7938 do_window_update (wp
);
7941 case kEventWindowBoundsChanging
:
7942 result
= CallNextEventHandler (next_handler
, event
);
7943 if (result
!= eventNotHandledErr
)
7946 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
7947 NULL
, sizeof (UInt32
), NULL
, &attributes
);
7948 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
7949 if ((attributes
& kWindowBoundsChangeUserResize
)
7950 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
7951 == (PResizeInc
| PBaseSize
| PMinSize
)))
7956 GetEventParameter (event
, kEventParamCurrentBounds
,
7958 NULL
, sizeof (Rect
), NULL
, &bounds
);
7959 width
= bounds
.right
- bounds
.left
;
7960 height
= bounds
.bottom
- bounds
.top
;
7962 if (width
< size_hints
->min_width
)
7963 width
= size_hints
->min_width
;
7965 width
= size_hints
->base_width
7966 + (int) ((width
- size_hints
->base_width
)
7967 / (float) size_hints
->width_inc
+ .5)
7968 * size_hints
->width_inc
;
7970 if (height
< size_hints
->min_height
)
7971 height
= size_hints
->min_height
;
7973 height
= size_hints
->base_height
7974 + (int) ((height
- size_hints
->base_height
)
7975 / (float) size_hints
->height_inc
+ .5)
7976 * size_hints
->height_inc
;
7978 bounds
.right
= bounds
.left
+ width
;
7979 bounds
.bottom
= bounds
.top
+ height
;
7980 SetEventParameter (event
, kEventParamCurrentBounds
,
7981 typeQDRectangle
, sizeof (Rect
), &bounds
);
7987 return eventNotHandledErr
;
7989 #endif /* USE_CARBON_EVENTS */
7993 install_window_handler (window
)
7997 #if USE_CARBON_EVENTS
7998 EventTypeSpec specs
[] = {{kEventClassWindow
, kEventWindowUpdate
},
7999 {kEventClassWindow
, kEventWindowBoundsChanging
}};
8000 static EventHandlerUPP handle_window_event_UPP
= NULL
;
8002 if (handle_window_event_UPP
== NULL
)
8003 handle_window_event_UPP
= NewEventHandlerUPP (mac_handle_window_event
);
8005 err
= InstallWindowEventHandler (window
, handle_window_event_UPP
,
8006 GetEventTypeCount (specs
), specs
,
8009 #if TARGET_API_MAC_CARBON
8010 if (mac_do_track_dragUPP
== NULL
)
8011 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8012 if (mac_do_receive_dragUPP
== NULL
)
8013 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8016 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8018 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8024 remove_window_handler (window
)
8027 #if TARGET_API_MAC_CARBON
8028 if (mac_do_track_dragUPP
)
8029 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8030 if (mac_do_receive_dragUPP
)
8031 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8035 /* Open Application Apple Event */
8037 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8043 /* Defined in mac.c. */
8045 path_from_vol_dir_name (char *, int, short, long, char *);
8048 /* Called when we receive an AppleEvent with an ID of
8049 "kAEOpenDocuments". This routine gets the direct parameter,
8050 extracts the FSSpecs in it, and puts their names on a list. */
8051 #pragma options align=mac68k
8052 typedef struct SelectionRange
{
8053 short unused1
; // 0 (not used)
8054 short lineNum
; // line to select (<0 to specify range)
8055 long startRange
; // start of selection range (if line < 0)
8056 long endRange
; // end of selection range (if line < 0)
8057 long unused2
; // 0 (not used)
8058 long theDate
; // modification date/time
8060 #pragma options align=reset
8063 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8068 DescType actual_type
;
8070 SelectionRange position
;
8072 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8074 goto descriptor_error_exit
;
8076 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8078 drag_and_drop_file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8079 make_number (position
.startRange
+ 1),
8080 make_number (position
.endRange
+ 1)),
8081 drag_and_drop_file_list
);
8083 /* Check to see that we got all of the required parameters from the
8084 event descriptor. For an 'odoc' event this should just be the
8086 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8087 &actual_type
, (Ptr
) &keyword
,
8088 sizeof (keyword
), &actual_size
);
8089 /* No error means that we found some unused parameters.
8090 errAEDescNotFound means that there are no more parameters. If we
8091 get an error code other than that, flag it. */
8092 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8094 err
= errAEEventNotHandled
;
8099 /* Got all the parameters we need. Now, go through the direct
8100 object list and parse it up. */
8102 long num_files_to_open
;
8104 err
= AECountItems (&the_desc
, &num_files_to_open
);
8109 /* AE file list is one based so just use that for indexing here. */
8110 for (i
= 1; i
<= num_files_to_open
; i
++)
8112 char unix_path_name
[MAXPATHLEN
];
8116 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8117 &actual_type
, &fref
, sizeof (FSRef
),
8119 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8122 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8127 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8128 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8129 if (err
!= noErr
) continue;
8131 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
8132 sizeof (unix_path_name
) - 1) == noErr
)
8134 /* x-dnd functions expect undecoded filenames. */
8135 drag_and_drop_file_list
=
8136 Fcons (make_unibyte_string (unix_path_name
,
8137 strlen (unix_path_name
)),
8138 drag_and_drop_file_list
);
8144 /* Nuke the coerced file list in any case */
8145 err2
= AEDisposeDesc(&the_desc
);
8147 descriptor_error_exit
:
8148 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8153 #if TARGET_API_MAC_CARBON
8155 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8156 void *handlerRefCon
, DragReference theDrag
)
8158 static int can_accept
;
8161 ItemReference theItem
;
8162 FlavorFlags theFlags
;
8165 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8166 return dragNotAcceptedErr
;
8170 case kDragTrackingEnterHandler
:
8171 CountDragItems (theDrag
, &items
);
8173 for (index
= 1; index
<= items
; index
++)
8175 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8176 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8177 if (result
== noErr
)
8185 case kDragTrackingEnterWindow
:
8188 RgnHandle hilite_rgn
= NewRgn ();
8190 struct frame
*f
= mac_window_to_frame (window
);
8192 GetWindowPortBounds (window
, &r
);
8193 OffsetRect (&r
, -r
.left
, -r
.top
);
8194 RectRgn (hilite_rgn
, &r
);
8195 ShowDragHilite (theDrag
, hilite_rgn
, true);
8196 DisposeRgn (hilite_rgn
);
8197 SetThemeCursor (kThemeCopyArrowCursor
);
8201 case kDragTrackingInWindow
:
8204 case kDragTrackingLeaveWindow
:
8207 struct frame
*f
= mac_window_to_frame (window
);
8209 HideDragHilite (theDrag
);
8210 SetThemeCursor (kThemeArrowCursor
);
8214 case kDragTrackingLeaveHandler
:
8222 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8223 DragReference theDrag
)
8227 FlavorFlags theFlags
;
8230 ItemReference theItem
;
8232 Size size
= sizeof (HFSFlavor
);
8234 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8235 return dragNotAcceptedErr
;
8237 drag_and_drop_file_list
= Qnil
;
8238 GetDragMouse (theDrag
, &mouse
, 0L);
8239 CountDragItems (theDrag
, &items
);
8240 for (index
= 1; index
<= items
; index
++)
8242 /* Only handle file references. */
8243 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8244 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8245 if (result
== noErr
)
8250 char unix_path_name
[MAXPATHLEN
];
8252 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8254 /* Use Carbon routines, otherwise it converts the file name
8255 to /Macintosh HD/..., which is not correct. */
8256 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8257 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8259 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
8260 sizeof (unix_path_name
) - 1) == noErr
)
8262 /* x-dnd functions expect undecoded filenames. */
8263 drag_and_drop_file_list
=
8264 Fcons (make_unibyte_string (unix_path_name
,
8265 strlen (unix_path_name
)),
8266 drag_and_drop_file_list
);
8269 /* If there are items in the list, construct an event and post it to
8270 the queue like an interrupt using kbd_buffer_store_event. */
8271 if (!NILP (drag_and_drop_file_list
))
8273 struct input_event event
;
8275 struct frame
*f
= mac_window_to_frame (window
);
8278 GlobalToLocal (&mouse
);
8279 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8281 event
.kind
= DRAG_N_DROP_EVENT
;
8283 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8284 event
.timestamp
= TickCount () * (1000 / 60);
8285 XSETINT (event
.x
, mouse
.h
);
8286 XSETINT (event
.y
, mouse
.v
);
8287 XSETFRAME (frame
, f
);
8288 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8290 /* Post to the interrupt queue */
8291 kbd_buffer_store_event (&event
);
8292 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8294 ProcessSerialNumber psn
;
8295 GetCurrentProcess (&psn
);
8296 SetFrontProcess (&psn
);
8302 return dragNotAcceptedErr
;
8307 /* Print Document Apple Event */
8309 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8311 return errAEEventNotHandled
;
8316 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8318 /* FixMe: Do we need an unwind-protect or something here? And what
8319 do we do about unsaved files. Currently just forces quit rather
8320 than doing recursive callback to get user input. */
8322 terminate_flag
= true;
8324 /* Fkill_emacs doesn't return. We have to return. (TI) */
8331 profiler_exit_proc ()
8333 ProfilerDump ("\pEmacs.prof");
8338 /* These few functions implement Emacs as a normal Mac application
8339 (almost): set up the heap and the Toolbox, handle necessary
8340 system events plus a few simple menu events. They also set up
8341 Emacs's access to functions defined in the rest of this file.
8342 Emacs uses function hooks to perform all its terminal I/O. A
8343 complete list of these functions appear in termhooks.h. For what
8344 they do, read the comments there and see also w32term.c and
8345 xterm.c. What's noticeably missing here is the event loop, which
8346 is normally present in most Mac application. After performing the
8347 necessary Mac initializations, main passes off control to
8348 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8349 mac_read_socket (defined further below) to read input. This is
8350 where WaitNextEvent is called to process Mac events. This is also
8351 where check_alarm in sysdep.c is called to simulate alarm signals.
8352 This makes the cursor jump back to its correct position after
8353 briefly jumping to that of the matching parenthesis, print useful
8354 hints and prompts in the minibuffer after the user stops typing for
8362 #if __profile__ /* is the profiler on? */
8363 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
8368 /* set creator and type for files created by MSL */
8373 do_init_managers ();
8378 do_check_ram_size ();
8381 init_emacs_passwd_dir ();
8385 initialize_applescript ();
8387 init_required_apple_events ();
8393 /* set up argv array from STR# resource */
8394 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
8398 /* free up AppleScript resources on exit */
8399 atexit (terminate_applescript
);
8401 #if __profile__ /* is the profiler on? */
8402 atexit (profiler_exit_proc
);
8405 /* 3rd param "envp" never used in emacs_main */
8406 (void) emacs_main (argc
, argv
, 0);
8409 /* Never reached - real exit in Fkill_emacs */
8414 /* Table for translating Mac keycode to X keysym values. Contributed
8416 Mapping for special keys is now identical to that in Apple X11
8417 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8418 on the right of the Cmd key on laptops, and fn + `enter' (->
8420 static unsigned char keycode_to_xkeysym_table
[] = {
8421 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8422 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8423 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8425 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8426 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8427 /*0x38*/ 0, 0, 0, 0,
8428 /*0x3C*/ 0, 0, 0, 0,
8430 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8431 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8432 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8433 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8435 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8436 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8437 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8438 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8440 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8441 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8442 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8443 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8445 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8446 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8447 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8448 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8452 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8454 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8455 return *xKeySym
!= 0;
8458 #if !USE_CARBON_EVENTS
8459 static RgnHandle mouse_region
= NULL
;
8462 mac_wait_next_event (er
, sleep_time
, dequeue
)
8467 static EventRecord er_buf
= {nullEvent
};
8468 UInt32 target_tick
, current_tick
;
8469 EventMask event_mask
;
8471 if (mouse_region
== NULL
)
8472 mouse_region
= NewRgn ();
8474 event_mask
= everyEvent
;
8475 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8476 event_mask
-= highLevelEventMask
;
8478 current_tick
= TickCount ();
8479 target_tick
= current_tick
+ sleep_time
;
8481 if (er_buf
.what
== nullEvent
)
8482 while (!WaitNextEvent (event_mask
, &er_buf
,
8483 target_tick
- current_tick
, mouse_region
))
8485 current_tick
= TickCount ();
8486 if (target_tick
<= current_tick
)
8492 er_buf
.what
= nullEvent
;
8495 #endif /* not USE_CARBON_EVENTS */
8497 /* Emacs calls this whenever it wants to read an input event from the
8500 XTread_socket (sd
, expected
, hold_quit
)
8502 struct input_event
*hold_quit
;
8504 struct input_event inev
;
8506 #if USE_CARBON_EVENTS
8508 EventTargetRef toolbox_dispatcher
;
8511 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8513 if (interrupt_input_blocked
)
8515 interrupt_input_pending
= 1;
8519 interrupt_input_pending
= 0;
8522 /* So people can tell when we have read the available input. */
8523 input_signal_count
++;
8525 /* Don't poll for events to process (specifically updateEvt) if
8526 window update currently already in progress. A call to redisplay
8527 (in do_window_update) can be preempted by another call to
8528 redisplay, causing blank regions to be left on the screen and the
8529 cursor to be left at strange places. */
8530 if (handling_window_update
)
8537 Fkill_emacs (make_number (1));
8539 #if USE_CARBON_EVENTS
8540 toolbox_dispatcher
= GetEventDispatcherTarget ();
8542 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8543 kEventRemoveFromQueue
, &eventRef
))
8544 #else /* !USE_CARBON_EVENTS */
8545 while (mac_wait_next_event (&er
, 0, true))
8546 #endif /* !USE_CARBON_EVENTS */
8551 /* It is necessary to set this (additional) argument slot of an
8552 event to nil because keyboard.c protects incompletely
8553 processed event from being garbage collected by placing them
8554 in the kbd_buffer_gcpro vector. */
8556 inev
.kind
= NO_EVENT
;
8559 #if USE_CARBON_EVENTS
8560 /* Handle new events */
8561 if (!mac_convert_event_ref (eventRef
, &er
))
8562 switch (GetEventClass (eventRef
))
8564 case kEventClassWindow
:
8565 if (GetEventKind (eventRef
) == kEventWindowBoundsChanged
)
8567 WindowPtr window_ptr
;
8568 GetEventParameter(eventRef
, kEventParamDirectObject
,
8569 typeWindowRef
, NULL
, sizeof(WindowPtr
),
8571 f
= mac_window_to_frame (window_ptr
);
8572 if (f
&& !f
->async_iconified
)
8573 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8574 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8577 case kEventClassMouse
:
8578 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
8582 WindowPtr window_ptr
= front_emacs_window ();
8584 if (!IsValidWindowPtr (window_ptr
))
8590 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
8591 typeSInt32
, NULL
, sizeof (SInt32
),
8593 GetEventParameter(eventRef
, kEventParamMouseLocation
,
8594 typeQDPoint
, NULL
, sizeof (Point
),
8596 inev
.kind
= WHEEL_EVENT
;
8598 inev
.modifiers
= (mac_event_to_emacs_modifiers (eventRef
)
8599 | ((delta
< 0) ? down_modifier
8601 SetPortWindowPort (window_ptr
);
8602 GlobalToLocal (&point
);
8603 XSETINT (inev
.x
, point
.h
);
8604 XSETINT (inev
.y
, point
.v
);
8605 XSETFRAME (inev
.frame_or_window
,
8606 mac_window_to_frame (window_ptr
));
8607 inev
.timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
8610 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8615 /* Send the event to the appropriate receiver. */
8616 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8619 #endif /* USE_CARBON_EVENTS */
8625 WindowPtr window_ptr
;
8629 #if USE_CARBON_EVENTS
8630 /* This is needed to send mouse events like aqua window
8631 buttons to the correct handler. */
8632 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8633 != eventNotHandledErr
)
8637 if (dpyinfo
->grabbed
&& last_mouse_frame
8638 && FRAME_LIVE_P (last_mouse_frame
))
8640 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
8641 part_code
= inContent
;
8645 part_code
= FindWindow (er
.where
, &window_ptr
);
8646 if (tip_window
&& window_ptr
== tip_window
)
8648 HideWindow (tip_window
);
8649 part_code
= FindWindow (er
.where
, &window_ptr
);
8653 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
8659 f
= mac_window_to_frame (front_emacs_window ());
8660 saved_menu_event_location
= er
.where
;
8661 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
8662 XSETFRAME (inev
.frame_or_window
, f
);
8666 if (window_ptr
!= front_emacs_window ())
8667 SelectWindow (window_ptr
);
8670 SInt16 control_part_code
;
8672 Point mouse_loc
= er
.where
;
8674 f
= mac_window_to_frame (window_ptr
);
8675 /* convert to local coordinates of new window */
8676 SetPortWindowPort (window_ptr
);
8678 GlobalToLocal (&mouse_loc
);
8679 #if TARGET_API_MAC_CARBON
8680 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
8681 &control_part_code
);
8683 control_part_code
= FindControl (mouse_loc
, window_ptr
,
8687 #if USE_CARBON_EVENTS
8688 inev
.code
= mac_get_mouse_btn (eventRef
);
8689 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
8691 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
8692 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
8694 XSETINT (inev
.x
, mouse_loc
.h
);
8695 XSETINT (inev
.y
, mouse_loc
.v
);
8696 inev
.timestamp
= er
.when
* (1000 / 60);
8697 /* ticks to milliseconds */
8699 if (dpyinfo
->grabbed
&& tracked_scroll_bar
8700 /* control_part_code becomes kControlNoPart if
8701 a progress indicator is clicked. */
8702 || ch
!= 0 && control_part_code
!= kControlNoPart
)
8704 struct scroll_bar
*bar
;
8706 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
8708 bar
= tracked_scroll_bar
;
8709 control_part_code
= kControlIndicatorPart
;
8712 bar
= (struct scroll_bar
*) GetControlReference (ch
);
8713 x_scroll_bar_handle_click (bar
, control_part_code
,
8715 if (er
.what
== mouseDown
8716 && control_part_code
== kControlIndicatorPart
)
8717 tracked_scroll_bar
= bar
;
8719 tracked_scroll_bar
= NULL
;
8724 int x
= mouse_loc
.h
;
8725 int y
= mouse_loc
.v
;
8727 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
8728 if (EQ (window
, f
->tool_bar_window
))
8730 if (er
.what
== mouseDown
)
8731 handle_tool_bar_click (f
, x
, y
, 1, 0);
8733 handle_tool_bar_click (f
, x
, y
, 0,
8739 XSETFRAME (inev
.frame_or_window
, f
);
8740 inev
.kind
= MOUSE_CLICK_EVENT
;
8744 if (er
.what
== mouseDown
)
8746 dpyinfo
->grabbed
|= (1 << inev
.code
);
8747 last_mouse_frame
= f
;
8748 /* Ignore any mouse motion that happened
8749 before this event; any subsequent
8750 mouse-movement Emacs events should reflect
8751 only motion after the ButtonPress. */
8756 last_tool_bar_item
= -1;
8760 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
8761 /* If a button is released though it was not
8762 previously pressed, that would be because
8763 of multi-button emulation. */
8764 dpyinfo
->grabbed
= 0;
8766 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
8772 inev
.modifiers
|= down_modifier
;
8775 inev
.modifiers
|= up_modifier
;
8782 #if TARGET_API_MAC_CARBON
8783 DragWindow (window_ptr
, er
.where
, NULL
);
8784 #else /* not TARGET_API_MAC_CARBON */
8785 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
8786 #endif /* not TARGET_API_MAC_CARBON */
8787 /* Update the frame parameters. */
8789 struct frame
*f
= mac_window_to_frame (window_ptr
);
8791 if (f
&& !f
->async_iconified
)
8792 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8797 if (TrackGoAway (window_ptr
, er
.where
))
8799 inev
.kind
= DELETE_WINDOW_EVENT
;
8800 XSETFRAME (inev
.frame_or_window
,
8801 mac_window_to_frame (window_ptr
));
8805 /* window resize handling added --ben */
8807 do_grow_window (window_ptr
, &er
);
8810 /* window zoom handling added --ben */
8813 if (TrackBox (window_ptr
, er
.where
, part_code
))
8814 do_zoom_window (window_ptr
, part_code
);
8824 #if USE_CARBON_EVENTS
8825 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8826 != eventNotHandledErr
)
8829 do_window_update ((WindowPtr
) er
.message
);
8834 #if USE_CARBON_EVENTS
8835 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8836 != eventNotHandledErr
)
8839 switch ((er
.message
>> 24) & 0x000000FF)
8841 case suspendResumeMessage
:
8842 if ((er
.message
& resumeFlag
) == 1)
8848 case mouseMovedMessage
:
8849 #if !USE_CARBON_EVENTS
8850 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
8851 er
.where
.h
+ 1, er
.where
.v
+ 1);
8853 previous_help_echo_string
= help_echo_string
;
8854 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
8857 do_mouse_moved (er
.where
, &f
);
8859 /* If the contents of the global variable
8860 help_echo_string has changed, generate a
8862 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
8870 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
8871 ControlRef root_control
;
8873 #if USE_CARBON_EVENTS
8874 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8875 != eventNotHandledErr
)
8878 if (window_ptr
== tip_window
)
8880 HideWindow (tip_window
);
8884 if (!is_emacs_window (window_ptr
))
8887 f
= mac_window_to_frame (window_ptr
);
8888 GetRootControl (window_ptr
, &root_control
);
8890 if ((er
.modifiers
& activeFlag
) != 0)
8892 /* A window has been activated */
8893 Point mouse_loc
= er
.where
;
8895 x_new_focus_frame (dpyinfo
, f
);
8896 ActivateControl (root_control
);
8898 SetPortWindowPort (window_ptr
);
8899 GlobalToLocal (&mouse_loc
);
8900 /* Window-activated event counts as mouse movement,
8901 so update things that depend on mouse position. */
8902 note_mouse_movement (mac_window_to_frame (window_ptr
),
8907 /* A window has been deactivated */
8908 dpyinfo
->grabbed
= 0;
8910 if (f
== dpyinfo
->x_focus_frame
)
8912 x_new_focus_frame (dpyinfo
, 0);
8913 DeactivateControl (root_control
);
8917 if (f
== dpyinfo
->mouse_face_mouse_frame
)
8919 /* If we move outside the frame, then we're
8920 certainly no longer on any text in the
8922 clear_mouse_face (dpyinfo
);
8923 dpyinfo
->mouse_face_mouse_frame
= 0;
8926 /* Generate a nil HELP_EVENT to cancel a help-echo.
8927 Do it only if there's something to cancel.
8928 Otherwise, the startup message is cleared when the
8929 mouse leaves the frame. */
8930 if (any_help_event_p
)
8939 int keycode
= (er
.message
& keyCodeMask
) >> 8;
8942 #if USE_CARBON_EVENTS && defined (MAC_OSX)
8943 /* When using Carbon Events, we need to pass raw keyboard
8944 events to the TSM ourselves. If TSM handles it, it
8945 will pass back noErr, otherwise it will pass back
8946 "eventNotHandledErr" and we can process it
8948 if ((!NILP (Vmac_pass_command_to_system
)
8949 || !(er
.modifiers
& cmdKey
))
8950 && (!NILP (Vmac_pass_control_to_system
)
8951 || !(er
.modifiers
& controlKey
)))
8952 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8953 != eventNotHandledErr
)
8957 #if TARGET_API_MAC_CARBON
8958 if (!IsValidWindowPtr (front_emacs_window ()))
8967 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
8969 clear_mouse_face (dpyinfo
);
8970 dpyinfo
->mouse_face_hidden
= 1;
8973 if (keycode_to_xkeysym (keycode
, &xkeysym
))
8975 inev
.code
= 0xff00 | xkeysym
;
8976 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
8980 if (er
.modifiers
& (controlKey
|
8981 (NILP (Vmac_command_key_is_meta
) ? optionKey
8984 /* This code comes from Keyboard Resource,
8985 Appendix C of IM - Text. This is necessary
8986 since shift is ignored in KCHR table
8987 translation when option or command is pressed.
8988 It also does not translate correctly
8989 control-shift chars like C-% so mask off shift
8991 int new_modifiers
= er
.modifiers
& 0xe600;
8992 /* mask off option and command */
8993 int new_keycode
= keycode
| new_modifiers
;
8994 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
8995 unsigned long some_state
= 0;
8996 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
8997 &some_state
) & 0xff;
8998 } else if (!NILP(Vmac_option_modifier
) && (er
.modifiers
& optionKey
))
9000 /* When using the option key as an emacs modifier, convert
9001 the pressed key code back to one without the Mac option
9002 modifier applied. */
9003 int new_modifiers
= er
.modifiers
& ~optionKey
;
9004 int new_keycode
= keycode
| new_modifiers
;
9005 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9006 unsigned long some_state
= 0;
9007 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9008 &some_state
) & 0xff;
9011 inev
.code
= er
.message
& charCodeMask
;
9012 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9016 /* If variable mac-convert-keyboard-input-to-latin-1 is
9017 non-nil, convert non-ASCII characters typed at the Mac
9018 keyboard (presumed to be in the Mac Roman encoding) to
9019 iso-latin-1 encoding before they are passed to Emacs.
9020 This enables the Mac keyboard to be used to enter
9021 non-ASCII iso-latin-1 characters directly. */
9022 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
9023 && inev
.kind
== ASCII_KEYSTROKE_EVENT
&& inev
.code
>= 128)
9025 static TECObjectRef converter
= NULL
;
9026 OSStatus the_err
= noErr
;
9027 OSStatus convert_status
= noErr
;
9029 if (converter
== NULL
)
9031 the_err
= TECCreateConverter (&converter
,
9032 kTextEncodingMacRoman
,
9033 mac_keyboard_text_encoding
);
9034 current_mac_keyboard_text_encoding
9035 = mac_keyboard_text_encoding
;
9037 else if (mac_keyboard_text_encoding
9038 != current_mac_keyboard_text_encoding
)
9040 /* Free the converter for the current encoding
9041 before creating a new one. */
9042 TECDisposeConverter (converter
);
9043 the_err
= TECCreateConverter (&converter
,
9044 kTextEncodingMacRoman
,
9045 mac_keyboard_text_encoding
);
9046 current_mac_keyboard_text_encoding
9047 = mac_keyboard_text_encoding
;
9050 if (the_err
== noErr
)
9052 unsigned char ch
= inev
.code
;
9053 ByteCount actual_input_length
, actual_output_length
;
9054 unsigned char outbuf
[32];
9056 convert_status
= TECConvertText (converter
, &ch
, 1,
9057 &actual_input_length
,
9059 &actual_output_length
);
9060 if (convert_status
== noErr
9061 && actual_input_length
== 1
9062 && actual_output_length
== 1)
9063 inev
.code
= *outbuf
;
9065 /* Reset internal states of the converter object.
9066 If it fails, create another one. */
9067 convert_status
= TECFlushText (converter
, outbuf
,
9069 &actual_output_length
);
9070 if (convert_status
!= noErr
)
9072 TECDisposeConverter (converter
);
9073 TECCreateConverter (&converter
,
9074 kTextEncodingMacRoman
,
9075 mac_keyboard_text_encoding
);
9080 #if USE_CARBON_EVENTS
9081 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9083 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9085 XSETFRAME (inev
.frame_or_window
,
9086 mac_window_to_frame (front_emacs_window ()));
9087 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9090 case kHighLevelEvent
:
9091 drag_and_drop_file_list
= Qnil
;
9093 AEProcessAppleEvent(&er
);
9095 /* Build a DRAG_N_DROP_EVENT type event as is done in
9096 constuct_drag_n_drop in w32term.c. */
9097 if (!NILP (drag_and_drop_file_list
))
9099 struct frame
*f
= NULL
;
9103 wp
= front_emacs_window ();
9107 struct frame
*f
= XFRAME (XCAR (Vframe_list
));
9108 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
9109 wp
= front_emacs_window ();
9113 f
= mac_window_to_frame (wp
);
9115 inev
.kind
= DRAG_N_DROP_EVENT
;
9117 inev
.timestamp
= er
.when
* (1000 / 60);
9118 /* ticks to milliseconds */
9119 #if USE_CARBON_EVENTS
9120 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9122 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9125 XSETINT (inev
.x
, 0);
9126 XSETINT (inev
.y
, 0);
9128 XSETFRAME (frame
, f
);
9129 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9131 /* Regardless of whether Emacs was suspended or in the
9132 foreground, ask it to redraw its entire screen.
9133 Otherwise parts of the screen can be left in an
9134 inconsistent state. */
9136 #if TARGET_API_MAC_CARBON
9140 GetWindowPortBounds (wp
, &r
);
9141 InvalWindowRect (wp
, &r
);
9143 #else /* not TARGET_API_MAC_CARBON */
9144 InvalRect (&(wp
->portRect
));
9145 #endif /* not TARGET_API_MAC_CARBON */
9150 #if USE_CARBON_EVENTS
9151 ReleaseEvent (eventRef
);
9154 if (inev
.kind
!= NO_EVENT
)
9156 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9161 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9166 XSETFRAME (frame
, f
);
9172 any_help_event_p
= 1;
9173 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9174 help_echo_object
, help_echo_pos
);
9178 help_echo_string
= Qnil
;
9179 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9186 /* If the focus was just given to an autoraising frame,
9188 /* ??? This ought to be able to handle more than one such frame. */
9189 if (pending_autoraise_frame
)
9191 x_raise_frame (pending_autoraise_frame
);
9192 pending_autoraise_frame
= 0;
9195 #if !TARGET_API_MAC_CARBON
9196 check_alarm (); /* simulate the handling of a SIGALRM */
9204 /* Need to override CodeWarrior's input function so no conversion is
9205 done on newlines Otherwise compiled functions in .elc files will be
9206 read incorrectly. Defined in ...:MSL C:MSL
9207 Common:Source:buffer_io.c. */
9210 __convert_to_newlines (unsigned char * p
, size_t * n
)
9216 __convert_from_newlines (unsigned char * p
, size_t * n
)
9224 make_mac_terminal_frame (struct frame
*f
)
9229 XSETFRAME (frame
, f
);
9231 f
->output_method
= output_mac
;
9232 f
->output_data
.mac
= (struct mac_output
*)
9233 xmalloc (sizeof (struct mac_output
));
9234 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9236 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9238 FRAME_COLS (f
) = 96;
9239 FRAME_LINES (f
) = 4;
9241 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9242 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9244 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9246 f
->output_data
.mac
->cursor_pixel
= 0;
9247 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9248 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9249 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9251 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9252 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9253 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9254 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9255 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9256 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9258 FRAME_FONTSET (f
) = -1;
9259 f
->output_data
.mac
->explicit_parent
= 0;
9262 f
->border_width
= 0;
9264 f
->internal_border_width
= 0;
9269 f
->new_text_cols
= 0;
9270 f
->new_text_lines
= 0;
9272 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9273 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9274 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9278 if (!(FRAME_MAC_WINDOW (f
) =
9279 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9280 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9282 /* so that update events can find this mac_output struct */
9283 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9289 /* Need to be initialized for unshow_buffer in window.c. */
9290 selected_window
= f
->selected_window
;
9292 Fmodify_frame_parameters (frame
,
9293 Fcons (Fcons (Qfont
,
9294 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9295 Fmodify_frame_parameters (frame
,
9296 Fcons (Fcons (Qforeground_color
,
9297 build_string ("black")), Qnil
));
9298 Fmodify_frame_parameters (frame
,
9299 Fcons (Fcons (Qbackground_color
,
9300 build_string ("white")), Qnil
));
9305 /***********************************************************************
9307 ***********************************************************************/
9309 int mac_initialized
= 0;
9312 mac_initialize_display_info ()
9314 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9315 GDHandle main_device_handle
;
9317 bzero (dpyinfo
, sizeof (*dpyinfo
));
9320 dpyinfo
->mac_id_name
9321 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9322 + SCHARS (Vsystem_name
)
9324 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9325 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9327 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9328 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9331 main_device_handle
= LMGetMainDevice();
9333 dpyinfo
->reference_count
= 0;
9334 dpyinfo
->resx
= 75.0;
9335 dpyinfo
->resy
= 75.0;
9336 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9338 /* HasDepth returns true if it is possible to have a 32 bit display,
9339 but this may not be what is actually used. Mac OSX can do better.
9340 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9341 header for CGGetActiveDisplayList says that the first display returned
9342 is the active one, so we use that. */
9344 CGDirectDisplayID disp_id
[1];
9345 CGDisplayCount disp_count
;
9346 CGDisplayErr error_code
;
9348 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
9349 if (error_code
!= 0)
9350 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
9352 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
9355 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
9356 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
9357 gdDevType
, dpyinfo
->color_p
))
9360 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
9361 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
9362 dpyinfo
->grabbed
= 0;
9363 dpyinfo
->root_window
= NULL
;
9364 dpyinfo
->image_cache
= make_image_cache ();
9366 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9367 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9368 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9369 dpyinfo
->mouse_face_window
= Qnil
;
9370 dpyinfo
->mouse_face_overlay
= Qnil
;
9371 dpyinfo
->mouse_face_hidden
= 0;
9374 /* Create an xrdb-style database of resources to supercede registry settings.
9375 The database is just a concatenation of C strings, finished by an additional
9376 \0. The string are submitted to some basic normalization, so
9378 [ *]option[ *]:[ *]value...
9384 but any whitespace following value is not removed. */
9387 mac_make_rdb (xrm_option
)
9390 char *buffer
= xmalloc (strlen (xrm_option
) + 2);
9391 char *current
= buffer
;
9394 int before_value
= 0;
9408 if (in_option
&& (ch
== ':'))
9413 else if (before_value
)
9418 else if (!(in_option
|| before_value
))
9429 struct mac_display_info
*
9430 mac_term_init (display_name
, xrm_option
, resource_name
)
9431 Lisp_Object display_name
;
9433 char *resource_name
;
9435 struct mac_display_info
*dpyinfo
;
9439 if (!mac_initialized
)
9442 mac_initialized
= 1;
9446 error ("Sorry, this version can only handle one display");
9448 mac_initialize_display_info ();
9450 dpyinfo
= &one_mac_display_info
;
9452 dpyinfo
->xrdb
= xrm_option
? mac_make_rdb (xrm_option
) : NULL
;
9454 /* Put this display on the chain. */
9455 dpyinfo
->next
= x_display_list
;
9456 x_display_list
= dpyinfo
;
9458 /* Put it on x_display_name_list. */
9459 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
9460 x_display_name_list
);
9461 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9467 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9470 x_delete_display (dpyinfo
)
9471 struct mac_display_info
*dpyinfo
;
9475 /* Discard this display from x_display_name_list and x_display_list.
9476 We can't use Fdelq because that can quit. */
9477 if (! NILP (x_display_name_list
)
9478 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9479 x_display_name_list
= XCDR (x_display_name_list
);
9484 tail
= x_display_name_list
;
9485 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9487 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9489 XSETCDR (tail
, XCDR (XCDR (tail
)));
9496 if (x_display_list
== dpyinfo
)
9497 x_display_list
= dpyinfo
->next
;
9500 struct x_display_info
*tail
;
9502 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9503 if (tail
->next
== dpyinfo
)
9504 tail
->next
= tail
->next
->next
;
9507 /* Free the font names in the font table. */
9508 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9509 if (dpyinfo
->font_table
[i
].name
)
9511 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9512 xfree (dpyinfo
->font_table
[i
].full_name
);
9513 xfree (dpyinfo
->font_table
[i
].name
);
9516 if (dpyinfo
->font_table
->font_encoder
)
9517 xfree (dpyinfo
->font_table
->font_encoder
);
9519 xfree (dpyinfo
->font_table
);
9520 xfree (dpyinfo
->mac_id_name
);
9522 if (x_display_list
== 0)
9524 mac_clear_font_name_table ();
9525 bzero (dpyinfo
, sizeof (*dpyinfo
));
9534 extern int inhibit_window_system
;
9535 extern int noninteractive
;
9536 CFBundleRef appsBundle
;
9539 /* No need to test if already -nw*/
9540 if (inhibit_window_system
|| noninteractive
)
9543 appsBundle
= CFBundleGetMainBundle();
9544 if (appsBundle
!= NULL
)
9546 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
9547 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
9548 /* We found the bundle identifier, now we know we are valid. */
9555 /* MAC_TODO: Have this start the bundled executable */
9557 /* For now, prevent the fatal error by bringing it up in the terminal */
9558 inhibit_window_system
= 1;
9562 MakeMeTheFrontProcess ()
9564 ProcessSerialNumber psn
;
9567 err
= GetCurrentProcess (&psn
);
9569 (void) SetFrontProcess (&psn
);
9572 /***** Code to handle C-g testing *****/
9574 /* Contains the Mac modifier formed from quit_char */
9575 static mac_quit_char_modifiers
= 0;
9576 static mac_quit_char_keycode
;
9577 extern int quit_char
;
9580 mac_determine_quit_char_modifiers()
9582 /* Todo: Determine modifiers from quit_char. */
9583 UInt32 qc_modifiers
= ctrl_modifier
;
9586 mac_quit_char_modifiers
= 0;
9587 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
9588 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
9589 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
9590 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
9594 init_quit_char_handler ()
9596 /* TODO: Let this support keys other the 'g' */
9597 mac_quit_char_keycode
= 5;
9598 /* Look at <architecture/adb_kb_map.h> for details */
9599 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9601 mac_determine_quit_char_modifiers();
9605 quit_char_comp (EventRef inEvent
, void *inCompData
)
9607 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
9609 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
9613 UInt32 keyModifiers
;
9614 GetEventParameter(inEvent
, kEventParamKeyCode
,
9615 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
9616 if (keyCode
!= mac_quit_char_keycode
)
9618 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
9619 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
9620 if (keyModifiers
!= mac_quit_char_modifiers
)
9627 mac_check_for_quit_char ()
9630 static EMACS_TIME last_check_time
= { 0, 0 };
9631 static EMACS_TIME one_second
= { 1, 0 };
9634 /* If windows are not initialized, return immediately (keep it bouncin'). */
9635 if (!mac_quit_char_modifiers
)
9638 /* Don't check if last check is less than a second ago. */
9639 EMACS_GET_TIME (now
);
9640 EMACS_SUB_TIME (t
, now
, last_check_time
);
9641 if (EMACS_TIME_LT (t
, one_second
))
9643 last_check_time
= now
;
9645 /* Redetermine modifiers because they are based on lisp variables */
9646 mac_determine_quit_char_modifiers ();
9648 /* Fill the queue with events */
9650 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
9651 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
9656 struct input_event e
;
9658 /* Use an input_event to emulate what the interrupt handler does. */
9660 e
.kind
= ASCII_KEYSTROKE_EVENT
;
9664 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
9665 XSETFRAME (e
.frame_or_window
, mac_window_to_frame (front_emacs_window ()));
9666 /* Remove event from queue to prevent looping. */
9667 RemoveEventFromQueue (GetMainEventQueue (), event
);
9668 ReleaseEvent (event
);
9669 kbd_buffer_store_event (&e
);
9673 #endif /* MAC_OSX */
9675 /* Set up use of X before we make the first connection. */
9677 extern frame_parm_handler mac_frame_parm_handlers
[];
9679 static struct redisplay_interface x_redisplay_interface
=
9681 mac_frame_parm_handlers
,
9685 x_clear_end_of_line
,
9687 x_after_update_window_line
,
9688 x_update_window_begin
,
9689 x_update_window_end
,
9692 0, /* flush_display_optional */
9693 x_clear_window_mouse_face
,
9694 x_get_glyph_overhangs
,
9695 x_fix_overlapping_area
,
9696 x_draw_fringe_bitmap
,
9697 0, /* define_fringe_bitmap */
9698 0, /* destroy_fringe_bitmap */
9699 mac_per_char_metric
,
9701 mac_compute_glyph_string_overhangs
,
9702 x_draw_glyph_string
,
9703 mac_define_frame_cursor
,
9704 mac_clear_frame_area
,
9705 mac_draw_window_cursor
,
9706 mac_draw_vertical_window_border
,
9707 mac_shift_glyphs_for_insert
9713 rif
= &x_redisplay_interface
;
9715 clear_frame_hook
= x_clear_frame
;
9716 ins_del_lines_hook
= x_ins_del_lines
;
9717 delete_glyphs_hook
= x_delete_glyphs
;
9718 ring_bell_hook
= XTring_bell
;
9719 reset_terminal_modes_hook
= XTreset_terminal_modes
;
9720 set_terminal_modes_hook
= XTset_terminal_modes
;
9721 update_begin_hook
= x_update_begin
;
9722 update_end_hook
= x_update_end
;
9723 set_terminal_window_hook
= XTset_terminal_window
;
9724 read_socket_hook
= XTread_socket
;
9725 frame_up_to_date_hook
= XTframe_up_to_date
;
9726 mouse_position_hook
= XTmouse_position
;
9727 frame_rehighlight_hook
= XTframe_rehighlight
;
9728 frame_raise_lower_hook
= XTframe_raise_lower
;
9730 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
9731 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
9732 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
9733 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
9735 scroll_region_ok
= 1; /* we'll scroll partial frames */
9736 char_ins_del_ok
= 1;
9737 line_ins_del_ok
= 1; /* we'll just blt 'em */
9738 fast_clear_end_of_line
= 1; /* X does this well */
9739 memory_below_frame
= 0; /* we don't remember what scrolls
9744 last_tool_bar_item
= -1;
9745 any_help_event_p
= 0;
9747 /* Try to use interrupt input; if we can't, then start polling. */
9748 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
9750 #ifdef USE_X_TOOLKIT
9751 XtToolkitInitialize ();
9752 Xt_app_con
= XtCreateApplicationContext ();
9753 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
9755 /* Install an asynchronous timer that processes Xt timeout events
9756 every 0.1s. This is necessary because some widget sets use
9757 timeouts internally, for example the LessTif menu bar, or the
9758 Xaw3d scroll bar. When Xt timouts aren't processed, these
9759 widgets don't behave normally. */
9761 EMACS_TIME interval
;
9762 EMACS_SET_SECS_USECS (interval
, 0, 100000);
9763 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
9767 #if USE_TOOLKIT_SCROLL_BARS
9768 xaw3d_arrow_scroll
= False
;
9769 xaw3d_pick_top
= True
;
9773 /* Note that there is no real way portable across R3/R4 to get the
9774 original error handler. */
9775 XSetErrorHandler (x_error_handler
);
9776 XSetIOErrorHandler (x_io_error_quitter
);
9778 /* Disable Window Change signals; they are handled by X events. */
9780 signal (SIGWINCH
, SIG_DFL
);
9781 #endif /* ! defined (SIGWINCH) */
9783 signal (SIGPIPE
, x_connection_signal
);
9788 #if TARGET_API_MAC_CARBON
9789 init_required_apple_events ();
9791 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9792 init_service_handler ();
9794 init_quit_char_handler ();
9797 DisableMenuCommand (NULL
, kHICommandQuit
);
9800 if (!inhibit_window_system
)
9801 MakeMeTheFrontProcess ();
9812 staticpro (&x_error_message_string
);
9813 x_error_message_string
= Qnil
;
9816 Qmodifier_value
= intern ("modifier-value");
9817 Qalt
= intern ("alt");
9818 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
9819 Qhyper
= intern ("hyper");
9820 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
9821 Qsuper
= intern ("super");
9822 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
9825 Fprovide (intern ("mac-carbon"), Qnil
);
9828 staticpro (&Qreverse
);
9829 Qreverse
= intern ("reverse");
9831 staticpro (&x_display_name_list
);
9832 x_display_name_list
= Qnil
;
9834 staticpro (&last_mouse_scroll_bar
);
9835 last_mouse_scroll_bar
= Qnil
;
9837 staticpro (&Qvendor_specific_keysyms
);
9838 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
9840 staticpro (&last_mouse_press_frame
);
9841 last_mouse_press_frame
= Qnil
;
9843 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
9844 staticpro (&Qmac_ready_for_drag_n_drop
);
9846 Qbig5
= intern ("big5");
9849 Qcn_gb
= intern ("cn-gb");
9850 staticpro (&Qcn_gb
);
9852 Qsjis
= intern ("sjis");
9855 Qeuc_kr
= intern ("euc-kr");
9856 staticpro (&Qeuc_kr
);
9858 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
9859 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
9860 x_autoselect_window_p
= 0;
9862 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
9863 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
9864 Vx_toolkit_scroll_bars
= Qt
;
9866 DEFVAR_BOOL ("x-use-underline-position-properties",
9867 &x_use_underline_position_properties
,
9868 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9869 nil means ignore them. If you encounter fonts with bogus
9870 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9871 to 4.1, set this to nil. */);
9872 x_use_underline_position_properties
= 0;
9874 staticpro (&last_mouse_motion_frame
);
9875 last_mouse_motion_frame
= Qnil
;
9877 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
9878 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
9879 Otherwise the option key is used. */);
9880 Vmac_command_key_is_meta
= Qt
;
9882 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
9883 doc
: /* Modifier to use for the Mac alt/option key. The value can
9884 be alt, hyper, or super for the respective modifier. If the value is
9885 nil then the key will act as the normal Mac option modifier. */);
9886 Vmac_option_modifier
= Qnil
;
9888 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
9889 doc
: /* Non-nil means that the control and meta keys are reversed. This is
9890 useful for non-standard keyboard layouts. */);
9891 Vmac_reverse_ctrl_meta
= Qnil
;
9893 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9894 &Vmac_emulate_three_button_mouse
,
9895 doc
: /* t means that when the option-key is held down while pressing the
9896 mouse button, the click will register as mouse-2 and while the
9897 command-key is held down, the click will register as mouse-3.
9898 'reverse means that the the option-key will register for mouse-3
9899 and the command-key will register for mouse-2. nil means that
9900 no emulation should be done and the modifiers should be placed
9901 on the mouse-1 event. */);
9902 Vmac_emulate_three_button_mouse
= Qnil
;
9904 #if USE_CARBON_EVENTS
9905 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
9906 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
9907 the right click will be mouse-3.
9908 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9909 Vmac_wheel_button_is_mouse_2
= Qt
;
9911 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
9912 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9913 Toolbox for processing before Emacs sees it. */);
9914 Vmac_pass_command_to_system
= Qt
;
9916 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9917 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9918 Toolbox for processing before Emacs sees it. */);
9919 Vmac_pass_control_to_system
= Qt
;
9921 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9922 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9923 Toolbox for processing before Emacs sees it. */);
9924 Vmac_pass_control_to_system
= Qt
;
9927 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
9928 doc
: /* If non-nil, allow anti-aliasing.
9929 The text will be rendered using Core Graphics text rendering which
9930 may anti-alias the text. */);
9931 Vmac_use_core_graphics
= Qnil
;
9933 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
9934 doc
: /* One of the Text Encoding Base constant values defined in the
9935 Basic Text Constants section of Inside Macintosh - Text Encoding
9936 Conversion Manager. Its value determines the encoding characters
9937 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9938 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9939 its default value, no conversion takes place. If it is set to
9940 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9941 characters typed on Mac keyboard are first converted into the
9942 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9943 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9944 command, this enables the Mac keyboard to be used to enter non-ASCII
9945 characters directly. */);
9946 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
9949 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9950 (do not change this comment) */