1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002 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 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
113 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
114 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
115 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
116 #define macShiftKey (shiftKey)
117 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
118 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
120 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
124 extern Lisp_Object Qhelp_echo
;
126 /* Non-nil means Emacs uses toolkit scroll bars. */
128 Lisp_Object Vx_toolkit_scroll_bars
;
130 /* If a string, XTread_socket generates an event to display that string.
131 (The display is done in read_char.) */
133 static Lisp_Object help_echo
;
134 static Lisp_Object help_echo_window
;
135 static Lisp_Object help_echo_object
;
136 static int help_echo_pos
;
138 /* Temporary variable for XTread_socket. */
140 static Lisp_Object previous_help_echo
;
142 /* Non-zero means that a HELP_EVENT has been generated since Emacs
145 static int any_help_event_p
;
147 /* Non-zero means autoselect window with the mouse cursor. */
149 int x_autoselect_window_p
;
151 /* Non-zero means draw block and hollow cursor as wide as the glyph
152 under it. For example, if a block cursor is over a tab, it will be
153 drawn as wide as that tab on the display. */
155 int x_stretch_cursor_p
;
157 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
159 int x_use_underline_position_properties
;
161 /* This is a chain of structures for all the X displays currently in
164 struct x_display_info
*x_display_list
;
166 /* This is a list of cons cells, each of the form (NAME
167 . FONT-LIST-CACHE), one for each element of x_display_list and in
168 the same order. NAME is the name of the frame. FONT-LIST-CACHE
169 records previous values returned by x-list-fonts. */
171 Lisp_Object x_display_name_list
;
173 /* This is display since Mac does not support multiple ones. */
174 struct mac_display_info one_mac_display_info
;
176 /* Frame being updated by update_frame. This is declared in term.c.
177 This is set by update_begin and looked at by all the XT functions.
178 It is zero while not inside an update. In that case, the XT
179 functions assume that `selected_frame' is the frame to apply to. */
181 extern struct frame
*updating_frame
;
183 extern int waiting_for_input
;
185 /* This is a frame waiting to be auto-raised, within XTread_socket. */
187 struct frame
*pending_autoraise_frame
;
189 /* Nominal cursor position -- where to draw output.
190 HPOS and VPOS are window relative glyph matrix coordinates.
191 X and Y are window relative pixel coordinates. */
193 struct cursor_pos output_cursor
;
195 /* Non-zero means user is interacting with a toolkit scroll bar. */
197 static int toolkit_scroll_bar_interaction
;
201 Formerly, we used PointerMotionHintMask (in standard_event_mask)
202 so that we would have to call XQueryPointer after each MotionNotify
203 event to ask for another such event. However, this made mouse tracking
204 slow, and there was a bug that made it eventually stop.
206 Simply asking for MotionNotify all the time seems to work better.
208 In order to avoid asking for motion events and then throwing most
209 of them away or busy-polling the server for mouse positions, we ask
210 the server for pointer motion hints. This means that we get only
211 one event per group of mouse movements. "Groups" are delimited by
212 other kinds of events (focus changes and button clicks, for
213 example), or by XQueryPointer calls; when one of these happens, we
214 get another MotionNotify event the next time the mouse moves. This
215 is at least as efficient as getting motion events when mouse
216 tracking is on, and I suspect only negligibly worse when tracking
219 /* Where the mouse was last time we reported a mouse event. */
221 FRAME_PTR last_mouse_frame
;
222 static Rect last_mouse_glyph
;
223 static Lisp_Object last_mouse_press_frame
;
225 /* The scroll bar in which the last X motion event occurred.
227 If the last X motion event occurred in a scroll bar, we set this so
228 XTmouse_position can know whether to report a scroll bar motion or
231 If the last X motion event didn't occur in a scroll bar, we set
232 this to Qnil, to tell XTmouse_position to return an ordinary motion
235 static Lisp_Object last_mouse_scroll_bar
;
237 /* This is a hack. We would really prefer that XTmouse_position would
238 return the time associated with the position it returns, but there
239 doesn't seem to be any way to wrest the time-stamp from the server
240 along with the position query. So, we just keep track of the time
241 of the last movement we received, and return that in hopes that
242 it's somewhat accurate. */
244 static Time last_mouse_movement_time
;
246 enum mouse_tracking_type
{
248 mouse_tracking_mouse_movement
,
249 mouse_tracking_scroll_bar
252 enum mouse_tracking_type mouse_tracking_in_progress
= mouse_tracking_none
;
254 struct scroll_bar
*tracked_scroll_bar
= NULL
;
256 /* Incremented by XTread_socket whenever it really tries to read
260 static int volatile input_signal_count
;
262 static int input_signal_count
;
265 /* Used locally within XTread_socket. */
267 static int x_noop_count
;
269 /* Initial values of argv and argc. */
271 extern char **initial_argv
;
272 extern int initial_argc
;
274 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
276 /* Tells if a window manager is present or not. */
278 extern Lisp_Object Vx_no_window_manager
;
280 extern Lisp_Object Qface
, Qmouse_face
;
284 /* A mask of extra modifier bits to put into every keyboard char. */
286 extern int extra_keyboard_modifiers
;
288 static Lisp_Object Qvendor_specific_keysyms
;
291 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
294 extern Lisp_Object x_icon_type
P_ ((struct frame
*));
296 extern int inhibit_window_system
;
299 QDGlobals qd
; /* QuickDraw global information structure. */
303 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
304 struct mac_display_info
*mac_display_info_for_display (Display
*);
305 static void x_update_window_end
P_ ((struct window
*, int, int));
306 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
307 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
308 int *, int *, Lisp_Object
));
309 static int fast_find_string_pos
P_ ((struct window
*, int, Lisp_Object
,
310 int *, int *, int *, int *, int));
311 static void set_output_cursor
P_ ((struct cursor_pos
*));
312 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
313 int *, int *, int *, int));
314 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
315 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
316 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
317 static void x_handle_tool_bar_click
P_ ((struct frame
*, EventRecord
*));
318 static void show_mouse_face
P_ ((struct x_display_info
*,
319 enum draw_glyphs_face
));
320 static int cursor_in_mouse_face_p
P_ ((struct window
*));
321 static int clear_mouse_face
P_ ((struct mac_display_info
*));
322 static int x_io_error_quitter
P_ ((Display
*));
323 int x_catch_errors
P_ ((Display
*));
324 void x_uncatch_errors
P_ ((Display
*, int));
325 void x_lower_frame
P_ ((struct frame
*));
326 void x_scroll_bar_clear
P_ ((struct frame
*));
327 int x_had_errors_p
P_ ((Display
*));
328 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
329 void x_raise_frame
P_ ((struct frame
*));
330 void x_set_window_size
P_ ((struct frame
*, int, int, int));
331 void x_wm_set_window_state
P_ ((struct frame
*, int));
332 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
333 void mac_initialize
P_ ((void));
334 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
335 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
336 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
338 enum draw_glyphs_face
));
339 static void x_update_end
P_ ((struct frame
*));
340 static void XTframe_up_to_date
P_ ((struct frame
*));
341 static void XTreassert_line_highlight
P_ ((int, int));
342 static void x_change_line_highlight
P_ ((int, int, int, int));
343 static void XTset_terminal_modes
P_ ((void));
344 static void XTreset_terminal_modes
P_ ((void));
345 static void XTcursor_to
P_ ((int, int, int, int));
346 static void x_write_glyphs
P_ ((struct glyph
*, int));
347 static void x_clear_end_of_line
P_ ((int));
348 static void x_clear_frame
P_ ((void));
349 static void x_clear_cursor
P_ ((struct window
*));
350 static void frame_highlight
P_ ((struct frame
*));
351 static void frame_unhighlight
P_ ((struct frame
*));
352 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
353 static void XTframe_rehighlight
P_ ((struct frame
*));
354 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
355 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
356 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int));
357 static int x_intersect_rectangles
P_ ((Rect
*, Rect
*, Rect
*));
358 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
359 static int expose_window_tree
P_ ((struct window
*, Rect
*));
360 static void expose_overlaps
P_ ((struct window
*, struct glyph_row
*,
361 struct glyph_row
*));
362 static int expose_window
P_ ((struct window
*, Rect
*));
363 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
364 Rect
*, enum glyph_row_area
));
365 static int expose_line
P_ ((struct window
*, struct glyph_row
*,
367 void x_display_cursor (struct window
*, int, int, int, int, int);
368 void x_update_cursor
P_ ((struct frame
*, int));
369 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
370 static void x_update_window_cursor
P_ ((struct window
*, int));
371 static void x_erase_phys_cursor
P_ ((struct window
*));
372 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
373 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
375 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, Rect
*));
376 static void x_flush
P_ ((struct frame
*f
));
377 static void x_update_begin
P_ ((struct frame
*));
378 static void x_update_window_begin
P_ ((struct window
*));
379 static void x_draw_vertical_border
P_ ((struct window
*));
380 static void x_after_update_window_line
P_ ((struct glyph_row
*));
382 static void activate_scroll_bars (FRAME_PTR
);
383 static void deactivate_scroll_bars (FRAME_PTR
);
385 static int is_emacs_window (WindowPtr
);
387 extern int image_ascent (struct image
*, struct face
*);
388 void x_set_offset (struct frame
*, int, int, int);
389 int x_bitmap_icon (struct frame
*, Lisp_Object
);
390 void x_make_frame_visible (struct frame
*);
392 extern void window_scroll (Lisp_Object
, int, int, int);
394 /* Defined in macmenu.h. */
395 extern void menubar_selection_callback (FRAME_PTR
, int);
396 extern void set_frame_menubar (FRAME_PTR
, int, int);
398 /* X display function emulation */
401 XFreePixmap (display
, pixmap
)
405 PixMap
*p
= (PixMap
*) pixmap
;
412 /* Set foreground color for subsequent QuickDraw commands. Assume
413 graphic port has already been set. */
416 mac_set_forecolor (unsigned long color
)
420 fg_color
.red
= RED_FROM_ULONG (color
) * 256;
421 fg_color
.green
= GREEN_FROM_ULONG (color
) * 256;
422 fg_color
.blue
= BLUE_FROM_ULONG (color
) * 256;
424 RGBForeColor (&fg_color
);
428 /* Set background color for subsequent QuickDraw commands. Assume
429 graphic port has already been set. */
432 mac_set_backcolor (unsigned long color
)
436 bg_color
.red
= RED_FROM_ULONG (color
) * 256;
437 bg_color
.green
= GREEN_FROM_ULONG (color
) * 256;
438 bg_color
.blue
= BLUE_FROM_ULONG (color
) * 256;
440 RGBBackColor (&bg_color
);
443 /* Set foreground and background color for subsequent QuickDraw
444 commands. Assume that the graphic port has already been set. */
447 mac_set_colors (GC gc
)
449 mac_set_forecolor (gc
->foreground
);
450 mac_set_backcolor (gc
->background
);
453 /* Mac version of XDrawLine. */
456 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
462 #if TARGET_API_MAC_CARBON
463 SetPort (GetWindowPort (w
));
474 /* Mac version of XClearArea. */
477 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
481 unsigned int width
, height
;
484 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
488 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
489 xgc
.background
= mwp
->x_compatible
.background_pixel
;
491 #if TARGET_API_MAC_CARBON
492 SetPort (GetWindowPort (w
));
497 mac_set_colors (&xgc
);
498 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
503 /* Mac version of XClearWindow. */
506 XClearWindow (display
, w
)
510 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
513 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
514 xgc
.background
= mwp
->x_compatible
.background_pixel
;
516 #if TARGET_API_MAC_CARBON
517 SetPort (GetWindowPort (w
));
522 mac_set_colors (&xgc
);
524 #if TARGET_API_MAC_CARBON
528 GetWindowPortBounds (w
, &r
);
531 #else /* not TARGET_API_MAC_CARBON */
532 EraseRect (&(w
->portRect
));
533 #endif /* not TARGET_API_MAC_CARBON */
537 /* Mac replacement for XCopyArea. */
540 mac_draw_bitmap (display
, w
, gc
, x
, y
, bitmap
)
549 #if TARGET_API_MAC_CARBON
550 SetPort (GetWindowPort (w
));
556 SetRect (&r
, x
, y
, x
+ bitmap
->bounds
.right
, y
+ bitmap
->bounds
.bottom
);
558 #if TARGET_API_MAC_CARBON
562 LockPortBits (GetWindowPort (w
));
563 pmh
= GetPortPixMap (GetWindowPort (w
));
564 CopyBits (bitmap
, (BitMap
*) *pmh
, &(bitmap
->bounds
), &r
, srcCopy
, 0);
565 UnlockPortBits (GetWindowPort (w
));
567 #else /* not TARGET_API_MAC_CARBON */
568 CopyBits (bitmap
, &(w
->portBits
), &(bitmap
->bounds
), &r
, srcCopy
, 0);
569 #endif /* not TARGET_API_MAC_CARBON */
573 /* Mac replacement for XSetClipRectangles. */
576 mac_set_clip_rectangle (display
, w
, r
)
581 #if TARGET_API_MAC_CARBON
582 SetPort (GetWindowPort (w
));
591 /* Mac replacement for XSetClipMask. */
594 mac_reset_clipping (display
, w
)
600 #if TARGET_API_MAC_CARBON
601 SetPort (GetWindowPort (w
));
606 SetRect (&r
, -32767, -32767, 32767, 32767);
611 /* Mac replacement for XCreateBitmapFromBitmapData. */
614 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
619 int bytes_per_row
, i
, j
;
621 bitmap
->rowBytes
= (w
+ 15) / 16 * 2; /* must be on word boundary */
622 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
623 if (!bitmap
->baseAddr
)
626 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
627 for (i
= 0; i
< h
; i
++)
628 for (j
= 0; j
< w
; j
++)
629 if (BitTst (bits
, i
* w
+ j
))
630 BitSet (bitmap
->baseAddr
, i
* bitmap
->rowBytes
* 8 + j
);
632 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
637 mac_free_bitmap (bitmap
)
640 xfree (bitmap
->baseAddr
);
643 /* Mac replacement for XFillRectangle. */
646 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
651 unsigned int width
, height
;
655 #if TARGET_API_MAC_CARBON
656 SetPort (GetWindowPort (w
));
662 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
664 PaintRect (&r
); /* using foreground color of gc */
668 /* Mac replacement for XDrawRectangle: dest is a window. */
671 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
676 unsigned int width
, height
;
680 #if TARGET_API_MAC_CARBON
681 SetPort (GetWindowPort (w
));
687 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
689 FrameRect (&r
); /* using foreground color of gc */
693 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
696 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
701 unsigned int width
, height
;
703 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
706 #if TARGET_API_MAC_CARBON
707 SetPort (GetWindowPort (w
));
713 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
715 FrameRect (&r
); /* using foreground color of gc */
721 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
728 int nchars
, mode
, bytes_per_char
;
730 #if TARGET_API_MAC_CARBON
731 SetPort (GetWindowPort (w
));
738 TextFont (gc
->font
->mac_fontnum
);
739 TextSize (gc
->font
->mac_fontsize
);
740 TextFace (gc
->font
->mac_fontface
);
744 DrawText (buf
, 0, nchars
* bytes_per_char
);
748 /* Mac replacement for XDrawString. */
751 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
759 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
763 /* Mac replacement for XDrawString16. */
766 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
774 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
779 /* Mac replacement for XDrawImageString. */
782 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
790 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
794 /* Mac replacement for XDrawString16. */
797 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
805 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
810 /* Mac replacement for XCopyArea: dest must be window. */
813 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
820 unsigned int width
, height
;
825 #if TARGET_API_MAC_CARBON
826 SetPort (GetWindowPort (dest
));
833 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
834 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
836 #if TARGET_API_MAC_CARBON
840 LockPortBits (GetWindowPort (dest
));
841 pmh
= GetPortPixMap (GetWindowPort (dest
));
842 CopyBits ((BitMap
*) &src
, (BitMap
*) *pmh
, &src_r
, &dest_r
, srcCopy
, 0);
843 UnlockPortBits (GetWindowPort (dest
));
845 #else /* not TARGET_API_MAC_CARBON */
846 CopyBits ((BitMap
*) &src
, &(dest
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
847 #endif /* not TARGET_API_MAC_CARBON */
852 /* Convert a pair of local coordinates to global (screen) coordinates.
853 Assume graphic port has been properly set. */
855 local_to_global_coord (short *h
, short *v
)
869 /* Mac replacement for XCopyArea: used only for scrolling. */
872 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
877 unsigned int width
, height
;
880 #if TARGET_API_MAC_CARBON
881 Rect gw_r
, src_r
, dest_r
;
884 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
885 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
887 SetPort (GetWindowPort (w
));
889 ForeColor (blackColor
);
890 BackColor (whiteColor
);
892 LockPortBits (GetWindowPort (w
));
893 pmh
= GetPortPixMap (GetWindowPort (w
));
894 CopyBits ((BitMap
*) *pmh
, (BitMap
*) *pmh
, &src_r
, &dest_r
, srcCopy
, 0);
895 UnlockPortBits (GetWindowPort (w
));
898 #else /* not TARGET_API_MAC_CARBON */
906 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
907 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
910 /* Need to use global coordinates and screenBits since src and dest
911 areas overlap in general. */
912 local_to_global_coord (&src_r
.left
, &src_r
.top
);
913 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
914 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
915 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
917 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
919 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
920 color mapping in CopyBits. Otherwise, it will be slow. */
921 ForeColor (blackColor
);
922 BackColor (whiteColor
);
923 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
927 #endif /* not TARGET_API_MAC_CARBON */
931 /* Mac replacement for XCopyArea: dest must be Pixmap. */
934 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
941 unsigned int width
, height
;
945 int src_right
= ((PixMap
*) src
)->bounds
.right
;
946 int src_bottom
= ((PixMap
*) src
)->bounds
.bottom
;
947 int w
= src_right
- src_x
;
948 int h
= src_bottom
- src_y
;
952 SetRect (&src_r
, src_x
, src_y
, src_right
, src_bottom
);
953 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ w
, dest_y
+ h
);
955 CopyBits ((BitMap
*) &src
, (BitMap
*) &dest
, &src_r
, &dest_r
, srcCopy
, 0);
959 /* Mac replacement for XChangeGC. */
962 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
965 if (mask
& GCForeground
)
966 gc
->foreground
= xgcv
->foreground
;
967 if (mask
& GCBackground
)
968 gc
->background
= xgcv
->background
;
970 gc
->font
= xgcv
->font
;
974 /* Mac replacement for XCreateGC. */
977 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
980 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
981 bzero (gc
, sizeof (XGCValues
));
983 XChangeGC (ignore
, gc
, mask
, xgcv
);
989 /* Used in xfaces.c. */
992 XFreeGC (display
, gc
)
1000 /* Mac replacement for XGetGCValues. */
1003 XGetGCValues (void* ignore
, XGCValues
*gc
,
1004 unsigned long mask
, XGCValues
*xgcv
)
1006 XChangeGC (ignore
, xgcv
, mask
, gc
);
1010 /* Mac replacement for XSetForeground. */
1013 XSetForeground (display
, gc
, color
)
1016 unsigned long color
;
1018 gc
->foreground
= color
;
1022 /* Mac replacement for XSetFont. */
1025 XSetFont (display
, gc
, font
)
1035 XTextExtents16 (XFontStruct
*font
, XChar2b
*text
, int nchars
,
1036 int *direction
,int *font_ascent
,
1037 int *font_descent
, XCharStruct
*cs
)
1039 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1043 /* x_sync is a no-op on Mac. */
1051 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1052 Calls to XFlush should be unnecessary because the X output buffer
1053 is flushed automatically as needed by calls to XPending,
1054 XNextEvent, or XWindowEvent according to the XFlush man page.
1055 XTread_socket calls XPending. Removing XFlush improves
1058 #if TARGET_API_MAC_CARBON
1059 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1061 #define XFlush(DISPLAY) (void) 0
1064 /* Flush display of frame F, or of all frames if F is null. */
1070 #if TARGET_API_MAC_CARBON
1074 Lisp_Object rest
, frame
;
1075 FOR_EACH_FRAME (rest
, frame
)
1076 x_flush (XFRAME (frame
));
1078 else if (FRAME_X_P (f
))
1079 XFlush (FRAME_MAC_DISPLAY (f
));
1081 #endif /* TARGET_API_MAC_CARBON */
1086 /* Return the struct mac_display_info corresponding to DPY. There's
1089 struct mac_display_info
*
1090 mac_display_info_for_display (dpy
)
1093 return &one_mac_display_info
;
1098 /***********************************************************************
1099 Starting and ending an update
1100 ***********************************************************************/
1102 /* Start an update of frame F. This function is installed as a hook
1103 for update_begin, i.e. it is called when update_begin is called.
1104 This function is called prior to calls to x_update_window_begin for
1105 each window being updated. */
1111 /* Nothing to do. */
1115 /* Start update of window W. Set the global variable updated_window
1116 to the window being updated and set output_cursor to the cursor
1120 x_update_window_begin (w
)
1123 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1124 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1127 set_output_cursor (&w
->cursor
);
1131 if (f
== display_info
->mouse_face_mouse_frame
)
1133 /* Don't do highlighting for mouse motion during the update. */
1134 display_info
->mouse_face_defer
= 1;
1136 /* If F needs to be redrawn, simply forget about any prior mouse
1138 if (FRAME_GARBAGED_P (f
))
1139 display_info
->mouse_face_window
= Qnil
;
1141 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1142 their mouse_face_p flag set, which means that they are always
1143 unequal to rows in a desired matrix which never have that
1144 flag set. So, rows containing mouse-face glyphs are never
1145 scrolled, and we don't have to switch the mouse highlight off
1146 here to prevent it from being scrolled. */
1148 /* Can we tell that this update does not affect the window
1149 where the mouse highlight is? If so, no need to turn off.
1150 Likewise, don't do anything if the frame is garbaged;
1151 in that case, the frame's current matrix that we would use
1152 is all wrong, and we will redisplay that line anyway. */
1153 if (!NILP (display_info
->mouse_face_window
)
1154 && w
== XWINDOW (display_info
->mouse_face_window
))
1158 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1159 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1162 if (i
< w
->desired_matrix
->nrows
)
1163 clear_mouse_face (display_info
);
1172 /* Draw a vertical window border to the right of window W if W doesn't
1173 have vertical scroll bars. */
1176 x_draw_vertical_border (w
)
1179 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1181 /* Redraw borders between horizontally adjacent windows. Don't
1182 do it for frames with vertical scroll bars because either the
1183 right scroll bar of a window, or the left scroll bar of its
1184 neighbor will suffice as a border. */
1185 if (!WINDOW_RIGHTMOST_P (w
)
1186 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1190 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
1191 x1
+= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
1194 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1195 f
->output_data
.mac
->normal_gc
, x1
, y0
, x1
, y1
);
1200 /* End update of window W (which is equal to updated_window).
1202 Draw vertical borders between horizontally adjacent windows, and
1203 display W's cursor if CURSOR_ON_P is non-zero.
1205 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1206 glyphs in mouse-face were overwritten. In that case we have to
1207 make sure that the mouse-highlight is properly redrawn.
1209 W may be a menu bar pseudo-window in case we don't have X toolkit
1210 support. Such windows don't have a cursor, so don't display it
1214 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1216 int cursor_on_p
, mouse_face_overwritten_p
;
1218 struct mac_display_info
*dpyinfo
1219 = FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1221 if (!w
->pseudo_window_p
)
1226 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1228 output_cursor
.x
, output_cursor
.y
);
1230 x_draw_vertical_border (w
);
1234 /* If a row with mouse-face was overwritten, arrange for
1235 XTframe_up_to_date to redisplay the mouse highlight. */
1236 if (mouse_face_overwritten_p
)
1238 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1239 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1240 dpyinfo
->mouse_face_window
= Qnil
;
1244 /* Unhide the caret. This won't actually show the cursor, unless it
1245 was visible before the corresponding call to HideCaret in
1246 x_update_window_begin. */
1247 if (w32_use_visible_system_caret
)
1248 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1251 updated_window
= NULL
;
1255 /* End update of frame F. This function is installed as a hook in
1262 /* Reset the background color of Mac OS Window to that of the frame after
1263 update so that it is used by Mac Toolbox to clear the update region before
1264 an update event is generated. */
1265 #if TARGET_API_MAC_CARBON
1266 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
1268 SetPort (FRAME_MAC_WINDOW (f
));
1271 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
1273 /* Mouse highlight may be displayed again. */
1274 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1277 XFlush (FRAME_MAC_DISPLAY (f
));
1282 /* This function is called from various places in xdisp.c whenever a
1283 complete update has been performed. The global variable
1284 updated_window is not available here. */
1287 XTframe_up_to_date (f
)
1292 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1294 if (dpyinfo
->mouse_face_deferred_gc
1295 || f
== dpyinfo
->mouse_face_mouse_frame
)
1298 if (dpyinfo
->mouse_face_mouse_frame
)
1299 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1300 dpyinfo
->mouse_face_mouse_x
,
1301 dpyinfo
->mouse_face_mouse_y
);
1302 dpyinfo
->mouse_face_deferred_gc
= 0;
1309 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1310 arrow bitmaps, or clear the fringes if no bitmaps are required
1311 before DESIRED_ROW is made current. The window being updated is
1312 found in updated_window. This function is called from
1313 update_window_line only if it is known that there are differences
1314 between bitmaps to be drawn between current row and DESIRED_ROW. */
1317 x_after_update_window_line (desired_row
)
1318 struct glyph_row
*desired_row
;
1320 struct window
*w
= updated_window
;
1326 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1329 draw_row_fringe_bitmaps (w
, desired_row
);
1333 /* When a window has disappeared, make sure that no rest of
1334 full-width rows stays visible in the internal border. Could
1335 check here if updated_window is the leftmost/rightmost window,
1336 but I guess it's not worth doing since vertically split windows
1337 are almost never used, internal border is rarely set, and the
1338 overhead is very small. */
1339 if (windows_or_buffers_changed
1340 && desired_row
->full_width_p
1341 && (f
= XFRAME (w
->frame
),
1342 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1344 && (height
= desired_row
->visible_height
,
1347 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1348 /* Internal border is drawn below the tool bar. */
1349 if (WINDOWP (f
->tool_bar_window
)
1350 && w
== XWINDOW (f
->tool_bar_window
))
1355 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1356 0, y
, width
, height
, 0);
1357 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1358 f
->output_data
.mac
->pixel_width
- width
, y
,
1366 /* Draw the bitmap WHICH in one of the left or right fringes of
1367 window W. ROW is the glyph row for which to display the bitmap; it
1368 determines the vertical position at which the bitmap has to be
1372 x_draw_fringe_bitmap (w
, row
, p
)
1374 struct glyph_row
*row
;
1375 struct draw_fringe_bitmap_params
*p
;
1377 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1378 Display
*display
= FRAME_MAC_DISPLAY (f
);
1379 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1381 GC gc
= f
->output_data
.mac
->normal_gc
;
1382 struct face
*face
= p
->face
;
1384 /* Must clip because of partially visible lines. */
1385 x_clip_to_row (w
, row
, gc
, 1);
1390 gcv
.foreground
= face
->background
;
1392 #if 0 /* MAC_TODO: stipple */
1393 /* In case the same realized face is used for fringes and
1394 for something displayed in the text (e.g. face `region' on
1395 mono-displays, the fill style may have been changed to
1396 FillSolid in x_draw_glyph_string_background. */
1398 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1400 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1403 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1405 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1407 #if 0 /* MAC_TODO: stipple */
1409 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1413 if (p
->which
!= NO_FRINGE_BITMAP
)
1415 unsigned char *bits
= fringe_bitmaps
[p
->which
].bits
+ p
->dh
;
1418 mac_create_bitmap_from_bitmap_data (&bitmap
, bits
, p
->wd
, p
->h
);
1419 gcv
.foreground
= face
->foreground
;
1420 gcv
.background
= face
->background
;
1422 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
, &bitmap
);
1424 mac_free_bitmap (&bitmap
);
1427 mac_reset_clipping (display
, window
);
1431 /* This is called when starting Emacs and when restarting after
1432 suspend. When starting Emacs, no window is mapped. And nothing
1433 must be done to Emacs's own window if it is suspended (though that
1437 XTset_terminal_modes ()
1441 /* This is called when exiting or suspending Emacs. Exiting will make
1442 the windows go away, and suspending requires no action. */
1445 XTreset_terminal_modes ()
1451 /***********************************************************************
1453 ***********************************************************************/
1455 /* Set the global variable output_cursor to CURSOR. All cursor
1456 positions are relative to updated_window. */
1459 set_output_cursor (cursor
)
1460 struct cursor_pos
*cursor
;
1462 output_cursor
.hpos
= cursor
->hpos
;
1463 output_cursor
.vpos
= cursor
->vpos
;
1464 output_cursor
.x
= cursor
->x
;
1465 output_cursor
.y
= cursor
->y
;
1469 /* Set a nominal cursor position.
1471 HPOS and VPOS are column/row positions in a window glyph matrix. X
1472 and Y are window text area relative pixel positions.
1474 If this is done during an update, updated_window will contain the
1475 window that is being updated and the position is the future output
1476 cursor position for that window. If updated_window is null, use
1477 selected_window and display the cursor at the given position. */
1480 XTcursor_to (vpos
, hpos
, y
, x
)
1481 int vpos
, hpos
, y
, x
;
1485 /* If updated_window is not set, work on selected_window. */
1489 w
= XWINDOW (selected_window
);
1491 /* Set the output cursor. */
1492 output_cursor
.hpos
= hpos
;
1493 output_cursor
.vpos
= vpos
;
1494 output_cursor
.x
= x
;
1495 output_cursor
.y
= y
;
1497 /* If not called as part of an update, really display the cursor.
1498 This will also set the cursor position of W. */
1499 if (updated_window
== NULL
)
1502 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1503 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1510 /***********************************************************************
1512 ***********************************************************************/
1514 /* Function prototypes of this page. */
1516 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1517 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1520 /* Return a pointer to per-char metric information in FONT of a
1521 character pointed by B which is a pointer to an XChar2b. */
1523 #define PER_CHAR_METRIC(font, b) \
1525 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1526 + (((font)->min_byte1 || (font)->max_byte1) \
1527 ? (((b)->byte1 - (font)->min_byte1) \
1528 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1530 : &((font)->max_bounds))
1533 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1534 is not contained in the font. */
1536 static INLINE XCharStruct
*
1537 x_per_char_metric (font
, char2b
)
1541 /* The result metric information. */
1542 XCharStruct
*pcm
= NULL
;
1544 xassert (font
&& char2b
);
1546 if (font
->per_char
!= NULL
)
1548 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1550 /* min_char_or_byte2 specifies the linear character index
1551 corresponding to the first element of the per_char array,
1552 max_char_or_byte2 is the index of the last character. A
1553 character with non-zero CHAR2B->byte1 is not in the font.
1554 A character with byte2 less than min_char_or_byte2 or
1555 greater max_char_or_byte2 is not in the font. */
1556 if (char2b
->byte1
== 0
1557 && char2b
->byte2
>= font
->min_char_or_byte2
1558 && char2b
->byte2
<= font
->max_char_or_byte2
)
1559 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1563 /* If either min_byte1 or max_byte1 are nonzero, both
1564 min_char_or_byte2 and max_char_or_byte2 are less than
1565 256, and the 2-byte character index values corresponding
1566 to the per_char array element N (counting from 0) are:
1568 byte1 = N/D + min_byte1
1569 byte2 = N\D + min_char_or_byte2
1573 D = max_char_or_byte2 - min_char_or_byte2 + 1
1574 / = integer division
1575 \ = integer modulus */
1576 if (char2b
->byte1
>= font
->min_byte1
1577 && char2b
->byte1
<= font
->max_byte1
1578 && char2b
->byte2
>= font
->min_char_or_byte2
1579 && char2b
->byte2
<= font
->max_char_or_byte2
)
1581 pcm
= (font
->per_char
1582 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1583 * (char2b
->byte1
- font
->min_byte1
))
1584 + (char2b
->byte2
- font
->min_char_or_byte2
));
1590 /* If the per_char pointer is null, all glyphs between the first
1591 and last character indexes inclusive have the same
1592 information, as given by both min_bounds and max_bounds. */
1593 if (char2b
->byte2
>= font
->min_char_or_byte2
1594 && char2b
->byte2
<= font
->max_char_or_byte2
)
1595 pcm
= &font
->max_bounds
;
1598 return ((pcm
== NULL
1599 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1606 static XCharStruct
*
1607 mac_per_char_metric (font
, char2b
, font_type
)
1612 return x_per_char_metric (font
, char2b
);
1616 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1617 the two-byte form of C. Encoding is returned in *CHAR2B. */
1620 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1623 struct font_info
*font_info
;
1626 int charset
= CHAR_CHARSET (c
);
1627 XFontStruct
*font
= font_info
->font
;
1629 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1630 This may be either a program in a special encoder language or a
1632 if (font_info
->font_encoder
)
1634 /* It's a program. */
1635 struct ccl_program
*ccl
= font_info
->font_encoder
;
1637 if (CHARSET_DIMENSION (charset
) == 1)
1639 ccl
->reg
[0] = charset
;
1640 ccl
->reg
[1] = char2b
->byte2
;
1644 ccl
->reg
[0] = charset
;
1645 ccl
->reg
[1] = char2b
->byte1
;
1646 ccl
->reg
[2] = char2b
->byte2
;
1649 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1651 /* We assume that MSBs are appropriately set/reset by CCL
1653 if (font
->max_byte1
== 0) /* 1-byte font */
1654 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1656 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1658 else if (font_info
->encoding
[charset
])
1660 /* Fixed encoding scheme. See fontset.h for the meaning of the
1661 encoding numbers. */
1662 int enc
= font_info
->encoding
[charset
];
1664 if ((enc
== 1 || enc
== 2)
1665 && CHARSET_DIMENSION (charset
) == 2)
1666 char2b
->byte1
|= 0x80;
1668 if (enc
== 1 || enc
== 3)
1669 char2b
->byte2
|= 0x80;
1675 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1676 char2b
->byte1
= sjis1
;
1677 char2b
->byte2
= sjis2
;
1682 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1684 return FONT_TYPE_UNKNOWN
;
1688 /* Estimate the pixel height of the mode or top line on frame F.
1689 FACE_ID specifies what line's height to estimate. */
1692 x_estimate_mode_line_height (f
, face_id
)
1694 enum face_id face_id
;
1696 int height
= FONT_HEIGHT (FRAME_FONT (f
));
1698 /* This function is called so early when Emacs starts that the face
1699 cache and mode line face are not yet initialized. */
1700 if (FRAME_FACE_CACHE (f
))
1702 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1706 height
= FONT_HEIGHT (face
->font
);
1707 if (face
->box_line_width
> 0)
1708 height
+= 2 * face
->box_line_width
;
1716 /***********************************************************************
1718 ***********************************************************************/
1721 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1722 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1723 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1725 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1726 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1727 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1728 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1729 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1730 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1731 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1732 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1733 unsigned long *, double, int));*/
1734 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1735 double, int, unsigned long));
1736 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1737 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1738 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1739 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1740 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1741 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1743 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1744 int, int, int, int, Rect
*));
1745 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1746 int, int, int, Rect
*));
1747 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
1748 enum glyph_row_area
));
1751 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1755 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1760 struct glyph_string
*s
;
1762 if (s
->font
== FRAME_FONT (s
->f
)
1763 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1764 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1766 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1769 /* Cursor on non-default face: must merge. */
1773 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1774 xgcv
.foreground
= s
->face
->background
;
1776 /* If the glyph would be invisible, try a different foreground. */
1777 if (xgcv
.foreground
== xgcv
.background
)
1778 xgcv
.foreground
= s
->face
->foreground
;
1779 if (xgcv
.foreground
== xgcv
.background
)
1780 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1781 if (xgcv
.foreground
== xgcv
.background
)
1782 xgcv
.foreground
= s
->face
->foreground
;
1784 /* Make sure the cursor is distinct from text in this face. */
1785 if (xgcv
.background
== s
->face
->background
1786 && xgcv
.foreground
== s
->face
->foreground
)
1788 xgcv
.background
= s
->face
->foreground
;
1789 xgcv
.foreground
= s
->face
->background
;
1792 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1793 xgcv
.font
= s
->font
;
1794 mask
= GCForeground
| GCBackground
| GCFont
;
1796 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1797 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1800 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1801 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1803 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1808 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1811 x_set_mouse_face_gc (s
)
1812 struct glyph_string
*s
;
1817 /* What face has to be used last for the mouse face? */
1818 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1819 face
= FACE_FROM_ID (s
->f
, face_id
);
1821 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1823 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1824 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1826 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1827 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1828 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1830 /* If font in this face is same as S->font, use it. */
1831 if (s
->font
== s
->face
->font
)
1832 s
->gc
= s
->face
->gc
;
1835 /* Otherwise construct scratch_cursor_gc with values from FACE
1840 xgcv
.background
= s
->face
->background
;
1841 xgcv
.foreground
= s
->face
->foreground
;
1842 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1843 xgcv
.font
= s
->font
;
1844 mask
= GCForeground
| GCBackground
| GCFont
;
1846 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1847 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1850 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1851 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1853 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1856 xassert (s
->gc
!= 0);
1860 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1861 Faces to use in the mode line have already been computed when the
1862 matrix was built, so there isn't much to do, here. */
1865 x_set_mode_line_face_gc (s
)
1866 struct glyph_string
*s
;
1868 s
->gc
= s
->face
->gc
;
1872 /* Set S->gc of glyph string S for drawing that glyph string. Set
1873 S->stippled_p to a non-zero value if the face of S has a stipple
1877 x_set_glyph_string_gc (s
)
1878 struct glyph_string
*s
;
1880 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1882 if (s
->hl
== DRAW_NORMAL_TEXT
)
1884 s
->gc
= s
->face
->gc
;
1885 s
->stippled_p
= s
->face
->stipple
!= 0;
1887 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1889 x_set_mode_line_face_gc (s
);
1890 s
->stippled_p
= s
->face
->stipple
!= 0;
1892 else if (s
->hl
== DRAW_CURSOR
)
1894 x_set_cursor_gc (s
);
1897 else if (s
->hl
== DRAW_MOUSE_FACE
)
1899 x_set_mouse_face_gc (s
);
1900 s
->stippled_p
= s
->face
->stipple
!= 0;
1902 else if (s
->hl
== DRAW_IMAGE_RAISED
1903 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1905 s
->gc
= s
->face
->gc
;
1906 s
->stippled_p
= s
->face
->stipple
!= 0;
1910 s
->gc
= s
->face
->gc
;
1911 s
->stippled_p
= s
->face
->stipple
!= 0;
1914 /* GC must have been set. */
1915 xassert (s
->gc
!= 0);
1919 /* Return in *R the clipping rectangle for glyph string S. */
1922 x_get_glyph_string_clip_rect (s
, r
)
1923 struct glyph_string
*s
;
1926 int r_height
, r_width
;
1928 if (s
->row
->full_width_p
)
1930 /* Draw full-width. X coordinates are relative to S->w->left. */
1931 int canon_x
= CANON_X_UNIT (s
->f
);
1933 r
->left
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
1934 r_width
= XFASTINT (s
->w
->width
) * canon_x
;
1936 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
1938 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
1939 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
1943 r
->left
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
1945 /* Unless displaying a mode or menu bar line, which are always
1946 fully visible, clip to the visible part of the row. */
1947 if (s
->w
->pseudo_window_p
)
1948 r_height
= s
->row
->visible_height
;
1950 r_height
= s
->height
;
1954 /* This is a text line that may be partially visible. */
1955 r
->left
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
1956 r_width
= window_box_width (s
->w
, s
->area
);
1957 r_height
= s
->row
->visible_height
;
1960 /* If S draws overlapping rows, it's sufficient to use the top and
1961 bottom of the window for clipping because this glyph string
1962 intentionally draws over other lines. */
1963 if (s
->for_overlaps_p
)
1965 r
->top
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
1966 r_height
= window_text_bottom_y (s
->w
) - r
->top
;
1970 /* Don't use S->y for clipping because it doesn't take partially
1971 visible lines into account. For example, it can be negative for
1972 partially visible lines at the top of a window. */
1973 if (!s
->row
->full_width_p
1974 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
1975 r
->top
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
1977 r
->top
= max (0, s
->row
->y
);
1979 /* If drawing a tool-bar window, draw it over the internal border
1980 at the top of the window. */
1981 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
1982 r
->top
-= s
->f
->output_data
.mac
->internal_border_width
;
1985 r
->top
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->top
);
1987 r
->bottom
= r
->top
+ r_height
;
1988 r
->right
= r
->left
+ r_width
;
1992 /* Set clipping for output of glyph string S. S may be part of a mode
1993 line or menu if we don't have X toolkit support. */
1996 x_set_glyph_string_clipping (s
)
1997 struct glyph_string
*s
;
2000 x_get_glyph_string_clip_rect (s
, &r
);
2001 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
2006 Compute left and right overhang of glyph string S. If S is a glyph
2007 string for a composition, assume overhangs don't exist. */
2010 mac_compute_glyph_string_overhangs (s
)
2011 struct glyph_string
*s
;
2014 /* MAC_TODO: XTextExtents16 does nothing yet... */
2017 && s
->first_glyph
->type
== CHAR_GLYPH
)
2020 int direction
, font_ascent
, font_descent
;
2021 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2022 &font_ascent
, &font_descent
, &cs
);
2023 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2024 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2030 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2033 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2034 struct glyph_string
*s
;
2039 xgcv
.foreground
= s
->gc
->background
;
2040 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
2044 /* Draw the background of glyph_string S. If S->background_filled_p
2045 is non-zero don't draw it. FORCE_P non-zero means draw the
2046 background even if it wouldn't be drawn normally. This is used
2047 when a string preceding S draws into the background of S, or S
2048 contains the first component of a composition. */
2051 x_draw_glyph_string_background (s
, force_p
)
2052 struct glyph_string
*s
;
2055 /* Nothing to do if background has already been drawn or if it
2056 shouldn't be drawn in the first place. */
2057 if (!s
->background_filled_p
)
2059 int box_line_width
= max (s
->face
->box_line_width
, 0);
2061 #if 0 /* MAC_TODO: stipple */
2064 /* Fill background with a stipple pattern. */
2065 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2066 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2067 s
->y
+ box_line_width
,
2068 s
->background_width
,
2069 s
->height
- 2 * box_line_width
);
2070 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2071 s
->background_filled_p
= 1;
2075 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2076 || s
->font_not_found_p
2077 || s
->extends_to_end_of_line_p
2080 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2081 s
->background_width
,
2082 s
->height
- 2 * box_line_width
);
2083 s
->background_filled_p
= 1;
2089 /* Draw the foreground of glyph string S. */
2092 x_draw_glyph_string_foreground (s
)
2093 struct glyph_string
*s
;
2097 /* If first glyph of S has a left box line, start drawing the text
2098 of S to the right of that box line. */
2099 if (s
->face
->box
!= FACE_NO_BOX
2100 && s
->first_glyph
->left_box_line_p
)
2101 x
= s
->x
+ abs (s
->face
->box_line_width
);
2105 /* Draw characters of S as rectangles if S's font could not be
2107 if (s
->font_not_found_p
)
2109 for (i
= 0; i
< s
->nchars
; ++i
)
2111 struct glyph
*g
= s
->first_glyph
+ i
;
2112 mac_draw_rectangle (s
->display
, s
->window
,
2113 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2115 x
+= g
->pixel_width
;
2120 char *char1b
= (char *) s
->char2b
;
2121 int boff
= s
->font_info
->baseline_offset
;
2123 if (s
->font_info
->vertical_centering
)
2124 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2126 /* If we can use 8-bit functions, condense S->char2b. */
2128 for (i
= 0; i
< s
->nchars
; ++i
)
2129 char1b
[i
] = s
->char2b
[i
].byte2
;
2131 /* Draw text with XDrawString if background has already been
2132 filled. Otherwise, use XDrawImageString. (Note that
2133 XDrawImageString is usually faster than XDrawString.) Always
2134 use XDrawImageString when drawing the cursor so that there is
2135 no chance that characters under a box cursor are invisible. */
2136 if (s
->for_overlaps_p
2137 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2139 /* Draw characters with 16-bit or 8-bit functions. */
2141 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2142 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2144 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2145 s
->ybase
- boff
, char1b
, s
->nchars
);
2150 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2151 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2153 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2154 s
->ybase
- boff
, char1b
, s
->nchars
);
2159 /* Draw the foreground of composite glyph string S. */
2162 x_draw_composite_glyph_string_foreground (s
)
2163 struct glyph_string
*s
;
2167 /* If first glyph of S has a left box line, start drawing the text
2168 of S to the right of that box line. */
2169 if (s
->face
->box
!= FACE_NO_BOX
2170 && s
->first_glyph
->left_box_line_p
)
2171 x
= s
->x
+ abs (s
->face
->box_line_width
);
2175 /* S is a glyph string for a composition. S->gidx is the index of
2176 the first character drawn for glyphs of this composition.
2177 S->gidx == 0 means we are drawing the very first character of
2178 this composition. */
2180 /* Draw a rectangle for the composition if the font for the very
2181 first character of the composition could not be loaded. */
2182 if (s
->font_not_found_p
)
2185 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2186 s
->width
- 1, s
->height
- 1);
2190 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2191 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2192 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2193 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2199 #ifdef USE_X_TOOLKIT
2201 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2204 /* Return the frame on which widget WIDGET is used.. Abort if frame
2205 cannot be determined. */
2207 static struct frame
*
2208 x_frame_of_widget (widget
)
2211 struct x_display_info
*dpyinfo
;
2215 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2217 /* Find the top-level shell of the widget. Note that this function
2218 can be called when the widget is not yet realized, so XtWindow
2219 (widget) == 0. That's the reason we can't simply use
2220 x_any_window_to_frame. */
2221 while (!XtIsTopLevelShell (widget
))
2222 widget
= XtParent (widget
);
2224 /* Look for a frame with that top-level widget. Allocate the color
2225 on that frame to get the right gamma correction value. */
2226 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2227 if (GC_FRAMEP (XCAR (tail
))
2228 && (f
= XFRAME (XCAR (tail
)),
2229 (f
->output_data
.nothing
!= 1
2230 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2231 && f
->output_data
.x
->widget
== widget
)
2238 /* Allocate the color COLOR->pixel on the screen and display of
2239 widget WIDGET in colormap CMAP. If an exact match cannot be
2240 allocated, try the nearest color available. Value is non-zero
2241 if successful. This is called from lwlib. */
2244 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2249 struct frame
*f
= x_frame_of_widget (widget
);
2250 return x_alloc_nearest_color (f
, cmap
, color
);
2254 #endif /* USE_X_TOOLKIT */
2256 #if 0 /* MAC_TODO */
2258 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2259 CMAP. If an exact match can't be allocated, try the nearest color
2260 available. Value is non-zero if successful. Set *COLOR to the
2264 x_alloc_nearest_color (f
, cmap
, color
)
2269 Display
*display
= FRAME_X_DISPLAY (f
);
2270 Screen
*screen
= FRAME_X_SCREEN (f
);
2273 gamma_correct (f
, color
);
2274 rc
= XAllocColor (display
, cmap
, color
);
2277 /* If we got to this point, the colormap is full, so we're going
2278 to try to get the next closest color. The algorithm used is
2279 a least-squares matching, which is what X uses for closest
2280 color matching with StaticColor visuals. */
2282 unsigned long nearest_delta
= ~0;
2283 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2284 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2286 for (i
= 0; i
< ncells
; ++i
)
2288 XQueryColors (display
, cmap
, cells
, ncells
);
2290 for (nearest
= i
= 0; i
< ncells
; ++i
)
2292 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2293 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2294 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2295 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2297 if (delta
< nearest_delta
)
2300 nearest_delta
= delta
;
2304 color
->red
= cells
[nearest
].red
;
2305 color
->green
= cells
[nearest
].green
;
2306 color
->blue
= cells
[nearest
].blue
;
2307 rc
= XAllocColor (display
, cmap
, color
);
2310 #ifdef DEBUG_X_COLORS
2312 register_color (color
->pixel
);
2313 #endif /* DEBUG_X_COLORS */
2319 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2320 It's necessary to do this instead of just using PIXEL directly to
2321 get color reference counts right. */
2324 x_copy_color (f
, pixel
)
2326 unsigned long pixel
;
2330 color
.pixel
= pixel
;
2332 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2333 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2335 #ifdef DEBUG_X_COLORS
2336 register_color (pixel
);
2342 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2343 It's necessary to do this instead of just using PIXEL directly to
2344 get color reference counts right. */
2347 x_copy_dpy_color (dpy
, cmap
, pixel
)
2350 unsigned long pixel
;
2354 color
.pixel
= pixel
;
2356 XQueryColor (dpy
, cmap
, &color
);
2357 XAllocColor (dpy
, cmap
, &color
);
2359 #ifdef DEBUG_X_COLORS
2360 register_color (pixel
);
2365 #endif /* MAC_TODO */
2367 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2368 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2369 If this produces the same color as COLOR, try a color where all RGB
2370 values have DELTA added. Return the allocated color in *COLOR.
2371 DISPLAY is the X display, CMAP is the colormap to operate on.
2372 Value is non-zero if successful. */
2375 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2377 unsigned long *color
;
2383 /* Change RGB values by specified FACTOR. Avoid overflow! */
2384 xassert (factor
>= 0);
2385 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2386 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2387 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2389 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2390 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2391 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2393 /* MAC_TODO: Map to palette and retry with delta if same? */
2394 /* MAC_TODO: Free colors (if using palette)? */
2405 /* Set up the foreground color for drawing relief lines of glyph
2406 string S. RELIEF is a pointer to a struct relief containing the GC
2407 with which lines will be drawn. Use a color that is FACTOR or
2408 DELTA lighter or darker than the relief's background which is found
2409 in S->f->output_data.x->relief_background. If such a color cannot
2410 be allocated, use DEFAULT_PIXEL, instead. */
2413 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2415 struct relief
*relief
;
2418 unsigned long default_pixel
;
2421 struct mac_output
*di
= f
->output_data
.mac
;
2422 unsigned long mask
= GCForeground
;
2423 unsigned long pixel
;
2424 unsigned long background
= di
->relief_background
;
2425 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2427 /* MAC_TODO: Free colors (if using palette)? */
2429 /* Allocate new color. */
2430 xgcv
.foreground
= default_pixel
;
2432 if (mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2434 relief
->allocated_p
= 1;
2435 xgcv
.foreground
= relief
->pixel
= pixel
;
2438 if (relief
->gc
== 0)
2440 #if 0 /* MAC_TODO: stipple */
2441 xgcv
.stipple
= dpyinfo
->gray
;
2444 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2447 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2451 /* Set up colors for the relief lines around glyph string S. */
2454 x_setup_relief_colors (s
)
2455 struct glyph_string
*s
;
2457 struct mac_output
*di
= s
->f
->output_data
.mac
;
2458 unsigned long color
;
2460 if (s
->face
->use_box_color_for_shadows_p
)
2461 color
= s
->face
->box_color
;
2466 /* Get the background color of the face. */
2467 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2468 color
= xgcv
.background
;
2471 if (di
->white_relief
.gc
== 0
2472 || color
!= di
->relief_background
)
2474 di
->relief_background
= color
;
2475 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2476 WHITE_PIX_DEFAULT (s
->f
));
2477 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2478 BLACK_PIX_DEFAULT (s
->f
));
2483 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2484 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2485 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2486 relief. LEFT_P non-zero means draw a relief on the left side of
2487 the rectangle. RIGHT_P non-zero means draw a relief on the right
2488 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2492 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2493 raised_p
, left_p
, right_p
, clip_rect
)
2495 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
2502 gc
= f
->output_data
.mac
->white_relief
.gc
;
2504 gc
= f
->output_data
.mac
->black_relief
.gc
;
2505 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), clip_rect
);
2508 for (i
= 0; i
< width
; ++i
)
2509 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
2510 left_x
+ i
* left_p
, top_y
+ i
,
2511 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2515 for (i
= 0; i
< width
; ++i
)
2516 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
2517 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2519 mac_reset_clipping (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
2521 gc
= f
->output_data
.mac
->black_relief
.gc
;
2523 gc
= f
->output_data
.mac
->white_relief
.gc
;
2524 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
2528 for (i
= 0; i
< width
; ++i
)
2529 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
2530 left_x
+ i
* left_p
, bottom_y
- i
,
2531 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2535 for (i
= 0; i
< width
; ++i
)
2536 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
2537 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
2539 mac_reset_clipping (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
2543 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2544 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2545 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2546 left side of the rectangle. RIGHT_P non-zero means draw a line
2547 on the right side of the rectangle. CLIP_RECT is the clipping
2548 rectangle to use when drawing. */
2551 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2552 left_p
, right_p
, clip_rect
)
2553 struct glyph_string
*s
;
2554 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
2559 xgcv
.foreground
= s
->face
->box_color
;
2560 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2563 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2564 left_x
, top_y
, right_x
- left_x
, width
);
2568 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2569 left_x
, top_y
, width
, bottom_y
- top_y
);
2572 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2573 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
2577 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2578 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
2580 mac_reset_clipping (s
->display
, s
->window
);
2584 /* Draw a box around glyph string S. */
2587 x_draw_glyph_string_box (s
)
2588 struct glyph_string
*s
;
2590 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2591 int left_p
, right_p
;
2592 struct glyph
*last_glyph
;
2595 last_x
= window_box_right (s
->w
, s
->area
);
2596 if (s
->row
->full_width_p
2597 && !s
->w
->pseudo_window_p
)
2599 last_x
+= FRAME_X_RIGHT_FRINGE_WIDTH (s
->f
);
2600 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
2601 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
2604 /* The glyph that may have a right box line. */
2605 last_glyph
= (s
->cmp
|| s
->img
2607 : s
->first_glyph
+ s
->nchars
- 1);
2609 width
= abs (s
->face
->box_line_width
);
2610 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2612 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2614 : min (last_x
, s
->x
+ s
->background_width
) - 1));
2616 bottom_y
= top_y
+ s
->height
- 1;
2618 left_p
= (s
->first_glyph
->left_box_line_p
2619 || (s
->hl
== DRAW_MOUSE_FACE
2621 || s
->prev
->hl
!= s
->hl
)));
2622 right_p
= (last_glyph
->right_box_line_p
2623 || (s
->hl
== DRAW_MOUSE_FACE
2625 || s
->next
->hl
!= s
->hl
)));
2627 x_get_glyph_string_clip_rect (s
, &clip_rect
);
2629 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2630 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2631 left_p
, right_p
, &clip_rect
);
2634 x_setup_relief_colors (s
);
2635 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2636 width
, raised_p
, left_p
, right_p
, &clip_rect
);
2641 /* Draw foreground of image glyph string S. */
2644 x_draw_image_foreground (s
)
2645 struct glyph_string
*s
;
2648 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2650 /* If first glyph of S has a left box line, start drawing it to the
2651 right of that line. */
2652 if (s
->face
->box
!= FACE_NO_BOX
2653 && s
->first_glyph
->left_box_line_p
)
2654 x
= s
->x
+ abs (s
->face
->box_line_width
);
2658 /* If there is a margin around the image, adjust x- and y-position
2660 x
+= s
->img
->hmargin
;
2661 y
+= s
->img
->vmargin
;
2665 #if 0 /* MAC_TODO: image mask */
2668 /* We can't set both a clip mask and use XSetClipRectangles
2669 because the latter also sets a clip mask. We also can't
2670 trust on the shape extension to be available
2671 (XShapeCombineRegion). So, compute the rectangle to draw
2673 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2676 XRectangle clip_rect
, image_rect
, r
;
2678 xgcv
.clip_mask
= s
->img
->mask
;
2679 xgcv
.clip_x_origin
= x
;
2680 xgcv
.clip_y_origin
= y
;
2681 xgcv
.function
= GXcopy
;
2682 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2684 x_get_glyph_string_clip_rect (s
, &clip_rect
);
2687 image_rect
.width
= s
->img
->width
;
2688 image_rect
.height
= s
->img
->height
;
2689 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2690 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2691 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
2694 #endif /* MAC_TODO */
2696 mac_copy_area (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2697 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2699 /* When the image has a mask, we can expect that at
2700 least part of a mouse highlight or a block cursor will
2701 be visible. If the image doesn't have a mask, make
2702 a block cursor visible by drawing a rectangle around
2703 the image. I believe it's looking better if we do
2704 nothing here for mouse-face. */
2705 if (s
->hl
== DRAW_CURSOR
)
2707 int r
= s
->img
->relief
;
2709 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2710 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2715 /* Draw a rectangle if image could not be loaded. */
2716 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2717 s
->img
->width
- 1, s
->img
->height
- 1);
2722 /* Draw a relief around the image glyph string S. */
2725 x_draw_image_relief (s
)
2726 struct glyph_string
*s
;
2728 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2731 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2733 /* If first glyph of S has a left box line, start drawing it to the
2734 right of that line. */
2735 if (s
->face
->box
!= FACE_NO_BOX
2736 && s
->first_glyph
->left_box_line_p
)
2737 x
= s
->x
+ abs (s
->face
->box_line_width
);
2741 /* If there is a margin around the image, adjust x- and y-position
2743 x
+= s
->img
->hmargin
;
2744 y
+= s
->img
->vmargin
;
2746 if (s
->hl
== DRAW_IMAGE_SUNKEN
2747 || s
->hl
== DRAW_IMAGE_RAISED
)
2749 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2750 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2754 thick
= abs (s
->img
->relief
);
2755 raised_p
= s
->img
->relief
> 0;
2760 x1
= x
+ s
->img
->width
+ thick
- 1;
2761 y1
= y
+ s
->img
->height
+ thick
- 1;
2763 x_setup_relief_colors (s
);
2764 x_get_glyph_string_clip_rect (s
, &r
);
2765 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
2769 /* Draw the foreground of image glyph string S to PIXMAP. */
2772 x_draw_image_foreground_1 (s
, pixmap
)
2773 struct glyph_string
*s
;
2777 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
2779 /* If first glyph of S has a left box line, start drawing it to the
2780 right of that line. */
2781 if (s
->face
->box
!= FACE_NO_BOX
2782 && s
->first_glyph
->left_box_line_p
)
2783 x
= abs (s
->face
->box_line_width
);
2787 /* If there is a margin around the image, adjust x- and y-position
2789 x
+= s
->img
->hmargin
;
2790 y
+= s
->img
->vmargin
;
2794 #if 0 /* MAC_TODO: image mask */
2797 /* We can't set both a clip mask and use XSetClipRectangles
2798 because the latter also sets a clip mask. We also can't
2799 trust on the shape extension to be available
2800 (XShapeCombineRegion). So, compute the rectangle to draw
2802 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2806 xgcv
.clip_mask
= s
->img
->mask
;
2807 xgcv
.clip_x_origin
= x
;
2808 xgcv
.clip_y_origin
= y
;
2809 xgcv
.function
= GXcopy
;
2810 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2812 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2813 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2814 XSetClipMask (s
->display
, s
->gc
, None
);
2817 #endif /* MAC_TODO */
2819 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2820 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2822 /* When the image has a mask, we can expect that at
2823 least part of a mouse highlight or a block cursor will
2824 be visible. If the image doesn't have a mask, make
2825 a block cursor visible by drawing a rectangle around
2826 the image. I believe it's looking better if we do
2827 nothing here for mouse-face. */
2828 if (s
->hl
== DRAW_CURSOR
)
2830 int r
= s
->img
->relief
;
2832 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
- r
, y
- r
,
2833 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2838 /* Draw a rectangle if image could not be loaded. */
2839 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2840 s
->img
->width
- 1, s
->img
->height
- 1);
2844 /* Draw part of the background of glyph string S. X, Y, W, and H
2845 give the rectangle to draw. */
2848 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2849 struct glyph_string
*s
;
2852 #if 0 /* MAC_TODO: stipple */
2855 /* Fill background with a stipple pattern. */
2856 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2857 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2858 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2861 #endif /* MAC_TODO */
2862 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2866 /* Draw image glyph string S.
2869 s->x +-------------------------
2872 | +-------------------------
2875 | | +-------------------
2881 x_draw_image_glyph_string (s
)
2882 struct glyph_string
*s
;
2885 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2886 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2890 height
= s
->height
- 2 * box_line_vwidth
;
2892 /* Fill background with face under the image. Do it only if row is
2893 taller than image or if image has a clip mask to reduce
2895 s
->stippled_p
= s
->face
->stipple
!= 0;
2896 if (height
> s
->img
->height
2899 #if 0 /* TODO: image mask */
2902 || s
->img
->pixmap
== 0
2903 || s
->width
!= s
->background_width
)
2905 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
2906 x
= s
->x
+ box_line_hwidth
;
2910 y
= s
->y
+ box_line_vwidth
;
2911 #if 0 /* TODO: image mask */
2914 /* Create a pixmap as large as the glyph string. Fill it
2915 with the background color. Copy the image to it, using
2916 its mask. Copy the temporary pixmap to the display. */
2917 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2918 int depth
= DefaultDepthOfScreen (screen
);
2920 /* Create a pixmap as large as the glyph string. */
2921 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2922 s
->background_width
,
2925 /* Don't clip in the following because we're working on the
2927 XSetClipMask (s
->display
, s
->gc
, None
);
2929 /* Fill the pixmap with the background color/stipple. */
2932 /* Fill background with a stipple pattern. */
2933 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2934 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2935 0, 0, s
->background_width
, s
->height
);
2936 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2941 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2943 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2944 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2945 0, 0, s
->background_width
, s
->height
);
2946 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2951 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2953 s
->background_filled_p
= 1;
2956 /* Draw the foreground. */
2959 x_draw_image_foreground_1 (s
, pixmap
);
2960 x_set_glyph_string_clipping (s
);
2961 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
2962 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2963 mac_reset_clipping (s
->display
, s
->window
);
2964 XFreePixmap (s
->display
, pixmap
);
2967 x_draw_image_foreground (s
);
2969 /* If we must draw a relief around the image, do it. */
2971 || s
->hl
== DRAW_IMAGE_RAISED
2972 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2973 x_draw_image_relief (s
);
2977 /* Draw stretch glyph string S. */
2980 x_draw_stretch_glyph_string (s
)
2981 struct glyph_string
*s
;
2983 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2984 s
->stippled_p
= s
->face
->stipple
!= 0;
2986 if (s
->hl
== DRAW_CURSOR
2987 && !x_stretch_cursor_p
)
2989 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2990 as wide as the stretch glyph. */
2991 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
2994 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2996 /* Clear rest using the GC of the original non-cursor face. */
2997 if (width
< s
->background_width
)
2999 GC gc
= s
->face
->gc
;
3000 int x
= s
->x
+ width
, y
= s
->y
;
3001 int w
= s
->background_width
- width
, h
= s
->height
;
3004 if (s
->row
->mouse_face_p
3005 && cursor_in_mouse_face_p (s
->w
))
3007 x_set_mouse_face_gc (s
);
3013 x_get_glyph_string_clip_rect (s
, &r
);
3014 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3016 #if 0 /* MAC_TODO: stipple */
3017 if (s
->face
->stipple
)
3019 /* Fill background with a stipple pattern. */
3020 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3021 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3022 XSetFillStyle (s
->display
, gc
, FillSolid
);
3025 #endif /* MAC_TODO */
3028 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3029 XSetForeground (s
->display
, gc
, xgcv
.background
);
3030 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3031 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3034 mac_reset_clipping (s
->display
, s
->window
);
3037 else if (!s
->background_filled_p
)
3038 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3041 s
->background_filled_p
= 1;
3045 /* Draw glyph string S. */
3048 x_draw_glyph_string (s
)
3049 struct glyph_string
*s
;
3051 int relief_drawn_p
= 0;
3053 /* If S draws into the background of its successor, draw the
3054 background of the successor first so that S can draw into it.
3055 This makes S->next use XDrawString instead of XDrawImageString. */
3056 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
3058 xassert (s
->next
->img
== NULL
);
3059 x_set_glyph_string_gc (s
->next
);
3060 x_set_glyph_string_clipping (s
->next
);
3061 x_draw_glyph_string_background (s
->next
, 1);
3065 /* Set up S->gc, set clipping and draw S. */
3066 x_set_glyph_string_gc (s
);
3068 /* Draw relief (if any) in advance for char/composition so that the
3069 glyph string can be drawn over it. */
3070 if (!s
->for_overlaps_p
3071 && s
->face
->box
!= FACE_NO_BOX
3072 && (s
->first_glyph
->type
== CHAR_GLYPH
3073 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3076 x_set_glyph_string_clipping (s
);
3077 x_draw_glyph_string_background (s
, 1);
3078 x_draw_glyph_string_box (s
);
3079 x_set_glyph_string_clipping (s
);
3083 x_set_glyph_string_clipping (s
);
3085 switch (s
->first_glyph
->type
)
3088 x_draw_image_glyph_string (s
);
3092 x_draw_stretch_glyph_string (s
);
3096 if (s
->for_overlaps_p
)
3097 s
->background_filled_p
= 1;
3099 x_draw_glyph_string_background (s
, 0);
3100 x_draw_glyph_string_foreground (s
);
3103 case COMPOSITE_GLYPH
:
3104 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3105 s
->background_filled_p
= 1;
3107 x_draw_glyph_string_background (s
, 1);
3108 x_draw_composite_glyph_string_foreground (s
);
3115 if (!s
->for_overlaps_p
)
3117 /* Draw underline. */
3118 if (s
->face
->underline_p
)
3120 unsigned long h
= 1;
3121 unsigned long dy
= s
->height
- h
;
3123 if (s
->face
->underline_defaulted_p
)
3124 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3129 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3130 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3131 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3133 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3137 /* Draw overline. */
3138 if (s
->face
->overline_p
)
3140 unsigned long dy
= 0, h
= 1;
3142 if (s
->face
->overline_color_defaulted_p
)
3143 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3148 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3149 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3150 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3152 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3156 /* Draw strike-through. */
3157 if (s
->face
->strike_through_p
)
3159 unsigned long h
= 1;
3160 unsigned long dy
= (s
->height
- h
) / 2;
3162 if (s
->face
->strike_through_color_defaulted_p
)
3163 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3168 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3169 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3170 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3172 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3177 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3178 x_draw_glyph_string_box (s
);
3181 /* Reset clipping. */
3182 mac_reset_clipping (s
->display
, s
->window
);
3186 /* Fix the display of area AREA of overlapping row ROW in window W. */
3189 x_fix_overlapping_area (w
, row
, area
)
3191 struct glyph_row
*row
;
3192 enum glyph_row_area area
;
3198 if (area
== LEFT_MARGIN_AREA
)
3200 else if (area
== TEXT_AREA
)
3201 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
3203 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
3204 + window_box_width (w
, TEXT_AREA
));
3206 for (i
= 0; i
< row
->used
[area
];)
3208 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
3210 int start
= i
, start_x
= x
;
3214 x
+= row
->glyphs
[area
][i
].pixel_width
;
3217 while (i
< row
->used
[area
]
3218 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
3220 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
3221 DRAW_NORMAL_TEXT
, 1);
3225 x
+= row
->glyphs
[area
][i
].pixel_width
;
3234 /* Output LEN glyphs starting at START at the nominal cursor position.
3235 Advance the nominal cursor over the text. The global variable
3236 updated_window contains the window being updated, updated_row is
3237 the glyph row being updated, and updated_area is the area of that
3238 row being updated. */
3241 x_write_glyphs (start
, len
)
3242 struct glyph
*start
;
3247 xassert (updated_window
&& updated_row
);
3252 hpos
= start
- updated_row
->glyphs
[updated_area
];
3253 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
3254 updated_row
, updated_area
,
3256 DRAW_NORMAL_TEXT
, 0);
3260 /* Advance the output cursor. */
3261 output_cursor
.hpos
+= len
;
3262 output_cursor
.x
= x
;
3266 /* Insert LEN glyphs from START at the nominal cursor position. */
3269 x_insert_glyphs (start
, len
)
3270 struct glyph
*start
;
3275 int line_height
, shift_by_width
, shifted_region_width
;
3276 struct glyph_row
*row
;
3277 struct glyph
*glyph
;
3278 int frame_x
, frame_y
, hpos
;
3280 xassert (updated_window
&& updated_row
);
3283 f
= XFRAME (WINDOW_FRAME (w
));
3285 /* Get the height of the line we are in. */
3287 line_height
= row
->height
;
3289 /* Get the width of the glyphs to insert. */
3291 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
3292 shift_by_width
+= glyph
->pixel_width
;
3294 /* Get the width of the region to shift right. */
3295 shifted_region_width
= (window_box_width (w
, updated_area
)
3300 frame_x
= window_box_left (w
, updated_area
) + output_cursor
.x
;
3301 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
3303 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3304 f
->output_data
.mac
->normal_gc
,
3306 shifted_region_width
, line_height
,
3307 frame_x
+ shift_by_width
, frame_y
);
3309 /* Write the glyphs. */
3310 hpos
= start
- row
->glyphs
[updated_area
];
3311 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
3312 DRAW_NORMAL_TEXT
, 0);
3314 /* Advance the output cursor. */
3315 output_cursor
.hpos
+= len
;
3316 output_cursor
.x
+= shift_by_width
;
3321 /* Delete N glyphs at the nominal cursor position. Not implemented
3332 /* Erase the current text line from the nominal cursor position
3333 (inclusive) to pixel column TO_X (exclusive). The idea is that
3334 everything from TO_X onward is already erased.
3336 TO_X is a pixel position relative to updated_area of
3337 updated_window. TO_X == -1 means clear to the end of this area. */
3340 x_clear_end_of_line (to_x
)
3344 struct window
*w
= updated_window
;
3345 int max_x
, min_y
, max_y
;
3346 int from_x
, from_y
, to_y
;
3348 xassert (updated_window
&& updated_row
);
3349 f
= XFRAME (w
->frame
);
3351 if (updated_row
->full_width_p
)
3353 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
3354 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3355 && !w
->pseudo_window_p
)
3356 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
3359 max_x
= window_box_width (w
, updated_area
);
3360 max_y
= window_text_bottom_y (w
);
3362 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
3363 of window. For TO_X > 0, truncate to end of drawing area. */
3369 to_x
= min (to_x
, max_x
);
3371 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
3373 /* Notice if the cursor will be cleared by this operation. */
3374 if (!updated_row
->full_width_p
)
3375 notice_overwritten_cursor (w
, updated_area
,
3376 output_cursor
.x
, -1,
3378 MATRIX_ROW_BOTTOM_Y (updated_row
));
3380 from_x
= output_cursor
.x
;
3382 /* Translate to frame coordinates. */
3383 if (updated_row
->full_width_p
)
3385 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
3386 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
3390 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
3391 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
3394 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
3395 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
3396 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
3398 /* Prevent inadvertently clearing to end of the X window. */
3399 if (to_x
> from_x
&& to_y
> from_y
)
3402 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3403 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
3410 /* Clear entire frame. If updating_frame is non-null, clear that
3411 frame. Otherwise clear the selected frame. */
3421 f
= SELECTED_FRAME ();
3423 /* Clearing the frame will erase any cursor, so mark them all as no
3425 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3426 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3427 output_cursor
.x
= -1;
3429 /* We don't set the output cursor here because there will always
3430 follow an explicit cursor_to. */
3432 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3434 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3435 /* We have to clear the scroll bars, too. If we have changed
3436 colors or something like that, then they should be notified. */
3437 x_scroll_bar_clear (f
);
3440 XFlush (FRAME_MAC_DISPLAY (f
));
3446 /* Invert the middle quarter of the frame for .15 sec. */
3448 /* We use the select system call to do the waiting, so we have to make
3449 sure it's available. If it isn't, we just won't do visual bells. */
3451 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3453 /* Subtract the `struct timeval' values X and Y, storing the result in
3454 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3457 timeval_subtract (result
, x
, y
)
3458 struct timeval
*result
, x
, y
;
3460 /* Perform the carry for the later subtraction by updating y. This
3461 is safer because on some systems the tv_sec member is unsigned. */
3462 if (x
.tv_usec
< y
.tv_usec
)
3464 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3465 y
.tv_usec
-= 1000000 * nsec
;
3469 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3471 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3472 y
.tv_usec
+= 1000000 * nsec
;
3476 /* Compute the time remaining to wait. tv_usec is certainly
3478 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3479 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3481 /* Return indication of whether the result should be considered
3483 return x
.tv_sec
< y
.tv_sec
;
3495 struct timeval wakeup
;
3497 EMACS_GET_TIME (wakeup
);
3499 /* Compute time to wait until, propagating carry from usecs. */
3500 wakeup
.tv_usec
+= 150000;
3501 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3502 wakeup
.tv_usec
%= 1000000;
3504 /* Keep waiting until past the time wakeup. */
3507 struct timeval timeout
;
3509 EMACS_GET_TIME (timeout
);
3511 /* In effect, timeout = wakeup - timeout.
3512 Break if result would be negative. */
3513 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3516 /* Try to wait that long--but we might wake up sooner. */
3517 select (0, NULL
, NULL
, NULL
, &timeout
);
3526 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3529 /* Make audible bell. */
3534 struct frame
*f
= SELECTED_FRAME ();
3536 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3544 XFlush (FRAME_MAC_DISPLAY (f
));
3551 /* Specify how many text lines, from the top of the window,
3552 should be affected by insert-lines and delete-lines operations.
3553 This, and those operations, are used only within an update
3554 that is bounded by calls to x_update_begin and x_update_end. */
3557 XTset_terminal_window (n
)
3560 /* This function intentionally left blank. */
3565 /***********************************************************************
3567 ***********************************************************************/
3569 /* Perform an insert-lines or delete-lines operation, inserting N
3570 lines or deleting -N lines at vertical position VPOS. */
3573 x_ins_del_lines (vpos
, n
)
3580 /* Scroll part of the display as described by RUN. */
3583 x_scroll_run (w
, run
)
3587 struct frame
*f
= XFRAME (w
->frame
);
3588 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3590 /* Get frame-relative bounding box of the text display area of W,
3591 without mode lines. Include in this box the left and right
3593 window_box (w
, -1, &x
, &y
, &width
, &height
);
3594 width
+= FRAME_X_FRINGE_WIDTH (f
);
3595 x
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
3597 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3598 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3599 bottom_y
= y
+ height
;
3603 /* Scrolling up. Make sure we don't copy part of the mode
3604 line at the bottom. */
3605 if (from_y
+ run
->height
> bottom_y
)
3606 height
= bottom_y
- from_y
;
3608 height
= run
->height
;
3612 /* Scolling down. Make sure we don't copy over the mode line.
3614 if (to_y
+ run
->height
> bottom_y
)
3615 height
= bottom_y
- to_y
;
3617 height
= run
->height
;
3622 /* Cursor off. Will be switched on again in x_update_window_end. */
3626 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3627 f
->output_data
.mac
->normal_gc
,
3637 /***********************************************************************
3639 ***********************************************************************/
3641 /* Redisplay an exposed area of frame F. X and Y are the upper-left
3642 corner of the exposed rectangle. W and H are width and height of
3643 the exposed area. All are pixel values. W or H zero means redraw
3644 the entire frame. */
3647 expose_frame (f
, x
, y
, w
, h
)
3652 int mouse_face_overwritten_p
= 0;
3654 TRACE ((stderr
, "expose_frame "));
3656 /* No need to redraw if frame will be redrawn soon. */
3657 if (FRAME_GARBAGED_P (f
))
3659 TRACE ((stderr
, " garbaged\n"));
3663 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
3664 or deactivated here, for unknown reasons, activated scroll bars
3665 are shown in deactivated frames in some instances. */
3666 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
3667 activate_scroll_bars (f
);
3669 deactivate_scroll_bars (f
);
3671 /* If basic faces haven't been realized yet, there is no point in
3672 trying to redraw anything. This can happen when we get an expose
3673 event while Emacs is starting, e.g. by moving another window. */
3674 if (FRAME_FACE_CACHE (f
) == NULL
3675 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
3677 TRACE ((stderr
, " no faces\n"));
3681 if (w
== 0 || h
== 0)
3684 r
.right
= CANON_X_UNIT (f
) * f
->width
;
3685 r
.bottom
= CANON_Y_UNIT (f
) * f
->height
;
3695 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.left
, r
.top
, r
.right
, r
.bottom
));
3696 mouse_face_overwritten_p
= expose_window_tree (XWINDOW (f
->root_window
), &r
);
3698 if (WINDOWP (f
->tool_bar_window
))
3699 mouse_face_overwritten_p
3700 |= expose_window (XWINDOW (f
->tool_bar_window
), &r
);
3702 /* Some window managers support a focus-follows-mouse style with
3703 delayed raising of frames. Imagine a partially obscured frame,
3704 and moving the mouse into partially obscured mouse-face on that
3705 frame. The visible part of the mouse-face will be highlighted,
3706 then the WM raises the obscured frame. With at least one WM, KDE
3707 2.1, Emacs is not getting any event for the raising of the frame
3708 (even tried with SubstructureRedirectMask), only Expose events.
3709 These expose events will draw text normally, i.e. not
3710 highlighted. Which means we must redo the highlight here.
3711 Subsume it under ``we love X''. --gerd 2001-08-15 */
3712 /* Included in Windows version because Windows most likely does not
3713 do the right thing if any third party tool offers
3714 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
3715 if (mouse_face_overwritten_p
&& !FRAME_GARBAGED_P (f
))
3717 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
3718 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3720 int x
= dpyinfo
->mouse_face_mouse_x
;
3721 int y
= dpyinfo
->mouse_face_mouse_y
;
3722 clear_mouse_face (dpyinfo
);
3723 note_mouse_highlight (f
, x
, y
);
3729 /* Redraw (parts) of all windows in the window tree rooted at W that
3730 intersect R. R contains frame pixel coordinates. */
3733 expose_window_tree (w
, r
)
3737 struct frame
*f
= XFRAME (w
->frame
);
3738 int mouse_face_overwritten_p
= 0;
3740 while (w
&& !FRAME_GARBAGED_P (f
))
3742 if (!NILP (w
->hchild
))
3743 mouse_face_overwritten_p
3744 |= expose_window_tree (XWINDOW (w
->hchild
), r
);
3745 else if (!NILP (w
->vchild
))
3746 mouse_face_overwritten_p
3747 |= expose_window_tree (XWINDOW (w
->vchild
), r
);
3749 mouse_face_overwritten_p
|= expose_window (w
, r
);
3751 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
3754 return mouse_face_overwritten_p
;
3758 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
3759 which intersects rectangle R. R is in window-relative coordinates. */
3762 expose_area (w
, row
, r
, area
)
3764 struct glyph_row
*row
;
3766 enum glyph_row_area area
;
3768 struct glyph
*first
= row
->glyphs
[area
];
3769 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
3771 int first_x
, start_x
, x
;
3773 if (area
== TEXT_AREA
&& row
->fill_line_p
)
3774 /* If row extends face to end of line write the whole line. */
3775 x_draw_glyphs (w
, 0, row
, area
,
3777 DRAW_NORMAL_TEXT
, 0);
3780 /* Set START_X to the window-relative start position for drawing glyphs of
3781 AREA. The first glyph of the text area can be partially visible.
3782 The first glyphs of other areas cannot. */
3783 if (area
== LEFT_MARGIN_AREA
)
3785 else if (area
== TEXT_AREA
)
3786 start_x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
3788 start_x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
3789 + window_box_width (w
, TEXT_AREA
));
3792 /* Find the first glyph that must be redrawn. */
3794 && x
+ first
->pixel_width
< r
->left
)
3796 x
+= first
->pixel_width
;
3800 /* Find the last one. */
3806 x
+= last
->pixel_width
;
3812 x_draw_glyphs (w
, first_x
- start_x
, row
, area
,
3813 first
- row
->glyphs
[area
],
3814 last
- row
->glyphs
[area
],
3815 DRAW_NORMAL_TEXT
, 0);
3820 /* Redraw the parts of the glyph row ROW on window W intersecting
3821 rectangle R. R is in window-relative coordinates. Value is
3822 non-zero if mouse face was overwritten. */
3825 expose_line (w
, row
, r
)
3827 struct glyph_row
*row
;
3830 xassert (row
->enabled_p
);
3832 if (row
->mode_line_p
|| w
->pseudo_window_p
)
3833 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
3834 DRAW_NORMAL_TEXT
, 0);
3837 if (row
->used
[LEFT_MARGIN_AREA
])
3838 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
3839 if (row
->used
[TEXT_AREA
])
3840 expose_area (w
, row
, r
, TEXT_AREA
);
3841 if (row
->used
[RIGHT_MARGIN_AREA
])
3842 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
3843 draw_row_fringe_bitmaps (w
, row
);
3846 return row
->mouse_face_p
;
3850 /* Return non-zero if W's cursor intersects rectangle R. */
3853 x_phys_cursor_in_rect_p (w
, r
)
3858 struct glyph
*cursor_glyph
;
3860 cursor_glyph
= get_phys_cursor_glyph (w
);
3863 cr
.left
= w
->phys_cursor
.x
;
3864 cr
.top
= w
->phys_cursor
.y
;
3865 cr
.right
= cr
.left
+ cursor_glyph
->pixel_width
;
3866 cr
.bottom
= cr
.top
+ w
->phys_cursor_height
;
3867 return x_intersect_rectangles (&cr
, r
, &result
);
3874 /* Redraw those parts of glyphs rows during expose event handling that
3875 overlap other rows. Redrawing of an exposed line writes over parts
3876 of lines overlapping that exposed line; this function fixes that.
3878 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
3879 row in W's current matrix that is exposed and overlaps other rows.
3880 LAST_OVERLAPPING_ROW is the last such row. */
3883 expose_overlaps (w
, first_overlapping_row
, last_overlapping_row
)
3885 struct glyph_row
*first_overlapping_row
;
3886 struct glyph_row
*last_overlapping_row
;
3888 struct glyph_row
*row
;
3890 for (row
= first_overlapping_row
; row
<= last_overlapping_row
; ++row
)
3891 if (row
->overlapping_p
)
3893 xassert (row
->enabled_p
&& !row
->mode_line_p
);
3895 if (row
->used
[LEFT_MARGIN_AREA
])
3896 x_fix_overlapping_area (w
, row
, LEFT_MARGIN_AREA
);
3898 if (row
->used
[TEXT_AREA
])
3899 x_fix_overlapping_area (w
, row
, TEXT_AREA
);
3901 if (row
->used
[RIGHT_MARGIN_AREA
])
3902 x_fix_overlapping_area (w
, row
, RIGHT_MARGIN_AREA
);
3907 /* Redraw the part of window W intersection rectangle FR. Pixel
3908 coordinates in FR are frame-relative. Call this function with
3909 input blocked. Value is non-zero if the exposure overwrites
3913 expose_window (w
, fr
)
3917 struct frame
*f
= XFRAME (w
->frame
);
3919 int mouse_face_overwritten_p
= 0;
3921 /* If window is not yet fully initialized, do nothing. This can
3922 happen when toolkit scroll bars are used and a window is split.
3923 Reconfiguring the scroll bar will generate an expose for a newly
3925 if (w
->current_matrix
== NULL
)
3928 /* When we're currently updating the window, display and current
3929 matrix usually don't agree. Arrange for a thorough display
3931 if (w
== updated_window
)
3933 SET_FRAME_GARBAGED (f
);
3937 /* Frame-relative pixel rectangle of W. */
3938 wr
.left
= XFASTINT (w
->left
) * CANON_X_UNIT (f
);
3939 wr
.top
= XFASTINT (w
->top
) * CANON_Y_UNIT (f
);
3940 wr
.right
= wr
.left
+ XFASTINT (w
->width
) * CANON_X_UNIT (f
);
3941 wr
.bottom
= wr
.top
+ XFASTINT (w
->height
) * CANON_Y_UNIT (f
);
3943 if (x_intersect_rectangles (fr
, &wr
, &r
))
3945 int yb
= window_text_bottom_y (w
);
3946 struct glyph_row
*row
;
3947 int cursor_cleared_p
;
3948 struct glyph_row
*first_overlapping_row
, *last_overlapping_row
;
3950 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
3951 r
.left
, r
.top
, r
.right
, r
.bottom
));
3953 /* Convert to window coordinates. */
3954 r
.left
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.left
);
3955 r
.right
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.right
);
3956 r
.top
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.top
);
3957 r
.bottom
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.bottom
);
3959 /* Turn off the cursor. */
3960 if (!w
->pseudo_window_p
3961 && x_phys_cursor_in_rect_p (w
, &r
))
3964 cursor_cleared_p
= 1;
3967 cursor_cleared_p
= 0;
3969 /* Update lines intersecting rectangle R. */
3970 first_overlapping_row
= last_overlapping_row
= NULL
;
3971 for (row
= w
->current_matrix
->rows
;
3976 int y1
= MATRIX_ROW_BOTTOM_Y (row
);
3978 if ((y0
>= r
.top
&& y0
< r
.bottom
)
3979 || (y1
> r
.top
&& y1
< r
.bottom
)
3980 || (r
.top
>= y0
&& r
.top
< y1
)
3981 || (r
.bottom
> y0
&& r
.bottom
< y1
))
3983 if (row
->overlapping_p
)
3985 if (first_overlapping_row
== NULL
)
3986 first_overlapping_row
= row
;
3987 last_overlapping_row
= row
;
3990 if (expose_line (w
, row
, &r
))
3991 mouse_face_overwritten_p
= 1;
3998 /* Display the mode line if there is one. */
3999 if (WINDOW_WANTS_MODELINE_P (w
)
4000 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
4002 && row
->y
< r
.bottom
)
4004 if (expose_line (w
, row
, &r
))
4005 mouse_face_overwritten_p
= 1;
4008 if (!w
->pseudo_window_p
)
4010 /* Fix the display of overlapping rows. */
4011 if (first_overlapping_row
)
4012 expose_overlaps (w
, first_overlapping_row
, last_overlapping_row
);
4014 /* Draw border between windows. */
4015 x_draw_vertical_border (w
);
4017 /* Turn the cursor on again. */
4018 if (cursor_cleared_p
)
4019 x_update_window_cursor (w
, 1);
4023 /* Display scroll bar for this window. */
4024 if (!NILP (w
->vertical_scroll_bar
))
4027 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w
->vertical_scroll_bar
));
4032 return mouse_face_overwritten_p
;
4036 x_intersect_rectangles (r1
, r2
, result
)
4037 Rect
*r1
, *r2
, *result
;
4040 Rect
*upper
, *lower
;
4041 int intersection_p
= 0;
4043 /* Rerrange so that R1 is the left-most rectangle. */
4044 if (r1
->left
< r2
->left
)
4045 left
= r1
, right
= r2
;
4047 left
= r2
, right
= r1
;
4049 /* X0 of the intersection is right.x0, if this is inside R1,
4050 otherwise there is no intersection. */
4051 if (right
->left
<= left
->right
)
4053 result
->left
= right
->left
;
4055 /* The right end of the intersection is the minimum of the
4056 the right ends of left and right. */
4057 result
->right
= min (left
->right
, right
->right
);
4059 /* Same game for Y. */
4060 if (r1
->top
< r2
->top
)
4061 upper
= r1
, lower
= r2
;
4063 upper
= r2
, lower
= r1
;
4065 /* The upper end of the intersection is lower.y0, if this is inside
4066 of upper. Otherwise, there is no intersection. */
4067 if (lower
->top
<= upper
->bottom
)
4069 result
->top
= lower
->top
;
4071 /* The lower end of the intersection is the minimum of the lower
4072 ends of upper and lower. */
4073 result
->bottom
= min (lower
->bottom
, upper
->bottom
);
4078 return intersection_p
;
4089 x_update_cursor (f
, 1);
4093 frame_unhighlight (f
)
4096 x_update_cursor (f
, 1);
4099 /* The focus has changed. Update the frames as necessary to reflect
4100 the new situation. Note that we can't change the selected frame
4101 here, because the Lisp code we are interrupting might become confused.
4102 Each event gets marked with the frame in which it occurred, so the
4103 Lisp code can tell when the switch took place by examining the events. */
4106 x_new_focus_frame (dpyinfo
, frame
)
4107 struct x_display_info
*dpyinfo
;
4108 struct frame
*frame
;
4110 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4112 if (frame
!= dpyinfo
->x_focus_frame
)
4114 /* Set this before calling other routines, so that they see
4115 the correct value of x_focus_frame. */
4116 dpyinfo
->x_focus_frame
= frame
;
4118 if (old_focus
&& old_focus
->auto_lower
)
4119 x_lower_frame (old_focus
);
4122 selected_frame
= frame
;
4123 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
4125 Fselect_window (selected_frame
->selected_window
);
4126 choose_minibuf_frame ();
4129 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4130 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4132 pending_autoraise_frame
= 0;
4135 x_frame_rehighlight (dpyinfo
);
4138 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4141 x_mouse_leave (dpyinfo
)
4142 struct x_display_info
*dpyinfo
;
4144 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4147 /* The focus has changed, or we have redirected a frame's focus to
4148 another frame (this happens when a frame uses a surrogate
4149 mini-buffer frame). Shift the highlight as appropriate.
4151 The FRAME argument doesn't necessarily have anything to do with which
4152 frame is being highlighted or un-highlighted; we only use it to find
4153 the appropriate X display info. */
4156 XTframe_rehighlight (frame
)
4157 struct frame
*frame
;
4159 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
4163 x_frame_rehighlight (dpyinfo
)
4164 struct x_display_info
*dpyinfo
;
4166 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4168 if (dpyinfo
->x_focus_frame
)
4170 dpyinfo
->x_highlight_frame
4171 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4172 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4173 : dpyinfo
->x_focus_frame
);
4174 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4176 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
4177 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4181 dpyinfo
->x_highlight_frame
= 0;
4183 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4186 frame_unhighlight (old_highlight
);
4187 if (dpyinfo
->x_highlight_frame
)
4188 frame_highlight (dpyinfo
->x_highlight_frame
);
4194 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
4196 #if 0 /* MAC_TODO */
4197 /* Initialize mode_switch_bit and modifier_meaning. */
4199 x_find_modifier_meanings (dpyinfo
)
4200 struct x_display_info
*dpyinfo
;
4202 int min_code
, max_code
;
4205 XModifierKeymap
*mods
;
4207 dpyinfo
->meta_mod_mask
= 0;
4208 dpyinfo
->shift_lock_mask
= 0;
4209 dpyinfo
->alt_mod_mask
= 0;
4210 dpyinfo
->super_mod_mask
= 0;
4211 dpyinfo
->hyper_mod_mask
= 0;
4214 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
4216 min_code
= dpyinfo
->display
->min_keycode
;
4217 max_code
= dpyinfo
->display
->max_keycode
;
4220 syms
= XGetKeyboardMapping (dpyinfo
->display
,
4221 min_code
, max_code
- min_code
+ 1,
4223 mods
= XGetModifierMapping (dpyinfo
->display
);
4225 /* Scan the modifier table to see which modifier bits the Meta and
4226 Alt keysyms are on. */
4228 int row
, col
; /* The row and column in the modifier table. */
4230 for (row
= 3; row
< 8; row
++)
4231 for (col
= 0; col
< mods
->max_keypermod
; col
++)
4234 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
4236 /* Zeroes are used for filler. Skip them. */
4240 /* Are any of this keycode's keysyms a meta key? */
4244 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
4246 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
4252 dpyinfo
->meta_mod_mask
|= (1 << row
);
4257 dpyinfo
->alt_mod_mask
|= (1 << row
);
4262 dpyinfo
->hyper_mod_mask
|= (1 << row
);
4267 dpyinfo
->super_mod_mask
|= (1 << row
);
4271 /* Ignore this if it's not on the lock modifier. */
4272 if ((1 << row
) == LockMask
)
4273 dpyinfo
->shift_lock_mask
= LockMask
;
4281 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
4282 if (! dpyinfo
->meta_mod_mask
)
4284 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
4285 dpyinfo
->alt_mod_mask
= 0;
4288 /* If some keys are both alt and meta,
4289 make them just meta, not alt. */
4290 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
4292 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4295 XFree ((char *) syms
);
4296 XFreeModifiermap (mods
);
4299 #endif /* MAC_TODO */
4301 /* Convert between the modifier bits X uses and the modifier bits
4305 x_mac_to_emacs_modifiers (dpyinfo
, state
)
4306 struct x_display_info
*dpyinfo
;
4307 unsigned short state
;
4309 return (((state
& shiftKey
) ? shift_modifier
: 0)
4310 | ((state
& controlKey
) ? ctrl_modifier
: 0)
4311 | ((state
& cmdKey
) ? meta_modifier
: 0)
4312 | ((state
& optionKey
) ? alt_modifier
: 0));
4315 #if 0 /* MAC_TODO */
4316 static unsigned short
4317 x_emacs_to_x_modifiers (dpyinfo
, state
)
4318 struct x_display_info
*dpyinfo
;
4321 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
4322 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
4323 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
4324 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4325 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4326 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
4328 #endif /* MAC_TODO */
4330 /* Convert a keysym to its name. */
4333 x_get_keysym_name (keysym
)
4340 value
= XKeysymToString (keysym
);
4351 /* Mouse clicks and mouse movement. Rah. */
4353 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
4354 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
4355 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
4356 not force the value into range. */
4359 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
4361 register int pix_x
, pix_y
;
4362 register int *x
, *y
;
4366 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
4367 if (NILP (Vwindow_system
))
4374 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
4375 even for negative values. */
4377 pix_x
-= FONT_WIDTH (FRAME_FONT (f
)) - 1;
4379 pix_y
-= (f
)->output_data
.mac
->line_height
- 1;
4381 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
4382 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
4386 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
4387 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
4388 bounds
->right
= bounds
->left
+ FONT_WIDTH (FRAME_FONT (f
)) - 1;
4389 bounds
->bottom
= bounds
->top
+ f
->output_data
.mac
->line_height
- 1;
4396 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
4397 pix_x
= FRAME_WINDOW_WIDTH (f
);
4401 else if (pix_y
> f
->height
)
4410 /* Given HPOS/VPOS in the current matrix of W, return corresponding
4411 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
4412 can't tell the positions because W's display is not up to date,
4416 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
4419 int *frame_x
, *frame_y
;
4423 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
4424 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
4426 if (display_completed
)
4428 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
4429 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
4430 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
4436 *frame_x
+= glyph
->pixel_width
;
4444 *frame_y
= *frame_x
= 0;
4448 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
4449 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
4454 /* Prepare a mouse-event in *RESULT for placement in the input queue.
4456 If the event is a button press, then note that we have grabbed
4460 construct_mouse_click (result
, event
, f
)
4461 struct input_event
*result
;
4467 result
->kind
= MOUSE_CLICK_EVENT
;
4468 result
->code
= 0; /* only one mouse button */
4469 result
->timestamp
= event
->when
;
4470 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
4472 mouseLoc
= event
->where
;
4474 #if TARGET_API_MAC_CARBON
4475 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
4477 SetPort (FRAME_MAC_WINDOW (f
));
4480 GlobalToLocal (&mouseLoc
);
4481 XSETINT (result
->x
, mouseLoc
.h
);
4482 XSETINT (result
->y
, mouseLoc
.v
);
4484 XSETFRAME (result
->frame_or_window
, f
);
4491 /* Function to report a mouse movement to the mainstream Emacs code.
4492 The input handler calls this.
4494 We have received a mouse movement event, which is given in *event.
4495 If the mouse is over a different glyph than it was last time, tell
4496 the mainstream emacs code by setting mouse_moved. If not, ask for
4497 another motion event, so we can check again the next time it moves. */
4499 static Point last_mouse_motion_position
;
4500 static Lisp_Object last_mouse_motion_frame
;
4503 note_mouse_movement (frame
, pos
)
4507 #if TARGET_API_MAC_CARBON
4511 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4512 last_mouse_motion_position
= *pos
;
4513 XSETFRAME (last_mouse_motion_frame
, frame
);
4515 #if TARGET_API_MAC_CARBON
4516 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4518 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4521 frame
->mouse_moved
= 1;
4522 last_mouse_scroll_bar
= Qnil
;
4523 note_mouse_highlight (frame
, -1, -1);
4525 /* Has the mouse moved off the glyph it was on at the last sighting? */
4526 else if (pos
->h
< last_mouse_glyph
.left
4527 || pos
->h
>= last_mouse_glyph
.right
4528 || pos
->v
< last_mouse_glyph
.top
4529 || pos
->v
>= last_mouse_glyph
.bottom
)
4531 frame
->mouse_moved
= 1;
4532 last_mouse_scroll_bar
= Qnil
;
4533 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4537 /* This is used for debugging, to turn off note_mouse_highlight. */
4539 int disable_mouse_highlight
;
4543 /************************************************************************
4545 ************************************************************************/
4547 /* Find the glyph under window-relative coordinates X/Y in window W.
4548 Consider only glyphs from buffer text, i.e. no glyphs from overlay
4549 strings. Return in *HPOS and *VPOS the row and column number of
4550 the glyph found. Return in *AREA the glyph area containing X.
4551 Value is a pointer to the glyph found or null if X/Y is not on
4552 text, or we can't tell because W's current matrix is not up to
4555 static struct glyph
*
4556 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
, buffer_only_p
)
4559 int *hpos
, *vpos
, *area
;
4562 struct glyph
*glyph
, *end
;
4563 struct glyph_row
*row
= NULL
;
4564 int x0
, i
, left_area_width
;
4566 /* Find row containing Y. Give up if some row is not enabled. */
4567 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
4569 row
= MATRIX_ROW (w
->current_matrix
, i
);
4570 if (!row
->enabled_p
)
4572 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
4579 /* Give up if Y is not in the window. */
4580 if (i
== w
->current_matrix
->nrows
)
4583 /* Get the glyph area containing X. */
4584 if (w
->pseudo_window_p
)
4591 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
4592 if (x
< left_area_width
)
4594 *area
= LEFT_MARGIN_AREA
;
4597 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
4600 x0
= row
->x
+ left_area_width
;
4604 *area
= RIGHT_MARGIN_AREA
;
4605 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
4609 /* Find glyph containing X. */
4610 glyph
= row
->glyphs
[*area
];
4611 end
= glyph
+ row
->used
[*area
];
4614 if (x
< x0
+ glyph
->pixel_width
)
4616 if (w
->pseudo_window_p
)
4618 else if (!buffer_only_p
|| BUFFERP (glyph
->object
))
4622 x0
+= glyph
->pixel_width
;
4629 *hpos
= glyph
- row
->glyphs
[*area
];
4634 /* Convert frame-relative x/y to coordinates relative to window W.
4635 Takes pseudo-windows into account. */
4638 frame_to_window_pixel_xy (w
, x
, y
)
4642 if (w
->pseudo_window_p
)
4644 /* A pseudo-window is always full-width, and starts at the
4645 left edge of the frame, plus a frame border. */
4646 struct frame
*f
= XFRAME (w
->frame
);
4647 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
4648 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
4652 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
4653 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
4658 /* Take proper action when mouse has moved to the mode or header line of
4659 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
4660 mode line. X is relative to the start of the text display area of
4661 W, so the width of fringes and scroll bars must be subtracted
4662 to get a position relative to the start of the mode line. */
4665 note_mode_line_highlight (w
, x
, mode_line_p
)
4669 struct frame
*f
= XFRAME (w
->frame
);
4670 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4671 struct Cursor
*cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
4672 struct glyph_row
*row
;
4675 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
4677 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
4681 struct glyph
*glyph
, *end
;
4682 Lisp_Object help
, map
;
4685 /* Find the glyph under X. */
4686 glyph
= row
->glyphs
[TEXT_AREA
];
4687 end
= glyph
+ row
->used
[TEXT_AREA
];
4688 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
4689 + FRAME_X_LEFT_FRINGE_WIDTH (f
));
4692 && x
>= x0
+ glyph
->pixel_width
)
4694 x0
+= glyph
->pixel_width
;
4699 && STRINGP (glyph
->object
)
4700 && STRING_INTERVALS (glyph
->object
)
4701 && glyph
->charpos
>= 0
4702 && glyph
->charpos
< SCHARS (glyph
->object
))
4704 /* If we're on a string with `help-echo' text property,
4705 arrange for the help to be displayed. This is done by
4706 setting the global variable help_echo to the help string. */
4707 help
= Fget_text_property (make_number (glyph
->charpos
),
4708 Qhelp_echo
, glyph
->object
);
4712 XSETWINDOW (help_echo_window
, w
);
4713 help_echo_object
= glyph
->object
;
4714 help_echo_pos
= glyph
->charpos
;
4717 /* Change the mouse pointer according to what is under X/Y. */
4718 map
= Fget_text_property (make_number (glyph
->charpos
),
4719 Qlocal_map
, glyph
->object
);
4721 cursor
= f
->output_data
.mac
->nontext_cursor
;
4724 map
= Fget_text_property (make_number (glyph
->charpos
),
4725 Qkeymap
, glyph
->object
);
4727 cursor
= f
->output_data
.mac
->nontext_cursor
;
4732 #if 0 /* MAC_TODO: mouse cursor */
4733 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
4738 /* Take proper action when the mouse has moved to position X, Y on
4739 frame F as regards highlighting characters that have mouse-face
4740 properties. Also de-highlighting chars where the mouse was before.
4741 X and Y can be negative or out of range. */
4744 note_mouse_highlight (f
, x
, y
)
4748 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4755 /* When a menu is active, don't highlight because this looks odd. */
4756 if (popup_activated ())
4760 if (NILP (Vmouse_highlight
)
4761 || !f
->glyphs_initialized_p
)
4764 dpyinfo
->mouse_face_mouse_x
= x
;
4765 dpyinfo
->mouse_face_mouse_y
= y
;
4766 dpyinfo
->mouse_face_mouse_frame
= f
;
4768 if (dpyinfo
->mouse_face_defer
)
4773 dpyinfo
->mouse_face_deferred_gc
= 1;
4777 /* Which window is that in? */
4778 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
4780 /* If we were displaying active text in another window, clear that. */
4781 if (! EQ (window
, dpyinfo
->mouse_face_window
))
4782 clear_mouse_face (dpyinfo
);
4784 /* Not on a window -> return. */
4785 if (!WINDOWP (window
))
4788 /* Reset help_echo. It will get recomputed below. */
4791 /* Convert to window-relative pixel coordinates. */
4792 w
= XWINDOW (window
);
4793 frame_to_window_pixel_xy (w
, &x
, &y
);
4795 /* Handle tool-bar window differently since it doesn't display a
4797 if (EQ (window
, f
->tool_bar_window
))
4799 note_tool_bar_highlight (f
, x
, y
);
4803 /* Mouse is on the mode or header line? */
4804 if (portion
== 1 || portion
== 3)
4806 note_mode_line_highlight (w
, x
, portion
== 1);
4809 #if 0 /* TODO: mouse cursor */
4811 cursor
= f
->output_data
.x
->horizontal_drag_cursor
;
4813 cursor
= f
->output_data
.x
->text_cursor
;
4815 /* Are we in a window whose display is up to date?
4816 And verify the buffer's text has not changed. */
4817 b
= XBUFFER (w
->buffer
);
4818 if (/* Within text portion of the window. */
4820 && EQ (w
->window_end_valid
, w
->buffer
)
4821 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
4822 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
4824 int hpos
, vpos
, pos
, i
, area
;
4825 struct glyph
*glyph
;
4827 Lisp_Object mouse_face
= Qnil
, overlay
= Qnil
, position
;
4828 Lisp_Object
*overlay_vec
= NULL
;
4830 struct buffer
*obuf
;
4831 int obegv
, ozv
, same_region
;
4833 /* Find the glyph under X/Y. */
4834 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
, 0);
4836 /* Clear mouse face if X/Y not over text. */
4838 || area
!= TEXT_AREA
4839 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
4841 clear_mouse_face (dpyinfo
);
4842 /* TODO: mouse cursor */
4846 pos
= glyph
->charpos
;
4847 object
= glyph
->object
;
4848 if (!STRINGP (object
) && !BUFFERP (object
))
4851 /* If we get an out-of-range value, return now; avoid an error. */
4852 if (BUFFERP (object
) && pos
> BUF_Z (b
))
4855 /* Make the window's buffer temporarily current for
4856 overlays_at and compute_char_face. */
4857 obuf
= current_buffer
;
4864 /* Is this char mouse-active or does it have help-echo? */
4865 position
= make_number (pos
);
4867 if (BUFFERP (object
))
4869 /* Put all the overlays we want in a vector in overlay_vec.
4870 Store the length in len. If there are more than 10, make
4871 enough space for all, and try again. */
4873 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
4874 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
, 0);
4875 if (noverlays
> len
)
4878 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
4879 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
,0);
4882 /* Sort overlays into increasing priority order. */
4883 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
4888 same_region
= (EQ (window
, dpyinfo
->mouse_face_window
)
4889 && vpos
>= dpyinfo
->mouse_face_beg_row
4890 && vpos
<= dpyinfo
->mouse_face_end_row
4891 && (vpos
> dpyinfo
->mouse_face_beg_row
4892 || hpos
>= dpyinfo
->mouse_face_beg_col
)
4893 && (vpos
< dpyinfo
->mouse_face_end_row
4894 || hpos
< dpyinfo
->mouse_face_end_col
4895 || dpyinfo
->mouse_face_past_end
));
4897 /* TODO: if (same_region)
4900 /* Check mouse-face highlighting. */
4902 /* If there exists an overlay with mouse-face overlapping
4903 the one we are currently highlighting, we have to
4904 check if we enter the overlapping overlay, and then
4906 || (OVERLAYP (dpyinfo
->mouse_face_overlay
)
4907 && mouse_face_overlay_overlaps (dpyinfo
->mouse_face_overlay
)))
4909 /* Find the highest priority overlay that has a mouse-face
4912 for (i
= noverlays
- 1; i
>= 0 && NILP (overlay
); --i
)
4914 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
4915 if (!NILP (mouse_face
))
4916 overlay
= overlay_vec
[i
];
4919 /* If we're actually highlighting the same overlay as
4920 before, there's no need to do that again. */
4922 && EQ (overlay
, dpyinfo
->mouse_face_overlay
))
4923 goto check_help_echo
;
4925 dpyinfo
->mouse_face_overlay
= overlay
;
4927 /* Clear the display of the old active region, if any. */
4928 clear_mouse_face (dpyinfo
);
4929 /* TODO: mouse cursor changes. */
4931 /* If no overlay applies, get a text property. */
4933 mouse_face
= Fget_text_property (position
, Qmouse_face
, object
);
4935 /* Handle the overlay case. */
4936 if (!NILP (overlay
))
4938 /* Find the range of text around this char that
4939 should be active. */
4940 Lisp_Object before
, after
;
4943 before
= Foverlay_start (overlay
);
4944 after
= Foverlay_end (overlay
);
4945 /* Record this as the current active region. */
4946 fast_find_position (w
, XFASTINT (before
),
4947 &dpyinfo
->mouse_face_beg_col
,
4948 &dpyinfo
->mouse_face_beg_row
,
4949 &dpyinfo
->mouse_face_beg_x
,
4950 &dpyinfo
->mouse_face_beg_y
, Qnil
);
4952 dpyinfo
->mouse_face_past_end
4953 = !fast_find_position (w
, XFASTINT (after
),
4954 &dpyinfo
->mouse_face_end_col
,
4955 &dpyinfo
->mouse_face_end_row
,
4956 &dpyinfo
->mouse_face_end_x
,
4957 &dpyinfo
->mouse_face_end_y
, Qnil
);
4958 dpyinfo
->mouse_face_window
= window
;
4960 dpyinfo
->mouse_face_face_id
4961 = face_at_buffer_position (w
, pos
, 0, 0,
4963 !dpyinfo
->mouse_face_hidden
);
4965 /* Display it as active. */
4966 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
4967 /* TODO: mouse cursor changes. */
4969 /* Handle the text property case. */
4970 else if (! NILP (mouse_face
) && BUFFERP (object
))
4972 /* Find the range of text around this char that
4973 should be active. */
4974 Lisp_Object before
, after
, beginning
, end
;
4977 beginning
= Fmarker_position (w
->start
);
4978 end
= make_number (BUF_Z (XBUFFER (object
))
4979 - XFASTINT (w
->window_end_pos
));
4981 = Fprevious_single_property_change (make_number (pos
+ 1),
4985 = Fnext_single_property_change (position
, Qmouse_face
,
4988 /* Record this as the current active region. */
4989 fast_find_position (w
, XFASTINT (before
),
4990 &dpyinfo
->mouse_face_beg_col
,
4991 &dpyinfo
->mouse_face_beg_row
,
4992 &dpyinfo
->mouse_face_beg_x
,
4993 &dpyinfo
->mouse_face_beg_y
, Qnil
);
4994 dpyinfo
->mouse_face_past_end
4995 = !fast_find_position (w
, XFASTINT (after
),
4996 &dpyinfo
->mouse_face_end_col
,
4997 &dpyinfo
->mouse_face_end_row
,
4998 &dpyinfo
->mouse_face_end_x
,
4999 &dpyinfo
->mouse_face_end_y
, Qnil
);
5000 dpyinfo
->mouse_face_window
= window
;
5002 if (BUFFERP (object
))
5003 dpyinfo
->mouse_face_face_id
5004 = face_at_buffer_position (w
, pos
, 0, 0,
5006 !dpyinfo
->mouse_face_hidden
);
5008 /* Display it as active. */
5009 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
5010 /* TODO: mouse cursor changes. */
5012 else if (!NILP (mouse_face
) && STRINGP (object
))
5017 b
= Fprevious_single_property_change (make_number (pos
+ 1),
5020 e
= Fnext_single_property_change (position
, Qmouse_face
,
5023 b
= make_number (0);
5025 e
= make_number (SCHARS (object
) - 1);
5026 fast_find_string_pos (w
, XINT (b
), object
,
5027 &dpyinfo
->mouse_face_beg_col
,
5028 &dpyinfo
->mouse_face_beg_row
,
5029 &dpyinfo
->mouse_face_beg_x
,
5030 &dpyinfo
->mouse_face_beg_y
, 0);
5031 fast_find_string_pos (w
, XINT (e
), object
,
5032 &dpyinfo
->mouse_face_end_col
,
5033 &dpyinfo
->mouse_face_end_row
,
5034 &dpyinfo
->mouse_face_end_x
,
5035 &dpyinfo
->mouse_face_end_y
, 1);
5036 dpyinfo
->mouse_face_past_end
= 0;
5037 dpyinfo
->mouse_face_window
= window
;
5038 dpyinfo
->mouse_face_face_id
5039 = face_at_string_position (w
, object
, pos
, 0, 0, 0, &ignore
,
5041 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
5042 /* TODO: mouse cursor changes. */
5044 else if (STRINGP (object
) && NILP (mouse_face
))
5046 /* A string which doesn't have mouse-face, but
5047 the text ``under'' it might have. */
5048 struct glyph_row
*r
= MATRIX_ROW (w
->current_matrix
, vpos
);
5049 int start
= MATRIX_ROW_START_CHARPOS (r
);
5051 pos
= string_buffer_position (w
, object
, start
);
5053 mouse_face
= get_char_property_and_overlay (make_number (pos
),
5057 if (!NILP (mouse_face
) && !NILP (overlay
))
5059 Lisp_Object before
= Foverlay_start (overlay
);
5060 Lisp_Object after
= Foverlay_end (overlay
);
5063 /* Note that we might not be able to find position
5064 BEFORE in the glyph matrix if the overlay is
5065 entirely covered by a `display' property. In
5066 this case, we overshoot. So let's stop in
5067 the glyph matrix before glyphs for OBJECT. */
5068 fast_find_position (w
, XFASTINT (before
),
5069 &dpyinfo
->mouse_face_beg_col
,
5070 &dpyinfo
->mouse_face_beg_row
,
5071 &dpyinfo
->mouse_face_beg_x
,
5072 &dpyinfo
->mouse_face_beg_y
,
5075 dpyinfo
->mouse_face_past_end
5076 = !fast_find_position (w
, XFASTINT (after
),
5077 &dpyinfo
->mouse_face_end_col
,
5078 &dpyinfo
->mouse_face_end_row
,
5079 &dpyinfo
->mouse_face_end_x
,
5080 &dpyinfo
->mouse_face_end_y
,
5082 dpyinfo
->mouse_face_window
= window
;
5083 dpyinfo
->mouse_face_face_id
5084 = face_at_buffer_position (w
, pos
, 0, 0,
5086 !dpyinfo
->mouse_face_hidden
);
5088 /* Display it as active. */
5089 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
5090 /* TODO: mouse cursor changes. */
5097 /* Look for a `help-echo' property. */
5099 Lisp_Object help
, overlay
;
5101 /* Check overlays first. */
5102 help
= overlay
= Qnil
;
5103 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
5105 overlay
= overlay_vec
[i
];
5106 help
= Foverlay_get (overlay
, Qhelp_echo
);
5112 help_echo_window
= window
;
5113 help_echo_object
= overlay
;
5114 help_echo_pos
= pos
;
5118 Lisp_Object object
= glyph
->object
;
5119 int charpos
= glyph
->charpos
;
5121 /* Try text properties. */
5122 if (STRINGP (object
)
5124 && charpos
< SCHARS (object
))
5126 help
= Fget_text_property (make_number (charpos
),
5127 Qhelp_echo
, object
);
5130 /* If the string itself doesn't specify a help-echo,
5131 see if the buffer text ``under'' it does. */
5133 = MATRIX_ROW (w
->current_matrix
, vpos
);
5134 int start
= MATRIX_ROW_START_CHARPOS (r
);
5135 int pos
= string_buffer_position (w
, object
, start
);
5138 help
= Fget_char_property (make_number (pos
),
5139 Qhelp_echo
, w
->buffer
);
5148 else if (BUFFERP (object
)
5151 help
= Fget_text_property (make_number (charpos
), Qhelp_echo
,
5157 help_echo_window
= window
;
5158 help_echo_object
= object
;
5159 help_echo_pos
= charpos
;
5166 current_buffer
= obuf
;
5170 /* TODO: mouse cursor changes. */
5175 redo_mouse_highlight ()
5177 if (!NILP (last_mouse_motion_frame
)
5178 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
5179 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
5180 last_mouse_motion_position
.h
,
5181 last_mouse_motion_position
.v
);
5186 /***********************************************************************
5188 ***********************************************************************/
5190 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
5191 struct glyph
**, int *, int *, int *));
5193 /* Tool-bar item index of the item on which a mouse button was pressed
5196 static int last_tool_bar_item
;
5199 /* Get information about the tool-bar item at position X/Y on frame F.
5200 Return in *GLYPH a pointer to the glyph of the tool-bar item in
5201 the current matrix of the tool-bar window of F, or NULL if not
5202 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
5203 item in F->current_tool_bar_items. Value is
5205 -1 if X/Y is not on a tool-bar item
5206 0 if X/Y is on the same item that was highlighted before.
5210 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
5213 struct glyph
**glyph
;
5214 int *hpos
, *vpos
, *prop_idx
;
5216 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5217 struct window
*w
= XWINDOW (f
->tool_bar_window
);
5220 /* Find the glyph under X/Y. */
5221 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
, 0);
5225 /* Get the start of this tool-bar item's properties in
5226 f->current_tool_bar_items. */
5227 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
5230 /* Is mouse on the highlighted item? */
5231 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
5232 && *vpos
>= dpyinfo
->mouse_face_beg_row
5233 && *vpos
<= dpyinfo
->mouse_face_end_row
5234 && (*vpos
> dpyinfo
->mouse_face_beg_row
5235 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
5236 && (*vpos
< dpyinfo
->mouse_face_end_row
5237 || *hpos
< dpyinfo
->mouse_face_end_col
5238 || dpyinfo
->mouse_face_past_end
))
5245 /* Handle mouse button event on the tool-bar of frame F, at
5246 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
5250 x_handle_tool_bar_click (f
, button_event
)
5252 EventRecord
*button_event
;
5254 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5255 struct window
*w
= XWINDOW (f
->tool_bar_window
);
5256 int hpos
, vpos
, prop_idx
;
5257 struct glyph
*glyph
;
5258 Lisp_Object enabled_p
;
5259 int x
= button_event
->where
.h
;
5260 int y
= button_event
->where
.v
;
5262 /* If not on the highlighted tool-bar item, return. */
5263 frame_to_window_pixel_xy (w
, &x
, &y
);
5264 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
5267 /* If item is disabled, do nothing. */
5268 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
5269 if (NILP (enabled_p
))
5272 if (button_event
->what
== mouseDown
)
5274 /* Show item in pressed state. */
5275 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
5276 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
5277 last_tool_bar_item
= prop_idx
;
5281 Lisp_Object key
, frame
;
5282 struct input_event event
;
5284 /* Show item in released state. */
5285 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
5286 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
5288 key
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_KEY
);
5290 XSETFRAME (frame
, f
);
5291 event
.kind
= TOOL_BAR_EVENT
;
5292 event
.frame_or_window
= frame
;
5294 kbd_buffer_store_event (&event
);
5296 event
.kind
= TOOL_BAR_EVENT
;
5297 event
.frame_or_window
= frame
;
5299 event
.modifiers
= x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
5300 button_event
->modifiers
);
5301 kbd_buffer_store_event (&event
);
5302 last_tool_bar_item
= -1;
5307 /* Possibly highlight a tool-bar item on frame F when mouse moves to
5308 tool-bar window-relative coordinates X/Y. Called from
5309 note_mouse_highlight. */
5312 note_tool_bar_highlight (f
, x
, y
)
5316 Lisp_Object window
= f
->tool_bar_window
;
5317 struct window
*w
= XWINDOW (window
);
5318 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5320 struct glyph
*glyph
;
5321 struct glyph_row
*row
;
5323 Lisp_Object enabled_p
;
5325 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
5326 int mouse_down_p
, rc
;
5328 /* Function note_mouse_highlight is called with negative x(y
5329 values when mouse moves outside of the frame. */
5330 if (x
<= 0 || y
<= 0)
5332 clear_mouse_face (dpyinfo
);
5336 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
5339 /* Not on tool-bar item. */
5340 clear_mouse_face (dpyinfo
);
5344 /* On same tool-bar item as before. */
5347 clear_mouse_face (dpyinfo
);
5349 /* Mouse is down, but on different tool-bar item? */
5350 mouse_down_p
= (dpyinfo
->grabbed
5351 && f
== last_mouse_frame
5352 && FRAME_LIVE_P (f
));
5354 && last_tool_bar_item
!= prop_idx
)
5357 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
5358 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
5360 /* If tool-bar item is not enabled, don't highlight it. */
5361 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
5362 if (!NILP (enabled_p
))
5364 /* Compute the x-position of the glyph. In front and past the
5365 image is a space. We include this is the highlighted area. */
5366 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
5367 for (i
= x
= 0; i
< hpos
; ++i
)
5368 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
5370 /* Record this as the current active region. */
5371 dpyinfo
->mouse_face_beg_col
= hpos
;
5372 dpyinfo
->mouse_face_beg_row
= vpos
;
5373 dpyinfo
->mouse_face_beg_x
= x
;
5374 dpyinfo
->mouse_face_beg_y
= row
->y
;
5375 dpyinfo
->mouse_face_past_end
= 0;
5377 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
5378 dpyinfo
->mouse_face_end_row
= vpos
;
5379 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
5380 dpyinfo
->mouse_face_end_y
= row
->y
;
5381 dpyinfo
->mouse_face_window
= window
;
5382 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
5384 /* Display it as active. */
5385 show_mouse_face (dpyinfo
, draw
);
5386 dpyinfo
->mouse_face_image_state
= draw
;
5391 /* Set help_echo to a help string.to display for this tool-bar item.
5392 XTread_socket does the rest. */
5393 help_echo_object
= help_echo_window
= Qnil
;
5395 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_HELP
);
5396 if (NILP (help_echo
))
5397 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_CAPTION
);
5402 /* Find the glyph matrix position of buffer position CHARPOS in window
5403 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
5404 current glyphs must be up to date. If CHARPOS is above window
5405 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
5406 of last line in W. In the row containing CHARPOS, stop before glyphs
5407 having STOP as object. */
5409 #if 0 /* This is a version of fast_find_position that's more correct
5410 in the presence of hscrolling, for example. I didn't install
5411 it right away because the problem fixed is minor, it failed
5412 in 20.x as well, and I think it's too risky to install
5413 so near the release of 21.1. 2001-09-25 gerd. */
5416 fast_find_position (w
, charpos
, hpos
, vpos
, x
, y
, stop
)
5419 int *hpos
, *vpos
, *x
, *y
;
5422 struct glyph_row
*row
, *first
;
5423 struct glyph
*glyph
, *end
;
5424 int i
, past_end
= 0;
5426 first
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
5427 row
= row_containing_pos (w
, charpos
, first
, NULL
, 0);
5430 if (charpos
< MATRIX_ROW_START_CHARPOS (first
))
5432 *x
= *y
= *hpos
= *vpos
= 0;
5437 row
= MATRIX_ROW (w
->current_matrix
, XFASTINT (w
->window_end_vpos
));
5444 *vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
5446 glyph
= row
->glyphs
[TEXT_AREA
];
5447 end
= glyph
+ row
->used
[TEXT_AREA
];
5449 /* Skip over glyphs not having an object at the start of the row.
5450 These are special glyphs like truncation marks on terminal
5452 if (row
->displays_text_p
)
5454 && INTEGERP (glyph
->object
)
5455 && !EQ (stop
, glyph
->object
)
5456 && glyph
->charpos
< 0)
5458 *x
+= glyph
->pixel_width
;
5463 && !INTEGERP (glyph
->object
)
5464 && !EQ (stop
, glyph
->object
)
5465 && (!BUFFERP (glyph
->object
)
5466 || glyph
->charpos
< charpos
))
5468 *x
+= glyph
->pixel_width
;
5472 *hpos
= glyph
- row
->glyphs
[TEXT_AREA
];
5479 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
, stop
)
5482 int *hpos
, *vpos
, *x
, *y
;
5487 int maybe_next_line_p
= 0;
5488 int line_start_position
;
5489 int yb
= window_text_bottom_y (w
);
5490 struct glyph_row
*row
, *best_row
;
5491 int row_vpos
, best_row_vpos
;
5494 row
= best_row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
5495 row_vpos
= best_row_vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
5499 if (row
->used
[TEXT_AREA
])
5500 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
5502 line_start_position
= 0;
5504 if (line_start_position
> pos
)
5506 /* If the position sought is the end of the buffer,
5507 don't include the blank lines at the bottom of the window. */
5508 else if (line_start_position
== pos
5509 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
5511 maybe_next_line_p
= 1;
5514 else if (line_start_position
> 0)
5517 best_row_vpos
= row_vpos
;
5520 if (row
->y
+ row
->height
>= yb
)
5527 /* Find the right column within BEST_ROW. */
5529 current_x
= best_row
->x
;
5530 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
5532 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
5533 int charpos
= glyph
->charpos
;
5535 if (BUFFERP (glyph
->object
))
5540 *vpos
= best_row_vpos
;
5545 else if (charpos
> pos
)
5548 else if (EQ (glyph
->object
, stop
))
5553 current_x
+= glyph
->pixel_width
;
5556 /* If we're looking for the end of the buffer,
5557 and we didn't find it in the line we scanned,
5558 use the start of the following line. */
5559 if (maybe_next_line_p
)
5564 current_x
= best_row
->x
;
5567 *vpos
= best_row_vpos
;
5568 *hpos
= lastcol
+ 1;
5577 /* Find the position of the glyph for position POS in OBJECT in
5578 window W's current matrix, and return in *X/*Y the pixel
5579 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
5581 RIGHT_P non-zero means return the position of the right edge of the
5582 glyph, RIGHT_P zero means return the left edge position.
5584 If no glyph for POS exists in the matrix, return the position of
5585 the glyph with the next smaller position that is in the matrix, if
5586 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
5587 exists in the matrix, return the position of the glyph with the
5588 next larger position in OBJECT.
5590 Value is non-zero if a glyph was found. */
5593 fast_find_string_pos (w
, pos
, object
, hpos
, vpos
, x
, y
, right_p
)
5597 int *hpos
, *vpos
, *x
, *y
;
5600 int yb
= window_text_bottom_y (w
);
5601 struct glyph_row
*r
;
5602 struct glyph
*best_glyph
= NULL
;
5603 struct glyph_row
*best_row
= NULL
;
5606 for (r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
5607 r
->enabled_p
&& r
->y
< yb
;
5610 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
5611 struct glyph
*e
= g
+ r
->used
[TEXT_AREA
];
5614 for (gx
= r
->x
; g
< e
; gx
+= g
->pixel_width
, ++g
)
5615 if (EQ (g
->object
, object
))
5617 if (g
->charpos
== pos
)
5624 else if (best_glyph
== NULL
5625 || ((abs (g
->charpos
- pos
)
5626 < abs (best_glyph
->charpos
- pos
))
5629 : g
->charpos
> pos
)))
5643 *hpos
= best_glyph
- best_row
->glyphs
[TEXT_AREA
];
5647 *x
+= best_glyph
->pixel_width
;
5652 *vpos
= best_row
- w
->current_matrix
->rows
;
5655 return best_glyph
!= NULL
;
5659 /* Display the active region described by mouse_face_*
5660 in its mouse-face if HL > 0, in its normal face if HL = 0. */
5663 show_mouse_face (dpyinfo
, draw
)
5664 struct mac_display_info
*dpyinfo
;
5665 enum draw_glyphs_face draw
;
5667 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
5668 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5670 if (/* If window is in the process of being destroyed, don't bother
5672 w
->current_matrix
!= NULL
5673 /* Don't update mouse highlight if hidden */
5674 && (draw
!= DRAW_MOUSE_FACE
|| !dpyinfo
->mouse_face_hidden
)
5675 /* Recognize when we are called to operate on rows that don't exist
5676 anymore. This can happen when a window is split. */
5677 && dpyinfo
->mouse_face_end_row
< w
->current_matrix
->nrows
)
5679 int phys_cursor_on_p
= w
->phys_cursor_on_p
;
5680 struct glyph_row
*row
, *first
, *last
;
5682 first
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_beg_row
);
5683 last
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_end_row
);
5685 for (row
= first
; row
<= last
&& row
->enabled_p
; ++row
)
5687 int start_hpos
, end_hpos
, start_x
;
5689 /* For all but the first row, the highlight starts at column 0. */
5692 start_hpos
= dpyinfo
->mouse_face_beg_col
;
5693 start_x
= dpyinfo
->mouse_face_beg_x
;
5702 end_hpos
= dpyinfo
->mouse_face_end_col
;
5704 end_hpos
= row
->used
[TEXT_AREA
];
5706 if (end_hpos
> start_hpos
)
5708 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
5709 start_hpos
, end_hpos
, draw
, 0);
5712 = draw
== DRAW_MOUSE_FACE
|| draw
== DRAW_IMAGE_RAISED
;
5716 /* When we've written over the cursor, arrange for it to
5717 be displayed again. */
5718 if (phys_cursor_on_p
&& !w
->phys_cursor_on_p
)
5719 x_display_cursor (w
, 1,
5720 w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
5721 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
5724 #if 0 /* MAC_TODO: mouse cursor */
5725 /* Change the mouse cursor. */
5726 if (draw
== DRAW_NORMAL_TEXT
)
5727 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5728 f
->output_data
.x
->text_cursor
);
5729 else if (draw
== DRAW_MOUSE_FACE
)
5730 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5731 f
->output_data
.x
->cross_cursor
);
5733 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5734 f
->output_data
.x
->nontext_cursor
);
5738 /* Clear out the mouse-highlighted active region.
5739 Redraw it un-highlighted first. */
5742 clear_mouse_face (dpyinfo
)
5743 struct mac_display_info
*dpyinfo
;
5747 if (! NILP (dpyinfo
->mouse_face_window
))
5749 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
5753 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5754 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5755 dpyinfo
->mouse_face_window
= Qnil
;
5756 dpyinfo
->mouse_face_overlay
= Qnil
;
5761 /* Clear any mouse-face on window W. This function is part of the
5762 redisplay interface, and is called from try_window_id and similar
5763 functions to ensure the mouse-highlight is off. */
5766 x_clear_mouse_face (w
)
5769 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
5773 XSETWINDOW (window
, w
);
5774 if (EQ (window
, dpyinfo
->mouse_face_window
))
5775 clear_mouse_face (dpyinfo
);
5780 /* Just discard the mouse face information for frame F, if any.
5781 This is used when the size of F is changed. */
5784 cancel_mouse_face (f
)
5788 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5790 window
= dpyinfo
->mouse_face_window
;
5791 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
5793 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5794 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5795 dpyinfo
->mouse_face_window
= Qnil
;
5799 static struct scroll_bar
*x_window_to_scroll_bar ();
5800 static void x_scroll_bar_report_motion ();
5801 static void x_check_fullscreen
P_ ((struct frame
*));
5802 static void x_check_fullscreen_move
P_ ((struct frame
*));
5803 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
5806 /* Try to determine frame pixel position and size of the glyph under
5807 frame pixel coordinates X/Y on frame F . Return the position and
5808 size in *RECT. Value is non-zero if we could compute these
5812 glyph_rect (f
, x
, y
, rect
)
5820 window
= window_from_coordinates (f
, x
, y
, &part
, 0);
5823 struct window
*w
= XWINDOW (window
);
5824 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
5825 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
5827 frame_to_window_pixel_xy (w
, &x
, &y
);
5829 for (; r
< end
&& r
->enabled_p
; ++r
)
5830 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
5832 /* Found the row at y. */
5833 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
5834 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
5837 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
5838 rect
->bottom
= rect
->top
+ r
->height
;
5842 /* x is to the left of the first glyph in the row. */
5843 rect
->left
= XINT (w
->left
);
5844 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
5848 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
5849 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
5851 /* x is on a glyph. */
5852 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
5853 rect
->right
= rect
->left
+ g
->pixel_width
;
5857 /* x is to the right of the last glyph in the row. */
5858 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
5859 rect
->right
= XINT (w
->left
) + XINT (w
->width
);
5864 /* The y is not on any row. */
5868 /* Record the position of the mouse in last_mouse_glyph. */
5870 remember_mouse_glyph (f1
, gx
, gy
)
5874 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
5876 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
5877 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
5879 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
5880 round down even for negative values. */
5886 /* This was the original code from XTmouse_position, but it seems
5887 to give the position of the glyph diagonally next to the one
5888 the mouse is over. */
5889 gx
= (gx
+ width
- 1) / width
* width
;
5890 gy
= (gy
+ height
- 1) / height
* height
;
5892 gx
= gx
/ width
* width
;
5893 gy
= gy
/ height
* height
;
5896 last_mouse_glyph
.left
= gx
;
5897 last_mouse_glyph
.top
= gy
;
5898 last_mouse_glyph
.right
= gx
+ width
;
5899 last_mouse_glyph
.bottom
= gy
+ height
;
5903 /* Return the current position of the mouse.
5904 *fp should be a frame which indicates which display to ask about.
5906 If the mouse movement started in a scroll bar, set *fp, *bar_window,
5907 and *part to the frame, window, and scroll bar part that the mouse
5908 is over. Set *x and *y to the portion and whole of the mouse's
5909 position on the scroll bar.
5911 If the mouse movement started elsewhere, set *fp to the frame the
5912 mouse is on, *bar_window to nil, and *x and *y to the character cell
5915 Set *time to the server time-stamp for the time at which the mouse
5916 was at this position.
5918 Don't store anything if we don't have a valid set of values to report.
5920 This clears the mouse_moved flag, so we can wait for the next mouse
5924 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
5927 Lisp_Object
*bar_window
;
5928 enum scroll_bar_part
*part
;
5930 unsigned long *time
;
5933 int ignore1
, ignore2
;
5934 WindowPtr wp
= FrontWindow ();
5936 Lisp_Object frame
, tail
;
5938 if (is_emacs_window(wp
))
5939 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
5943 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
5944 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
5947 /* Clear the mouse-moved flag for every frame on this display. */
5948 FOR_EACH_FRAME (tail
, frame
)
5949 XFRAME (frame
)->mouse_moved
= 0;
5951 last_mouse_scroll_bar
= Qnil
;
5953 #if TARGET_API_MAC_CARBON
5954 SetPort (GetWindowPort (wp
));
5959 GetMouse (&mouse_pos
);
5961 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
5962 &last_mouse_glyph
, insist
);
5965 *part
= scroll_bar_handle
;
5967 XSETINT (*x
, mouse_pos
.h
);
5968 XSETINT (*y
, mouse_pos
.v
);
5969 *time
= last_mouse_movement_time
;
5976 /************************************************************************
5977 Scroll bars, general
5978 ************************************************************************/
5980 /* Create a scroll bar and return the scroll bar vector for it. W is
5981 the Emacs window on which to create the scroll bar. TOP, LEFT,
5982 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5985 static struct scroll_bar
*
5986 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
5988 int top
, left
, width
, height
, disp_top
, disp_height
;
5990 struct frame
*f
= XFRAME (w
->frame
);
5991 struct scroll_bar
*bar
5992 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
6000 r
.right
= left
+ width
;
6001 r
.bottom
= disp_top
+ disp_height
;
6003 #ifdef TARGET_API_MAC_CARBON
6004 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
6005 kControlScrollBarProc
, 0L);
6007 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
6010 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
6011 SetControlReference (ch
, (long) bar
);
6013 XSETWINDOW (bar
->window
, w
);
6014 XSETINT (bar
->top
, top
);
6015 XSETINT (bar
->left
, left
);
6016 XSETINT (bar
->width
, width
);
6017 XSETINT (bar
->height
, height
);
6018 XSETINT (bar
->start
, 0);
6019 XSETINT (bar
->end
, 0);
6020 bar
->dragging
= Qnil
;
6022 /* Add bar to its frame's list of scroll bars. */
6023 bar
->next
= FRAME_SCROLL_BARS (f
);
6025 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
6026 if (!NILP (bar
->next
))
6027 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
6034 /* Draw BAR's handle in the proper position.
6036 If the handle is already drawn from START to END, don't bother
6037 redrawing it, unless REBUILD is non-zero; in that case, always
6038 redraw it. (REBUILD is handy for drawing the handle after expose
6041 Normally, we want to constrain the start and end of the handle to
6042 fit inside its rectangle, but if the user is dragging the scroll
6043 bar handle, we want to let them drag it down all the way, so that
6044 the bar's top is as far down as it goes; otherwise, there's no way
6045 to move to the very end of the buffer. */
6048 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
6049 struct scroll_bar
*bar
;
6053 int dragging
= ! NILP (bar
->dragging
);
6054 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
6055 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6056 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
6057 int length
= end
- start
;
6059 /* If the display is already accurate, do nothing. */
6061 && start
== XINT (bar
->start
)
6062 && end
== XINT (bar
->end
))
6067 /* Make sure the values are reasonable, and try to preserve the
6068 distance between start and end. */
6071 else if (start
> top_range
)
6073 end
= start
+ length
;
6077 else if (end
> top_range
&& ! dragging
)
6080 /* Store the adjusted setting in the scroll bar. */
6081 XSETINT (bar
->start
, start
);
6082 XSETINT (bar
->end
, end
);
6084 /* Clip the end position, just for display. */
6085 if (end
> top_range
)
6088 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
6089 top positions, to make sure the handle is always at least that
6090 many pixels tall. */
6091 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
6093 SetControlMinimum (ch
, 0);
6094 /* Don't inadvertently activate deactivated scroll bars */
6095 if (GetControlMaximum (ch
) != -1)
6096 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
6098 SetControlValue (ch
, start
);
6099 #if TARGET_API_MAC_CARBON
6100 SetControlViewSize (ch
, end
- start
);
6107 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
6111 x_scroll_bar_remove (bar
)
6112 struct scroll_bar
*bar
;
6114 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6118 /* Destroy the Mac scroll bar control */
6119 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
6121 /* Disassociate this scroll bar from its window. */
6122 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
6127 /* Set the handle of the vertical scroll bar for WINDOW to indicate
6128 that we are displaying PORTION characters out of a total of WHOLE
6129 characters, starting at POSITION. If WINDOW has no scroll bar,
6132 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
6134 int portion
, whole
, position
;
6136 struct frame
*f
= XFRAME (w
->frame
);
6137 struct scroll_bar
*bar
;
6138 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
6139 int window_x
, window_y
, window_width
, window_height
;
6141 /* Get window dimensions. */
6142 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
6147 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
6149 height
= window_height
;
6151 /* Compute the left edge of the scroll bar area. */
6152 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
6153 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
6155 left
= XFASTINT (w
->left
);
6156 left
*= CANON_X_UNIT (f
);
6157 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
6159 /* Compute the width of the scroll bar which might be less than
6160 the width of the area reserved for the scroll bar. */
6161 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
6162 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
6166 /* Compute the left edge of the scroll bar. */
6167 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
6168 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
6170 sb_left
= left
+ (width
- sb_width
) / 2;
6172 /* Adjustments according to Inside Macintosh to make it look nice */
6174 disp_height
= height
;
6180 else if (disp_top
== PIXEL_HEIGHT (f
) - 16)
6186 if (sb_left
+ sb_width
== PIXEL_WIDTH (f
))
6189 /* Does the scroll bar exist yet? */
6190 if (NILP (w
->vertical_scroll_bar
))
6193 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
6194 left
, top
, width
, height
, 0);
6196 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
6198 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
6202 /* It may just need to be moved and resized. */
6205 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
6206 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
6210 /* If already correctly positioned, do nothing. */
6211 if (XINT (bar
->left
) == sb_left
6212 && XINT (bar
->top
) == top
6213 && XINT (bar
->width
) == sb_width
6214 && XINT (bar
->height
) == height
)
6218 /* Clear areas not covered by the scroll bar because it's not as
6219 wide as the area reserved for it . This makes sure a
6220 previous mode line display is cleared after C-x 2 C-x 1, for
6222 int area_width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
6223 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
6224 left
, top
, area_width
, height
, 0);
6227 if (sb_left
+ sb_width
>= PIXEL_WIDTH (f
))
6228 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
6229 sb_left
- 1, top
, 1, height
, 0);
6233 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
6234 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
6238 /* Remember new settings. */
6239 XSETINT (bar
->left
, sb_left
);
6240 XSETINT (bar
->top
, top
);
6241 XSETINT (bar
->width
, sb_width
);
6242 XSETINT (bar
->height
, height
);
6248 /* Set the scroll bar's current state, unless we're currently being
6250 if (NILP (bar
->dragging
))
6252 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
6255 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
6258 int start
= ((double) position
* top_range
) / whole
;
6259 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
6260 x_scroll_bar_set_handle (bar
, start
, end
, 0);
6266 /* The following three hooks are used when we're doing a thorough
6267 redisplay of the frame. We don't explicitly know which scroll bars
6268 are going to be deleted, because keeping track of when windows go
6269 away is a real pain - "Can you say set-window-configuration, boys
6270 and girls?" Instead, we just assert at the beginning of redisplay
6271 that *all* scroll bars are to be removed, and then save a scroll bar
6272 from the fiery pit when we actually redisplay its window. */
6274 /* Arrange for all scroll bars on FRAME to be removed at the next call
6275 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
6276 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
6279 XTcondemn_scroll_bars (frame
)
6282 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
6283 while (! NILP (FRAME_SCROLL_BARS (frame
)))
6286 bar
= FRAME_SCROLL_BARS (frame
);
6287 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
6288 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
6289 XSCROLL_BAR (bar
)->prev
= Qnil
;
6290 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
6291 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
6292 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
6297 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
6298 Note that WINDOW isn't necessarily condemned at all. */
6301 XTredeem_scroll_bar (window
)
6302 struct window
*window
;
6304 struct scroll_bar
*bar
;
6306 /* We can't redeem this window's scroll bar if it doesn't have one. */
6307 if (NILP (window
->vertical_scroll_bar
))
6310 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
6312 /* Unlink it from the condemned list. */
6314 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
6316 if (NILP (bar
->prev
))
6318 /* If the prev pointer is nil, it must be the first in one of
6320 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
6321 /* It's not condemned. Everything's fine. */
6323 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
6324 window
->vertical_scroll_bar
))
6325 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
6327 /* If its prev pointer is nil, it must be at the front of
6328 one or the other! */
6332 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
6334 if (! NILP (bar
->next
))
6335 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
6337 bar
->next
= FRAME_SCROLL_BARS (f
);
6339 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
6340 if (! NILP (bar
->next
))
6341 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
6345 /* Remove all scroll bars on FRAME that haven't been saved since the
6346 last call to `*condemn_scroll_bars_hook'. */
6349 XTjudge_scroll_bars (f
)
6352 Lisp_Object bar
, next
;
6354 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
6356 /* Clear out the condemned list now so we won't try to process any
6357 more events on the hapless scroll bars. */
6358 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
6360 for (; ! NILP (bar
); bar
= next
)
6362 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
6364 x_scroll_bar_remove (b
);
6367 b
->next
= b
->prev
= Qnil
;
6370 /* Now there should be no references to the condemned scroll bars,
6371 and they should get garbage-collected. */
6376 activate_scroll_bars (frame
)
6382 bar
= FRAME_SCROLL_BARS (frame
);
6383 while (! NILP (bar
))
6385 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
6386 #ifdef TARGET_API_MAC_CARBON
6387 ActivateControl (ch
);
6389 SetControlMaximum (ch
,
6390 VERTICAL_SCROLL_BAR_TOP_RANGE (frame
,
6391 XINT (XSCROLL_BAR (bar
)
6394 bar
= XSCROLL_BAR (bar
)->next
;
6400 deactivate_scroll_bars (frame
)
6406 bar
= FRAME_SCROLL_BARS (frame
);
6407 while (! NILP (bar
))
6409 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
6410 #ifdef TARGET_API_MAC_CARBON
6411 DeactivateControl (ch
);
6413 SetControlMaximum (ch
, XINT (-1));
6415 bar
= XSCROLL_BAR (bar
)->next
;
6419 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
6420 is set to something other than NO_EVENT, it is enqueued.
6422 This may be called from a signal handler, so we have to ignore GC
6426 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
6427 struct scroll_bar
*bar
;
6430 struct input_event
*bufp
;
6432 if (! GC_WINDOWP (bar
->window
))
6435 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
6436 bufp
->frame_or_window
= bar
->window
;
6439 bar
->dragging
= Qnil
;
6443 case kControlUpButtonPart
:
6444 bufp
->part
= scroll_bar_up_arrow
;
6446 case kControlDownButtonPart
:
6447 bufp
->part
= scroll_bar_down_arrow
;
6449 case kControlPageUpPart
:
6450 bufp
->part
= scroll_bar_above_handle
;
6452 case kControlPageDownPart
:
6453 bufp
->part
= scroll_bar_below_handle
;
6455 #ifdef TARGET_API_MAC_CARBON
6458 case kControlIndicatorPart
:
6460 if (er
->what
== mouseDown
)
6461 bar
->dragging
= make_number (0);
6462 XSETVECTOR (last_mouse_scroll_bar
, bar
);
6463 bufp
->part
= scroll_bar_handle
;
6469 /* Handle some mouse motion while someone is dragging the scroll bar.
6471 This may be called from a signal handler, so we have to ignore GC
6475 x_scroll_bar_note_movement (bar
, y_pos
, t
)
6476 struct scroll_bar
*bar
;
6480 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
6482 last_mouse_movement_time
= t
;
6485 XSETVECTOR (last_mouse_scroll_bar
, bar
);
6487 /* If we're dragging the bar, display it. */
6488 if (! GC_NILP (bar
->dragging
))
6490 /* Where should the handle be now? */
6491 int new_start
= y_pos
- 24;
6493 if (new_start
!= XINT (bar
->start
))
6495 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
6497 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
6503 /* Return information to the user about the current position of the
6504 mouse on the scroll bar. */
6507 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
6509 Lisp_Object
*bar_window
;
6510 enum scroll_bar_part
*part
;
6512 unsigned long *time
;
6514 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
6515 WindowPtr wp
= FrontWindow ();
6517 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
6518 int win_y
, top_range
;
6520 #if TARGET_API_MAC_CARBON
6521 SetPort (GetWindowPort (wp
));
6526 GetMouse (&mouse_pos
);
6528 win_y
= mouse_pos
.v
- XINT (bar
->top
);
6529 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
6531 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
6535 if (! NILP (bar
->dragging
))
6536 win_y
-= XINT (bar
->dragging
);
6540 if (win_y
> top_range
)
6544 *bar_window
= bar
->window
;
6546 if (! NILP (bar
->dragging
))
6547 *part
= scroll_bar_handle
;
6548 else if (win_y
< XINT (bar
->start
))
6549 *part
= scroll_bar_above_handle
;
6550 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
6551 *part
= scroll_bar_handle
;
6553 *part
= scroll_bar_below_handle
;
6555 XSETINT (*x
, win_y
);
6556 XSETINT (*y
, top_range
);
6559 last_mouse_scroll_bar
= Qnil
;
6561 *time
= last_mouse_movement_time
;
6564 /***********************************************************************
6566 ***********************************************************************/
6568 /* Set clipping for output in glyph row ROW. W is the window in which
6569 we operate. GC is the graphics context to set clipping in.
6570 WHOLE_LINE_P non-zero means include the areas used for truncation
6571 mark display and alike in the clipping rectangle.
6573 ROW may be a text row or, e.g., a mode line. Text rows must be
6574 clipped to the interior of the window dedicated to text display,
6575 mode lines must be clipped to the whole window. */
6578 x_clip_to_row (w
, row
, gc
, whole_line_p
)
6580 struct glyph_row
*row
;
6584 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6586 int window_x
, window_y
, window_width
, window_height
;
6588 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
6590 clip_rect
.left
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
6591 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
6592 clip_rect
.top
= max (clip_rect
.top
, window_y
);
6593 clip_rect
.right
= clip_rect
.left
+ window_width
;
6594 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
6596 /* If clipping to the whole line, including trunc marks, extend
6597 the rectangle to the left and increase its width. */
6600 clip_rect
.left
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
6601 clip_rect
.right
+= FRAME_X_FRINGE_WIDTH (f
);
6604 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
6608 /* Draw a hollow box cursor on window W in glyph row ROW. */
6611 x_draw_hollow_cursor (w
, row
)
6613 struct glyph_row
*row
;
6615 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6616 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6617 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
6620 struct glyph
*cursor_glyph
;
6623 /* Compute frame-relative coordinates from window-relative
6625 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
6626 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
6627 + row
->ascent
- w
->phys_cursor_ascent
);
6628 h
= row
->height
- 1;
6630 /* Get the glyph the cursor is on. If we can't tell because
6631 the current matrix is invalid or such, give up. */
6632 cursor_glyph
= get_phys_cursor_glyph (w
);
6633 if (cursor_glyph
== NULL
)
6636 /* Compute the width of the rectangle to draw. If on a stretch
6637 glyph, and `x-stretch-block-cursor' is nil, don't draw a
6638 rectangle as wide as the glyph, but use a canonical character
6640 wd
= cursor_glyph
->pixel_width
- 1;
6641 if (cursor_glyph
->type
== STRETCH_GLYPH
6642 && !x_stretch_cursor_p
)
6643 wd
= min (CANON_X_UNIT (f
), wd
);
6645 /* The foreground of cursor_gc is typically the same as the normal
6646 background color, which can cause the cursor box to be invisible. */
6647 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6648 if (dpyinfo
->scratch_cursor_gc
)
6649 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
6651 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
6652 GCForeground
, &xgcv
);
6653 gc
= dpyinfo
->scratch_cursor_gc
;
6655 /* Set clipping, draw the rectangle, and reset clipping again. */
6656 x_clip_to_row (w
, row
, gc
, 0);
6657 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
6658 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
6662 /* Draw a bar cursor on window W in glyph row ROW.
6664 Implementation note: One would like to draw a bar cursor with an
6665 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6666 Unfortunately, I didn't find a font yet that has this property set.
6670 x_draw_bar_cursor (w
, row
, width
)
6672 struct glyph_row
*row
;
6675 /* If cursor hpos is out of bounds, don't draw garbage. This can
6676 happen in mini-buffer windows when switching between echo area
6677 glyphs and mini-buffer. */
6678 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
6680 struct frame
*f
= XFRAME (w
->frame
);
6681 struct glyph
*cursor_glyph
;
6689 cursor_glyph
= get_phys_cursor_glyph (w
);
6690 if (cursor_glyph
== NULL
)
6693 xgcv
.background
= f
->output_data
.mac
->cursor_pixel
;
6694 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
6695 mask
= GCForeground
| GCBackground
;
6696 dpy
= FRAME_MAC_DISPLAY (f
);
6697 window
= FRAME_MAC_WINDOW (f
);
6698 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
6701 XChangeGC (dpy
, gc
, mask
, &xgcv
);
6704 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
6705 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
6709 width
= FRAME_CURSOR_WIDTH (f
);
6711 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
6712 x_clip_to_row (w
, row
, gc
, 0);
6713 XFillRectangle (dpy
, window
, gc
,
6715 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
6716 min (cursor_glyph
->pixel_width
, width
),
6718 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
6723 /* Clear the cursor of window W to background color, and mark the
6724 cursor as not shown. This is used when the text where the cursor
6725 is is about to be rewritten. */
6731 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
6732 x_update_window_cursor (w
, 0);
6736 /* Draw the cursor glyph of window W in glyph row ROW. See the
6737 comment of x_draw_glyphs for the meaning of HL. */
6740 x_draw_phys_cursor_glyph (w
, row
, hl
)
6742 struct glyph_row
*row
;
6743 enum draw_glyphs_face hl
;
6745 /* If cursor hpos is out of bounds, don't draw garbage. This can
6746 happen in mini-buffer windows when switching between echo area
6747 glyphs and mini-buffer. */
6748 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
6750 int on_p
= w
->phys_cursor_on_p
;
6751 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
6752 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
6754 w
->phys_cursor_on_p
= on_p
;
6756 /* When we erase the cursor, and ROW is overlapped by other
6757 rows, make sure that these overlapping parts of other rows
6759 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
6761 if (row
> w
->current_matrix
->rows
6762 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
6763 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
6765 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
6766 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
6767 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
6773 /* Erase the image of a cursor of window W from the screen. */
6776 x_erase_phys_cursor (w
)
6779 struct frame
*f
= XFRAME (w
->frame
);
6780 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6781 int hpos
= w
->phys_cursor
.hpos
;
6782 int vpos
= w
->phys_cursor
.vpos
;
6783 int mouse_face_here_p
= 0;
6784 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
6785 struct glyph_row
*cursor_row
;
6786 struct glyph
*cursor_glyph
;
6787 enum draw_glyphs_face hl
;
6789 /* No cursor displayed or row invalidated => nothing to do on the
6791 if (w
->phys_cursor_type
== NO_CURSOR
)
6792 goto mark_cursor_off
;
6794 /* VPOS >= active_glyphs->nrows means that window has been resized.
6795 Don't bother to erase the cursor. */
6796 if (vpos
>= active_glyphs
->nrows
)
6797 goto mark_cursor_off
;
6799 /* If row containing cursor is marked invalid, there is nothing we
6801 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
6802 if (!cursor_row
->enabled_p
)
6803 goto mark_cursor_off
;
6805 /* If row is completely invisible, don't attempt to delete a cursor which
6806 isn't there. This may happen if cursor is at top of window, and
6807 we switch to a buffer with a header line in that window. */
6808 if (cursor_row
->visible_height
<= 0)
6809 goto mark_cursor_off
;
6811 /* This can happen when the new row is shorter than the old one.
6812 In this case, either x_draw_glyphs or clear_end_of_line
6813 should have cleared the cursor. Note that we wouldn't be
6814 able to erase the cursor in this case because we don't have a
6815 cursor glyph at hand. */
6816 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
6817 goto mark_cursor_off
;
6819 /* If the cursor is in the mouse face area, redisplay that when
6820 we clear the cursor. */
6821 if (! NILP (dpyinfo
->mouse_face_window
)
6822 && w
== XWINDOW (dpyinfo
->mouse_face_window
)
6823 && (vpos
> dpyinfo
->mouse_face_beg_row
6824 || (vpos
== dpyinfo
->mouse_face_beg_row
6825 && hpos
>= dpyinfo
->mouse_face_beg_col
))
6826 && (vpos
< dpyinfo
->mouse_face_end_row
6827 || (vpos
== dpyinfo
->mouse_face_end_row
6828 && hpos
< dpyinfo
->mouse_face_end_col
))
6829 /* Don't redraw the cursor's spot in mouse face if it is at the
6830 end of a line (on a newline). The cursor appears there, but
6831 mouse highlighting does not. */
6832 && cursor_row
->used
[TEXT_AREA
] > hpos
)
6833 mouse_face_here_p
= 1;
6835 /* Maybe clear the display under the cursor. */
6836 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
6839 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
6841 cursor_glyph
= get_phys_cursor_glyph (w
);
6842 if (cursor_glyph
== NULL
)
6843 goto mark_cursor_off
;
6845 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
6847 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
6849 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
6851 cursor_glyph
->pixel_width
,
6852 cursor_row
->visible_height
,
6856 /* Erase the cursor by redrawing the character underneath it. */
6857 if (mouse_face_here_p
)
6858 hl
= DRAW_MOUSE_FACE
;
6860 hl
= DRAW_NORMAL_TEXT
;
6861 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
6864 w
->phys_cursor_on_p
= 0;
6865 w
->phys_cursor_type
= NO_CURSOR
;
6869 /* Non-zero if physical cursor of window W is within mouse face. */
6872 cursor_in_mouse_face_p (w
)
6875 struct mac_display_info
*dpyinfo
6876 = FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
6877 int in_mouse_face
= 0;
6879 if (WINDOWP (dpyinfo
->mouse_face_window
)
6880 && XWINDOW (dpyinfo
->mouse_face_window
) == w
)
6882 int hpos
= w
->phys_cursor
.hpos
;
6883 int vpos
= w
->phys_cursor
.vpos
;
6885 if (vpos
>= dpyinfo
->mouse_face_beg_row
6886 && vpos
<= dpyinfo
->mouse_face_end_row
6887 && (vpos
> dpyinfo
->mouse_face_beg_row
6888 || hpos
>= dpyinfo
->mouse_face_beg_col
)
6889 && (vpos
< dpyinfo
->mouse_face_end_row
6890 || hpos
< dpyinfo
->mouse_face_end_col
6891 || dpyinfo
->mouse_face_past_end
))
6895 return in_mouse_face
;
6899 /* Display or clear cursor of window W. If ON is zero, clear the
6900 cursor. If it is non-zero, display the cursor. If ON is nonzero,
6901 where to put the cursor is specified by HPOS, VPOS, X and Y. */
6904 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
6906 int on
, hpos
, vpos
, x
, y
;
6908 struct frame
*f
= XFRAME (w
->frame
);
6909 int new_cursor_type
;
6910 int new_cursor_width
;
6912 struct glyph_matrix
*current_glyphs
;
6913 struct glyph_row
*glyph_row
;
6914 struct glyph
*glyph
;
6916 /* This is pointless on invisible frames, and dangerous on garbaged
6917 windows and frames; in the latter case, the frame or window may
6918 be in the midst of changing its size, and x and y may be off the
6920 if (! FRAME_VISIBLE_P (f
)
6921 || FRAME_GARBAGED_P (f
)
6922 || vpos
>= w
->current_matrix
->nrows
6923 || hpos
>= w
->current_matrix
->matrix_w
)
6926 /* If cursor is off and we want it off, return quickly. */
6927 if (!on
&& !w
->phys_cursor_on_p
)
6930 current_glyphs
= w
->current_matrix
;
6931 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
6932 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
6934 /* If cursor row is not enabled, we don't really know where to
6935 display the cursor. */
6936 if (!glyph_row
->enabled_p
)
6938 w
->phys_cursor_on_p
= 0;
6942 xassert (interrupt_input_blocked
);
6944 /* Set new_cursor_type to the cursor we want to be displayed. */
6945 new_cursor_type
= get_window_cursor_type (w
, &new_cursor_width
, &active_cursor
);
6948 /* If cursor is currently being shown and we don't want it to be or
6949 it is in the wrong place, or the cursor type is not what we want,
6951 if (w
->phys_cursor_on_p
6953 || w
->phys_cursor
.x
!= x
6954 || w
->phys_cursor
.y
!= y
6955 || new_cursor_type
!= w
->phys_cursor_type
6956 || ((new_cursor_type
== BAR_CURSOR
|| new_cursor_type
== HBAR_CURSOR
)
6957 && new_cursor_width
!= w
->phys_cursor_width
)))
6958 x_erase_phys_cursor (w
);
6960 /* If the cursor is now invisible and we want it to be visible,
6962 if (on
&& !w
->phys_cursor_on_p
)
6964 w
->phys_cursor_ascent
= glyph_row
->ascent
;
6965 w
->phys_cursor_height
= glyph_row
->height
;
6967 /* Set phys_cursor_.* before x_draw_.* is called because some
6968 of them may need the information. */
6969 w
->phys_cursor
.x
= x
;
6970 w
->phys_cursor
.y
= glyph_row
->y
;
6971 w
->phys_cursor
.hpos
= hpos
;
6972 w
->phys_cursor
.vpos
= vpos
;
6973 w
->phys_cursor_type
= new_cursor_type
;
6974 w
->phys_cursor_width
= new_cursor_width
;
6975 w
->phys_cursor_on_p
= 1;
6977 switch (new_cursor_type
)
6979 case HOLLOW_BOX_CURSOR
:
6980 x_draw_hollow_cursor (w
, glyph_row
);
6983 case FILLED_BOX_CURSOR
:
6984 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
6988 /* TODO. For now, just draw bar cursor. */
6990 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
);
7003 /* Display the cursor on window W, or clear it. X and Y are window
7004 relative pixel coordinates. HPOS and VPOS are glyph matrix
7005 positions. If W is not the selected window, display a hollow
7006 cursor. ON non-zero means display the cursor at X, Y which
7007 correspond to HPOS, VPOS, otherwise it is cleared. */
7010 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
7012 int on
, hpos
, vpos
, x
, y
;
7015 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
7020 /* Display the cursor on window W, or clear it, according to ON_P.
7021 Don't change the cursor's position. */
7024 x_update_cursor (f
, on_p
)
7028 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
7032 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
7033 in the window tree rooted at W. */
7036 x_update_cursor_in_window_tree (w
, on_p
)
7042 if (!NILP (w
->hchild
))
7043 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
7044 else if (!NILP (w
->vchild
))
7045 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
7047 x_update_window_cursor (w
, on_p
);
7049 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
7054 /* Switch the display of W's cursor on or off, according to the value
7058 x_update_window_cursor (w
, on
)
7062 /* Don't update cursor in windows whose frame is in the process
7063 of being deleted. */
7064 if (w
->current_matrix
)
7067 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
,
7068 w
->phys_cursor
.vpos
, w
->phys_cursor
.x
,
7079 #if 0 /* MAC_TODO: no icon support yet. */
7081 x_bitmap_icon (f
, icon
)
7087 if (FRAME_W32_WINDOW (f
) == 0)
7091 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
7092 else if (STRINGP (icon
))
7093 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
7094 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
7095 else if (SYMBOLP (icon
))
7099 if (EQ (icon
, intern ("application")))
7100 name
= (LPCTSTR
) IDI_APPLICATION
;
7101 else if (EQ (icon
, intern ("hand")))
7102 name
= (LPCTSTR
) IDI_HAND
;
7103 else if (EQ (icon
, intern ("question")))
7104 name
= (LPCTSTR
) IDI_QUESTION
;
7105 else if (EQ (icon
, intern ("exclamation")))
7106 name
= (LPCTSTR
) IDI_EXCLAMATION
;
7107 else if (EQ (icon
, intern ("asterisk")))
7108 name
= (LPCTSTR
) IDI_ASTERISK
;
7109 else if (EQ (icon
, intern ("winlogo")))
7110 name
= (LPCTSTR
) IDI_WINLOGO
;
7114 hicon
= LoadIcon (NULL
, name
);
7122 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
7127 #endif /* MAC_TODO */
7129 /************************************************************************
7131 ************************************************************************/
7133 /* Display Error Handling functions not used on W32. Listing them here
7134 helps diff stay in step when comparing w32term.c with xterm.c.
7136 x_error_catcher (display, error)
7137 x_catch_errors (dpy)
7138 x_catch_errors_unwind (old_val)
7139 x_check_errors (dpy, format)
7140 x_had_errors_p (dpy)
7141 x_clear_errors (dpy)
7142 x_uncatch_errors (dpy, count)
7144 x_connection_signal (signalnum)
7145 x_connection_closed (dpy, error_message)
7146 x_error_quitter (display, error)
7147 x_error_handler (display, error)
7148 x_io_error_quitter (display)
7153 /* Changing the font of the frame. */
7155 /* Give frame F the font named FONTNAME as its default font, and
7156 return the full name of that font. FONTNAME may be a wildcard
7157 pattern; in that case, we choose some font that fits the pattern.
7158 The return value shows which font we chose. */
7161 x_new_font (f
, fontname
)
7163 register char *fontname
;
7165 struct font_info
*fontp
7166 = FS_LOAD_FONT (f
, 0, fontname
, -1);
7171 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
7172 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
7173 FRAME_FONTSET (f
) = -1;
7175 /* Compute the scroll bar width in character columns. */
7176 if (f
->scroll_bar_pixel_width
> 0)
7178 int wid
= FONT_WIDTH (FRAME_FONT (f
));
7179 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
7183 int wid
= FONT_WIDTH (FRAME_FONT (f
));
7184 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
7187 /* Now make the frame display the given font. */
7188 if (FRAME_MAC_WINDOW (f
) != 0)
7190 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
7191 f
->output_data
.mac
->font
);
7192 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
7193 f
->output_data
.mac
->font
);
7194 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
7195 f
->output_data
.mac
->font
);
7197 frame_update_line_height (f
);
7198 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
7199 x_set_window_size (f
, 0, f
->width
, f
->height
);
7202 /* If we are setting a new frame's font for the first time,
7203 there are no faces yet, so this font's height is the line height. */
7204 f
->output_data
.mac
->line_height
= FONT_HEIGHT (FRAME_FONT (f
));
7206 return build_string (fontp
->full_name
);
7209 /* Give frame F the fontset named FONTSETNAME as its default font, and
7210 return the full name of that fontset. FONTSETNAME may be a wildcard
7211 pattern; in that case, we choose some fontset that fits the pattern.
7212 The return value shows which fontset we chose. */
7215 x_new_fontset (f
, fontsetname
)
7219 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
7225 if (FRAME_FONTSET (f
) == fontset
)
7226 /* This fontset is already set in frame F. There's nothing more
7228 return fontset_name (fontset
);
7230 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
7232 if (!STRINGP (result
))
7233 /* Can't load ASCII font. */
7236 /* Since x_new_font doesn't update any fontset information, do it now. */
7237 FRAME_FONTSET(f
) = fontset
;
7239 return build_string (fontsetname
);
7243 /***********************************************************************
7244 TODO: W32 Input Methods
7245 ***********************************************************************/
7246 /* Listing missing functions from xterm.c helps diff stay in step.
7248 xim_destroy_callback (xim, client_data, call_data)
7249 xim_open_dpy (dpyinfo, resource_name)
7251 xim_instantiate_callback (display, client_data, call_data)
7252 xim_initialize (dpyinfo, resource_name)
7253 xim_close_dpy (dpyinfo)
7258 /* Calculate the absolute position in frame F
7259 from its current recorded position values and gravity. */
7262 x_calc_absolute_position (f
)
7266 int flags
= f
->output_data
.mac
->size_hint_flags
;
7270 /* Find the position of the outside upper-left corner of
7271 the inner window, with respect to the outer window. */
7272 if (f
->output_data
.mac
->parent_desc
!= FRAME_MAC_DISPLAY_INFO (f
)->root_window
)
7275 GetPort (&savePort
);
7277 #if TARGET_API_MAC_CARBON
7278 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
7280 SetPort (FRAME_MAC_WINDOW (f
));
7283 #if TARGET_API_MAC_CARBON
7287 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
7288 SetPt(&pt
, r
.left
, r
.top
);
7290 #else /* not TARGET_API_MAC_CARBON */
7291 SetPt(&pt
, FRAME_MAC_WINDOW (f
)->portRect
.left
, FRAME_MAC_WINDOW (f
)->portRect
.top
);
7292 #endif /* not TARGET_API_MAC_CARBON */
7293 LocalToGlobal (&pt
);
7297 /* Treat negative positions as relative to the leftmost bottommost
7298 position that fits on the screen. */
7299 if (flags
& XNegative
)
7300 f
->output_data
.mac
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
7301 - 2 * f
->output_data
.mac
->border_width
- pt
.h
7303 + f
->output_data
.mac
->left_pos
);
7304 /* NTEMACS_TODO: Subtract menubar height? */
7305 if (flags
& YNegative
)
7306 f
->output_data
.mac
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
7307 - 2 * f
->output_data
.mac
->border_width
- pt
.v
7309 + f
->output_data
.mac
->top_pos
);
7310 /* The left_pos and top_pos
7311 are now relative to the top and left screen edges,
7312 so the flags should correspond. */
7313 f
->output_data
.mac
->size_hint_flags
&= ~ (XNegative
| YNegative
);
7316 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
7317 to really change the position, and 0 when calling from
7318 x_make_frame_visible (in that case, XOFF and YOFF are the current
7319 position values). It is -1 when calling from x_set_frame_parameters,
7320 which means, do adjust for borders but don't change the gravity. */
7323 x_set_offset (f
, xoff
, yoff
, change_gravity
)
7325 register int xoff
, yoff
;
7328 int modified_top
, modified_left
;
7330 if (change_gravity
> 0)
7332 f
->output_data
.mac
->top_pos
= yoff
;
7333 f
->output_data
.mac
->left_pos
= xoff
;
7334 f
->output_data
.mac
->size_hint_flags
&= ~ (XNegative
| YNegative
);
7336 f
->output_data
.mac
->size_hint_flags
|= XNegative
;
7338 f
->output_data
.mac
->size_hint_flags
|= YNegative
;
7339 f
->output_data
.mac
->win_gravity
= NorthWestGravity
;
7341 x_calc_absolute_position (f
);
7344 x_wm_set_size_hint (f
, (long) 0, 0);
7346 modified_left
= f
->output_data
.mac
->left_pos
;
7347 modified_top
= f
->output_data
.mac
->top_pos
;
7349 MoveWindow (f
->output_data
.mac
->mWP
, modified_left
+ 6,
7350 modified_top
+ 42, false);
7355 /* Call this to change the size of frame F's x-window.
7356 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
7357 for this size change and subsequent size changes.
7358 Otherwise we leave the window gravity unchanged. */
7361 x_set_window_size (f
, change_gravity
, cols
, rows
)
7366 int pixelwidth
, pixelheight
;
7370 check_frame_size (f
, &rows
, &cols
);
7371 f
->output_data
.mac
->vertical_scroll_bar_extra
7372 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
7374 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.mac
->font
)));
7376 compute_fringe_widths (f
, 0);
7378 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
7379 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
7381 f
->output_data
.mac
->win_gravity
= NorthWestGravity
;
7382 x_wm_set_size_hint (f
, (long) 0, 0);
7384 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
7386 /* Now, strictly speaking, we can't be sure that this is accurate,
7387 but the window manager will get around to dealing with the size
7388 change request eventually, and we'll hear how it went when the
7389 ConfigureNotify event gets here.
7391 We could just not bother storing any of this information here,
7392 and let the ConfigureNotify event set everything up, but that
7393 might be kind of confusing to the Lisp code, since size changes
7394 wouldn't be reported in the frame parameters until some random
7395 point in the future when the ConfigureNotify event arrives.
7397 We pass 1 for DELAY since we can't run Lisp code inside of
7399 change_frame_size (f
, rows
, cols
, 0, 1, 0);
7400 PIXEL_WIDTH (f
) = pixelwidth
;
7401 PIXEL_HEIGHT (f
) = pixelheight
;
7403 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
7404 receive in the ConfigureNotify event; if we get what we asked
7405 for, then the event won't cause the screen to become garbaged, so
7406 we have to make sure to do it here. */
7407 SET_FRAME_GARBAGED (f
);
7409 XFlush (FRAME_X_DISPLAY (f
));
7411 /* If cursor was outside the new size, mark it as off. */
7412 mark_window_cursors_off (XWINDOW (f
->root_window
));
7414 /* Clear out any recollection of where the mouse highlighting was,
7415 since it might be in a place that's outside the new frame size.
7416 Actually checking whether it is outside is a pain in the neck,
7417 so don't try--just let the highlighting be done afresh with new size. */
7418 cancel_mouse_face (f
);
7423 /* Mouse warping. */
7425 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
7428 x_set_mouse_position (f
, x
, y
)
7434 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.mac
->font
) / 2;
7435 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.mac
->line_height
/ 2;
7437 if (pix_x
< 0) pix_x
= 0;
7438 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
7440 if (pix_y
< 0) pix_y
= 0;
7441 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
7443 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
7447 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
7451 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
7454 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
7455 0, 0, 0, 0, pix_x
, pix_y
);
7461 /* focus shifting, raising and lowering. */
7464 x_focus_on_frame (f
)
7467 #if 0 /* This proves to be unpleasant. */
7471 /* I don't think that the ICCCM allows programs to do things like this
7472 without the interaction of the window manager. Whatever you end up
7473 doing with this code, do it to x_unfocus_frame too. */
7474 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7475 RevertToPointerRoot
, CurrentTime
);
7485 /* Raise frame F. */
7490 if (f
->async_visible
)
7491 SelectWindow (FRAME_MAC_WINDOW (f
));
7494 /* Lower frame F. */
7499 if (f
->async_visible
)
7500 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
7504 XTframe_raise_lower (f
, raise_flag
)
7514 /* Change of visibility. */
7516 /* This tries to wait until the frame is really visible.
7517 However, if the window manager asks the user where to position
7518 the frame, this will return before the user finishes doing that.
7519 The frame will not actually be visible at that time,
7520 but it will become visible later when the window manager
7521 finishes with it. */
7524 x_make_frame_visible (f
)
7528 int original_top
, original_left
;
7532 if (! FRAME_VISIBLE_P (f
))
7534 /* We test FRAME_GARBAGED_P here to make sure we don't
7535 call x_set_offset a second time
7536 if we get to x_make_frame_visible a second time
7537 before the window gets really visible. */
7538 if (! FRAME_ICONIFIED_P (f
)
7539 && ! f
->output_data
.mac
->asked_for_visible
)
7540 x_set_offset (f
, f
->output_data
.mac
->left_pos
,
7541 f
->output_data
.mac
->top_pos
, 0);
7543 f
->output_data
.mac
->asked_for_visible
= 1;
7545 ShowWindow (FRAME_MAC_WINDOW (f
));
7548 XFlush (FRAME_MAC_DISPLAY (f
));
7550 #if 0 /* MAC_TODO */
7551 /* Synchronize to ensure Emacs knows the frame is visible
7552 before we do anything else. We do this loop with input not blocked
7553 so that incoming events are handled. */
7558 /* This must come after we set COUNT. */
7561 XSETFRAME (frame
, f
);
7563 /* Wait until the frame is visible. Process X events until a
7564 MapNotify event has been seen, or until we think we won't get a
7565 MapNotify at all.. */
7566 for (count
= input_signal_count
+ 10;
7567 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
7569 /* Force processing of queued events. */
7572 /* Machines that do polling rather than SIGIO have been
7573 observed to go into a busy-wait here. So we'll fake an
7574 alarm signal to let the handler know that there's something
7575 to be read. We used to raise a real alarm, but it seems
7576 that the handler isn't always enabled here. This is
7578 if (input_polling_used ())
7580 /* It could be confusing if a real alarm arrives while
7581 processing the fake one. Turn it off and let the
7582 handler reset it. */
7583 extern void poll_for_input_1
P_ ((void));
7584 int old_poll_suppress_count
= poll_suppress_count
;
7585 poll_suppress_count
= 1;
7586 poll_for_input_1 ();
7587 poll_suppress_count
= old_poll_suppress_count
;
7590 /* See if a MapNotify event has been processed. */
7591 FRAME_SAMPLE_VISIBILITY (f
);
7594 #endif /* MAC_TODO */
7597 /* Change from mapped state to withdrawn state. */
7599 /* Make the frame visible (mapped and not iconified). */
7602 x_make_frame_invisible (f
)
7605 /* Don't keep the highlight on an invisible frame. */
7606 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7607 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7611 HideWindow (FRAME_MAC_WINDOW (f
));
7613 /* We can't distinguish this from iconification
7614 just by the event that we get from the server.
7615 So we can't win using the usual strategy of letting
7616 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
7617 and synchronize with the server to make sure we agree. */
7619 FRAME_ICONIFIED_P (f
) = 0;
7620 f
->async_visible
= 0;
7621 f
->async_iconified
= 0;
7626 /* Change window state from mapped to iconified. */
7632 /* Don't keep the highlight on an invisible frame. */
7633 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
7634 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
7637 /* Review: Since window is still visible in dock, still allow updates? */
7638 if (f
->async_iconified
)
7644 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
7650 /* Destroy the X window of frame F. */
7653 x_destroy_window (f
)
7656 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7660 DisposeWindow (FRAME_MAC_WINDOW (f
));
7662 free_frame_menubar (f
);
7663 free_frame_faces (f
);
7665 xfree (f
->output_data
.mac
);
7666 f
->output_data
.mac
= 0;
7667 if (f
== dpyinfo
->x_focus_frame
)
7668 dpyinfo
->x_focus_frame
= 0;
7669 if (f
== dpyinfo
->x_focus_event_frame
)
7670 dpyinfo
->x_focus_event_frame
= 0;
7671 if (f
== dpyinfo
->x_highlight_frame
)
7672 dpyinfo
->x_highlight_frame
= 0;
7674 dpyinfo
->reference_count
--;
7676 if (f
== dpyinfo
->mouse_face_mouse_frame
)
7678 dpyinfo
->mouse_face_beg_row
7679 = dpyinfo
->mouse_face_beg_col
= -1;
7680 dpyinfo
->mouse_face_end_row
7681 = dpyinfo
->mouse_face_end_col
= -1;
7682 dpyinfo
->mouse_face_window
= Qnil
;
7683 dpyinfo
->mouse_face_deferred_gc
= 0;
7684 dpyinfo
->mouse_face_mouse_frame
= 0;
7690 /* Setting window manager hints. */
7692 /* Set the normal size hints for the window manager, for frame F.
7693 FLAGS is the flags word to use--or 0 meaning preserve the flags
7694 that the window now has.
7695 If USER_POSITION is nonzero, we set the USPosition
7696 flag (this is useful when FLAGS is 0). */
7698 x_wm_set_size_hint (f
, flags
, user_position
)
7703 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
7704 XSizeHints size_hints
;
7706 #ifdef USE_X_TOOLKIT
7709 Dimension widget_width
, widget_height
;
7710 Window window
= XtWindow (f
->output_data
.x
->widget
);
7711 #else /* not USE_X_TOOLKIT */
7712 Window window
= FRAME_X_WINDOW (f
);
7713 #endif /* not USE_X_TOOLKIT */
7715 /* Setting PMaxSize caused various problems. */
7716 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
7718 size_hints
.x
= f
->output_data
.x
->left_pos
;
7719 size_hints
.y
= f
->output_data
.x
->top_pos
;
7721 #ifdef USE_X_TOOLKIT
7722 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
7723 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
7724 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
7725 size_hints
.height
= widget_height
;
7726 size_hints
.width
= widget_width
;
7727 #else /* not USE_X_TOOLKIT */
7728 size_hints
.height
= PIXEL_HEIGHT (f
);
7729 size_hints
.width
= PIXEL_WIDTH (f
);
7730 #endif /* not USE_X_TOOLKIT */
7732 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
7733 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
7734 size_hints
.max_width
7735 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
7736 size_hints
.max_height
7737 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
7739 /* Calculate the base and minimum sizes.
7741 (When we use the X toolkit, we don't do it here.
7742 Instead we copy the values that the widgets are using, below.) */
7743 #ifndef USE_X_TOOLKIT
7745 int base_width
, base_height
;
7746 int min_rows
= 0, min_cols
= 0;
7748 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
7749 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
7751 check_frame_size (f
, &min_rows
, &min_cols
);
7753 /* The window manager uses the base width hints to calculate the
7754 current number of rows and columns in the frame while
7755 resizing; min_width and min_height aren't useful for this
7756 purpose, since they might not give the dimensions for a
7757 zero-row, zero-column frame.
7759 We use the base_width and base_height members if we have
7760 them; otherwise, we set the min_width and min_height members
7761 to the size for a zero x zero frame. */
7764 size_hints
.flags
|= PBaseSize
;
7765 size_hints
.base_width
= base_width
;
7766 size_hints
.base_height
= base_height
;
7767 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
7768 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
7770 size_hints
.min_width
= base_width
;
7771 size_hints
.min_height
= base_height
;
7775 /* If we don't need the old flags, we don't need the old hint at all. */
7778 size_hints
.flags
|= flags
;
7781 #endif /* not USE_X_TOOLKIT */
7784 XSizeHints hints
; /* Sometimes I hate X Windows... */
7785 long supplied_return
;
7789 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
7792 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
7795 #ifdef USE_X_TOOLKIT
7796 size_hints
.base_height
= hints
.base_height
;
7797 size_hints
.base_width
= hints
.base_width
;
7798 size_hints
.min_height
= hints
.min_height
;
7799 size_hints
.min_width
= hints
.min_width
;
7803 size_hints
.flags
|= flags
;
7808 if (hints
.flags
& PSize
)
7809 size_hints
.flags
|= PSize
;
7810 if (hints
.flags
& PPosition
)
7811 size_hints
.flags
|= PPosition
;
7812 if (hints
.flags
& USPosition
)
7813 size_hints
.flags
|= USPosition
;
7814 if (hints
.flags
& USSize
)
7815 size_hints
.flags
|= USSize
;
7819 #ifndef USE_X_TOOLKIT
7824 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
7825 size_hints
.flags
|= PWinGravity
;
7829 size_hints
.flags
&= ~ PPosition
;
7830 size_hints
.flags
|= USPosition
;
7832 #endif /* PWinGravity */
7835 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
7837 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
7839 #endif /* MAC_TODO */
7842 #if 0 /* MAC_TODO: hide application instead of iconify? */
7843 /* Used for IconicState or NormalState */
7846 x_wm_set_window_state (f
, state
)
7850 #ifdef USE_X_TOOLKIT
7853 XtSetArg (al
[0], XtNinitialState
, state
);
7854 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7855 #else /* not USE_X_TOOLKIT */
7856 Window window
= FRAME_X_WINDOW (f
);
7858 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
7859 f
->output_data
.x
->wm_hints
.initial_state
= state
;
7861 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7862 #endif /* not USE_X_TOOLKIT */
7866 x_wm_set_icon_pixmap (f
, pixmap_id
)
7872 #ifndef USE_X_TOOLKIT
7873 Window window
= FRAME_X_WINDOW (f
);
7878 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
7879 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
7883 /* It seems there is no way to turn off use of an icon pixmap.
7884 The following line does it, only if no icon has yet been created,
7885 for some window managers. But with mwm it crashes.
7886 Some people say it should clear the IconPixmapHint bit in this case,
7887 but that doesn't work, and the X consortium said it isn't the
7888 right thing at all. Since there is no way to win,
7889 best to explicitly give up. */
7891 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
7897 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7901 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
7902 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
7905 #else /* not USE_X_TOOLKIT */
7907 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
7908 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7910 #endif /* not USE_X_TOOLKIT */
7913 #endif /* MAC_TODO */
7916 x_wm_set_icon_position (f
, icon_x
, icon_y
)
7920 #if 0 /* MAC_TODO: no icons on Mac */
7921 #ifdef USE_X_TOOLKIT
7922 Window window
= XtWindow (f
->output_data
.x
->widget
);
7924 Window window
= FRAME_X_WINDOW (f
);
7927 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
7928 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
7929 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
7931 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
7932 #endif /* MAC_TODO */
7936 /***********************************************************************
7938 ***********************************************************************/
7940 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7943 x_get_font_info (f
, font_idx
)
7947 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
7950 /* the global font name table */
7951 char **font_name_table
= NULL
;
7952 int font_name_table_size
= 0;
7953 int font_name_count
= 0;
7955 /* compare two strings ignoring case */
7957 stricmp (const char *s
, const char *t
)
7959 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
7962 return tolower (*s
) - tolower (*t
);
7965 /* compare two strings ignoring case and handling wildcard */
7967 wildstrieq (char *s1
, char *s2
)
7969 if (strcmp (s1
, "*") == 0 || strcmp (s2
, "*") == 0)
7972 return stricmp (s1
, s2
) == 0;
7975 /* Assume parameter 1 is fully qualified, no wildcards. */
7977 mac_font_pattern_match (fontname
, pattern
)
7981 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
7982 char *font_name_copy
= (char *) alloca (strlen (fontname
) + 1);
7985 /* Copy fontname so we can modify it during comparison. */
7986 strcpy (font_name_copy
, fontname
);
7991 /* Turn pattern into a regexp and do a regexp match. */
7992 for (; *pattern
; pattern
++)
7994 if (*pattern
== '?')
7996 else if (*pattern
== '*')
8007 return (fast_c_string_match_ignore_case (build_string (regex
),
8008 font_name_copy
) >= 0);
8011 /* Two font specs are considered to match if their foundry, family,
8012 weight, slant, and charset match. */
8014 mac_font_match (char *mf
, char *xf
)
8016 char m_foundry
[50], m_family
[50], m_weight
[20], m_slant
[2], m_charset
[20];
8017 char x_foundry
[50], x_family
[50], x_weight
[20], x_slant
[2], x_charset
[20];
8019 if (sscanf (mf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
8020 m_foundry
, m_family
, m_weight
, m_slant
, m_charset
) != 5)
8021 return mac_font_pattern_match (mf
, xf
);
8023 if (sscanf (xf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
8024 x_foundry
, x_family
, x_weight
, x_slant
, x_charset
) != 5)
8025 return mac_font_pattern_match (mf
, xf
);
8027 return (wildstrieq (m_foundry
, x_foundry
)
8028 && wildstrieq (m_family
, x_family
)
8029 && wildstrieq (m_weight
, x_weight
)
8030 && wildstrieq (m_slant
, x_slant
)
8031 && wildstrieq (m_charset
, x_charset
))
8032 || mac_font_pattern_match (mf
, xf
);
8037 mac_to_x_fontname (char *name
, int size
, Style style
, short scriptcode
)
8039 char foundry
[32], family
[32], cs
[32];
8040 char xf
[255], *result
, *p
;
8042 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) != 3)
8044 strcpy(foundry
, "Apple");
8045 strcpy(family
, name
);
8050 strcpy(cs
, "big5-0");
8053 strcpy(cs
, "gb2312.1980-0");
8056 strcpy(cs
, "jisx0208.1983-sjis");
8059 /* Each Apple Japanese font is entered into the font table
8060 twice: once as a jisx0208.1983-sjis font and once as a
8061 jisx0201.1976-0 font. The latter can be used to display
8062 the ascii charset and katakana-jisx0201 charset. A
8063 negative script code signals that the name of this latter
8064 font is being built. */
8065 strcpy(cs
, "jisx0201.1976-0");
8068 strcpy(cs
, "ksc5601.1989-0");
8071 strcpy(cs
, "mac-roman");
8076 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
8077 foundry
, family
, style
& bold
? "bold" : "medium",
8078 style
& italic
? 'i' : 'r', size
, size
* 10, size
* 10, cs
);
8080 result
= (char *) xmalloc (strlen (xf
) + 1);
8081 strcpy (result
, xf
);
8082 for (p
= result
; *p
; p
++)
8088 /* Convert an X font spec to the corresponding mac font name, which
8089 can then be passed to GetFNum after conversion to a Pascal string.
8090 For ordinary Mac fonts, this should just be their names, like
8091 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
8092 collection contain their charset designation in their names, like
8093 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
8094 names are handled accordingly. */
8096 x_font_name_to_mac_font_name (char *xf
, char *mf
)
8098 char foundry
[32], family
[32], weight
[20], slant
[2], cs
[32];
8102 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
8103 foundry
, family
, weight
, slant
, cs
) != 5 &&
8104 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
8105 foundry
, family
, weight
, slant
, cs
) != 5)
8108 if (strcmp (cs
, "big5-0") == 0 || strcmp (cs
, "gb2312.1980-0") == 0
8109 || strcmp (cs
, "jisx0208.1983-sjis") == 0
8110 || strcmp (cs
, "jisx0201.1976-0") == 0
8111 || strcmp (cs
, "ksc5601.1989-0") == 0 || strcmp (cs
, "mac-roman") == 0)
8114 sprintf(mf
, "%s-%s-%s", foundry
, family
, cs
);
8119 add_font_name_table_entry (char *font_name
)
8121 if (font_name_table_size
== 0)
8123 font_name_table_size
= 16;
8124 font_name_table
= (char **)
8125 xmalloc (font_name_table_size
* sizeof (char *));
8127 else if (font_name_count
+ 1 >= font_name_table_size
)
8129 font_name_table_size
+= 16;
8130 font_name_table
= (char **)
8131 xrealloc (font_name_table
,
8132 font_name_table_size
* sizeof (char *));
8135 font_name_table
[font_name_count
++] = font_name
;
8138 /* Sets up the table font_name_table to contain the list of all fonts
8139 in the system the first time the table is used so that the Resource
8140 Manager need not be accessed every time this information is
8144 init_font_name_table ()
8146 #if TARGET_API_MAC_CARBON
8149 if (Gestalt (gestaltSystemVersion
, &sv
) == noErr
&& sv
>= 0x1000)
8151 FMFontFamilyIterator ffi
;
8152 FMFontFamilyInstanceIterator ffii
;
8155 /* Create a dummy instance iterator here to avoid creating and
8156 destroying it in the loop. */
8157 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
8159 /* Create an iterator to enumerate the font families. */
8160 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
8163 FMDisposeFontFamilyInstanceIterator (&ffii
);
8167 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
8175 if (FMGetFontFamilyName (ff
, name
) != noErr
)
8179 sc
= FontToScript (ff
);
8181 /* Point the instance iterator at the current font family. */
8182 if (FMResetFontFamilyInstanceIterator(ff
, &ffii
) != noErr
)
8185 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
8189 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
8191 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
8193 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
8195 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
8201 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
8203 if (smJapanese
== sc
)
8204 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
8210 /* Dispose of the iterators. */
8211 FMDisposeFontFamilyIterator (&ffi
);
8212 FMDisposeFontFamilyInstanceIterator (&ffii
);
8216 #endif /* TARGET_API_MAC_CARBON */
8218 SInt16 fontnum
, old_fontnum
;
8219 int num_mac_fonts
= CountResources('FOND');
8221 Handle font_handle
, font_handle_2
;
8222 short id
, scriptcode
;
8225 struct FontAssoc
*fat
;
8226 struct AsscEntry
*assc_entry
;
8228 GetPort (&port
); /* save the current font number used */
8229 #if TARGET_API_MAC_CARBON
8230 old_fontnum
= GetPortTextFont (port
);
8232 old_fontnum
= port
->txFont
;
8235 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
8237 font_handle
= GetIndResource ('FOND', i
);
8241 GetResInfo (font_handle
, &id
, &type
, name
);
8242 GetFNum (name
, &fontnum
);
8248 scriptcode
= FontToScript (fontnum
);
8251 HLock (font_handle
);
8253 if (GetResourceSizeOnDisk (font_handle
)
8254 >= sizeof (struct FamRec
))
8256 fat
= (struct FontAssoc
*) (*font_handle
8257 + sizeof (struct FamRec
));
8259 = (struct AsscEntry
*) (*font_handle
8260 + sizeof (struct FamRec
)
8261 + sizeof (struct FontAssoc
));
8263 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
8265 if (font_name_table_size
== 0)
8267 font_name_table_size
= 16;
8268 font_name_table
= (char **)
8269 xmalloc (font_name_table_size
* sizeof (char *));
8271 else if (font_name_count
>= font_name_table_size
)
8273 font_name_table_size
+= 16;
8274 font_name_table
= (char **)
8275 xrealloc (font_name_table
,
8276 font_name_table_size
* sizeof (char *));
8278 font_name_table
[font_name_count
++]
8279 = mac_to_x_fontname (name
,
8280 assc_entry
->fontSize
,
8281 assc_entry
->fontStyle
,
8283 /* Both jisx0208.1983-sjis and
8284 jisx0201.1976-sjis parts are contained in
8285 Apple Japanese (SJIS) font. */
8286 if (smJapanese
== scriptcode
)
8288 font_name_table
[font_name_count
++]
8289 = mac_to_x_fontname (name
,
8290 assc_entry
->fontSize
,
8291 assc_entry
->fontStyle
,
8297 HUnlock (font_handle
);
8298 font_handle_2
= GetNextFOND (font_handle
);
8299 ReleaseResource (font_handle
);
8300 font_handle
= font_handle_2
;
8302 while (ResError () == noErr
&& font_handle
);
8305 TextFont (old_fontnum
);
8306 #if TARGET_API_MAC_CARBON
8308 #endif /* TARGET_API_MAC_CARBON */
8312 /* Return a list of at most MAXNAMES font specs matching the one in
8313 PATTERN. Cache matching fonts for patterns in
8314 dpyinfo->name_list_element to avoid looking them up again by
8315 calling mac_font_pattern_match (slow). */
8318 x_list_fonts (struct frame
*f
,
8319 Lisp_Object pattern
,
8324 Lisp_Object newlist
= Qnil
, tem
, key
;
8327 struct gcpro gcpro1
, gcpro2
;
8328 struct mac_display_info
*dpyinfo
= f
? FRAME_MAC_DISPLAY_INFO (f
) : NULL
;
8330 if (font_name_table
== NULL
) /* Initialize when first used. */
8331 init_font_name_table ();
8335 tem
= XCDR (dpyinfo
->name_list_element
);
8336 key
= Fcons (pattern
, make_number (maxnames
));
8338 newlist
= Fassoc (key
, tem
);
8339 if (!NILP (newlist
))
8341 newlist
= Fcdr_safe (newlist
);
8346 ptnstr
= SDATA (pattern
);
8348 GCPRO2 (pattern
, newlist
);
8350 /* Scan and matching bitmap fonts. */
8351 for (i
= 0; i
< font_name_count
; i
++)
8353 if (mac_font_pattern_match (font_name_table
[i
], ptnstr
))
8355 newlist
= Fcons (build_string (font_name_table
[i
]), newlist
);
8358 if (n_fonts
>= maxnames
)
8363 /* MAC_TODO: add code for matching outline fonts here */
8369 XSETCDR (dpyinfo
->name_list_element
,
8370 Fcons (Fcons (key
, newlist
),
8371 XCDR (dpyinfo
->name_list_element
)));
8381 /* Check that FONT is valid on frame F. It is if it can be found in F's
8385 x_check_font (f
, font
)
8390 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8392 xassert (font
!= NULL
);
8394 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8395 if (dpyinfo
->font_table
[i
].name
8396 && font
== dpyinfo
->font_table
[i
].font
)
8399 xassert (i
< dpyinfo
->n_fonts
);
8402 #endif /* GLYPH_DEBUG != 0 */
8404 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8405 Note: There are (broken) X fonts out there with invalid XFontStruct
8406 min_bounds contents. For example, handa@etl.go.jp reports that
8407 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8408 have font->min_bounds.width == 0. */
8411 x_font_min_bounds (font
, w
, h
)
8412 MacFontStruct
*font
;
8416 * TODO: Windows does not appear to offer min bound, only
8417 * average and maximum width, and maximum height.
8419 *h
= FONT_HEIGHT (font
);
8420 *w
= FONT_WIDTH (font
);
8424 /* Compute the smallest character width and smallest font height over
8425 all fonts available on frame F. Set the members smallest_char_width
8426 and smallest_font_height in F's x_display_info structure to
8427 the values computed. Value is non-zero if smallest_font_height or
8428 smallest_char_width become smaller than they were before. */
8431 x_compute_min_glyph_bounds (f
)
8435 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8436 MacFontStruct
*font
;
8437 int old_width
= dpyinfo
->smallest_char_width
;
8438 int old_height
= dpyinfo
->smallest_font_height
;
8440 dpyinfo
->smallest_font_height
= 100000;
8441 dpyinfo
->smallest_char_width
= 100000;
8443 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8444 if (dpyinfo
->font_table
[i
].name
)
8446 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8449 font
= (MacFontStruct
*) fontp
->font
;
8450 xassert (font
!= (MacFontStruct
*) ~0);
8451 x_font_min_bounds (font
, &w
, &h
);
8453 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8454 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8457 xassert (dpyinfo
->smallest_char_width
> 0
8458 && dpyinfo
->smallest_font_height
> 0);
8460 return (dpyinfo
->n_fonts
== 1
8461 || dpyinfo
->smallest_char_width
< old_width
8462 || dpyinfo
->smallest_font_height
< old_height
);
8466 /* Determine whether given string is a fully-specified XLFD: all 14
8467 fields are present, none is '*'. */
8470 is_fully_specified_xlfd (char *p
)
8478 for (i
= 0; i
< 13; i
++)
8480 q
= strchr (p
+ 1, '-');
8483 if (q
- p
== 2 && *(p
+ 1) == '*')
8488 if (strchr (p
+ 1, '-') != NULL
)
8491 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
8498 const int kDefaultFontSize
= 9;
8501 /* XLoadQueryFont creates and returns an internal representation for a
8502 font in a MacFontStruct struct. There is really no concept
8503 corresponding to "loading" a font on the Mac. But we check its
8504 existence and find the font number and all other information for it
8505 and store them in the returned MacFontStruct. */
8507 static MacFontStruct
*
8508 XLoadQueryFont (Display
*dpy
, char *fontname
)
8510 int i
, size
, is_two_byte_font
, char_width
;
8513 SInt16 old_fontnum
, old_fontsize
;
8517 Style fontface
= normal
;
8518 MacFontStruct
*font
;
8519 FontInfo the_fontinfo
;
8520 char s_weight
[7], c_slant
;
8522 if (is_fully_specified_xlfd (fontname
))
8526 for (i
= 0; i
< font_name_count
; i
++)
8527 if (mac_font_pattern_match (font_name_table
[i
], fontname
))
8530 if (i
>= font_name_count
)
8533 name
= font_name_table
[i
];
8536 GetPort (&port
); /* save the current font number used */
8537 #if TARGET_API_MAC_CARBON
8538 old_fontnum
= GetPortTextFont (port
);
8539 old_fontsize
= GetPortTextSize (port
);
8540 old_fontface
= GetPortTextFace (port
);
8542 old_fontnum
= port
->txFont
;
8543 old_fontsize
= port
->txSize
;
8544 old_fontface
= port
->txFace
;
8547 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size
) != 1)
8548 size
= kDefaultFontSize
;
8550 if (sscanf (name
, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight
) == 1)
8551 if (strcmp (s_weight
, "bold") == 0)
8554 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant
) == 1)
8558 x_font_name_to_mac_font_name (name
, mfontname
);
8560 GetFNum (mfontname
, &fontnum
);
8564 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
8566 font
->fontname
= (char *) xmalloc (strlen (name
) + 1);
8567 bcopy (name
, font
->fontname
, strlen (name
) + 1);
8569 font
->mac_fontnum
= fontnum
;
8570 font
->mac_fontsize
= size
;
8571 font
->mac_fontface
= fontface
;
8572 font
->mac_scriptcode
= FontToScript (fontnum
);
8574 /* Apple Japanese (SJIS) font is listed as both
8575 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8576 (Roman script) in init_font_name_table (). The latter should be
8577 treated as a one-byte font. */
8582 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
8584 && 0 == strcmp (cs
, "jisx0201.1976-0"))
8585 font
->mac_scriptcode
= smRoman
;
8588 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
8589 font
->mac_scriptcode
== smTradChinese
||
8590 font
->mac_scriptcode
== smSimpChinese
||
8591 font
->mac_scriptcode
== smKorean
;
8595 TextFace (fontface
);
8597 GetFontInfo (&the_fontinfo
);
8599 font
->ascent
= the_fontinfo
.ascent
;
8600 font
->descent
= the_fontinfo
.descent
;
8602 font
->min_byte1
= 0;
8603 if (is_two_byte_font
)
8604 font
->max_byte1
= 1;
8606 font
->max_byte1
= 0;
8607 font
->min_char_or_byte2
= 0x20;
8608 font
->max_char_or_byte2
= 0xff;
8610 if (is_two_byte_font
)
8612 /* Use the width of an "ideographic space" of that font because
8613 the_fontinfo.widMax returns the wrong width for some fonts. */
8614 switch (font
->mac_scriptcode
)
8617 char_width
= StringWidth("\p\x81\x40");
8620 char_width
= StringWidth("\p\xa1\x40");
8623 char_width
= StringWidth("\p\xa1\xa1");
8626 char_width
= StringWidth("\p\xa1\xa1");
8631 /* Do this instead of use the_fontinfo.widMax, which incorrectly
8632 returns 15 for 12-point Monaco! */
8633 char_width
= CharWidth ('m');
8635 font
->max_bounds
.rbearing
= char_width
;
8636 font
->max_bounds
.lbearing
= 0;
8637 font
->max_bounds
.width
= char_width
;
8638 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
8639 font
->max_bounds
.descent
= the_fontinfo
.descent
;
8641 font
->min_bounds
= font
->max_bounds
;
8643 if (is_two_byte_font
|| CharWidth ('m') == CharWidth ('i'))
8644 font
->per_char
= NULL
;
8647 font
->per_char
= (XCharStruct
*)
8648 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
8652 for (c
= 0x20; c
<= 0xff; c
++)
8654 font
->per_char
[c
- 0x20] = font
->max_bounds
;
8655 font
->per_char
[c
- 0x20].width
= CharWidth (c
);
8660 TextFont (old_fontnum
); /* restore previous font number, size and face */
8661 TextSize (old_fontsize
);
8662 TextFace (old_fontface
);
8668 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8669 pointer to the structure font_info while allocating it dynamically.
8670 If SIZE is 0, load any size of font.
8671 If loading is failed, return NULL. */
8674 x_load_font (f
, fontname
, size
)
8676 register char *fontname
;
8679 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8680 Lisp_Object font_names
;
8682 /* Get a list of all the fonts that match this name. Once we
8683 have a list of matching fonts, we compare them against the fonts
8684 we already have by comparing names. */
8685 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
8687 if (!NILP (font_names
))
8692 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8693 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
8694 if (dpyinfo
->font_table
[i
].name
8695 && (!strcmp (dpyinfo
->font_table
[i
].name
,
8696 SDATA (XCAR (tail
)))
8697 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
8698 SDATA (XCAR (tail
)))))
8699 return (dpyinfo
->font_table
+ i
);
8702 /* Load the font and add it to the table. */
8705 struct MacFontStruct
*font
;
8706 struct font_info
*fontp
;
8707 unsigned long value
;
8710 /* If we have found fonts by x_list_font, load one of them. If
8711 not, we still try to load a font by the name given as FONTNAME
8712 because XListFonts (called in x_list_font) of some X server has
8713 a bug of not finding a font even if the font surely exists and
8714 is loadable by XLoadQueryFont. */
8715 if (size
> 0 && !NILP (font_names
))
8716 fontname
= (char *) SDATA (XCAR (font_names
));
8718 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
8722 /* Find a free slot in the font table. */
8723 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8724 if (dpyinfo
->font_table
[i
].name
== NULL
)
8727 /* If no free slot found, maybe enlarge the font table. */
8728 if (i
== dpyinfo
->n_fonts
8729 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
8732 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
8733 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
8735 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
8738 fontp
= dpyinfo
->font_table
+ i
;
8739 if (i
== dpyinfo
->n_fonts
)
8742 /* Now fill in the slots of *FONTP. */
8745 fontp
->font_idx
= i
;
8746 fontp
->name
= (char *) xmalloc (strlen (font
->fontname
) + 1);
8747 bcopy (font
->fontname
, fontp
->name
, strlen (font
->fontname
) + 1);
8749 fontp
->full_name
= fontp
->name
;
8751 fontp
->size
= font
->max_bounds
.width
;
8752 fontp
->height
= FONT_HEIGHT (font
);
8754 /* For some font, ascent and descent in max_bounds field is
8755 larger than the above value. */
8756 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8757 if (max_height
> fontp
->height
)
8758 fontp
->height
= max_height
;
8761 /* The slot `encoding' specifies how to map a character
8762 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8763 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8764 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8765 2:0xA020..0xFF7F). For the moment, we don't know which charset
8766 uses this font. So, we set information in fontp->encoding[1]
8767 which is never used by any charset. If mapping can't be
8768 decided, set FONT_ENCODING_NOT_DECIDED. */
8769 if (font
->mac_scriptcode
== smJapanese
)
8770 fontp
->encoding
[1] = 4;
8774 = (font
->max_byte1
== 0
8776 ? (font
->min_char_or_byte2
< 0x80
8777 ? (font
->max_char_or_byte2
< 0x80
8778 ? 0 /* 0x20..0x7F */
8779 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8780 : 1) /* 0xA0..0xFF */
8782 : (font
->min_byte1
< 0x80
8783 ? (font
->max_byte1
< 0x80
8784 ? (font
->min_char_or_byte2
< 0x80
8785 ? (font
->max_char_or_byte2
< 0x80
8786 ? 0 /* 0x2020..0x7F7F */
8787 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8788 : 3) /* 0x20A0..0x7FFF */
8789 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8790 : (font
->min_char_or_byte2
< 0x80
8791 ? (font
->max_char_or_byte2
< 0x80
8792 ? 2 /* 0xA020..0xFF7F */
8793 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8794 : 1))); /* 0xA0A0..0xFFFF */
8797 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8798 fontp
->baseline_offset
8799 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8800 ? (long) value
: 0);
8801 fontp
->relative_compose
8802 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8803 ? (long) value
: 0);
8804 fontp
->default_ascent
8805 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8806 ? (long) value
: 0);
8808 fontp
->baseline_offset
= 0;
8809 fontp
->relative_compose
= 0;
8810 fontp
->default_ascent
= 0;
8813 /* Set global flag fonts_changed_p to non-zero if the font loaded
8814 has a character with a smaller width than any other character
8815 before, or if the font loaded has a smalle>r height than any
8816 other font loaded before. If this happens, it will make a
8817 glyph matrix reallocation necessary. */
8818 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
8825 /* Return a pointer to struct font_info of a font named FONTNAME for
8826 frame F. If no such font is loaded, return NULL. */
8829 x_query_font (f
, fontname
)
8831 register char *fontname
;
8833 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8836 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8837 if (dpyinfo
->font_table
[i
].name
8838 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8839 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8840 return (dpyinfo
->font_table
+ i
);
8845 /* Find a CCL program for a font specified by FONTP, and set the member
8846 `encoder' of the structure. */
8849 x_find_ccl_program (fontp
)
8850 struct font_info
*fontp
;
8852 Lisp_Object list
, elt
;
8854 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8858 && STRINGP (XCAR (elt
))
8859 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8865 struct ccl_program
*ccl
8866 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8868 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8871 fontp
->font_encoder
= ccl
;
8877 /***********************************************************************
8879 ***********************************************************************/
8881 #ifdef USE_X_TOOLKIT
8882 static XrmOptionDescRec emacs_options
[] = {
8883 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
8884 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
8886 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
8887 XrmoptionSepArg
, NULL
},
8888 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
8890 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
8891 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
8892 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
8893 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
8894 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
8895 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
8896 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
8898 #endif /* USE_X_TOOLKIT */
8900 static int x_initialized
;
8903 /* Test whether two display-name strings agree up to the dot that separates
8904 the screen number from the server number. */
8906 same_x_server (name1
, name2
)
8907 char *name1
, *name2
;
8910 unsigned char *system_name
= SDATA (Vsystem_name
);
8911 int system_name_length
= strlen (system_name
);
8912 int length_until_period
= 0;
8914 while (system_name
[length_until_period
] != 0
8915 && system_name
[length_until_period
] != '.')
8916 length_until_period
++;
8918 /* Treat `unix' like an empty host name. */
8919 if (! strncmp (name1
, "unix:", 5))
8921 if (! strncmp (name2
, "unix:", 5))
8923 /* Treat this host's name like an empty host name. */
8924 if (! strncmp (name1
, system_name
, system_name_length
)
8925 && name1
[system_name_length
] == ':')
8926 name1
+= system_name_length
;
8927 if (! strncmp (name2
, system_name
, system_name_length
)
8928 && name2
[system_name_length
] == ':')
8929 name2
+= system_name_length
;
8930 /* Treat this host's domainless name like an empty host name. */
8931 if (! strncmp (name1
, system_name
, length_until_period
)
8932 && name1
[length_until_period
] == ':')
8933 name1
+= length_until_period
;
8934 if (! strncmp (name2
, system_name
, length_until_period
)
8935 && name2
[length_until_period
] == ':')
8936 name2
+= length_until_period
;
8938 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
8942 if (seen_colon
&& *name1
== '.')
8946 && (*name1
== '.' || *name1
== '\0')
8947 && (*name2
== '.' || *name2
== '\0'));
8952 /* The Mac Event loop code */
8956 #include <Quickdraw.h>
8957 #include <Balloons.h>
8958 #include <Devices.h>
8960 #include <Gestalt.h>
8962 #include <Processes.h>
8964 #include <ToolUtils.h>
8965 #include <TextUtils.h>
8966 #include <Dialogs.h>
8969 #include <TextEncodingConverter.h>
8970 #include <Resources.h>
8975 #endif /* ! MAC_OSX */
8980 #define WINDOW_RESOURCE 128
8981 #define TERM_WINDOW_RESOURCE 129
8983 #define DEFAULT_NUM_COLS 80
8985 #define MIN_DOC_SIZE 64
8986 #define MAX_DOC_SIZE 32767
8988 /* sleep time for WaitNextEvent */
8989 #define WNE_SLEEP_AT_SUSPEND 10
8990 #define WNE_SLEEP_AT_RESUME 1
8992 /* true when cannot handle any Mac OS events */
8993 static int handling_window_update
= 0;
8995 /* the flag appl_is_suspended is used both for determining the sleep
8996 time to be passed to WaitNextEvent and whether the cursor should be
8997 drawn when updating the display. The cursor is turned off when
8998 Emacs is suspended. Redrawing it is unnecessary and what needs to
8999 be done depends on whether the cursor lies inside or outside the
9000 redraw region. So we might as well skip drawing it when Emacs is
9002 static Boolean app_is_suspended
= false;
9003 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
9005 #define EXTRA_STACK_ALLOC (256 * 1024)
9007 #define ARGV_STRING_LIST_ID 129
9008 #define ABOUT_ALERT_ID 128
9009 #define RAM_TOO_LARGE_ALERT_ID 129
9011 Boolean terminate_flag
= false;
9013 /* True if using command key as meta key. */
9014 Lisp_Object Vmac_command_key_is_meta
;
9016 /* True if the ctrl and meta keys should be reversed. */
9017 Lisp_Object Vmac_reverse_ctrl_meta
;
9019 #if USE_CARBON_EVENTS
9020 /* True if the mouse wheel button (i.e. button 4) should map to
9021 mouse-2, instead of mouse-3. */
9022 Lisp_Object Vmac_wheel_button_is_mouse_2
;
9024 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
9025 for processing before Emacs sees it. */
9026 Lisp_Object Vmac_pass_command_to_system
;
9028 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
9029 for processing before Emacs sees it. */
9030 Lisp_Object Vmac_pass_control_to_system
;
9033 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
9034 to this text encoding */
9035 int mac_keyboard_text_encoding
;
9036 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
9038 /* Set in term/mac-win.el to indicate that event loop can now generate
9039 drag and drop events. */
9040 Lisp_Object Qmac_ready_for_drag_n_drop
;
9042 Lisp_Object drag_and_drop_file_list
;
9044 Point saved_menu_event_location
;
9047 static void init_required_apple_events (void);
9049 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
9051 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
9052 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
9053 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
9056 static OSErr
init_mac_drag_n_drop ();
9057 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
9059 #if USE_CARBON_EVENTS
9060 /* Preliminary Support for the OSX Services Menu */
9061 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
9062 static void init_service_handler ();
9065 extern void init_emacs_passwd_dir ();
9066 extern int emacs_main (int, char **, char **);
9067 extern void check_alarm ();
9069 extern void initialize_applescript();
9070 extern void terminate_applescript();
9073 #if USE_CARBON_EVENTS
9074 mac_to_emacs_modifiers (UInt32 mods
)
9076 mac_to_emacs_modifiers (EventModifiers mods
)
9079 unsigned int result
= 0;
9080 if (mods
& macShiftKey
)
9081 result
|= shift_modifier
;
9082 if (mods
& macCtrlKey
)
9083 result
|= ctrl_modifier
;
9084 if (mods
& macMetaKey
)
9085 result
|= meta_modifier
;
9086 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
9087 result
|= alt_modifier
;
9091 #if USE_CARBON_EVENTS
9092 /* Obtains the event modifiers from the event ref and then calls
9093 mac_to_emacs_modifiers. */
9095 mac_event_to_emacs_modifiers (EventRef eventRef
)
9098 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9099 sizeof (UInt32
), NULL
, &mods
);
9100 return mac_to_emacs_modifiers (mods
);
9103 /* Given an event ref, return the code to use for the mouse button
9104 code in the emacs input_event. */
9106 mac_get_mouse_btn (EventRef ref
)
9108 EventMouseButton result
= kEventMouseButtonPrimary
;
9109 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
9110 sizeof (EventMouseButton
), NULL
, &result
);
9113 case kEventMouseButtonPrimary
:
9115 case kEventMouseButtonSecondary
:
9116 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
9117 case kEventMouseButtonTertiary
:
9118 case 4: /* 4 is the number for the mouse wheel button */
9119 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
9125 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9126 events. However the click of the mouse wheel is not converted to a
9127 mouseDown or mouseUp event. This calls ConvertEventRef, but then
9128 checks to see if it is a mouse up or down carbon event that has not
9129 been converted, and if so, converts it by hand (to be picked up in
9130 the XTread_socket loop). */
9131 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
9133 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
9134 /* Do special case for mouse wheel button. */
9135 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
9137 UInt32 kind
= GetEventKind (eventRef
);
9138 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
9140 eventRec
->what
= mouseDown
;
9143 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
9145 eventRec
->what
= mouseUp
;
9150 /* Need where and when. */
9152 GetEventParameter (eventRef
, kEventParamMouseLocation
,
9153 typeQDPoint
, NULL
, sizeof (Point
),
9154 NULL
, &eventRec
->where
);
9155 /* Use two step process because new event modifiers are
9156 32-bit and old are 16-bit. Currently, only loss is
9158 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
9159 typeUInt32
, NULL
, sizeof (UInt32
),
9161 eventRec
->modifiers
= mods
;
9163 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
9174 Handle menubar_handle
;
9175 MenuHandle menu_handle
;
9177 menubar_handle
= GetNewMBar (128);
9178 if(menubar_handle
== NULL
)
9180 SetMenuBar (menubar_handle
);
9183 menu_handle
= GetMenuHandle (M_APPLE
);
9184 if(menu_handle
!= NULL
)
9185 AppendResMenu (menu_handle
,'DRVR');
9192 do_init_managers (void)
9194 #if !TARGET_API_MAC_CARBON
9195 InitGraf (&qd
.thePort
);
9197 FlushEvents (everyEvent
, 0);
9202 #endif /* !TARGET_API_MAC_CARBON */
9205 #if !TARGET_API_MAC_CARBON
9206 /* set up some extra stack space for use by emacs */
9207 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
9209 /* MaxApplZone must be called for AppleScript to execute more
9210 complicated scripts */
9213 #endif /* !TARGET_API_MAC_CARBON */
9217 do_check_ram_size (void)
9219 SInt32 physical_ram_size
, logical_ram_size
;
9221 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
9222 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
9223 || physical_ram_size
> 256 * 1024 * 1024
9224 || logical_ram_size
> 256 * 1024 * 1024)
9226 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
9232 do_window_update (WindowPtr win
)
9234 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (win
);
9235 struct frame
*f
= mwp
->mFP
;
9239 if (f
->async_visible
== 0)
9241 f
->async_visible
= 1;
9242 f
->async_iconified
= 0;
9243 SET_FRAME_GARBAGED (f
);
9245 /* An update event is equivalent to MapNotify on X, so report
9246 visibility changes properly. */
9247 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
9248 /* Force a redisplay sooner or later to update the
9249 frame titles in case this is the second frame. */
9250 record_asynch_buffer_change ();
9255 handling_window_update
= 1;
9257 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
9259 expose_frame (f
, 0, 0, 0, 0);
9261 handling_window_update
= 0;
9268 is_emacs_window (WindowPtr win
)
9270 Lisp_Object tail
, frame
;
9275 FOR_EACH_FRAME (tail
, frame
)
9276 if (FRAME_MAC_P (XFRAME (frame
)))
9277 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
9284 do_window_activate (WindowPtr win
)
9289 if (is_emacs_window (win
))
9291 mwp
= (mac_output
*) GetWRefCon (win
);
9296 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
9297 activate_scroll_bars (f
);
9303 do_window_deactivate (WindowPtr win
)
9308 if (is_emacs_window (win
))
9310 mwp
= (mac_output
*) GetWRefCon (win
);
9313 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
9315 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
9316 deactivate_scroll_bars (f
);
9329 if (is_emacs_window (wp
))
9331 mwp
= (mac_output
*) GetWRefCon (wp
);
9336 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
9337 activate_scroll_bars (f
);
9341 app_is_suspended
= false;
9342 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
9353 if (is_emacs_window (wp
))
9355 mwp
= (mac_output
*) GetWRefCon (wp
);
9358 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
9360 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
9361 deactivate_scroll_bars (f
);
9365 app_is_suspended
= true;
9366 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
9371 do_mouse_moved (Point mouse_pos
)
9373 WindowPtr wp
= FrontWindow ();
9376 if (is_emacs_window (wp
))
9378 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
9380 #if TARGET_API_MAC_CARBON
9381 SetPort (GetWindowPort (wp
));
9386 GlobalToLocal (&mouse_pos
);
9388 note_mouse_movement (f
, &mouse_pos
);
9394 do_os_event (EventRecord
*erp
)
9396 switch((erp
->message
>> 24) & 0x000000FF)
9398 case suspendResumeMessage
:
9399 if((erp
->message
& resumeFlag
) == 1)
9405 case mouseMovedMessage
:
9406 do_mouse_moved (erp
->where
);
9412 do_events (EventRecord
*erp
)
9417 do_window_update ((WindowPtr
) erp
->message
);
9425 if ((erp
->modifiers
& activeFlag
) != 0)
9426 do_window_activate ((WindowPtr
) erp
->message
);
9428 do_window_deactivate ((WindowPtr
) erp
->message
);
9434 do_apple_menu (SInt16 menu_item
)
9436 #if !TARGET_API_MAC_CARBON
9438 SInt16 da_driver_refnum
;
9440 if (menu_item
== I_ABOUT
)
9441 NoteAlert (ABOUT_ALERT_ID
, NULL
);
9444 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
9445 da_driver_refnum
= OpenDeskAcc (item_name
);
9447 #endif /* !TARGET_API_MAC_CARBON */
9451 do_menu_choice (SInt32 menu_choice
)
9453 SInt16 menu_id
, menu_item
;
9455 menu_id
= HiWord (menu_choice
);
9456 menu_item
= LoWord (menu_choice
);
9464 do_apple_menu (menu_item
);
9469 WindowPtr wp
= FrontWindow ();
9470 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
9471 MenuHandle menu
= GetMenuHandle (menu_id
);
9476 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
9477 menubar_selection_callback (f
, refcon
);
9486 /* Handle drags in size box. Based on code contributed by Ben
9487 Mesander and IM - Window Manager A. */
9490 do_grow_window (WindowPtr w
, EventRecord
*e
)
9495 mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
9496 struct frame
*f
= mwp
->mFP
;
9498 SetRect(&limit_rect
, MIN_DOC_SIZE
, MIN_DOC_SIZE
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
9500 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
9502 /* see if it really changed size */
9505 rows
= PIXEL_TO_CHAR_HEIGHT (f
, HiWord (grow_size
));
9506 columns
= PIXEL_TO_CHAR_WIDTH (f
, LoWord (grow_size
));
9508 x_set_window_size (f
, 0, columns
, rows
);
9513 /* Handle clicks in zoom box. Calculation of "standard state" based
9514 on code in IM - Window Manager A and code contributed by Ben
9515 Mesander. The standard state of an Emacs window is 80-characters
9516 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9519 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
9522 Rect zoom_rect
, port_rect
;
9524 int w_title_height
, columns
, rows
, width
, height
, dummy
, x
, y
;
9525 mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
9526 struct frame
*f
= mwp
->mFP
;
9528 GetPort (&save_port
);
9530 #if TARGET_API_MAC_CARBON
9531 SetPort (GetWindowPort (w
));
9536 /* Clear window to avoid flicker. */
9537 #if TARGET_API_MAC_CARBON
9542 GetWindowPortBounds (w
, &r
);
9545 if (zoom_in_or_out
== inZoomOut
)
9547 /* calculate height of window's title bar (hard card it for now). */
9548 w_title_height
= 20 + GetMBarHeight ();
9550 /* get maximum height of window into zoom_rect.bottom -
9552 GetQDGlobalsScreenBits (&bm
);
9553 zoom_rect
= bm
.bounds
;
9554 zoom_rect
.top
+= w_title_height
;
9555 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9557 zoom_rect
.right
= zoom_rect
.left
9558 + CHAR_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9560 SetWindowStandardState (w
, &zoom_rect
);
9563 #else /* not TARGET_API_MAC_CARBON */
9564 EraseRect (&(w
->portRect
));
9565 if (zoom_in_or_out
== inZoomOut
)
9567 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
9568 LocalToGlobal (&top_left
);
9570 /* calculate height of window's title bar */
9571 w_title_height
= top_left
.v
- 1
9572 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
9574 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9575 zoom_rect
= qd
.screenBits
.bounds
;
9576 zoom_rect
.top
+= w_title_height
;
9577 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
9579 zoom_rect
.right
= zoom_rect
.left
9580 + CHAR_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
9582 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
9585 #endif /* not TARGET_API_MAC_CARBON */
9587 ZoomWindow (w
, zoom_in_or_out
, w
== FrontWindow ());
9589 /* retrieve window size and update application values */
9590 #if TARGET_API_MAC_CARBON
9591 GetWindowPortBounds (w
, &port_rect
);
9593 port_rect
= w
->portRect
;
9595 rows
= PIXEL_TO_CHAR_HEIGHT (f
, port_rect
.bottom
- port_rect
.top
);
9596 columns
= PIXEL_TO_CHAR_WIDTH (f
, port_rect
.right
- port_rect
.left
);
9597 x_set_window_size (mwp
->mFP
, 0, columns
, rows
);
9599 SetPort (save_port
);
9602 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
9604 init_mac_drag_n_drop ()
9606 OSErr result
= InstallReceiveHandler (mac_do_receive_drag
, 0L, NULL
);
9610 /* Intialize AppleEvent dispatcher table for the required events. */
9612 init_required_apple_events ()
9617 /* Make sure we have apple events before starting. */
9618 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
9622 if (!(result
& (1 << gestaltAppleEventsPresent
)))
9625 #if TARGET_API_MAC_CARBON
9626 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
9627 NewAEEventHandlerUPP
9628 ((AEEventHandlerProcPtr
) do_ae_open_application
),
9631 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
9632 NewAEEventHandlerProc
9633 ((AEEventHandlerProcPtr
) do_ae_open_application
),
9639 #if TARGET_API_MAC_CARBON
9640 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
9641 NewAEEventHandlerUPP
9642 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
9645 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
9646 NewAEEventHandlerProc
9647 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
9653 #if TARGET_API_MAC_CARBON
9654 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
9655 NewAEEventHandlerUPP
9656 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
9659 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
9660 NewAEEventHandlerProc
9661 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
9667 #if TARGET_API_MAC_CARBON
9668 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
9669 NewAEEventHandlerUPP
9670 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
9673 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
9674 NewAEEventHandlerProc
9675 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
9682 #if USE_CARBON_EVENTS
9685 init_service_handler ()
9687 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
9688 {kEventClassService
, kEventServiceCopy
},
9689 {kEventClassService
, kEventServicePaste
}};
9690 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
9691 3, specs
, NULL
, NULL
);
9695 MAC_TODO: Check to see if this is called by AEProcessDesc...
9698 mac_handle_service_event (EventHandlerCallRef callRef
,
9699 EventRef event
, void *data
)
9701 OSStatus err
= noErr
;
9702 switch (GetEventKind (event
))
9704 case kEventServiceGetTypes
:
9706 CFMutableArrayRef copyTypes
, pasteTypes
;
9708 Boolean selection
= true;
9710 GetEventParameter(event, kEventParamServicePasteTypes,
9711 typeCFMutableArrayRef, NULL,
9712 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
9714 GetEventParameter(event
, kEventParamServiceCopyTypes
,
9715 typeCFMutableArrayRef
, NULL
,
9716 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
9717 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
9719 CFArrayAppendValue (copyTypes
, type
);
9720 //CFArrayAppendValue (pasteTypes, type);
9724 case kEventServiceCopy
:
9726 ScrapRef currentScrap
, specificScrap
;
9730 GetCurrentScrap (¤tScrap
);
9732 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
9735 void *buffer
= xmalloc (byteCount
);
9738 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
9739 sizeof (ScrapRef
), NULL
, &specificScrap
);
9741 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
9742 &byteCount
, buffer
);
9744 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
9745 kScrapFlavorMaskNone
, byteCount
, buffer
);
9751 case kEventServicePaste
:
9754 // Get the current location
9756 ScrapRef specificScrap;
9757 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
9758 sizeof(ScrapRef), NULL, &specificScrap);
9759 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
9761 void * buffer = xmalloc(byteCount);
9762 if (buffer != NULL ) {
9763 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
9764 &byteCount, buffer);
9766 // Actually place in the buffer
9768 // Get the current "selection" string here
9781 /* Open Application Apple Event */
9783 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
9789 /* Defined in mac.c. */
9791 path_from_vol_dir_name (char *, int, short, long, char *);
9794 /* Called when we receive an AppleEvent with an ID of
9795 "kAEOpenDocuments". This routine gets the direct parameter,
9796 extracts the FSSpecs in it, and puts their names on a list. */
9798 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
9803 DescType actual_type
;
9806 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
9808 goto descriptor_error_exit
;
9810 /* Check to see that we got all of the required parameters from the
9811 event descriptor. For an 'odoc' event this should just be the
9813 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
9814 &actual_type
, (Ptr
) &keyword
,
9815 sizeof (keyword
), &actual_size
);
9816 /* No error means that we found some unused parameters.
9817 errAEDescNotFound means that there are no more parameters. If we
9818 get an error code other than that, flag it. */
9819 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
9821 err
= errAEEventNotHandled
;
9826 /* Got all the parameters we need. Now, go through the direct
9827 object list and parse it up. */
9829 long num_files_to_open
;
9831 err
= AECountItems (&the_desc
, &num_files_to_open
);
9836 /* AE file list is one based so just use that for indexing here. */
9837 for (i
= 1; (err
== noErr
) && (i
<= num_files_to_open
); i
++)
9840 Str255 path_name
, unix_path_name
;
9845 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
9846 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
9847 if (err
!= noErr
) break;
9850 err
= FSpMakeFSRef (&fs
, &fref
);
9851 if (err
!= noErr
) break;
9853 if (FSRefMakePath (&fref
, unix_path_name
, 255) == noErr
)
9855 if (path_from_vol_dir_name (path_name
, 255, fs
.vRefNum
, fs
.parID
,
9857 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
9859 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
9860 drag_and_drop_file_list
);
9866 /* Nuke the coerced file list in any case */
9867 err2
= AEDisposeDesc(&the_desc
);
9869 descriptor_error_exit
:
9870 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
9876 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9877 DragReference theDrag
)
9881 FlavorFlags theFlags
;
9884 ItemReference theItem
;
9887 Size size
= sizeof (HFSFlavor
);
9889 drag_and_drop_file_list
= Qnil
;
9890 GetDragMouse (theDrag
, &mouse
, 0L);
9891 CountDragItems (theDrag
, &items
);
9892 for (index
= 1; index
<= items
; index
++)
9894 /* Only handle file references. */
9895 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9896 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9897 if (result
== noErr
)
9904 Str255 unix_path_name
;
9905 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
9907 /* Use Carbon routines, otherwise it converts the file name
9908 to /Macintosh HD/..., which is not correct. */
9909 FSpMakeFSRef (&data
.fileSpec
, &fref
);
9910 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
9912 if (path_from_vol_dir_name (path_name
, 255, data
.fileSpec
.vRefNum
,
9913 data
.fileSpec
.parID
, data
.fileSpec
.name
) &&
9914 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
9916 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
9917 drag_and_drop_file_list
);
9922 /* If there are items in the list, construct an event and post it to
9923 the queue like an interrupt using kbd_buffer_store_event. */
9924 if (!NILP (drag_and_drop_file_list
))
9926 struct input_event event
;
9928 struct frame
*f
= ((mac_output
*) GetWRefCon(window
))->mFP
;
9929 SetPort (GetWindowPort (window
));
9930 GlobalToLocal (&mouse
);
9932 event
.kind
= DRAG_N_DROP_EVENT
;
9934 event
.modifiers
= 0;
9935 event
.timestamp
= TickCount () * (1000 / 60);
9936 XSETINT (event
.x
, mouse
.h
);
9937 XSETINT (event
.y
, mouse
.v
);
9938 XSETFRAME (frame
, f
);
9939 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
9941 /* Post to the interrupt queue */
9942 kbd_buffer_store_event (&event
);
9943 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9945 ProcessSerialNumber psn
;
9946 GetCurrentProcess (&psn
);
9947 SetFrontProcess (&psn
);
9953 /* Print Document Apple Event */
9955 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
9957 return errAEEventNotHandled
;
9962 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
9964 /* FixMe: Do we need an unwind-protect or something here? And what
9965 do we do about unsaved files. Currently just forces quit rather
9966 than doing recursive callback to get user input. */
9968 terminate_flag
= true;
9970 /* Fkill_emacs doesn't return. We have to return. (TI) */
9977 profiler_exit_proc ()
9979 ProfilerDump ("\pEmacs.prof");
9984 /* These few functions implement Emacs as a normal Mac application
9985 (almost): set up the heap and the Toolbox, handle necessary
9986 system events plus a few simple menu events. They also set up
9987 Emacs's access to functions defined in the rest of this file.
9988 Emacs uses function hooks to perform all its terminal I/O. A
9989 complete list of these functions appear in termhooks.h. For what
9990 they do, read the comments there and see also w32term.c and
9991 xterm.c. What's noticeably missing here is the event loop, which
9992 is normally present in most Mac application. After performing the
9993 necessary Mac initializations, main passes off control to
9994 emacs_main (corresponding to main in emacs.c). Emacs_main calls
9995 mac_read_socket (defined further below) to read input. This is
9996 where WaitNextEvent is called to process Mac events. This is also
9997 where check_alarm in sysdep.c is called to simulate alarm signals.
9998 This makes the cursor jump back to its correct position after
9999 briefly jumping to that of the matching parenthesis, print useful
10000 hints and prompts in the minibuffer after the user stops typing for
10003 #if !TARGET_API_MAC_CARBON
10008 #if __profile__ /* is the profiler on? */
10009 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
10014 /* set creator and type for files created by MSL */
10015 _fcreator
= 'EMAx';
10019 do_init_managers ();
10023 do_check_ram_size ();
10025 init_emacs_passwd_dir ();
10029 initialize_applescript ();
10031 init_required_apple_events ();
10037 /* set up argv array from STR# resource */
10038 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
10042 /* free up AppleScript resources on exit */
10043 atexit (terminate_applescript
);
10045 #if __profile__ /* is the profiler on? */
10046 atexit (profiler_exit_proc
);
10049 /* 3rd param "envp" never used in emacs_main */
10050 (void) emacs_main (argc
, argv
, 0);
10053 /* Never reached - real exit in Fkill_emacs */
10058 /* Table for translating Mac keycode to X keysym values. Contributed
10059 by Sudhir Shenoy. */
10060 static unsigned char keycode_to_xkeysym_table
[] = {
10061 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10062 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10063 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10065 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
10066 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
10067 /*0x38*/ 0, 0, 0, 0,
10068 /*0x3C*/ 0, 0, 0, 0,
10070 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
10071 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
10072 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
10073 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
10075 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
10076 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
10077 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
10078 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
10080 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
10081 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
10082 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
10083 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
10085 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
10086 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
10087 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
10088 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
10092 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
10094 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
10095 return *xKeySym
!= 0;
10098 /* Emacs calls this whenever it wants to read an input event from the
10101 XTread_socket (int sd
, struct input_event
*bufp
, int numchars
, int expected
)
10104 #if USE_CARBON_EVENTS
10105 OSStatus rneResult
;
10107 EventMouseButton mouseBtn
;
10111 EventMask event_mask
;
10114 if (interrupt_input_blocked
)
10116 interrupt_input_pending
= 1;
10121 interrupt_input_pending
= 0;
10124 /* So people can tell when we have read the available input. */
10125 input_signal_count
++;
10130 /* Don't poll for events to process (specifically updateEvt) if
10131 window update currently already in progress. A call to redisplay
10132 (in do_window_update) can be preempted by another call to
10133 redisplay, causing blank regions to be left on the screen and the
10134 cursor to be left at strange places. */
10135 if (handling_window_update
)
10141 if (terminate_flag
)
10142 Fkill_emacs (make_number (1));
10144 /* It is necessary to set this (additional) argument slot of an
10145 event to nil because keyboard.c protects incompletely processed
10146 event from being garbage collected by placing them in the
10147 kbd_buffer_gcpro vector. */
10150 event_mask
= everyEvent
;
10151 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
10152 event_mask
-= highLevelEventMask
;
10154 #if USE_CARBON_EVENTS
10155 rneResult
= ReceiveNextEvent (0, NULL
,
10157 ? TicksToEventTime (app_sleep_time
)
10159 kEventRemoveFromQueue
, &eventRef
);
10162 /* Handle new events */
10163 if (!mac_convert_event_ref (eventRef
, &er
))
10164 switch (GetEventClass (eventRef
))
10166 case kEventClassMouse
:
10167 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
10171 WindowPtr window_ptr
= FrontNonFloatingWindow ();
10172 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (window_ptr
);
10173 if (!IsValidWindowPtr (window_ptr
))
10180 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
10181 typeSInt32
, NULL
, sizeof (SInt32
),
10183 GetEventParameter(eventRef
, kEventParamMouseLocation
,
10184 typeQDPoint
, NULL
, sizeof (Point
),
10186 bufp
->kind
= MOUSE_WHEEL_EVENT
;
10187 bufp
->code
= delta
;
10188 bufp
->modifiers
= mac_event_to_emacs_modifiers(eventRef
);
10189 SetPort (GetWindowPort (window_ptr
));
10190 GlobalToLocal (&point
);
10191 XSETINT (bufp
->x
, point
.h
);
10192 XSETINT (bufp
->y
, point
.v
);
10193 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
10194 bufp
->timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
10198 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
10202 /* Send the event to the appropriate receiver. */
10203 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
10207 if (WaitNextEvent (event_mask
, &er
, (expected
? app_sleep_time
: 0L), NULL
))
10208 #endif /* USE_CARBON_EVENTS */
10214 WindowPtr window_ptr
= FrontWindow ();
10217 #if USE_CARBON_EVENTS
10218 /* This is needed to send mouse events like aqua window buttons
10219 to the correct handler. */
10220 if (eventNotHandledErr
!= SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ())) {
10224 if (!is_emacs_window(window_ptr
))
10228 if (mouse_tracking_in_progress
== mouse_tracking_scroll_bar
10229 && er
.what
== mouseUp
)
10231 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (window_ptr
);
10232 Point mouse_loc
= er
.where
;
10234 /* Convert to local coordinates of new window. */
10235 #if TARGET_API_MAC_CARBON
10236 SetPort (GetWindowPort (window_ptr
));
10238 SetPort (window_ptr
);
10241 GlobalToLocal (&mouse_loc
);
10243 #if USE_CARBON_EVENTS
10244 bufp
->code
= mac_get_mouse_btn (eventRef
);
10246 bufp
->code
= 0; /* only one mouse button */
10248 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
10249 bufp
->frame_or_window
= tracked_scroll_bar
->window
;
10250 bufp
->part
= scroll_bar_handle
;
10251 #if USE_CARBON_EVENTS
10252 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10254 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10256 bufp
->modifiers
|= up_modifier
;
10257 bufp
->timestamp
= er
.when
* (1000 / 60);
10258 /* ticks to milliseconds */
10260 XSETINT (bufp
->x
, tracked_scroll_bar
->left
+ 2);
10261 XSETINT (bufp
->y
, mouse_loc
.v
- 24);
10262 tracked_scroll_bar
->dragging
= Qnil
;
10263 mouse_tracking_in_progress
= mouse_tracking_none
;
10264 tracked_scroll_bar
= NULL
;
10269 part_code
= FindWindow (er
.where
, &window_ptr
);
10275 struct frame
*f
= ((mac_output
*)
10276 GetWRefCon (FrontWindow ()))->mFP
;
10277 saved_menu_event_location
= er
.where
;
10278 bufp
->kind
= MENU_BAR_ACTIVATE_EVENT
;
10279 XSETFRAME (bufp
->frame_or_window
, f
);
10285 if (window_ptr
!= FrontWindow ())
10286 SelectWindow (window_ptr
);
10289 SInt16 control_part_code
;
10291 struct mac_output
*mwp
= (mac_output
*)
10292 GetWRefCon (window_ptr
);
10293 Point mouse_loc
= er
.where
;
10295 /* convert to local coordinates of new window */
10296 #if TARGET_API_MAC_CARBON
10297 SetPort (GetWindowPort (window_ptr
));
10299 SetPort (window_ptr
);
10302 GlobalToLocal (&mouse_loc
);
10303 #if TARGET_API_MAC_CARBON
10304 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
10305 &control_part_code
);
10307 control_part_code
= FindControl (mouse_loc
, window_ptr
, &ch
);
10310 #if USE_CARBON_EVENTS
10311 bufp
->code
= mac_get_mouse_btn (eventRef
);
10313 bufp
->code
= 0; /* only one mouse button */
10315 XSETINT (bufp
->x
, mouse_loc
.h
);
10316 XSETINT (bufp
->y
, mouse_loc
.v
);
10317 bufp
->timestamp
= er
.when
* (1000 / 60);
10318 /* ticks to milliseconds */
10320 #if TARGET_API_MAC_CARBON
10323 if (control_part_code
!= 0)
10326 struct scroll_bar
*bar
= (struct scroll_bar
*)
10327 GetControlReference (ch
);
10328 x_scroll_bar_handle_click (bar
, control_part_code
, &er
,
10330 if (er
.what
== mouseDown
10331 && control_part_code
== kControlIndicatorPart
)
10333 mouse_tracking_in_progress
10334 = mouse_tracking_scroll_bar
;
10335 tracked_scroll_bar
= bar
;
10339 mouse_tracking_in_progress
= mouse_tracking_none
;
10340 tracked_scroll_bar
= NULL
;
10345 bufp
->kind
= MOUSE_CLICK_EVENT
;
10346 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
10347 if (er
.what
== mouseDown
)
10348 mouse_tracking_in_progress
10349 = mouse_tracking_mouse_movement
;
10351 mouse_tracking_in_progress
= mouse_tracking_none
;
10354 #if USE_CARBON_EVENTS
10355 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10357 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10363 bufp
->modifiers
|= down_modifier
;
10366 bufp
->modifiers
|= up_modifier
;
10375 #if TARGET_API_MAC_CARBON
10379 GetQDGlobalsScreenBits (&bm
);
10380 DragWindow (window_ptr
, er
.where
, &bm
.bounds
);
10382 #else /* not TARGET_API_MAC_CARBON */
10383 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
10384 #endif /* not TARGET_API_MAC_CARBON */
10388 if (TrackGoAway (window_ptr
, er
.where
))
10390 bufp
->kind
= DELETE_WINDOW_EVENT
;
10391 XSETFRAME (bufp
->frame_or_window
,
10392 ((mac_output
*) GetWRefCon (window_ptr
))->mFP
);
10397 /* window resize handling added --ben */
10399 do_grow_window(window_ptr
, &er
);
10402 /* window zoom handling added --ben */
10405 if (TrackBox (window_ptr
, er
.where
, part_code
))
10406 do_zoom_window (window_ptr
, part_code
);
10418 #if USE_CARBON_EVENTS
10419 if (eventNotHandledErr
== SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ()))
10427 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10430 #if USE_CARBON_EVENTS
10431 /* When using Carbon Events, we need to pass raw keyboard events
10432 to the TSM ourselves. If TSM handles it, it will pass back
10433 noErr, otherwise it will pass back "eventNotHandledErr" and
10434 we can process it normally. */
10435 if ((!NILP (Vmac_pass_command_to_system
)
10436 || !(er
.modifiers
& cmdKey
))
10437 && (!NILP (Vmac_pass_control_to_system
)
10438 || !(er
.modifiers
& controlKey
)))
10441 err
= SendEventToEventTarget (eventRef
,
10442 GetEventDispatcherTarget ());
10443 if (err
!= eventNotHandledErr
)
10448 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
10457 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10459 bufp
->code
= 0xff00 | xkeysym
;
10460 bufp
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10464 if (er
.modifiers
& (controlKey
|
10465 (NILP (Vmac_command_key_is_meta
) ? optionKey
10468 /* This code comes from Keyboard Resource, Appendix
10469 C of IM - Text. This is necessary since shift is
10470 ignored in KCHR table translation when option or
10471 command is pressed. It also does not translate
10472 correctly control-shift chars like C-% so mask off
10474 int new_modifiers
= er
.modifiers
& 0xe600;
10475 /* mask off option and command */
10476 int new_keycode
= keycode
| new_modifiers
;
10477 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10478 unsigned long some_state
= 0;
10479 bufp
->code
= KeyTranslate (kchr_ptr
, new_keycode
,
10480 &some_state
) & 0xff;
10483 bufp
->code
= er
.message
& charCodeMask
;
10484 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
10488 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
10489 convert non-ASCII characters typed at the Mac keyboard
10490 (presumed to be in the Mac Roman encoding) to iso-latin-1
10491 encoding before they are passed to Emacs. This enables the
10492 Mac keyboard to be used to enter non-ASCII iso-latin-1
10493 characters directly. */
10494 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
10495 && bufp
->kind
== ASCII_KEYSTROKE_EVENT
&& bufp
->code
>= 128)
10497 static TECObjectRef converter
= NULL
;
10498 OSStatus the_err
= noErr
;
10499 OSStatus convert_status
= noErr
;
10501 if (converter
== NULL
)
10503 the_err
= TECCreateConverter (&converter
,
10504 kTextEncodingMacRoman
,
10505 mac_keyboard_text_encoding
);
10506 current_mac_keyboard_text_encoding
10507 = mac_keyboard_text_encoding
;
10509 else if (mac_keyboard_text_encoding
10510 != current_mac_keyboard_text_encoding
)
10512 /* Free the converter for the current encoding before
10513 creating a new one. */
10514 TECDisposeConverter (converter
);
10515 the_err
= TECCreateConverter (&converter
,
10516 kTextEncodingMacRoman
,
10517 mac_keyboard_text_encoding
);
10518 current_mac_keyboard_text_encoding
10519 = mac_keyboard_text_encoding
;
10522 if (the_err
== noErr
)
10524 unsigned char ch
= bufp
->code
;
10525 ByteCount actual_input_length
, actual_output_length
;
10526 unsigned char outch
;
10528 convert_status
= TECConvertText (converter
, &ch
, 1,
10529 &actual_input_length
,
10531 &actual_output_length
);
10532 if (convert_status
== noErr
10533 && actual_input_length
== 1
10534 && actual_output_length
== 1)
10535 bufp
->code
= outch
;
10539 #if USE_CARBON_EVENTS
10540 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10542 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10547 = (mac_output
*) GetWRefCon (FrontNonFloatingWindow ());
10548 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
10551 bufp
->timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
10556 case kHighLevelEvent
:
10557 drag_and_drop_file_list
= Qnil
;
10559 AEProcessAppleEvent(&er
);
10561 /* Build a DRAG_N_DROP_EVENT type event as is done in
10562 constuct_drag_n_drop in w32term.c. */
10563 if (!NILP (drag_and_drop_file_list
))
10565 struct frame
*f
= NULL
;
10569 wp
= FrontNonFloatingWindow ();
10573 struct frame
*f
= XFRAME (XCAR (Vframe_list
));
10574 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
10575 wp
= FrontNonFloatingWindow ();
10578 if (wp
&& is_emacs_window(wp
))
10579 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
10581 bufp
->kind
= DRAG_N_DROP_EVENT
;
10583 bufp
->timestamp
= er
.when
* (1000 / 60);
10584 /* ticks to milliseconds */
10585 #if USE_CARBON_EVENTS
10586 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10588 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10591 XSETINT (bufp
->x
, 0);
10592 XSETINT (bufp
->y
, 0);
10594 XSETFRAME (frame
, f
);
10595 bufp
->frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
10597 /* Regardless of whether Emacs was suspended or in the
10598 foreground, ask it to redraw its entire screen.
10599 Otherwise parts of the screen can be left in an
10600 inconsistent state. */
10602 #if TARGET_API_MAC_CARBON
10606 GetWindowPortBounds (wp
, &r
);
10607 InvalWindowRect (wp
, &r
);
10609 #else /* not TARGET_API_MAC_CARBON */
10610 InvalRect (&(wp
->portRect
));
10611 #endif /* not TARGET_API_MAC_CARBON */
10618 #if USE_CARBON_EVENTS
10619 ReleaseEvent (eventRef
);
10623 /* If the focus was just given to an autoraising frame,
10625 /* ??? This ought to be able to handle more than one such frame. */
10626 if (pending_autoraise_frame
)
10628 x_raise_frame (pending_autoraise_frame
);
10629 pending_autoraise_frame
= 0;
10632 #if !TARGET_API_MAC_CARBON
10633 check_alarm (); /* simulate the handling of a SIGALRM */
10637 static Point old_mouse_pos
= { -1, -1 };
10639 if (app_is_suspended
)
10641 old_mouse_pos
.h
= -1;
10642 old_mouse_pos
.v
= -1;
10650 struct scroll_bar
*sb
;
10652 wp
= FrontWindow ();
10653 if (is_emacs_window (wp
))
10655 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
10657 #if TARGET_API_MAC_CARBON
10658 SetPort (GetWindowPort (wp
));
10663 GetMouse (&mouse_pos
);
10665 if (!EqualPt (mouse_pos
, old_mouse_pos
))
10667 if (mouse_tracking_in_progress
== mouse_tracking_scroll_bar
10668 && tracked_scroll_bar
)
10669 x_scroll_bar_note_movement (tracked_scroll_bar
,
10671 - XINT (tracked_scroll_bar
->top
),
10672 TickCount() * (1000 / 60));
10674 note_mouse_movement (f
, &mouse_pos
);
10676 old_mouse_pos
= mouse_pos
;
10688 /* Need to override CodeWarrior's input function so no conversion is
10689 done on newlines Otherwise compiled functions in .elc files will be
10690 read incorrectly. Defined in ...:MSL C:MSL
10691 Common:Source:buffer_io.c. */
10694 __convert_to_newlines (unsigned char * p
, size_t * n
)
10696 #pragma unused(p,n)
10700 __convert_from_newlines (unsigned char * p
, size_t * n
)
10702 #pragma unused(p,n)
10707 /* Initialize the struct pointed to by MW to represent a new COLS x
10708 ROWS Macintosh window, using font with name FONTNAME and size
10711 NewMacWindow (FRAME_PTR fp
)
10714 #if TARGET_API_MAC_CARBON
10715 static int making_terminal_window
= 0;
10717 static int making_terminal_window
= 1;
10720 mwp
= fp
->output_data
.mac
;
10722 if (making_terminal_window
)
10724 if (!(mwp
->mWP
= GetNewCWindow (TERM_WINDOW_RESOURCE
, NULL
,
10727 making_terminal_window
= 0;
10730 if (!(mwp
->mWP
= GetNewCWindow (WINDOW_RESOURCE
, NULL
, (WindowPtr
) -1)))
10733 SetWRefCon (mwp
->mWP
, (long) mwp
);
10734 /* so that update events can find this mac_output struct */
10735 mwp
->mFP
= fp
; /* point back to emacs frame */
10737 #if TARGET_API_MAC_CARBON
10738 SetPort (GetWindowPort (mwp
->mWP
));
10740 SetPort (mwp
->mWP
);
10745 SizeWindow (mwp
->mWP
, mwp
->pixel_width
, mwp
->pixel_height
, false);
10746 ShowWindow (mwp
->mWP
);
10752 make_mac_frame (struct frame
*f
)
10754 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10755 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10757 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10761 f
->output_data
.mac
->cursor_pixel
= 0;
10762 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10763 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10764 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10766 f
->output_data
.mac
->fontset
= -1;
10767 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
10768 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
10769 f
->output_data
.mac
->left_pos
= 4;
10770 f
->output_data
.mac
->top_pos
= 4;
10771 f
->output_data
.mac
->border_width
= 0;
10772 f
->output_data
.mac
->explicit_parent
= 0;
10774 f
->output_data
.mac
->internal_border_width
= 0;
10776 f
->output_method
= output_mac
;
10786 make_mac_terminal_frame (struct frame
*f
)
10790 XSETFRAME (frame
, f
);
10792 f
->output_method
= output_mac
;
10793 f
->output_data
.mac
= (struct mac_output
*)
10794 xmalloc (sizeof (struct mac_output
));
10795 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10796 f
->output_data
.mac
->fontset
= -1;
10797 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
10798 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
10800 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10805 make_mac_frame (f
);
10809 /* Need to be initialized for unshow_buffer in window.c. */
10810 selected_window
= f
->selected_window
;
10812 Fmodify_frame_parameters (frame
,
10813 Fcons (Fcons (Qfont
,
10814 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10815 Fmodify_frame_parameters (frame
,
10816 Fcons (Fcons (Qforeground_color
,
10817 build_string ("black")), Qnil
));
10818 Fmodify_frame_parameters (frame
,
10819 Fcons (Fcons (Qbackground_color
,
10820 build_string ("white")), Qnil
));
10824 /***********************************************************************
10826 ***********************************************************************/
10828 #ifdef USE_X_TOOLKIT
10829 static XrmOptionDescRec emacs_options
[] = {
10830 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
10831 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
10833 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
10834 XrmoptionSepArg
, NULL
},
10835 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
10837 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10838 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10839 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10840 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10841 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10842 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
10843 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
10845 #endif /* USE_X_TOOLKIT */
10847 #ifdef MULTI_KBOARD
10848 /* Test whether two display-name strings agree up to the dot that separates
10849 the screen number from the server number. */
10851 same_x_server (name1
, name2
)
10852 char *name1
, *name2
;
10854 int seen_colon
= 0;
10855 unsigned char *system_name
= SDATA (Vsystem_name
);
10856 int system_name_length
= strlen (system_name
);
10857 int length_until_period
= 0;
10859 while (system_name
[length_until_period
] != 0
10860 && system_name
[length_until_period
] != '.')
10861 length_until_period
++;
10863 /* Treat `unix' like an empty host name. */
10864 if (! strncmp (name1
, "unix:", 5))
10866 if (! strncmp (name2
, "unix:", 5))
10868 /* Treat this host's name like an empty host name. */
10869 if (! strncmp (name1
, system_name
, system_name_length
)
10870 && name1
[system_name_length
] == ':')
10871 name1
+= system_name_length
;
10872 if (! strncmp (name2
, system_name
, system_name_length
)
10873 && name2
[system_name_length
] == ':')
10874 name2
+= system_name_length
;
10875 /* Treat this host's domainless name like an empty host name. */
10876 if (! strncmp (name1
, system_name
, length_until_period
)
10877 && name1
[length_until_period
] == ':')
10878 name1
+= length_until_period
;
10879 if (! strncmp (name2
, system_name
, length_until_period
)
10880 && name2
[length_until_period
] == ':')
10881 name2
+= length_until_period
;
10883 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
10887 if (seen_colon
&& *name1
== '.')
10891 && (*name1
== '.' || *name1
== '\0')
10892 && (*name2
== '.' || *name2
== '\0'));
10896 int mac_initialized
= 0;
10899 mac_initialize_display_info ()
10901 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10902 GDHandle main_device_handle
;
10904 bzero (dpyinfo
, sizeof (*dpyinfo
));
10906 /* Put it on x_display_name_list. */
10907 x_display_name_list
= Fcons (Fcons (build_string ("Mac"), Qnil
),
10908 x_display_name_list
);
10909 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10912 dpyinfo
->mac_id_name
10913 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10914 + SCHARS (Vsystem_name
)
10916 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10917 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10919 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10920 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10923 main_device_handle
= LMGetMainDevice();
10925 dpyinfo
->reference_count
= 0;
10926 dpyinfo
->resx
= 75.0;
10927 dpyinfo
->resy
= 75.0;
10928 dpyinfo
->n_planes
= 1;
10929 dpyinfo
->n_cbits
= 16;
10930 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10931 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10932 dpyinfo
->grabbed
= 0;
10933 dpyinfo
->root_window
= NULL
;
10935 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10936 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10937 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10938 dpyinfo
->mouse_face_window
= Qnil
;
10941 struct mac_display_info
*
10942 mac_term_init (display_name
, xrm_option
, resource_name
)
10943 Lisp_Object display_name
;
10945 char *resource_name
;
10947 struct mac_display_info
*dpyinfo
;
10948 GDHandle main_device_handle
;
10950 if (!mac_initialized
)
10953 mac_initialized
= 1;
10956 mac_initialize_display_info (display_name
);
10958 dpyinfo
= &one_mac_display_info
;
10960 main_device_handle
= LMGetMainDevice();
10962 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10963 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10972 extern int inhibit_window_system
;
10973 extern int noninteractive
;
10974 CFBundleRef appsBundle
;
10977 /* No need to test if already -nw*/
10978 if (inhibit_window_system
|| noninteractive
)
10981 appsBundle
= CFBundleGetMainBundle();
10982 if (appsBundle
!= NULL
)
10984 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10985 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10986 /* We found the bundle identifier, now we know we are valid. */
10993 /* MAC_TODO: Have this start the bundled executable */
10995 /* For now, prevent the fatal error by bringing it up in the terminal */
10996 inhibit_window_system
= 1;
11000 MakeMeTheFrontProcess ()
11002 ProcessSerialNumber psn
;
11005 err
= GetCurrentProcess (&psn
);
11007 (void) SetFrontProcess (&psn
);
11010 /***** Code to handle C-g testing *****/
11012 /* Contains the Mac modifier formed from quit_char */
11013 static mac_quit_char_modifiers
= 0;
11014 static mac_quit_char_keycode
;
11015 extern int quit_char
;
11018 mac_determine_quit_char_modifiers()
11020 /* Todo: Determine modifiers from quit_char. */
11021 UInt32 qc_modifiers
= ctrl_modifier
;
11023 /* Map modifiers */
11024 mac_quit_char_modifiers
= 0;
11025 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
11026 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
11027 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
11028 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
11032 init_quit_char_handler ()
11034 /* TODO: Let this support keys other the 'g' */
11035 mac_quit_char_keycode
= 5;
11036 /* Look at <architecture/adb_kb_map.h> for details */
11037 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
11039 mac_determine_quit_char_modifiers();
11043 quit_char_comp (EventRef inEvent
, void *inCompData
)
11045 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
11047 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
11051 UInt32 keyModifiers
;
11052 GetEventParameter(inEvent
, kEventParamKeyCode
,
11053 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
11054 if (keyCode
!= mac_quit_char_keycode
)
11056 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
11057 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
11058 if (keyModifiers
!= mac_quit_char_modifiers
)
11065 mac_check_for_quit_char()
11068 /* If windows are not initialized, return immediately (keep it bouncin')*/
11069 if (!mac_quit_char_modifiers
)
11072 /* Redetermine modifiers because they are based on lisp variables */
11073 mac_determine_quit_char_modifiers();
11075 /* Fill the queue with events */
11076 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
11077 event
= FindSpecificEventInQueue (GetMainEventQueue(), quit_char_comp
, NULL
);
11080 struct input_event e
;
11081 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (FrontNonFloatingWindow ());
11082 /* Use an input_event to emulate what the interrupt handler does. */
11083 e
.kind
= ASCII_KEYSTROKE_EVENT
;
11084 e
.code
= quit_char
;
11086 e
.modifiers
= NULL
;
11087 e
.timestamp
= EventTimeToTicks(GetEventTime(event
))*(1000/60);
11088 XSETFRAME(e
.frame_or_window
, mwp
->mFP
);
11089 /* Remove event from queue to prevent looping. */
11090 RemoveEventFromQueue(GetMainEventQueue(), event
);
11091 ReleaseEvent(event
);
11092 kbd_buffer_store_event(&e
);
11096 #endif /* MAC_OSX */
11098 /* Set up use of X before we make the first connection. */
11100 static struct redisplay_interface x_redisplay_interface
=
11105 x_clear_end_of_line
,
11107 x_after_update_window_line
,
11108 x_update_window_begin
,
11109 x_update_window_end
,
11112 x_clear_mouse_face
,
11113 x_get_glyph_overhangs
,
11114 x_fix_overlapping_area
,
11115 x_draw_fringe_bitmap
,
11116 mac_per_char_metric
,
11118 NULL
, /* mac_compute_glyph_string_overhangs */
11119 x_draw_glyph_string
11125 rif
= &x_redisplay_interface
;
11127 clear_frame_hook
= x_clear_frame
;
11128 ins_del_lines_hook
= x_ins_del_lines
;
11129 delete_glyphs_hook
= x_delete_glyphs
;
11130 ring_bell_hook
= XTring_bell
;
11131 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11132 set_terminal_modes_hook
= XTset_terminal_modes
;
11133 update_begin_hook
= x_update_begin
;
11134 update_end_hook
= x_update_end
;
11135 set_terminal_window_hook
= XTset_terminal_window
;
11136 read_socket_hook
= XTread_socket
;
11137 frame_up_to_date_hook
= XTframe_up_to_date
;
11138 mouse_position_hook
= XTmouse_position
;
11139 frame_rehighlight_hook
= XTframe_rehighlight
;
11140 frame_raise_lower_hook
= XTframe_raise_lower
;
11142 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11143 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11144 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11145 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11147 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
11149 scroll_region_ok
= 1; /* we'll scroll partial frames */
11150 char_ins_del_ok
= 1;
11151 line_ins_del_ok
= 1; /* we'll just blt 'em */
11152 fast_clear_end_of_line
= 1; /* X does this well */
11153 memory_below_frame
= 0; /* we don't remember what scrolls
11158 last_tool_bar_item
= -1;
11159 any_help_event_p
= 0;
11161 /* Try to use interrupt input; if we can't, then start polling. */
11162 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11164 #ifdef USE_X_TOOLKIT
11165 XtToolkitInitialize ();
11166 Xt_app_con
= XtCreateApplicationContext ();
11167 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
11169 /* Install an asynchronous timer that processes Xt timeout events
11170 every 0.1s. This is necessary because some widget sets use
11171 timeouts internally, for example the LessTif menu bar, or the
11172 Xaw3d scroll bar. When Xt timouts aren't processed, these
11173 widgets don't behave normally. */
11175 EMACS_TIME interval
;
11176 EMACS_SET_SECS_USECS (interval
, 0, 100000);
11177 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
11181 #if USE_TOOLKIT_SCROLL_BARS
11182 xaw3d_arrow_scroll
= False
;
11183 xaw3d_pick_top
= True
;
11187 /* Note that there is no real way portable across R3/R4 to get the
11188 original error handler. */
11189 XSetErrorHandler (x_error_handler
);
11190 XSetIOErrorHandler (x_io_error_quitter
);
11192 /* Disable Window Change signals; they are handled by X events. */
11194 signal (SIGWINCH
, SIG_DFL
);
11195 #endif /* ! defined (SIGWINCH) */
11197 signal (SIGPIPE
, x_connection_signal
);
11200 mac_initialize_display_info ();
11202 #if TARGET_API_MAC_CARBON
11203 init_required_apple_events ();
11205 init_mac_drag_n_drop ();
11207 #if USE_CARBON_EVENTS
11208 init_service_handler ();
11210 init_quit_char_handler ();
11213 DisableMenuCommand (NULL
, kHICommandQuit
);
11215 if (!inhibit_window_system
)
11216 MakeMeTheFrontProcess ();
11225 staticpro (&x_error_message_string
);
11226 x_error_message_string
= Qnil
;
11229 Fprovide (intern ("mac-carbon"), Qnil
);
11231 staticpro (&x_display_name_list
);
11232 x_display_name_list
= Qnil
;
11234 staticpro (&last_mouse_scroll_bar
);
11235 last_mouse_scroll_bar
= Qnil
;
11237 staticpro (&Qvendor_specific_keysyms
);
11238 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
11240 staticpro (&last_mouse_press_frame
);
11241 last_mouse_press_frame
= Qnil
;
11243 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
11244 staticpro (&Qmac_ready_for_drag_n_drop
);
11247 staticpro (&help_echo
);
11248 help_echo_object
= Qnil
;
11249 staticpro (&help_echo_object
);
11250 help_echo_window
= Qnil
;
11251 staticpro (&help_echo_window
);
11252 previous_help_echo
= Qnil
;
11253 staticpro (&previous_help_echo
);
11254 help_echo_pos
= -1;
11256 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
11257 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
11258 x_autoselect_window_p
= 0;
11260 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
11261 doc
: /* *Non-nil means draw block cursor as wide as the glyph under it.
11262 For example, if a block cursor is over a tab, it will be drawn as
11263 wide as that tab on the display. */);
11264 x_stretch_cursor_p
= 0;
11266 #if 0 /* TODO: Setting underline position from font properties. */
11267 DEFVAR_BOOL ("x-use-underline-position-properties",
11268 &x_use_underline_position_properties
,
11269 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11270 nil means ignore them. If you encounter fonts with bogus
11271 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11272 to 4.1, set this to nil. */);
11273 x_use_underline_position_properties
= 1;
11276 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
11277 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
11278 Vx_toolkit_scroll_bars
= Qt
;
11280 staticpro (&last_mouse_motion_frame
);
11281 last_mouse_motion_frame
= Qnil
;
11283 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
11284 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
11285 Otherwise the option key is used. */);
11286 Vmac_command_key_is_meta
= Qt
;
11288 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
11289 doc
: /* Non-nil means that the control and meta keys are reversed. This is
11290 useful for non-standard keyboard layouts. */);
11291 Vmac_reverse_ctrl_meta
= Qnil
;
11293 #if USE_CARBON_EVENTS
11294 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
11295 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
11296 the right click will be mouse-3.
11297 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
11298 Vmac_wheel_button_is_mouse_2
= Qt
;
11300 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
11301 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
11302 Toolbox for processing before Emacs sees it. */);
11303 Vmac_pass_command_to_system
= Qt
;
11305 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
11306 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
11307 Toolbox for processing before Emacs sees it. */);
11308 Vmac_pass_control_to_system
= Qt
;
11311 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
11312 doc
: /* One of the Text Encoding Base constant values defined in the
11313 Basic Text Constants section of Inside Macintosh - Text Encoding
11314 Conversion Manager. Its value determines the encoding characters
11315 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
11316 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
11317 its default value, no conversion takes place. If it is set to
11318 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
11319 characters typed on Mac keyboard are first converted into the
11320 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
11321 passed to Emacs. Together with Emacs's set-keyboard-coding-system
11322 command, this enables the Mac keyboard to be used to enter non-ASCII
11323 characters directly. */);
11324 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;