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 . RESOURCE-DATABASE), one for each element of
133 x_display_list and in the same order. NAME is the name of the
134 frame. FONT-LIST-CACHE records previous values returned by
135 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
136 equivalent, which is implemented with a Lisp object, for the
139 Lisp_Object x_display_name_list
;
141 /* This is display since Mac does not support multiple ones. */
142 struct mac_display_info one_mac_display_info
;
144 /* Frame being updated by update_frame. This is declared in term.c.
145 This is set by update_begin and looked at by all the XT functions.
146 It is zero while not inside an update. In that case, the XT
147 functions assume that `selected_frame' is the frame to apply to. */
149 extern struct frame
*updating_frame
;
151 extern int waiting_for_input
;
153 /* This is a frame waiting to be auto-raised, within XTread_socket. */
155 struct frame
*pending_autoraise_frame
;
157 /* Non-zero means user is interacting with a toolkit scroll bar. */
159 static int toolkit_scroll_bar_interaction
;
163 Formerly, we used PointerMotionHintMask (in standard_event_mask)
164 so that we would have to call XQueryPointer after each MotionNotify
165 event to ask for another such event. However, this made mouse tracking
166 slow, and there was a bug that made it eventually stop.
168 Simply asking for MotionNotify all the time seems to work better.
170 In order to avoid asking for motion events and then throwing most
171 of them away or busy-polling the server for mouse positions, we ask
172 the server for pointer motion hints. This means that we get only
173 one event per group of mouse movements. "Groups" are delimited by
174 other kinds of events (focus changes and button clicks, for
175 example), or by XQueryPointer calls; when one of these happens, we
176 get another MotionNotify event the next time the mouse moves. This
177 is at least as efficient as getting motion events when mouse
178 tracking is on, and I suspect only negligibly worse when tracking
181 /* Where the mouse was last time we reported a mouse event. */
183 static Rect last_mouse_glyph
;
184 static Lisp_Object last_mouse_press_frame
;
186 /* The scroll bar in which the last X motion event occurred.
188 If the last X motion event occurred in a scroll bar, we set this so
189 XTmouse_position can know whether to report a scroll bar motion or
192 If the last X motion event didn't occur in a scroll bar, we set
193 this to Qnil, to tell XTmouse_position to return an ordinary motion
196 static Lisp_Object last_mouse_scroll_bar
;
198 /* This is a hack. We would really prefer that XTmouse_position would
199 return the time associated with the position it returns, but there
200 doesn't seem to be any way to wrest the time-stamp from the server
201 along with the position query. So, we just keep track of the time
202 of the last movement we received, and return that in hopes that
203 it's somewhat accurate. */
205 static Time last_mouse_movement_time
;
207 struct scroll_bar
*tracked_scroll_bar
= NULL
;
209 /* Incremented by XTread_socket whenever it really tries to read
213 static int volatile input_signal_count
;
215 static int input_signal_count
;
218 /* Used locally within XTread_socket. */
220 static int x_noop_count
;
222 /* Initial values of argv and argc. */
224 extern char **initial_argv
;
225 extern int initial_argc
;
227 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
229 /* Tells if a window manager is present or not. */
231 extern Lisp_Object Vx_no_window_manager
;
235 /* A mask of extra modifier bits to put into every keyboard char. */
237 extern int extra_keyboard_modifiers
;
239 /* The keysyms to use for the various modifiers. */
241 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qmodifier_value
;
243 static Lisp_Object Qvendor_specific_keysyms
;
246 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
249 extern int inhibit_window_system
;
251 #if __MRC__ && !TARGET_API_MAC_CARBON
252 QDGlobals qd
; /* QuickDraw global information structure. */
256 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
257 struct mac_display_info
*mac_display_info_for_display (Display
*);
258 static void x_update_window_end
P_ ((struct window
*, int, int));
259 static void mac_handle_tool_bar_click
P_ ((struct frame
*, EventRecord
*));
260 static int x_io_error_quitter
P_ ((Display
*));
261 int x_catch_errors
P_ ((Display
*));
262 void x_uncatch_errors
P_ ((Display
*, int));
263 void x_lower_frame
P_ ((struct frame
*));
264 void x_scroll_bar_clear
P_ ((struct frame
*));
265 int x_had_errors_p
P_ ((Display
*));
266 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
267 void x_raise_frame
P_ ((struct frame
*));
268 void x_set_window_size
P_ ((struct frame
*, int, int, int));
269 void x_wm_set_window_state
P_ ((struct frame
*, int));
270 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
271 void mac_initialize
P_ ((void));
272 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
273 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
274 static void x_update_end
P_ ((struct frame
*));
275 static void XTframe_up_to_date
P_ ((struct frame
*));
276 static void XTreassert_line_highlight
P_ ((int, int));
277 static void x_change_line_highlight
P_ ((int, int, int, int));
278 static void XTset_terminal_modes
P_ ((void));
279 static void XTreset_terminal_modes
P_ ((void));
280 static void x_clear_frame
P_ ((void));
281 static void frame_highlight
P_ ((struct frame
*));
282 static void frame_unhighlight
P_ ((struct frame
*));
283 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
284 static void XTframe_rehighlight
P_ ((struct frame
*));
285 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
286 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
287 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
288 enum text_cursor_kinds
));
290 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
291 static void x_flush
P_ ((struct frame
*f
));
292 static void x_update_begin
P_ ((struct frame
*));
293 static void x_update_window_begin
P_ ((struct window
*));
294 static void x_after_update_window_line
P_ ((struct glyph_row
*));
296 static int is_emacs_window (WindowPtr
);
298 int x_bitmap_icon (struct frame
*, Lisp_Object
);
299 void x_make_frame_visible (struct frame
*);
301 extern void window_scroll (Lisp_Object
, int, int, int);
303 /* Defined in macmenu.h. */
304 extern void menubar_selection_callback (FRAME_PTR
, int);
305 extern void set_frame_menubar (FRAME_PTR
, int, int);
307 /* X display function emulation */
310 XFreePixmap (display
, pixmap
)
311 Display
*display
; /* not used */
314 DisposeGWorld (pixmap
);
318 /* Set foreground color for subsequent QuickDraw commands. Assume
319 graphic port has already been set. */
322 mac_set_forecolor (unsigned long color
)
326 fg_color
.red
= RED16_FROM_ULONG (color
);
327 fg_color
.green
= GREEN16_FROM_ULONG (color
);
328 fg_color
.blue
= BLUE16_FROM_ULONG (color
);
330 RGBForeColor (&fg_color
);
334 /* Set background color for subsequent QuickDraw commands. Assume
335 graphic port has already been set. */
338 mac_set_backcolor (unsigned long color
)
342 bg_color
.red
= RED16_FROM_ULONG (color
);
343 bg_color
.green
= GREEN16_FROM_ULONG (color
);
344 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
346 RGBBackColor (&bg_color
);
349 /* Set foreground and background color for subsequent QuickDraw
350 commands. Assume that the graphic port has already been set. */
353 mac_set_colors (gc
, bg_save
)
358 GetBackColor (bg_save
);
359 mac_set_forecolor (gc
->foreground
);
360 mac_set_backcolor (gc
->background
);
363 /* Mac version of XDrawLine. */
366 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
374 SetPortWindowPort (w
);
376 mac_set_colors (gc
, &old_bg
);
381 RGBBackColor (&old_bg
);
385 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
394 GetGWorld (&old_port
, &old_gdh
);
397 mac_set_colors (gc
, NULL
);
399 LockPixels (GetGWorldPixMap (p
));
402 UnlockPixels (GetGWorldPixMap (p
));
404 SetGWorld (old_port
, old_gdh
);
407 /* Mac version of XClearArea. */
410 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
414 unsigned int width
, height
;
417 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
422 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
423 xgc
.background
= mwp
->x_compatible
.background_pixel
;
425 SetPortWindowPort (w
);
427 mac_set_colors (&xgc
, &old_bg
);
428 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
432 RGBBackColor (&old_bg
);
435 /* Mac version of XClearWindow. */
438 XClearWindow (display
, w
)
442 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
445 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
446 xgc
.background
= mwp
->x_compatible
.background_pixel
;
448 SetPortWindowPort (w
);
450 mac_set_colors (&xgc
, NULL
);
452 #if TARGET_API_MAC_CARBON
456 GetWindowPortBounds (w
, &r
);
459 #else /* not TARGET_API_MAC_CARBON */
460 EraseRect (&(w
->portRect
));
461 #endif /* not TARGET_API_MAC_CARBON */
465 /* Mac replacement for XCopyArea. */
468 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
472 int x
, y
, width
, height
;
473 unsigned short *bits
;
480 bitmap
.rowBytes
= sizeof(unsigned short);
481 bitmap
.baseAddr
= (char *)bits
;
482 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
484 SetPortWindowPort (w
);
486 mac_set_colors (gc
, &old_bg
);
487 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
489 #if TARGET_API_MAC_CARBON
490 LockPortBits (GetWindowPort (w
));
491 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
492 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
493 UnlockPortBits (GetWindowPort (w
));
494 #else /* not TARGET_API_MAC_CARBON */
495 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
496 overlay_p
? srcOr
: srcCopy
, 0);
497 #endif /* not TARGET_API_MAC_CARBON */
499 RGBBackColor (&old_bg
);
503 /* Mac replacement for XSetClipRectangles. */
506 mac_set_clip_rectangle (display
, w
, r
)
511 SetPortWindowPort (w
);
517 /* Mac replacement for XSetClipMask. */
520 mac_reset_clipping (display
, w
)
526 SetPortWindowPort (w
);
528 SetRect (&r
, -32767, -32767, 32767, 32767);
533 /* Mac replacement for XCreateBitmapFromBitmapData. */
536 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
541 static unsigned char swap_nibble
[16]
542 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
543 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
544 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
545 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
549 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
550 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
551 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
552 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
553 for (i
= 0; i
< h
; i
++)
555 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
556 for (j
= 0; j
< w1
; j
++)
558 /* Bitswap XBM bytes to match how Mac does things. */
559 unsigned char c
= *bits
++;
560 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
561 | (swap_nibble
[(c
>>4) & 0xf]));;
565 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
570 mac_free_bitmap (bitmap
)
573 xfree (bitmap
->baseAddr
);
578 XCreatePixmap (display
, w
, width
, height
, depth
)
579 Display
*display
; /* not used */
581 unsigned int width
, height
;
588 SetPortWindowPort (w
);
590 SetRect (&r
, 0, 0, width
, height
);
591 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
599 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
600 Display
*display
; /* not used */
603 unsigned int width
, height
;
604 unsigned long fg
, bg
;
605 unsigned int depth
; /* not used */
612 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
616 GetGWorld (&old_port
, &old_gdh
);
617 SetGWorld (pixmap
, NULL
);
618 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
619 mac_set_forecolor (fg
);
620 mac_set_backcolor (bg
);
621 LockPixels (GetGWorldPixMap (pixmap
));
622 #if TARGET_API_MAC_CARBON
623 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
624 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
625 #else /* not TARGET_API_MAC_CARBON */
626 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
627 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
628 #endif /* not TARGET_API_MAC_CARBON */
629 UnlockPixels (GetGWorldPixMap (pixmap
));
630 SetGWorld (old_port
, old_gdh
);
631 mac_free_bitmap (&bitmap
);
637 /* Mac replacement for XFillRectangle. */
640 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
645 unsigned int width
, height
;
650 SetPortWindowPort (w
);
652 mac_set_colors (gc
, &old_bg
);
653 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
655 PaintRect (&r
); /* using foreground color of gc */
657 RGBBackColor (&old_bg
);
661 #if 0 /* TODO: figure out if we need to do this on Mac. */
663 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
668 unsigned int width
, height
;
674 GetGWorld (&old_port
, &old_gdh
);
676 mac_set_colors (gc
, NULL
);
677 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
679 LockPixels (GetGWorldPixMap (p
));
680 PaintRect (&r
); /* using foreground color of gc */
681 UnlockPixels (GetGWorldPixMap (p
));
683 SetGWorld (old_port
, old_gdh
);
688 /* Mac replacement for XDrawRectangle: dest is a window. */
691 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
696 unsigned int width
, height
;
701 SetPortWindowPort (w
);
703 mac_set_colors (gc
, &old_bg
);
704 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
706 FrameRect (&r
); /* using foreground color of gc */
708 RGBBackColor (&old_bg
);
712 #if 0 /* TODO: figure out if we need to do this on Mac. */
713 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
716 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
721 unsigned int width
, height
;
727 GetGWorld (&old_port
, &old_gdh
);
729 mac_set_colors (gc
, NULL
);
730 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
732 LockPixels (GetGWorldPixMap (p
));
733 FrameRect (&r
); /* using foreground color of gc */
734 UnlockPixels (GetGWorldPixMap (p
));
736 SetGWorld (old_port
, old_gdh
);
742 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
749 int nchars
, mode
, bytes_per_char
;
753 SetPortWindowPort (w
);
754 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
755 UInt32 textFlags
, savedFlags
;
756 if (!NILP(Vmac_use_core_graphics
)) {
757 textFlags
= kQDUseCGTextRendering
;
758 savedFlags
= SwapQDTextFlags(textFlags
);
762 mac_set_colors (gc
, &old_bg
);
764 TextFont (gc
->font
->mac_fontnum
);
765 TextSize (gc
->font
->mac_fontsize
);
766 TextFace (gc
->font
->mac_fontface
);
770 DrawText (buf
, 0, nchars
* bytes_per_char
);
772 RGBBackColor (&old_bg
);
773 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
774 if (!NILP(Vmac_use_core_graphics
))
775 SwapQDTextFlags(savedFlags
);
780 /* Mac replacement for XDrawString. */
783 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
791 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
795 /* Mac replacement for XDrawString16. */
798 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
806 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
811 /* Mac replacement for XDrawImageString. */
814 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
822 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
826 /* Mac replacement for XDrawString16. */
829 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
837 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
842 /* Mac replacement for XCopyArea: dest must be window. */
845 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
852 unsigned int width
, height
;
857 SetPortWindowPort (dest
);
859 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
860 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
862 ForeColor (blackColor
);
863 BackColor (whiteColor
);
865 LockPixels (GetGWorldPixMap (src
));
866 #if TARGET_API_MAC_CARBON
867 LockPortBits (GetWindowPort (dest
));
868 CopyBits (GetPortBitMapForCopyBits (src
),
869 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
870 &src_r
, &dest_r
, srcCopy
, 0);
871 UnlockPortBits (GetWindowPort (dest
));
872 #else /* not TARGET_API_MAC_CARBON */
873 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
874 &src_r
, &dest_r
, srcCopy
, 0);
875 #endif /* not TARGET_API_MAC_CARBON */
876 UnlockPixels (GetGWorldPixMap (src
));
881 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
882 width
, height
, dest_x
, dest_y
)
888 unsigned int width
, height
;
893 SetPortWindowPort (dest
);
895 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
896 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
898 ForeColor (blackColor
);
899 BackColor (whiteColor
);
901 LockPixels (GetGWorldPixMap (src
));
902 LockPixels (GetGWorldPixMap (mask
));
903 #if TARGET_API_MAC_CARBON
904 LockPortBits (GetWindowPort (dest
));
905 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
906 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
907 &src_r
, &src_r
, &dest_r
);
908 UnlockPortBits (GetWindowPort (dest
));
909 #else /* not TARGET_API_MAC_CARBON */
910 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
911 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
912 #endif /* not TARGET_API_MAC_CARBON */
913 UnlockPixels (GetGWorldPixMap (mask
));
914 UnlockPixels (GetGWorldPixMap (src
));
919 /* Convert a pair of local coordinates to global (screen) coordinates.
920 Assume graphic port has been properly set. */
922 local_to_global_coord (short *h
, short *v
)
936 /* Mac replacement for XCopyArea: used only for scrolling. */
939 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
944 unsigned int width
, height
;
947 #if TARGET_API_MAC_CARBON
949 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
951 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
952 ScrollWindowRect (w
, &src_r
, dest_x
- src_x
, dest_y
- src_y
,
953 kScrollWindowNoOptions
, dummy
);
955 #else /* not TARGET_API_MAC_CARBON */
960 mac_set_colors (gc
, NULL
);
963 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
964 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
967 /* Need to use global coordinates and screenBits since src and dest
968 areas overlap in general. */
969 local_to_global_coord (&src_r
.left
, &src_r
.top
);
970 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
971 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
972 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
974 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
976 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
977 color mapping in CopyBits. Otherwise, it will be slow. */
978 ForeColor (blackColor
);
979 BackColor (whiteColor
);
980 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
982 mac_set_colors (gc
, NULL
);
984 #endif /* not TARGET_API_MAC_CARBON */
988 #if 0 /* TODO: figure out if we need to do this on Mac. */
989 /* Mac replacement for XCopyArea: dest must be Pixmap. */
992 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
998 unsigned int width
, height
;
1005 GetGWorld (&old_port
, &old_gdh
);
1006 SetGWorld (dest
, NULL
);
1007 ForeColor (blackColor
);
1008 BackColor (whiteColor
);
1010 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1011 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1013 LockPixels (GetGWorldPixMap (src
));
1014 LockPixels (GetGWorldPixMap (dest
));
1015 #if TARGET_API_MAC_CARBON
1016 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
1017 &src_r
, &dest_r
, srcCopy
, 0);
1018 #else /* not TARGET_API_MAC_CARBON */
1019 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
1020 &src_r
, &dest_r
, srcCopy
, 0);
1021 #endif /* not TARGET_API_MAC_CARBON */
1022 UnlockPixels (GetGWorldPixMap (dest
));
1023 UnlockPixels (GetGWorldPixMap (src
));
1025 SetGWorld (old_port
, old_gdh
);
1030 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
1031 width
, height
, dest_x
, dest_y
)
1033 Pixmap src
, mask
, dest
;
1036 unsigned int width
, height
;
1043 GetGWorld (&old_port
, &old_gdh
);
1044 SetGWorld (dest
, NULL
);
1045 ForeColor (blackColor
);
1046 BackColor (whiteColor
);
1048 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1049 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1051 LockPixels (GetGWorldPixMap (src
));
1052 LockPixels (GetGWorldPixMap (mask
));
1053 LockPixels (GetGWorldPixMap (dest
));
1054 #if TARGET_API_MAC_CARBON
1055 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1056 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
1057 #else /* not TARGET_API_MAC_CARBON */
1058 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1059 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
1060 #endif /* not TARGET_API_MAC_CARBON */
1061 UnlockPixels (GetGWorldPixMap (dest
));
1062 UnlockPixels (GetGWorldPixMap (mask
));
1063 UnlockPixels (GetGWorldPixMap (src
));
1065 SetGWorld (old_port
, old_gdh
);
1070 /* Mac replacement for XChangeGC. */
1073 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1076 if (mask
& GCForeground
)
1077 gc
->foreground
= xgcv
->foreground
;
1078 if (mask
& GCBackground
)
1079 gc
->background
= xgcv
->background
;
1081 gc
->font
= xgcv
->font
;
1085 /* Mac replacement for XCreateGC. */
1088 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1091 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1092 bzero (gc
, sizeof (XGCValues
));
1094 XChangeGC (ignore
, gc
, mask
, xgcv
);
1100 /* Used in xfaces.c. */
1103 XFreeGC (display
, gc
)
1111 /* Mac replacement for XGetGCValues. */
1114 XGetGCValues (void* ignore
, XGCValues
*gc
,
1115 unsigned long mask
, XGCValues
*xgcv
)
1117 XChangeGC (ignore
, xgcv
, mask
, gc
);
1121 /* Mac replacement for XSetForeground. */
1124 XSetForeground (display
, gc
, color
)
1127 unsigned long color
;
1129 gc
->foreground
= color
;
1133 /* Mac replacement for XSetBackground. */
1136 XSetBackground (display
, gc
, color
)
1139 unsigned long color
;
1141 gc
->background
= color
;
1145 /* Mac replacement for XSetWindowBackground. */
1148 XSetWindowBackground (display
, w
, color
)
1151 unsigned long color
;
1153 #if !TARGET_API_MAC_CARBON
1154 AuxWinHandle aw_handle
;
1155 CTabHandle ctab_handle
;
1156 ColorSpecPtr ct_table
;
1161 bg_color
.red
= RED16_FROM_ULONG (color
);
1162 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1163 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1165 #if TARGET_API_MAC_CARBON
1166 SetWindowContentColor (w
, &bg_color
);
1168 if (GetAuxWin (w
, &aw_handle
))
1170 ctab_handle
= (*aw_handle
)->awCTable
;
1171 HandToHand ((Handle
*) &ctab_handle
);
1172 ct_table
= (*ctab_handle
)->ctTable
;
1173 ct_size
= (*ctab_handle
)->ctSize
;
1174 while (ct_size
> -1)
1176 if (ct_table
->value
== 0)
1178 ct_table
->rgb
= bg_color
;
1179 CTabChanged (ctab_handle
);
1180 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1189 /* Mac replacement for XSetFont. */
1192 XSetFont (display
, gc
, font
)
1202 XTextExtents16 (XFontStruct
*font
, XChar2b
*text
, int nchars
,
1203 int *direction
,int *font_ascent
,
1204 int *font_descent
, XCharStruct
*cs
)
1206 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1210 /* x_sync is a no-op on Mac. */
1218 /* Flush display of frame F, or of all frames if F is null. */
1224 #if TARGET_API_MAC_CARBON
1227 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1229 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1235 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1236 Calls to XFlush should be unnecessary because the X output buffer
1237 is flushed automatically as needed by calls to XPending,
1238 XNextEvent, or XWindowEvent according to the XFlush man page.
1239 XTread_socket calls XPending. Removing XFlush improves
1242 #define XFlush(DISPLAY) (void) 0
1245 /* Return the struct mac_display_info corresponding to DPY. There's
1248 struct mac_display_info
*
1249 mac_display_info_for_display (dpy
)
1252 return &one_mac_display_info
;
1257 /***********************************************************************
1258 Starting and ending an update
1259 ***********************************************************************/
1261 /* Start an update of frame F. This function is installed as a hook
1262 for update_begin, i.e. it is called when update_begin is called.
1263 This function is called prior to calls to x_update_window_begin for
1264 each window being updated. */
1270 #if TARGET_API_MAC_CARBON
1271 /* During update of a frame, availability of input events is
1272 periodically checked with ReceiveNextEvent if
1273 redisplay-dont-pause is nil. That normally flushes window buffer
1274 changes for every check, and thus screen update looks waving even
1275 if no input is available. So we disable screen updates during
1276 update of a frame. */
1278 DisableScreenUpdates ();
1284 /* Start update of window W. Set the global variable updated_window
1285 to the window being updated and set output_cursor to the cursor
1289 x_update_window_begin (w
)
1292 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1293 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1296 set_output_cursor (&w
->cursor
);
1300 if (f
== display_info
->mouse_face_mouse_frame
)
1302 /* Don't do highlighting for mouse motion during the update. */
1303 display_info
->mouse_face_defer
= 1;
1305 /* If F needs to be redrawn, simply forget about any prior mouse
1307 if (FRAME_GARBAGED_P (f
))
1308 display_info
->mouse_face_window
= Qnil
;
1310 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1311 their mouse_face_p flag set, which means that they are always
1312 unequal to rows in a desired matrix which never have that
1313 flag set. So, rows containing mouse-face glyphs are never
1314 scrolled, and we don't have to switch the mouse highlight off
1315 here to prevent it from being scrolled. */
1317 /* Can we tell that this update does not affect the window
1318 where the mouse highlight is? If so, no need to turn off.
1319 Likewise, don't do anything if the frame is garbaged;
1320 in that case, the frame's current matrix that we would use
1321 is all wrong, and we will redisplay that line anyway. */
1322 if (!NILP (display_info
->mouse_face_window
)
1323 && w
== XWINDOW (display_info
->mouse_face_window
))
1327 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1328 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1331 if (i
< w
->desired_matrix
->nrows
)
1332 clear_mouse_face (display_info
);
1341 /* Draw a vertical window border from (x,y0) to (x,y1) */
1344 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1348 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1350 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1351 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1355 /* End update of window W (which is equal to updated_window).
1357 Draw vertical borders between horizontally adjacent windows, and
1358 display W's cursor if CURSOR_ON_P is non-zero.
1360 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1361 glyphs in mouse-face were overwritten. In that case we have to
1362 make sure that the mouse-highlight is properly redrawn.
1364 W may be a menu bar pseudo-window in case we don't have X toolkit
1365 support. Such windows don't have a cursor, so don't display it
1369 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1371 int cursor_on_p
, mouse_face_overwritten_p
;
1373 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1375 if (!w
->pseudo_window_p
)
1380 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1382 output_cursor
.x
, output_cursor
.y
);
1384 if (draw_window_fringes (w
, 1))
1385 x_draw_vertical_border (w
);
1390 /* If a row with mouse-face was overwritten, arrange for
1391 XTframe_up_to_date to redisplay the mouse highlight. */
1392 if (mouse_face_overwritten_p
)
1394 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1395 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1396 dpyinfo
->mouse_face_window
= Qnil
;
1400 /* Unhide the caret. This won't actually show the cursor, unless it
1401 was visible before the corresponding call to HideCaret in
1402 x_update_window_begin. */
1403 if (w32_use_visible_system_caret
)
1404 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1407 updated_window
= NULL
;
1411 /* End update of frame F. This function is installed as a hook in
1418 /* Mouse highlight may be displayed again. */
1419 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1422 #if TARGET_API_MAC_CARBON
1423 EnableScreenUpdates ();
1425 XFlush (FRAME_MAC_DISPLAY (f
));
1430 /* This function is called from various places in xdisp.c whenever a
1431 complete update has been performed. The global variable
1432 updated_window is not available here. */
1435 XTframe_up_to_date (f
)
1438 if (FRAME_MAC_P (f
))
1440 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1442 if (dpyinfo
->mouse_face_deferred_gc
1443 || f
== dpyinfo
->mouse_face_mouse_frame
)
1446 if (dpyinfo
->mouse_face_mouse_frame
)
1447 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1448 dpyinfo
->mouse_face_mouse_x
,
1449 dpyinfo
->mouse_face_mouse_y
);
1450 dpyinfo
->mouse_face_deferred_gc
= 0;
1457 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1458 arrow bitmaps, or clear the fringes if no bitmaps are required
1459 before DESIRED_ROW is made current. The window being updated is
1460 found in updated_window. This function is called from
1461 update_window_line only if it is known that there are differences
1462 between bitmaps to be drawn between current row and DESIRED_ROW. */
1465 x_after_update_window_line (desired_row
)
1466 struct glyph_row
*desired_row
;
1468 struct window
*w
= updated_window
;
1474 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1475 desired_row
->redraw_fringe_bitmaps_p
= 1;
1477 /* When a window has disappeared, make sure that no rest of
1478 full-width rows stays visible in the internal border. Could
1479 check here if updated_window is the leftmost/rightmost window,
1480 but I guess it's not worth doing since vertically split windows
1481 are almost never used, internal border is rarely set, and the
1482 overhead is very small. */
1483 if (windows_or_buffers_changed
1484 && desired_row
->full_width_p
1485 && (f
= XFRAME (w
->frame
),
1486 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1488 && (height
= desired_row
->visible_height
,
1491 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1492 /* Internal border is drawn below the tool bar. */
1493 if (WINDOWP (f
->tool_bar_window
)
1494 && w
== XWINDOW (f
->tool_bar_window
))
1499 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1500 0, y
, width
, height
, 0);
1501 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1502 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1510 /* Draw the bitmap WHICH in one of the left or right fringes of
1511 window W. ROW is the glyph row for which to display the bitmap; it
1512 determines the vertical position at which the bitmap has to be
1516 x_draw_fringe_bitmap (w
, row
, p
)
1518 struct glyph_row
*row
;
1519 struct draw_fringe_bitmap_params
*p
;
1521 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1522 Display
*display
= FRAME_MAC_DISPLAY (f
);
1523 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1525 GC gc
= f
->output_data
.mac
->normal_gc
;
1526 struct face
*face
= p
->face
;
1529 /* Must clip because of partially visible lines. */
1530 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1533 /* Adjust position of "bottom aligned" bitmap on partially
1534 visible last row. */
1536 int oldVH
= row
->visible_height
;
1537 row
->visible_height
= p
->h
;
1538 row
->y
-= rowY
- p
->y
;
1539 x_clip_to_row (w
, row
, -1, gc
);
1541 row
->visible_height
= oldVH
;
1544 x_clip_to_row (w
, row
, -1, gc
);
1546 if (p
->bx
>= 0 && !p
->overlay_p
)
1549 gcv
.foreground
= face
->background
;
1551 #if 0 /* MAC_TODO: stipple */
1552 /* In case the same realized face is used for fringes and
1553 for something displayed in the text (e.g. face `region' on
1554 mono-displays, the fill style may have been changed to
1555 FillSolid in x_draw_glyph_string_background. */
1557 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1559 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1562 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1564 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1566 #if 0 /* MAC_TODO: stipple */
1568 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1574 unsigned short *bits
= p
->bits
+ p
->dh
;
1576 gcv
.foreground
= (p
->cursor_p
1577 ? (p
->overlay_p
? face
->background
1578 : f
->output_data
.mac
->cursor_pixel
)
1579 : face
->foreground
);
1580 gcv
.background
= face
->background
;
1582 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
,
1583 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1586 mac_reset_clipping (display
, window
);
1590 /* This is called when starting Emacs and when restarting after
1591 suspend. When starting Emacs, no window is mapped. And nothing
1592 must be done to Emacs's own window if it is suspended (though that
1596 XTset_terminal_modes ()
1600 /* This is called when exiting or suspending Emacs. Exiting will make
1601 the windows go away, and suspending requires no action. */
1604 XTreset_terminal_modes ()
1609 /***********************************************************************
1611 ***********************************************************************/
1613 /* Function prototypes of this page. */
1615 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1616 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1619 /* Return a pointer to per-char metric information in FONT of a
1620 character pointed by B which is a pointer to an XChar2b. */
1622 #define PER_CHAR_METRIC(font, b) \
1624 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1625 + (((font)->min_byte1 || (font)->max_byte1) \
1626 ? (((b)->byte1 - (font)->min_byte1) \
1627 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1629 : &((font)->max_bounds))
1632 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1633 is not contained in the font. */
1635 static INLINE XCharStruct
*
1636 x_per_char_metric (font
, char2b
)
1640 /* The result metric information. */
1641 XCharStruct
*pcm
= NULL
;
1643 xassert (font
&& char2b
);
1645 if (font
->per_char
!= NULL
)
1647 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1649 /* min_char_or_byte2 specifies the linear character index
1650 corresponding to the first element of the per_char array,
1651 max_char_or_byte2 is the index of the last character. A
1652 character with non-zero CHAR2B->byte1 is not in the font.
1653 A character with byte2 less than min_char_or_byte2 or
1654 greater max_char_or_byte2 is not in the font. */
1655 if (char2b
->byte1
== 0
1656 && char2b
->byte2
>= font
->min_char_or_byte2
1657 && char2b
->byte2
<= font
->max_char_or_byte2
)
1658 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1662 /* If either min_byte1 or max_byte1 are nonzero, both
1663 min_char_or_byte2 and max_char_or_byte2 are less than
1664 256, and the 2-byte character index values corresponding
1665 to the per_char array element N (counting from 0) are:
1667 byte1 = N/D + min_byte1
1668 byte2 = N\D + min_char_or_byte2
1672 D = max_char_or_byte2 - min_char_or_byte2 + 1
1673 / = integer division
1674 \ = integer modulus */
1675 if (char2b
->byte1
>= font
->min_byte1
1676 && char2b
->byte1
<= font
->max_byte1
1677 && char2b
->byte2
>= font
->min_char_or_byte2
1678 && char2b
->byte2
<= font
->max_char_or_byte2
)
1680 pcm
= (font
->per_char
1681 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1682 * (char2b
->byte1
- font
->min_byte1
))
1683 + (char2b
->byte2
- font
->min_char_or_byte2
));
1689 /* If the per_char pointer is null, all glyphs between the first
1690 and last character indexes inclusive have the same
1691 information, as given by both min_bounds and max_bounds. */
1692 if (char2b
->byte2
>= font
->min_char_or_byte2
1693 && char2b
->byte2
<= font
->max_char_or_byte2
)
1694 pcm
= &font
->max_bounds
;
1697 return ((pcm
== NULL
1698 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1705 static XCharStruct
*
1706 mac_per_char_metric (font
, char2b
, font_type
)
1711 return x_per_char_metric (font
, char2b
);
1715 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1716 the two-byte form of C. Encoding is returned in *CHAR2B. */
1719 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1722 struct font_info
*font_info
;
1725 int charset
= CHAR_CHARSET (c
);
1726 XFontStruct
*font
= font_info
->font
;
1728 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1729 This may be either a program in a special encoder language or a
1731 if (font_info
->font_encoder
)
1733 /* It's a program. */
1734 struct ccl_program
*ccl
= font_info
->font_encoder
;
1736 if (CHARSET_DIMENSION (charset
) == 1)
1738 ccl
->reg
[0] = charset
;
1739 ccl
->reg
[1] = char2b
->byte2
;
1743 ccl
->reg
[0] = charset
;
1744 ccl
->reg
[1] = char2b
->byte1
;
1745 ccl
->reg
[2] = char2b
->byte2
;
1748 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1750 /* We assume that MSBs are appropriately set/reset by CCL
1752 if (font
->max_byte1
== 0) /* 1-byte font */
1753 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1755 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1757 else if (font_info
->encoding
[charset
])
1759 /* Fixed encoding scheme. See fontset.h for the meaning of the
1760 encoding numbers. */
1761 int enc
= font_info
->encoding
[charset
];
1763 if ((enc
== 1 || enc
== 2)
1764 && CHARSET_DIMENSION (charset
) == 2)
1765 char2b
->byte1
|= 0x80;
1767 if (enc
== 1 || enc
== 3)
1768 char2b
->byte2
|= 0x80;
1774 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1775 char2b
->byte1
= sjis1
;
1776 char2b
->byte2
= sjis2
;
1781 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1783 return FONT_TYPE_UNKNOWN
;
1788 /***********************************************************************
1790 ***********************************************************************/
1793 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1794 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1795 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1797 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1798 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1799 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1800 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1801 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1802 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1803 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1804 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1805 unsigned long *, double, int));*/
1806 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1807 double, int, unsigned long));
1808 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1809 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1810 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1811 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1812 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1813 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1815 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1816 int, int, int, int, int, int,
1818 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1819 int, int, int, Rect
*));
1822 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1826 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1831 struct glyph_string
*s
;
1833 if (s
->font
== FRAME_FONT (s
->f
)
1834 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1835 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1837 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1840 /* Cursor on non-default face: must merge. */
1844 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1845 xgcv
.foreground
= s
->face
->background
;
1847 /* If the glyph would be invisible, try a different foreground. */
1848 if (xgcv
.foreground
== xgcv
.background
)
1849 xgcv
.foreground
= s
->face
->foreground
;
1850 if (xgcv
.foreground
== xgcv
.background
)
1851 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1852 if (xgcv
.foreground
== xgcv
.background
)
1853 xgcv
.foreground
= s
->face
->foreground
;
1855 /* Make sure the cursor is distinct from text in this face. */
1856 if (xgcv
.background
== s
->face
->background
1857 && xgcv
.foreground
== s
->face
->foreground
)
1859 xgcv
.background
= s
->face
->foreground
;
1860 xgcv
.foreground
= s
->face
->background
;
1863 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1864 xgcv
.font
= s
->font
;
1865 mask
= GCForeground
| GCBackground
| GCFont
;
1867 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1868 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1871 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1872 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1874 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1879 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1882 x_set_mouse_face_gc (s
)
1883 struct glyph_string
*s
;
1888 /* What face has to be used last for the mouse face? */
1889 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1890 face
= FACE_FROM_ID (s
->f
, face_id
);
1892 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1894 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1895 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1897 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1898 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1899 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1901 /* If font in this face is same as S->font, use it. */
1902 if (s
->font
== s
->face
->font
)
1903 s
->gc
= s
->face
->gc
;
1906 /* Otherwise construct scratch_cursor_gc with values from FACE
1911 xgcv
.background
= s
->face
->background
;
1912 xgcv
.foreground
= s
->face
->foreground
;
1913 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1914 xgcv
.font
= s
->font
;
1915 mask
= GCForeground
| GCBackground
| GCFont
;
1917 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1918 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1921 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1922 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1924 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1927 xassert (s
->gc
!= 0);
1931 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1932 Faces to use in the mode line have already been computed when the
1933 matrix was built, so there isn't much to do, here. */
1936 x_set_mode_line_face_gc (s
)
1937 struct glyph_string
*s
;
1939 s
->gc
= s
->face
->gc
;
1943 /* Set S->gc of glyph string S for drawing that glyph string. Set
1944 S->stippled_p to a non-zero value if the face of S has a stipple
1948 x_set_glyph_string_gc (s
)
1949 struct glyph_string
*s
;
1951 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1953 if (s
->hl
== DRAW_NORMAL_TEXT
)
1955 s
->gc
= s
->face
->gc
;
1956 s
->stippled_p
= s
->face
->stipple
!= 0;
1958 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1960 x_set_mode_line_face_gc (s
);
1961 s
->stippled_p
= s
->face
->stipple
!= 0;
1963 else if (s
->hl
== DRAW_CURSOR
)
1965 x_set_cursor_gc (s
);
1968 else if (s
->hl
== DRAW_MOUSE_FACE
)
1970 x_set_mouse_face_gc (s
);
1971 s
->stippled_p
= s
->face
->stipple
!= 0;
1973 else if (s
->hl
== DRAW_IMAGE_RAISED
1974 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1976 s
->gc
= s
->face
->gc
;
1977 s
->stippled_p
= s
->face
->stipple
!= 0;
1981 s
->gc
= s
->face
->gc
;
1982 s
->stippled_p
= s
->face
->stipple
!= 0;
1985 /* GC must have been set. */
1986 xassert (s
->gc
!= 0);
1990 /* Set clipping for output of glyph string S. S may be part of a mode
1991 line or menu if we don't have X toolkit support. */
1994 x_set_glyph_string_clipping (s
)
1995 struct glyph_string
*s
;
1998 get_glyph_string_clip_rect (s
, &r
);
1999 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
2004 Compute left and right overhang of glyph string S. If S is a glyph
2005 string for a composition, assume overhangs don't exist. */
2008 mac_compute_glyph_string_overhangs (s
)
2009 struct glyph_string
*s
;
2012 MacFontStruct
*font
= s
->font
;
2014 TextFont (font
->mac_fontnum
);
2015 TextSize (font
->mac_fontsize
);
2016 TextFace (font
->mac_fontface
);
2019 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2023 char *buf
= xmalloc (s
->nchars
);
2026 SetRect (&r
, 0, 0, 0, 0);
2029 for (i
= 0; i
< s
->nchars
; ++i
)
2030 buf
[i
] = s
->char2b
[i
].byte2
;
2031 QDTextBounds (s
->nchars
, buf
, &r
);
2036 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2037 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2041 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2044 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2045 struct glyph_string
*s
;
2050 xgcv
.foreground
= s
->gc
->background
;
2051 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2055 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2056 on Mac OS X because:
2057 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2058 into an offscreen graphics world first. So performance gain
2059 cannot be expected.)
2060 - It lowers rendering quality.
2061 - Some fonts leave garbage on cursor movement. */
2063 /* Draw the background of glyph_string S. If S->background_filled_p
2064 is non-zero don't draw it. FORCE_P non-zero means draw the
2065 background even if it wouldn't be drawn normally. This is used
2066 when a string preceding S draws into the background of S, or S
2067 contains the first component of a composition. */
2070 x_draw_glyph_string_background (s
, force_p
)
2071 struct glyph_string
*s
;
2074 /* Nothing to do if background has already been drawn or if it
2075 shouldn't be drawn in the first place. */
2076 if (!s
->background_filled_p
)
2078 int box_line_width
= max (s
->face
->box_line_width
, 0);
2080 #if 0 /* MAC_TODO: stipple */
2083 /* Fill background with a stipple pattern. */
2084 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2085 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2086 s
->y
+ box_line_width
,
2087 s
->background_width
,
2088 s
->height
- 2 * box_line_width
);
2089 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2090 s
->background_filled_p
= 1;
2095 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2096 || s
->font_not_found_p
2097 || s
->extends_to_end_of_line_p
2101 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2102 s
->background_width
,
2103 s
->height
- 2 * box_line_width
);
2104 s
->background_filled_p
= 1;
2110 /* Draw the foreground of glyph string S. */
2113 x_draw_glyph_string_foreground (s
)
2114 struct glyph_string
*s
;
2118 /* If first glyph of S has a left box line, start drawing the text
2119 of S to the right of that box line. */
2120 if (s
->face
->box
!= FACE_NO_BOX
2121 && s
->first_glyph
->left_box_line_p
)
2122 x
= s
->x
+ abs (s
->face
->box_line_width
);
2126 /* Draw characters of S as rectangles if S's font could not be
2128 if (s
->font_not_found_p
)
2130 for (i
= 0; i
< s
->nchars
; ++i
)
2132 struct glyph
*g
= s
->first_glyph
+ i
;
2133 mac_draw_rectangle (s
->display
, s
->window
,
2134 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2136 x
+= g
->pixel_width
;
2141 char *char1b
= (char *) s
->char2b
;
2142 int boff
= s
->font_info
->baseline_offset
;
2144 if (s
->font_info
->vertical_centering
)
2145 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2147 /* If we can use 8-bit functions, condense S->char2b. */
2149 for (i
= 0; i
< s
->nchars
; ++i
)
2150 char1b
[i
] = s
->char2b
[i
].byte2
;
2153 /* Draw text with XDrawString if background has already been
2154 filled. Otherwise, use XDrawImageString. (Note that
2155 XDrawImageString is usually faster than XDrawString.) Always
2156 use XDrawImageString when drawing the cursor so that there is
2157 no chance that characters under a box cursor are invisible. */
2158 if (s
->for_overlaps_p
2159 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2162 /* Draw characters with 16-bit or 8-bit functions. */
2164 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2165 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2167 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2168 s
->ybase
- boff
, char1b
, s
->nchars
);
2174 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2175 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2177 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2178 s
->ybase
- boff
, char1b
, s
->nchars
);
2184 /* Draw the foreground of composite glyph string S. */
2187 x_draw_composite_glyph_string_foreground (s
)
2188 struct glyph_string
*s
;
2192 /* If first glyph of S has a left box line, start drawing the text
2193 of S to the right of that box line. */
2194 if (s
->face
->box
!= FACE_NO_BOX
2195 && s
->first_glyph
->left_box_line_p
)
2196 x
= s
->x
+ abs (s
->face
->box_line_width
);
2200 /* S is a glyph string for a composition. S->gidx is the index of
2201 the first character drawn for glyphs of this composition.
2202 S->gidx == 0 means we are drawing the very first character of
2203 this composition. */
2205 /* Draw a rectangle for the composition if the font for the very
2206 first character of the composition could not be loaded. */
2207 if (s
->font_not_found_p
)
2210 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2211 s
->width
- 1, s
->height
- 1);
2215 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2216 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2217 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2218 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2224 #ifdef USE_X_TOOLKIT
2226 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2229 /* Return the frame on which widget WIDGET is used.. Abort if frame
2230 cannot be determined. */
2232 static struct frame
*
2233 x_frame_of_widget (widget
)
2236 struct x_display_info
*dpyinfo
;
2240 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2242 /* Find the top-level shell of the widget. Note that this function
2243 can be called when the widget is not yet realized, so XtWindow
2244 (widget) == 0. That's the reason we can't simply use
2245 x_any_window_to_frame. */
2246 while (!XtIsTopLevelShell (widget
))
2247 widget
= XtParent (widget
);
2249 /* Look for a frame with that top-level widget. Allocate the color
2250 on that frame to get the right gamma correction value. */
2251 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2252 if (GC_FRAMEP (XCAR (tail
))
2253 && (f
= XFRAME (XCAR (tail
)),
2254 (f
->output_data
.nothing
!= 1
2255 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2256 && f
->output_data
.x
->widget
== widget
)
2263 /* Allocate the color COLOR->pixel on the screen and display of
2264 widget WIDGET in colormap CMAP. If an exact match cannot be
2265 allocated, try the nearest color available. Value is non-zero
2266 if successful. This is called from lwlib. */
2269 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2274 struct frame
*f
= x_frame_of_widget (widget
);
2275 return x_alloc_nearest_color (f
, cmap
, color
);
2279 #endif /* USE_X_TOOLKIT */
2281 #if 0 /* MAC_TODO */
2283 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2284 CMAP. If an exact match can't be allocated, try the nearest color
2285 available. Value is non-zero if successful. Set *COLOR to the
2289 x_alloc_nearest_color (f
, cmap
, color
)
2294 Display
*display
= FRAME_X_DISPLAY (f
);
2295 Screen
*screen
= FRAME_X_SCREEN (f
);
2298 gamma_correct (f
, color
);
2299 rc
= XAllocColor (display
, cmap
, color
);
2302 /* If we got to this point, the colormap is full, so we're going
2303 to try to get the next closest color. The algorithm used is
2304 a least-squares matching, which is what X uses for closest
2305 color matching with StaticColor visuals. */
2307 unsigned long nearest_delta
= ~0;
2308 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2309 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2311 for (i
= 0; i
< ncells
; ++i
)
2313 XQueryColors (display
, cmap
, cells
, ncells
);
2315 for (nearest
= i
= 0; i
< ncells
; ++i
)
2317 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2318 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2319 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2320 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2322 if (delta
< nearest_delta
)
2325 nearest_delta
= delta
;
2329 color
->red
= cells
[nearest
].red
;
2330 color
->green
= cells
[nearest
].green
;
2331 color
->blue
= cells
[nearest
].blue
;
2332 rc
= XAllocColor (display
, cmap
, color
);
2335 #ifdef DEBUG_X_COLORS
2337 register_color (color
->pixel
);
2338 #endif /* DEBUG_X_COLORS */
2344 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2345 It's necessary to do this instead of just using PIXEL directly to
2346 get color reference counts right. */
2349 x_copy_color (f
, pixel
)
2351 unsigned long pixel
;
2355 color
.pixel
= pixel
;
2357 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2358 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2360 #ifdef DEBUG_X_COLORS
2361 register_color (pixel
);
2367 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2368 It's necessary to do this instead of just using PIXEL directly to
2369 get color reference counts right. */
2372 x_copy_dpy_color (dpy
, cmap
, pixel
)
2375 unsigned long pixel
;
2379 color
.pixel
= pixel
;
2381 XQueryColor (dpy
, cmap
, &color
);
2382 XAllocColor (dpy
, cmap
, &color
);
2384 #ifdef DEBUG_X_COLORS
2385 register_color (pixel
);
2390 #endif /* MAC_TODO */
2393 /* Brightness beyond which a color won't have its highlight brightness
2396 Nominally, highlight colors for `3d' faces are calculated by
2397 brightening an object's color by a constant scale factor, but this
2398 doesn't yield good results for dark colors, so for colors who's
2399 brightness is less than this value (on a scale of 0-255) have to
2400 use an additional additive factor.
2402 The value here is set so that the default menu-bar/mode-line color
2403 (grey75) will not have its highlights changed at all. */
2404 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2407 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2408 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2409 If this produces the same color as COLOR, try a color where all RGB
2410 values have DELTA added. Return the allocated color in *COLOR.
2411 DISPLAY is the X display, CMAP is the colormap to operate on.
2412 Value is non-zero if successful. */
2415 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2417 unsigned long *color
;
2424 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2427 /* Change RGB values by specified FACTOR. Avoid overflow! */
2428 xassert (factor
>= 0);
2429 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2430 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2431 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2433 /* Calculate brightness of COLOR. */
2434 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2435 + BLUE_FROM_ULONG (*color
)) / 6;
2437 /* We only boost colors that are darker than
2438 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2439 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2440 /* Make an additive adjustment to NEW, because it's dark enough so
2441 that scaling by FACTOR alone isn't enough. */
2443 /* How far below the limit this color is (0 - 1, 1 being darker). */
2444 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2445 /* The additive adjustment. */
2446 int min_delta
= delta
* dimness
* factor
/ 2;
2449 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2450 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2451 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2453 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2454 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2455 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2459 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2460 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2461 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2463 /* MAC_TODO: Map to palette and retry with delta if same? */
2464 /* MAC_TODO: Free colors (if using palette)? */
2475 /* Set up the foreground color for drawing relief lines of glyph
2476 string S. RELIEF is a pointer to a struct relief containing the GC
2477 with which lines will be drawn. Use a color that is FACTOR or
2478 DELTA lighter or darker than the relief's background which is found
2479 in S->f->output_data.x->relief_background. If such a color cannot
2480 be allocated, use DEFAULT_PIXEL, instead. */
2483 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2485 struct relief
*relief
;
2488 unsigned long default_pixel
;
2491 struct mac_output
*di
= f
->output_data
.mac
;
2492 unsigned long mask
= GCForeground
;
2493 unsigned long pixel
;
2494 unsigned long background
= di
->relief_background
;
2495 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2497 /* MAC_TODO: Free colors (if using palette)? */
2499 /* Allocate new color. */
2500 xgcv
.foreground
= default_pixel
;
2502 if (dpyinfo
->n_planes
!= 1
2503 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2505 relief
->allocated_p
= 1;
2506 xgcv
.foreground
= relief
->pixel
= pixel
;
2509 if (relief
->gc
== 0)
2511 #if 0 /* MAC_TODO: stipple */
2512 xgcv
.stipple
= dpyinfo
->gray
;
2515 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2518 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2522 /* Set up colors for the relief lines around glyph string S. */
2525 x_setup_relief_colors (s
)
2526 struct glyph_string
*s
;
2528 struct mac_output
*di
= s
->f
->output_data
.mac
;
2529 unsigned long color
;
2531 if (s
->face
->use_box_color_for_shadows_p
)
2532 color
= s
->face
->box_color
;
2533 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2535 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2536 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2541 /* Get the background color of the face. */
2542 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2543 color
= xgcv
.background
;
2546 if (di
->white_relief
.gc
== 0
2547 || color
!= di
->relief_background
)
2549 di
->relief_background
= color
;
2550 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2551 WHITE_PIX_DEFAULT (s
->f
));
2552 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2553 BLACK_PIX_DEFAULT (s
->f
));
2558 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2559 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2560 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2561 relief. LEFT_P non-zero means draw a relief on the left side of
2562 the rectangle. RIGHT_P non-zero means draw a relief on the right
2563 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2567 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2568 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2570 int left_x
, top_y
, right_x
, bottom_y
, width
;
2571 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2574 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2575 Window window
= FRAME_MAC_WINDOW (f
);
2580 gc
= f
->output_data
.mac
->white_relief
.gc
;
2582 gc
= f
->output_data
.mac
->black_relief
.gc
;
2583 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2587 for (i
= 0; i
< width
; ++i
)
2588 XDrawLine (dpy
, window
, gc
,
2589 left_x
+ i
* left_p
, top_y
+ i
,
2590 right_x
- i
* right_p
, top_y
+ i
);
2594 for (i
= 0; i
< width
; ++i
)
2595 XDrawLine (dpy
, window
, gc
,
2596 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2598 mac_reset_clipping (dpy
, window
);
2600 gc
= f
->output_data
.mac
->black_relief
.gc
;
2602 gc
= f
->output_data
.mac
->white_relief
.gc
;
2603 mac_set_clip_rectangle (dpy
, window
,
2608 for (i
= 0; i
< width
; ++i
)
2609 XDrawLine (dpy
, window
, gc
,
2610 left_x
+ i
* left_p
, bottom_y
- i
,
2611 right_x
- i
* right_p
, bottom_y
- i
);
2615 for (i
= 0; i
< width
; ++i
)
2616 XDrawLine (dpy
, window
, gc
,
2617 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2619 mac_reset_clipping (dpy
, window
);
2623 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2624 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2625 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2626 left side of the rectangle. RIGHT_P non-zero means draw a line
2627 on the right side of the rectangle. CLIP_RECT is the clipping
2628 rectangle to use when drawing. */
2631 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2632 left_p
, right_p
, clip_rect
)
2633 struct glyph_string
*s
;
2634 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2639 xgcv
.foreground
= s
->face
->box_color
;
2640 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2643 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2644 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2648 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2649 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2652 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2653 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2657 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2658 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2660 mac_reset_clipping (s
->display
, s
->window
);
2664 /* Draw a box around glyph string S. */
2667 x_draw_glyph_string_box (s
)
2668 struct glyph_string
*s
;
2670 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2671 int left_p
, right_p
;
2672 struct glyph
*last_glyph
;
2675 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2676 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2677 : window_box_right (s
->w
, s
->area
));
2679 /* The glyph that may have a right box line. */
2680 last_glyph
= (s
->cmp
|| s
->img
2682 : s
->first_glyph
+ s
->nchars
- 1);
2684 width
= abs (s
->face
->box_line_width
);
2685 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2687 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2689 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2691 bottom_y
= top_y
+ s
->height
- 1;
2693 left_p
= (s
->first_glyph
->left_box_line_p
2694 || (s
->hl
== DRAW_MOUSE_FACE
2696 || s
->prev
->hl
!= s
->hl
)));
2697 right_p
= (last_glyph
->right_box_line_p
2698 || (s
->hl
== DRAW_MOUSE_FACE
2700 || s
->next
->hl
!= s
->hl
)));
2702 get_glyph_string_clip_rect (s
, &clip_rect
);
2704 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2705 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2706 left_p
, right_p
, &clip_rect
);
2709 x_setup_relief_colors (s
);
2710 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2711 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2716 /* Draw foreground of image glyph string S. */
2719 x_draw_image_foreground (s
)
2720 struct glyph_string
*s
;
2723 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2725 /* If first glyph of S has a left box line, start drawing it to the
2726 right of that line. */
2727 if (s
->face
->box
!= FACE_NO_BOX
2728 && s
->first_glyph
->left_box_line_p
2730 x
+= abs (s
->face
->box_line_width
);
2732 /* If there is a margin around the image, adjust x- and y-position
2734 if (s
->slice
.x
== 0)
2735 x
+= s
->img
->hmargin
;
2736 if (s
->slice
.y
== 0)
2737 y
+= s
->img
->vmargin
;
2741 x_set_glyph_string_clipping (s
);
2744 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2745 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2746 s
->slice
.width
, s
->slice
.height
, x
, y
);
2749 mac_copy_area (s
->display
, s
->img
->pixmap
,
2750 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2751 s
->slice
.width
, s
->slice
.height
, x
, y
);
2753 /* When the image has a mask, we can expect that at
2754 least part of a mouse highlight or a block cursor will
2755 be visible. If the image doesn't have a mask, make
2756 a block cursor visible by drawing a rectangle around
2757 the image. I believe it's looking better if we do
2758 nothing here for mouse-face. */
2759 if (s
->hl
== DRAW_CURSOR
)
2761 int r
= s
->img
->relief
;
2763 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2765 s
->slice
.width
+ r
*2 - 1,
2766 s
->slice
.height
+ r
*2 - 1);
2771 /* Draw a rectangle if image could not be loaded. */
2772 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2773 s
->slice
.width
- 1, s
->slice
.height
- 1);
2777 /* Draw a relief around the image glyph string S. */
2780 x_draw_image_relief (s
)
2781 struct glyph_string
*s
;
2783 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2786 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2788 /* If first glyph of S has a left box line, start drawing it to the
2789 right of that line. */
2790 if (s
->face
->box
!= FACE_NO_BOX
2791 && s
->first_glyph
->left_box_line_p
2793 x
+= abs (s
->face
->box_line_width
);
2795 /* If there is a margin around the image, adjust x- and y-position
2797 if (s
->slice
.x
== 0)
2798 x
+= s
->img
->hmargin
;
2799 if (s
->slice
.y
== 0)
2800 y
+= s
->img
->vmargin
;
2802 if (s
->hl
== DRAW_IMAGE_SUNKEN
2803 || s
->hl
== DRAW_IMAGE_RAISED
)
2805 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2806 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2810 thick
= abs (s
->img
->relief
);
2811 raised_p
= s
->img
->relief
> 0;
2816 x1
= x
+ s
->slice
.width
+ thick
- 1;
2817 y1
= y
+ s
->slice
.height
+ thick
- 1;
2819 x_setup_relief_colors (s
);
2820 get_glyph_string_clip_rect (s
, &r
);
2821 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2823 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2825 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2830 #if 0 /* TODO: figure out if we need to do this on Mac. */
2831 /* Draw the foreground of image glyph string S to PIXMAP. */
2834 x_draw_image_foreground_1 (s
, pixmap
)
2835 struct glyph_string
*s
;
2839 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2841 /* If first glyph of S has a left box line, start drawing it to the
2842 right of that line. */
2843 if (s
->face
->box
!= FACE_NO_BOX
2844 && s
->first_glyph
->left_box_line_p
2846 x
+= abs (s
->face
->box_line_width
);
2848 /* If there is a margin around the image, adjust x- and y-position
2850 if (s
->slice
.x
== 0)
2851 x
+= s
->img
->hmargin
;
2852 if (s
->slice
.y
== 0)
2853 y
+= s
->img
->vmargin
;
2858 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2859 s
->img
->mask
, pixmap
, s
->gc
,
2860 s
->slice
.x
, s
->slice
.y
,
2861 s
->slice
.width
, s
->slice
.height
,
2865 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2866 s
->slice
.x
, s
->slice
.y
,
2867 s
->slice
.width
, s
->slice
.height
,
2870 /* When the image has a mask, we can expect that at
2871 least part of a mouse highlight or a block cursor will
2872 be visible. If the image doesn't have a mask, make
2873 a block cursor visible by drawing a rectangle around
2874 the image. I believe it's looking better if we do
2875 nothing here for mouse-face. */
2876 if (s
->hl
== DRAW_CURSOR
)
2878 int r
= s
->img
->relief
;
2880 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2881 s
->slice
.width
+ r
*2 - 1,
2882 s
->slice
.height
+ r
*2 - 1);
2887 /* Draw a rectangle if image could not be loaded. */
2888 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2889 s
->slice
.width
- 1, s
->slice
.height
- 1);
2894 /* Draw part of the background of glyph string S. X, Y, W, and H
2895 give the rectangle to draw. */
2898 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2899 struct glyph_string
*s
;
2902 #if 0 /* MAC_TODO: stipple */
2905 /* Fill background with a stipple pattern. */
2906 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2907 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2908 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2911 #endif /* MAC_TODO */
2912 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2916 /* Draw image glyph string S.
2919 s->x +-------------------------
2922 | +-------------------------
2925 | | +-------------------
2931 x_draw_image_glyph_string (s
)
2932 struct glyph_string
*s
;
2935 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2936 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2940 height
= s
->height
- 2 * box_line_vwidth
;
2943 /* Fill background with face under the image. Do it only if row is
2944 taller than image or if image has a clip mask to reduce
2946 s
->stippled_p
= s
->face
->stipple
!= 0;
2947 if (height
> s
->slice
.height
2951 || s
->img
->pixmap
== 0
2952 || s
->width
!= s
->background_width
)
2955 if (s
->first_glyph
->left_box_line_p
2957 x
+= box_line_hwidth
;
2960 if (s
->slice
.y
== 0)
2961 y
+= box_line_vwidth
;
2963 #if 0 /* TODO: figure out if we need to do this on Mac. */
2966 /* Create a pixmap as large as the glyph string. Fill it
2967 with the background color. Copy the image to it, using
2968 its mask. Copy the temporary pixmap to the display. */
2969 int depth
= one_mac_display_info
.n_planes
;
2971 /* Create a pixmap as large as the glyph string. */
2972 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2973 s
->background_width
,
2976 /* Fill the pixmap with the background color/stipple. */
2977 #if 0 /* TODO: stipple */
2980 /* Fill background with a stipple pattern. */
2981 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2982 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2983 0, 0, s
->background_width
, s
->height
);
2984 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2990 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2992 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2993 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2994 0, 0, s
->background_width
,
2996 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3001 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3003 s
->background_filled_p
= 1;
3006 /* Draw the foreground. */
3007 #if 0 /* TODO: figure out if we need to do this on Mac. */
3010 x_draw_image_foreground_1 (s
, pixmap
);
3011 x_set_glyph_string_clipping (s
);
3012 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
3013 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3014 mac_reset_clipping (s
->display
, s
->window
);
3015 XFreePixmap (s
->display
, pixmap
);
3019 x_draw_image_foreground (s
);
3021 /* If we must draw a relief around the image, do it. */
3023 || s
->hl
== DRAW_IMAGE_RAISED
3024 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3025 x_draw_image_relief (s
);
3029 /* Draw stretch glyph string S. */
3032 x_draw_stretch_glyph_string (s
)
3033 struct glyph_string
*s
;
3035 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3036 s
->stippled_p
= s
->face
->stipple
!= 0;
3038 if (s
->hl
== DRAW_CURSOR
3039 && !x_stretch_cursor_p
)
3041 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3042 as wide as the stretch glyph. */
3043 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3046 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3048 /* Clear rest using the GC of the original non-cursor face. */
3049 if (width
< s
->background_width
)
3051 int x
= s
->x
+ width
, y
= s
->y
;
3052 int w
= s
->background_width
- width
, h
= s
->height
;
3056 if (s
->row
->mouse_face_p
3057 && cursor_in_mouse_face_p (s
->w
))
3059 x_set_mouse_face_gc (s
);
3065 get_glyph_string_clip_rect (s
, &r
);
3066 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3068 #if 0 /* MAC_TODO: stipple */
3069 if (s
->face
->stipple
)
3071 /* Fill background with a stipple pattern. */
3072 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3073 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3074 XSetFillStyle (s
->display
, gc
, FillSolid
);
3077 #endif /* MAC_TODO */
3080 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3081 XSetForeground (s
->display
, gc
, xgcv
.background
);
3082 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3083 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3086 mac_reset_clipping (s
->display
, s
->window
);
3089 else if (!s
->background_filled_p
)
3090 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3093 s
->background_filled_p
= 1;
3097 /* Draw glyph string S. */
3100 x_draw_glyph_string (s
)
3101 struct glyph_string
*s
;
3103 int relief_drawn_p
= 0;
3105 /* If S draws into the background of its successor that does not
3106 draw a cursor, draw the background of the successor first so that
3107 S can draw into it. This makes S->next use XDrawString instead
3108 of XDrawImageString. */
3109 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
3110 && s
->next
->hl
!= DRAW_CURSOR
)
3112 xassert (s
->next
->img
== NULL
);
3113 x_set_glyph_string_gc (s
->next
);
3114 x_set_glyph_string_clipping (s
->next
);
3115 x_draw_glyph_string_background (s
->next
, 1);
3118 /* Set up S->gc, set clipping and draw S. */
3119 x_set_glyph_string_gc (s
);
3121 /* Draw relief (if any) in advance for char/composition so that the
3122 glyph string can be drawn over it. */
3123 if (!s
->for_overlaps_p
3124 && s
->face
->box
!= FACE_NO_BOX
3125 && (s
->first_glyph
->type
== CHAR_GLYPH
3126 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3129 x_set_glyph_string_clipping (s
);
3130 x_draw_glyph_string_background (s
, 1);
3131 x_draw_glyph_string_box (s
);
3132 x_set_glyph_string_clipping (s
);
3136 x_set_glyph_string_clipping (s
);
3138 switch (s
->first_glyph
->type
)
3141 x_draw_image_glyph_string (s
);
3145 x_draw_stretch_glyph_string (s
);
3149 if (s
->for_overlaps_p
)
3150 s
->background_filled_p
= 1;
3152 x_draw_glyph_string_background (s
, 0);
3153 x_draw_glyph_string_foreground (s
);
3156 case COMPOSITE_GLYPH
:
3157 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3158 s
->background_filled_p
= 1;
3160 x_draw_glyph_string_background (s
, 1);
3161 x_draw_composite_glyph_string_foreground (s
);
3168 if (!s
->for_overlaps_p
)
3170 /* Draw underline. */
3171 if (s
->face
->underline_p
)
3173 unsigned long h
= 1;
3174 unsigned long dy
= s
->height
- h
;
3176 if (s
->face
->underline_defaulted_p
)
3177 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3182 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3183 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3184 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3186 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3190 /* Draw overline. */
3191 if (s
->face
->overline_p
)
3193 unsigned long dy
= 0, h
= 1;
3195 if (s
->face
->overline_color_defaulted_p
)
3196 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3201 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3202 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3203 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3205 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3209 /* Draw strike-through. */
3210 if (s
->face
->strike_through_p
)
3212 unsigned long h
= 1;
3213 unsigned long dy
= (s
->height
- h
) / 2;
3215 if (s
->face
->strike_through_color_defaulted_p
)
3216 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3221 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3222 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3223 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3225 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3229 /* Draw relief if not yet drawn. */
3230 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3231 x_draw_glyph_string_box (s
);
3234 /* Reset clipping. */
3235 mac_reset_clipping (s
->display
, s
->window
);
3238 /* Shift display to make room for inserted glyphs. */
3241 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3243 int x
, y
, width
, height
, shift_by
;
3245 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3246 f
->output_data
.mac
->normal_gc
,
3247 x
, y
, width
, height
,
3251 /* Delete N glyphs at the nominal cursor position. Not implemented
3262 /* Clear entire frame. If updating_frame is non-null, clear that
3263 frame. Otherwise clear the selected frame. */
3273 f
= SELECTED_FRAME ();
3275 /* Clearing the frame will erase any cursor, so mark them all as no
3277 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3278 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3279 output_cursor
.x
= -1;
3281 /* We don't set the output cursor here because there will always
3282 follow an explicit cursor_to. */
3284 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3286 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3287 /* We have to clear the scroll bars, too. If we have changed
3288 colors or something like that, then they should be notified. */
3289 x_scroll_bar_clear (f
);
3292 XFlush (FRAME_MAC_DISPLAY (f
));
3298 /* Invert the middle quarter of the frame for .15 sec. */
3300 /* We use the select system call to do the waiting, so we have to make
3301 sure it's available. If it isn't, we just won't do visual bells. */
3303 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3306 /* Subtract the `struct timeval' values X and Y, storing the result in
3307 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3310 timeval_subtract (result
, x
, y
)
3311 struct timeval
*result
, x
, y
;
3313 /* Perform the carry for the later subtraction by updating y. This
3314 is safer because on some systems the tv_sec member is unsigned. */
3315 if (x
.tv_usec
< y
.tv_usec
)
3317 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3318 y
.tv_usec
-= 1000000 * nsec
;
3322 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3324 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3325 y
.tv_usec
+= 1000000 * nsec
;
3329 /* Compute the time remaining to wait. tv_usec is certainly
3331 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3332 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3334 /* Return indication of whether the result should be considered
3336 return x
.tv_sec
< y
.tv_sec
;
3348 struct timeval wakeup
;
3350 EMACS_GET_TIME (wakeup
);
3352 /* Compute time to wait until, propagating carry from usecs. */
3353 wakeup
.tv_usec
+= 150000;
3354 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3355 wakeup
.tv_usec
%= 1000000;
3357 /* Keep waiting until past the time wakeup. */
3360 struct timeval timeout
;
3362 EMACS_GET_TIME (timeout
);
3364 /* In effect, timeout = wakeup - timeout.
3365 Break if result would be negative. */
3366 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3369 /* Try to wait that long--but we might wake up sooner. */
3370 select (0, NULL
, NULL
, NULL
, &timeout
);
3379 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3382 /* Make audible bell. */
3387 struct frame
*f
= SELECTED_FRAME ();
3389 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3397 XFlush (FRAME_MAC_DISPLAY (f
));
3404 /* Specify how many text lines, from the top of the window,
3405 should be affected by insert-lines and delete-lines operations.
3406 This, and those operations, are used only within an update
3407 that is bounded by calls to x_update_begin and x_update_end. */
3410 XTset_terminal_window (n
)
3413 /* This function intentionally left blank. */
3418 /***********************************************************************
3420 ***********************************************************************/
3422 /* Perform an insert-lines or delete-lines operation, inserting N
3423 lines or deleting -N lines at vertical position VPOS. */
3426 x_ins_del_lines (vpos
, n
)
3433 /* Scroll part of the display as described by RUN. */
3436 x_scroll_run (w
, run
)
3440 struct frame
*f
= XFRAME (w
->frame
);
3441 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3443 /* Get frame-relative bounding box of the text display area of W,
3444 without mode lines. Include in this box the left and right
3446 window_box (w
, -1, &x
, &y
, &width
, &height
);
3448 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3449 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3450 bottom_y
= y
+ height
;
3454 /* Scrolling up. Make sure we don't copy part of the mode
3455 line at the bottom. */
3456 if (from_y
+ run
->height
> bottom_y
)
3457 height
= bottom_y
- from_y
;
3459 height
= run
->height
;
3463 /* Scolling down. Make sure we don't copy over the mode line.
3465 if (to_y
+ run
->height
> bottom_y
)
3466 height
= bottom_y
- to_y
;
3468 height
= run
->height
;
3473 /* Cursor off. Will be switched on again in x_update_window_end. */
3477 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3478 f
->output_data
.mac
->normal_gc
,
3488 /***********************************************************************
3490 ***********************************************************************/
3497 x_update_cursor (f
, 1);
3501 frame_unhighlight (f
)
3504 x_update_cursor (f
, 1);
3507 /* The focus has changed. Update the frames as necessary to reflect
3508 the new situation. Note that we can't change the selected frame
3509 here, because the Lisp code we are interrupting might become confused.
3510 Each event gets marked with the frame in which it occurred, so the
3511 Lisp code can tell when the switch took place by examining the events. */
3514 x_new_focus_frame (dpyinfo
, frame
)
3515 struct x_display_info
*dpyinfo
;
3516 struct frame
*frame
;
3518 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3520 if (frame
!= dpyinfo
->x_focus_frame
)
3522 /* Set this before calling other routines, so that they see
3523 the correct value of x_focus_frame. */
3524 dpyinfo
->x_focus_frame
= frame
;
3526 if (old_focus
&& old_focus
->auto_lower
)
3527 x_lower_frame (old_focus
);
3530 selected_frame
= frame
;
3531 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3533 Fselect_window (selected_frame
->selected_window
, Qnil
);
3534 choose_minibuf_frame ();
3537 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3538 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3540 pending_autoraise_frame
= 0;
3543 x_frame_rehighlight (dpyinfo
);
3546 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3549 x_mouse_leave (dpyinfo
)
3550 struct x_display_info
*dpyinfo
;
3552 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3555 /* The focus has changed, or we have redirected a frame's focus to
3556 another frame (this happens when a frame uses a surrogate
3557 mini-buffer frame). Shift the highlight as appropriate.
3559 The FRAME argument doesn't necessarily have anything to do with which
3560 frame is being highlighted or un-highlighted; we only use it to find
3561 the appropriate X display info. */
3564 XTframe_rehighlight (frame
)
3565 struct frame
*frame
;
3567 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3571 x_frame_rehighlight (dpyinfo
)
3572 struct x_display_info
*dpyinfo
;
3574 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3576 if (dpyinfo
->x_focus_frame
)
3578 dpyinfo
->x_highlight_frame
3579 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3580 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3581 : dpyinfo
->x_focus_frame
);
3582 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3584 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3585 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3589 dpyinfo
->x_highlight_frame
= 0;
3591 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3594 frame_unhighlight (old_highlight
);
3595 if (dpyinfo
->x_highlight_frame
)
3596 frame_highlight (dpyinfo
->x_highlight_frame
);
3602 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3604 #if 0 /* MAC_TODO */
3605 /* Initialize mode_switch_bit and modifier_meaning. */
3607 x_find_modifier_meanings (dpyinfo
)
3608 struct x_display_info
*dpyinfo
;
3610 int min_code
, max_code
;
3613 XModifierKeymap
*mods
;
3615 dpyinfo
->meta_mod_mask
= 0;
3616 dpyinfo
->shift_lock_mask
= 0;
3617 dpyinfo
->alt_mod_mask
= 0;
3618 dpyinfo
->super_mod_mask
= 0;
3619 dpyinfo
->hyper_mod_mask
= 0;
3622 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3624 min_code
= dpyinfo
->display
->min_keycode
;
3625 max_code
= dpyinfo
->display
->max_keycode
;
3628 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3629 min_code
, max_code
- min_code
+ 1,
3631 mods
= XGetModifierMapping (dpyinfo
->display
);
3633 /* Scan the modifier table to see which modifier bits the Meta and
3634 Alt keysyms are on. */
3636 int row
, col
; /* The row and column in the modifier table. */
3638 for (row
= 3; row
< 8; row
++)
3639 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3642 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3644 /* Zeroes are used for filler. Skip them. */
3648 /* Are any of this keycode's keysyms a meta key? */
3652 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3654 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3660 dpyinfo
->meta_mod_mask
|= (1 << row
);
3665 dpyinfo
->alt_mod_mask
|= (1 << row
);
3670 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3675 dpyinfo
->super_mod_mask
|= (1 << row
);
3679 /* Ignore this if it's not on the lock modifier. */
3680 if ((1 << row
) == LockMask
)
3681 dpyinfo
->shift_lock_mask
= LockMask
;
3689 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3690 if (! dpyinfo
->meta_mod_mask
)
3692 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3693 dpyinfo
->alt_mod_mask
= 0;
3696 /* If some keys are both alt and meta,
3697 make them just meta, not alt. */
3698 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3700 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3703 XFree ((char *) syms
);
3704 XFreeModifiermap (mods
);
3707 #endif /* MAC_TODO */
3709 /* Convert between the modifier bits X uses and the modifier bits
3713 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3714 struct x_display_info
*dpyinfo
;
3715 unsigned short state
;
3717 return (((state
& shiftKey
) ? shift_modifier
: 0)
3718 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3719 | ((state
& cmdKey
) ? meta_modifier
: 0)
3720 | ((state
& optionKey
) ? alt_modifier
: 0));
3723 #if 0 /* MAC_TODO */
3724 static unsigned short
3725 x_emacs_to_x_modifiers (dpyinfo
, state
)
3726 struct x_display_info
*dpyinfo
;
3729 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3730 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3731 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3732 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3733 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3734 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3736 #endif /* MAC_TODO */
3738 /* Convert a keysym to its name. */
3741 x_get_keysym_name (keysym
)
3748 value
= XKeysymToString (keysym
);
3760 /* Mouse clicks and mouse movement. Rah. */
3762 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3764 If the event is a button press, then note that we have grabbed
3768 construct_mouse_click (result
, event
, f
)
3769 struct input_event
*result
;
3775 result
->kind
= MOUSE_CLICK_EVENT
;
3776 result
->code
= 0; /* only one mouse button */
3777 result
->timestamp
= event
->when
;
3778 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3780 mouseLoc
= event
->where
;
3782 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3784 GlobalToLocal (&mouseLoc
);
3785 XSETINT (result
->x
, mouseLoc
.h
);
3786 XSETINT (result
->y
, mouseLoc
.v
);
3788 XSETFRAME (result
->frame_or_window
, f
);
3796 /* Function to report a mouse movement to the mainstream Emacs code.
3797 The input handler calls this.
3799 We have received a mouse movement event, which is given in *event.
3800 If the mouse is over a different glyph than it was last time, tell
3801 the mainstream emacs code by setting mouse_moved. If not, ask for
3802 another motion event, so we can check again the next time it moves. */
3804 static Point last_mouse_motion_position
;
3805 static Lisp_Object last_mouse_motion_frame
;
3808 note_mouse_movement (frame
, pos
)
3812 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3813 #if TARGET_API_MAC_CARBON
3817 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3818 last_mouse_motion_position
= *pos
;
3819 XSETFRAME (last_mouse_motion_frame
, frame
);
3821 #if TARGET_API_MAC_CARBON
3822 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3824 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3827 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3828 /* This case corresponds to LeaveNotify in X11. */
3830 /* If we move outside the frame, then we're certainly no
3831 longer on any text in the frame. */
3832 clear_mouse_face (dpyinfo
);
3833 dpyinfo
->mouse_face_mouse_frame
= 0;
3834 if (!dpyinfo
->grabbed
)
3835 rif
->define_frame_cursor (frame
,
3836 frame
->output_data
.mac
->nontext_cursor
);
3839 /* Has the mouse moved off the glyph it was on at the last sighting? */
3840 else if (pos
->h
< last_mouse_glyph
.left
3841 || pos
->h
>= last_mouse_glyph
.right
3842 || pos
->v
< last_mouse_glyph
.top
3843 || pos
->v
>= last_mouse_glyph
.bottom
)
3845 frame
->mouse_moved
= 1;
3846 last_mouse_scroll_bar
= Qnil
;
3847 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3851 /* This is used for debugging, to turn off note_mouse_highlight. */
3853 int disable_mouse_highlight
;
3857 /************************************************************************
3859 ************************************************************************/
3861 static struct scroll_bar
*x_window_to_scroll_bar ();
3862 static void x_scroll_bar_report_motion ();
3863 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3866 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3869 redo_mouse_highlight ()
3871 if (!NILP (last_mouse_motion_frame
)
3872 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3873 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3874 last_mouse_motion_position
.h
,
3875 last_mouse_motion_position
.v
);
3879 /* Try to determine frame pixel position and size of the glyph under
3880 frame pixel coordinates X/Y on frame F . Return the position and
3881 size in *RECT. Value is non-zero if we could compute these
3885 glyph_rect (f
, x
, y
, rect
)
3892 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3896 struct window
*w
= XWINDOW (window
);
3897 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3898 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3900 for (; r
< end
&& r
->enabled_p
; ++r
)
3901 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3903 /* Found the row at y. */
3904 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3905 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3908 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3909 rect
->bottom
= rect
->top
+ r
->height
;
3913 /* x is to the left of the first glyph in the row. */
3914 /* Shouldn't this be a pixel value?
3915 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3917 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3918 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3922 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3923 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3925 /* x is on a glyph. */
3926 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3927 rect
->right
= rect
->left
+ g
->pixel_width
;
3931 /* x is to the right of the last glyph in the row. */
3932 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3933 /* Shouldn't this be a pixel value?
3934 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3936 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3941 /* The y is not on any row. */
3945 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3947 /* Record the position of the mouse in last_mouse_glyph. */
3949 remember_mouse_glyph (f1
, gx
, gy
)
3953 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3955 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3956 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3958 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3959 round down even for negative values. */
3965 /* This was the original code from XTmouse_position, but it seems
3966 to give the position of the glyph diagonally next to the one
3967 the mouse is over. */
3968 gx
= (gx
+ width
- 1) / width
* width
;
3969 gy
= (gy
+ height
- 1) / height
* height
;
3971 gx
= gx
/ width
* width
;
3972 gy
= gy
/ height
* height
;
3975 last_mouse_glyph
.left
= gx
;
3976 last_mouse_glyph
.top
= gy
;
3977 last_mouse_glyph
.right
= gx
+ width
;
3978 last_mouse_glyph
.bottom
= gy
+ height
;
3984 front_emacs_window ()
3986 #if TARGET_API_MAC_CARBON
3987 WindowPtr wp
= GetFrontWindowOfClass (kDocumentWindowClass
, true);
3989 while (wp
&& !is_emacs_window (wp
))
3990 wp
= GetNextWindowOfClass (wp
, kDocumentWindowClass
, true);
3992 WindowPtr wp
= FrontWindow ();
3994 while (wp
&& (wp
== tip_window
|| !is_emacs_window (wp
)))
3995 wp
= GetNextWindow (wp
);
4001 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
4003 /* Return the current position of the mouse.
4004 *fp should be a frame which indicates which display to ask about.
4006 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4007 and *part to the frame, window, and scroll bar part that the mouse
4008 is over. Set *x and *y to the portion and whole of the mouse's
4009 position on the scroll bar.
4011 If the mouse movement started elsewhere, set *fp to the frame the
4012 mouse is on, *bar_window to nil, and *x and *y to the character cell
4015 Set *time to the server time-stamp for the time at which the mouse
4016 was at this position.
4018 Don't store anything if we don't have a valid set of values to report.
4020 This clears the mouse_moved flag, so we can wait for the next mouse
4024 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4027 Lisp_Object
*bar_window
;
4028 enum scroll_bar_part
*part
;
4030 unsigned long *time
;
4033 int ignore1
, ignore2
;
4034 WindowPtr wp
= front_emacs_window ();
4036 Lisp_Object frame
, tail
;
4038 if (is_emacs_window(wp
))
4039 f
= mac_window_to_frame (wp
);
4043 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4044 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4047 /* Clear the mouse-moved flag for every frame on this display. */
4048 FOR_EACH_FRAME (tail
, frame
)
4049 XFRAME (frame
)->mouse_moved
= 0;
4051 last_mouse_scroll_bar
= Qnil
;
4053 SetPortWindowPort (wp
);
4055 GetMouse (&mouse_pos
);
4057 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4058 &last_mouse_glyph
, insist
);
4061 *part
= scroll_bar_handle
;
4063 XSETINT (*x
, mouse_pos
.h
);
4064 XSETINT (*y
, mouse_pos
.v
);
4065 *time
= last_mouse_movement_time
;
4072 /***********************************************************************
4074 ***********************************************************************/
4076 /* Handle mouse button event on the tool-bar of frame F, at
4077 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4081 mac_handle_tool_bar_click (f
, button_event
)
4083 EventRecord
*button_event
;
4085 int x
= button_event
->where
.h
;
4086 int y
= button_event
->where
.v
;
4088 if (button_event
->what
== mouseDown
)
4089 handle_tool_bar_click (f
, x
, y
, 1, 0);
4091 handle_tool_bar_click (f
, x
, y
, 0,
4092 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f
),
4093 button_event
->modifiers
));
4097 /************************************************************************
4098 Scroll bars, general
4099 ************************************************************************/
4101 /* Create a scroll bar and return the scroll bar vector for it. W is
4102 the Emacs window on which to create the scroll bar. TOP, LEFT,
4103 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4106 static struct scroll_bar
*
4107 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4109 int top
, left
, width
, height
, disp_top
, disp_height
;
4111 struct frame
*f
= XFRAME (w
->frame
);
4112 struct scroll_bar
*bar
4113 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4121 r
.right
= left
+ width
;
4122 r
.bottom
= disp_top
+ disp_height
;
4124 #if TARGET_API_MAC_CARBON
4125 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4126 kControlScrollBarProc
, 0L);
4128 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
4131 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4132 SetControlReference (ch
, (long) bar
);
4134 XSETWINDOW (bar
->window
, w
);
4135 XSETINT (bar
->top
, top
);
4136 XSETINT (bar
->left
, left
);
4137 XSETINT (bar
->width
, width
);
4138 XSETINT (bar
->height
, height
);
4139 XSETINT (bar
->start
, 0);
4140 XSETINT (bar
->end
, 0);
4141 bar
->dragging
= Qnil
;
4143 /* Add bar to its frame's list of scroll bars. */
4144 bar
->next
= FRAME_SCROLL_BARS (f
);
4146 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4147 if (!NILP (bar
->next
))
4148 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4155 /* Draw BAR's handle in the proper position.
4157 If the handle is already drawn from START to END, don't bother
4158 redrawing it, unless REBUILD is non-zero; in that case, always
4159 redraw it. (REBUILD is handy for drawing the handle after expose
4162 Normally, we want to constrain the start and end of the handle to
4163 fit inside its rectangle, but if the user is dragging the scroll
4164 bar handle, we want to let them drag it down all the way, so that
4165 the bar's top is as far down as it goes; otherwise, there's no way
4166 to move to the very end of the buffer. */
4169 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4170 struct scroll_bar
*bar
;
4174 int dragging
= ! NILP (bar
->dragging
);
4175 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4176 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4177 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4178 int length
= end
- start
;
4180 /* If the display is already accurate, do nothing. */
4182 && start
== XINT (bar
->start
)
4183 && end
== XINT (bar
->end
))
4188 /* Make sure the values are reasonable, and try to preserve the
4189 distance between start and end. */
4192 else if (start
> top_range
)
4194 end
= start
+ length
;
4198 else if (end
> top_range
&& ! dragging
)
4201 /* Store the adjusted setting in the scroll bar. */
4202 XSETINT (bar
->start
, start
);
4203 XSETINT (bar
->end
, end
);
4205 /* Clip the end position, just for display. */
4206 if (end
> top_range
)
4209 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4210 top positions, to make sure the handle is always at least that
4211 many pixels tall. */
4212 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4214 SetControlMinimum (ch
, 0);
4215 /* Don't inadvertently activate deactivated scroll bars */
4216 if (GetControlMaximum (ch
) != -1)
4217 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4219 SetControlValue (ch
, start
);
4220 #if TARGET_API_MAC_CARBON
4221 SetControlViewSize (ch
, end
- start
);
4228 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4232 x_scroll_bar_remove (bar
)
4233 struct scroll_bar
*bar
;
4235 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4239 /* Destroy the Mac scroll bar control */
4240 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4242 /* Disassociate this scroll bar from its window. */
4243 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4248 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4249 that we are displaying PORTION characters out of a total of WHOLE
4250 characters, starting at POSITION. If WINDOW has no scroll bar,
4253 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4255 int portion
, whole
, position
;
4257 struct frame
*f
= XFRAME (w
->frame
);
4258 struct scroll_bar
*bar
;
4259 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4260 int window_y
, window_height
;
4262 /* Get window dimensions. */
4263 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4268 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4270 height
= window_height
;
4272 /* Compute the left edge of the scroll bar area. */
4273 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4275 /* Compute the width of the scroll bar which might be less than
4276 the width of the area reserved for the scroll bar. */
4277 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4278 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4282 /* Compute the left edge of the scroll bar. */
4283 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4284 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
4286 sb_left
= left
+ (width
- sb_width
) / 2;
4288 /* Adjustments according to Inside Macintosh to make it look nice */
4290 disp_height
= height
;
4296 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4302 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4305 /* Does the scroll bar exist yet? */
4306 if (NILP (w
->vertical_scroll_bar
))
4309 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4310 left
, top
, width
, height
, 0);
4312 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4314 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4318 /* It may just need to be moved and resized. */
4321 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4322 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4326 /* If already correctly positioned, do nothing. */
4327 if (XINT (bar
->left
) == sb_left
4328 && XINT (bar
->top
) == top
4329 && XINT (bar
->width
) == sb_width
4330 && XINT (bar
->height
) == height
)
4334 /* Clear areas not covered by the scroll bar because it's not as
4335 wide as the area reserved for it . This makes sure a
4336 previous mode line display is cleared after C-x 2 C-x 1, for
4338 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4339 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4340 left
, top
, area_width
, height
, 0);
4343 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4344 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4345 sb_left
- 1, top
, 1, height
, 0);
4349 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4350 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4354 /* Remember new settings. */
4355 XSETINT (bar
->left
, sb_left
);
4356 XSETINT (bar
->top
, top
);
4357 XSETINT (bar
->width
, sb_width
);
4358 XSETINT (bar
->height
, height
);
4364 /* Set the scroll bar's current state, unless we're currently being
4366 if (NILP (bar
->dragging
))
4368 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4371 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4374 int start
= ((double) position
* top_range
) / whole
;
4375 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4376 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4382 /* The following three hooks are used when we're doing a thorough
4383 redisplay of the frame. We don't explicitly know which scroll bars
4384 are going to be deleted, because keeping track of when windows go
4385 away is a real pain - "Can you say set-window-configuration, boys
4386 and girls?" Instead, we just assert at the beginning of redisplay
4387 that *all* scroll bars are to be removed, and then save a scroll bar
4388 from the fiery pit when we actually redisplay its window. */
4390 /* Arrange for all scroll bars on FRAME to be removed at the next call
4391 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4392 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4395 XTcondemn_scroll_bars (frame
)
4398 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4399 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4402 bar
= FRAME_SCROLL_BARS (frame
);
4403 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4404 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4405 XSCROLL_BAR (bar
)->prev
= Qnil
;
4406 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4407 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4408 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4413 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4414 Note that WINDOW isn't necessarily condemned at all. */
4417 XTredeem_scroll_bar (window
)
4418 struct window
*window
;
4420 struct scroll_bar
*bar
;
4422 /* We can't redeem this window's scroll bar if it doesn't have one. */
4423 if (NILP (window
->vertical_scroll_bar
))
4426 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4428 /* Unlink it from the condemned list. */
4430 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4432 if (NILP (bar
->prev
))
4434 /* If the prev pointer is nil, it must be the first in one of
4436 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4437 /* It's not condemned. Everything's fine. */
4439 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4440 window
->vertical_scroll_bar
))
4441 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4443 /* If its prev pointer is nil, it must be at the front of
4444 one or the other! */
4448 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4450 if (! NILP (bar
->next
))
4451 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4453 bar
->next
= FRAME_SCROLL_BARS (f
);
4455 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4456 if (! NILP (bar
->next
))
4457 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4461 /* Remove all scroll bars on FRAME that haven't been saved since the
4462 last call to `*condemn_scroll_bars_hook'. */
4465 XTjudge_scroll_bars (f
)
4468 Lisp_Object bar
, next
;
4470 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4472 /* Clear out the condemned list now so we won't try to process any
4473 more events on the hapless scroll bars. */
4474 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4476 for (; ! NILP (bar
); bar
= next
)
4478 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4480 x_scroll_bar_remove (b
);
4483 b
->next
= b
->prev
= Qnil
;
4486 /* Now there should be no references to the condemned scroll bars,
4487 and they should get garbage-collected. */
4491 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4492 is set to something other than NO_EVENT, it is enqueued.
4494 This may be called from a signal handler, so we have to ignore GC
4498 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4499 struct scroll_bar
*bar
;
4502 struct input_event
*bufp
;
4504 int win_y
, top_range
;
4506 if (! GC_WINDOWP (bar
->window
))
4509 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4510 bufp
->frame_or_window
= bar
->window
;
4513 bar
->dragging
= Qnil
;
4517 case kControlUpButtonPart
:
4518 bufp
->part
= scroll_bar_up_arrow
;
4520 case kControlDownButtonPart
:
4521 bufp
->part
= scroll_bar_down_arrow
;
4523 case kControlPageUpPart
:
4524 bufp
->part
= scroll_bar_above_handle
;
4526 case kControlPageDownPart
:
4527 bufp
->part
= scroll_bar_below_handle
;
4529 #if TARGET_API_MAC_CARBON
4532 case kControlIndicatorPart
:
4534 if (er
->what
== mouseDown
)
4535 bar
->dragging
= make_number (0);
4536 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4537 bufp
->part
= scroll_bar_handle
;
4541 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4542 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4544 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4548 if (! NILP (bar
->dragging
))
4549 win_y
-= XINT (bar
->dragging
);
4553 if (win_y
> top_range
)
4556 XSETINT (bufp
->x
, win_y
);
4557 XSETINT (bufp
->y
, top_range
);
4561 /* Handle some mouse motion while someone is dragging the scroll bar.
4563 This may be called from a signal handler, so we have to ignore GC
4567 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4568 struct scroll_bar
*bar
;
4572 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4574 last_mouse_movement_time
= t
;
4577 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4579 /* If we're dragging the bar, display it. */
4580 if (! GC_NILP (bar
->dragging
))
4582 /* Where should the handle be now? */
4583 int new_start
= y_pos
- 24;
4585 if (new_start
!= XINT (bar
->start
))
4587 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4589 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4595 /* Return information to the user about the current position of the
4596 mouse on the scroll bar. */
4599 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4601 Lisp_Object
*bar_window
;
4602 enum scroll_bar_part
*part
;
4604 unsigned long *time
;
4606 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4607 WindowPtr wp
= front_emacs_window ();
4609 struct frame
*f
= mac_window_to_frame (wp
);
4610 int win_y
, top_range
;
4612 SetPortWindowPort (wp
);
4614 GetMouse (&mouse_pos
);
4616 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4617 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4619 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4623 if (! NILP (bar
->dragging
))
4624 win_y
-= XINT (bar
->dragging
);
4628 if (win_y
> top_range
)
4632 *bar_window
= bar
->window
;
4634 if (! NILP (bar
->dragging
))
4635 *part
= scroll_bar_handle
;
4636 else if (win_y
< XINT (bar
->start
))
4637 *part
= scroll_bar_above_handle
;
4638 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
4639 *part
= scroll_bar_handle
;
4641 *part
= scroll_bar_below_handle
;
4643 XSETINT (*x
, win_y
);
4644 XSETINT (*y
, top_range
);
4647 last_mouse_scroll_bar
= Qnil
;
4649 *time
= last_mouse_movement_time
;
4652 /***********************************************************************
4654 ***********************************************************************/
4656 /* Set clipping for output in glyph row ROW. W is the window in which
4657 we operate. GC is the graphics context to set clipping in.
4659 ROW may be a text row or, e.g., a mode line. Text rows must be
4660 clipped to the interior of the window dedicated to text display,
4661 mode lines must be clipped to the whole window. */
4664 x_clip_to_row (w
, row
, area
, gc
)
4666 struct glyph_row
*row
;
4670 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4672 int window_x
, window_y
, window_width
;
4674 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
4676 clip_rect
.left
= window_x
;
4677 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4678 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4679 clip_rect
.right
= clip_rect
.left
+ window_width
;
4680 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4682 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
4686 /* Draw a hollow box cursor on window W in glyph row ROW. */
4689 x_draw_hollow_cursor (w
, row
)
4691 struct glyph_row
*row
;
4693 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4694 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4695 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4698 struct glyph
*cursor_glyph
;
4701 /* Get the glyph the cursor is on. If we can't tell because
4702 the current matrix is invalid or such, give up. */
4703 cursor_glyph
= get_phys_cursor_glyph (w
);
4704 if (cursor_glyph
== NULL
)
4707 /* Compute frame-relative coordinates for phys cursor. */
4708 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
4709 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
4710 wd
= w
->phys_cursor_width
;
4712 /* The foreground of cursor_gc is typically the same as the normal
4713 background color, which can cause the cursor box to be invisible. */
4714 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4715 if (dpyinfo
->scratch_cursor_gc
)
4716 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
4718 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
4719 GCForeground
, &xgcv
);
4720 gc
= dpyinfo
->scratch_cursor_gc
;
4722 /* Set clipping, draw the rectangle, and reset clipping again. */
4723 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4724 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
4725 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4729 /* Draw a bar cursor on window W in glyph row ROW.
4731 Implementation note: One would like to draw a bar cursor with an
4732 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4733 Unfortunately, I didn't find a font yet that has this property set.
4737 x_draw_bar_cursor (w
, row
, width
, kind
)
4739 struct glyph_row
*row
;
4741 enum text_cursor_kinds kind
;
4743 struct frame
*f
= XFRAME (w
->frame
);
4744 struct glyph
*cursor_glyph
;
4746 /* If cursor is out of bounds, don't draw garbage. This can happen
4747 in mini-buffer windows when switching between echo area glyphs
4749 cursor_glyph
= get_phys_cursor_glyph (w
);
4750 if (cursor_glyph
== NULL
)
4753 /* If on an image, draw like a normal cursor. That's usually better
4754 visible than drawing a bar, esp. if the image is large so that
4755 the bar might not be in the window. */
4756 if (cursor_glyph
->type
== IMAGE_GLYPH
)
4758 struct glyph_row
*row
;
4759 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
4760 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
4764 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4765 Window window
= FRAME_MAC_WINDOW (f
);
4766 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
4767 unsigned long mask
= GCForeground
| GCBackground
;
4768 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
4771 /* If the glyph's background equals the color we normally draw
4772 the bar cursor in, the bar cursor in its normal color is
4773 invisible. Use the glyph's foreground color instead in this
4774 case, on the assumption that the glyph's colors are chosen so
4775 that the glyph is legible. */
4776 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
4777 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
4779 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4782 XChangeGC (dpy
, gc
, mask
, &xgcv
);
4785 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
4786 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
4790 width
= FRAME_CURSOR_WIDTH (f
);
4791 width
= min (cursor_glyph
->pixel_width
, width
);
4793 w
->phys_cursor_width
= width
;
4794 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4796 if (kind
== BAR_CURSOR
)
4797 XFillRectangle (dpy
, window
, gc
,
4798 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4799 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
4800 width
, row
->height
);
4802 XFillRectangle (dpy
, window
, gc
,
4803 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4804 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
4805 row
->height
- width
),
4806 cursor_glyph
->pixel_width
,
4809 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4814 /* RIF: Define cursor CURSOR on frame F. */
4817 mac_define_frame_cursor (f
, cursor
)
4821 SetThemeCursor (cursor
);
4825 /* RIF: Clear area on frame F. */
4828 mac_clear_frame_area (f
, x
, y
, width
, height
)
4830 int x
, y
, width
, height
;
4832 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4833 x
, y
, width
, height
, 0);
4837 /* RIF: Draw cursor on window W. */
4840 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
4842 struct glyph_row
*glyph_row
;
4844 int cursor_type
, cursor_width
;
4849 w
->phys_cursor_type
= cursor_type
;
4850 w
->phys_cursor_on_p
= 1;
4852 if (glyph_row
->exact_window_width_line_p
4853 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
4855 glyph_row
->cursor_in_fringe_p
= 1;
4856 draw_fringe_bitmap (w
, glyph_row
, 0);
4859 switch (cursor_type
)
4861 case HOLLOW_BOX_CURSOR
:
4862 x_draw_hollow_cursor (w
, glyph_row
);
4865 case FILLED_BOX_CURSOR
:
4866 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
4870 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
4874 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
4878 w
->phys_cursor_width
= 0;
4890 #if 0 /* MAC_TODO: no icon support yet. */
4892 x_bitmap_icon (f
, icon
)
4898 if (FRAME_W32_WINDOW (f
) == 0)
4902 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
4903 else if (STRINGP (icon
))
4904 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
4905 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
4906 else if (SYMBOLP (icon
))
4910 if (EQ (icon
, intern ("application")))
4911 name
= (LPCTSTR
) IDI_APPLICATION
;
4912 else if (EQ (icon
, intern ("hand")))
4913 name
= (LPCTSTR
) IDI_HAND
;
4914 else if (EQ (icon
, intern ("question")))
4915 name
= (LPCTSTR
) IDI_QUESTION
;
4916 else if (EQ (icon
, intern ("exclamation")))
4917 name
= (LPCTSTR
) IDI_EXCLAMATION
;
4918 else if (EQ (icon
, intern ("asterisk")))
4919 name
= (LPCTSTR
) IDI_ASTERISK
;
4920 else if (EQ (icon
, intern ("winlogo")))
4921 name
= (LPCTSTR
) IDI_WINLOGO
;
4925 hicon
= LoadIcon (NULL
, name
);
4933 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
4938 #endif /* MAC_TODO */
4940 /************************************************************************
4942 ************************************************************************/
4944 /* Display Error Handling functions not used on W32. Listing them here
4945 helps diff stay in step when comparing w32term.c with xterm.c.
4947 x_error_catcher (display, error)
4948 x_catch_errors (dpy)
4949 x_catch_errors_unwind (old_val)
4950 x_check_errors (dpy, format)
4951 x_had_errors_p (dpy)
4952 x_clear_errors (dpy)
4953 x_uncatch_errors (dpy, count)
4955 x_connection_signal (signalnum)
4956 x_connection_closed (dpy, error_message)
4957 x_error_quitter (display, error)
4958 x_error_handler (display, error)
4959 x_io_error_quitter (display)
4964 /* Changing the font of the frame. */
4966 /* Give frame F the font named FONTNAME as its default font, and
4967 return the full name of that font. FONTNAME may be a wildcard
4968 pattern; in that case, we choose some font that fits the pattern.
4969 The return value shows which font we chose. */
4972 x_new_font (f
, fontname
)
4974 register char *fontname
;
4976 struct font_info
*fontp
4977 = FS_LOAD_FONT (f
, 0, fontname
, -1);
4982 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4983 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
4984 FRAME_FONTSET (f
) = -1;
4986 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
4987 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
4988 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
4990 compute_fringe_widths (f
, 1);
4992 /* Compute the scroll bar width in character columns. */
4993 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
4995 int wid
= FRAME_COLUMN_WIDTH (f
);
4996 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
4997 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5001 int wid
= FRAME_COLUMN_WIDTH (f
);
5002 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5005 /* Now make the frame display the given font. */
5006 if (FRAME_MAC_WINDOW (f
) != 0)
5008 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5010 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5012 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5015 /* Don't change the size of a tip frame; there's no point in
5016 doing it because it's done in Fx_show_tip, and it leads to
5017 problems because the tip frame has no widget. */
5018 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5019 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5022 return build_string (fontp
->full_name
);
5025 /* Give frame F the fontset named FONTSETNAME as its default font, and
5026 return the full name of that fontset. FONTSETNAME may be a wildcard
5027 pattern; in that case, we choose some fontset that fits the pattern.
5028 The return value shows which fontset we chose. */
5031 x_new_fontset (f
, fontsetname
)
5035 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5041 if (FRAME_FONTSET (f
) == fontset
)
5042 /* This fontset is already set in frame F. There's nothing more
5044 return fontset_name (fontset
);
5046 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5048 if (!STRINGP (result
))
5049 /* Can't load ASCII font. */
5052 /* Since x_new_font doesn't update any fontset information, do it now. */
5053 FRAME_FONTSET(f
) = fontset
;
5055 return build_string (fontsetname
);
5059 /***********************************************************************
5060 TODO: W32 Input Methods
5061 ***********************************************************************/
5062 /* Listing missing functions from xterm.c helps diff stay in step.
5064 xim_destroy_callback (xim, client_data, call_data)
5065 xim_open_dpy (dpyinfo, resource_name)
5067 xim_instantiate_callback (display, client_data, call_data)
5068 xim_initialize (dpyinfo, resource_name)
5069 xim_close_dpy (dpyinfo)
5075 mac_get_window_bounds (f
, inner
, outer
)
5077 Rect
*inner
, *outer
;
5079 #if TARGET_API_MAC_CARBON
5080 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5081 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5082 #else /* not TARGET_API_MAC_CARBON */
5083 RgnHandle region
= NewRgn ();
5085 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5086 *inner
= (*region
)->rgnBBox
;
5087 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5088 *outer
= (*region
)->rgnBBox
;
5089 DisposeRgn (region
);
5090 #endif /* not TARGET_API_MAC_CARBON */
5094 /* Calculate the absolute position in frame F
5095 from its current recorded position values and gravity. */
5098 x_calc_absolute_position (f
)
5101 int width_diff
= 0, height_diff
= 0;
5102 int flags
= f
->size_hint_flags
;
5105 /* We have nothing to do if the current position
5106 is already for the top-left corner. */
5107 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5110 /* Find the offsets of the outside upper-left corner of
5111 the inner window, with respect to the outer window. */
5112 mac_get_window_bounds (f
, &inner
, &outer
);
5114 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5115 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5117 /* Treat negative positions as relative to the leftmost bottommost
5118 position that fits on the screen. */
5119 if (flags
& XNegative
)
5120 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5122 - FRAME_PIXEL_WIDTH (f
)
5125 if (flags
& YNegative
)
5126 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5128 - FRAME_PIXEL_HEIGHT (f
)
5131 /* The left_pos and top_pos
5132 are now relative to the top and left screen edges,
5133 so the flags should correspond. */
5134 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5137 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5138 to really change the position, and 0 when calling from
5139 x_make_frame_visible (in that case, XOFF and YOFF are the current
5140 position values). It is -1 when calling from x_set_frame_parameters,
5141 which means, do adjust for borders but don't change the gravity. */
5144 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5146 register int xoff
, yoff
;
5149 if (change_gravity
> 0)
5153 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5155 f
->size_hint_flags
|= XNegative
;
5157 f
->size_hint_flags
|= YNegative
;
5158 f
->win_gravity
= NorthWestGravity
;
5160 x_calc_absolute_position (f
);
5163 x_wm_set_size_hint (f
, (long) 0, 0);
5165 #if TARGET_API_MAC_CARBON
5166 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5167 /* If the title bar is completely outside the screen, adjust the
5169 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5170 kWindowConstrainMoveRegardlessOfFit
5171 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5172 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5175 Rect inner
, outer
, screen_rect
, dummy
;
5176 RgnHandle region
= NewRgn ();
5178 mac_get_window_bounds (f
, &inner
, &outer
);
5179 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5180 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5181 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5182 f
->top_pos
+ f
->y_pixels_diff
, false);
5184 /* If the title bar is completely outside the screen, adjust the
5185 position. The variable `outer' holds the title bar rectangle.
5186 The variable `inner' holds slightly smaller one than `outer',
5187 so that the calculation of overlapping may not become too
5189 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5190 outer
= (*region
)->rgnBBox
;
5191 DisposeRgn (region
);
5193 InsetRect (&inner
, 8, 8);
5194 screen_rect
= qd
.screenBits
.bounds
;
5195 screen_rect
.top
+= GetMBarHeight ();
5197 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5199 if (inner
.right
<= screen_rect
.left
)
5200 f
->left_pos
= screen_rect
.left
;
5201 else if (inner
.left
>= screen_rect
.right
)
5202 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5204 if (inner
.bottom
<= screen_rect
.top
)
5205 f
->top_pos
= screen_rect
.top
;
5206 else if (inner
.top
>= screen_rect
.bottom
)
5207 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5209 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5210 f
->top_pos
+ f
->y_pixels_diff
, false);
5218 /* Call this to change the size of frame F's x-window.
5219 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5220 for this size change and subsequent size changes.
5221 Otherwise we leave the window gravity unchanged. */
5224 x_set_window_size (f
, change_gravity
, cols
, rows
)
5229 int pixelwidth
, pixelheight
;
5233 check_frame_size (f
, &rows
, &cols
);
5234 f
->scroll_bar_actual_width
5235 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5237 compute_fringe_widths (f
, 0);
5239 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5240 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5242 f
->win_gravity
= NorthWestGravity
;
5243 x_wm_set_size_hint (f
, (long) 0, 0);
5245 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5246 #if TARGET_API_MAC_CARBON
5247 if (f
->output_data
.mac
->hourglass_control
)
5248 MoveControl (f
->output_data
.mac
->hourglass_control
,
5249 pixelwidth
- HOURGLASS_WIDTH
, 0);
5252 /* Now, strictly speaking, we can't be sure that this is accurate,
5253 but the window manager will get around to dealing with the size
5254 change request eventually, and we'll hear how it went when the
5255 ConfigureNotify event gets here.
5257 We could just not bother storing any of this information here,
5258 and let the ConfigureNotify event set everything up, but that
5259 might be kind of confusing to the Lisp code, since size changes
5260 wouldn't be reported in the frame parameters until some random
5261 point in the future when the ConfigureNotify event arrives.
5263 We pass 1 for DELAY since we can't run Lisp code inside of
5265 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5266 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5267 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5269 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5270 receive in the ConfigureNotify event; if we get what we asked
5271 for, then the event won't cause the screen to become garbaged, so
5272 we have to make sure to do it here. */
5273 SET_FRAME_GARBAGED (f
);
5275 XFlush (FRAME_X_DISPLAY (f
));
5277 /* If cursor was outside the new size, mark it as off. */
5278 mark_window_cursors_off (XWINDOW (f
->root_window
));
5280 /* Clear out any recollection of where the mouse highlighting was,
5281 since it might be in a place that's outside the new frame size.
5282 Actually checking whether it is outside is a pain in the neck,
5283 so don't try--just let the highlighting be done afresh with new size. */
5284 cancel_mouse_face (f
);
5289 /* Mouse warping. */
5291 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5294 x_set_mouse_position (f
, x
, y
)
5300 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5301 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5303 if (pix_x
< 0) pix_x
= 0;
5304 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5306 if (pix_y
< 0) pix_y
= 0;
5307 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5309 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5313 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5317 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5320 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5321 0, 0, 0, 0, pix_x
, pix_y
);
5327 /* focus shifting, raising and lowering. */
5330 x_focus_on_frame (f
)
5333 #if 0 /* This proves to be unpleasant. */
5337 /* I don't think that the ICCCM allows programs to do things like this
5338 without the interaction of the window manager. Whatever you end up
5339 doing with this code, do it to x_unfocus_frame too. */
5340 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5341 RevertToPointerRoot
, CurrentTime
);
5351 /* Raise frame F. */
5356 if (f
->async_visible
)
5359 SelectWindow (FRAME_MAC_WINDOW (f
));
5364 /* Lower frame F. */
5369 if (f
->async_visible
)
5372 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5378 XTframe_raise_lower (f
, raise_flag
)
5388 /* Change of visibility. */
5390 /* This tries to wait until the frame is really visible.
5391 However, if the window manager asks the user where to position
5392 the frame, this will return before the user finishes doing that.
5393 The frame will not actually be visible at that time,
5394 but it will become visible later when the window manager
5395 finishes with it. */
5398 x_make_frame_visible (f
)
5402 int original_top
, original_left
;
5406 if (! FRAME_VISIBLE_P (f
))
5408 /* We test FRAME_GARBAGED_P here to make sure we don't
5409 call x_set_offset a second time
5410 if we get to x_make_frame_visible a second time
5411 before the window gets really visible. */
5412 if (! FRAME_ICONIFIED_P (f
)
5413 && ! f
->output_data
.mac
->asked_for_visible
)
5414 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5416 f
->output_data
.mac
->asked_for_visible
= 1;
5418 #if TARGET_API_MAC_CARBON
5419 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5421 struct frame
*sf
= SELECTED_FRAME ();
5422 if (!FRAME_MAC_P (sf
))
5423 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5424 kWindowCenterOnMainScreen
);
5426 RepositionWindow (FRAME_MAC_WINDOW (f
),
5427 FRAME_MAC_WINDOW (sf
),
5428 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5429 kWindowCascadeStartAtParentWindowScreen
5431 kWindowCascadeOnParentWindowScreen
5434 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5437 ShowWindow (FRAME_MAC_WINDOW (f
));
5440 XFlush (FRAME_MAC_DISPLAY (f
));
5442 /* Synchronize to ensure Emacs knows the frame is visible
5443 before we do anything else. We do this loop with input not blocked
5444 so that incoming events are handled. */
5449 /* This must come after we set COUNT. */
5452 XSETFRAME (frame
, f
);
5454 /* Wait until the frame is visible. Process X events until a
5455 MapNotify event has been seen, or until we think we won't get a
5456 MapNotify at all.. */
5457 for (count
= input_signal_count
+ 10;
5458 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5460 /* Force processing of queued events. */
5463 /* Machines that do polling rather than SIGIO have been
5464 observed to go into a busy-wait here. So we'll fake an
5465 alarm signal to let the handler know that there's something
5466 to be read. We used to raise a real alarm, but it seems
5467 that the handler isn't always enabled here. This is
5469 if (input_polling_used ())
5471 /* It could be confusing if a real alarm arrives while
5472 processing the fake one. Turn it off and let the
5473 handler reset it. */
5474 extern void poll_for_input_1
P_ ((void));
5475 int old_poll_suppress_count
= poll_suppress_count
;
5476 poll_suppress_count
= 1;
5477 poll_for_input_1 ();
5478 poll_suppress_count
= old_poll_suppress_count
;
5481 /* See if a MapNotify event has been processed. */
5482 FRAME_SAMPLE_VISIBILITY (f
);
5487 /* Change from mapped state to withdrawn state. */
5489 /* Make the frame visible (mapped and not iconified). */
5492 x_make_frame_invisible (f
)
5495 /* Don't keep the highlight on an invisible frame. */
5496 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5497 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5501 HideWindow (FRAME_MAC_WINDOW (f
));
5503 /* We can't distinguish this from iconification
5504 just by the event that we get from the server.
5505 So we can't win using the usual strategy of letting
5506 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5507 and synchronize with the server to make sure we agree. */
5509 FRAME_ICONIFIED_P (f
) = 0;
5510 f
->async_visible
= 0;
5511 f
->async_iconified
= 0;
5516 /* Change window state from mapped to iconified. */
5522 /* Don't keep the highlight on an invisible frame. */
5523 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5524 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5527 /* Review: Since window is still visible in dock, still allow updates? */
5528 if (f
->async_iconified
)
5534 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5540 /* Free X resources of frame F. */
5543 x_free_frame_resources (f
)
5546 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5547 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5551 if (wp
!= tip_window
)
5552 remove_window_handler (wp
);
5555 if (wp
== tip_window
)
5556 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5557 closed' event. So we reset tip_window here. */
5560 free_frame_menubar (f
);
5562 if (FRAME_FACE_CACHE (f
))
5563 free_frame_faces (f
);
5567 if (FRAME_SIZE_HINTS (f
))
5568 xfree (FRAME_SIZE_HINTS (f
));
5570 xfree (f
->output_data
.mac
);
5571 f
->output_data
.mac
= NULL
;
5573 if (f
== dpyinfo
->x_focus_frame
)
5574 dpyinfo
->x_focus_frame
= 0;
5575 if (f
== dpyinfo
->x_focus_event_frame
)
5576 dpyinfo
->x_focus_event_frame
= 0;
5577 if (f
== dpyinfo
->x_highlight_frame
)
5578 dpyinfo
->x_highlight_frame
= 0;
5580 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5582 dpyinfo
->mouse_face_beg_row
5583 = dpyinfo
->mouse_face_beg_col
= -1;
5584 dpyinfo
->mouse_face_end_row
5585 = dpyinfo
->mouse_face_end_col
= -1;
5586 dpyinfo
->mouse_face_window
= Qnil
;
5587 dpyinfo
->mouse_face_deferred_gc
= 0;
5588 dpyinfo
->mouse_face_mouse_frame
= 0;
5595 /* Destroy the X window of frame F. */
5598 x_destroy_window (f
)
5601 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5603 x_free_frame_resources (f
);
5605 dpyinfo
->reference_count
--;
5609 /* Setting window manager hints. */
5611 /* Set the normal size hints for the window manager, for frame F.
5612 FLAGS is the flags word to use--or 0 meaning preserve the flags
5613 that the window now has.
5614 If USER_POSITION is nonzero, we set the USPosition
5615 flag (this is useful when FLAGS is 0). */
5617 x_wm_set_size_hint (f
, flags
, user_position
)
5622 int base_width
, base_height
, width_inc
, height_inc
;
5623 int min_rows
= 0, min_cols
= 0;
5624 XSizeHints
*size_hints
;
5626 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5627 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5628 width_inc
= FRAME_COLUMN_WIDTH (f
);
5629 height_inc
= FRAME_LINE_HEIGHT (f
);
5631 check_frame_size (f
, &min_rows
, &min_cols
);
5633 size_hints
= FRAME_SIZE_HINTS (f
);
5634 if (size_hints
== NULL
)
5636 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
5637 bzero (size_hints
, sizeof (XSizeHints
));
5640 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
5641 size_hints
->width_inc
= width_inc
;
5642 size_hints
->height_inc
= height_inc
;
5643 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
5644 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
5645 size_hints
->base_width
= base_width
;
5646 size_hints
->base_height
= base_height
;
5649 size_hints
->flags
= flags
;
5650 else if (user_position
)
5652 size_hints
->flags
&= ~ PPosition
;
5653 size_hints
->flags
|= USPosition
;
5657 #if 0 /* MAC_TODO: hide application instead of iconify? */
5658 /* Used for IconicState or NormalState */
5661 x_wm_set_window_state (f
, state
)
5665 #ifdef USE_X_TOOLKIT
5668 XtSetArg (al
[0], XtNinitialState
, state
);
5669 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5670 #else /* not USE_X_TOOLKIT */
5671 Window window
= FRAME_X_WINDOW (f
);
5673 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5674 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5676 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5677 #endif /* not USE_X_TOOLKIT */
5681 x_wm_set_icon_pixmap (f
, pixmap_id
)
5687 #ifndef USE_X_TOOLKIT
5688 Window window
= FRAME_X_WINDOW (f
);
5693 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5694 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5698 /* It seems there is no way to turn off use of an icon pixmap.
5699 The following line does it, only if no icon has yet been created,
5700 for some window managers. But with mwm it crashes.
5701 Some people say it should clear the IconPixmapHint bit in this case,
5702 but that doesn't work, and the X consortium said it isn't the
5703 right thing at all. Since there is no way to win,
5704 best to explicitly give up. */
5706 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5712 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5716 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
5717 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5720 #else /* not USE_X_TOOLKIT */
5722 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5723 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5725 #endif /* not USE_X_TOOLKIT */
5728 #endif /* MAC_TODO */
5731 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5735 #if 0 /* MAC_TODO: no icons on Mac */
5736 #ifdef USE_X_TOOLKIT
5737 Window window
= XtWindow (f
->output_data
.x
->widget
);
5739 Window window
= FRAME_X_WINDOW (f
);
5742 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5743 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5744 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5746 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5747 #endif /* MAC_TODO */
5751 /***********************************************************************
5753 ***********************************************************************/
5755 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5758 x_get_font_info (f
, font_idx
)
5762 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
5765 /* the global font name table */
5766 char **font_name_table
= NULL
;
5767 int font_name_table_size
= 0;
5768 int font_name_count
= 0;
5771 /* compare two strings ignoring case */
5773 stricmp (const char *s
, const char *t
)
5775 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
5778 return tolower (*s
) - tolower (*t
);
5781 /* compare two strings ignoring case and handling wildcard */
5783 wildstrieq (char *s1
, char *s2
)
5785 if (strcmp (s1
, "*") == 0 || strcmp (s2
, "*") == 0)
5788 return stricmp (s1
, s2
) == 0;
5791 /* Assume parameter 1 is fully qualified, no wildcards. */
5793 mac_font_pattern_match (fontname
, pattern
)
5797 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
5798 char *font_name_copy
= (char *) alloca (strlen (fontname
) + 1);
5801 /* Copy fontname so we can modify it during comparison. */
5802 strcpy (font_name_copy
, fontname
);
5807 /* Turn pattern into a regexp and do a regexp match. */
5808 for (; *pattern
; pattern
++)
5810 if (*pattern
== '?')
5812 else if (*pattern
== '*')
5823 return (fast_c_string_match_ignore_case (build_string (regex
),
5824 font_name_copy
) >= 0);
5827 /* Two font specs are considered to match if their foundry, family,
5828 weight, slant, and charset match. */
5830 mac_font_match (char *mf
, char *xf
)
5832 char m_foundry
[50], m_family
[50], m_weight
[20], m_slant
[2], m_charset
[20];
5833 char x_foundry
[50], x_family
[50], x_weight
[20], x_slant
[2], x_charset
[20];
5835 if (sscanf (mf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5836 m_foundry
, m_family
, m_weight
, m_slant
, m_charset
) != 5)
5837 return mac_font_pattern_match (mf
, xf
);
5839 if (sscanf (xf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5840 x_foundry
, x_family
, x_weight
, x_slant
, x_charset
) != 5)
5841 return mac_font_pattern_match (mf
, xf
);
5843 return (wildstrieq (m_foundry
, x_foundry
)
5844 && wildstrieq (m_family
, x_family
)
5845 && wildstrieq (m_weight
, x_weight
)
5846 && wildstrieq (m_slant
, x_slant
)
5847 && wildstrieq (m_charset
, x_charset
))
5848 || mac_font_pattern_match (mf
, xf
);
5852 static Lisp_Object Qbig5
, Qcn_gb
, Qsjis
, Qeuc_kr
;
5855 decode_mac_font_name (name
, size
, scriptcode
)
5858 #if TARGET_API_MAC_CARBON
5864 Lisp_Object coding_system
;
5865 struct coding_system coding
;
5871 coding_system
= Qbig5
;
5874 coding_system
= Qcn_gb
;
5877 coding_system
= Qsjis
;
5880 coding_system
= Qeuc_kr
;
5886 setup_coding_system (coding_system
, &coding
);
5887 coding
.src_multibyte
= 0;
5888 coding
.dst_multibyte
= 1;
5889 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5890 coding
.composing
= COMPOSITION_DISABLED
;
5891 buf
= (char *) alloca (size
);
5893 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
5894 bcopy (buf
, name
, coding
.produced
);
5895 name
[coding
.produced
] = '\0';
5900 mac_to_x_fontname (name
, size
, style
, scriptcode
)
5904 #if TARGET_API_MAC_CARBON
5910 char foundry
[32], family
[32], cs
[32];
5911 char xf
[256], *result
, *p
;
5913 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) != 3)
5915 strcpy(foundry
, "Apple");
5916 strcpy(family
, name
);
5920 case smTradChinese
: /* == kTextEncodingMacChineseTrad */
5921 strcpy(cs
, "big5-0");
5923 case smSimpChinese
: /* == kTextEncodingMacChineseSimp */
5924 strcpy(cs
, "gb2312.1980-0");
5926 case smJapanese
: /* == kTextEncodingMacJapanese */
5927 strcpy(cs
, "jisx0208.1983-sjis");
5930 /* Each Apple Japanese font is entered into the font table
5931 twice: once as a jisx0208.1983-sjis font and once as a
5932 jisx0201.1976-0 font. The latter can be used to display
5933 the ascii charset and katakana-jisx0201 charset. A
5934 negative script code signals that the name of this latter
5935 font is being built. */
5936 strcpy(cs
, "jisx0201.1976-0");
5938 case smKorean
: /* == kTextEncodingMacKorean */
5939 strcpy(cs
, "ksc5601.1989-0");
5941 #if TARGET_API_MAC_CARBON
5942 case kTextEncodingMacCyrillic
:
5943 strcpy(cs
, "mac-cyrillic");
5945 case kTextEncodingMacCentralEurRoman
:
5946 strcpy(cs
, "mac-centraleurroman");
5948 case kTextEncodingMacSymbol
:
5949 case kTextEncodingMacDingbats
:
5950 strcpy(cs
, "adobe-fontspecific");
5954 strcpy(cs
, "mac-roman");
5959 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5960 foundry
, family
, style
& bold
? "bold" : "medium",
5961 style
& italic
? 'i' : 'r', size
, size
* 10, size
* 10, cs
);
5963 result
= (char *) xmalloc (strlen (xf
) + 1);
5964 strcpy (result
, xf
);
5965 for (p
= result
; *p
; p
++)
5971 /* Convert an X font spec to the corresponding mac font name, which
5972 can then be passed to GetFNum after conversion to a Pascal string.
5973 For ordinary Mac fonts, this should just be their names, like
5974 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5975 collection contain their charset designation in their names, like
5976 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5977 names are handled accordingly. */
5979 x_font_name_to_mac_font_name (char *xf
, char *mf
)
5981 char foundry
[32], family
[32], weight
[20], slant
[2], cs
[32];
5982 Lisp_Object coding_system
= Qnil
;
5983 struct coding_system coding
;
5987 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5988 foundry
, family
, weight
, slant
, cs
) != 5 &&
5989 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5990 foundry
, family
, weight
, slant
, cs
) != 5)
5993 if (strcmp (cs
, "big5-0") == 0)
5994 coding_system
= Qbig5
;
5995 else if (strcmp (cs
, "gb2312.1980-0") == 0)
5996 coding_system
= Qcn_gb
;
5997 else if (strcmp (cs
, "jisx0208.1983-sjis") == 0
5998 || strcmp (cs
, "jisx0201.1976-0") == 0)
5999 coding_system
= Qsjis
;
6000 else if (strcmp (cs
, "ksc5601.1989-0") == 0)
6001 coding_system
= Qeuc_kr
;
6002 else if (strcmp (cs
, "mac-roman") == 0
6003 || strcmp (cs
, "mac-cyrillic") == 0
6004 || strcmp (cs
, "mac-centraleurroman") == 0
6005 || strcmp (cs
, "adobe-fontspecific") == 0)
6006 strcpy (mf
, family
);
6008 sprintf (mf
, "%s-%s-%s", foundry
, family
, cs
);
6010 if (!NILP (coding_system
))
6012 setup_coding_system (coding_system
, &coding
);
6013 coding
.src_multibyte
= 1;
6014 coding
.dst_multibyte
= 1;
6015 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6016 encode_coding (&coding
, family
, mf
, strlen (family
), sizeof (Str32
) - 1);
6017 mf
[coding
.produced
] = '\0';
6023 add_font_name_table_entry (char *font_name
)
6025 if (font_name_table_size
== 0)
6027 font_name_table_size
= 16;
6028 font_name_table
= (char **)
6029 xmalloc (font_name_table_size
* sizeof (char *));
6031 else if (font_name_count
+ 1 >= font_name_table_size
)
6033 font_name_table_size
+= 16;
6034 font_name_table
= (char **)
6035 xrealloc (font_name_table
,
6036 font_name_table_size
* sizeof (char *));
6039 font_name_table
[font_name_count
++] = font_name
;
6042 /* Sets up the table font_name_table to contain the list of all fonts
6043 in the system the first time the table is used so that the Resource
6044 Manager need not be accessed every time this information is
6048 init_font_name_table ()
6050 #if TARGET_API_MAC_CARBON
6053 if (Gestalt (gestaltSystemVersion
, &sv
) == noErr
&& sv
>= 0x1000)
6055 FMFontFamilyIterator ffi
;
6056 FMFontFamilyInstanceIterator ffii
;
6059 /* Create a dummy instance iterator here to avoid creating and
6060 destroying it in the loop. */
6061 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6063 /* Create an iterator to enumerate the font families. */
6064 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6067 FMDisposeFontFamilyInstanceIterator (&ffii
);
6071 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6077 TextEncoding encoding
;
6078 TextEncodingBase sc
;
6080 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6086 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6088 sc
= GetTextEncodingBase (encoding
);
6089 decode_mac_font_name (name
, sizeof (name
), sc
);
6091 /* Point the instance iterator at the current font family. */
6092 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6095 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6098 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6099 contained in Apple Japanese (SJIS) font. */
6103 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6105 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6107 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6109 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6114 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6116 if (sc
== smJapanese
)
6121 else if (sc
== -smJapanese
)
6126 /* Dispose of the iterators. */
6127 FMDisposeFontFamilyIterator (&ffi
);
6128 FMDisposeFontFamilyInstanceIterator (&ffii
);
6132 #endif /* TARGET_API_MAC_CARBON */
6134 SInt16 fontnum
, old_fontnum
;
6135 int num_mac_fonts
= CountResources('FOND');
6137 Handle font_handle
, font_handle_2
;
6138 short id
, scriptcode
;
6141 struct FontAssoc
*fat
;
6142 struct AsscEntry
*assc_entry
;
6144 GetPort (&port
); /* save the current font number used */
6145 #if TARGET_API_MAC_CARBON
6146 old_fontnum
= GetPortTextFont (port
);
6148 old_fontnum
= port
->txFont
;
6151 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6153 font_handle
= GetIndResource ('FOND', i
);
6157 GetResInfo (font_handle
, &id
, &type
, name
);
6158 GetFNum (name
, &fontnum
);
6164 scriptcode
= FontToScript (fontnum
);
6165 decode_mac_font_name (name
, sizeof (name
), scriptcode
);
6168 HLock (font_handle
);
6170 if (GetResourceSizeOnDisk (font_handle
)
6171 >= sizeof (struct FamRec
))
6173 fat
= (struct FontAssoc
*) (*font_handle
6174 + sizeof (struct FamRec
));
6176 = (struct AsscEntry
*) (*font_handle
6177 + sizeof (struct FamRec
)
6178 + sizeof (struct FontAssoc
));
6180 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6182 if (font_name_table_size
== 0)
6184 font_name_table_size
= 16;
6185 font_name_table
= (char **)
6186 xmalloc (font_name_table_size
* sizeof (char *));
6188 else if (font_name_count
>= font_name_table_size
)
6190 font_name_table_size
+= 16;
6191 font_name_table
= (char **)
6192 xrealloc (font_name_table
,
6193 font_name_table_size
* sizeof (char *));
6195 font_name_table
[font_name_count
++]
6196 = mac_to_x_fontname (name
,
6197 assc_entry
->fontSize
,
6198 assc_entry
->fontStyle
,
6200 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6201 parts are contained in Apple Japanese (SJIS)
6203 if (smJapanese
== scriptcode
)
6205 font_name_table
[font_name_count
++]
6206 = mac_to_x_fontname (name
,
6207 assc_entry
->fontSize
,
6208 assc_entry
->fontStyle
,
6214 HUnlock (font_handle
);
6215 font_handle_2
= GetNextFOND (font_handle
);
6216 ReleaseResource (font_handle
);
6217 font_handle
= font_handle_2
;
6219 while (ResError () == noErr
&& font_handle
);
6222 TextFont (old_fontnum
);
6223 #if TARGET_API_MAC_CARBON
6225 #endif /* TARGET_API_MAC_CARBON */
6230 mac_clear_font_name_table ()
6234 for (i
= 0; i
< font_name_count
; i
++)
6235 xfree (font_name_table
[i
]);
6236 xfree (font_name_table
);
6237 font_name_table
= NULL
;
6238 font_name_table_size
= font_name_count
= 0;
6242 enum xlfd_scalable_field_index
6244 XLFD_SCL_PIXEL_SIZE
,
6245 XLFD_SCL_POINT_SIZE
,
6250 static int xlfd_scalable_fields
[] =
6259 mac_c_string_match (regexp
, string
, nonspecial
, exact
)
6261 const char *string
, *nonspecial
;
6266 if (strcmp (string
, nonspecial
) == 0)
6267 return build_string (string
);
6269 else if (strstr (string
, nonspecial
))
6271 Lisp_Object str
= build_string (string
);
6273 if (fast_string_match (regexp
, str
) >= 0)
6281 mac_do_list_fonts (pattern
, maxnames
)
6286 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6287 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6290 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6291 char *longest_start
, *cur_start
, *nonspecial
;
6292 int longest_len
, exact
;
6294 if (font_name_table
== NULL
) /* Initialize when first used. */
6295 init_font_name_table ();
6297 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6300 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6301 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6302 fonts are scaled according to the specified size. */
6305 field
= xlfd_scalable_fields
;
6313 if ('1' <= *ptr
&& *ptr
<= '9')
6315 *val
= *ptr
++ - '0';
6316 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6317 *val
= *val
* 10 + *ptr
++ - '0';
6324 ptr
= strchr (ptr
, '-');
6327 while (ptr
&& i
< 14);
6329 if (i
== 14 && ptr
== NULL
)
6331 if (scl_val
[XLFD_SCL_POINT_SIZE
] > 0)
6333 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_POINT_SIZE
] / 10;
6334 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_POINT_SIZE
];
6336 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0)
6338 scl_val
[XLFD_SCL_POINT_SIZE
] =
6339 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10;
6341 else if (scl_val
[XLFD_SCL_AVGWIDTH
] > 0)
6343 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
] / 10;
6344 scl_val
[XLFD_SCL_POINT_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
];
6348 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6353 longest_start
= cur_start
= ptr
;
6357 /* Turn pattern into a regexp and do a regexp match. Also find the
6358 longest substring containing no special characters. */
6359 for (; *pattern
; pattern
++)
6361 if (*pattern
== '?' || *pattern
== '*')
6363 if (ptr
- cur_start
> longest_len
)
6365 longest_start
= cur_start
;
6366 longest_len
= ptr
- cur_start
;
6370 if (*pattern
== '?')
6372 else /* if (*pattern == '*') */
6380 *ptr
++ = tolower (*pattern
);
6383 if (ptr
- cur_start
> longest_len
)
6385 longest_start
= cur_start
;
6386 longest_len
= ptr
- cur_start
;
6392 nonspecial
= xmalloc (longest_len
+ 1);
6393 strncpy (nonspecial
, longest_start
, longest_len
);
6394 nonspecial
[longest_len
] = '\0';
6396 pattern_regex
= build_string (regex
);
6398 for (i
= 0; i
< font_name_count
; i
++)
6400 fontname
= mac_c_string_match (pattern_regex
, font_name_table
[i
],
6402 if (!NILP (fontname
))
6404 font_list
= Fcons (fontname
, font_list
);
6405 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6408 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6409 && (ptr
= strstr (font_name_table
[i
], "-0-0-75-75-m-0-")))
6411 int former_len
= ptr
- font_name_table
[i
];
6413 memcpy (scaled
, font_name_table
[i
], former_len
);
6414 sprintf (scaled
+ former_len
,
6415 "-%d-%d-75-75-m-%d-%s",
6416 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6417 scl_val
[XLFD_SCL_POINT_SIZE
],
6418 scl_val
[XLFD_SCL_AVGWIDTH
],
6419 ptr
+ sizeof ("-0-0-75-75-m-0-") - 1);
6420 fontname
= mac_c_string_match (pattern_regex
, scaled
,
6422 if (!NILP (fontname
))
6424 font_list
= Fcons (fontname
, font_list
);
6425 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6436 /* Return a list of at most MAXNAMES font specs matching the one in
6437 PATTERN. Cache matching fonts for patterns in
6438 dpyinfo->name_list_element to avoid looking them up again by
6439 calling mac_font_pattern_match (slow). Return as many matching
6440 fonts as possible if MAXNAMES = -1. */
6443 x_list_fonts (struct frame
*f
,
6444 Lisp_Object pattern
,
6448 Lisp_Object newlist
= Qnil
, tem
, key
;
6449 struct mac_display_info
*dpyinfo
= f
? FRAME_MAC_DISPLAY_INFO (f
) : NULL
;
6453 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
6454 key
= Fcons (pattern
, make_number (maxnames
));
6456 newlist
= Fassoc (key
, tem
);
6457 if (!NILP (newlist
))
6459 newlist
= Fcdr_safe (newlist
);
6465 newlist
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6468 /* MAC_TODO: add code for matching outline fonts here */
6472 XSETCAR (XCDR (dpyinfo
->name_list_element
),
6473 Fcons (Fcons (key
, newlist
),
6474 XCAR (XCDR (dpyinfo
->name_list_element
))));
6484 /* Check that FONT is valid on frame F. It is if it can be found in F's
6488 x_check_font (f
, font
)
6493 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6495 xassert (font
!= NULL
);
6497 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6498 if (dpyinfo
->font_table
[i
].name
6499 && font
== dpyinfo
->font_table
[i
].font
)
6502 xassert (i
< dpyinfo
->n_fonts
);
6505 #endif /* GLYPH_DEBUG != 0 */
6507 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6508 Note: There are (broken) X fonts out there with invalid XFontStruct
6509 min_bounds contents. For example, handa@etl.go.jp reports that
6510 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6511 have font->min_bounds.width == 0. */
6514 x_font_min_bounds (font
, w
, h
)
6515 MacFontStruct
*font
;
6518 *h
= FONT_HEIGHT (font
);
6519 *w
= font
->min_bounds
.width
;
6523 /* Compute the smallest character width and smallest font height over
6524 all fonts available on frame F. Set the members smallest_char_width
6525 and smallest_font_height in F's x_display_info structure to
6526 the values computed. Value is non-zero if smallest_font_height or
6527 smallest_char_width become smaller than they were before. */
6530 x_compute_min_glyph_bounds (f
)
6534 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6535 MacFontStruct
*font
;
6536 int old_width
= dpyinfo
->smallest_char_width
;
6537 int old_height
= dpyinfo
->smallest_font_height
;
6539 dpyinfo
->smallest_font_height
= 100000;
6540 dpyinfo
->smallest_char_width
= 100000;
6542 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6543 if (dpyinfo
->font_table
[i
].name
)
6545 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6548 font
= (MacFontStruct
*) fontp
->font
;
6549 xassert (font
!= (MacFontStruct
*) ~0);
6550 x_font_min_bounds (font
, &w
, &h
);
6552 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6553 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6556 xassert (dpyinfo
->smallest_char_width
> 0
6557 && dpyinfo
->smallest_font_height
> 0);
6559 return (dpyinfo
->n_fonts
== 1
6560 || dpyinfo
->smallest_char_width
< old_width
6561 || dpyinfo
->smallest_font_height
< old_height
);
6565 /* Determine whether given string is a fully-specified XLFD: all 14
6566 fields are present, none is '*'. */
6569 is_fully_specified_xlfd (char *p
)
6577 for (i
= 0; i
< 13; i
++)
6579 q
= strchr (p
+ 1, '-');
6582 if (q
- p
== 2 && *(p
+ 1) == '*')
6587 if (strchr (p
+ 1, '-') != NULL
)
6590 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6597 const int kDefaultFontSize
= 9;
6600 /* XLoadQueryFont creates and returns an internal representation for a
6601 font in a MacFontStruct struct. There is really no concept
6602 corresponding to "loading" a font on the Mac. But we check its
6603 existence and find the font number and all other information for it
6604 and store them in the returned MacFontStruct. */
6606 static MacFontStruct
*
6607 XLoadQueryFont (Display
*dpy
, char *fontname
)
6609 int i
, size
, is_two_byte_font
, char_width
;
6612 SInt16 old_fontnum
, old_fontsize
;
6616 Style fontface
= normal
;
6617 MacFontStruct
*font
;
6618 FontInfo the_fontinfo
;
6619 char s_weight
[7], c_slant
;
6621 if (is_fully_specified_xlfd (fontname
))
6625 Lisp_Object matched_fonts
;
6627 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6628 if (NILP (matched_fonts
))
6630 name
= SDATA (XCAR (matched_fonts
));
6633 GetPort (&port
); /* save the current font number used */
6634 #if TARGET_API_MAC_CARBON
6635 old_fontnum
= GetPortTextFont (port
);
6636 old_fontsize
= GetPortTextSize (port
);
6637 old_fontface
= GetPortTextFace (port
);
6639 old_fontnum
= port
->txFont
;
6640 old_fontsize
= port
->txSize
;
6641 old_fontface
= port
->txFace
;
6644 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size
) != 1)
6645 size
= kDefaultFontSize
;
6647 if (sscanf (name
, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight
) == 1)
6648 if (strcmp (s_weight
, "bold") == 0)
6651 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant
) == 1)
6655 x_font_name_to_mac_font_name (name
, mfontname
);
6657 GetFNum (mfontname
, &fontnum
);
6661 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
6663 font
->fontname
= (char *) xmalloc (strlen (name
) + 1);
6664 bcopy (name
, font
->fontname
, strlen (name
) + 1);
6666 font
->mac_fontnum
= fontnum
;
6667 font
->mac_fontsize
= size
;
6668 font
->mac_fontface
= fontface
;
6669 font
->mac_scriptcode
= FontToScript (fontnum
);
6671 /* Apple Japanese (SJIS) font is listed as both
6672 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6673 (Roman script) in init_font_name_table (). The latter should be
6674 treated as a one-byte font. */
6679 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6681 && 0 == strcmp (cs
, "jisx0201.1976-0"))
6682 font
->mac_scriptcode
= smRoman
;
6685 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
6686 font
->mac_scriptcode
== smTradChinese
||
6687 font
->mac_scriptcode
== smSimpChinese
||
6688 font
->mac_scriptcode
== smKorean
;
6692 TextFace (fontface
);
6694 GetFontInfo (&the_fontinfo
);
6696 font
->ascent
= the_fontinfo
.ascent
;
6697 font
->descent
= the_fontinfo
.descent
;
6699 font
->min_byte1
= 0;
6700 if (is_two_byte_font
)
6701 font
->max_byte1
= 1;
6703 font
->max_byte1
= 0;
6704 font
->min_char_or_byte2
= 0x20;
6705 font
->max_char_or_byte2
= 0xff;
6707 if (is_two_byte_font
)
6709 /* Use the width of an "ideographic space" of that font because
6710 the_fontinfo.widMax returns the wrong width for some fonts. */
6711 switch (font
->mac_scriptcode
)
6714 char_width
= StringWidth("\p\x81\x40");
6717 char_width
= StringWidth("\p\xa1\x40");
6720 char_width
= StringWidth("\p\xa1\xa1");
6723 char_width
= StringWidth("\p\xa1\xa1");
6728 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6729 returns 15 for 12-point Monaco! */
6730 char_width
= CharWidth ('m');
6732 if (is_two_byte_font
)
6734 font
->per_char
= NULL
;
6736 if (fontface
& italic
)
6737 font
->max_bounds
.rbearing
= char_width
+ 1;
6739 font
->max_bounds
.rbearing
= char_width
;
6740 font
->max_bounds
.lbearing
= 0;
6741 font
->max_bounds
.width
= char_width
;
6742 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
6743 font
->max_bounds
.descent
= the_fontinfo
.descent
;
6745 font
->min_bounds
= font
->max_bounds
;
6749 font
->per_char
= (XCharStruct
*)
6750 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
6752 int c
, min_width
, max_width
;
6753 Rect char_bounds
, min_bounds
, max_bounds
;
6756 min_width
= max_width
= char_width
;
6757 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
6758 SetRect (&max_bounds
, 0, 0, 0, 0);
6759 for (c
= 0x20; c
<= 0xff; c
++)
6762 char_width
= CharWidth (ch
);
6763 QDTextBounds (1, &ch
, &char_bounds
);
6764 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
6765 char_width
, char_bounds
);
6766 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6767 character width of 0x7f. */
6770 min_width
= min (min_width
, char_width
);
6771 max_width
= max (max_width
, char_width
);
6773 if (!EmptyRect (&char_bounds
))
6775 SetRect (&min_bounds
,
6776 max (min_bounds
.left
, char_bounds
.left
),
6777 max (min_bounds
.top
, char_bounds
.top
),
6778 min (min_bounds
.right
, char_bounds
.right
),
6779 min (min_bounds
.bottom
, char_bounds
.bottom
));
6780 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
6783 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
6784 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
6785 if (min_width
== max_width
6786 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
6788 /* Fixed width and no overhangs. */
6789 xfree (font
->per_char
);
6790 font
->per_char
= NULL
;
6795 TextFont (old_fontnum
); /* restore previous font number, size and face */
6796 TextSize (old_fontsize
);
6797 TextFace (old_fontface
);
6804 mac_unload_font (dpyinfo
, font
)
6805 struct mac_display_info
*dpyinfo
;
6808 xfree (font
->fontname
);
6810 xfree (font
->per_char
);
6815 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6816 pointer to the structure font_info while allocating it dynamically.
6817 If SIZE is 0, load any size of font.
6818 If loading is failed, return NULL. */
6821 x_load_font (f
, fontname
, size
)
6823 register char *fontname
;
6826 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6827 Lisp_Object font_names
;
6829 /* Get a list of all the fonts that match this name. Once we
6830 have a list of matching fonts, we compare them against the fonts
6831 we already have by comparing names. */
6832 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
6834 if (!NILP (font_names
))
6839 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6840 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
6841 if (dpyinfo
->font_table
[i
].name
6842 && (!strcmp (dpyinfo
->font_table
[i
].name
,
6843 SDATA (XCAR (tail
)))
6844 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6845 SDATA (XCAR (tail
)))))
6846 return (dpyinfo
->font_table
+ i
);
6849 /* Load the font and add it to the table. */
6852 struct MacFontStruct
*font
;
6853 struct font_info
*fontp
;
6854 unsigned long value
;
6857 /* If we have found fonts by x_list_font, load one of them. If
6858 not, we still try to load a font by the name given as FONTNAME
6859 because XListFonts (called in x_list_font) of some X server has
6860 a bug of not finding a font even if the font surely exists and
6861 is loadable by XLoadQueryFont. */
6862 if (size
> 0 && !NILP (font_names
))
6863 fontname
= (char *) SDATA (XCAR (font_names
));
6866 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
6871 /* Find a free slot in the font table. */
6872 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6873 if (dpyinfo
->font_table
[i
].name
== NULL
)
6876 /* If no free slot found, maybe enlarge the font table. */
6877 if (i
== dpyinfo
->n_fonts
6878 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
6881 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
6882 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
6884 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
6887 fontp
= dpyinfo
->font_table
+ i
;
6888 if (i
== dpyinfo
->n_fonts
)
6891 /* Now fill in the slots of *FONTP. */
6893 bzero (fontp
, sizeof (*fontp
));
6895 fontp
->font_idx
= i
;
6896 fontp
->name
= (char *) xmalloc (strlen (font
->fontname
) + 1);
6897 bcopy (font
->fontname
, fontp
->name
, strlen (font
->fontname
) + 1);
6899 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
6901 /* Fixed width font. */
6902 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
6909 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
6910 pcm
= mac_per_char_metric (font
, &char2b
, 0);
6912 fontp
->space_width
= pcm
->width
;
6914 fontp
->space_width
= FONT_WIDTH (font
);
6918 int width
= pcm
->width
;
6919 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
6920 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
6921 width
+= pcm
->width
;
6922 fontp
->average_width
= width
/ 95;
6925 fontp
->average_width
= FONT_WIDTH (font
);
6928 fontp
->full_name
= fontp
->name
;
6930 fontp
->size
= font
->max_bounds
.width
;
6931 fontp
->height
= FONT_HEIGHT (font
);
6933 /* For some font, ascent and descent in max_bounds field is
6934 larger than the above value. */
6935 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6936 if (max_height
> fontp
->height
)
6937 fontp
->height
= max_height
;
6940 /* The slot `encoding' specifies how to map a character
6941 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6942 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6943 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6944 2:0xA020..0xFF7F). For the moment, we don't know which charset
6945 uses this font. So, we set information in fontp->encoding[1]
6946 which is never used by any charset. If mapping can't be
6947 decided, set FONT_ENCODING_NOT_DECIDED. */
6948 if (font
->mac_scriptcode
== smJapanese
)
6949 fontp
->encoding
[1] = 4;
6953 = (font
->max_byte1
== 0
6955 ? (font
->min_char_or_byte2
< 0x80
6956 ? (font
->max_char_or_byte2
< 0x80
6957 ? 0 /* 0x20..0x7F */
6958 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6959 : 1) /* 0xA0..0xFF */
6961 : (font
->min_byte1
< 0x80
6962 ? (font
->max_byte1
< 0x80
6963 ? (font
->min_char_or_byte2
< 0x80
6964 ? (font
->max_char_or_byte2
< 0x80
6965 ? 0 /* 0x2020..0x7F7F */
6966 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6967 : 3) /* 0x20A0..0x7FFF */
6968 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6969 : (font
->min_char_or_byte2
< 0x80
6970 ? (font
->max_char_or_byte2
< 0x80
6971 ? 2 /* 0xA020..0xFF7F */
6972 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6973 : 1))); /* 0xA0A0..0xFFFF */
6976 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6977 fontp
->baseline_offset
6978 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6979 ? (long) value
: 0);
6980 fontp
->relative_compose
6981 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6982 ? (long) value
: 0);
6983 fontp
->default_ascent
6984 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6985 ? (long) value
: 0);
6987 fontp
->baseline_offset
= 0;
6988 fontp
->relative_compose
= 0;
6989 fontp
->default_ascent
= 0;
6992 /* Set global flag fonts_changed_p to non-zero if the font loaded
6993 has a character with a smaller width than any other character
6994 before, or if the font loaded has a smalle>r height than any
6995 other font loaded before. If this happens, it will make a
6996 glyph matrix reallocation necessary. */
6997 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
7004 /* Return a pointer to struct font_info of a font named FONTNAME for
7005 frame F. If no such font is loaded, return NULL. */
7008 x_query_font (f
, fontname
)
7010 register char *fontname
;
7012 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7015 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7016 if (dpyinfo
->font_table
[i
].name
7017 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7018 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7019 return (dpyinfo
->font_table
+ i
);
7024 /* Find a CCL program for a font specified by FONTP, and set the member
7025 `encoder' of the structure. */
7028 x_find_ccl_program (fontp
)
7029 struct font_info
*fontp
;
7031 Lisp_Object list
, elt
;
7033 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7037 && STRINGP (XCAR (elt
))
7038 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7044 struct ccl_program
*ccl
7045 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7047 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7050 fontp
->font_encoder
= ccl
;
7056 /* The Mac Event loop code */
7058 #if !TARGET_API_MAC_CARBON
7060 #include <Quickdraw.h>
7061 #include <Balloons.h>
7062 #include <Devices.h>
7064 #include <Gestalt.h>
7066 #include <Processes.h>
7068 #include <ToolUtils.h>
7069 #include <TextUtils.h>
7070 #include <Dialogs.h>
7073 #include <TextEncodingConverter.h>
7074 #include <Resources.h>
7079 #endif /* ! TARGET_API_MAC_CARBON */
7084 #define WINDOW_RESOURCE 128
7085 #define TERM_WINDOW_RESOURCE 129
7087 #define DEFAULT_NUM_COLS 80
7089 #define MIN_DOC_SIZE 64
7090 #define MAX_DOC_SIZE 32767
7092 /* sleep time for WaitNextEvent */
7093 #define WNE_SLEEP_AT_SUSPEND 10
7094 #define WNE_SLEEP_AT_RESUME 1
7096 /* true when cannot handle any Mac OS events */
7097 static int handling_window_update
= 0;
7100 /* the flag appl_is_suspended is used both for determining the sleep
7101 time to be passed to WaitNextEvent and whether the cursor should be
7102 drawn when updating the display. The cursor is turned off when
7103 Emacs is suspended. Redrawing it is unnecessary and what needs to
7104 be done depends on whether the cursor lies inside or outside the
7105 redraw region. So we might as well skip drawing it when Emacs is
7107 static Boolean app_is_suspended
= false;
7108 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7111 #define EXTRA_STACK_ALLOC (256 * 1024)
7113 #define ARGV_STRING_LIST_ID 129
7114 #define ABOUT_ALERT_ID 128
7115 #define RAM_TOO_LARGE_ALERT_ID 129
7117 Boolean terminate_flag
= false;
7119 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7120 Lisp_Object Qreverse
;
7122 /* True if using command key as meta key. */
7123 Lisp_Object Vmac_command_key_is_meta
;
7125 /* Modifier associated with the option key, or nil for normal behavior. */
7126 Lisp_Object Vmac_option_modifier
;
7128 /* True if the ctrl and meta keys should be reversed. */
7129 Lisp_Object Vmac_reverse_ctrl_meta
;
7131 /* True if the option and command modifiers should be used to emulate
7132 a three button mouse */
7133 Lisp_Object Vmac_emulate_three_button_mouse
;
7135 #if USE_CARBON_EVENTS
7136 /* True if the mouse wheel button (i.e. button 4) should map to
7137 mouse-2, instead of mouse-3. */
7138 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7140 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7141 for processing before Emacs sees it. */
7142 Lisp_Object Vmac_pass_command_to_system
;
7144 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7145 for processing before Emacs sees it. */
7146 Lisp_Object Vmac_pass_control_to_system
;
7149 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7150 to this text encoding */
7151 int mac_keyboard_text_encoding
;
7152 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
7154 /* Set in term/mac-win.el to indicate that event loop can now generate
7155 drag and drop events. */
7156 Lisp_Object Qmac_ready_for_drag_n_drop
;
7158 Lisp_Object drag_and_drop_file_list
;
7160 Point saved_menu_event_location
;
7163 static void init_required_apple_events (void);
7165 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7167 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7168 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7169 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7171 #if TARGET_API_MAC_CARBON
7173 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7174 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7175 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7176 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7179 #if USE_CARBON_EVENTS
7181 /* Preliminary Support for the OSX Services Menu */
7182 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
7183 static void init_service_handler ();
7185 /* Window Event Handler */
7186 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7189 OSErr
install_window_handler (WindowPtr
);
7191 extern void init_emacs_passwd_dir ();
7192 extern int emacs_main (int, char **, char **);
7193 extern void check_alarm ();
7195 extern void initialize_applescript();
7196 extern void terminate_applescript();
7199 #if USE_CARBON_EVENTS
7200 mac_to_emacs_modifiers (UInt32 mods
)
7202 mac_to_emacs_modifiers (EventModifiers mods
)
7205 unsigned int result
= 0;
7206 if (mods
& macShiftKey
)
7207 result
|= shift_modifier
;
7208 if (mods
& macCtrlKey
)
7209 result
|= ctrl_modifier
;
7210 if (mods
& macMetaKey
)
7211 result
|= meta_modifier
;
7212 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7213 result
|= alt_modifier
;
7214 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7215 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7217 result
|= XUINT(val
);
7224 mac_get_emulated_btn ( UInt32 modifiers
)
7227 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7228 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7229 if (modifiers
& cmdKey
)
7230 result
= cmdIs3
? 2 : 1;
7231 else if (modifiers
& optionKey
)
7232 result
= cmdIs3
? 1 : 2;
7237 #if USE_CARBON_EVENTS
7238 /* Obtains the event modifiers from the event ref and then calls
7239 mac_to_emacs_modifiers. */
7241 mac_event_to_emacs_modifiers (EventRef eventRef
)
7244 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7245 sizeof (UInt32
), NULL
, &mods
);
7246 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7247 GetEventClass(eventRef
) == kEventClassMouse
)
7249 mods
&= ~(optionKey
| cmdKey
);
7251 return mac_to_emacs_modifiers (mods
);
7254 /* Given an event ref, return the code to use for the mouse button
7255 code in the emacs input_event. */
7257 mac_get_mouse_btn (EventRef ref
)
7259 EventMouseButton result
= kEventMouseButtonPrimary
;
7260 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7261 sizeof (EventMouseButton
), NULL
, &result
);
7264 case kEventMouseButtonPrimary
:
7265 if (NILP (Vmac_emulate_three_button_mouse
))
7269 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7270 sizeof (UInt32
), NULL
, &mods
);
7271 return mac_get_emulated_btn(mods
);
7273 case kEventMouseButtonSecondary
:
7274 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7275 case kEventMouseButtonTertiary
:
7276 case 4: /* 4 is the number for the mouse wheel button */
7277 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7283 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7284 events. However the click of the mouse wheel is not converted to a
7285 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7286 checks to see if it is a mouse up or down carbon event that has not
7287 been converted, and if so, converts it by hand (to be picked up in
7288 the XTread_socket loop). */
7289 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7291 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7292 /* Do special case for mouse wheel button. */
7293 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
7295 UInt32 kind
= GetEventKind (eventRef
);
7296 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
7298 eventRec
->what
= mouseDown
;
7301 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
7303 eventRec
->what
= mouseUp
;
7308 /* Need where and when. */
7310 GetEventParameter (eventRef
, kEventParamMouseLocation
,
7311 typeQDPoint
, NULL
, sizeof (Point
),
7312 NULL
, &eventRec
->where
);
7313 /* Use two step process because new event modifiers are
7314 32-bit and old are 16-bit. Currently, only loss is
7316 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
7317 typeUInt32
, NULL
, sizeof (UInt32
),
7319 eventRec
->modifiers
= mods
;
7321 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7332 Handle menubar_handle
;
7333 MenuHandle menu_handle
;
7335 menubar_handle
= GetNewMBar (128);
7336 if(menubar_handle
== NULL
)
7338 SetMenuBar (menubar_handle
);
7341 menu_handle
= GetMenuHandle (M_APPLE
);
7342 if(menu_handle
!= NULL
)
7343 AppendResMenu (menu_handle
,'DRVR');
7350 do_init_managers (void)
7352 #if !TARGET_API_MAC_CARBON
7353 InitGraf (&qd
.thePort
);
7355 FlushEvents (everyEvent
, 0);
7360 #endif /* !TARGET_API_MAC_CARBON */
7363 #if !TARGET_API_MAC_CARBON
7364 /* set up some extra stack space for use by emacs */
7365 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7367 /* MaxApplZone must be called for AppleScript to execute more
7368 complicated scripts */
7371 #endif /* !TARGET_API_MAC_CARBON */
7375 do_check_ram_size (void)
7377 SInt32 physical_ram_size
, logical_ram_size
;
7379 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7380 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7381 || physical_ram_size
> (1 << VALBITS
)
7382 || logical_ram_size
> (1 << VALBITS
))
7384 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7390 do_window_update (WindowPtr win
)
7392 struct frame
*f
= mac_window_to_frame (win
);
7396 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7398 if (win
!= tip_window
)
7400 if (f
->async_visible
== 0)
7402 f
->async_visible
= 1;
7403 f
->async_iconified
= 0;
7404 SET_FRAME_GARBAGED (f
);
7406 /* An update event is equivalent to MapNotify on X, so report
7407 visibility changes properly. */
7408 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7409 /* Force a redisplay sooner or later to update the
7410 frame titles in case this is the second frame. */
7411 record_asynch_buffer_change ();
7417 handling_window_update
= 1;
7419 #if TARGET_API_MAC_CARBON
7421 RgnHandle region
= NewRgn ();
7423 GetPortVisibleRegion (GetWindowPort (win
), region
);
7424 GetRegionBounds (region
, &r
);
7425 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7426 UpdateControls (win
, region
);
7427 DisposeRgn (region
);
7430 r
= (*win
->visRgn
)->rgnBBox
;
7431 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7432 UpdateControls (win
, win
->visRgn
);
7435 handling_window_update
= 0;
7443 is_emacs_window (WindowPtr win
)
7445 Lisp_Object tail
, frame
;
7450 FOR_EACH_FRAME (tail
, frame
)
7451 if (FRAME_MAC_P (XFRAME (frame
)))
7452 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7461 /* Window-activate events will do the job. */
7466 wp
= front_emacs_window ();
7469 f
= mac_window_to_frame (wp
);
7473 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
7474 activate_scroll_bars (f
);
7478 app_is_suspended
= false;
7479 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7486 /* Window-deactivate events will do the job. */
7491 wp
= front_emacs_window ();
7494 f
= mac_window_to_frame (wp
);
7496 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
7498 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
7499 deactivate_scroll_bars (f
);
7503 app_is_suspended
= true;
7504 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7510 do_mouse_moved (mouse_pos
, f
)
7514 WindowPtr wp
= front_emacs_window ();
7515 struct x_display_info
*dpyinfo
;
7519 *f
= mac_window_to_frame (wp
);
7520 dpyinfo
= FRAME_MAC_DISPLAY_INFO (*f
);
7522 if (dpyinfo
->mouse_face_hidden
)
7524 dpyinfo
->mouse_face_hidden
= 0;
7525 clear_mouse_face (dpyinfo
);
7528 SetPortWindowPort (wp
);
7530 GlobalToLocal (&mouse_pos
);
7532 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
7533 x_scroll_bar_note_movement (tracked_scroll_bar
,
7535 - XINT (tracked_scroll_bar
->top
),
7536 TickCount() * (1000 / 60));
7538 note_mouse_movement (*f
, &mouse_pos
);
7544 do_apple_menu (SInt16 menu_item
)
7546 #if !TARGET_API_MAC_CARBON
7548 SInt16 da_driver_refnum
;
7550 if (menu_item
== I_ABOUT
)
7551 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7554 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7555 da_driver_refnum
= OpenDeskAcc (item_name
);
7557 #endif /* !TARGET_API_MAC_CARBON */
7561 do_menu_choice (SInt32 menu_choice
)
7563 SInt16 menu_id
, menu_item
;
7565 menu_id
= HiWord (menu_choice
);
7566 menu_item
= LoWord (menu_choice
);
7574 do_apple_menu (menu_item
);
7579 struct frame
*f
= mac_window_to_frame (front_emacs_window ());
7580 MenuHandle menu
= GetMenuHandle (menu_id
);
7585 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7586 menubar_selection_callback (f
, refcon
);
7595 /* Handle drags in size box. Based on code contributed by Ben
7596 Mesander and IM - Window Manager A. */
7599 do_grow_window (WindowPtr w
, EventRecord
*e
)
7602 int rows
, columns
, width
, height
;
7603 struct frame
*f
= mac_window_to_frame (w
);
7604 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
7605 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
7606 #if TARGET_API_MAC_CARBON
7612 if (size_hints
->flags
& PMinSize
)
7614 min_width
= size_hints
->min_width
;
7615 min_height
= size_hints
->min_height
;
7617 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7619 #if TARGET_API_MAC_CARBON
7620 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
7622 height
= new_rect
.bottom
- new_rect
.top
;
7623 width
= new_rect
.right
- new_rect
.left
;
7625 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7626 /* see if it really changed size */
7629 height
= HiWord (grow_size
);
7630 width
= LoWord (grow_size
);
7633 if (width
!= FRAME_PIXEL_WIDTH (f
)
7634 || height
!= FRAME_PIXEL_HEIGHT (f
))
7636 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7637 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7639 x_set_window_size (f
, 0, columns
, rows
);
7644 /* Handle clicks in zoom box. Calculation of "standard state" based
7645 on code in IM - Window Manager A and code contributed by Ben
7646 Mesander. The standard state of an Emacs window is 80-characters
7647 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7650 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7653 Rect zoom_rect
, port_rect
;
7655 int w_title_height
, columns
, rows
, width
, height
;
7656 struct frame
*f
= mac_window_to_frame (w
);
7658 #if TARGET_API_MAC_CARBON
7660 Point standard_size
;
7662 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7663 standard_size
.v
= FRAME_MAC_DISPLAY_INFO (f
)->height
;
7665 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7666 zoom_in_or_out
= inZoomIn
;
7669 /* Adjust the standard size according to character boundaries. */
7671 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7672 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7673 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7674 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7675 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
7676 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
7677 && port_rect
.left
== zoom_rect
.left
7678 && port_rect
.top
== zoom_rect
.top
)
7679 zoom_in_or_out
= inZoomIn
;
7681 zoom_in_or_out
= inZoomOut
;
7684 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
7686 #else /* not TARGET_API_MAC_CARBON */
7687 GetPort (&save_port
);
7689 SetPortWindowPort (w
);
7691 /* Clear window to avoid flicker. */
7692 EraseRect (&(w
->portRect
));
7693 if (zoom_in_or_out
== inZoomOut
)
7695 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
7696 LocalToGlobal (&top_left
);
7698 /* calculate height of window's title bar */
7699 w_title_height
= top_left
.v
- 1
7700 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
7702 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7703 zoom_rect
= qd
.screenBits
.bounds
;
7704 zoom_rect
.top
+= w_title_height
;
7705 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
7707 zoom_rect
.right
= zoom_rect
.left
7708 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7710 /* Adjust the standard size according to character boundaries. */
7711 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7713 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7715 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
7719 ZoomWindow (w
, zoom_in_or_out
, w
== front_emacs_window ());
7721 SetPort (save_port
);
7722 #endif /* not TARGET_API_MAC_CARBON */
7724 /* retrieve window size and update application values */
7725 #if TARGET_API_MAC_CARBON
7726 GetWindowPortBounds (w
, &port_rect
);
7728 port_rect
= w
->portRect
;
7730 height
= port_rect
.bottom
- port_rect
.top
;
7731 width
= port_rect
.right
- port_rect
.left
;
7733 if (width
!= FRAME_PIXEL_WIDTH (f
)
7734 || height
!= FRAME_PIXEL_HEIGHT (f
))
7736 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
7737 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
7739 change_frame_size (f
, rows
, columns
, 0, 1, 0);
7740 SET_FRAME_GARBAGED (f
);
7741 cancel_mouse_face (f
);
7743 FRAME_PIXEL_WIDTH (f
) = width
;
7744 FRAME_PIXEL_HEIGHT (f
) = height
;
7746 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
7749 /* Intialize AppleEvent dispatcher table for the required events. */
7751 init_required_apple_events ()
7756 /* Make sure we have apple events before starting. */
7757 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
7761 if (!(result
& (1 << gestaltAppleEventsPresent
)))
7764 #if TARGET_API_MAC_CARBON
7765 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7766 NewAEEventHandlerUPP
7767 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7770 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7771 NewAEEventHandlerProc
7772 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7778 #if TARGET_API_MAC_CARBON
7779 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7780 NewAEEventHandlerUPP
7781 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7784 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7785 NewAEEventHandlerProc
7786 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7792 #if TARGET_API_MAC_CARBON
7793 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7794 NewAEEventHandlerUPP
7795 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7798 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7799 NewAEEventHandlerProc
7800 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7806 #if TARGET_API_MAC_CARBON
7807 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7808 NewAEEventHandlerUPP
7809 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7812 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7813 NewAEEventHandlerProc
7814 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7821 #if USE_CARBON_EVENTS
7824 init_service_handler ()
7826 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
7827 {kEventClassService
, kEventServiceCopy
},
7828 {kEventClassService
, kEventServicePaste
}};
7829 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
7830 3, specs
, NULL
, NULL
);
7834 MAC_TODO: Check to see if this is called by AEProcessDesc...
7837 mac_handle_service_event (EventHandlerCallRef callRef
,
7838 EventRef event
, void *data
)
7840 OSStatus err
= noErr
;
7841 switch (GetEventKind (event
))
7843 case kEventServiceGetTypes
:
7845 CFMutableArrayRef copyTypes
, pasteTypes
;
7847 Boolean selection
= true;
7849 GetEventParameter(event, kEventParamServicePasteTypes,
7850 typeCFMutableArrayRef, NULL,
7851 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7853 GetEventParameter(event
, kEventParamServiceCopyTypes
,
7854 typeCFMutableArrayRef
, NULL
,
7855 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
7856 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
7858 CFArrayAppendValue (copyTypes
, type
);
7859 //CFArrayAppendValue (pasteTypes, type);
7863 case kEventServiceCopy
:
7865 ScrapRef currentScrap
, specificScrap
;
7869 GetCurrentScrap (¤tScrap
);
7871 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
7874 void *buffer
= xmalloc (byteCount
);
7877 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
7878 sizeof (ScrapRef
), NULL
, &specificScrap
);
7880 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
7881 &byteCount
, buffer
);
7883 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
7884 kScrapFlavorMaskNone
, byteCount
, buffer
);
7890 case kEventServicePaste
:
7893 // Get the current location
7895 ScrapRef specificScrap;
7896 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7897 sizeof(ScrapRef), NULL, &specificScrap);
7898 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7900 void * buffer = xmalloc(byteCount);
7901 if (buffer != NULL ) {
7902 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7903 &byteCount, buffer);
7905 // Actually place in the buffer
7907 // Get the current "selection" string here
7920 static pascal OSStatus
7921 mac_handle_window_event (next_handler
, event
, data
)
7922 EventHandlerCallRef next_handler
;
7929 XSizeHints
*size_hints
;
7931 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
7932 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
7934 switch (GetEventKind (event
))
7936 case kEventWindowUpdate
:
7937 result
= CallNextEventHandler (next_handler
, event
);
7938 if (result
!= eventNotHandledErr
)
7941 do_window_update (wp
);
7944 case kEventWindowBoundsChanging
:
7945 result
= CallNextEventHandler (next_handler
, event
);
7946 if (result
!= eventNotHandledErr
)
7949 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
7950 NULL
, sizeof (UInt32
), NULL
, &attributes
);
7951 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
7952 if ((attributes
& kWindowBoundsChangeUserResize
)
7953 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
7954 == (PResizeInc
| PBaseSize
| PMinSize
)))
7959 GetEventParameter (event
, kEventParamCurrentBounds
,
7961 NULL
, sizeof (Rect
), NULL
, &bounds
);
7962 width
= bounds
.right
- bounds
.left
;
7963 height
= bounds
.bottom
- bounds
.top
;
7965 if (width
< size_hints
->min_width
)
7966 width
= size_hints
->min_width
;
7968 width
= size_hints
->base_width
7969 + (int) ((width
- size_hints
->base_width
)
7970 / (float) size_hints
->width_inc
+ .5)
7971 * size_hints
->width_inc
;
7973 if (height
< size_hints
->min_height
)
7974 height
= size_hints
->min_height
;
7976 height
= size_hints
->base_height
7977 + (int) ((height
- size_hints
->base_height
)
7978 / (float) size_hints
->height_inc
+ .5)
7979 * size_hints
->height_inc
;
7981 bounds
.right
= bounds
.left
+ width
;
7982 bounds
.bottom
= bounds
.top
+ height
;
7983 SetEventParameter (event
, kEventParamCurrentBounds
,
7984 typeQDRectangle
, sizeof (Rect
), &bounds
);
7990 return eventNotHandledErr
;
7992 #endif /* USE_CARBON_EVENTS */
7996 install_window_handler (window
)
8000 #if USE_CARBON_EVENTS
8001 EventTypeSpec specs
[] = {{kEventClassWindow
, kEventWindowUpdate
},
8002 {kEventClassWindow
, kEventWindowBoundsChanging
}};
8003 static EventHandlerUPP handle_window_event_UPP
= NULL
;
8005 if (handle_window_event_UPP
== NULL
)
8006 handle_window_event_UPP
= NewEventHandlerUPP (mac_handle_window_event
);
8008 err
= InstallWindowEventHandler (window
, handle_window_event_UPP
,
8009 GetEventTypeCount (specs
), specs
,
8012 #if TARGET_API_MAC_CARBON
8013 if (mac_do_track_dragUPP
== NULL
)
8014 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8015 if (mac_do_receive_dragUPP
== NULL
)
8016 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8019 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8021 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8027 remove_window_handler (window
)
8030 #if TARGET_API_MAC_CARBON
8031 if (mac_do_track_dragUPP
)
8032 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8033 if (mac_do_receive_dragUPP
)
8034 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8038 /* Open Application Apple Event */
8040 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8046 /* Defined in mac.c. */
8048 path_from_vol_dir_name (char *, int, short, long, char *);
8051 /* Called when we receive an AppleEvent with an ID of
8052 "kAEOpenDocuments". This routine gets the direct parameter,
8053 extracts the FSSpecs in it, and puts their names on a list. */
8054 #pragma options align=mac68k
8055 typedef struct SelectionRange
{
8056 short unused1
; // 0 (not used)
8057 short lineNum
; // line to select (<0 to specify range)
8058 long startRange
; // start of selection range (if line < 0)
8059 long endRange
; // end of selection range (if line < 0)
8060 long unused2
; // 0 (not used)
8061 long theDate
; // modification date/time
8063 #pragma options align=reset
8066 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8071 DescType actual_type
;
8073 SelectionRange position
;
8075 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8077 goto descriptor_error_exit
;
8079 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8081 drag_and_drop_file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8082 make_number (position
.startRange
+ 1),
8083 make_number (position
.endRange
+ 1)),
8084 drag_and_drop_file_list
);
8086 /* Check to see that we got all of the required parameters from the
8087 event descriptor. For an 'odoc' event this should just be the
8089 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8090 &actual_type
, (Ptr
) &keyword
,
8091 sizeof (keyword
), &actual_size
);
8092 /* No error means that we found some unused parameters.
8093 errAEDescNotFound means that there are no more parameters. If we
8094 get an error code other than that, flag it. */
8095 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8097 err
= errAEEventNotHandled
;
8102 /* Got all the parameters we need. Now, go through the direct
8103 object list and parse it up. */
8105 long num_files_to_open
;
8107 err
= AECountItems (&the_desc
, &num_files_to_open
);
8112 /* AE file list is one based so just use that for indexing here. */
8113 for (i
= 1; i
<= num_files_to_open
; i
++)
8115 char unix_path_name
[MAXPATHLEN
];
8119 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8120 &actual_type
, &fref
, sizeof (FSRef
),
8122 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8125 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8130 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8131 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8132 if (err
!= noErr
) continue;
8134 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
8135 sizeof (unix_path_name
) - 1) == noErr
)
8137 /* x-dnd functions expect undecoded filenames. */
8138 drag_and_drop_file_list
=
8139 Fcons (make_unibyte_string (unix_path_name
,
8140 strlen (unix_path_name
)),
8141 drag_and_drop_file_list
);
8147 /* Nuke the coerced file list in any case */
8148 err2
= AEDisposeDesc(&the_desc
);
8150 descriptor_error_exit
:
8151 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8156 #if TARGET_API_MAC_CARBON
8158 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8159 void *handlerRefCon
, DragReference theDrag
)
8161 static int can_accept
;
8164 ItemReference theItem
;
8165 FlavorFlags theFlags
;
8168 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8169 return dragNotAcceptedErr
;
8173 case kDragTrackingEnterHandler
:
8174 CountDragItems (theDrag
, &items
);
8176 for (index
= 1; index
<= items
; index
++)
8178 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8179 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8180 if (result
== noErr
)
8188 case kDragTrackingEnterWindow
:
8191 RgnHandle hilite_rgn
= NewRgn ();
8193 struct frame
*f
= mac_window_to_frame (window
);
8195 GetWindowPortBounds (window
, &r
);
8196 OffsetRect (&r
, -r
.left
, -r
.top
);
8197 RectRgn (hilite_rgn
, &r
);
8198 ShowDragHilite (theDrag
, hilite_rgn
, true);
8199 DisposeRgn (hilite_rgn
);
8200 SetThemeCursor (kThemeCopyArrowCursor
);
8204 case kDragTrackingInWindow
:
8207 case kDragTrackingLeaveWindow
:
8210 struct frame
*f
= mac_window_to_frame (window
);
8212 HideDragHilite (theDrag
);
8213 SetThemeCursor (kThemeArrowCursor
);
8217 case kDragTrackingLeaveHandler
:
8225 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8226 DragReference theDrag
)
8230 FlavorFlags theFlags
;
8233 ItemReference theItem
;
8235 Size size
= sizeof (HFSFlavor
);
8237 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8238 return dragNotAcceptedErr
;
8240 drag_and_drop_file_list
= Qnil
;
8241 GetDragMouse (theDrag
, &mouse
, 0L);
8242 CountDragItems (theDrag
, &items
);
8243 for (index
= 1; index
<= items
; index
++)
8245 /* Only handle file references. */
8246 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8247 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8248 if (result
== noErr
)
8253 char unix_path_name
[MAXPATHLEN
];
8255 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8257 /* Use Carbon routines, otherwise it converts the file name
8258 to /Macintosh HD/..., which is not correct. */
8259 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8260 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8262 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
8263 sizeof (unix_path_name
) - 1) == noErr
)
8265 /* x-dnd functions expect undecoded filenames. */
8266 drag_and_drop_file_list
=
8267 Fcons (make_unibyte_string (unix_path_name
,
8268 strlen (unix_path_name
)),
8269 drag_and_drop_file_list
);
8272 /* If there are items in the list, construct an event and post it to
8273 the queue like an interrupt using kbd_buffer_store_event. */
8274 if (!NILP (drag_and_drop_file_list
))
8276 struct input_event event
;
8278 struct frame
*f
= mac_window_to_frame (window
);
8281 GlobalToLocal (&mouse
);
8282 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8284 event
.kind
= DRAG_N_DROP_EVENT
;
8286 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8287 event
.timestamp
= TickCount () * (1000 / 60);
8288 XSETINT (event
.x
, mouse
.h
);
8289 XSETINT (event
.y
, mouse
.v
);
8290 XSETFRAME (frame
, f
);
8291 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8293 /* Post to the interrupt queue */
8294 kbd_buffer_store_event (&event
);
8295 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8297 ProcessSerialNumber psn
;
8298 GetCurrentProcess (&psn
);
8299 SetFrontProcess (&psn
);
8305 return dragNotAcceptedErr
;
8310 /* Print Document Apple Event */
8312 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8314 return errAEEventNotHandled
;
8319 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8321 /* FixMe: Do we need an unwind-protect or something here? And what
8322 do we do about unsaved files. Currently just forces quit rather
8323 than doing recursive callback to get user input. */
8325 terminate_flag
= true;
8327 /* Fkill_emacs doesn't return. We have to return. (TI) */
8334 profiler_exit_proc ()
8336 ProfilerDump ("\pEmacs.prof");
8341 /* These few functions implement Emacs as a normal Mac application
8342 (almost): set up the heap and the Toolbox, handle necessary
8343 system events plus a few simple menu events. They also set up
8344 Emacs's access to functions defined in the rest of this file.
8345 Emacs uses function hooks to perform all its terminal I/O. A
8346 complete list of these functions appear in termhooks.h. For what
8347 they do, read the comments there and see also w32term.c and
8348 xterm.c. What's noticeably missing here is the event loop, which
8349 is normally present in most Mac application. After performing the
8350 necessary Mac initializations, main passes off control to
8351 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8352 mac_read_socket (defined further below) to read input. This is
8353 where WaitNextEvent is called to process Mac events. This is also
8354 where check_alarm in sysdep.c is called to simulate alarm signals.
8355 This makes the cursor jump back to its correct position after
8356 briefly jumping to that of the matching parenthesis, print useful
8357 hints and prompts in the minibuffer after the user stops typing for
8365 #if __profile__ /* is the profiler on? */
8366 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
8371 /* set creator and type for files created by MSL */
8376 do_init_managers ();
8381 do_check_ram_size ();
8384 init_emacs_passwd_dir ();
8388 initialize_applescript ();
8390 init_required_apple_events ();
8396 /* set up argv array from STR# resource */
8397 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
8401 /* free up AppleScript resources on exit */
8402 atexit (terminate_applescript
);
8404 #if __profile__ /* is the profiler on? */
8405 atexit (profiler_exit_proc
);
8408 /* 3rd param "envp" never used in emacs_main */
8409 (void) emacs_main (argc
, argv
, 0);
8412 /* Never reached - real exit in Fkill_emacs */
8417 /* Table for translating Mac keycode to X keysym values. Contributed
8419 Mapping for special keys is now identical to that in Apple X11
8420 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8421 on the right of the Cmd key on laptops, and fn + `enter' (->
8423 static unsigned char keycode_to_xkeysym_table
[] = {
8424 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8425 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8426 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8428 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8429 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8430 /*0x38*/ 0, 0, 0, 0,
8431 /*0x3C*/ 0, 0, 0, 0,
8433 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8434 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8435 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8436 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8438 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8439 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8440 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8441 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8443 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8444 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8445 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8446 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8448 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8449 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8450 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8451 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8455 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8457 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8458 return *xKeySym
!= 0;
8461 #if !USE_CARBON_EVENTS
8462 static RgnHandle mouse_region
= NULL
;
8465 mac_wait_next_event (er
, sleep_time
, dequeue
)
8470 static EventRecord er_buf
= {nullEvent
};
8471 UInt32 target_tick
, current_tick
;
8472 EventMask event_mask
;
8474 if (mouse_region
== NULL
)
8475 mouse_region
= NewRgn ();
8477 event_mask
= everyEvent
;
8478 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8479 event_mask
-= highLevelEventMask
;
8481 current_tick
= TickCount ();
8482 target_tick
= current_tick
+ sleep_time
;
8484 if (er_buf
.what
== nullEvent
)
8485 while (!WaitNextEvent (event_mask
, &er_buf
,
8486 target_tick
- current_tick
, mouse_region
))
8488 current_tick
= TickCount ();
8489 if (target_tick
<= current_tick
)
8495 er_buf
.what
= nullEvent
;
8498 #endif /* not USE_CARBON_EVENTS */
8500 /* Emacs calls this whenever it wants to read an input event from the
8503 XTread_socket (sd
, expected
, hold_quit
)
8505 struct input_event
*hold_quit
;
8507 struct input_event inev
;
8509 #if USE_CARBON_EVENTS
8511 EventTargetRef toolbox_dispatcher
;
8514 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8516 if (interrupt_input_blocked
)
8518 interrupt_input_pending
= 1;
8522 interrupt_input_pending
= 0;
8525 /* So people can tell when we have read the available input. */
8526 input_signal_count
++;
8528 /* Don't poll for events to process (specifically updateEvt) if
8529 window update currently already in progress. A call to redisplay
8530 (in do_window_update) can be preempted by another call to
8531 redisplay, causing blank regions to be left on the screen and the
8532 cursor to be left at strange places. */
8533 if (handling_window_update
)
8540 Fkill_emacs (make_number (1));
8542 #if USE_CARBON_EVENTS
8543 toolbox_dispatcher
= GetEventDispatcherTarget ();
8545 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8546 kEventRemoveFromQueue
, &eventRef
))
8547 #else /* !USE_CARBON_EVENTS */
8548 while (mac_wait_next_event (&er
, 0, true))
8549 #endif /* !USE_CARBON_EVENTS */
8554 /* It is necessary to set this (additional) argument slot of an
8555 event to nil because keyboard.c protects incompletely
8556 processed event from being garbage collected by placing them
8557 in the kbd_buffer_gcpro vector. */
8559 inev
.kind
= NO_EVENT
;
8562 #if USE_CARBON_EVENTS
8563 /* Handle new events */
8564 if (!mac_convert_event_ref (eventRef
, &er
))
8565 switch (GetEventClass (eventRef
))
8567 case kEventClassWindow
:
8568 if (GetEventKind (eventRef
) == kEventWindowBoundsChanged
)
8570 WindowPtr window_ptr
;
8571 GetEventParameter(eventRef
, kEventParamDirectObject
,
8572 typeWindowRef
, NULL
, sizeof(WindowPtr
),
8574 f
= mac_window_to_frame (window_ptr
);
8575 if (f
&& !f
->async_iconified
)
8576 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8577 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8580 case kEventClassMouse
:
8581 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
8585 WindowPtr window_ptr
= front_emacs_window ();
8587 if (!IsValidWindowPtr (window_ptr
))
8593 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
8594 typeSInt32
, NULL
, sizeof (SInt32
),
8596 GetEventParameter(eventRef
, kEventParamMouseLocation
,
8597 typeQDPoint
, NULL
, sizeof (Point
),
8599 inev
.kind
= WHEEL_EVENT
;
8601 inev
.modifiers
= (mac_event_to_emacs_modifiers (eventRef
)
8602 | ((delta
< 0) ? down_modifier
8604 SetPortWindowPort (window_ptr
);
8605 GlobalToLocal (&point
);
8606 XSETINT (inev
.x
, point
.h
);
8607 XSETINT (inev
.y
, point
.v
);
8608 XSETFRAME (inev
.frame_or_window
,
8609 mac_window_to_frame (window_ptr
));
8610 inev
.timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
8613 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8618 /* Send the event to the appropriate receiver. */
8619 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8622 #endif /* USE_CARBON_EVENTS */
8628 WindowPtr window_ptr
;
8632 #if USE_CARBON_EVENTS
8633 /* This is needed to send mouse events like aqua window
8634 buttons to the correct handler. */
8635 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8636 != eventNotHandledErr
)
8640 if (dpyinfo
->grabbed
&& last_mouse_frame
8641 && FRAME_LIVE_P (last_mouse_frame
))
8643 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
8644 part_code
= inContent
;
8648 part_code
= FindWindow (er
.where
, &window_ptr
);
8649 if (tip_window
&& window_ptr
== tip_window
)
8651 HideWindow (tip_window
);
8652 part_code
= FindWindow (er
.where
, &window_ptr
);
8656 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
8662 f
= mac_window_to_frame (front_emacs_window ());
8663 saved_menu_event_location
= er
.where
;
8664 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
8665 XSETFRAME (inev
.frame_or_window
, f
);
8669 if (window_ptr
!= front_emacs_window ())
8670 SelectWindow (window_ptr
);
8673 SInt16 control_part_code
;
8675 Point mouse_loc
= er
.where
;
8677 f
= mac_window_to_frame (window_ptr
);
8678 /* convert to local coordinates of new window */
8679 SetPortWindowPort (window_ptr
);
8681 GlobalToLocal (&mouse_loc
);
8682 #if TARGET_API_MAC_CARBON
8683 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
8684 &control_part_code
);
8686 control_part_code
= FindControl (mouse_loc
, window_ptr
,
8690 #if USE_CARBON_EVENTS
8691 inev
.code
= mac_get_mouse_btn (eventRef
);
8692 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
8694 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
8695 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
8697 XSETINT (inev
.x
, mouse_loc
.h
);
8698 XSETINT (inev
.y
, mouse_loc
.v
);
8699 inev
.timestamp
= er
.when
* (1000 / 60);
8700 /* ticks to milliseconds */
8702 if (dpyinfo
->grabbed
&& tracked_scroll_bar
8703 /* control_part_code becomes kControlNoPart if
8704 a progress indicator is clicked. */
8705 || ch
!= 0 && control_part_code
!= kControlNoPart
)
8707 struct scroll_bar
*bar
;
8709 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
8711 bar
= tracked_scroll_bar
;
8712 control_part_code
= kControlIndicatorPart
;
8715 bar
= (struct scroll_bar
*) GetControlReference (ch
);
8716 x_scroll_bar_handle_click (bar
, control_part_code
,
8718 if (er
.what
== mouseDown
8719 && control_part_code
== kControlIndicatorPart
)
8720 tracked_scroll_bar
= bar
;
8722 tracked_scroll_bar
= NULL
;
8727 int x
= mouse_loc
.h
;
8728 int y
= mouse_loc
.v
;
8730 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
8731 if (EQ (window
, f
->tool_bar_window
))
8733 if (er
.what
== mouseDown
)
8734 handle_tool_bar_click (f
, x
, y
, 1, 0);
8736 handle_tool_bar_click (f
, x
, y
, 0,
8742 XSETFRAME (inev
.frame_or_window
, f
);
8743 inev
.kind
= MOUSE_CLICK_EVENT
;
8747 if (er
.what
== mouseDown
)
8749 dpyinfo
->grabbed
|= (1 << inev
.code
);
8750 last_mouse_frame
= f
;
8751 /* Ignore any mouse motion that happened
8752 before this event; any subsequent
8753 mouse-movement Emacs events should reflect
8754 only motion after the ButtonPress. */
8759 last_tool_bar_item
= -1;
8763 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
8764 /* If a button is released though it was not
8765 previously pressed, that would be because
8766 of multi-button emulation. */
8767 dpyinfo
->grabbed
= 0;
8769 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
8775 inev
.modifiers
|= down_modifier
;
8778 inev
.modifiers
|= up_modifier
;
8785 #if TARGET_API_MAC_CARBON
8786 DragWindow (window_ptr
, er
.where
, NULL
);
8787 #else /* not TARGET_API_MAC_CARBON */
8788 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
8789 #endif /* not TARGET_API_MAC_CARBON */
8790 /* Update the frame parameters. */
8792 struct frame
*f
= mac_window_to_frame (window_ptr
);
8794 if (f
&& !f
->async_iconified
)
8795 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8800 if (TrackGoAway (window_ptr
, er
.where
))
8802 inev
.kind
= DELETE_WINDOW_EVENT
;
8803 XSETFRAME (inev
.frame_or_window
,
8804 mac_window_to_frame (window_ptr
));
8808 /* window resize handling added --ben */
8810 do_grow_window (window_ptr
, &er
);
8813 /* window zoom handling added --ben */
8816 if (TrackBox (window_ptr
, er
.where
, part_code
))
8817 do_zoom_window (window_ptr
, part_code
);
8827 #if USE_CARBON_EVENTS
8828 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8829 != eventNotHandledErr
)
8832 do_window_update ((WindowPtr
) er
.message
);
8837 #if USE_CARBON_EVENTS
8838 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8839 != eventNotHandledErr
)
8842 switch ((er
.message
>> 24) & 0x000000FF)
8844 case suspendResumeMessage
:
8845 if ((er
.message
& resumeFlag
) == 1)
8851 case mouseMovedMessage
:
8852 #if !USE_CARBON_EVENTS
8853 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
8854 er
.where
.h
+ 1, er
.where
.v
+ 1);
8856 previous_help_echo_string
= help_echo_string
;
8857 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
8860 do_mouse_moved (er
.where
, &f
);
8862 /* If the contents of the global variable
8863 help_echo_string has changed, generate a
8865 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
8873 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
8874 ControlRef root_control
;
8876 #if USE_CARBON_EVENTS
8877 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8878 != eventNotHandledErr
)
8881 if (window_ptr
== tip_window
)
8883 HideWindow (tip_window
);
8887 if (!is_emacs_window (window_ptr
))
8890 f
= mac_window_to_frame (window_ptr
);
8891 GetRootControl (window_ptr
, &root_control
);
8893 if ((er
.modifiers
& activeFlag
) != 0)
8895 /* A window has been activated */
8896 Point mouse_loc
= er
.where
;
8898 x_new_focus_frame (dpyinfo
, f
);
8899 ActivateControl (root_control
);
8901 SetPortWindowPort (window_ptr
);
8902 GlobalToLocal (&mouse_loc
);
8903 /* Window-activated event counts as mouse movement,
8904 so update things that depend on mouse position. */
8905 note_mouse_movement (mac_window_to_frame (window_ptr
),
8910 /* A window has been deactivated */
8911 dpyinfo
->grabbed
= 0;
8913 if (f
== dpyinfo
->x_focus_frame
)
8915 x_new_focus_frame (dpyinfo
, 0);
8916 DeactivateControl (root_control
);
8920 if (f
== dpyinfo
->mouse_face_mouse_frame
)
8922 /* If we move outside the frame, then we're
8923 certainly no longer on any text in the
8925 clear_mouse_face (dpyinfo
);
8926 dpyinfo
->mouse_face_mouse_frame
= 0;
8929 /* Generate a nil HELP_EVENT to cancel a help-echo.
8930 Do it only if there's something to cancel.
8931 Otherwise, the startup message is cleared when the
8932 mouse leaves the frame. */
8933 if (any_help_event_p
)
8942 int keycode
= (er
.message
& keyCodeMask
) >> 8;
8945 #if USE_CARBON_EVENTS && defined (MAC_OSX)
8946 /* When using Carbon Events, we need to pass raw keyboard
8947 events to the TSM ourselves. If TSM handles it, it
8948 will pass back noErr, otherwise it will pass back
8949 "eventNotHandledErr" and we can process it
8951 if ((!NILP (Vmac_pass_command_to_system
)
8952 || !(er
.modifiers
& cmdKey
))
8953 && (!NILP (Vmac_pass_control_to_system
)
8954 || !(er
.modifiers
& controlKey
)))
8955 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8956 != eventNotHandledErr
)
8960 #if TARGET_API_MAC_CARBON
8961 if (!IsValidWindowPtr (front_emacs_window ()))
8970 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
8972 clear_mouse_face (dpyinfo
);
8973 dpyinfo
->mouse_face_hidden
= 1;
8976 if (keycode_to_xkeysym (keycode
, &xkeysym
))
8978 inev
.code
= 0xff00 | xkeysym
;
8979 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
8983 if (er
.modifiers
& (controlKey
|
8984 (NILP (Vmac_command_key_is_meta
) ? optionKey
8987 /* This code comes from Keyboard Resource,
8988 Appendix C of IM - Text. This is necessary
8989 since shift is ignored in KCHR table
8990 translation when option or command is pressed.
8991 It also does not translate correctly
8992 control-shift chars like C-% so mask off shift
8994 int new_modifiers
= er
.modifiers
& 0xe600;
8995 /* mask off option and command */
8996 int new_keycode
= keycode
| new_modifiers
;
8997 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
8998 unsigned long some_state
= 0;
8999 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9000 &some_state
) & 0xff;
9001 } else if (!NILP(Vmac_option_modifier
) && (er
.modifiers
& optionKey
))
9003 /* When using the option key as an emacs modifier, convert
9004 the pressed key code back to one without the Mac option
9005 modifier applied. */
9006 int new_modifiers
= er
.modifiers
& ~optionKey
;
9007 int new_keycode
= keycode
| new_modifiers
;
9008 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9009 unsigned long some_state
= 0;
9010 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9011 &some_state
) & 0xff;
9014 inev
.code
= er
.message
& charCodeMask
;
9015 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9019 /* If variable mac-convert-keyboard-input-to-latin-1 is
9020 non-nil, convert non-ASCII characters typed at the Mac
9021 keyboard (presumed to be in the Mac Roman encoding) to
9022 iso-latin-1 encoding before they are passed to Emacs.
9023 This enables the Mac keyboard to be used to enter
9024 non-ASCII iso-latin-1 characters directly. */
9025 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
9026 && inev
.kind
== ASCII_KEYSTROKE_EVENT
&& inev
.code
>= 128)
9028 static TECObjectRef converter
= NULL
;
9029 OSStatus the_err
= noErr
;
9030 OSStatus convert_status
= noErr
;
9032 if (converter
== NULL
)
9034 the_err
= TECCreateConverter (&converter
,
9035 kTextEncodingMacRoman
,
9036 mac_keyboard_text_encoding
);
9037 current_mac_keyboard_text_encoding
9038 = mac_keyboard_text_encoding
;
9040 else if (mac_keyboard_text_encoding
9041 != current_mac_keyboard_text_encoding
)
9043 /* Free the converter for the current encoding
9044 before creating a new one. */
9045 TECDisposeConverter (converter
);
9046 the_err
= TECCreateConverter (&converter
,
9047 kTextEncodingMacRoman
,
9048 mac_keyboard_text_encoding
);
9049 current_mac_keyboard_text_encoding
9050 = mac_keyboard_text_encoding
;
9053 if (the_err
== noErr
)
9055 unsigned char ch
= inev
.code
;
9056 ByteCount actual_input_length
, actual_output_length
;
9057 unsigned char outbuf
[32];
9059 convert_status
= TECConvertText (converter
, &ch
, 1,
9060 &actual_input_length
,
9062 &actual_output_length
);
9063 if (convert_status
== noErr
9064 && actual_input_length
== 1
9065 && actual_output_length
== 1)
9066 inev
.code
= *outbuf
;
9068 /* Reset internal states of the converter object.
9069 If it fails, create another one. */
9070 convert_status
= TECFlushText (converter
, outbuf
,
9072 &actual_output_length
);
9073 if (convert_status
!= noErr
)
9075 TECDisposeConverter (converter
);
9076 TECCreateConverter (&converter
,
9077 kTextEncodingMacRoman
,
9078 mac_keyboard_text_encoding
);
9083 #if USE_CARBON_EVENTS
9084 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9086 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9088 XSETFRAME (inev
.frame_or_window
,
9089 mac_window_to_frame (front_emacs_window ()));
9090 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9093 case kHighLevelEvent
:
9094 drag_and_drop_file_list
= Qnil
;
9096 AEProcessAppleEvent(&er
);
9098 /* Build a DRAG_N_DROP_EVENT type event as is done in
9099 constuct_drag_n_drop in w32term.c. */
9100 if (!NILP (drag_and_drop_file_list
))
9102 struct frame
*f
= NULL
;
9106 wp
= front_emacs_window ();
9110 struct frame
*f
= XFRAME (XCAR (Vframe_list
));
9111 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
9112 wp
= front_emacs_window ();
9116 f
= mac_window_to_frame (wp
);
9118 inev
.kind
= DRAG_N_DROP_EVENT
;
9120 inev
.timestamp
= er
.when
* (1000 / 60);
9121 /* ticks to milliseconds */
9122 #if USE_CARBON_EVENTS
9123 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9125 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9128 XSETINT (inev
.x
, 0);
9129 XSETINT (inev
.y
, 0);
9131 XSETFRAME (frame
, f
);
9132 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9134 /* Regardless of whether Emacs was suspended or in the
9135 foreground, ask it to redraw its entire screen.
9136 Otherwise parts of the screen can be left in an
9137 inconsistent state. */
9139 #if TARGET_API_MAC_CARBON
9143 GetWindowPortBounds (wp
, &r
);
9144 InvalWindowRect (wp
, &r
);
9146 #else /* not TARGET_API_MAC_CARBON */
9147 InvalRect (&(wp
->portRect
));
9148 #endif /* not TARGET_API_MAC_CARBON */
9153 #if USE_CARBON_EVENTS
9154 ReleaseEvent (eventRef
);
9157 if (inev
.kind
!= NO_EVENT
)
9159 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9164 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9169 XSETFRAME (frame
, f
);
9175 any_help_event_p
= 1;
9176 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9177 help_echo_object
, help_echo_pos
);
9181 help_echo_string
= Qnil
;
9182 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9189 /* If the focus was just given to an autoraising frame,
9191 /* ??? This ought to be able to handle more than one such frame. */
9192 if (pending_autoraise_frame
)
9194 x_raise_frame (pending_autoraise_frame
);
9195 pending_autoraise_frame
= 0;
9198 #if !TARGET_API_MAC_CARBON
9199 check_alarm (); /* simulate the handling of a SIGALRM */
9207 /* Need to override CodeWarrior's input function so no conversion is
9208 done on newlines Otherwise compiled functions in .elc files will be
9209 read incorrectly. Defined in ...:MSL C:MSL
9210 Common:Source:buffer_io.c. */
9213 __convert_to_newlines (unsigned char * p
, size_t * n
)
9219 __convert_from_newlines (unsigned char * p
, size_t * n
)
9227 make_mac_terminal_frame (struct frame
*f
)
9232 XSETFRAME (frame
, f
);
9234 f
->output_method
= output_mac
;
9235 f
->output_data
.mac
= (struct mac_output
*)
9236 xmalloc (sizeof (struct mac_output
));
9237 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9239 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9241 FRAME_COLS (f
) = 96;
9242 FRAME_LINES (f
) = 4;
9244 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9245 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9247 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9249 f
->output_data
.mac
->cursor_pixel
= 0;
9250 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9251 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9252 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9254 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9255 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9256 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9257 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9258 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9259 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9261 FRAME_FONTSET (f
) = -1;
9262 f
->output_data
.mac
->explicit_parent
= 0;
9265 f
->border_width
= 0;
9267 f
->internal_border_width
= 0;
9272 f
->new_text_cols
= 0;
9273 f
->new_text_lines
= 0;
9275 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9276 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9277 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9281 if (!(FRAME_MAC_WINDOW (f
) =
9282 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9283 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9285 /* so that update events can find this mac_output struct */
9286 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9292 /* Need to be initialized for unshow_buffer in window.c. */
9293 selected_window
= f
->selected_window
;
9295 Fmodify_frame_parameters (frame
,
9296 Fcons (Fcons (Qfont
,
9297 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9298 Fmodify_frame_parameters (frame
,
9299 Fcons (Fcons (Qforeground_color
,
9300 build_string ("black")), Qnil
));
9301 Fmodify_frame_parameters (frame
,
9302 Fcons (Fcons (Qbackground_color
,
9303 build_string ("white")), Qnil
));
9308 /***********************************************************************
9310 ***********************************************************************/
9312 int mac_initialized
= 0;
9315 mac_initialize_display_info ()
9317 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9318 GDHandle main_device_handle
;
9320 bzero (dpyinfo
, sizeof (*dpyinfo
));
9323 dpyinfo
->mac_id_name
9324 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9325 + SCHARS (Vsystem_name
)
9327 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9328 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9330 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9331 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9334 main_device_handle
= LMGetMainDevice();
9336 dpyinfo
->reference_count
= 0;
9337 dpyinfo
->resx
= 75.0;
9338 dpyinfo
->resy
= 75.0;
9339 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9341 /* HasDepth returns true if it is possible to have a 32 bit display,
9342 but this may not be what is actually used. Mac OSX can do better.
9343 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9344 header for CGGetActiveDisplayList says that the first display returned
9345 is the active one, so we use that. */
9347 CGDirectDisplayID disp_id
[1];
9348 CGDisplayCount disp_count
;
9349 CGDisplayErr error_code
;
9351 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
9352 if (error_code
!= 0)
9353 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
9355 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
9358 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
9359 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
9360 gdDevType
, dpyinfo
->color_p
))
9363 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
9364 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
9365 dpyinfo
->grabbed
= 0;
9366 dpyinfo
->root_window
= NULL
;
9367 dpyinfo
->image_cache
= make_image_cache ();
9369 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
9370 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
9371 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
9372 dpyinfo
->mouse_face_window
= Qnil
;
9373 dpyinfo
->mouse_face_overlay
= Qnil
;
9374 dpyinfo
->mouse_face_hidden
= 0;
9379 mac_make_rdb (xrm_option
)
9382 XrmDatabase database
;
9384 database
= xrm_get_preference_database (NULL
);
9386 xrm_merge_string_database (database
, xrm_option
);
9391 struct mac_display_info
*
9392 mac_term_init (display_name
, xrm_option
, resource_name
)
9393 Lisp_Object display_name
;
9395 char *resource_name
;
9397 struct mac_display_info
*dpyinfo
;
9401 if (!mac_initialized
)
9404 mac_initialized
= 1;
9408 error ("Sorry, this version can only handle one display");
9410 mac_initialize_display_info ();
9412 dpyinfo
= &one_mac_display_info
;
9414 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
9416 /* Put this display on the chain. */
9417 dpyinfo
->next
= x_display_list
;
9418 x_display_list
= dpyinfo
;
9420 /* Put it on x_display_name_list. */
9421 x_display_name_list
= Fcons (Fcons (display_name
,
9422 Fcons (Qnil
, dpyinfo
->xrdb
)),
9423 x_display_name_list
);
9424 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
9430 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9433 x_delete_display (dpyinfo
)
9434 struct mac_display_info
*dpyinfo
;
9438 /* Discard this display from x_display_name_list and x_display_list.
9439 We can't use Fdelq because that can quit. */
9440 if (! NILP (x_display_name_list
)
9441 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
9442 x_display_name_list
= XCDR (x_display_name_list
);
9447 tail
= x_display_name_list
;
9448 while (CONSP (tail
) && CONSP (XCDR (tail
)))
9450 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
9452 XSETCDR (tail
, XCDR (XCDR (tail
)));
9459 if (x_display_list
== dpyinfo
)
9460 x_display_list
= dpyinfo
->next
;
9463 struct x_display_info
*tail
;
9465 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
9466 if (tail
->next
== dpyinfo
)
9467 tail
->next
= tail
->next
->next
;
9470 /* Free the font names in the font table. */
9471 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9472 if (dpyinfo
->font_table
[i
].name
)
9474 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
9475 xfree (dpyinfo
->font_table
[i
].full_name
);
9476 xfree (dpyinfo
->font_table
[i
].name
);
9479 if (dpyinfo
->font_table
->font_encoder
)
9480 xfree (dpyinfo
->font_table
->font_encoder
);
9482 xfree (dpyinfo
->font_table
);
9483 xfree (dpyinfo
->mac_id_name
);
9485 if (x_display_list
== 0)
9487 mac_clear_font_name_table ();
9488 bzero (dpyinfo
, sizeof (*dpyinfo
));
9497 extern int inhibit_window_system
;
9498 extern int noninteractive
;
9499 CFBundleRef appsBundle
;
9502 /* No need to test if already -nw*/
9503 if (inhibit_window_system
|| noninteractive
)
9506 appsBundle
= CFBundleGetMainBundle();
9507 if (appsBundle
!= NULL
)
9509 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
9510 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
9511 /* We found the bundle identifier, now we know we are valid. */
9518 /* MAC_TODO: Have this start the bundled executable */
9520 /* For now, prevent the fatal error by bringing it up in the terminal */
9521 inhibit_window_system
= 1;
9525 MakeMeTheFrontProcess ()
9527 ProcessSerialNumber psn
;
9530 err
= GetCurrentProcess (&psn
);
9532 (void) SetFrontProcess (&psn
);
9535 /***** Code to handle C-g testing *****/
9537 /* Contains the Mac modifier formed from quit_char */
9538 static mac_quit_char_modifiers
= 0;
9539 static mac_quit_char_keycode
;
9540 extern int quit_char
;
9543 mac_determine_quit_char_modifiers()
9545 /* Todo: Determine modifiers from quit_char. */
9546 UInt32 qc_modifiers
= ctrl_modifier
;
9549 mac_quit_char_modifiers
= 0;
9550 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
9551 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
9552 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
9553 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
9557 init_quit_char_handler ()
9559 /* TODO: Let this support keys other the 'g' */
9560 mac_quit_char_keycode
= 5;
9561 /* Look at <architecture/adb_kb_map.h> for details */
9562 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9564 mac_determine_quit_char_modifiers();
9568 quit_char_comp (EventRef inEvent
, void *inCompData
)
9570 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
9572 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
9576 UInt32 keyModifiers
;
9577 GetEventParameter(inEvent
, kEventParamKeyCode
,
9578 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
9579 if (keyCode
!= mac_quit_char_keycode
)
9581 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
9582 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
9583 if (keyModifiers
!= mac_quit_char_modifiers
)
9590 mac_check_for_quit_char ()
9593 static EMACS_TIME last_check_time
= { 0, 0 };
9594 static EMACS_TIME one_second
= { 1, 0 };
9597 /* If windows are not initialized, return immediately (keep it bouncin'). */
9598 if (!mac_quit_char_modifiers
)
9601 /* Don't check if last check is less than a second ago. */
9602 EMACS_GET_TIME (now
);
9603 EMACS_SUB_TIME (t
, now
, last_check_time
);
9604 if (EMACS_TIME_LT (t
, one_second
))
9606 last_check_time
= now
;
9608 /* Redetermine modifiers because they are based on lisp variables */
9609 mac_determine_quit_char_modifiers ();
9611 /* Fill the queue with events */
9613 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
9614 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
9619 struct input_event e
;
9621 /* Use an input_event to emulate what the interrupt handler does. */
9623 e
.kind
= ASCII_KEYSTROKE_EVENT
;
9627 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
9628 XSETFRAME (e
.frame_or_window
, mac_window_to_frame (front_emacs_window ()));
9629 /* Remove event from queue to prevent looping. */
9630 RemoveEventFromQueue (GetMainEventQueue (), event
);
9631 ReleaseEvent (event
);
9632 kbd_buffer_store_event (&e
);
9636 #endif /* MAC_OSX */
9638 /* Set up use of X before we make the first connection. */
9640 extern frame_parm_handler mac_frame_parm_handlers
[];
9642 static struct redisplay_interface x_redisplay_interface
=
9644 mac_frame_parm_handlers
,
9648 x_clear_end_of_line
,
9650 x_after_update_window_line
,
9651 x_update_window_begin
,
9652 x_update_window_end
,
9655 0, /* flush_display_optional */
9656 x_clear_window_mouse_face
,
9657 x_get_glyph_overhangs
,
9658 x_fix_overlapping_area
,
9659 x_draw_fringe_bitmap
,
9660 0, /* define_fringe_bitmap */
9661 0, /* destroy_fringe_bitmap */
9662 mac_per_char_metric
,
9664 mac_compute_glyph_string_overhangs
,
9665 x_draw_glyph_string
,
9666 mac_define_frame_cursor
,
9667 mac_clear_frame_area
,
9668 mac_draw_window_cursor
,
9669 mac_draw_vertical_window_border
,
9670 mac_shift_glyphs_for_insert
9676 rif
= &x_redisplay_interface
;
9678 clear_frame_hook
= x_clear_frame
;
9679 ins_del_lines_hook
= x_ins_del_lines
;
9680 delete_glyphs_hook
= x_delete_glyphs
;
9681 ring_bell_hook
= XTring_bell
;
9682 reset_terminal_modes_hook
= XTreset_terminal_modes
;
9683 set_terminal_modes_hook
= XTset_terminal_modes
;
9684 update_begin_hook
= x_update_begin
;
9685 update_end_hook
= x_update_end
;
9686 set_terminal_window_hook
= XTset_terminal_window
;
9687 read_socket_hook
= XTread_socket
;
9688 frame_up_to_date_hook
= XTframe_up_to_date
;
9689 mouse_position_hook
= XTmouse_position
;
9690 frame_rehighlight_hook
= XTframe_rehighlight
;
9691 frame_raise_lower_hook
= XTframe_raise_lower
;
9693 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
9694 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
9695 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
9696 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
9698 scroll_region_ok
= 1; /* we'll scroll partial frames */
9699 char_ins_del_ok
= 1;
9700 line_ins_del_ok
= 1; /* we'll just blt 'em */
9701 fast_clear_end_of_line
= 1; /* X does this well */
9702 memory_below_frame
= 0; /* we don't remember what scrolls
9707 last_tool_bar_item
= -1;
9708 any_help_event_p
= 0;
9710 /* Try to use interrupt input; if we can't, then start polling. */
9711 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
9713 #ifdef USE_X_TOOLKIT
9714 XtToolkitInitialize ();
9715 Xt_app_con
= XtCreateApplicationContext ();
9716 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
9718 /* Install an asynchronous timer that processes Xt timeout events
9719 every 0.1s. This is necessary because some widget sets use
9720 timeouts internally, for example the LessTif menu bar, or the
9721 Xaw3d scroll bar. When Xt timouts aren't processed, these
9722 widgets don't behave normally. */
9724 EMACS_TIME interval
;
9725 EMACS_SET_SECS_USECS (interval
, 0, 100000);
9726 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
9730 #if USE_TOOLKIT_SCROLL_BARS
9731 xaw3d_arrow_scroll
= False
;
9732 xaw3d_pick_top
= True
;
9736 /* Note that there is no real way portable across R3/R4 to get the
9737 original error handler. */
9738 XSetErrorHandler (x_error_handler
);
9739 XSetIOErrorHandler (x_io_error_quitter
);
9741 /* Disable Window Change signals; they are handled by X events. */
9743 signal (SIGWINCH
, SIG_DFL
);
9744 #endif /* ! defined (SIGWINCH) */
9746 signal (SIGPIPE
, x_connection_signal
);
9751 #if TARGET_API_MAC_CARBON
9752 init_required_apple_events ();
9754 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9755 init_service_handler ();
9757 init_quit_char_handler ();
9760 DisableMenuCommand (NULL
, kHICommandQuit
);
9763 if (!inhibit_window_system
)
9764 MakeMeTheFrontProcess ();
9775 staticpro (&x_error_message_string
);
9776 x_error_message_string
= Qnil
;
9779 Qmodifier_value
= intern ("modifier-value");
9780 Qalt
= intern ("alt");
9781 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
9782 Qhyper
= intern ("hyper");
9783 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
9784 Qsuper
= intern ("super");
9785 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
9788 Fprovide (intern ("mac-carbon"), Qnil
);
9791 staticpro (&Qreverse
);
9792 Qreverse
= intern ("reverse");
9794 staticpro (&x_display_name_list
);
9795 x_display_name_list
= Qnil
;
9797 staticpro (&last_mouse_scroll_bar
);
9798 last_mouse_scroll_bar
= Qnil
;
9800 staticpro (&Qvendor_specific_keysyms
);
9801 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
9803 staticpro (&last_mouse_press_frame
);
9804 last_mouse_press_frame
= Qnil
;
9806 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
9807 staticpro (&Qmac_ready_for_drag_n_drop
);
9809 Qbig5
= intern ("big5");
9812 Qcn_gb
= intern ("cn-gb");
9813 staticpro (&Qcn_gb
);
9815 Qsjis
= intern ("sjis");
9818 Qeuc_kr
= intern ("euc-kr");
9819 staticpro (&Qeuc_kr
);
9821 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
9822 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
9823 x_autoselect_window_p
= 0;
9825 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
9826 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
9827 Vx_toolkit_scroll_bars
= Qt
;
9829 DEFVAR_BOOL ("x-use-underline-position-properties",
9830 &x_use_underline_position_properties
,
9831 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9832 nil means ignore them. If you encounter fonts with bogus
9833 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9834 to 4.1, set this to nil. */);
9835 x_use_underline_position_properties
= 0;
9837 staticpro (&last_mouse_motion_frame
);
9838 last_mouse_motion_frame
= Qnil
;
9840 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
9841 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
9842 Otherwise the option key is used. */);
9843 Vmac_command_key_is_meta
= Qt
;
9845 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
9846 doc
: /* Modifier to use for the Mac alt/option key. The value can
9847 be alt, hyper, or super for the respective modifier. If the value is
9848 nil then the key will act as the normal Mac option modifier. */);
9849 Vmac_option_modifier
= Qnil
;
9851 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
9852 doc
: /* Non-nil means that the control and meta keys are reversed. This is
9853 useful for non-standard keyboard layouts. */);
9854 Vmac_reverse_ctrl_meta
= Qnil
;
9856 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9857 &Vmac_emulate_three_button_mouse
,
9858 doc
: /* t means that when the option-key is held down while pressing the
9859 mouse button, the click will register as mouse-2 and while the
9860 command-key is held down, the click will register as mouse-3.
9861 'reverse means that the the option-key will register for mouse-3
9862 and the command-key will register for mouse-2. nil means that
9863 no emulation should be done and the modifiers should be placed
9864 on the mouse-1 event. */);
9865 Vmac_emulate_three_button_mouse
= Qnil
;
9867 #if USE_CARBON_EVENTS
9868 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
9869 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
9870 the right click will be mouse-3.
9871 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9872 Vmac_wheel_button_is_mouse_2
= Qt
;
9874 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
9875 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9876 Toolbox for processing before Emacs sees it. */);
9877 Vmac_pass_command_to_system
= Qt
;
9879 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9880 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9881 Toolbox for processing before Emacs sees it. */);
9882 Vmac_pass_control_to_system
= Qt
;
9884 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9885 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9886 Toolbox for processing before Emacs sees it. */);
9887 Vmac_pass_control_to_system
= Qt
;
9890 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
9891 doc
: /* If non-nil, allow anti-aliasing.
9892 The text will be rendered using Core Graphics text rendering which
9893 may anti-alias the text. */);
9894 Vmac_use_core_graphics
= Qnil
;
9896 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
9897 doc
: /* One of the Text Encoding Base constant values defined in the
9898 Basic Text Constants section of Inside Macintosh - Text Encoding
9899 Conversion Manager. Its value determines the encoding characters
9900 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9901 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9902 its default value, no conversion takes place. If it is set to
9903 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9904 characters typed on Mac keyboard are first converted into the
9905 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9906 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9907 command, this enables the Mac keyboard to be used to enter non-ASCII
9908 characters directly. */);
9909 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
9912 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9913 (do not change this comment) */