1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004 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"
43 /* Macros max and min defined in lisp.h conflict with those in
44 precompiled header Carbon.h. */
48 #include <Carbon/Carbon.h>
50 #define free unexec_free
52 #define malloc unexec_malloc
54 #define realloc unexec_realloc
56 #define min(a, b) ((a) < (b) ? (a) : (b))
58 #define max(a, b) ((a) > (b) ? (a) : (b))
60 #define init_process emacs_init_process
61 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
62 obtain events from the event queue. If set to 0, WaitNextEvent is
64 #define USE_CARBON_EVENTS 1
65 #else /* not MAC_OSX */
66 #include <Quickdraw.h>
67 #include <ToolUtils.h>
71 #include <Resources.h>
73 #include <TextUtils.h>
76 #if defined (__MRC__) || (__MSL__ >= 0x6000)
77 #include <ControlDefinitions.h>
84 #endif /* not MAC_OSX */
98 #include "dispextern.h"
100 #include "termhooks.h"
101 #include "termopts.h"
102 #include "termchar.h"
107 #include "intervals.h"
108 #include "composite.h"
111 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
112 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
113 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
114 #define macShiftKey (shiftKey)
115 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
116 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
118 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
122 /* Non-nil means Emacs uses toolkit scroll bars. */
124 Lisp_Object Vx_toolkit_scroll_bars
;
126 /* Non-zero means that a HELP_EVENT has been generated since Emacs
129 static int any_help_event_p
;
131 /* Non-zero means autoselect window with the mouse cursor. */
133 int x_autoselect_window_p
;
135 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
137 int x_use_underline_position_properties
;
139 /* Non-zero means draw block and hollow cursor as wide as the glyph
140 under it. For example, if a block cursor is over a tab, it will be
141 drawn as wide as that tab on the display. */
144 /* This is a chain of structures for all the X displays currently in
147 struct x_display_info
*x_display_list
;
149 /* This is a list of cons cells, each of the form (NAME
150 . FONT-LIST-CACHE), one for each element of x_display_list and in
151 the same order. NAME is the name of the frame. FONT-LIST-CACHE
152 records previous values returned by x-list-fonts. */
154 Lisp_Object x_display_name_list
;
156 /* This is display since Mac does not support multiple ones. */
157 struct mac_display_info one_mac_display_info
;
159 /* Frame being updated by update_frame. This is declared in term.c.
160 This is set by update_begin and looked at by all the XT functions.
161 It is zero while not inside an update. In that case, the XT
162 functions assume that `selected_frame' is the frame to apply to. */
164 extern struct frame
*updating_frame
;
166 extern int waiting_for_input
;
168 /* This is a frame waiting to be auto-raised, within XTread_socket. */
170 struct frame
*pending_autoraise_frame
;
172 /* Non-zero means user is interacting with a toolkit scroll bar. */
174 static int toolkit_scroll_bar_interaction
;
178 Formerly, we used PointerMotionHintMask (in standard_event_mask)
179 so that we would have to call XQueryPointer after each MotionNotify
180 event to ask for another such event. However, this made mouse tracking
181 slow, and there was a bug that made it eventually stop.
183 Simply asking for MotionNotify all the time seems to work better.
185 In order to avoid asking for motion events and then throwing most
186 of them away or busy-polling the server for mouse positions, we ask
187 the server for pointer motion hints. This means that we get only
188 one event per group of mouse movements. "Groups" are delimited by
189 other kinds of events (focus changes and button clicks, for
190 example), or by XQueryPointer calls; when one of these happens, we
191 get another MotionNotify event the next time the mouse moves. This
192 is at least as efficient as getting motion events when mouse
193 tracking is on, and I suspect only negligibly worse when tracking
196 /* Where the mouse was last time we reported a mouse event. */
198 static Rect last_mouse_glyph
;
199 static Lisp_Object last_mouse_press_frame
;
201 /* The scroll bar in which the last X motion event occurred.
203 If the last X motion event occurred in a scroll bar, we set this so
204 XTmouse_position can know whether to report a scroll bar motion or
207 If the last X motion event didn't occur in a scroll bar, we set
208 this to Qnil, to tell XTmouse_position to return an ordinary motion
211 static Lisp_Object last_mouse_scroll_bar
;
213 /* This is a hack. We would really prefer that XTmouse_position would
214 return the time associated with the position it returns, but there
215 doesn't seem to be any way to wrest the time-stamp from the server
216 along with the position query. So, we just keep track of the time
217 of the last movement we received, and return that in hopes that
218 it's somewhat accurate. */
220 static Time last_mouse_movement_time
;
222 enum mouse_tracking_type
{
224 mouse_tracking_mouse_movement
,
225 mouse_tracking_scroll_bar
228 enum mouse_tracking_type mouse_tracking_in_progress
= mouse_tracking_none
;
230 struct scroll_bar
*tracked_scroll_bar
= NULL
;
232 /* Incremented by XTread_socket whenever it really tries to read
236 static int volatile input_signal_count
;
238 static int input_signal_count
;
241 /* Used locally within XTread_socket. */
243 static int x_noop_count
;
245 /* Initial values of argv and argc. */
247 extern char **initial_argv
;
248 extern int initial_argc
;
250 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
252 /* Tells if a window manager is present or not. */
254 extern Lisp_Object Vx_no_window_manager
;
258 /* A mask of extra modifier bits to put into every keyboard char. */
260 extern int extra_keyboard_modifiers
;
262 static Lisp_Object Qvendor_specific_keysyms
;
265 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
268 extern int inhibit_window_system
;
271 QDGlobals qd
; /* QuickDraw global information structure. */
275 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
276 struct mac_display_info
*mac_display_info_for_display (Display
*);
277 static void x_update_window_end
P_ ((struct window
*, int, int));
278 static void mac_handle_tool_bar_click
P_ ((struct frame
*, EventRecord
*));
279 static int x_io_error_quitter
P_ ((Display
*));
280 int x_catch_errors
P_ ((Display
*));
281 void x_uncatch_errors
P_ ((Display
*, int));
282 void x_lower_frame
P_ ((struct frame
*));
283 void x_scroll_bar_clear
P_ ((struct frame
*));
284 int x_had_errors_p
P_ ((Display
*));
285 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
286 void x_raise_frame
P_ ((struct frame
*));
287 void x_set_window_size
P_ ((struct frame
*, int, int, int));
288 void x_wm_set_window_state
P_ ((struct frame
*, int));
289 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
290 void mac_initialize
P_ ((void));
291 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
292 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
293 static void x_update_end
P_ ((struct frame
*));
294 static void XTframe_up_to_date
P_ ((struct frame
*));
295 static void XTreassert_line_highlight
P_ ((int, int));
296 static void x_change_line_highlight
P_ ((int, int, int, int));
297 static void XTset_terminal_modes
P_ ((void));
298 static void XTreset_terminal_modes
P_ ((void));
299 static void x_clear_frame
P_ ((void));
300 static void frame_highlight
P_ ((struct frame
*));
301 static void frame_unhighlight
P_ ((struct frame
*));
302 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
303 static void XTframe_rehighlight
P_ ((struct frame
*));
304 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
305 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
306 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int));
307 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, GC
));
308 static void x_flush
P_ ((struct frame
*f
));
309 static void x_update_begin
P_ ((struct frame
*));
310 static void x_update_window_begin
P_ ((struct window
*));
311 static void x_after_update_window_line
P_ ((struct glyph_row
*));
313 void activate_scroll_bars (FRAME_PTR
);
314 void deactivate_scroll_bars (FRAME_PTR
);
316 static int is_emacs_window (WindowPtr
);
318 extern int image_ascent (struct image
*, struct face
*);
319 int x_bitmap_icon (struct frame
*, Lisp_Object
);
320 void x_make_frame_visible (struct frame
*);
322 extern void window_scroll (Lisp_Object
, int, int, int);
324 /* Defined in macmenu.h. */
325 extern void menubar_selection_callback (FRAME_PTR
, int);
326 extern void set_frame_menubar (FRAME_PTR
, int, int);
328 /* X display function emulation */
331 XFreePixmap (display
, pixmap
)
335 PixMap
*p
= (PixMap
*) pixmap
;
342 /* Set foreground color for subsequent QuickDraw commands. Assume
343 graphic port has already been set. */
346 mac_set_forecolor (unsigned long color
)
350 fg_color
.red
= RED_FROM_ULONG (color
) * 256;
351 fg_color
.green
= GREEN_FROM_ULONG (color
) * 256;
352 fg_color
.blue
= BLUE_FROM_ULONG (color
) * 256;
354 RGBForeColor (&fg_color
);
358 /* Set background color for subsequent QuickDraw commands. Assume
359 graphic port has already been set. */
362 mac_set_backcolor (unsigned long color
)
366 bg_color
.red
= RED_FROM_ULONG (color
) * 256;
367 bg_color
.green
= GREEN_FROM_ULONG (color
) * 256;
368 bg_color
.blue
= BLUE_FROM_ULONG (color
) * 256;
370 RGBBackColor (&bg_color
);
373 /* Set foreground and background color for subsequent QuickDraw
374 commands. Assume that the graphic port has already been set. */
377 mac_set_colors (GC gc
)
379 mac_set_forecolor (gc
->foreground
);
380 mac_set_backcolor (gc
->background
);
383 /* Mac version of XDrawLine. */
386 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
392 #if TARGET_API_MAC_CARBON
393 SetPort (GetWindowPort (w
));
404 /* Mac version of XClearArea. */
407 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
411 unsigned int width
, height
;
414 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
418 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
419 xgc
.background
= mwp
->x_compatible
.background_pixel
;
421 #if TARGET_API_MAC_CARBON
422 SetPort (GetWindowPort (w
));
427 mac_set_colors (&xgc
);
428 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
433 /* Mac version of XClearWindow. */
436 XClearWindow (display
, w
)
440 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
443 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
444 xgc
.background
= mwp
->x_compatible
.background_pixel
;
446 #if TARGET_API_MAC_CARBON
447 SetPort (GetWindowPort (w
));
452 mac_set_colors (&xgc
);
454 #if TARGET_API_MAC_CARBON
458 GetWindowPortBounds (w
, &r
);
461 #else /* not TARGET_API_MAC_CARBON */
462 EraseRect (&(w
->portRect
));
463 #endif /* not TARGET_API_MAC_CARBON */
467 /* Mac replacement for XCopyArea. */
470 mac_draw_bitmap (display
, w
, gc
, x
, y
, bitmap
)
479 #if TARGET_API_MAC_CARBON
480 SetPort (GetWindowPort (w
));
486 SetRect (&r
, x
, y
, x
+ bitmap
->bounds
.right
, y
+ bitmap
->bounds
.bottom
);
488 #if TARGET_API_MAC_CARBON
492 LockPortBits (GetWindowPort (w
));
493 pmh
= GetPortPixMap (GetWindowPort (w
));
494 CopyBits (bitmap
, (BitMap
*) *pmh
, &(bitmap
->bounds
), &r
, srcCopy
, 0);
495 UnlockPortBits (GetWindowPort (w
));
497 #else /* not TARGET_API_MAC_CARBON */
498 CopyBits (bitmap
, &(w
->portBits
), &(bitmap
->bounds
), &r
, srcCopy
, 0);
499 #endif /* not TARGET_API_MAC_CARBON */
503 /* Mac replacement for XSetClipRectangles. */
506 mac_set_clip_rectangle (display
, w
, r
)
511 #if TARGET_API_MAC_CARBON
512 SetPort (GetWindowPort (w
));
521 /* Mac replacement for XSetClipMask. */
524 mac_reset_clipping (display
, w
)
530 #if TARGET_API_MAC_CARBON
531 SetPort (GetWindowPort (w
));
536 SetRect (&r
, -32767, -32767, 32767, 32767);
541 /* Mac replacement for XCreateBitmapFromBitmapData. */
544 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
549 int bytes_per_row
, i
, j
;
551 bitmap
->rowBytes
= (w
+ 15) / 16 * 2; /* must be on word boundary */
552 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
553 if (!bitmap
->baseAddr
)
556 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
557 for (i
= 0; i
< h
; i
++)
558 for (j
= 0; j
< w
; j
++)
559 if (BitTst (bits
, i
* w
+ j
))
560 BitSet (bitmap
->baseAddr
, i
* bitmap
->rowBytes
* 8 + j
);
562 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
567 mac_free_bitmap (bitmap
)
570 xfree (bitmap
->baseAddr
);
573 /* Mac replacement for XFillRectangle. */
576 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
581 unsigned int width
, height
;
585 #if TARGET_API_MAC_CARBON
586 SetPort (GetWindowPort (w
));
592 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
594 PaintRect (&r
); /* using foreground color of gc */
598 /* Mac replacement for XDrawRectangle: dest is a window. */
601 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
606 unsigned int width
, height
;
610 #if TARGET_API_MAC_CARBON
611 SetPort (GetWindowPort (w
));
617 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
619 FrameRect (&r
); /* using foreground color of gc */
623 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
626 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
631 unsigned int width
, height
;
633 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
636 #if TARGET_API_MAC_CARBON
637 SetPort (GetWindowPort (w
));
643 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
645 FrameRect (&r
); /* using foreground color of gc */
651 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
658 int nchars
, mode
, bytes_per_char
;
660 #if TARGET_API_MAC_CARBON
661 SetPort (GetWindowPort (w
));
668 TextFont (gc
->font
->mac_fontnum
);
669 TextSize (gc
->font
->mac_fontsize
);
670 TextFace (gc
->font
->mac_fontface
);
674 DrawText (buf
, 0, nchars
* bytes_per_char
);
678 /* Mac replacement for XDrawString. */
681 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
689 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
693 /* Mac replacement for XDrawString16. */
696 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
704 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
709 /* Mac replacement for XDrawImageString. */
712 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
720 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
724 /* Mac replacement for XDrawString16. */
727 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
735 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
740 /* Mac replacement for XCopyArea: dest must be window. */
743 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
750 unsigned int width
, height
;
755 #if TARGET_API_MAC_CARBON
756 SetPort (GetWindowPort (dest
));
763 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
764 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
766 #if TARGET_API_MAC_CARBON
770 LockPortBits (GetWindowPort (dest
));
771 pmh
= GetPortPixMap (GetWindowPort (dest
));
772 CopyBits ((BitMap
*) &src
, (BitMap
*) *pmh
, &src_r
, &dest_r
, srcCopy
, 0);
773 UnlockPortBits (GetWindowPort (dest
));
775 #else /* not TARGET_API_MAC_CARBON */
776 CopyBits ((BitMap
*) &src
, &(dest
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
777 #endif /* not TARGET_API_MAC_CARBON */
782 /* Convert a pair of local coordinates to global (screen) coordinates.
783 Assume graphic port has been properly set. */
785 local_to_global_coord (short *h
, short *v
)
799 /* Mac replacement for XCopyArea: used only for scrolling. */
802 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
807 unsigned int width
, height
;
810 #if TARGET_API_MAC_CARBON
811 Rect gw_r
, src_r
, dest_r
;
814 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
815 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
817 SetPort (GetWindowPort (w
));
819 ForeColor (blackColor
);
820 BackColor (whiteColor
);
822 LockPortBits (GetWindowPort (w
));
823 pmh
= GetPortPixMap (GetWindowPort (w
));
824 CopyBits ((BitMap
*) *pmh
, (BitMap
*) *pmh
, &src_r
, &dest_r
, srcCopy
, 0);
825 UnlockPortBits (GetWindowPort (w
));
828 #else /* not TARGET_API_MAC_CARBON */
836 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
837 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
840 /* Need to use global coordinates and screenBits since src and dest
841 areas overlap in general. */
842 local_to_global_coord (&src_r
.left
, &src_r
.top
);
843 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
844 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
845 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
847 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
849 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
850 color mapping in CopyBits. Otherwise, it will be slow. */
851 ForeColor (blackColor
);
852 BackColor (whiteColor
);
853 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
857 #endif /* not TARGET_API_MAC_CARBON */
861 /* Mac replacement for XCopyArea: dest must be Pixmap. */
864 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
871 unsigned int width
, height
;
875 int src_right
= ((PixMap
*) src
)->bounds
.right
;
876 int src_bottom
= ((PixMap
*) src
)->bounds
.bottom
;
877 int w
= src_right
- src_x
;
878 int h
= src_bottom
- src_y
;
882 SetRect (&src_r
, src_x
, src_y
, src_right
, src_bottom
);
883 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ w
, dest_y
+ h
);
885 CopyBits ((BitMap
*) &src
, (BitMap
*) &dest
, &src_r
, &dest_r
, srcCopy
, 0);
889 /* Mac replacement for XChangeGC. */
892 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
895 if (mask
& GCForeground
)
896 gc
->foreground
= xgcv
->foreground
;
897 if (mask
& GCBackground
)
898 gc
->background
= xgcv
->background
;
900 gc
->font
= xgcv
->font
;
904 /* Mac replacement for XCreateGC. */
907 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
910 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
911 bzero (gc
, sizeof (XGCValues
));
913 XChangeGC (ignore
, gc
, mask
, xgcv
);
919 /* Used in xfaces.c. */
922 XFreeGC (display
, gc
)
930 /* Mac replacement for XGetGCValues. */
933 XGetGCValues (void* ignore
, XGCValues
*gc
,
934 unsigned long mask
, XGCValues
*xgcv
)
936 XChangeGC (ignore
, xgcv
, mask
, gc
);
940 /* Mac replacement for XSetForeground. */
943 XSetForeground (display
, gc
, color
)
948 gc
->foreground
= color
;
952 /* Mac replacement for XSetFont. */
955 XSetFont (display
, gc
, font
)
965 XTextExtents16 (XFontStruct
*font
, XChar2b
*text
, int nchars
,
966 int *direction
,int *font_ascent
,
967 int *font_descent
, XCharStruct
*cs
)
969 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
973 /* x_sync is a no-op on Mac. */
981 /* Remove calls to XFlush by defining XFlush to an empty replacement.
982 Calls to XFlush should be unnecessary because the X output buffer
983 is flushed automatically as needed by calls to XPending,
984 XNextEvent, or XWindowEvent according to the XFlush man page.
985 XTread_socket calls XPending. Removing XFlush improves
988 #if TARGET_API_MAC_CARBON
989 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
991 #define XFlush(DISPLAY) (void) 0
994 /* Flush display of frame F, or of all frames if F is null. */
1000 #if TARGET_API_MAC_CARBON
1004 Lisp_Object rest
, frame
;
1005 FOR_EACH_FRAME (rest
, frame
)
1006 x_flush (XFRAME (frame
));
1008 else if (FRAME_X_P (f
))
1009 XFlush (FRAME_MAC_DISPLAY (f
));
1011 #endif /* TARGET_API_MAC_CARBON */
1016 /* Return the struct mac_display_info corresponding to DPY. There's
1019 struct mac_display_info
*
1020 mac_display_info_for_display (dpy
)
1023 return &one_mac_display_info
;
1028 /***********************************************************************
1029 Starting and ending an update
1030 ***********************************************************************/
1032 /* Start an update of frame F. This function is installed as a hook
1033 for update_begin, i.e. it is called when update_begin is called.
1034 This function is called prior to calls to x_update_window_begin for
1035 each window being updated. */
1041 /* Nothing to do. */
1045 /* Start update of window W. Set the global variable updated_window
1046 to the window being updated and set output_cursor to the cursor
1050 x_update_window_begin (w
)
1053 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1054 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1057 set_output_cursor (&w
->cursor
);
1061 if (f
== display_info
->mouse_face_mouse_frame
)
1063 /* Don't do highlighting for mouse motion during the update. */
1064 display_info
->mouse_face_defer
= 1;
1066 /* If F needs to be redrawn, simply forget about any prior mouse
1068 if (FRAME_GARBAGED_P (f
))
1069 display_info
->mouse_face_window
= Qnil
;
1071 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1072 their mouse_face_p flag set, which means that they are always
1073 unequal to rows in a desired matrix which never have that
1074 flag set. So, rows containing mouse-face glyphs are never
1075 scrolled, and we don't have to switch the mouse highlight off
1076 here to prevent it from being scrolled. */
1078 /* Can we tell that this update does not affect the window
1079 where the mouse highlight is? If so, no need to turn off.
1080 Likewise, don't do anything if the frame is garbaged;
1081 in that case, the frame's current matrix that we would use
1082 is all wrong, and we will redisplay that line anyway. */
1083 if (!NILP (display_info
->mouse_face_window
)
1084 && w
== XWINDOW (display_info
->mouse_face_window
))
1088 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1089 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1092 if (i
< w
->desired_matrix
->nrows
)
1093 clear_mouse_face (display_info
);
1102 /* Draw a vertical window border from (x,y0) to (x,y1) */
1105 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1109 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1111 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1112 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1116 /* End update of window W (which is equal to updated_window).
1118 Draw vertical borders between horizontally adjacent windows, and
1119 display W's cursor if CURSOR_ON_P is non-zero.
1121 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1122 glyphs in mouse-face were overwritten. In that case we have to
1123 make sure that the mouse-highlight is properly redrawn.
1125 W may be a menu bar pseudo-window in case we don't have X toolkit
1126 support. Such windows don't have a cursor, so don't display it
1130 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1132 int cursor_on_p
, mouse_face_overwritten_p
;
1134 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1136 if (!w
->pseudo_window_p
)
1141 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1143 output_cursor
.x
, output_cursor
.y
);
1145 x_draw_vertical_border (w
);
1147 draw_window_fringes (w
);
1152 /* If a row with mouse-face was overwritten, arrange for
1153 XTframe_up_to_date to redisplay the mouse highlight. */
1154 if (mouse_face_overwritten_p
)
1156 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1157 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1158 dpyinfo
->mouse_face_window
= Qnil
;
1162 /* Unhide the caret. This won't actually show the cursor, unless it
1163 was visible before the corresponding call to HideCaret in
1164 x_update_window_begin. */
1165 if (w32_use_visible_system_caret
)
1166 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1169 updated_window
= NULL
;
1173 /* End update of frame F. This function is installed as a hook in
1180 /* Reset the background color of Mac OS Window to that of the frame after
1181 update so that it is used by Mac Toolbox to clear the update region before
1182 an update event is generated. */
1183 #if TARGET_API_MAC_CARBON
1184 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
1186 SetPort (FRAME_MAC_WINDOW (f
));
1189 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
1191 /* Mouse highlight may be displayed again. */
1192 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1195 XFlush (FRAME_MAC_DISPLAY (f
));
1200 /* This function is called from various places in xdisp.c whenever a
1201 complete update has been performed. The global variable
1202 updated_window is not available here. */
1205 XTframe_up_to_date (f
)
1210 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1212 if (dpyinfo
->mouse_face_deferred_gc
1213 || f
== dpyinfo
->mouse_face_mouse_frame
)
1216 if (dpyinfo
->mouse_face_mouse_frame
)
1217 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1218 dpyinfo
->mouse_face_mouse_x
,
1219 dpyinfo
->mouse_face_mouse_y
);
1220 dpyinfo
->mouse_face_deferred_gc
= 0;
1227 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1228 arrow bitmaps, or clear the fringes if no bitmaps are required
1229 before DESIRED_ROW is made current. The window being updated is
1230 found in updated_window. This function is called from
1231 update_window_line only if it is known that there are differences
1232 between bitmaps to be drawn between current row and DESIRED_ROW. */
1235 x_after_update_window_line (desired_row
)
1236 struct glyph_row
*desired_row
;
1238 struct window
*w
= updated_window
;
1244 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1245 desired_row
->redraw_fringe_bitmaps_p
= 1;
1247 /* When a window has disappeared, make sure that no rest of
1248 full-width rows stays visible in the internal border. Could
1249 check here if updated_window is the leftmost/rightmost window,
1250 but I guess it's not worth doing since vertically split windows
1251 are almost never used, internal border is rarely set, and the
1252 overhead is very small. */
1253 if (windows_or_buffers_changed
1254 && desired_row
->full_width_p
1255 && (f
= XFRAME (w
->frame
),
1256 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1258 && (height
= desired_row
->visible_height
,
1261 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1262 /* Internal border is drawn below the tool bar. */
1263 if (WINDOWP (f
->tool_bar_window
)
1264 && w
== XWINDOW (f
->tool_bar_window
))
1269 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1270 0, y
, width
, height
, 0);
1271 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1272 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1280 /* Draw the bitmap WHICH in one of the left or right fringes of
1281 window W. ROW is the glyph row for which to display the bitmap; it
1282 determines the vertical position at which the bitmap has to be
1286 x_draw_fringe_bitmap (w
, row
, p
)
1288 struct glyph_row
*row
;
1289 struct draw_fringe_bitmap_params
*p
;
1291 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1292 Display
*display
= FRAME_MAC_DISPLAY (f
);
1293 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1295 GC gc
= f
->output_data
.mac
->normal_gc
;
1296 struct face
*face
= p
->face
;
1299 /* Must clip because of partially visible lines. */
1300 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1303 /* Adjust position of "bottom aligned" bitmap on partially
1304 visible last row. */
1306 int oldVH
= row
->visible_height
;
1307 row
->visible_height
= p
->h
;
1308 row
->y
-= rowY
- p
->y
;
1309 x_clip_to_row (w
, row
, gc
);
1311 row
->visible_height
= oldVH
;
1314 x_clip_to_row (w
, row
, gc
);
1319 gcv
.foreground
= face
->background
;
1321 #if 0 /* MAC_TODO: stipple */
1322 /* In case the same realized face is used for fringes and
1323 for something displayed in the text (e.g. face `region' on
1324 mono-displays, the fill style may have been changed to
1325 FillSolid in x_draw_glyph_string_background. */
1327 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1329 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1332 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1334 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1336 #if 0 /* MAC_TODO: stipple */
1338 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1342 if (p
->which
!= NO_FRINGE_BITMAP
)
1344 unsigned char *bits
= fringe_bitmaps
[p
->which
].bits
+ p
->dh
;
1347 mac_create_bitmap_from_bitmap_data (&bitmap
, bits
, p
->wd
, p
->h
);
1348 gcv
.foreground
= face
->foreground
;
1349 gcv
.background
= face
->background
;
1351 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
, &bitmap
);
1353 mac_free_bitmap (&bitmap
);
1356 mac_reset_clipping (display
, window
);
1360 /* This is called when starting Emacs and when restarting after
1361 suspend. When starting Emacs, no window is mapped. And nothing
1362 must be done to Emacs's own window if it is suspended (though that
1366 XTset_terminal_modes ()
1370 /* This is called when exiting or suspending Emacs. Exiting will make
1371 the windows go away, and suspending requires no action. */
1374 XTreset_terminal_modes ()
1379 /***********************************************************************
1381 ***********************************************************************/
1383 /* Function prototypes of this page. */
1385 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1386 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1389 /* Return a pointer to per-char metric information in FONT of a
1390 character pointed by B which is a pointer to an XChar2b. */
1392 #define PER_CHAR_METRIC(font, b) \
1394 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1395 + (((font)->min_byte1 || (font)->max_byte1) \
1396 ? (((b)->byte1 - (font)->min_byte1) \
1397 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1399 : &((font)->max_bounds))
1402 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1403 is not contained in the font. */
1405 static INLINE XCharStruct
*
1406 x_per_char_metric (font
, char2b
)
1410 /* The result metric information. */
1411 XCharStruct
*pcm
= NULL
;
1413 xassert (font
&& char2b
);
1415 if (font
->per_char
!= NULL
)
1417 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1419 /* min_char_or_byte2 specifies the linear character index
1420 corresponding to the first element of the per_char array,
1421 max_char_or_byte2 is the index of the last character. A
1422 character with non-zero CHAR2B->byte1 is not in the font.
1423 A character with byte2 less than min_char_or_byte2 or
1424 greater max_char_or_byte2 is not in the font. */
1425 if (char2b
->byte1
== 0
1426 && char2b
->byte2
>= font
->min_char_or_byte2
1427 && char2b
->byte2
<= font
->max_char_or_byte2
)
1428 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1432 /* If either min_byte1 or max_byte1 are nonzero, both
1433 min_char_or_byte2 and max_char_or_byte2 are less than
1434 256, and the 2-byte character index values corresponding
1435 to the per_char array element N (counting from 0) are:
1437 byte1 = N/D + min_byte1
1438 byte2 = N\D + min_char_or_byte2
1442 D = max_char_or_byte2 - min_char_or_byte2 + 1
1443 / = integer division
1444 \ = integer modulus */
1445 if (char2b
->byte1
>= font
->min_byte1
1446 && char2b
->byte1
<= font
->max_byte1
1447 && char2b
->byte2
>= font
->min_char_or_byte2
1448 && char2b
->byte2
<= font
->max_char_or_byte2
)
1450 pcm
= (font
->per_char
1451 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1452 * (char2b
->byte1
- font
->min_byte1
))
1453 + (char2b
->byte2
- font
->min_char_or_byte2
));
1459 /* If the per_char pointer is null, all glyphs between the first
1460 and last character indexes inclusive have the same
1461 information, as given by both min_bounds and max_bounds. */
1462 if (char2b
->byte2
>= font
->min_char_or_byte2
1463 && char2b
->byte2
<= font
->max_char_or_byte2
)
1464 pcm
= &font
->max_bounds
;
1467 return ((pcm
== NULL
1468 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1475 static XCharStruct
*
1476 mac_per_char_metric (font
, char2b
, font_type
)
1481 return x_per_char_metric (font
, char2b
);
1485 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1486 the two-byte form of C. Encoding is returned in *CHAR2B. */
1489 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1492 struct font_info
*font_info
;
1495 int charset
= CHAR_CHARSET (c
);
1496 XFontStruct
*font
= font_info
->font
;
1498 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1499 This may be either a program in a special encoder language or a
1501 if (font_info
->font_encoder
)
1503 /* It's a program. */
1504 struct ccl_program
*ccl
= font_info
->font_encoder
;
1506 if (CHARSET_DIMENSION (charset
) == 1)
1508 ccl
->reg
[0] = charset
;
1509 ccl
->reg
[1] = char2b
->byte2
;
1513 ccl
->reg
[0] = charset
;
1514 ccl
->reg
[1] = char2b
->byte1
;
1515 ccl
->reg
[2] = char2b
->byte2
;
1518 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1520 /* We assume that MSBs are appropriately set/reset by CCL
1522 if (font
->max_byte1
== 0) /* 1-byte font */
1523 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1525 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1527 else if (font_info
->encoding
[charset
])
1529 /* Fixed encoding scheme. See fontset.h for the meaning of the
1530 encoding numbers. */
1531 int enc
= font_info
->encoding
[charset
];
1533 if ((enc
== 1 || enc
== 2)
1534 && CHARSET_DIMENSION (charset
) == 2)
1535 char2b
->byte1
|= 0x80;
1537 if (enc
== 1 || enc
== 3)
1538 char2b
->byte2
|= 0x80;
1544 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1545 char2b
->byte1
= sjis1
;
1546 char2b
->byte2
= sjis2
;
1551 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1553 return FONT_TYPE_UNKNOWN
;
1558 /***********************************************************************
1560 ***********************************************************************/
1563 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1564 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1565 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1567 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1568 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1569 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1570 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1571 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1572 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1573 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1574 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1575 unsigned long *, double, int));*/
1576 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1577 double, int, unsigned long));
1578 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1579 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1580 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1581 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1582 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1583 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1585 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1586 int, int, int, int, Rect
*));
1587 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1588 int, int, int, Rect
*));
1591 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1595 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1600 struct glyph_string
*s
;
1602 if (s
->font
== FRAME_FONT (s
->f
)
1603 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1604 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1606 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1609 /* Cursor on non-default face: must merge. */
1613 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1614 xgcv
.foreground
= s
->face
->background
;
1616 /* If the glyph would be invisible, try a different foreground. */
1617 if (xgcv
.foreground
== xgcv
.background
)
1618 xgcv
.foreground
= s
->face
->foreground
;
1619 if (xgcv
.foreground
== xgcv
.background
)
1620 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1621 if (xgcv
.foreground
== xgcv
.background
)
1622 xgcv
.foreground
= s
->face
->foreground
;
1624 /* Make sure the cursor is distinct from text in this face. */
1625 if (xgcv
.background
== s
->face
->background
1626 && xgcv
.foreground
== s
->face
->foreground
)
1628 xgcv
.background
= s
->face
->foreground
;
1629 xgcv
.foreground
= s
->face
->background
;
1632 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1633 xgcv
.font
= s
->font
;
1634 mask
= GCForeground
| GCBackground
| GCFont
;
1636 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1637 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1640 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1641 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1643 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1648 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1651 x_set_mouse_face_gc (s
)
1652 struct glyph_string
*s
;
1657 /* What face has to be used last for the mouse face? */
1658 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1659 face
= FACE_FROM_ID (s
->f
, face_id
);
1661 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1663 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1664 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1666 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1667 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1668 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1670 /* If font in this face is same as S->font, use it. */
1671 if (s
->font
== s
->face
->font
)
1672 s
->gc
= s
->face
->gc
;
1675 /* Otherwise construct scratch_cursor_gc with values from FACE
1680 xgcv
.background
= s
->face
->background
;
1681 xgcv
.foreground
= s
->face
->foreground
;
1682 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1683 xgcv
.font
= s
->font
;
1684 mask
= GCForeground
| GCBackground
| GCFont
;
1686 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1687 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1690 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1691 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1693 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1696 xassert (s
->gc
!= 0);
1700 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1701 Faces to use in the mode line have already been computed when the
1702 matrix was built, so there isn't much to do, here. */
1705 x_set_mode_line_face_gc (s
)
1706 struct glyph_string
*s
;
1708 s
->gc
= s
->face
->gc
;
1712 /* Set S->gc of glyph string S for drawing that glyph string. Set
1713 S->stippled_p to a non-zero value if the face of S has a stipple
1717 x_set_glyph_string_gc (s
)
1718 struct glyph_string
*s
;
1720 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1722 if (s
->hl
== DRAW_NORMAL_TEXT
)
1724 s
->gc
= s
->face
->gc
;
1725 s
->stippled_p
= s
->face
->stipple
!= 0;
1727 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1729 x_set_mode_line_face_gc (s
);
1730 s
->stippled_p
= s
->face
->stipple
!= 0;
1732 else if (s
->hl
== DRAW_CURSOR
)
1734 x_set_cursor_gc (s
);
1737 else if (s
->hl
== DRAW_MOUSE_FACE
)
1739 x_set_mouse_face_gc (s
);
1740 s
->stippled_p
= s
->face
->stipple
!= 0;
1742 else if (s
->hl
== DRAW_IMAGE_RAISED
1743 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1745 s
->gc
= s
->face
->gc
;
1746 s
->stippled_p
= s
->face
->stipple
!= 0;
1750 s
->gc
= s
->face
->gc
;
1751 s
->stippled_p
= s
->face
->stipple
!= 0;
1754 /* GC must have been set. */
1755 xassert (s
->gc
!= 0);
1759 /* Set clipping for output of glyph string S. S may be part of a mode
1760 line or menu if we don't have X toolkit support. */
1763 x_set_glyph_string_clipping (s
)
1764 struct glyph_string
*s
;
1767 get_glyph_string_clip_rect (s
, &r
);
1768 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
1773 Compute left and right overhang of glyph string S. If S is a glyph
1774 string for a composition, assume overhangs don't exist. */
1777 mac_compute_glyph_string_overhangs (s
)
1778 struct glyph_string
*s
;
1781 /* MAC_TODO: XTextExtents16 does nothing yet... */
1784 && s
->first_glyph
->type
== CHAR_GLYPH
)
1787 int direction
, font_ascent
, font_descent
;
1788 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
1789 &font_ascent
, &font_descent
, &cs
);
1790 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
1791 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
1797 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1800 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1801 struct glyph_string
*s
;
1806 xgcv
.foreground
= s
->gc
->background
;
1807 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
1811 /* Draw the background of glyph_string S. If S->background_filled_p
1812 is non-zero don't draw it. FORCE_P non-zero means draw the
1813 background even if it wouldn't be drawn normally. This is used
1814 when a string preceding S draws into the background of S, or S
1815 contains the first component of a composition. */
1818 x_draw_glyph_string_background (s
, force_p
)
1819 struct glyph_string
*s
;
1822 /* Nothing to do if background has already been drawn or if it
1823 shouldn't be drawn in the first place. */
1824 if (!s
->background_filled_p
)
1826 int box_line_width
= max (s
->face
->box_line_width
, 0);
1828 #if 0 /* MAC_TODO: stipple */
1831 /* Fill background with a stipple pattern. */
1832 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1833 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1834 s
->y
+ box_line_width
,
1835 s
->background_width
,
1836 s
->height
- 2 * box_line_width
);
1837 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1838 s
->background_filled_p
= 1;
1842 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1843 || s
->font_not_found_p
1844 || s
->extends_to_end_of_line_p
1847 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1848 s
->background_width
,
1849 s
->height
- 2 * box_line_width
);
1850 s
->background_filled_p
= 1;
1856 /* Draw the foreground of glyph string S. */
1859 x_draw_glyph_string_foreground (s
)
1860 struct glyph_string
*s
;
1864 /* If first glyph of S has a left box line, start drawing the text
1865 of S to the right of that box line. */
1866 if (s
->face
->box
!= FACE_NO_BOX
1867 && s
->first_glyph
->left_box_line_p
)
1868 x
= s
->x
+ abs (s
->face
->box_line_width
);
1872 /* Draw characters of S as rectangles if S's font could not be
1874 if (s
->font_not_found_p
)
1876 for (i
= 0; i
< s
->nchars
; ++i
)
1878 struct glyph
*g
= s
->first_glyph
+ i
;
1879 mac_draw_rectangle (s
->display
, s
->window
,
1880 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1882 x
+= g
->pixel_width
;
1887 char *char1b
= (char *) s
->char2b
;
1888 int boff
= s
->font_info
->baseline_offset
;
1890 if (s
->font_info
->vertical_centering
)
1891 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1893 /* If we can use 8-bit functions, condense S->char2b. */
1895 for (i
= 0; i
< s
->nchars
; ++i
)
1896 char1b
[i
] = s
->char2b
[i
].byte2
;
1898 /* Draw text with XDrawString if background has already been
1899 filled. Otherwise, use XDrawImageString. (Note that
1900 XDrawImageString is usually faster than XDrawString.) Always
1901 use XDrawImageString when drawing the cursor so that there is
1902 no chance that characters under a box cursor are invisible. */
1903 if (s
->for_overlaps_p
1904 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1906 /* Draw characters with 16-bit or 8-bit functions. */
1908 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
1909 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1911 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
1912 s
->ybase
- boff
, char1b
, s
->nchars
);
1917 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
1918 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1920 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
1921 s
->ybase
- boff
, char1b
, s
->nchars
);
1926 /* Draw the foreground of composite glyph string S. */
1929 x_draw_composite_glyph_string_foreground (s
)
1930 struct glyph_string
*s
;
1934 /* If first glyph of S has a left box line, start drawing the text
1935 of S to the right of that box line. */
1936 if (s
->face
->box
!= FACE_NO_BOX
1937 && s
->first_glyph
->left_box_line_p
)
1938 x
= s
->x
+ abs (s
->face
->box_line_width
);
1942 /* S is a glyph string for a composition. S->gidx is the index of
1943 the first character drawn for glyphs of this composition.
1944 S->gidx == 0 means we are drawing the very first character of
1945 this composition. */
1947 /* Draw a rectangle for the composition if the font for the very
1948 first character of the composition could not be loaded. */
1949 if (s
->font_not_found_p
)
1952 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
1953 s
->width
- 1, s
->height
- 1);
1957 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
1958 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1959 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
1960 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1966 #ifdef USE_X_TOOLKIT
1968 static struct frame
*x_frame_of_widget
P_ ((Widget
));
1971 /* Return the frame on which widget WIDGET is used.. Abort if frame
1972 cannot be determined. */
1974 static struct frame
*
1975 x_frame_of_widget (widget
)
1978 struct x_display_info
*dpyinfo
;
1982 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
1984 /* Find the top-level shell of the widget. Note that this function
1985 can be called when the widget is not yet realized, so XtWindow
1986 (widget) == 0. That's the reason we can't simply use
1987 x_any_window_to_frame. */
1988 while (!XtIsTopLevelShell (widget
))
1989 widget
= XtParent (widget
);
1991 /* Look for a frame with that top-level widget. Allocate the color
1992 on that frame to get the right gamma correction value. */
1993 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
1994 if (GC_FRAMEP (XCAR (tail
))
1995 && (f
= XFRAME (XCAR (tail
)),
1996 (f
->output_data
.nothing
!= 1
1997 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
1998 && f
->output_data
.x
->widget
== widget
)
2005 /* Allocate the color COLOR->pixel on the screen and display of
2006 widget WIDGET in colormap CMAP. If an exact match cannot be
2007 allocated, try the nearest color available. Value is non-zero
2008 if successful. This is called from lwlib. */
2011 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2016 struct frame
*f
= x_frame_of_widget (widget
);
2017 return x_alloc_nearest_color (f
, cmap
, color
);
2021 #endif /* USE_X_TOOLKIT */
2023 #if 0 /* MAC_TODO */
2025 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2026 CMAP. If an exact match can't be allocated, try the nearest color
2027 available. Value is non-zero if successful. Set *COLOR to the
2031 x_alloc_nearest_color (f
, cmap
, color
)
2036 Display
*display
= FRAME_X_DISPLAY (f
);
2037 Screen
*screen
= FRAME_X_SCREEN (f
);
2040 gamma_correct (f
, color
);
2041 rc
= XAllocColor (display
, cmap
, color
);
2044 /* If we got to this point, the colormap is full, so we're going
2045 to try to get the next closest color. The algorithm used is
2046 a least-squares matching, which is what X uses for closest
2047 color matching with StaticColor visuals. */
2049 unsigned long nearest_delta
= ~0;
2050 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2051 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2053 for (i
= 0; i
< ncells
; ++i
)
2055 XQueryColors (display
, cmap
, cells
, ncells
);
2057 for (nearest
= i
= 0; i
< ncells
; ++i
)
2059 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2060 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2061 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2062 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2064 if (delta
< nearest_delta
)
2067 nearest_delta
= delta
;
2071 color
->red
= cells
[nearest
].red
;
2072 color
->green
= cells
[nearest
].green
;
2073 color
->blue
= cells
[nearest
].blue
;
2074 rc
= XAllocColor (display
, cmap
, color
);
2077 #ifdef DEBUG_X_COLORS
2079 register_color (color
->pixel
);
2080 #endif /* DEBUG_X_COLORS */
2086 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2087 It's necessary to do this instead of just using PIXEL directly to
2088 get color reference counts right. */
2091 x_copy_color (f
, pixel
)
2093 unsigned long pixel
;
2097 color
.pixel
= pixel
;
2099 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2100 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2102 #ifdef DEBUG_X_COLORS
2103 register_color (pixel
);
2109 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2110 It's necessary to do this instead of just using PIXEL directly to
2111 get color reference counts right. */
2114 x_copy_dpy_color (dpy
, cmap
, pixel
)
2117 unsigned long pixel
;
2121 color
.pixel
= pixel
;
2123 XQueryColor (dpy
, cmap
, &color
);
2124 XAllocColor (dpy
, cmap
, &color
);
2126 #ifdef DEBUG_X_COLORS
2127 register_color (pixel
);
2132 #endif /* MAC_TODO */
2134 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2135 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2136 If this produces the same color as COLOR, try a color where all RGB
2137 values have DELTA added. Return the allocated color in *COLOR.
2138 DISPLAY is the X display, CMAP is the colormap to operate on.
2139 Value is non-zero if successful. */
2142 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2144 unsigned long *color
;
2150 /* Change RGB values by specified FACTOR. Avoid overflow! */
2151 xassert (factor
>= 0);
2152 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2153 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2154 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2156 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2157 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2158 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2160 /* MAC_TODO: Map to palette and retry with delta if same? */
2161 /* MAC_TODO: Free colors (if using palette)? */
2172 /* Set up the foreground color for drawing relief lines of glyph
2173 string S. RELIEF is a pointer to a struct relief containing the GC
2174 with which lines will be drawn. Use a color that is FACTOR or
2175 DELTA lighter or darker than the relief's background which is found
2176 in S->f->output_data.x->relief_background. If such a color cannot
2177 be allocated, use DEFAULT_PIXEL, instead. */
2180 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2182 struct relief
*relief
;
2185 unsigned long default_pixel
;
2188 struct mac_output
*di
= f
->output_data
.mac
;
2189 unsigned long mask
= GCForeground
;
2190 unsigned long pixel
;
2191 unsigned long background
= di
->relief_background
;
2192 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2194 /* MAC_TODO: Free colors (if using palette)? */
2196 /* Allocate new color. */
2197 xgcv
.foreground
= default_pixel
;
2199 if (mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2201 relief
->allocated_p
= 1;
2202 xgcv
.foreground
= relief
->pixel
= pixel
;
2205 if (relief
->gc
== 0)
2207 #if 0 /* MAC_TODO: stipple */
2208 xgcv
.stipple
= dpyinfo
->gray
;
2211 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2214 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2218 /* Set up colors for the relief lines around glyph string S. */
2221 x_setup_relief_colors (s
)
2222 struct glyph_string
*s
;
2224 struct mac_output
*di
= s
->f
->output_data
.mac
;
2225 unsigned long color
;
2227 if (s
->face
->use_box_color_for_shadows_p
)
2228 color
= s
->face
->box_color
;
2233 /* Get the background color of the face. */
2234 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2235 color
= xgcv
.background
;
2238 if (di
->white_relief
.gc
== 0
2239 || color
!= di
->relief_background
)
2241 di
->relief_background
= color
;
2242 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2243 WHITE_PIX_DEFAULT (s
->f
));
2244 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2245 BLACK_PIX_DEFAULT (s
->f
));
2250 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2251 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2252 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2253 relief. LEFT_P non-zero means draw a relief on the left side of
2254 the rectangle. RIGHT_P non-zero means draw a relief on the right
2255 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2259 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2260 raised_p
, left_p
, right_p
, clip_rect
)
2262 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
2269 gc
= f
->output_data
.mac
->white_relief
.gc
;
2271 gc
= f
->output_data
.mac
->black_relief
.gc
;
2272 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), clip_rect
);
2275 for (i
= 0; i
< width
; ++i
)
2276 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
2277 left_x
+ i
* left_p
, top_y
+ i
,
2278 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2282 for (i
= 0; i
< width
; ++i
)
2283 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
2284 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2286 mac_reset_clipping (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
2288 gc
= f
->output_data
.mac
->black_relief
.gc
;
2290 gc
= f
->output_data
.mac
->white_relief
.gc
;
2291 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
2295 for (i
= 0; i
< width
; ++i
)
2296 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
2297 left_x
+ i
* left_p
, bottom_y
- i
,
2298 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2302 for (i
= 0; i
< width
; ++i
)
2303 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
2304 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
2306 mac_reset_clipping (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
2310 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2311 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2312 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2313 left side of the rectangle. RIGHT_P non-zero means draw a line
2314 on the right side of the rectangle. CLIP_RECT is the clipping
2315 rectangle to use when drawing. */
2318 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2319 left_p
, right_p
, clip_rect
)
2320 struct glyph_string
*s
;
2321 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
2326 xgcv
.foreground
= s
->face
->box_color
;
2327 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2330 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2331 left_x
, top_y
, right_x
- left_x
, width
);
2335 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2336 left_x
, top_y
, width
, bottom_y
- top_y
);
2339 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2340 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
2344 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2345 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
2347 mac_reset_clipping (s
->display
, s
->window
);
2351 /* Draw a box around glyph string S. */
2354 x_draw_glyph_string_box (s
)
2355 struct glyph_string
*s
;
2357 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2358 int left_p
, right_p
;
2359 struct glyph
*last_glyph
;
2362 last_x
= window_box_right (s
->w
, s
->area
);
2363 if (s
->row
->full_width_p
2364 && !s
->w
->pseudo_window_p
)
2366 last_x
+= WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s
->w
);
2367 if (s
->area
!= RIGHT_MARGIN_AREA
2368 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s
->w
))
2369 last_x
+= WINDOW_RIGHT_FRINGE_WIDTH (s
->w
);
2372 /* The glyph that may have a right box line. */
2373 last_glyph
= (s
->cmp
|| s
->img
2375 : s
->first_glyph
+ s
->nchars
- 1);
2377 width
= abs (s
->face
->box_line_width
);
2378 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2380 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2382 : min (last_x
, s
->x
+ s
->background_width
) - 1));
2384 bottom_y
= top_y
+ s
->height
- 1;
2386 left_p
= (s
->first_glyph
->left_box_line_p
2387 || (s
->hl
== DRAW_MOUSE_FACE
2389 || s
->prev
->hl
!= s
->hl
)));
2390 right_p
= (last_glyph
->right_box_line_p
2391 || (s
->hl
== DRAW_MOUSE_FACE
2393 || s
->next
->hl
!= s
->hl
)));
2395 get_glyph_string_clip_rect (s
, &clip_rect
);
2397 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2398 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2399 left_p
, right_p
, &clip_rect
);
2402 x_setup_relief_colors (s
);
2403 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2404 width
, raised_p
, left_p
, right_p
, &clip_rect
);
2409 /* Draw foreground of image glyph string S. */
2412 x_draw_image_foreground (s
)
2413 struct glyph_string
*s
;
2416 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2418 /* If first glyph of S has a left box line, start drawing it to the
2419 right of that line. */
2420 if (s
->face
->box
!= FACE_NO_BOX
2421 && s
->first_glyph
->left_box_line_p
)
2422 x
= s
->x
+ abs (s
->face
->box_line_width
);
2426 /* If there is a margin around the image, adjust x- and y-position
2428 x
+= s
->img
->hmargin
;
2429 y
+= s
->img
->vmargin
;
2433 #if 0 /* MAC_TODO: image mask */
2436 /* We can't set both a clip mask and use XSetClipRectangles
2437 because the latter also sets a clip mask. We also can't
2438 trust on the shape extension to be available
2439 (XShapeCombineRegion). So, compute the rectangle to draw
2441 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2444 XRectangle clip_rect
, image_rect
, r
;
2446 xgcv
.clip_mask
= s
->img
->mask
;
2447 xgcv
.clip_x_origin
= x
;
2448 xgcv
.clip_y_origin
= y
;
2449 xgcv
.function
= GXcopy
;
2450 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2452 get_glyph_string_clip_rect (s
, &clip_rect
);
2455 image_rect
.width
= s
->img
->width
;
2456 image_rect
.height
= s
->img
->height
;
2457 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2458 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2459 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
2462 #endif /* MAC_TODO */
2464 mac_copy_area (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2465 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2467 /* When the image has a mask, we can expect that at
2468 least part of a mouse highlight or a block cursor will
2469 be visible. If the image doesn't have a mask, make
2470 a block cursor visible by drawing a rectangle around
2471 the image. I believe it's looking better if we do
2472 nothing here for mouse-face. */
2473 if (s
->hl
== DRAW_CURSOR
)
2475 int r
= s
->img
->relief
;
2477 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2478 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2483 /* Draw a rectangle if image could not be loaded. */
2484 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2485 s
->img
->width
- 1, s
->img
->height
- 1);
2490 /* Draw a relief around the image glyph string S. */
2493 x_draw_image_relief (s
)
2494 struct glyph_string
*s
;
2496 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2499 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2501 /* If first glyph of S has a left box line, start drawing it to the
2502 right of that line. */
2503 if (s
->face
->box
!= FACE_NO_BOX
2504 && s
->first_glyph
->left_box_line_p
)
2505 x
= s
->x
+ abs (s
->face
->box_line_width
);
2509 /* If there is a margin around the image, adjust x- and y-position
2511 x
+= s
->img
->hmargin
;
2512 y
+= s
->img
->vmargin
;
2514 if (s
->hl
== DRAW_IMAGE_SUNKEN
2515 || s
->hl
== DRAW_IMAGE_RAISED
)
2517 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2518 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2522 thick
= abs (s
->img
->relief
);
2523 raised_p
= s
->img
->relief
> 0;
2528 x1
= x
+ s
->img
->width
+ thick
- 1;
2529 y1
= y
+ s
->img
->height
+ thick
- 1;
2531 x_setup_relief_colors (s
);
2532 get_glyph_string_clip_rect (s
, &r
);
2533 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
2537 /* Draw the foreground of image glyph string S to PIXMAP. */
2540 x_draw_image_foreground_1 (s
, pixmap
)
2541 struct glyph_string
*s
;
2545 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
2547 /* If first glyph of S has a left box line, start drawing it to the
2548 right of that line. */
2549 if (s
->face
->box
!= FACE_NO_BOX
2550 && s
->first_glyph
->left_box_line_p
)
2551 x
= abs (s
->face
->box_line_width
);
2555 /* If there is a margin around the image, adjust x- and y-position
2557 x
+= s
->img
->hmargin
;
2558 y
+= s
->img
->vmargin
;
2562 #if 0 /* MAC_TODO: image mask */
2565 /* We can't set both a clip mask and use XSetClipRectangles
2566 because the latter also sets a clip mask. We also can't
2567 trust on the shape extension to be available
2568 (XShapeCombineRegion). So, compute the rectangle to draw
2570 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2574 xgcv
.clip_mask
= s
->img
->mask
;
2575 xgcv
.clip_x_origin
= x
;
2576 xgcv
.clip_y_origin
= y
;
2577 xgcv
.function
= GXcopy
;
2578 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2580 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2581 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2582 XSetClipMask (s
->display
, s
->gc
, None
);
2585 #endif /* MAC_TODO */
2587 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2588 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2590 /* When the image has a mask, we can expect that at
2591 least part of a mouse highlight or a block cursor will
2592 be visible. If the image doesn't have a mask, make
2593 a block cursor visible by drawing a rectangle around
2594 the image. I believe it's looking better if we do
2595 nothing here for mouse-face. */
2596 if (s
->hl
== DRAW_CURSOR
)
2598 int r
= s
->img
->relief
;
2600 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
- r
, y
- r
,
2601 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2606 /* Draw a rectangle if image could not be loaded. */
2607 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2608 s
->img
->width
- 1, s
->img
->height
- 1);
2612 /* Draw part of the background of glyph string S. X, Y, W, and H
2613 give the rectangle to draw. */
2616 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2617 struct glyph_string
*s
;
2620 #if 0 /* MAC_TODO: stipple */
2623 /* Fill background with a stipple pattern. */
2624 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2625 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2626 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2629 #endif /* MAC_TODO */
2630 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2634 /* Draw image glyph string S.
2637 s->x +-------------------------
2640 | +-------------------------
2643 | | +-------------------
2649 x_draw_image_glyph_string (s
)
2650 struct glyph_string
*s
;
2653 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2654 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2658 height
= s
->height
- 2 * box_line_vwidth
;
2660 /* Fill background with face under the image. Do it only if row is
2661 taller than image or if image has a clip mask to reduce
2663 s
->stippled_p
= s
->face
->stipple
!= 0;
2664 if (height
> s
->img
->height
2667 #if 0 /* TODO: image mask */
2670 || s
->img
->pixmap
== 0
2671 || s
->width
!= s
->background_width
)
2673 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
2674 x
= s
->x
+ box_line_hwidth
;
2678 y
= s
->y
+ box_line_vwidth
;
2679 #if 0 /* TODO: image mask */
2682 /* Create a pixmap as large as the glyph string. Fill it
2683 with the background color. Copy the image to it, using
2684 its mask. Copy the temporary pixmap to the display. */
2685 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2686 int depth
= DefaultDepthOfScreen (screen
);
2688 /* Create a pixmap as large as the glyph string. */
2689 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2690 s
->background_width
,
2693 /* Don't clip in the following because we're working on the
2695 XSetClipMask (s
->display
, s
->gc
, None
);
2697 /* Fill the pixmap with the background color/stipple. */
2700 /* Fill background with a stipple pattern. */
2701 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2702 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2703 0, 0, s
->background_width
, s
->height
);
2704 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2709 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2711 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2712 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2713 0, 0, s
->background_width
, s
->height
);
2714 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2719 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2721 s
->background_filled_p
= 1;
2724 /* Draw the foreground. */
2727 x_draw_image_foreground_1 (s
, pixmap
);
2728 x_set_glyph_string_clipping (s
);
2729 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
2730 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2731 mac_reset_clipping (s
->display
, s
->window
);
2732 XFreePixmap (s
->display
, pixmap
);
2735 x_draw_image_foreground (s
);
2737 /* If we must draw a relief around the image, do it. */
2739 || s
->hl
== DRAW_IMAGE_RAISED
2740 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2741 x_draw_image_relief (s
);
2745 /* Draw stretch glyph string S. */
2748 x_draw_stretch_glyph_string (s
)
2749 struct glyph_string
*s
;
2751 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2752 s
->stippled_p
= s
->face
->stipple
!= 0;
2754 if (s
->hl
== DRAW_CURSOR
2755 && !x_stretch_cursor_p
)
2757 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2758 as wide as the stretch glyph. */
2759 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2762 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2764 /* Clear rest using the GC of the original non-cursor face. */
2765 if (width
< s
->background_width
)
2767 GC gc
= s
->face
->gc
;
2768 int x
= s
->x
+ width
, y
= s
->y
;
2769 int w
= s
->background_width
- width
, h
= s
->height
;
2772 if (s
->row
->mouse_face_p
2773 && cursor_in_mouse_face_p (s
->w
))
2775 x_set_mouse_face_gc (s
);
2781 get_glyph_string_clip_rect (s
, &r
);
2782 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
2784 #if 0 /* MAC_TODO: stipple */
2785 if (s
->face
->stipple
)
2787 /* Fill background with a stipple pattern. */
2788 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2789 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2790 XSetFillStyle (s
->display
, gc
, FillSolid
);
2793 #endif /* MAC_TODO */
2796 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2797 XSetForeground (s
->display
, gc
, xgcv
.background
);
2798 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2799 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2802 mac_reset_clipping (s
->display
, s
->window
);
2805 else if (!s
->background_filled_p
)
2806 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
2809 s
->background_filled_p
= 1;
2813 /* Draw glyph string S. */
2816 x_draw_glyph_string (s
)
2817 struct glyph_string
*s
;
2819 int relief_drawn_p
= 0;
2821 /* If S draws into the background of its successor, draw the
2822 background of the successor first so that S can draw into it.
2823 This makes S->next use XDrawString instead of XDrawImageString. */
2824 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
2826 xassert (s
->next
->img
== NULL
);
2827 x_set_glyph_string_gc (s
->next
);
2828 x_set_glyph_string_clipping (s
->next
);
2829 x_draw_glyph_string_background (s
->next
, 1);
2833 /* Set up S->gc, set clipping and draw S. */
2834 x_set_glyph_string_gc (s
);
2836 /* Draw relief (if any) in advance for char/composition so that the
2837 glyph string can be drawn over it. */
2838 if (!s
->for_overlaps_p
2839 && s
->face
->box
!= FACE_NO_BOX
2840 && (s
->first_glyph
->type
== CHAR_GLYPH
2841 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2844 x_set_glyph_string_clipping (s
);
2845 x_draw_glyph_string_background (s
, 1);
2846 x_draw_glyph_string_box (s
);
2847 x_set_glyph_string_clipping (s
);
2851 x_set_glyph_string_clipping (s
);
2853 switch (s
->first_glyph
->type
)
2856 x_draw_image_glyph_string (s
);
2860 x_draw_stretch_glyph_string (s
);
2864 if (s
->for_overlaps_p
)
2865 s
->background_filled_p
= 1;
2867 x_draw_glyph_string_background (s
, 0);
2868 x_draw_glyph_string_foreground (s
);
2871 case COMPOSITE_GLYPH
:
2872 if (s
->for_overlaps_p
|| s
->gidx
> 0)
2873 s
->background_filled_p
= 1;
2875 x_draw_glyph_string_background (s
, 1);
2876 x_draw_composite_glyph_string_foreground (s
);
2883 if (!s
->for_overlaps_p
)
2885 /* Draw underline. */
2886 if (s
->face
->underline_p
)
2888 unsigned long h
= 1;
2889 unsigned long dy
= s
->height
- h
;
2891 if (s
->face
->underline_defaulted_p
)
2892 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2897 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2898 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2899 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2901 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2905 /* Draw overline. */
2906 if (s
->face
->overline_p
)
2908 unsigned long dy
= 0, h
= 1;
2910 if (s
->face
->overline_color_defaulted_p
)
2911 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2916 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2917 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
2918 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2920 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2924 /* Draw strike-through. */
2925 if (s
->face
->strike_through_p
)
2927 unsigned long h
= 1;
2928 unsigned long dy
= (s
->height
- h
) / 2;
2930 if (s
->face
->strike_through_color_defaulted_p
)
2931 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2936 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2937 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
2938 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2940 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2945 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2946 x_draw_glyph_string_box (s
);
2949 /* Reset clipping. */
2950 mac_reset_clipping (s
->display
, s
->window
);
2953 /* Shift display to make room for inserted glyphs. */
2956 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
2958 int x
, y
, width
, height
, shift_by
;
2960 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
2961 f
->output_data
.mac
->normal_gc
,
2962 x
, y
, width
, height
,
2967 /* Delete N glyphs at the nominal cursor position. Not implemented
2978 /* Clear entire frame. If updating_frame is non-null, clear that
2979 frame. Otherwise clear the selected frame. */
2989 f
= SELECTED_FRAME ();
2991 /* Clearing the frame will erase any cursor, so mark them all as no
2993 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2994 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2995 output_cursor
.x
= -1;
2997 /* We don't set the output cursor here because there will always
2998 follow an explicit cursor_to. */
3000 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3002 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3003 /* We have to clear the scroll bars, too. If we have changed
3004 colors or something like that, then they should be notified. */
3005 x_scroll_bar_clear (f
);
3008 XFlush (FRAME_MAC_DISPLAY (f
));
3014 /* Invert the middle quarter of the frame for .15 sec. */
3016 /* We use the select system call to do the waiting, so we have to make
3017 sure it's available. If it isn't, we just won't do visual bells. */
3019 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3021 /* Subtract the `struct timeval' values X and Y, storing the result in
3022 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3025 timeval_subtract (result
, x
, y
)
3026 struct timeval
*result
, x
, y
;
3028 /* Perform the carry for the later subtraction by updating y. This
3029 is safer because on some systems the tv_sec member is unsigned. */
3030 if (x
.tv_usec
< y
.tv_usec
)
3032 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3033 y
.tv_usec
-= 1000000 * nsec
;
3037 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3039 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3040 y
.tv_usec
+= 1000000 * nsec
;
3044 /* Compute the time remaining to wait. tv_usec is certainly
3046 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3047 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3049 /* Return indication of whether the result should be considered
3051 return x
.tv_sec
< y
.tv_sec
;
3063 struct timeval wakeup
;
3065 EMACS_GET_TIME (wakeup
);
3067 /* Compute time to wait until, propagating carry from usecs. */
3068 wakeup
.tv_usec
+= 150000;
3069 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3070 wakeup
.tv_usec
%= 1000000;
3072 /* Keep waiting until past the time wakeup. */
3075 struct timeval timeout
;
3077 EMACS_GET_TIME (timeout
);
3079 /* In effect, timeout = wakeup - timeout.
3080 Break if result would be negative. */
3081 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3084 /* Try to wait that long--but we might wake up sooner. */
3085 select (0, NULL
, NULL
, NULL
, &timeout
);
3094 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3097 /* Make audible bell. */
3102 struct frame
*f
= SELECTED_FRAME ();
3104 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3112 XFlush (FRAME_MAC_DISPLAY (f
));
3119 /* Specify how many text lines, from the top of the window,
3120 should be affected by insert-lines and delete-lines operations.
3121 This, and those operations, are used only within an update
3122 that is bounded by calls to x_update_begin and x_update_end. */
3125 XTset_terminal_window (n
)
3128 /* This function intentionally left blank. */
3133 /***********************************************************************
3135 ***********************************************************************/
3137 /* Perform an insert-lines or delete-lines operation, inserting N
3138 lines or deleting -N lines at vertical position VPOS. */
3141 x_ins_del_lines (vpos
, n
)
3148 /* Scroll part of the display as described by RUN. */
3151 x_scroll_run (w
, run
)
3155 struct frame
*f
= XFRAME (w
->frame
);
3156 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3158 /* Get frame-relative bounding box of the text display area of W,
3159 without mode lines. Include in this box the left and right
3161 window_box (w
, -1, &x
, &y
, &width
, &height
);
3163 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3164 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3165 bottom_y
= y
+ height
;
3169 /* Scrolling up. Make sure we don't copy part of the mode
3170 line at the bottom. */
3171 if (from_y
+ run
->height
> bottom_y
)
3172 height
= bottom_y
- from_y
;
3174 height
= run
->height
;
3178 /* Scolling down. Make sure we don't copy over the mode line.
3180 if (to_y
+ run
->height
> bottom_y
)
3181 height
= bottom_y
- to_y
;
3183 height
= run
->height
;
3188 /* Cursor off. Will be switched on again in x_update_window_end. */
3192 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3193 f
->output_data
.mac
->normal_gc
,
3203 /***********************************************************************
3205 ***********************************************************************/
3212 x_update_cursor (f
, 1);
3216 frame_unhighlight (f
)
3219 x_update_cursor (f
, 1);
3222 /* The focus has changed. Update the frames as necessary to reflect
3223 the new situation. Note that we can't change the selected frame
3224 here, because the Lisp code we are interrupting might become confused.
3225 Each event gets marked with the frame in which it occurred, so the
3226 Lisp code can tell when the switch took place by examining the events. */
3229 x_new_focus_frame (dpyinfo
, frame
)
3230 struct x_display_info
*dpyinfo
;
3231 struct frame
*frame
;
3233 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3235 if (frame
!= dpyinfo
->x_focus_frame
)
3237 /* Set this before calling other routines, so that they see
3238 the correct value of x_focus_frame. */
3239 dpyinfo
->x_focus_frame
= frame
;
3241 if (old_focus
&& old_focus
->auto_lower
)
3242 x_lower_frame (old_focus
);
3245 selected_frame
= frame
;
3246 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3248 Fselect_window (selected_frame
->selected_window
, Qnil
);
3249 choose_minibuf_frame ();
3252 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3253 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3255 pending_autoraise_frame
= 0;
3258 x_frame_rehighlight (dpyinfo
);
3261 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3264 x_mouse_leave (dpyinfo
)
3265 struct x_display_info
*dpyinfo
;
3267 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3270 /* The focus has changed, or we have redirected a frame's focus to
3271 another frame (this happens when a frame uses a surrogate
3272 mini-buffer frame). Shift the highlight as appropriate.
3274 The FRAME argument doesn't necessarily have anything to do with which
3275 frame is being highlighted or un-highlighted; we only use it to find
3276 the appropriate X display info. */
3279 XTframe_rehighlight (frame
)
3280 struct frame
*frame
;
3284 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3288 x_frame_rehighlight (dpyinfo
)
3289 struct x_display_info
*dpyinfo
;
3291 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3293 if (dpyinfo
->x_focus_frame
)
3295 dpyinfo
->x_highlight_frame
3296 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3297 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3298 : dpyinfo
->x_focus_frame
);
3299 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3301 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3302 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3306 dpyinfo
->x_highlight_frame
= 0;
3308 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3311 frame_unhighlight (old_highlight
);
3312 if (dpyinfo
->x_highlight_frame
)
3313 frame_highlight (dpyinfo
->x_highlight_frame
);
3319 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3321 #if 0 /* MAC_TODO */
3322 /* Initialize mode_switch_bit and modifier_meaning. */
3324 x_find_modifier_meanings (dpyinfo
)
3325 struct x_display_info
*dpyinfo
;
3327 int min_code
, max_code
;
3330 XModifierKeymap
*mods
;
3332 dpyinfo
->meta_mod_mask
= 0;
3333 dpyinfo
->shift_lock_mask
= 0;
3334 dpyinfo
->alt_mod_mask
= 0;
3335 dpyinfo
->super_mod_mask
= 0;
3336 dpyinfo
->hyper_mod_mask
= 0;
3339 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3341 min_code
= dpyinfo
->display
->min_keycode
;
3342 max_code
= dpyinfo
->display
->max_keycode
;
3345 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3346 min_code
, max_code
- min_code
+ 1,
3348 mods
= XGetModifierMapping (dpyinfo
->display
);
3350 /* Scan the modifier table to see which modifier bits the Meta and
3351 Alt keysyms are on. */
3353 int row
, col
; /* The row and column in the modifier table. */
3355 for (row
= 3; row
< 8; row
++)
3356 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3359 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3361 /* Zeroes are used for filler. Skip them. */
3365 /* Are any of this keycode's keysyms a meta key? */
3369 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3371 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3377 dpyinfo
->meta_mod_mask
|= (1 << row
);
3382 dpyinfo
->alt_mod_mask
|= (1 << row
);
3387 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3392 dpyinfo
->super_mod_mask
|= (1 << row
);
3396 /* Ignore this if it's not on the lock modifier. */
3397 if ((1 << row
) == LockMask
)
3398 dpyinfo
->shift_lock_mask
= LockMask
;
3406 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3407 if (! dpyinfo
->meta_mod_mask
)
3409 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3410 dpyinfo
->alt_mod_mask
= 0;
3413 /* If some keys are both alt and meta,
3414 make them just meta, not alt. */
3415 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3417 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3420 XFree ((char *) syms
);
3421 XFreeModifiermap (mods
);
3424 #endif /* MAC_TODO */
3426 /* Convert between the modifier bits X uses and the modifier bits
3430 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3431 struct x_display_info
*dpyinfo
;
3432 unsigned short state
;
3434 return (((state
& shiftKey
) ? shift_modifier
: 0)
3435 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3436 | ((state
& cmdKey
) ? meta_modifier
: 0)
3437 | ((state
& optionKey
) ? alt_modifier
: 0));
3440 #if 0 /* MAC_TODO */
3441 static unsigned short
3442 x_emacs_to_x_modifiers (dpyinfo
, state
)
3443 struct x_display_info
*dpyinfo
;
3446 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3447 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3448 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3449 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3450 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3451 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3453 #endif /* MAC_TODO */
3455 /* Convert a keysym to its name. */
3458 x_get_keysym_name (keysym
)
3465 value
= XKeysymToString (keysym
);
3476 /* Mouse clicks and mouse movement. Rah. */
3478 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3480 If the event is a button press, then note that we have grabbed
3484 construct_mouse_click (result
, event
, f
)
3485 struct input_event
*result
;
3491 result
->kind
= MOUSE_CLICK_EVENT
;
3492 result
->code
= 0; /* only one mouse button */
3493 result
->timestamp
= event
->when
;
3494 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3496 mouseLoc
= event
->where
;
3498 #if TARGET_API_MAC_CARBON
3499 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
3501 SetPort (FRAME_MAC_WINDOW (f
));
3504 GlobalToLocal (&mouseLoc
);
3505 XSETINT (result
->x
, mouseLoc
.h
);
3506 XSETINT (result
->y
, mouseLoc
.v
);
3508 XSETFRAME (result
->frame_or_window
, f
);
3515 /* Function to report a mouse movement to the mainstream Emacs code.
3516 The input handler calls this.
3518 We have received a mouse movement event, which is given in *event.
3519 If the mouse is over a different glyph than it was last time, tell
3520 the mainstream emacs code by setting mouse_moved. If not, ask for
3521 another motion event, so we can check again the next time it moves. */
3523 static Point last_mouse_motion_position
;
3524 static Lisp_Object last_mouse_motion_frame
;
3527 note_mouse_movement (frame
, pos
)
3531 #if TARGET_API_MAC_CARBON
3535 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3536 last_mouse_motion_position
= *pos
;
3537 XSETFRAME (last_mouse_motion_frame
, frame
);
3539 #if TARGET_API_MAC_CARBON
3540 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3542 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3545 frame
->mouse_moved
= 1;
3546 last_mouse_scroll_bar
= Qnil
;
3547 note_mouse_highlight (frame
, -1, -1);
3549 /* Has the mouse moved off the glyph it was on at the last sighting? */
3550 else if (pos
->h
< last_mouse_glyph
.left
3551 || pos
->h
>= last_mouse_glyph
.right
3552 || pos
->v
< last_mouse_glyph
.top
3553 || pos
->v
>= last_mouse_glyph
.bottom
)
3555 frame
->mouse_moved
= 1;
3556 last_mouse_scroll_bar
= Qnil
;
3557 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3561 /* This is used for debugging, to turn off note_mouse_highlight. */
3563 int disable_mouse_highlight
;
3567 /************************************************************************
3569 ************************************************************************/
3571 static struct scroll_bar
*x_window_to_scroll_bar ();
3572 static void x_scroll_bar_report_motion ();
3573 static void x_check_fullscreen
P_ ((struct frame
*));
3574 static void x_check_fullscreen_move
P_ ((struct frame
*));
3575 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3578 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3581 redo_mouse_highlight ()
3583 if (!NILP (last_mouse_motion_frame
)
3584 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3585 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3586 last_mouse_motion_position
.h
,
3587 last_mouse_motion_position
.v
);
3591 /* Try to determine frame pixel position and size of the glyph under
3592 frame pixel coordinates X/Y on frame F . Return the position and
3593 size in *RECT. Value is non-zero if we could compute these
3597 glyph_rect (f
, x
, y
, rect
)
3604 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3608 struct window
*w
= XWINDOW (window
);
3609 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3610 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3612 for (; r
< end
&& r
->enabled_p
; ++r
)
3613 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3615 /* Found the row at y. */
3616 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3617 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3620 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3621 rect
->bottom
= rect
->top
+ r
->height
;
3625 /* x is to the left of the first glyph in the row. */
3626 /* Shouldn't this be a pixel value?
3627 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3629 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3630 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3634 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3635 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3637 /* x is on a glyph. */
3638 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3639 rect
->right
= rect
->left
+ g
->pixel_width
;
3643 /* x is to the right of the last glyph in the row. */
3644 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3645 /* Shouldn't this be a pixel value?
3646 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3648 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3653 /* The y is not on any row. */
3657 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3659 /* Record the position of the mouse in last_mouse_glyph. */
3661 remember_mouse_glyph (f1
, gx
, gy
)
3665 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3667 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3668 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3670 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3671 round down even for negative values. */
3677 /* This was the original code from XTmouse_position, but it seems
3678 to give the position of the glyph diagonally next to the one
3679 the mouse is over. */
3680 gx
= (gx
+ width
- 1) / width
* width
;
3681 gy
= (gy
+ height
- 1) / height
* height
;
3683 gx
= gx
/ width
* width
;
3684 gy
= gy
/ height
* height
;
3687 last_mouse_glyph
.left
= gx
;
3688 last_mouse_glyph
.top
= gy
;
3689 last_mouse_glyph
.right
= gx
+ width
;
3690 last_mouse_glyph
.bottom
= gy
+ height
;
3695 /* Return the current position of the mouse.
3696 *fp should be a frame which indicates which display to ask about.
3698 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3699 and *part to the frame, window, and scroll bar part that the mouse
3700 is over. Set *x and *y to the portion and whole of the mouse's
3701 position on the scroll bar.
3703 If the mouse movement started elsewhere, set *fp to the frame the
3704 mouse is on, *bar_window to nil, and *x and *y to the character cell
3707 Set *time to the server time-stamp for the time at which the mouse
3708 was at this position.
3710 Don't store anything if we don't have a valid set of values to report.
3712 This clears the mouse_moved flag, so we can wait for the next mouse
3716 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3719 Lisp_Object
*bar_window
;
3720 enum scroll_bar_part
*part
;
3722 unsigned long *time
;
3725 int ignore1
, ignore2
;
3726 WindowPtr wp
= FrontWindow ();
3728 Lisp_Object frame
, tail
;
3730 if (is_emacs_window(wp
))
3731 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
3735 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3736 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3739 /* Clear the mouse-moved flag for every frame on this display. */
3740 FOR_EACH_FRAME (tail
, frame
)
3741 XFRAME (frame
)->mouse_moved
= 0;
3743 last_mouse_scroll_bar
= Qnil
;
3745 #if TARGET_API_MAC_CARBON
3746 SetPort (GetWindowPort (wp
));
3751 GetMouse (&mouse_pos
);
3753 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
3754 &last_mouse_glyph
, insist
);
3757 *part
= scroll_bar_handle
;
3759 XSETINT (*x
, mouse_pos
.h
);
3760 XSETINT (*y
, mouse_pos
.v
);
3761 *time
= last_mouse_movement_time
;
3768 /***********************************************************************
3770 ***********************************************************************/
3772 /* Handle mouse button event on the tool-bar of frame F, at
3773 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3777 mac_handle_tool_bar_click (f
, button_event
)
3779 EventRecord
*button_event
;
3781 int x
= button_event
->where
.h
;
3782 int y
= button_event
->where
.v
;
3784 if (button_event
->what
== mouseDown
)
3785 handle_tool_bar_click (f
, x
, y
, 1, 0);
3787 handle_tool_bar_click (f
, x
, y
, 0,
3788 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f
),
3789 button_event
->modifiers
));
3793 /************************************************************************
3794 Scroll bars, general
3795 ************************************************************************/
3797 /* Create a scroll bar and return the scroll bar vector for it. W is
3798 the Emacs window on which to create the scroll bar. TOP, LEFT,
3799 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
3802 static struct scroll_bar
*
3803 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
3805 int top
, left
, width
, height
, disp_top
, disp_height
;
3807 struct frame
*f
= XFRAME (w
->frame
);
3808 struct scroll_bar
*bar
3809 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
3817 r
.right
= left
+ width
;
3818 r
.bottom
= disp_top
+ disp_height
;
3820 #ifdef TARGET_API_MAC_CARBON
3821 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
3822 kControlScrollBarProc
, 0L);
3824 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
3827 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
3828 SetControlReference (ch
, (long) bar
);
3830 XSETWINDOW (bar
->window
, w
);
3831 XSETINT (bar
->top
, top
);
3832 XSETINT (bar
->left
, left
);
3833 XSETINT (bar
->width
, width
);
3834 XSETINT (bar
->height
, height
);
3835 XSETINT (bar
->start
, 0);
3836 XSETINT (bar
->end
, 0);
3837 bar
->dragging
= Qnil
;
3839 /* Add bar to its frame's list of scroll bars. */
3840 bar
->next
= FRAME_SCROLL_BARS (f
);
3842 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3843 if (!NILP (bar
->next
))
3844 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3851 /* Draw BAR's handle in the proper position.
3853 If the handle is already drawn from START to END, don't bother
3854 redrawing it, unless REBUILD is non-zero; in that case, always
3855 redraw it. (REBUILD is handy for drawing the handle after expose
3858 Normally, we want to constrain the start and end of the handle to
3859 fit inside its rectangle, but if the user is dragging the scroll
3860 bar handle, we want to let them drag it down all the way, so that
3861 the bar's top is as far down as it goes; otherwise, there's no way
3862 to move to the very end of the buffer. */
3865 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
3866 struct scroll_bar
*bar
;
3870 int dragging
= ! NILP (bar
->dragging
);
3871 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
3872 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3873 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3874 int length
= end
- start
;
3876 /* If the display is already accurate, do nothing. */
3878 && start
== XINT (bar
->start
)
3879 && end
== XINT (bar
->end
))
3884 /* Make sure the values are reasonable, and try to preserve the
3885 distance between start and end. */
3888 else if (start
> top_range
)
3890 end
= start
+ length
;
3894 else if (end
> top_range
&& ! dragging
)
3897 /* Store the adjusted setting in the scroll bar. */
3898 XSETINT (bar
->start
, start
);
3899 XSETINT (bar
->end
, end
);
3901 /* Clip the end position, just for display. */
3902 if (end
> top_range
)
3905 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
3906 top positions, to make sure the handle is always at least that
3907 many pixels tall. */
3908 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3910 SetControlMinimum (ch
, 0);
3911 /* Don't inadvertently activate deactivated scroll bars */
3912 if (GetControlMaximum (ch
) != -1)
3913 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
3915 SetControlValue (ch
, start
);
3916 #if TARGET_API_MAC_CARBON
3917 SetControlViewSize (ch
, end
- start
);
3924 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3928 x_scroll_bar_remove (bar
)
3929 struct scroll_bar
*bar
;
3931 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3935 /* Destroy the Mac scroll bar control */
3936 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
3938 /* Disassociate this scroll bar from its window. */
3939 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3944 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3945 that we are displaying PORTION characters out of a total of WHOLE
3946 characters, starting at POSITION. If WINDOW has no scroll bar,
3949 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
3951 int portion
, whole
, position
;
3953 struct frame
*f
= XFRAME (w
->frame
);
3954 struct scroll_bar
*bar
;
3955 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
3956 int window_y
, window_height
;
3958 /* Get window dimensions. */
3959 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
3964 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
3966 height
= window_height
;
3968 /* Compute the left edge of the scroll bar area. */
3969 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
3971 /* Compute the width of the scroll bar which might be less than
3972 the width of the area reserved for the scroll bar. */
3973 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
3974 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
3978 /* Compute the left edge of the scroll bar. */
3979 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
3980 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
3982 sb_left
= left
+ (width
- sb_width
) / 2;
3984 /* Adjustments according to Inside Macintosh to make it look nice */
3986 disp_height
= height
;
3992 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
3998 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4001 /* Does the scroll bar exist yet? */
4002 if (NILP (w
->vertical_scroll_bar
))
4005 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4006 left
, top
, width
, height
, 0);
4008 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4010 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4014 /* It may just need to be moved and resized. */
4017 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4018 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4022 /* If already correctly positioned, do nothing. */
4023 if (XINT (bar
->left
) == sb_left
4024 && XINT (bar
->top
) == top
4025 && XINT (bar
->width
) == sb_width
4026 && XINT (bar
->height
) == height
)
4030 /* Clear areas not covered by the scroll bar because it's not as
4031 wide as the area reserved for it . This makes sure a
4032 previous mode line display is cleared after C-x 2 C-x 1, for
4034 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4035 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4036 left
, top
, area_width
, height
, 0);
4039 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4040 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4041 sb_left
- 1, top
, 1, height
, 0);
4045 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4046 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4050 /* Remember new settings. */
4051 XSETINT (bar
->left
, sb_left
);
4052 XSETINT (bar
->top
, top
);
4053 XSETINT (bar
->width
, sb_width
);
4054 XSETINT (bar
->height
, height
);
4060 /* Set the scroll bar's current state, unless we're currently being
4062 if (NILP (bar
->dragging
))
4064 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4067 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4070 int start
= ((double) position
* top_range
) / whole
;
4071 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4072 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4078 /* The following three hooks are used when we're doing a thorough
4079 redisplay of the frame. We don't explicitly know which scroll bars
4080 are going to be deleted, because keeping track of when windows go
4081 away is a real pain - "Can you say set-window-configuration, boys
4082 and girls?" Instead, we just assert at the beginning of redisplay
4083 that *all* scroll bars are to be removed, and then save a scroll bar
4084 from the fiery pit when we actually redisplay its window. */
4086 /* Arrange for all scroll bars on FRAME to be removed at the next call
4087 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4088 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4091 XTcondemn_scroll_bars (frame
)
4094 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4095 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4098 bar
= FRAME_SCROLL_BARS (frame
);
4099 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4100 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4101 XSCROLL_BAR (bar
)->prev
= Qnil
;
4102 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4103 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4104 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4109 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4110 Note that WINDOW isn't necessarily condemned at all. */
4113 XTredeem_scroll_bar (window
)
4114 struct window
*window
;
4116 struct scroll_bar
*bar
;
4118 /* We can't redeem this window's scroll bar if it doesn't have one. */
4119 if (NILP (window
->vertical_scroll_bar
))
4122 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4124 /* Unlink it from the condemned list. */
4126 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4128 if (NILP (bar
->prev
))
4130 /* If the prev pointer is nil, it must be the first in one of
4132 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4133 /* It's not condemned. Everything's fine. */
4135 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4136 window
->vertical_scroll_bar
))
4137 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4139 /* If its prev pointer is nil, it must be at the front of
4140 one or the other! */
4144 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4146 if (! NILP (bar
->next
))
4147 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4149 bar
->next
= FRAME_SCROLL_BARS (f
);
4151 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4152 if (! NILP (bar
->next
))
4153 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4157 /* Remove all scroll bars on FRAME that haven't been saved since the
4158 last call to `*condemn_scroll_bars_hook'. */
4161 XTjudge_scroll_bars (f
)
4164 Lisp_Object bar
, next
;
4166 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4168 /* Clear out the condemned list now so we won't try to process any
4169 more events on the hapless scroll bars. */
4170 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4172 for (; ! NILP (bar
); bar
= next
)
4174 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4176 x_scroll_bar_remove (b
);
4179 b
->next
= b
->prev
= Qnil
;
4182 /* Now there should be no references to the condemned scroll bars,
4183 and they should get garbage-collected. */
4188 activate_scroll_bars (frame
)
4194 bar
= FRAME_SCROLL_BARS (frame
);
4195 while (! NILP (bar
))
4197 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
4198 #ifdef TARGET_API_MAC_CARBON
4199 ActivateControl (ch
);
4201 SetControlMaximum (ch
,
4202 VERTICAL_SCROLL_BAR_TOP_RANGE (frame
,
4203 XINT (XSCROLL_BAR (bar
)
4206 bar
= XSCROLL_BAR (bar
)->next
;
4212 deactivate_scroll_bars (frame
)
4218 bar
= FRAME_SCROLL_BARS (frame
);
4219 while (! NILP (bar
))
4221 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
4222 #ifdef TARGET_API_MAC_CARBON
4223 DeactivateControl (ch
);
4225 SetControlMaximum (ch
, XINT (-1));
4227 bar
= XSCROLL_BAR (bar
)->next
;
4231 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4232 is set to something other than NO_EVENT, it is enqueued.
4234 This may be called from a signal handler, so we have to ignore GC
4238 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4239 struct scroll_bar
*bar
;
4242 struct input_event
*bufp
;
4244 if (! GC_WINDOWP (bar
->window
))
4247 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4248 bufp
->frame_or_window
= bar
->window
;
4251 bar
->dragging
= Qnil
;
4255 case kControlUpButtonPart
:
4256 bufp
->part
= scroll_bar_up_arrow
;
4258 case kControlDownButtonPart
:
4259 bufp
->part
= scroll_bar_down_arrow
;
4261 case kControlPageUpPart
:
4262 bufp
->part
= scroll_bar_above_handle
;
4264 case kControlPageDownPart
:
4265 bufp
->part
= scroll_bar_below_handle
;
4267 #ifdef TARGET_API_MAC_CARBON
4270 case kControlIndicatorPart
:
4272 if (er
->what
== mouseDown
)
4273 bar
->dragging
= make_number (0);
4274 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4275 bufp
->part
= scroll_bar_handle
;
4281 /* Handle some mouse motion while someone is dragging the scroll bar.
4283 This may be called from a signal handler, so we have to ignore GC
4287 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4288 struct scroll_bar
*bar
;
4292 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4294 last_mouse_movement_time
= t
;
4297 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4299 /* If we're dragging the bar, display it. */
4300 if (! GC_NILP (bar
->dragging
))
4302 /* Where should the handle be now? */
4303 int new_start
= y_pos
- 24;
4305 if (new_start
!= XINT (bar
->start
))
4307 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4309 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4315 /* Return information to the user about the current position of the
4316 mouse on the scroll bar. */
4319 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4321 Lisp_Object
*bar_window
;
4322 enum scroll_bar_part
*part
;
4324 unsigned long *time
;
4326 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4327 WindowPtr wp
= FrontWindow ();
4329 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
4330 int win_y
, top_range
;
4332 #if TARGET_API_MAC_CARBON
4333 SetPort (GetWindowPort (wp
));
4338 GetMouse (&mouse_pos
);
4340 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4341 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4343 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4347 if (! NILP (bar
->dragging
))
4348 win_y
-= XINT (bar
->dragging
);
4352 if (win_y
> top_range
)
4356 *bar_window
= bar
->window
;
4358 if (! NILP (bar
->dragging
))
4359 *part
= scroll_bar_handle
;
4360 else if (win_y
< XINT (bar
->start
))
4361 *part
= scroll_bar_above_handle
;
4362 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
4363 *part
= scroll_bar_handle
;
4365 *part
= scroll_bar_below_handle
;
4367 XSETINT (*x
, win_y
);
4368 XSETINT (*y
, top_range
);
4371 last_mouse_scroll_bar
= Qnil
;
4373 *time
= last_mouse_movement_time
;
4376 /***********************************************************************
4378 ***********************************************************************/
4380 /* Set clipping for output in glyph row ROW. W is the window in which
4381 we operate. GC is the graphics context to set clipping in.
4383 ROW may be a text row or, e.g., a mode line. Text rows must be
4384 clipped to the interior of the window dedicated to text display,
4385 mode lines must be clipped to the whole window. */
4388 x_clip_to_row (w
, row
, gc
)
4390 struct glyph_row
*row
;
4393 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4395 int window_y
, window_width
;
4397 window_box (w
, -1, 0, &window_y
, &window_width
, 0);
4399 clip_rect
.left
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
4400 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4401 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4402 clip_rect
.right
= clip_rect
.left
+ window_width
;
4403 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4405 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
4409 /* Draw a hollow box cursor on window W in glyph row ROW. */
4412 x_draw_hollow_cursor (w
, row
)
4414 struct glyph_row
*row
;
4416 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4417 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4418 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4421 struct glyph
*cursor_glyph
;
4424 /* Compute frame-relative coordinates from window-relative
4426 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
4427 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
4428 + row
->ascent
- w
->phys_cursor_ascent
);
4429 h
= row
->height
- 1;
4431 /* Get the glyph the cursor is on. If we can't tell because
4432 the current matrix is invalid or such, give up. */
4433 cursor_glyph
= get_phys_cursor_glyph (w
);
4434 if (cursor_glyph
== NULL
)
4437 /* Compute the width of the rectangle to draw. If on a stretch
4438 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4439 rectangle as wide as the glyph, but use a canonical character
4441 wd
= cursor_glyph
->pixel_width
- 1;
4442 if (cursor_glyph
->type
== STRETCH_GLYPH
4443 && !x_stretch_cursor_p
)
4444 wd
= min (FRAME_COLUMN_WIDTH (f
), wd
);
4446 /* The foreground of cursor_gc is typically the same as the normal
4447 background color, which can cause the cursor box to be invisible. */
4448 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4449 if (dpyinfo
->scratch_cursor_gc
)
4450 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
4452 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
4453 GCForeground
, &xgcv
);
4454 gc
= dpyinfo
->scratch_cursor_gc
;
4456 /* Set clipping, draw the rectangle, and reset clipping again. */
4457 x_clip_to_row (w
, row
, gc
);
4458 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
4459 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4463 /* Draw a bar cursor on window W in glyph row ROW.
4465 Implementation note: One would like to draw a bar cursor with an
4466 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4467 Unfortunately, I didn't find a font yet that has this property set.
4471 x_draw_bar_cursor (w
, row
, width
)
4473 struct glyph_row
*row
;
4476 /* If cursor hpos is out of bounds, don't draw garbage. This can
4477 happen in mini-buffer windows when switching between echo area
4478 glyphs and mini-buffer. */
4479 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
4481 struct frame
*f
= XFRAME (w
->frame
);
4482 struct glyph
*cursor_glyph
;
4490 cursor_glyph
= get_phys_cursor_glyph (w
);
4491 if (cursor_glyph
== NULL
)
4494 xgcv
.background
= f
->output_data
.mac
->cursor_pixel
;
4495 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4496 mask
= GCForeground
| GCBackground
;
4497 dpy
= FRAME_MAC_DISPLAY (f
);
4498 window
= FRAME_MAC_WINDOW (f
);
4499 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
4502 XChangeGC (dpy
, gc
, mask
, &xgcv
);
4505 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
4506 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
4510 width
= FRAME_CURSOR_WIDTH (f
);
4512 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
4513 x_clip_to_row (w
, row
, gc
);
4514 XFillRectangle (dpy
, window
, gc
,
4516 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
4517 min (cursor_glyph
->pixel_width
, width
),
4519 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4524 /* RIF: Define cursor CURSOR on frame F. */
4527 mac_define_frame_cursor (f
, cursor
)
4535 /* RIF: Clear area on frame F. */
4538 mac_clear_frame_area (f
, x
, y
, width
, height
)
4540 int x
, y
, width
, height
;
4542 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4543 x
, y
, width
, height
, 0);
4547 /* RIF: Draw cursor on window W. */
4550 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
4552 struct glyph_row
*glyph_row
;
4554 int cursor_type
, cursor_width
;
4559 w
->phys_cursor_type
= cursor_type
;
4560 w
->phys_cursor_width
= cursor_width
;
4561 w
->phys_cursor_on_p
= 1;
4563 if (glyph_row
->exact_window_width_line_p
4564 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
4566 glyph_row
->cursor_in_fringe_p
= 1;
4567 draw_fringe_bitmap (w
, glyph_row
, 0);
4571 switch (cursor_type
)
4573 case HOLLOW_BOX_CURSOR
:
4574 x_draw_hollow_cursor (w
, glyph_row
);
4577 case FILLED_BOX_CURSOR
:
4578 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
4582 /* TODO. For now, just draw bar cursor. */
4584 x_draw_bar_cursor (w
, glyph_row
, cursor_width
);
4599 #if 0 /* MAC_TODO: no icon support yet. */
4601 x_bitmap_icon (f
, icon
)
4607 if (FRAME_W32_WINDOW (f
) == 0)
4611 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
4612 else if (STRINGP (icon
))
4613 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
4614 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
4615 else if (SYMBOLP (icon
))
4619 if (EQ (icon
, intern ("application")))
4620 name
= (LPCTSTR
) IDI_APPLICATION
;
4621 else if (EQ (icon
, intern ("hand")))
4622 name
= (LPCTSTR
) IDI_HAND
;
4623 else if (EQ (icon
, intern ("question")))
4624 name
= (LPCTSTR
) IDI_QUESTION
;
4625 else if (EQ (icon
, intern ("exclamation")))
4626 name
= (LPCTSTR
) IDI_EXCLAMATION
;
4627 else if (EQ (icon
, intern ("asterisk")))
4628 name
= (LPCTSTR
) IDI_ASTERISK
;
4629 else if (EQ (icon
, intern ("winlogo")))
4630 name
= (LPCTSTR
) IDI_WINLOGO
;
4634 hicon
= LoadIcon (NULL
, name
);
4642 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
4647 #endif /* MAC_TODO */
4649 /************************************************************************
4651 ************************************************************************/
4653 /* Display Error Handling functions not used on W32. Listing them here
4654 helps diff stay in step when comparing w32term.c with xterm.c.
4656 x_error_catcher (display, error)
4657 x_catch_errors (dpy)
4658 x_catch_errors_unwind (old_val)
4659 x_check_errors (dpy, format)
4660 x_had_errors_p (dpy)
4661 x_clear_errors (dpy)
4662 x_uncatch_errors (dpy, count)
4664 x_connection_signal (signalnum)
4665 x_connection_closed (dpy, error_message)
4666 x_error_quitter (display, error)
4667 x_error_handler (display, error)
4668 x_io_error_quitter (display)
4673 /* Changing the font of the frame. */
4675 /* Give frame F the font named FONTNAME as its default font, and
4676 return the full name of that font. FONTNAME may be a wildcard
4677 pattern; in that case, we choose some font that fits the pattern.
4678 The return value shows which font we chose. */
4681 x_new_font (f
, fontname
)
4683 register char *fontname
;
4685 struct font_info
*fontp
4686 = FS_LOAD_FONT (f
, 0, fontname
, -1);
4691 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4692 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
4693 FRAME_FONTSET (f
) = -1;
4695 FRAME_COLUMN_WIDTH (f
) = FONT_WIDTH (FRAME_FONT (f
));
4696 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
4698 compute_fringe_widths (f
, 1);
4700 /* Compute the scroll bar width in character columns. */
4701 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
4703 int wid
= FRAME_COLUMN_WIDTH (f
);
4704 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
4705 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
4709 int wid
= FRAME_COLUMN_WIDTH (f
);
4710 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
4713 /* Now make the frame display the given font. */
4714 if (FRAME_MAC_WINDOW (f
) != 0)
4716 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
4718 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
4720 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
4723 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
4724 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
4727 return build_string (fontp
->full_name
);
4730 /* Give frame F the fontset named FONTSETNAME as its default font, and
4731 return the full name of that fontset. FONTSETNAME may be a wildcard
4732 pattern; in that case, we choose some fontset that fits the pattern.
4733 The return value shows which fontset we chose. */
4736 x_new_fontset (f
, fontsetname
)
4740 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
4746 if (FRAME_FONTSET (f
) == fontset
)
4747 /* This fontset is already set in frame F. There's nothing more
4749 return fontset_name (fontset
);
4751 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
4753 if (!STRINGP (result
))
4754 /* Can't load ASCII font. */
4757 /* Since x_new_font doesn't update any fontset information, do it now. */
4758 FRAME_FONTSET(f
) = fontset
;
4760 return build_string (fontsetname
);
4764 /***********************************************************************
4765 TODO: W32 Input Methods
4766 ***********************************************************************/
4767 /* Listing missing functions from xterm.c helps diff stay in step.
4769 xim_destroy_callback (xim, client_data, call_data)
4770 xim_open_dpy (dpyinfo, resource_name)
4772 xim_instantiate_callback (display, client_data, call_data)
4773 xim_initialize (dpyinfo, resource_name)
4774 xim_close_dpy (dpyinfo)
4779 /* Calculate the absolute position in frame F
4780 from its current recorded position values and gravity. */
4783 x_calc_absolute_position (f
)
4787 int flags
= f
->size_hint_flags
;
4791 /* Find the position of the outside upper-left corner of
4792 the inner window, with respect to the outer window. */
4793 if (f
->output_data
.mac
->parent_desc
!= FRAME_MAC_DISPLAY_INFO (f
)->root_window
)
4796 GetPort (&savePort
);
4798 #if TARGET_API_MAC_CARBON
4799 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
4801 SetPort (FRAME_MAC_WINDOW (f
));
4804 #if TARGET_API_MAC_CARBON
4808 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
4809 SetPt(&pt
, r
.left
, r
.top
);
4811 #else /* not TARGET_API_MAC_CARBON */
4812 SetPt(&pt
, FRAME_MAC_WINDOW (f
)->portRect
.left
, FRAME_MAC_WINDOW (f
)->portRect
.top
);
4813 #endif /* not TARGET_API_MAC_CARBON */
4814 LocalToGlobal (&pt
);
4818 /* Treat negative positions as relative to the leftmost bottommost
4819 position that fits on the screen. */
4820 if (flags
& XNegative
)
4821 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
4822 - 2 * f
->border_width
- pt
.h
4823 - FRAME_PIXEL_WIDTH (f
)
4825 /* NTEMACS_TODO: Subtract menubar height? */
4826 if (flags
& YNegative
)
4827 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
4828 - 2 * f
->border_width
- pt
.v
4829 - FRAME_PIXEL_HEIGHT (f
)
4831 /* The left_pos and top_pos
4832 are now relative to the top and left screen edges,
4833 so the flags should correspond. */
4834 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4837 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4838 to really change the position, and 0 when calling from
4839 x_make_frame_visible (in that case, XOFF and YOFF are the current
4840 position values). It is -1 when calling from x_set_frame_parameters,
4841 which means, do adjust for borders but don't change the gravity. */
4844 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4846 register int xoff
, yoff
;
4849 int modified_top
, modified_left
;
4851 if (change_gravity
> 0)
4855 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4857 f
->size_hint_flags
|= XNegative
;
4859 f
->size_hint_flags
|= YNegative
;
4860 f
->win_gravity
= NorthWestGravity
;
4862 x_calc_absolute_position (f
);
4865 x_wm_set_size_hint (f
, (long) 0, 0);
4867 modified_left
= f
->left_pos
;
4868 modified_top
= f
->top_pos
;
4870 MoveWindow (f
->output_data
.mac
->mWP
, modified_left
+ 6,
4871 modified_top
+ 42, false);
4876 /* Call this to change the size of frame F's x-window.
4877 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4878 for this size change and subsequent size changes.
4879 Otherwise we leave the window gravity unchanged. */
4882 x_set_window_size (f
, change_gravity
, cols
, rows
)
4887 int pixelwidth
, pixelheight
;
4891 check_frame_size (f
, &rows
, &cols
);
4892 f
->scroll_bar_actual_width
4893 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
4895 compute_fringe_widths (f
, 0);
4897 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
4898 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
4900 f
->win_gravity
= NorthWestGravity
;
4901 x_wm_set_size_hint (f
, (long) 0, 0);
4903 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
4905 /* Now, strictly speaking, we can't be sure that this is accurate,
4906 but the window manager will get around to dealing with the size
4907 change request eventually, and we'll hear how it went when the
4908 ConfigureNotify event gets here.
4910 We could just not bother storing any of this information here,
4911 and let the ConfigureNotify event set everything up, but that
4912 might be kind of confusing to the Lisp code, since size changes
4913 wouldn't be reported in the frame parameters until some random
4914 point in the future when the ConfigureNotify event arrives.
4916 We pass 1 for DELAY since we can't run Lisp code inside of
4918 change_frame_size (f
, rows
, cols
, 0, 1, 0);
4919 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
4920 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
4922 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4923 receive in the ConfigureNotify event; if we get what we asked
4924 for, then the event won't cause the screen to become garbaged, so
4925 we have to make sure to do it here. */
4926 SET_FRAME_GARBAGED (f
);
4928 XFlush (FRAME_X_DISPLAY (f
));
4930 /* If cursor was outside the new size, mark it as off. */
4931 mark_window_cursors_off (XWINDOW (f
->root_window
));
4933 /* Clear out any recollection of where the mouse highlighting was,
4934 since it might be in a place that's outside the new frame size.
4935 Actually checking whether it is outside is a pain in the neck,
4936 so don't try--just let the highlighting be done afresh with new size. */
4937 cancel_mouse_face (f
);
4942 /* Mouse warping. */
4944 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
4947 x_set_mouse_position (f
, x
, y
)
4953 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
4954 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
4956 if (pix_x
< 0) pix_x
= 0;
4957 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
4959 if (pix_y
< 0) pix_y
= 0;
4960 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
4962 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
4966 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4970 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
4973 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
4974 0, 0, 0, 0, pix_x
, pix_y
);
4980 /* focus shifting, raising and lowering. */
4983 x_focus_on_frame (f
)
4986 #if 0 /* This proves to be unpleasant. */
4990 /* I don't think that the ICCCM allows programs to do things like this
4991 without the interaction of the window manager. Whatever you end up
4992 doing with this code, do it to x_unfocus_frame too. */
4993 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4994 RevertToPointerRoot
, CurrentTime
);
5004 /* Raise frame F. */
5009 if (f
->async_visible
)
5010 SelectWindow (FRAME_MAC_WINDOW (f
));
5013 /* Lower frame F. */
5018 if (f
->async_visible
)
5019 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5023 XTframe_raise_lower (f
, raise_flag
)
5033 /* Change of visibility. */
5035 /* This tries to wait until the frame is really visible.
5036 However, if the window manager asks the user where to position
5037 the frame, this will return before the user finishes doing that.
5038 The frame will not actually be visible at that time,
5039 but it will become visible later when the window manager
5040 finishes with it. */
5043 x_make_frame_visible (f
)
5047 int original_top
, original_left
;
5051 if (! FRAME_VISIBLE_P (f
))
5053 /* We test FRAME_GARBAGED_P here to make sure we don't
5054 call x_set_offset a second time
5055 if we get to x_make_frame_visible a second time
5056 before the window gets really visible. */
5057 if (! FRAME_ICONIFIED_P (f
)
5058 && ! f
->output_data
.mac
->asked_for_visible
)
5059 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5061 f
->output_data
.mac
->asked_for_visible
= 1;
5063 ShowWindow (FRAME_MAC_WINDOW (f
));
5066 XFlush (FRAME_MAC_DISPLAY (f
));
5068 #if 0 /* MAC_TODO */
5069 /* Synchronize to ensure Emacs knows the frame is visible
5070 before we do anything else. We do this loop with input not blocked
5071 so that incoming events are handled. */
5076 /* This must come after we set COUNT. */
5079 XSETFRAME (frame
, f
);
5081 /* Wait until the frame is visible. Process X events until a
5082 MapNotify event has been seen, or until we think we won't get a
5083 MapNotify at all.. */
5084 for (count
= input_signal_count
+ 10;
5085 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5087 /* Force processing of queued events. */
5090 /* Machines that do polling rather than SIGIO have been
5091 observed to go into a busy-wait here. So we'll fake an
5092 alarm signal to let the handler know that there's something
5093 to be read. We used to raise a real alarm, but it seems
5094 that the handler isn't always enabled here. This is
5096 if (input_polling_used ())
5098 /* It could be confusing if a real alarm arrives while
5099 processing the fake one. Turn it off and let the
5100 handler reset it. */
5101 extern void poll_for_input_1
P_ ((void));
5102 int old_poll_suppress_count
= poll_suppress_count
;
5103 poll_suppress_count
= 1;
5104 poll_for_input_1 ();
5105 poll_suppress_count
= old_poll_suppress_count
;
5108 /* See if a MapNotify event has been processed. */
5109 FRAME_SAMPLE_VISIBILITY (f
);
5112 #endif /* MAC_TODO */
5115 /* Change from mapped state to withdrawn state. */
5117 /* Make the frame visible (mapped and not iconified). */
5120 x_make_frame_invisible (f
)
5123 /* Don't keep the highlight on an invisible frame. */
5124 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5125 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5129 HideWindow (FRAME_MAC_WINDOW (f
));
5131 /* We can't distinguish this from iconification
5132 just by the event that we get from the server.
5133 So we can't win using the usual strategy of letting
5134 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5135 and synchronize with the server to make sure we agree. */
5137 FRAME_ICONIFIED_P (f
) = 0;
5138 f
->async_visible
= 0;
5139 f
->async_iconified
= 0;
5144 /* Change window state from mapped to iconified. */
5150 /* Don't keep the highlight on an invisible frame. */
5151 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5152 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5155 /* Review: Since window is still visible in dock, still allow updates? */
5156 if (f
->async_iconified
)
5162 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5168 /* Destroy the X window of frame F. */
5171 x_destroy_window (f
)
5174 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5178 DisposeWindow (FRAME_MAC_WINDOW (f
));
5180 free_frame_menubar (f
);
5181 free_frame_faces (f
);
5183 xfree (f
->output_data
.mac
);
5184 f
->output_data
.mac
= 0;
5185 if (f
== dpyinfo
->x_focus_frame
)
5186 dpyinfo
->x_focus_frame
= 0;
5187 if (f
== dpyinfo
->x_focus_event_frame
)
5188 dpyinfo
->x_focus_event_frame
= 0;
5189 if (f
== dpyinfo
->x_highlight_frame
)
5190 dpyinfo
->x_highlight_frame
= 0;
5192 dpyinfo
->reference_count
--;
5194 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5196 dpyinfo
->mouse_face_beg_row
5197 = dpyinfo
->mouse_face_beg_col
= -1;
5198 dpyinfo
->mouse_face_end_row
5199 = dpyinfo
->mouse_face_end_col
= -1;
5200 dpyinfo
->mouse_face_window
= Qnil
;
5201 dpyinfo
->mouse_face_deferred_gc
= 0;
5202 dpyinfo
->mouse_face_mouse_frame
= 0;
5208 /* Setting window manager hints. */
5210 /* Set the normal size hints for the window manager, for frame F.
5211 FLAGS is the flags word to use--or 0 meaning preserve the flags
5212 that the window now has.
5213 If USER_POSITION is nonzero, we set the USPosition
5214 flag (this is useful when FLAGS is 0). */
5216 x_wm_set_size_hint (f
, flags
, user_position
)
5221 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
5222 XSizeHints size_hints
;
5224 #ifdef USE_X_TOOLKIT
5227 Dimension widget_width
, widget_height
;
5228 Window window
= XtWindow (f
->output_data
.x
->widget
);
5229 #else /* not USE_X_TOOLKIT */
5230 Window window
= FRAME_X_WINDOW (f
);
5231 #endif /* not USE_X_TOOLKIT */
5233 /* Setting PMaxSize caused various problems. */
5234 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5236 size_hints
.x
= f
->left_pos
;
5237 size_hints
.y
= f
->top_pos
;
5239 #ifdef USE_X_TOOLKIT
5240 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5241 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5242 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5243 size_hints
.height
= widget_height
;
5244 size_hints
.width
= widget_width
;
5245 #else /* not USE_X_TOOLKIT */
5246 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
5247 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
5248 #endif /* not USE_X_TOOLKIT */
5250 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
5251 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
5252 size_hints
.max_width
5253 = FRAME_X_DISPLAY_INFO (f
)->width
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5254 size_hints
.max_height
5255 = FRAME_X_DISPLAY_INFO (f
)->height
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5257 /* Calculate the base and minimum sizes.
5259 (When we use the X toolkit, we don't do it here.
5260 Instead we copy the values that the widgets are using, below.) */
5261 #ifndef USE_X_TOOLKIT
5263 int base_width
, base_height
;
5264 int min_rows
= 0, min_cols
= 0;
5266 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5267 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5269 check_frame_size (f
, &min_rows
, &min_cols
);
5271 /* The window manager uses the base width hints to calculate the
5272 current number of rows and columns in the frame while
5273 resizing; min_width and min_height aren't useful for this
5274 purpose, since they might not give the dimensions for a
5275 zero-row, zero-column frame.
5277 We use the base_width and base_height members if we have
5278 them; otherwise, we set the min_width and min_height members
5279 to the size for a zero x zero frame. */
5282 size_hints
.flags
|= PBaseSize
;
5283 size_hints
.base_width
= base_width
;
5284 size_hints
.base_height
= base_height
;
5285 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5286 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5288 size_hints
.min_width
= base_width
;
5289 size_hints
.min_height
= base_height
;
5293 /* If we don't need the old flags, we don't need the old hint at all. */
5296 size_hints
.flags
|= flags
;
5299 #endif /* not USE_X_TOOLKIT */
5302 XSizeHints hints
; /* Sometimes I hate X Windows... */
5303 long supplied_return
;
5307 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5310 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5313 #ifdef USE_X_TOOLKIT
5314 size_hints
.base_height
= hints
.base_height
;
5315 size_hints
.base_width
= hints
.base_width
;
5316 size_hints
.min_height
= hints
.min_height
;
5317 size_hints
.min_width
= hints
.min_width
;
5321 size_hints
.flags
|= flags
;
5326 if (hints
.flags
& PSize
)
5327 size_hints
.flags
|= PSize
;
5328 if (hints
.flags
& PPosition
)
5329 size_hints
.flags
|= PPosition
;
5330 if (hints
.flags
& USPosition
)
5331 size_hints
.flags
|= USPosition
;
5332 if (hints
.flags
& USSize
)
5333 size_hints
.flags
|= USSize
;
5337 #ifndef USE_X_TOOLKIT
5342 size_hints
.win_gravity
= f
->win_gravity
;
5343 size_hints
.flags
|= PWinGravity
;
5347 size_hints
.flags
&= ~ PPosition
;
5348 size_hints
.flags
|= USPosition
;
5350 #endif /* PWinGravity */
5353 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5355 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5357 #endif /* MAC_TODO */
5360 #if 0 /* MAC_TODO: hide application instead of iconify? */
5361 /* Used for IconicState or NormalState */
5364 x_wm_set_window_state (f
, state
)
5368 #ifdef USE_X_TOOLKIT
5371 XtSetArg (al
[0], XtNinitialState
, state
);
5372 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5373 #else /* not USE_X_TOOLKIT */
5374 Window window
= FRAME_X_WINDOW (f
);
5376 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5377 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5379 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5380 #endif /* not USE_X_TOOLKIT */
5384 x_wm_set_icon_pixmap (f
, pixmap_id
)
5390 #ifndef USE_X_TOOLKIT
5391 Window window
= FRAME_X_WINDOW (f
);
5396 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5397 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5401 /* It seems there is no way to turn off use of an icon pixmap.
5402 The following line does it, only if no icon has yet been created,
5403 for some window managers. But with mwm it crashes.
5404 Some people say it should clear the IconPixmapHint bit in this case,
5405 but that doesn't work, and the X consortium said it isn't the
5406 right thing at all. Since there is no way to win,
5407 best to explicitly give up. */
5409 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5415 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5419 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
5420 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5423 #else /* not USE_X_TOOLKIT */
5425 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5426 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5428 #endif /* not USE_X_TOOLKIT */
5431 #endif /* MAC_TODO */
5434 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5438 #if 0 /* MAC_TODO: no icons on Mac */
5439 #ifdef USE_X_TOOLKIT
5440 Window window
= XtWindow (f
->output_data
.x
->widget
);
5442 Window window
= FRAME_X_WINDOW (f
);
5445 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5446 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5447 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5449 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5450 #endif /* MAC_TODO */
5454 /***********************************************************************
5456 ***********************************************************************/
5458 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5461 x_get_font_info (f
, font_idx
)
5465 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
5468 /* the global font name table */
5469 char **font_name_table
= NULL
;
5470 int font_name_table_size
= 0;
5471 int font_name_count
= 0;
5473 /* compare two strings ignoring case */
5475 stricmp (const char *s
, const char *t
)
5477 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
5480 return tolower (*s
) - tolower (*t
);
5483 /* compare two strings ignoring case and handling wildcard */
5485 wildstrieq (char *s1
, char *s2
)
5487 if (strcmp (s1
, "*") == 0 || strcmp (s2
, "*") == 0)
5490 return stricmp (s1
, s2
) == 0;
5493 /* Assume parameter 1 is fully qualified, no wildcards. */
5495 mac_font_pattern_match (fontname
, pattern
)
5499 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
5500 char *font_name_copy
= (char *) alloca (strlen (fontname
) + 1);
5503 /* Copy fontname so we can modify it during comparison. */
5504 strcpy (font_name_copy
, fontname
);
5509 /* Turn pattern into a regexp and do a regexp match. */
5510 for (; *pattern
; pattern
++)
5512 if (*pattern
== '?')
5514 else if (*pattern
== '*')
5525 return (fast_c_string_match_ignore_case (build_string (regex
),
5526 font_name_copy
) >= 0);
5529 /* Two font specs are considered to match if their foundry, family,
5530 weight, slant, and charset match. */
5532 mac_font_match (char *mf
, char *xf
)
5534 char m_foundry
[50], m_family
[50], m_weight
[20], m_slant
[2], m_charset
[20];
5535 char x_foundry
[50], x_family
[50], x_weight
[20], x_slant
[2], x_charset
[20];
5537 if (sscanf (mf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5538 m_foundry
, m_family
, m_weight
, m_slant
, m_charset
) != 5)
5539 return mac_font_pattern_match (mf
, xf
);
5541 if (sscanf (xf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5542 x_foundry
, x_family
, x_weight
, x_slant
, x_charset
) != 5)
5543 return mac_font_pattern_match (mf
, xf
);
5545 return (wildstrieq (m_foundry
, x_foundry
)
5546 && wildstrieq (m_family
, x_family
)
5547 && wildstrieq (m_weight
, x_weight
)
5548 && wildstrieq (m_slant
, x_slant
)
5549 && wildstrieq (m_charset
, x_charset
))
5550 || mac_font_pattern_match (mf
, xf
);
5555 mac_to_x_fontname (char *name
, int size
, Style style
, short scriptcode
)
5557 char foundry
[32], family
[32], cs
[32];
5558 char xf
[255], *result
, *p
;
5560 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) != 3)
5562 strcpy(foundry
, "Apple");
5563 strcpy(family
, name
);
5568 strcpy(cs
, "big5-0");
5571 strcpy(cs
, "gb2312.1980-0");
5574 strcpy(cs
, "jisx0208.1983-sjis");
5577 /* Each Apple Japanese font is entered into the font table
5578 twice: once as a jisx0208.1983-sjis font and once as a
5579 jisx0201.1976-0 font. The latter can be used to display
5580 the ascii charset and katakana-jisx0201 charset. A
5581 negative script code signals that the name of this latter
5582 font is being built. */
5583 strcpy(cs
, "jisx0201.1976-0");
5586 strcpy(cs
, "ksc5601.1989-0");
5589 strcpy(cs
, "mac-roman");
5594 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5595 foundry
, family
, style
& bold
? "bold" : "medium",
5596 style
& italic
? 'i' : 'r', size
, size
* 10, size
* 10, cs
);
5598 result
= (char *) xmalloc (strlen (xf
) + 1);
5599 strcpy (result
, xf
);
5600 for (p
= result
; *p
; p
++)
5606 /* Convert an X font spec to the corresponding mac font name, which
5607 can then be passed to GetFNum after conversion to a Pascal string.
5608 For ordinary Mac fonts, this should just be their names, like
5609 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5610 collection contain their charset designation in their names, like
5611 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5612 names are handled accordingly. */
5614 x_font_name_to_mac_font_name (char *xf
, char *mf
)
5616 char foundry
[32], family
[32], weight
[20], slant
[2], cs
[32];
5620 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5621 foundry
, family
, weight
, slant
, cs
) != 5 &&
5622 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5623 foundry
, family
, weight
, slant
, cs
) != 5)
5626 if (strcmp (cs
, "big5-0") == 0 || strcmp (cs
, "gb2312.1980-0") == 0
5627 || strcmp (cs
, "jisx0208.1983-sjis") == 0
5628 || strcmp (cs
, "jisx0201.1976-0") == 0
5629 || strcmp (cs
, "ksc5601.1989-0") == 0 || strcmp (cs
, "mac-roman") == 0)
5632 sprintf(mf
, "%s-%s-%s", foundry
, family
, cs
);
5637 add_font_name_table_entry (char *font_name
)
5639 if (font_name_table_size
== 0)
5641 font_name_table_size
= 16;
5642 font_name_table
= (char **)
5643 xmalloc (font_name_table_size
* sizeof (char *));
5645 else if (font_name_count
+ 1 >= font_name_table_size
)
5647 font_name_table_size
+= 16;
5648 font_name_table
= (char **)
5649 xrealloc (font_name_table
,
5650 font_name_table_size
* sizeof (char *));
5653 font_name_table
[font_name_count
++] = font_name
;
5656 /* Sets up the table font_name_table to contain the list of all fonts
5657 in the system the first time the table is used so that the Resource
5658 Manager need not be accessed every time this information is
5662 init_font_name_table ()
5664 #if TARGET_API_MAC_CARBON
5667 if (Gestalt (gestaltSystemVersion
, &sv
) == noErr
&& sv
>= 0x1000)
5669 FMFontFamilyIterator ffi
;
5670 FMFontFamilyInstanceIterator ffii
;
5673 /* Create a dummy instance iterator here to avoid creating and
5674 destroying it in the loop. */
5675 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
5677 /* Create an iterator to enumerate the font families. */
5678 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
5681 FMDisposeFontFamilyInstanceIterator (&ffii
);
5685 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
5693 if (FMGetFontFamilyName (ff
, name
) != noErr
)
5697 sc
= FontToScript (ff
);
5699 /* Point the instance iterator at the current font family. */
5700 if (FMResetFontFamilyInstanceIterator(ff
, &ffii
) != noErr
)
5703 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
5707 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
5709 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
5711 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
5713 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
5719 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
5721 if (smJapanese
== sc
)
5722 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
5728 /* Dispose of the iterators. */
5729 FMDisposeFontFamilyIterator (&ffi
);
5730 FMDisposeFontFamilyInstanceIterator (&ffii
);
5734 #endif /* TARGET_API_MAC_CARBON */
5736 SInt16 fontnum
, old_fontnum
;
5737 int num_mac_fonts
= CountResources('FOND');
5739 Handle font_handle
, font_handle_2
;
5740 short id
, scriptcode
;
5743 struct FontAssoc
*fat
;
5744 struct AsscEntry
*assc_entry
;
5746 GetPort (&port
); /* save the current font number used */
5747 #if TARGET_API_MAC_CARBON
5748 old_fontnum
= GetPortTextFont (port
);
5750 old_fontnum
= port
->txFont
;
5753 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
5755 font_handle
= GetIndResource ('FOND', i
);
5759 GetResInfo (font_handle
, &id
, &type
, name
);
5760 GetFNum (name
, &fontnum
);
5766 scriptcode
= FontToScript (fontnum
);
5769 HLock (font_handle
);
5771 if (GetResourceSizeOnDisk (font_handle
)
5772 >= sizeof (struct FamRec
))
5774 fat
= (struct FontAssoc
*) (*font_handle
5775 + sizeof (struct FamRec
));
5777 = (struct AsscEntry
*) (*font_handle
5778 + sizeof (struct FamRec
)
5779 + sizeof (struct FontAssoc
));
5781 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
5783 if (font_name_table_size
== 0)
5785 font_name_table_size
= 16;
5786 font_name_table
= (char **)
5787 xmalloc (font_name_table_size
* sizeof (char *));
5789 else if (font_name_count
>= font_name_table_size
)
5791 font_name_table_size
+= 16;
5792 font_name_table
= (char **)
5793 xrealloc (font_name_table
,
5794 font_name_table_size
* sizeof (char *));
5796 font_name_table
[font_name_count
++]
5797 = mac_to_x_fontname (name
,
5798 assc_entry
->fontSize
,
5799 assc_entry
->fontStyle
,
5801 /* Both jisx0208.1983-sjis and
5802 jisx0201.1976-sjis parts are contained in
5803 Apple Japanese (SJIS) font. */
5804 if (smJapanese
== scriptcode
)
5806 font_name_table
[font_name_count
++]
5807 = mac_to_x_fontname (name
,
5808 assc_entry
->fontSize
,
5809 assc_entry
->fontStyle
,
5815 HUnlock (font_handle
);
5816 font_handle_2
= GetNextFOND (font_handle
);
5817 ReleaseResource (font_handle
);
5818 font_handle
= font_handle_2
;
5820 while (ResError () == noErr
&& font_handle
);
5823 TextFont (old_fontnum
);
5824 #if TARGET_API_MAC_CARBON
5826 #endif /* TARGET_API_MAC_CARBON */
5830 /* Return a list of at most MAXNAMES font specs matching the one in
5831 PATTERN. Cache matching fonts for patterns in
5832 dpyinfo->name_list_element to avoid looking them up again by
5833 calling mac_font_pattern_match (slow). Return as many matching
5834 fonts as possible if MAXNAMES = -1. */
5837 x_list_fonts (struct frame
*f
,
5838 Lisp_Object pattern
,
5843 Lisp_Object newlist
= Qnil
, tem
, key
;
5846 struct gcpro gcpro1
, gcpro2
;
5847 struct mac_display_info
*dpyinfo
= f
? FRAME_MAC_DISPLAY_INFO (f
) : NULL
;
5849 if (font_name_table
== NULL
) /* Initialize when first used. */
5850 init_font_name_table ();
5854 tem
= XCDR (dpyinfo
->name_list_element
);
5855 key
= Fcons (pattern
, make_number (maxnames
));
5857 newlist
= Fassoc (key
, tem
);
5858 if (!NILP (newlist
))
5860 newlist
= Fcdr_safe (newlist
);
5865 ptnstr
= SDATA (pattern
);
5867 GCPRO2 (pattern
, newlist
);
5869 /* Scan and matching bitmap fonts. */
5870 for (i
= 0; i
< font_name_count
; i
++)
5872 if (mac_font_pattern_match (font_name_table
[i
], ptnstr
))
5874 newlist
= Fcons (build_string (font_name_table
[i
]), newlist
);
5877 if (maxnames
> 0 && n_fonts
>= maxnames
)
5882 /* MAC_TODO: add code for matching outline fonts here */
5888 XSETCDR (dpyinfo
->name_list_element
,
5889 Fcons (Fcons (key
, newlist
),
5890 XCDR (dpyinfo
->name_list_element
)));
5900 /* Check that FONT is valid on frame F. It is if it can be found in F's
5904 x_check_font (f
, font
)
5909 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5911 xassert (font
!= NULL
);
5913 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5914 if (dpyinfo
->font_table
[i
].name
5915 && font
== dpyinfo
->font_table
[i
].font
)
5918 xassert (i
< dpyinfo
->n_fonts
);
5921 #endif /* GLYPH_DEBUG != 0 */
5923 /* Set *W to the minimum width, *H to the minimum font height of FONT.
5924 Note: There are (broken) X fonts out there with invalid XFontStruct
5925 min_bounds contents. For example, handa@etl.go.jp reports that
5926 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
5927 have font->min_bounds.width == 0. */
5930 x_font_min_bounds (font
, w
, h
)
5931 MacFontStruct
*font
;
5935 * TODO: Windows does not appear to offer min bound, only
5936 * average and maximum width, and maximum height.
5938 *h
= FONT_HEIGHT (font
);
5939 *w
= FONT_WIDTH (font
);
5943 /* Compute the smallest character width and smallest font height over
5944 all fonts available on frame F. Set the members smallest_char_width
5945 and smallest_font_height in F's x_display_info structure to
5946 the values computed. Value is non-zero if smallest_font_height or
5947 smallest_char_width become smaller than they were before. */
5950 x_compute_min_glyph_bounds (f
)
5954 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5955 MacFontStruct
*font
;
5956 int old_width
= dpyinfo
->smallest_char_width
;
5957 int old_height
= dpyinfo
->smallest_font_height
;
5959 dpyinfo
->smallest_font_height
= 100000;
5960 dpyinfo
->smallest_char_width
= 100000;
5962 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
5963 if (dpyinfo
->font_table
[i
].name
)
5965 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
5968 font
= (MacFontStruct
*) fontp
->font
;
5969 xassert (font
!= (MacFontStruct
*) ~0);
5970 x_font_min_bounds (font
, &w
, &h
);
5972 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
5973 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
5976 xassert (dpyinfo
->smallest_char_width
> 0
5977 && dpyinfo
->smallest_font_height
> 0);
5979 return (dpyinfo
->n_fonts
== 1
5980 || dpyinfo
->smallest_char_width
< old_width
5981 || dpyinfo
->smallest_font_height
< old_height
);
5985 /* Determine whether given string is a fully-specified XLFD: all 14
5986 fields are present, none is '*'. */
5989 is_fully_specified_xlfd (char *p
)
5997 for (i
= 0; i
< 13; i
++)
5999 q
= strchr (p
+ 1, '-');
6002 if (q
- p
== 2 && *(p
+ 1) == '*')
6007 if (strchr (p
+ 1, '-') != NULL
)
6010 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6017 const int kDefaultFontSize
= 9;
6020 /* XLoadQueryFont creates and returns an internal representation for a
6021 font in a MacFontStruct struct. There is really no concept
6022 corresponding to "loading" a font on the Mac. But we check its
6023 existence and find the font number and all other information for it
6024 and store them in the returned MacFontStruct. */
6026 static MacFontStruct
*
6027 XLoadQueryFont (Display
*dpy
, char *fontname
)
6029 int i
, size
, is_two_byte_font
, char_width
;
6032 SInt16 old_fontnum
, old_fontsize
;
6036 Style fontface
= normal
;
6037 MacFontStruct
*font
;
6038 FontInfo the_fontinfo
;
6039 char s_weight
[7], c_slant
;
6041 if (is_fully_specified_xlfd (fontname
))
6045 for (i
= 0; i
< font_name_count
; i
++)
6046 if (mac_font_pattern_match (font_name_table
[i
], fontname
))
6049 if (i
>= font_name_count
)
6052 name
= font_name_table
[i
];
6055 GetPort (&port
); /* save the current font number used */
6056 #if TARGET_API_MAC_CARBON
6057 old_fontnum
= GetPortTextFont (port
);
6058 old_fontsize
= GetPortTextSize (port
);
6059 old_fontface
= GetPortTextFace (port
);
6061 old_fontnum
= port
->txFont
;
6062 old_fontsize
= port
->txSize
;
6063 old_fontface
= port
->txFace
;
6066 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size
) != 1)
6067 size
= kDefaultFontSize
;
6069 if (sscanf (name
, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight
) == 1)
6070 if (strcmp (s_weight
, "bold") == 0)
6073 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant
) == 1)
6077 x_font_name_to_mac_font_name (name
, mfontname
);
6079 GetFNum (mfontname
, &fontnum
);
6083 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
6085 font
->fontname
= (char *) xmalloc (strlen (name
) + 1);
6086 bcopy (name
, font
->fontname
, strlen (name
) + 1);
6088 font
->mac_fontnum
= fontnum
;
6089 font
->mac_fontsize
= size
;
6090 font
->mac_fontface
= fontface
;
6091 font
->mac_scriptcode
= FontToScript (fontnum
);
6093 /* Apple Japanese (SJIS) font is listed as both
6094 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6095 (Roman script) in init_font_name_table (). The latter should be
6096 treated as a one-byte font. */
6101 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6103 && 0 == strcmp (cs
, "jisx0201.1976-0"))
6104 font
->mac_scriptcode
= smRoman
;
6107 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
6108 font
->mac_scriptcode
== smTradChinese
||
6109 font
->mac_scriptcode
== smSimpChinese
||
6110 font
->mac_scriptcode
== smKorean
;
6114 TextFace (fontface
);
6116 GetFontInfo (&the_fontinfo
);
6118 font
->ascent
= the_fontinfo
.ascent
;
6119 font
->descent
= the_fontinfo
.descent
;
6121 font
->min_byte1
= 0;
6122 if (is_two_byte_font
)
6123 font
->max_byte1
= 1;
6125 font
->max_byte1
= 0;
6126 font
->min_char_or_byte2
= 0x20;
6127 font
->max_char_or_byte2
= 0xff;
6129 if (is_two_byte_font
)
6131 /* Use the width of an "ideographic space" of that font because
6132 the_fontinfo.widMax returns the wrong width for some fonts. */
6133 switch (font
->mac_scriptcode
)
6136 char_width
= StringWidth("\p\x81\x40");
6139 char_width
= StringWidth("\p\xa1\x40");
6142 char_width
= StringWidth("\p\xa1\xa1");
6145 char_width
= StringWidth("\p\xa1\xa1");
6150 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6151 returns 15 for 12-point Monaco! */
6152 char_width
= CharWidth ('m');
6154 font
->max_bounds
.rbearing
= char_width
;
6155 font
->max_bounds
.lbearing
= 0;
6156 font
->max_bounds
.width
= char_width
;
6157 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
6158 font
->max_bounds
.descent
= the_fontinfo
.descent
;
6160 font
->min_bounds
= font
->max_bounds
;
6162 if (is_two_byte_font
|| CharWidth ('m') == CharWidth ('i'))
6163 font
->per_char
= NULL
;
6166 font
->per_char
= (XCharStruct
*)
6167 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
6171 for (c
= 0x20; c
<= 0xff; c
++)
6173 font
->per_char
[c
- 0x20] = font
->max_bounds
;
6174 font
->per_char
[c
- 0x20].width
= CharWidth (c
);
6179 TextFont (old_fontnum
); /* restore previous font number, size and face */
6180 TextSize (old_fontsize
);
6181 TextFace (old_fontface
);
6187 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6188 pointer to the structure font_info while allocating it dynamically.
6189 If SIZE is 0, load any size of font.
6190 If loading is failed, return NULL. */
6193 x_load_font (f
, fontname
, size
)
6195 register char *fontname
;
6198 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6199 Lisp_Object font_names
;
6201 /* Get a list of all the fonts that match this name. Once we
6202 have a list of matching fonts, we compare them against the fonts
6203 we already have by comparing names. */
6204 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
6206 if (!NILP (font_names
))
6211 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6212 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
6213 if (dpyinfo
->font_table
[i
].name
6214 && (!strcmp (dpyinfo
->font_table
[i
].name
,
6215 SDATA (XCAR (tail
)))
6216 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6217 SDATA (XCAR (tail
)))))
6218 return (dpyinfo
->font_table
+ i
);
6221 /* Load the font and add it to the table. */
6224 struct MacFontStruct
*font
;
6225 struct font_info
*fontp
;
6226 unsigned long value
;
6229 /* If we have found fonts by x_list_font, load one of them. If
6230 not, we still try to load a font by the name given as FONTNAME
6231 because XListFonts (called in x_list_font) of some X server has
6232 a bug of not finding a font even if the font surely exists and
6233 is loadable by XLoadQueryFont. */
6234 if (size
> 0 && !NILP (font_names
))
6235 fontname
= (char *) SDATA (XCAR (font_names
));
6237 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
6241 /* Find a free slot in the font table. */
6242 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6243 if (dpyinfo
->font_table
[i
].name
== NULL
)
6246 /* If no free slot found, maybe enlarge the font table. */
6247 if (i
== dpyinfo
->n_fonts
6248 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
6251 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
6252 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
6254 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
6257 fontp
= dpyinfo
->font_table
+ i
;
6258 if (i
== dpyinfo
->n_fonts
)
6261 /* Now fill in the slots of *FONTP. */
6263 bzero (fontp
, sizeof (*fontp
));
6265 fontp
->font_idx
= i
;
6266 fontp
->name
= (char *) xmalloc (strlen (font
->fontname
) + 1);
6267 bcopy (font
->fontname
, fontp
->name
, strlen (font
->fontname
) + 1);
6269 fontp
->full_name
= fontp
->name
;
6271 fontp
->size
= font
->max_bounds
.width
;
6272 fontp
->height
= FONT_HEIGHT (font
);
6274 /* For some font, ascent and descent in max_bounds field is
6275 larger than the above value. */
6276 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6277 if (max_height
> fontp
->height
)
6278 fontp
->height
= max_height
;
6281 /* The slot `encoding' specifies how to map a character
6282 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6283 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6284 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6285 2:0xA020..0xFF7F). For the moment, we don't know which charset
6286 uses this font. So, we set information in fontp->encoding[1]
6287 which is never used by any charset. If mapping can't be
6288 decided, set FONT_ENCODING_NOT_DECIDED. */
6289 if (font
->mac_scriptcode
== smJapanese
)
6290 fontp
->encoding
[1] = 4;
6294 = (font
->max_byte1
== 0
6296 ? (font
->min_char_or_byte2
< 0x80
6297 ? (font
->max_char_or_byte2
< 0x80
6298 ? 0 /* 0x20..0x7F */
6299 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6300 : 1) /* 0xA0..0xFF */
6302 : (font
->min_byte1
< 0x80
6303 ? (font
->max_byte1
< 0x80
6304 ? (font
->min_char_or_byte2
< 0x80
6305 ? (font
->max_char_or_byte2
< 0x80
6306 ? 0 /* 0x2020..0x7F7F */
6307 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6308 : 3) /* 0x20A0..0x7FFF */
6309 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6310 : (font
->min_char_or_byte2
< 0x80
6311 ? (font
->max_char_or_byte2
< 0x80
6312 ? 2 /* 0xA020..0xFF7F */
6313 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6314 : 1))); /* 0xA0A0..0xFFFF */
6317 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6318 fontp
->baseline_offset
6319 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6320 ? (long) value
: 0);
6321 fontp
->relative_compose
6322 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6323 ? (long) value
: 0);
6324 fontp
->default_ascent
6325 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6326 ? (long) value
: 0);
6328 fontp
->baseline_offset
= 0;
6329 fontp
->relative_compose
= 0;
6330 fontp
->default_ascent
= 0;
6333 /* Set global flag fonts_changed_p to non-zero if the font loaded
6334 has a character with a smaller width than any other character
6335 before, or if the font loaded has a smalle>r height than any
6336 other font loaded before. If this happens, it will make a
6337 glyph matrix reallocation necessary. */
6338 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
6345 /* Return a pointer to struct font_info of a font named FONTNAME for
6346 frame F. If no such font is loaded, return NULL. */
6349 x_query_font (f
, fontname
)
6351 register char *fontname
;
6353 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6356 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6357 if (dpyinfo
->font_table
[i
].name
6358 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
6359 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
6360 return (dpyinfo
->font_table
+ i
);
6365 /* Find a CCL program for a font specified by FONTP, and set the member
6366 `encoder' of the structure. */
6369 x_find_ccl_program (fontp
)
6370 struct font_info
*fontp
;
6372 Lisp_Object list
, elt
;
6374 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
6378 && STRINGP (XCAR (elt
))
6379 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
6385 struct ccl_program
*ccl
6386 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
6388 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
6391 fontp
->font_encoder
= ccl
;
6397 /* The Mac Event loop code */
6401 #include <Quickdraw.h>
6402 #include <Balloons.h>
6403 #include <Devices.h>
6405 #include <Gestalt.h>
6407 #include <Processes.h>
6409 #include <ToolUtils.h>
6410 #include <TextUtils.h>
6411 #include <Dialogs.h>
6414 #include <TextEncodingConverter.h>
6415 #include <Resources.h>
6420 #endif /* ! MAC_OSX */
6425 #define WINDOW_RESOURCE 128
6426 #define TERM_WINDOW_RESOURCE 129
6428 #define DEFAULT_NUM_COLS 80
6430 #define MIN_DOC_SIZE 64
6431 #define MAX_DOC_SIZE 32767
6433 /* sleep time for WaitNextEvent */
6434 #define WNE_SLEEP_AT_SUSPEND 10
6435 #define WNE_SLEEP_AT_RESUME 1
6437 /* true when cannot handle any Mac OS events */
6438 static int handling_window_update
= 0;
6440 /* the flag appl_is_suspended is used both for determining the sleep
6441 time to be passed to WaitNextEvent and whether the cursor should be
6442 drawn when updating the display. The cursor is turned off when
6443 Emacs is suspended. Redrawing it is unnecessary and what needs to
6444 be done depends on whether the cursor lies inside or outside the
6445 redraw region. So we might as well skip drawing it when Emacs is
6447 static Boolean app_is_suspended
= false;
6448 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
6450 #define EXTRA_STACK_ALLOC (256 * 1024)
6452 #define ARGV_STRING_LIST_ID 129
6453 #define ABOUT_ALERT_ID 128
6454 #define RAM_TOO_LARGE_ALERT_ID 129
6456 Boolean terminate_flag
= false;
6458 /* True if using command key as meta key. */
6459 Lisp_Object Vmac_command_key_is_meta
;
6461 /* True if the ctrl and meta keys should be reversed. */
6462 Lisp_Object Vmac_reverse_ctrl_meta
;
6464 #if USE_CARBON_EVENTS
6465 /* True if the mouse wheel button (i.e. button 4) should map to
6466 mouse-2, instead of mouse-3. */
6467 Lisp_Object Vmac_wheel_button_is_mouse_2
;
6469 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
6470 for processing before Emacs sees it. */
6471 Lisp_Object Vmac_pass_command_to_system
;
6473 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
6474 for processing before Emacs sees it. */
6475 Lisp_Object Vmac_pass_control_to_system
;
6478 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
6479 to this text encoding */
6480 int mac_keyboard_text_encoding
;
6481 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
6483 /* Set in term/mac-win.el to indicate that event loop can now generate
6484 drag and drop events. */
6485 Lisp_Object Qmac_ready_for_drag_n_drop
;
6487 Lisp_Object drag_and_drop_file_list
;
6489 Point saved_menu_event_location
;
6492 static void init_required_apple_events (void);
6494 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
6496 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
6497 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
6498 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
6501 static OSErr
init_mac_drag_n_drop ();
6502 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
6504 #if USE_CARBON_EVENTS
6505 /* Preliminary Support for the OSX Services Menu */
6506 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
6507 static void init_service_handler ();
6510 extern void init_emacs_passwd_dir ();
6511 extern int emacs_main (int, char **, char **);
6512 extern void check_alarm ();
6514 extern void initialize_applescript();
6515 extern void terminate_applescript();
6518 #if USE_CARBON_EVENTS
6519 mac_to_emacs_modifiers (UInt32 mods
)
6521 mac_to_emacs_modifiers (EventModifiers mods
)
6524 unsigned int result
= 0;
6525 if (mods
& macShiftKey
)
6526 result
|= shift_modifier
;
6527 if (mods
& macCtrlKey
)
6528 result
|= ctrl_modifier
;
6529 if (mods
& macMetaKey
)
6530 result
|= meta_modifier
;
6531 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
6532 result
|= alt_modifier
;
6536 #if USE_CARBON_EVENTS
6537 /* Obtains the event modifiers from the event ref and then calls
6538 mac_to_emacs_modifiers. */
6540 mac_event_to_emacs_modifiers (EventRef eventRef
)
6543 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
6544 sizeof (UInt32
), NULL
, &mods
);
6545 return mac_to_emacs_modifiers (mods
);
6548 /* Given an event ref, return the code to use for the mouse button
6549 code in the emacs input_event. */
6551 mac_get_mouse_btn (EventRef ref
)
6553 EventMouseButton result
= kEventMouseButtonPrimary
;
6554 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
6555 sizeof (EventMouseButton
), NULL
, &result
);
6558 case kEventMouseButtonPrimary
:
6560 case kEventMouseButtonSecondary
:
6561 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
6562 case kEventMouseButtonTertiary
:
6563 case 4: /* 4 is the number for the mouse wheel button */
6564 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
6570 /* Normally, ConvertEventRefToEventRecord will correctly handle all
6571 events. However the click of the mouse wheel is not converted to a
6572 mouseDown or mouseUp event. This calls ConvertEventRef, but then
6573 checks to see if it is a mouse up or down carbon event that has not
6574 been converted, and if so, converts it by hand (to be picked up in
6575 the XTread_socket loop). */
6576 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
6578 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
6579 /* Do special case for mouse wheel button. */
6580 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
6582 UInt32 kind
= GetEventKind (eventRef
);
6583 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
6585 eventRec
->what
= mouseDown
;
6588 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
6590 eventRec
->what
= mouseUp
;
6595 /* Need where and when. */
6597 GetEventParameter (eventRef
, kEventParamMouseLocation
,
6598 typeQDPoint
, NULL
, sizeof (Point
),
6599 NULL
, &eventRec
->where
);
6600 /* Use two step process because new event modifiers are
6601 32-bit and old are 16-bit. Currently, only loss is
6603 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
6604 typeUInt32
, NULL
, sizeof (UInt32
),
6606 eventRec
->modifiers
= mods
;
6608 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
6619 Handle menubar_handle
;
6620 MenuHandle menu_handle
;
6622 menubar_handle
= GetNewMBar (128);
6623 if(menubar_handle
== NULL
)
6625 SetMenuBar (menubar_handle
);
6628 menu_handle
= GetMenuHandle (M_APPLE
);
6629 if(menu_handle
!= NULL
)
6630 AppendResMenu (menu_handle
,'DRVR');
6637 do_init_managers (void)
6639 #if !TARGET_API_MAC_CARBON
6640 InitGraf (&qd
.thePort
);
6642 FlushEvents (everyEvent
, 0);
6647 #endif /* !TARGET_API_MAC_CARBON */
6650 #if !TARGET_API_MAC_CARBON
6651 /* set up some extra stack space for use by emacs */
6652 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
6654 /* MaxApplZone must be called for AppleScript to execute more
6655 complicated scripts */
6658 #endif /* !TARGET_API_MAC_CARBON */
6662 do_check_ram_size (void)
6664 SInt32 physical_ram_size
, logical_ram_size
;
6666 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
6667 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
6668 || physical_ram_size
> (1 << VALBITS
)
6669 || logical_ram_size
> (1 << VALBITS
))
6671 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
6677 do_window_update (WindowPtr win
)
6679 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (win
);
6680 struct frame
*f
= mwp
->mFP
;
6684 if (f
->async_visible
== 0)
6686 f
->async_visible
= 1;
6687 f
->async_iconified
= 0;
6688 SET_FRAME_GARBAGED (f
);
6690 /* An update event is equivalent to MapNotify on X, so report
6691 visibility changes properly. */
6692 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6693 /* Force a redisplay sooner or later to update the
6694 frame titles in case this is the second frame. */
6695 record_asynch_buffer_change ();
6700 handling_window_update
= 1;
6702 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
6704 expose_frame (f
, 0, 0, 0, 0);
6706 handling_window_update
= 0;
6713 is_emacs_window (WindowPtr win
)
6715 Lisp_Object tail
, frame
;
6720 FOR_EACH_FRAME (tail
, frame
)
6721 if (FRAME_MAC_P (XFRAME (frame
)))
6722 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
6729 do_window_activate (WindowPtr win
)
6734 if (is_emacs_window (win
))
6736 mwp
= (mac_output
*) GetWRefCon (win
);
6741 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
6742 activate_scroll_bars (f
);
6748 do_window_deactivate (WindowPtr win
)
6753 if (is_emacs_window (win
))
6755 mwp
= (mac_output
*) GetWRefCon (win
);
6758 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
6760 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
6761 deactivate_scroll_bars (f
);
6774 if (is_emacs_window (wp
))
6776 mwp
= (mac_output
*) GetWRefCon (wp
);
6781 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
6782 activate_scroll_bars (f
);
6786 app_is_suspended
= false;
6787 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
6798 if (is_emacs_window (wp
))
6800 mwp
= (mac_output
*) GetWRefCon (wp
);
6803 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
6805 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
6806 deactivate_scroll_bars (f
);
6810 app_is_suspended
= true;
6811 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
6816 do_mouse_moved (Point mouse_pos
)
6818 WindowPtr wp
= FrontWindow ();
6821 if (is_emacs_window (wp
))
6823 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
6825 #if TARGET_API_MAC_CARBON
6826 SetPort (GetWindowPort (wp
));
6831 GlobalToLocal (&mouse_pos
);
6833 note_mouse_movement (f
, &mouse_pos
);
6839 do_os_event (EventRecord
*erp
)
6841 switch((erp
->message
>> 24) & 0x000000FF)
6843 case suspendResumeMessage
:
6844 if((erp
->message
& resumeFlag
) == 1)
6850 case mouseMovedMessage
:
6851 do_mouse_moved (erp
->where
);
6857 do_events (EventRecord
*erp
)
6862 do_window_update ((WindowPtr
) erp
->message
);
6870 if ((erp
->modifiers
& activeFlag
) != 0)
6871 do_window_activate ((WindowPtr
) erp
->message
);
6873 do_window_deactivate ((WindowPtr
) erp
->message
);
6879 do_apple_menu (SInt16 menu_item
)
6881 #if !TARGET_API_MAC_CARBON
6883 SInt16 da_driver_refnum
;
6885 if (menu_item
== I_ABOUT
)
6886 NoteAlert (ABOUT_ALERT_ID
, NULL
);
6889 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
6890 da_driver_refnum
= OpenDeskAcc (item_name
);
6892 #endif /* !TARGET_API_MAC_CARBON */
6896 do_menu_choice (SInt32 menu_choice
)
6898 SInt16 menu_id
, menu_item
;
6900 menu_id
= HiWord (menu_choice
);
6901 menu_item
= LoWord (menu_choice
);
6909 do_apple_menu (menu_item
);
6914 WindowPtr wp
= FrontWindow ();
6915 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
6916 MenuHandle menu
= GetMenuHandle (menu_id
);
6921 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
6922 menubar_selection_callback (f
, refcon
);
6931 /* Handle drags in size box. Based on code contributed by Ben
6932 Mesander and IM - Window Manager A. */
6935 do_grow_window (WindowPtr w
, EventRecord
*e
)
6940 mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
6941 struct frame
*f
= mwp
->mFP
;
6943 SetRect(&limit_rect
, MIN_DOC_SIZE
, MIN_DOC_SIZE
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
6945 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
6947 /* see if it really changed size */
6950 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, HiWord (grow_size
));
6951 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, LoWord (grow_size
));
6953 x_set_window_size (f
, 0, columns
, rows
);
6958 /* Handle clicks in zoom box. Calculation of "standard state" based
6959 on code in IM - Window Manager A and code contributed by Ben
6960 Mesander. The standard state of an Emacs window is 80-characters
6961 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
6964 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
6967 Rect zoom_rect
, port_rect
;
6969 int w_title_height
, columns
, rows
, width
, height
, dummy
, x
, y
;
6970 mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
6971 struct frame
*f
= mwp
->mFP
;
6973 GetPort (&save_port
);
6975 #if TARGET_API_MAC_CARBON
6976 SetPort (GetWindowPort (w
));
6981 /* Clear window to avoid flicker. */
6982 #if TARGET_API_MAC_CARBON
6987 GetWindowPortBounds (w
, &r
);
6990 if (zoom_in_or_out
== inZoomOut
)
6992 /* calculate height of window's title bar (hard card it for now). */
6993 w_title_height
= 20 + GetMBarHeight ();
6995 /* get maximum height of window into zoom_rect.bottom -
6997 GetQDGlobalsScreenBits (&bm
);
6998 zoom_rect
= bm
.bounds
;
6999 zoom_rect
.top
+= w_title_height
;
7000 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
7002 zoom_rect
.right
= zoom_rect
.left
7003 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7005 SetWindowStandardState (w
, &zoom_rect
);
7008 #else /* not TARGET_API_MAC_CARBON */
7009 EraseRect (&(w
->portRect
));
7010 if (zoom_in_or_out
== inZoomOut
)
7012 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
7013 LocalToGlobal (&top_left
);
7015 /* calculate height of window's title bar */
7016 w_title_height
= top_left
.v
- 1
7017 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
7019 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7020 zoom_rect
= qd
.screenBits
.bounds
;
7021 zoom_rect
.top
+= w_title_height
;
7022 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
7024 zoom_rect
.right
= zoom_rect
.left
7025 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7027 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
7030 #endif /* not TARGET_API_MAC_CARBON */
7032 ZoomWindow (w
, zoom_in_or_out
, w
== FrontWindow ());
7034 /* retrieve window size and update application values */
7035 #if TARGET_API_MAC_CARBON
7036 GetWindowPortBounds (w
, &port_rect
);
7038 port_rect
= w
->portRect
;
7040 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, port_rect
.bottom
- port_rect
.top
);
7041 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, port_rect
.right
- port_rect
.left
);
7042 x_set_window_size (mwp
->mFP
, 0, columns
, rows
);
7044 SetPort (save_port
);
7047 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7049 init_mac_drag_n_drop ()
7051 OSErr result
= InstallReceiveHandler (mac_do_receive_drag
, 0L, NULL
);
7055 /* Intialize AppleEvent dispatcher table for the required events. */
7057 init_required_apple_events ()
7062 /* Make sure we have apple events before starting. */
7063 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
7067 if (!(result
& (1 << gestaltAppleEventsPresent
)))
7070 #if TARGET_API_MAC_CARBON
7071 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7072 NewAEEventHandlerUPP
7073 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7076 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7077 NewAEEventHandlerProc
7078 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7084 #if TARGET_API_MAC_CARBON
7085 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7086 NewAEEventHandlerUPP
7087 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7090 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7091 NewAEEventHandlerProc
7092 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7098 #if TARGET_API_MAC_CARBON
7099 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7100 NewAEEventHandlerUPP
7101 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7104 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7105 NewAEEventHandlerProc
7106 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7112 #if TARGET_API_MAC_CARBON
7113 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7114 NewAEEventHandlerUPP
7115 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7118 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7119 NewAEEventHandlerProc
7120 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7127 #if USE_CARBON_EVENTS
7130 init_service_handler ()
7132 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
7133 {kEventClassService
, kEventServiceCopy
},
7134 {kEventClassService
, kEventServicePaste
}};
7135 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
7136 3, specs
, NULL
, NULL
);
7140 MAC_TODO: Check to see if this is called by AEProcessDesc...
7143 mac_handle_service_event (EventHandlerCallRef callRef
,
7144 EventRef event
, void *data
)
7146 OSStatus err
= noErr
;
7147 switch (GetEventKind (event
))
7149 case kEventServiceGetTypes
:
7151 CFMutableArrayRef copyTypes
, pasteTypes
;
7153 Boolean selection
= true;
7155 GetEventParameter(event, kEventParamServicePasteTypes,
7156 typeCFMutableArrayRef, NULL,
7157 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7159 GetEventParameter(event
, kEventParamServiceCopyTypes
,
7160 typeCFMutableArrayRef
, NULL
,
7161 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
7162 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
7164 CFArrayAppendValue (copyTypes
, type
);
7165 //CFArrayAppendValue (pasteTypes, type);
7169 case kEventServiceCopy
:
7171 ScrapRef currentScrap
, specificScrap
;
7175 GetCurrentScrap (¤tScrap
);
7177 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
7180 void *buffer
= xmalloc (byteCount
);
7183 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
7184 sizeof (ScrapRef
), NULL
, &specificScrap
);
7186 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
7187 &byteCount
, buffer
);
7189 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
7190 kScrapFlavorMaskNone
, byteCount
, buffer
);
7196 case kEventServicePaste
:
7199 // Get the current location
7201 ScrapRef specificScrap;
7202 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7203 sizeof(ScrapRef), NULL, &specificScrap);
7204 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7206 void * buffer = xmalloc(byteCount);
7207 if (buffer != NULL ) {
7208 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7209 &byteCount, buffer);
7211 // Actually place in the buffer
7213 // Get the current "selection" string here
7226 /* Open Application Apple Event */
7228 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
7234 /* Defined in mac.c. */
7236 path_from_vol_dir_name (char *, int, short, long, char *);
7239 /* Called when we receive an AppleEvent with an ID of
7240 "kAEOpenDocuments". This routine gets the direct parameter,
7241 extracts the FSSpecs in it, and puts their names on a list. */
7243 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
7248 DescType actual_type
;
7251 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
7253 goto descriptor_error_exit
;
7255 /* Check to see that we got all of the required parameters from the
7256 event descriptor. For an 'odoc' event this should just be the
7258 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
7259 &actual_type
, (Ptr
) &keyword
,
7260 sizeof (keyword
), &actual_size
);
7261 /* No error means that we found some unused parameters.
7262 errAEDescNotFound means that there are no more parameters. If we
7263 get an error code other than that, flag it. */
7264 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
7266 err
= errAEEventNotHandled
;
7271 /* Got all the parameters we need. Now, go through the direct
7272 object list and parse it up. */
7274 long num_files_to_open
;
7276 err
= AECountItems (&the_desc
, &num_files_to_open
);
7281 /* AE file list is one based so just use that for indexing here. */
7282 for (i
= 1; (err
== noErr
) && (i
<= num_files_to_open
); i
++)
7285 Str255 path_name
, unix_path_name
;
7290 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
7291 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
7292 if (err
!= noErr
) break;
7295 err
= FSpMakeFSRef (&fs
, &fref
);
7296 if (err
!= noErr
) break;
7298 if (FSRefMakePath (&fref
, unix_path_name
, 255) == noErr
)
7300 if (path_from_vol_dir_name (path_name
, 255, fs
.vRefNum
, fs
.parID
,
7302 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
7304 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
7305 drag_and_drop_file_list
);
7311 /* Nuke the coerced file list in any case */
7312 err2
= AEDisposeDesc(&the_desc
);
7314 descriptor_error_exit
:
7315 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
7321 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
7322 DragReference theDrag
)
7326 FlavorFlags theFlags
;
7329 ItemReference theItem
;
7332 Size size
= sizeof (HFSFlavor
);
7334 drag_and_drop_file_list
= Qnil
;
7335 GetDragMouse (theDrag
, &mouse
, 0L);
7336 CountDragItems (theDrag
, &items
);
7337 for (index
= 1; index
<= items
; index
++)
7339 /* Only handle file references. */
7340 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
7341 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
7342 if (result
== noErr
)
7349 Str255 unix_path_name
;
7350 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
7352 /* Use Carbon routines, otherwise it converts the file name
7353 to /Macintosh HD/..., which is not correct. */
7354 FSpMakeFSRef (&data
.fileSpec
, &fref
);
7355 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
7357 if (path_from_vol_dir_name (path_name
, 255, data
.fileSpec
.vRefNum
,
7358 data
.fileSpec
.parID
, data
.fileSpec
.name
) &&
7359 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
7361 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
7362 drag_and_drop_file_list
);
7367 /* If there are items in the list, construct an event and post it to
7368 the queue like an interrupt using kbd_buffer_store_event. */
7369 if (!NILP (drag_and_drop_file_list
))
7371 struct input_event event
;
7373 struct frame
*f
= ((mac_output
*) GetWRefCon(window
))->mFP
;
7374 SetPort (GetWindowPort (window
));
7375 GlobalToLocal (&mouse
);
7377 event
.kind
= DRAG_N_DROP_EVENT
;
7379 event
.modifiers
= 0;
7380 event
.timestamp
= TickCount () * (1000 / 60);
7381 XSETINT (event
.x
, mouse
.h
);
7382 XSETINT (event
.y
, mouse
.v
);
7383 XSETFRAME (frame
, f
);
7384 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
7386 /* Post to the interrupt queue */
7387 kbd_buffer_store_event (&event
);
7388 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
7390 ProcessSerialNumber psn
;
7391 GetCurrentProcess (&psn
);
7392 SetFrontProcess (&psn
);
7398 /* Print Document Apple Event */
7400 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
7402 return errAEEventNotHandled
;
7407 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
7409 /* FixMe: Do we need an unwind-protect or something here? And what
7410 do we do about unsaved files. Currently just forces quit rather
7411 than doing recursive callback to get user input. */
7413 terminate_flag
= true;
7415 /* Fkill_emacs doesn't return. We have to return. (TI) */
7422 profiler_exit_proc ()
7424 ProfilerDump ("\pEmacs.prof");
7429 /* These few functions implement Emacs as a normal Mac application
7430 (almost): set up the heap and the Toolbox, handle necessary
7431 system events plus a few simple menu events. They also set up
7432 Emacs's access to functions defined in the rest of this file.
7433 Emacs uses function hooks to perform all its terminal I/O. A
7434 complete list of these functions appear in termhooks.h. For what
7435 they do, read the comments there and see also w32term.c and
7436 xterm.c. What's noticeably missing here is the event loop, which
7437 is normally present in most Mac application. After performing the
7438 necessary Mac initializations, main passes off control to
7439 emacs_main (corresponding to main in emacs.c). Emacs_main calls
7440 mac_read_socket (defined further below) to read input. This is
7441 where WaitNextEvent is called to process Mac events. This is also
7442 where check_alarm in sysdep.c is called to simulate alarm signals.
7443 This makes the cursor jump back to its correct position after
7444 briefly jumping to that of the matching parenthesis, print useful
7445 hints and prompts in the minibuffer after the user stops typing for
7448 #if !TARGET_API_MAC_CARBON
7453 #if __profile__ /* is the profiler on? */
7454 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
7459 /* set creator and type for files created by MSL */
7464 do_init_managers ();
7468 do_check_ram_size ();
7470 init_emacs_passwd_dir ();
7474 initialize_applescript ();
7476 init_required_apple_events ();
7482 /* set up argv array from STR# resource */
7483 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
7487 /* free up AppleScript resources on exit */
7488 atexit (terminate_applescript
);
7490 #if __profile__ /* is the profiler on? */
7491 atexit (profiler_exit_proc
);
7494 /* 3rd param "envp" never used in emacs_main */
7495 (void) emacs_main (argc
, argv
, 0);
7498 /* Never reached - real exit in Fkill_emacs */
7503 /* Table for translating Mac keycode to X keysym values. Contributed
7504 by Sudhir Shenoy. */
7505 static unsigned char keycode_to_xkeysym_table
[] = {
7506 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7507 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7508 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7510 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
7511 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
7512 /*0x38*/ 0, 0, 0, 0,
7513 /*0x3C*/ 0, 0, 0, 0,
7515 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
7516 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
7517 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
7518 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
7520 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
7521 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
7522 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
7523 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
7525 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
7526 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
7527 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
7528 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
7530 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
7531 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
7532 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
7533 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
7537 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
7539 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
7540 return *xKeySym
!= 0;
7543 /* Emacs calls this whenever it wants to read an input event from the
7546 XTread_socket (int sd
, struct input_event
*bufp
, int numchars
, int expected
)
7549 #if USE_CARBON_EVENTS
7552 EventMouseButton mouseBtn
;
7556 EventMask event_mask
;
7559 if (interrupt_input_blocked
)
7561 interrupt_input_pending
= 1;
7566 interrupt_input_pending
= 0;
7569 /* So people can tell when we have read the available input. */
7570 input_signal_count
++;
7575 /* Don't poll for events to process (specifically updateEvt) if
7576 window update currently already in progress. A call to redisplay
7577 (in do_window_update) can be preempted by another call to
7578 redisplay, causing blank regions to be left on the screen and the
7579 cursor to be left at strange places. */
7580 if (handling_window_update
)
7587 Fkill_emacs (make_number (1));
7589 /* It is necessary to set this (additional) argument slot of an
7590 event to nil because keyboard.c protects incompletely processed
7591 event from being garbage collected by placing them in the
7592 kbd_buffer_gcpro vector. */
7595 event_mask
= everyEvent
;
7596 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
7597 event_mask
-= highLevelEventMask
;
7599 #if USE_CARBON_EVENTS
7600 rneResult
= ReceiveNextEvent (0, NULL
,
7602 ? TicksToEventTime (app_sleep_time
)
7604 kEventRemoveFromQueue
, &eventRef
);
7607 /* Handle new events */
7608 if (!mac_convert_event_ref (eventRef
, &er
))
7609 switch (GetEventClass (eventRef
))
7611 case kEventClassMouse
:
7612 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
7616 WindowPtr window_ptr
= FrontNonFloatingWindow ();
7617 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (window_ptr
);
7618 if (!IsValidWindowPtr (window_ptr
))
7625 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
7626 typeSInt32
, NULL
, sizeof (SInt32
),
7628 GetEventParameter(eventRef
, kEventParamMouseLocation
,
7629 typeQDPoint
, NULL
, sizeof (Point
),
7631 bufp
->kind
= WHEEL_EVENT
;
7633 bufp
->modifiers
= (mac_event_to_emacs_modifiers(eventRef
)
7634 | ((delta
< 0) ? down_modifier
7636 SetPort (GetWindowPort (window_ptr
));
7637 GlobalToLocal (&point
);
7638 XSETINT (bufp
->x
, point
.h
);
7639 XSETINT (bufp
->y
, point
.v
);
7640 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
7641 bufp
->timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
7645 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
7649 /* Send the event to the appropriate receiver. */
7650 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
7654 if (WaitNextEvent (event_mask
, &er
, (expected
? app_sleep_time
: 0L), NULL
))
7655 #endif /* USE_CARBON_EVENTS */
7661 WindowPtr window_ptr
= FrontWindow ();
7664 #if USE_CARBON_EVENTS
7665 /* This is needed to send mouse events like aqua window buttons
7666 to the correct handler. */
7667 if (eventNotHandledErr
!= SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ())) {
7671 if (!is_emacs_window(window_ptr
))
7675 if (mouse_tracking_in_progress
== mouse_tracking_scroll_bar
7676 && er
.what
== mouseUp
)
7678 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (window_ptr
);
7679 Point mouse_loc
= er
.where
;
7681 /* Convert to local coordinates of new window. */
7682 #if TARGET_API_MAC_CARBON
7683 SetPort (GetWindowPort (window_ptr
));
7685 SetPort (window_ptr
);
7688 GlobalToLocal (&mouse_loc
);
7690 #if USE_CARBON_EVENTS
7691 bufp
->code
= mac_get_mouse_btn (eventRef
);
7693 bufp
->code
= 0; /* only one mouse button */
7695 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
7696 bufp
->frame_or_window
= tracked_scroll_bar
->window
;
7697 bufp
->part
= scroll_bar_handle
;
7698 #if USE_CARBON_EVENTS
7699 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
7701 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
7703 bufp
->modifiers
|= up_modifier
;
7704 bufp
->timestamp
= er
.when
* (1000 / 60);
7705 /* ticks to milliseconds */
7707 XSETINT (bufp
->x
, tracked_scroll_bar
->left
+ 2);
7708 XSETINT (bufp
->y
, mouse_loc
.v
- 24);
7709 tracked_scroll_bar
->dragging
= Qnil
;
7710 mouse_tracking_in_progress
= mouse_tracking_none
;
7711 tracked_scroll_bar
= NULL
;
7716 part_code
= FindWindow (er
.where
, &window_ptr
);
7721 if (er
.what
== mouseDown
)
7723 struct frame
*f
= ((mac_output
*)
7724 GetWRefCon (FrontWindow ()))->mFP
;
7725 saved_menu_event_location
= er
.where
;
7726 bufp
->kind
= MENU_BAR_ACTIVATE_EVENT
;
7727 XSETFRAME (bufp
->frame_or_window
, f
);
7733 if (window_ptr
!= FrontWindow ())
7734 SelectWindow (window_ptr
);
7737 SInt16 control_part_code
;
7739 struct mac_output
*mwp
= (mac_output
*)
7740 GetWRefCon (window_ptr
);
7741 Point mouse_loc
= er
.where
;
7743 /* convert to local coordinates of new window */
7744 #if TARGET_API_MAC_CARBON
7745 SetPort (GetWindowPort (window_ptr
));
7747 SetPort (window_ptr
);
7750 GlobalToLocal (&mouse_loc
);
7751 #if TARGET_API_MAC_CARBON
7752 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
7753 &control_part_code
);
7755 control_part_code
= FindControl (mouse_loc
, window_ptr
, &ch
);
7758 #if USE_CARBON_EVENTS
7759 bufp
->code
= mac_get_mouse_btn (eventRef
);
7761 bufp
->code
= 0; /* only one mouse button */
7763 XSETINT (bufp
->x
, mouse_loc
.h
);
7764 XSETINT (bufp
->y
, mouse_loc
.v
);
7765 bufp
->timestamp
= er
.when
* (1000 / 60);
7766 /* ticks to milliseconds */
7768 #if TARGET_API_MAC_CARBON
7771 if (control_part_code
!= 0)
7774 struct scroll_bar
*bar
= (struct scroll_bar
*)
7775 GetControlReference (ch
);
7776 x_scroll_bar_handle_click (bar
, control_part_code
, &er
,
7778 if (er
.what
== mouseDown
7779 && control_part_code
== kControlIndicatorPart
)
7781 mouse_tracking_in_progress
7782 = mouse_tracking_scroll_bar
;
7783 tracked_scroll_bar
= bar
;
7787 mouse_tracking_in_progress
= mouse_tracking_none
;
7788 tracked_scroll_bar
= NULL
;
7793 bufp
->kind
= MOUSE_CLICK_EVENT
;
7794 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
7795 if (er
.what
== mouseDown
)
7796 mouse_tracking_in_progress
7797 = mouse_tracking_mouse_movement
;
7799 mouse_tracking_in_progress
= mouse_tracking_none
;
7802 #if USE_CARBON_EVENTS
7803 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
7805 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
7811 bufp
->modifiers
|= down_modifier
;
7814 bufp
->modifiers
|= up_modifier
;
7823 #if TARGET_API_MAC_CARBON
7824 if (er
.what
== mouseDown
)
7828 GetQDGlobalsScreenBits (&bm
);
7829 DragWindow (window_ptr
, er
.where
, &bm
.bounds
);
7831 #else /* not TARGET_API_MAC_CARBON */
7832 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
7833 #endif /* not TARGET_API_MAC_CARBON */
7837 if (TrackGoAway (window_ptr
, er
.where
))
7839 bufp
->kind
= DELETE_WINDOW_EVENT
;
7840 XSETFRAME (bufp
->frame_or_window
,
7841 ((mac_output
*) GetWRefCon (window_ptr
))->mFP
);
7846 /* window resize handling added --ben */
7848 if (er
.what
== mouseDown
)
7850 do_grow_window(window_ptr
, &er
);
7854 /* window zoom handling added --ben */
7857 if (TrackBox (window_ptr
, er
.where
, part_code
))
7858 do_zoom_window (window_ptr
, part_code
);
7870 #if USE_CARBON_EVENTS
7871 if (eventNotHandledErr
== SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ()))
7879 int keycode
= (er
.message
& keyCodeMask
) >> 8;
7882 #if USE_CARBON_EVENTS
7883 /* When using Carbon Events, we need to pass raw keyboard events
7884 to the TSM ourselves. If TSM handles it, it will pass back
7885 noErr, otherwise it will pass back "eventNotHandledErr" and
7886 we can process it normally. */
7887 if ((!NILP (Vmac_pass_command_to_system
)
7888 || !(er
.modifiers
& cmdKey
))
7889 && (!NILP (Vmac_pass_control_to_system
)
7890 || !(er
.modifiers
& controlKey
)))
7893 err
= SendEventToEventTarget (eventRef
,
7894 GetEventDispatcherTarget ());
7895 if (err
!= eventNotHandledErr
)
7900 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
7909 if (keycode_to_xkeysym (keycode
, &xkeysym
))
7911 bufp
->code
= 0xff00 | xkeysym
;
7912 bufp
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
7916 if (er
.modifiers
& (controlKey
|
7917 (NILP (Vmac_command_key_is_meta
) ? optionKey
7920 /* This code comes from Keyboard Resource, Appendix
7921 C of IM - Text. This is necessary since shift is
7922 ignored in KCHR table translation when option or
7923 command is pressed. It also does not translate
7924 correctly control-shift chars like C-% so mask off
7926 int new_modifiers
= er
.modifiers
& 0xe600;
7927 /* mask off option and command */
7928 int new_keycode
= keycode
| new_modifiers
;
7929 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
7930 unsigned long some_state
= 0;
7931 bufp
->code
= KeyTranslate (kchr_ptr
, new_keycode
,
7932 &some_state
) & 0xff;
7935 bufp
->code
= er
.message
& charCodeMask
;
7936 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
7940 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
7941 convert non-ASCII characters typed at the Mac keyboard
7942 (presumed to be in the Mac Roman encoding) to iso-latin-1
7943 encoding before they are passed to Emacs. This enables the
7944 Mac keyboard to be used to enter non-ASCII iso-latin-1
7945 characters directly. */
7946 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
7947 && bufp
->kind
== ASCII_KEYSTROKE_EVENT
&& bufp
->code
>= 128)
7949 static TECObjectRef converter
= NULL
;
7950 OSStatus the_err
= noErr
;
7951 OSStatus convert_status
= noErr
;
7953 if (converter
== NULL
)
7955 the_err
= TECCreateConverter (&converter
,
7956 kTextEncodingMacRoman
,
7957 mac_keyboard_text_encoding
);
7958 current_mac_keyboard_text_encoding
7959 = mac_keyboard_text_encoding
;
7961 else if (mac_keyboard_text_encoding
7962 != current_mac_keyboard_text_encoding
)
7964 /* Free the converter for the current encoding before
7965 creating a new one. */
7966 TECDisposeConverter (converter
);
7967 the_err
= TECCreateConverter (&converter
,
7968 kTextEncodingMacRoman
,
7969 mac_keyboard_text_encoding
);
7970 current_mac_keyboard_text_encoding
7971 = mac_keyboard_text_encoding
;
7974 if (the_err
== noErr
)
7976 unsigned char ch
= bufp
->code
;
7977 ByteCount actual_input_length
, actual_output_length
;
7978 unsigned char outch
;
7980 convert_status
= TECConvertText (converter
, &ch
, 1,
7981 &actual_input_length
,
7983 &actual_output_length
);
7984 if (convert_status
== noErr
7985 && actual_input_length
== 1
7986 && actual_output_length
== 1)
7991 #if USE_CARBON_EVENTS
7992 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
7994 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
7999 = (mac_output
*) GetWRefCon (FrontNonFloatingWindow ());
8000 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
8003 bufp
->timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
8008 case kHighLevelEvent
:
8009 drag_and_drop_file_list
= Qnil
;
8011 AEProcessAppleEvent(&er
);
8013 /* Build a DRAG_N_DROP_EVENT type event as is done in
8014 constuct_drag_n_drop in w32term.c. */
8015 if (!NILP (drag_and_drop_file_list
))
8017 struct frame
*f
= NULL
;
8021 wp
= FrontNonFloatingWindow ();
8025 struct frame
*f
= XFRAME (XCAR (Vframe_list
));
8026 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
8027 wp
= FrontNonFloatingWindow ();
8030 if (wp
&& is_emacs_window(wp
))
8031 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
8033 bufp
->kind
= DRAG_N_DROP_EVENT
;
8035 bufp
->timestamp
= er
.when
* (1000 / 60);
8036 /* ticks to milliseconds */
8037 #if USE_CARBON_EVENTS
8038 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
8040 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
8043 XSETINT (bufp
->x
, 0);
8044 XSETINT (bufp
->y
, 0);
8046 XSETFRAME (frame
, f
);
8047 bufp
->frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8049 /* Regardless of whether Emacs was suspended or in the
8050 foreground, ask it to redraw its entire screen.
8051 Otherwise parts of the screen can be left in an
8052 inconsistent state. */
8054 #if TARGET_API_MAC_CARBON
8058 GetWindowPortBounds (wp
, &r
);
8059 InvalWindowRect (wp
, &r
);
8061 #else /* not TARGET_API_MAC_CARBON */
8062 InvalRect (&(wp
->portRect
));
8063 #endif /* not TARGET_API_MAC_CARBON */
8070 #if USE_CARBON_EVENTS
8071 ReleaseEvent (eventRef
);
8075 /* If the focus was just given to an autoraising frame,
8077 /* ??? This ought to be able to handle more than one such frame. */
8078 if (pending_autoraise_frame
)
8080 x_raise_frame (pending_autoraise_frame
);
8081 pending_autoraise_frame
= 0;
8084 #if !TARGET_API_MAC_CARBON
8085 check_alarm (); /* simulate the handling of a SIGALRM */
8089 static Point old_mouse_pos
= { -1, -1 };
8091 if (app_is_suspended
)
8093 old_mouse_pos
.h
= -1;
8094 old_mouse_pos
.v
= -1;
8102 struct scroll_bar
*sb
;
8104 wp
= FrontWindow ();
8105 if (is_emacs_window (wp
))
8107 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
8109 #if TARGET_API_MAC_CARBON
8110 SetPort (GetWindowPort (wp
));
8115 GetMouse (&mouse_pos
);
8117 if (!EqualPt (mouse_pos
, old_mouse_pos
))
8119 if (mouse_tracking_in_progress
== mouse_tracking_scroll_bar
8120 && tracked_scroll_bar
)
8121 x_scroll_bar_note_movement (tracked_scroll_bar
,
8123 - XINT (tracked_scroll_bar
->top
),
8124 TickCount() * (1000 / 60));
8126 note_mouse_movement (f
, &mouse_pos
);
8128 old_mouse_pos
= mouse_pos
;
8140 /* Need to override CodeWarrior's input function so no conversion is
8141 done on newlines Otherwise compiled functions in .elc files will be
8142 read incorrectly. Defined in ...:MSL C:MSL
8143 Common:Source:buffer_io.c. */
8146 __convert_to_newlines (unsigned char * p
, size_t * n
)
8152 __convert_from_newlines (unsigned char * p
, size_t * n
)
8159 /* Initialize the struct pointed to by MW to represent a new COLS x
8160 ROWS Macintosh window, using font with name FONTNAME and size
8163 NewMacWindow (FRAME_PTR fp
)
8166 #if TARGET_API_MAC_CARBON
8167 static int making_terminal_window
= 0;
8169 static int making_terminal_window
= 1;
8172 mwp
= fp
->output_data
.mac
;
8174 if (making_terminal_window
)
8176 if (!(mwp
->mWP
= GetNewCWindow (TERM_WINDOW_RESOURCE
, NULL
,
8179 making_terminal_window
= 0;
8182 if (!(mwp
->mWP
= GetNewCWindow (WINDOW_RESOURCE
, NULL
, (WindowPtr
) -1)))
8185 SetWRefCon (mwp
->mWP
, (long) mwp
);
8186 /* so that update events can find this mac_output struct */
8187 mwp
->mFP
= fp
; /* point back to emacs frame */
8189 #if TARGET_API_MAC_CARBON
8190 SetPort (GetWindowPort (mwp
->mWP
));
8197 SizeWindow (mwp
->mWP
, FRAME_PIXEL_WIDTH (fp
), FRAME_PIXEL_HEIGHT (fp
), false);
8198 ShowWindow (mwp
->mWP
);
8204 make_mac_frame (struct frame
*f
)
8206 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
8207 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
8209 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
8213 f
->output_data
.mac
->cursor_pixel
= 0;
8214 f
->output_data
.mac
->border_pixel
= 0x00ff00;
8215 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
8216 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
8218 FRAME_FONTSET (f
) = -1;
8219 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
8220 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
8221 f
->output_data
.mac
->explicit_parent
= 0;
8224 f
->border_width
= 0;
8226 f
->internal_border_width
= 0;
8228 f
->output_method
= output_mac
;
8233 f
->new_text_cols
= 0;
8234 f
->new_text_lines
= 0;
8238 make_mac_terminal_frame (struct frame
*f
)
8242 XSETFRAME (frame
, f
);
8244 f
->output_method
= output_mac
;
8245 f
->output_data
.mac
= (struct mac_output
*)
8246 xmalloc (sizeof (struct mac_output
));
8247 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
8248 FRAME_FONTSET (f
) = -1;
8249 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
8250 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
8252 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
8254 FRAME_COLS (f
) = 96;
8255 FRAME_LINES (f
) = 4;
8261 /* Need to be initialized for unshow_buffer in window.c. */
8262 selected_window
= f
->selected_window
;
8264 Fmodify_frame_parameters (frame
,
8265 Fcons (Fcons (Qfont
,
8266 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
8267 Fmodify_frame_parameters (frame
,
8268 Fcons (Fcons (Qforeground_color
,
8269 build_string ("black")), Qnil
));
8270 Fmodify_frame_parameters (frame
,
8271 Fcons (Fcons (Qbackground_color
,
8272 build_string ("white")), Qnil
));
8276 /***********************************************************************
8278 ***********************************************************************/
8280 int mac_initialized
= 0;
8283 mac_initialize_display_info ()
8285 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8286 GDHandle main_device_handle
;
8288 bzero (dpyinfo
, sizeof (*dpyinfo
));
8290 /* Put it on x_display_name_list. */
8291 x_display_name_list
= Fcons (Fcons (build_string ("Mac"), Qnil
),
8292 x_display_name_list
);
8293 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
8296 dpyinfo
->mac_id_name
8297 = (char *) xmalloc (SCHARS (Vinvocation_name
)
8298 + SCHARS (Vsystem_name
)
8300 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
8301 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
8303 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
8304 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
8307 main_device_handle
= LMGetMainDevice();
8309 dpyinfo
->reference_count
= 0;
8310 dpyinfo
->resx
= 75.0;
8311 dpyinfo
->resy
= 75.0;
8312 dpyinfo
->n_planes
= 1;
8313 dpyinfo
->n_cbits
= 16;
8314 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
8315 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
8316 dpyinfo
->grabbed
= 0;
8317 dpyinfo
->root_window
= NULL
;
8319 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8320 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8321 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
8322 dpyinfo
->mouse_face_window
= Qnil
;
8325 struct mac_display_info
*
8326 mac_term_init (display_name
, xrm_option
, resource_name
)
8327 Lisp_Object display_name
;
8329 char *resource_name
;
8331 struct mac_display_info
*dpyinfo
;
8332 GDHandle main_device_handle
;
8334 if (!mac_initialized
)
8337 mac_initialized
= 1;
8340 mac_initialize_display_info (display_name
);
8342 dpyinfo
= &one_mac_display_info
;
8344 main_device_handle
= LMGetMainDevice();
8346 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
8347 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
8356 extern int inhibit_window_system
;
8357 extern int noninteractive
;
8358 CFBundleRef appsBundle
;
8361 /* No need to test if already -nw*/
8362 if (inhibit_window_system
|| noninteractive
)
8365 appsBundle
= CFBundleGetMainBundle();
8366 if (appsBundle
!= NULL
)
8368 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
8369 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
8370 /* We found the bundle identifier, now we know we are valid. */
8377 /* MAC_TODO: Have this start the bundled executable */
8379 /* For now, prevent the fatal error by bringing it up in the terminal */
8380 inhibit_window_system
= 1;
8384 MakeMeTheFrontProcess ()
8386 ProcessSerialNumber psn
;
8389 err
= GetCurrentProcess (&psn
);
8391 (void) SetFrontProcess (&psn
);
8394 /***** Code to handle C-g testing *****/
8396 /* Contains the Mac modifier formed from quit_char */
8397 static mac_quit_char_modifiers
= 0;
8398 static mac_quit_char_keycode
;
8399 extern int quit_char
;
8402 mac_determine_quit_char_modifiers()
8404 /* Todo: Determine modifiers from quit_char. */
8405 UInt32 qc_modifiers
= ctrl_modifier
;
8408 mac_quit_char_modifiers
= 0;
8409 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
8410 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
8411 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
8412 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
8416 init_quit_char_handler ()
8418 /* TODO: Let this support keys other the 'g' */
8419 mac_quit_char_keycode
= 5;
8420 /* Look at <architecture/adb_kb_map.h> for details */
8421 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
8423 mac_determine_quit_char_modifiers();
8427 quit_char_comp (EventRef inEvent
, void *inCompData
)
8429 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
8431 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
8435 UInt32 keyModifiers
;
8436 GetEventParameter(inEvent
, kEventParamKeyCode
,
8437 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
8438 if (keyCode
!= mac_quit_char_keycode
)
8440 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
8441 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
8442 if (keyModifiers
!= mac_quit_char_modifiers
)
8449 mac_check_for_quit_char ()
8452 static EMACS_TIME last_check_time
= { 0, 0 };
8453 static EMACS_TIME one_second
= { 1, 0 };
8456 /* If windows are not initialized, return immediately (keep it bouncin'). */
8457 if (!mac_quit_char_modifiers
)
8460 /* Don't check if last check is less than a second ago. */
8461 EMACS_GET_TIME (now
);
8462 EMACS_SUB_TIME (t
, now
, last_check_time
);
8463 if (EMACS_TIME_LT (t
, one_second
))
8465 last_check_time
= now
;
8467 /* Redetermine modifiers because they are based on lisp variables */
8468 mac_determine_quit_char_modifiers ();
8470 /* Fill the queue with events */
8471 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
8472 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
8476 struct input_event e
;
8477 struct mac_output
*mwp
=
8478 (mac_output
*) GetWRefCon (FrontNonFloatingWindow ());
8479 /* Use an input_event to emulate what the interrupt handler does. */
8481 e
.kind
= ASCII_KEYSTROKE_EVENT
;
8485 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
8486 XSETFRAME (e
.frame_or_window
, mwp
->mFP
);
8487 /* Remove event from queue to prevent looping. */
8488 RemoveEventFromQueue (GetMainEventQueue (), event
);
8489 ReleaseEvent (event
);
8490 kbd_buffer_store_event (&e
);
8494 #endif /* MAC_OSX */
8496 /* Set up use of X before we make the first connection. */
8498 extern frame_parm_handler mac_frame_parm_handlers
[];
8500 static struct redisplay_interface x_redisplay_interface
=
8502 mac_frame_parm_handlers
,
8506 x_clear_end_of_line
,
8508 x_after_update_window_line
,
8509 x_update_window_begin
,
8510 x_update_window_end
,
8514 x_clear_window_mouse_face
,
8515 x_get_glyph_overhangs
,
8516 x_fix_overlapping_area
,
8517 x_draw_fringe_bitmap
,
8518 mac_per_char_metric
,
8520 NULL
, /* mac_compute_glyph_string_overhangs */
8521 x_draw_glyph_string
,
8522 mac_define_frame_cursor
,
8523 mac_clear_frame_area
,
8524 mac_draw_window_cursor
,
8525 mac_draw_vertical_window_border
,
8526 mac_shift_glyphs_for_insert
8532 rif
= &x_redisplay_interface
;
8534 clear_frame_hook
= x_clear_frame
;
8535 ins_del_lines_hook
= x_ins_del_lines
;
8536 delete_glyphs_hook
= x_delete_glyphs
;
8537 ring_bell_hook
= XTring_bell
;
8538 reset_terminal_modes_hook
= XTreset_terminal_modes
;
8539 set_terminal_modes_hook
= XTset_terminal_modes
;
8540 update_begin_hook
= x_update_begin
;
8541 update_end_hook
= x_update_end
;
8542 set_terminal_window_hook
= XTset_terminal_window
;
8543 read_socket_hook
= XTread_socket
;
8544 frame_up_to_date_hook
= XTframe_up_to_date
;
8545 mouse_position_hook
= XTmouse_position
;
8546 frame_rehighlight_hook
= XTframe_rehighlight
;
8547 frame_raise_lower_hook
= XTframe_raise_lower
;
8549 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
8550 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
8551 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
8552 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
8554 scroll_region_ok
= 1; /* we'll scroll partial frames */
8555 char_ins_del_ok
= 1;
8556 line_ins_del_ok
= 1; /* we'll just blt 'em */
8557 fast_clear_end_of_line
= 1; /* X does this well */
8558 memory_below_frame
= 0; /* we don't remember what scrolls
8563 last_tool_bar_item
= -1;
8564 any_help_event_p
= 0;
8566 /* Try to use interrupt input; if we can't, then start polling. */
8567 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
8569 #ifdef USE_X_TOOLKIT
8570 XtToolkitInitialize ();
8571 Xt_app_con
= XtCreateApplicationContext ();
8572 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
8574 /* Install an asynchronous timer that processes Xt timeout events
8575 every 0.1s. This is necessary because some widget sets use
8576 timeouts internally, for example the LessTif menu bar, or the
8577 Xaw3d scroll bar. When Xt timouts aren't processed, these
8578 widgets don't behave normally. */
8580 EMACS_TIME interval
;
8581 EMACS_SET_SECS_USECS (interval
, 0, 100000);
8582 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
8586 #if USE_TOOLKIT_SCROLL_BARS
8587 xaw3d_arrow_scroll
= False
;
8588 xaw3d_pick_top
= True
;
8592 /* Note that there is no real way portable across R3/R4 to get the
8593 original error handler. */
8594 XSetErrorHandler (x_error_handler
);
8595 XSetIOErrorHandler (x_io_error_quitter
);
8597 /* Disable Window Change signals; they are handled by X events. */
8599 signal (SIGWINCH
, SIG_DFL
);
8600 #endif /* ! defined (SIGWINCH) */
8602 signal (SIGPIPE
, x_connection_signal
);
8605 mac_initialize_display_info ();
8607 #if TARGET_API_MAC_CARBON
8608 init_required_apple_events ();
8610 init_mac_drag_n_drop ();
8612 #if USE_CARBON_EVENTS
8613 init_service_handler ();
8615 init_quit_char_handler ();
8618 DisableMenuCommand (NULL
, kHICommandQuit
);
8620 if (!inhibit_window_system
)
8621 MakeMeTheFrontProcess ();
8630 staticpro (&x_error_message_string
);
8631 x_error_message_string
= Qnil
;
8634 Fprovide (intern ("mac-carbon"), Qnil
);
8636 staticpro (&x_display_name_list
);
8637 x_display_name_list
= Qnil
;
8639 staticpro (&last_mouse_scroll_bar
);
8640 last_mouse_scroll_bar
= Qnil
;
8642 staticpro (&Qvendor_specific_keysyms
);
8643 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
8645 staticpro (&last_mouse_press_frame
);
8646 last_mouse_press_frame
= Qnil
;
8648 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
8649 staticpro (&Qmac_ready_for_drag_n_drop
);
8651 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
8652 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
8653 x_autoselect_window_p
= 0;
8655 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
8656 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
8657 Vx_toolkit_scroll_bars
= Qt
;
8659 DEFVAR_BOOL ("x-use-underline-position-properties",
8660 &x_use_underline_position_properties
,
8661 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
8662 nil means ignore them. If you encounter fonts with bogus
8663 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
8664 to 4.1, set this to nil. */);
8665 x_use_underline_position_properties
= 0;
8667 staticpro (&last_mouse_motion_frame
);
8668 last_mouse_motion_frame
= Qnil
;
8670 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
8671 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
8672 Otherwise the option key is used. */);
8673 Vmac_command_key_is_meta
= Qt
;
8675 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
8676 doc
: /* Non-nil means that the control and meta keys are reversed. This is
8677 useful for non-standard keyboard layouts. */);
8678 Vmac_reverse_ctrl_meta
= Qnil
;
8680 #if USE_CARBON_EVENTS
8681 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
8682 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
8683 the right click will be mouse-3.
8684 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
8685 Vmac_wheel_button_is_mouse_2
= Qt
;
8687 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
8688 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
8689 Toolbox for processing before Emacs sees it. */);
8690 Vmac_pass_command_to_system
= Qt
;
8692 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
8693 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
8694 Toolbox for processing before Emacs sees it. */);
8695 Vmac_pass_control_to_system
= Qt
;
8698 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
8699 doc
: /* One of the Text Encoding Base constant values defined in the
8700 Basic Text Constants section of Inside Macintosh - Text Encoding
8701 Conversion Manager. Its value determines the encoding characters
8702 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
8703 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
8704 its default value, no conversion takes place. If it is set to
8705 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
8706 characters typed on Mac keyboard are first converted into the
8707 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
8708 passed to Emacs. Together with Emacs's set-keyboard-coding-system
8709 command, this enables the Mac keyboard to be used to enter non-ASCII
8710 characters directly. */);
8711 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
8714 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
8715 (do not change this comment) */