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)
123 /* Fringe bitmaps. */
125 enum fringe_bitmap_type
128 LEFT_TRUNCATION_BITMAP
,
129 RIGHT_TRUNCATION_BITMAP
,
130 OVERLAY_ARROW_BITMAP
,
131 CONTINUED_LINE_BITMAP
,
132 CONTINUATION_LINE_BITMAP
,
136 /* Bitmap drawn to indicate lines not displaying text if
137 `indicate-empty-lines' is non-nil. */
142 static unsigned char zv_bits
[] = {
143 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
144 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
145 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
146 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
147 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
148 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
149 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
150 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
152 /* An arrow like this: `<-'. */
155 #define left_height 8
156 static unsigned char left_bits
[] = {
157 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
159 /* Right truncation arrow bitmap `->'. */
161 #define right_width 8
162 #define right_height 8
163 static unsigned char right_bits
[] = {
164 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
166 /* Marker for continued lines. */
168 #define continued_width 8
169 #define continued_height 8
170 static unsigned char continued_bits
[] = {
171 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
173 /* Marker for continuation lines. */
175 #define continuation_width 8
176 #define continuation_height 8
177 static unsigned char continuation_bits
[] = {
178 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
180 /* Overlay arrow bitmap. */
186 static unsigned char ov_bits
[] = {
187 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
189 /* A triangular arrow. */
192 static unsigned char ov_bits
[] = {
193 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
196 extern Lisp_Object Qhelp_echo
;
199 /* Non-nil means Emacs uses toolkit scroll bars. */
201 Lisp_Object Vx_toolkit_scroll_bars
;
203 /* If a string, XTread_socket generates an event to display that string.
204 (The display is done in read_char.) */
206 static Lisp_Object help_echo
;
207 static Lisp_Object help_echo_window
;
208 static Lisp_Object help_echo_object
;
209 static int help_echo_pos
;
211 /* Temporary variable for XTread_socket. */
213 static Lisp_Object previous_help_echo
;
215 /* Non-zero means that a HELP_EVENT has been generated since Emacs
218 static int any_help_event_p
;
220 /* Non-zero means autoselect window with the mouse cursor. */
222 int x_autoselect_window_p
;
224 /* Non-zero means draw block and hollow cursor as wide as the glyph
225 under it. For example, if a block cursor is over a tab, it will be
226 drawn as wide as that tab on the display. */
228 int x_stretch_cursor_p
;
230 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
232 int x_use_underline_position_properties
;
234 /* This is a chain of structures for all the X displays currently in
237 struct x_display_info
*x_display_list
;
239 /* This is a list of cons cells, each of the form (NAME
240 . FONT-LIST-CACHE), one for each element of x_display_list and in
241 the same order. NAME is the name of the frame. FONT-LIST-CACHE
242 records previous values returned by x-list-fonts. */
244 Lisp_Object x_display_name_list
;
246 /* This is display since Mac does not support multiple ones. */
247 struct mac_display_info one_mac_display_info
;
249 /* Frame being updated by update_frame. This is declared in term.c.
250 This is set by update_begin and looked at by all the XT functions.
251 It is zero while not inside an update. In that case, the XT
252 functions assume that `selected_frame' is the frame to apply to. */
254 extern struct frame
*updating_frame
;
256 extern int waiting_for_input
;
258 /* This is a frame waiting to be auto-raised, within XTread_socket. */
260 struct frame
*pending_autoraise_frame
;
262 /* Nominal cursor position -- where to draw output.
263 HPOS and VPOS are window relative glyph matrix coordinates.
264 X and Y are window relative pixel coordinates. */
266 struct cursor_pos output_cursor
;
268 /* Non-zero means user is interacting with a toolkit scroll bar. */
270 static int toolkit_scroll_bar_interaction
;
274 Formerly, we used PointerMotionHintMask (in standard_event_mask)
275 so that we would have to call XQueryPointer after each MotionNotify
276 event to ask for another such event. However, this made mouse tracking
277 slow, and there was a bug that made it eventually stop.
279 Simply asking for MotionNotify all the time seems to work better.
281 In order to avoid asking for motion events and then throwing most
282 of them away or busy-polling the server for mouse positions, we ask
283 the server for pointer motion hints. This means that we get only
284 one event per group of mouse movements. "Groups" are delimited by
285 other kinds of events (focus changes and button clicks, for
286 example), or by XQueryPointer calls; when one of these happens, we
287 get another MotionNotify event the next time the mouse moves. This
288 is at least as efficient as getting motion events when mouse
289 tracking is on, and I suspect only negligibly worse when tracking
292 /* Where the mouse was last time we reported a mouse event. */
294 FRAME_PTR last_mouse_frame
;
295 static Rect last_mouse_glyph
;
296 static Lisp_Object last_mouse_press_frame
;
298 /* The scroll bar in which the last X motion event occurred.
300 If the last X motion event occurred in a scroll bar, we set this so
301 XTmouse_position can know whether to report a scroll bar motion or
304 If the last X motion event didn't occur in a scroll bar, we set
305 this to Qnil, to tell XTmouse_position to return an ordinary motion
308 static Lisp_Object last_mouse_scroll_bar
;
310 /* This is a hack. We would really prefer that XTmouse_position would
311 return the time associated with the position it returns, but there
312 doesn't seem to be any way to wrest the time-stamp from the server
313 along with the position query. So, we just keep track of the time
314 of the last movement we received, and return that in hopes that
315 it's somewhat accurate. */
317 static Time last_mouse_movement_time
;
319 enum mouse_tracking_type
{
321 mouse_tracking_mouse_movement
,
322 mouse_tracking_scroll_bar
325 enum mouse_tracking_type mouse_tracking_in_progress
= mouse_tracking_none
;
327 struct scroll_bar
*tracked_scroll_bar
= NULL
;
329 /* Incremented by XTread_socket whenever it really tries to read
333 static int volatile input_signal_count
;
335 static int input_signal_count
;
338 /* Used locally within XTread_socket. */
340 static int x_noop_count
;
342 /* Initial values of argv and argc. */
344 extern char **initial_argv
;
345 extern int initial_argc
;
347 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
349 /* Tells if a window manager is present or not. */
351 extern Lisp_Object Vx_no_window_manager
;
353 extern Lisp_Object Qface
, Qmouse_face
;
357 /* A mask of extra modifier bits to put into every keyboard char. */
359 extern int extra_keyboard_modifiers
;
361 static Lisp_Object Qvendor_specific_keysyms
;
364 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
367 extern Lisp_Object x_icon_type
P_ ((struct frame
*));
369 extern int inhibit_window_system
;
372 QDGlobals qd
; /* QuickDraw global information structure. */
376 /* Enumeration for overriding/changing the face to use for drawing
377 glyphs in x_draw_glyphs. */
379 enum draw_glyphs_face
389 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
390 struct mac_display_info
*mac_display_info_for_display (Display
*);
391 static void x_update_window_end
P_ ((struct window
*, int, int));
392 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
393 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
394 int *, int *, Lisp_Object
));
395 static int fast_find_string_pos
P_ ((struct window
*, int, Lisp_Object
,
396 int *, int *, int *, int *, int));
397 static void set_output_cursor
P_ ((struct cursor_pos
*));
398 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
399 int *, int *, int *, int));
400 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
401 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
402 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
403 static void x_handle_tool_bar_click
P_ ((struct frame
*, EventRecord
*));
404 static void show_mouse_face
P_ ((struct x_display_info
*,
405 enum draw_glyphs_face
));
406 static int cursor_in_mouse_face_p
P_ ((struct window
*));
407 static int clear_mouse_face
P_ ((struct mac_display_info
*));
408 static int x_io_error_quitter
P_ ((Display
*));
409 int x_catch_errors
P_ ((Display
*));
410 void x_uncatch_errors
P_ ((Display
*, int));
411 void x_lower_frame
P_ ((struct frame
*));
412 void x_scroll_bar_clear
P_ ((struct frame
*));
413 int x_had_errors_p
P_ ((Display
*));
414 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
415 void x_raise_frame
P_ ((struct frame
*));
416 void x_set_window_size
P_ ((struct frame
*, int, int, int));
417 void x_wm_set_window_state
P_ ((struct frame
*, int));
418 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
419 void mac_initialize
P_ ((void));
420 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
421 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
422 enum text_cursor_kinds x_specified_cursor_type
P_ ((Lisp_Object
, int *));
423 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
425 enum draw_glyphs_face
));
426 static void x_update_end
P_ ((struct frame
*));
427 static void XTframe_up_to_date
P_ ((struct frame
*));
428 static void XTreassert_line_highlight
P_ ((int, int));
429 static void x_change_line_highlight
P_ ((int, int, int, int));
430 static void XTset_terminal_modes
P_ ((void));
431 static void XTreset_terminal_modes
P_ ((void));
432 static void XTcursor_to
P_ ((int, int, int, int));
433 static void x_write_glyphs
P_ ((struct glyph
*, int));
434 static void x_clear_end_of_line
P_ ((int));
435 static void x_clear_frame
P_ ((void));
436 static void x_clear_cursor
P_ ((struct window
*));
437 static void frame_highlight
P_ ((struct frame
*));
438 static void frame_unhighlight
P_ ((struct frame
*));
439 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
440 static void XTframe_rehighlight
P_ ((struct frame
*));
441 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
442 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
443 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int));
444 static int x_intersect_rectangles
P_ ((Rect
*, Rect
*, Rect
*));
445 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
446 static int expose_window_tree
P_ ((struct window
*, Rect
*));
447 static int expose_window
P_ ((struct window
*, Rect
*));
448 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
449 Rect
*, enum glyph_row_area
));
450 static int expose_line
P_ ((struct window
*, struct glyph_row
*,
452 void x_display_cursor (struct window
*, int, int, int, int, int);
453 void x_update_cursor
P_ ((struct frame
*, int));
454 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
455 static void x_update_window_cursor
P_ ((struct window
*, int));
456 static void x_erase_phys_cursor
P_ ((struct window
*));
457 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
458 static void x_draw_fringe_bitmap
P_ ((struct window
*, struct glyph_row
*,
459 enum fringe_bitmap_type
, int left_p
));
460 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
462 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, Rect
*));
463 static void x_draw_row_fringe_bitmaps
P_ ((struct window
*, struct glyph_row
*));
464 static void notice_overwritten_cursor
P_ ((struct window
*,
466 int, int, int, int));
467 static void x_flush
P_ ((struct frame
*f
));
468 static void x_update_begin
P_ ((struct frame
*));
469 static void x_update_window_begin
P_ ((struct window
*));
470 static void x_draw_vertical_border
P_ ((struct window
*));
471 static void x_after_update_window_line
P_ ((struct glyph_row
*));
472 static INLINE
void take_vertical_position_into_account
P_ ((struct it
*));
473 static void x_produce_stretch_glyph
P_ ((struct it
*));
475 static void activate_scroll_bars (FRAME_PTR
);
476 static void deactivate_scroll_bars (FRAME_PTR
);
478 extern int image_ascent (struct image
*, struct face
*);
479 void x_set_offset (struct frame
*, int, int, int);
480 int x_bitmap_icon (struct frame
*, Lisp_Object
);
481 void x_make_frame_visible (struct frame
*);
483 extern void window_scroll (Lisp_Object
, int, int, int);
485 /* Defined in macmenu.h. */
486 extern void menubar_selection_callback (FRAME_PTR
, int);
487 extern void set_frame_menubar (FRAME_PTR
, int, int);
489 /* X display function emulation */
491 /* Structure borrowed from Xlib.h to represent two-byte characters in
500 XFreePixmap (display
, pixmap
)
504 PixMap
*p
= (PixMap
*) pixmap
;
511 /* Set foreground color for subsequent QuickDraw commands. Assume
512 graphic port has already been set. */
515 mac_set_forecolor (unsigned long color
)
519 fg_color
.red
= RED_FROM_ULONG (color
) * 256;
520 fg_color
.green
= GREEN_FROM_ULONG (color
) * 256;
521 fg_color
.blue
= BLUE_FROM_ULONG (color
) * 256;
523 RGBForeColor (&fg_color
);
527 /* Set background color for subsequent QuickDraw commands. Assume
528 graphic port has already been set. */
531 mac_set_backcolor (unsigned long color
)
535 bg_color
.red
= RED_FROM_ULONG (color
) * 256;
536 bg_color
.green
= GREEN_FROM_ULONG (color
) * 256;
537 bg_color
.blue
= BLUE_FROM_ULONG (color
) * 256;
539 RGBBackColor (&bg_color
);
542 /* Set foreground and background color for subsequent QuickDraw
543 commands. Assume that the graphic port has already been set. */
546 mac_set_colors (GC gc
)
548 mac_set_forecolor (gc
->foreground
);
549 mac_set_backcolor (gc
->background
);
552 /* Mac version of XDrawLine. */
555 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
561 #if TARGET_API_MAC_CARBON
562 SetPort (GetWindowPort (w
));
573 /* Mac version of XClearArea. */
576 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
580 unsigned int width
, height
;
583 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
587 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
588 xgc
.background
= mwp
->x_compatible
.background_pixel
;
590 #if TARGET_API_MAC_CARBON
591 SetPort (GetWindowPort (w
));
596 mac_set_colors (&xgc
);
597 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
602 /* Mac version of XClearWindow. */
605 XClearWindow (display
, w
)
609 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
612 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
613 xgc
.background
= mwp
->x_compatible
.background_pixel
;
615 #if TARGET_API_MAC_CARBON
616 SetPort (GetWindowPort (w
));
621 mac_set_colors (&xgc
);
623 #if TARGET_API_MAC_CARBON
627 GetWindowPortBounds (w
, &r
);
630 #else /* not TARGET_API_MAC_CARBON */
631 EraseRect (&(w
->portRect
));
632 #endif /* not TARGET_API_MAC_CARBON */
636 /* Mac replacement for XCopyArea. */
639 mac_draw_bitmap (display
, w
, gc
, x
, y
, bitmap
)
648 #if TARGET_API_MAC_CARBON
649 SetPort (GetWindowPort (w
));
655 SetRect (&r
, x
, y
, x
+ bitmap
->bounds
.right
, y
+ bitmap
->bounds
.bottom
);
657 #if TARGET_API_MAC_CARBON
661 LockPortBits (GetWindowPort (w
));
662 pmh
= GetPortPixMap (GetWindowPort (w
));
663 CopyBits (bitmap
, (BitMap
*) *pmh
, &(bitmap
->bounds
), &r
, srcCopy
, 0);
664 UnlockPortBits (GetWindowPort (w
));
666 #else /* not TARGET_API_MAC_CARBON */
667 CopyBits (bitmap
, &(w
->portBits
), &(bitmap
->bounds
), &r
, srcCopy
, 0);
668 #endif /* not TARGET_API_MAC_CARBON */
672 /* Mac replacement for XSetClipRectangles. */
675 mac_set_clip_rectangle (display
, w
, r
)
680 #if TARGET_API_MAC_CARBON
681 SetPort (GetWindowPort (w
));
690 /* Mac replacement for XSetClipMask. */
693 mac_reset_clipping (display
, w
)
699 #if TARGET_API_MAC_CARBON
700 SetPort (GetWindowPort (w
));
705 SetRect (&r
, -32767, -32767, 32767, 32767);
710 /* Mac replacement for XCreateBitmapFromBitmapData. */
713 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
718 int bytes_per_row
, i
, j
;
720 bitmap
->rowBytes
= (w
+ 15) / 16 * 2; /* must be on word boundary */
721 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
722 if (!bitmap
->baseAddr
)
725 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
726 for (i
= 0; i
< h
; i
++)
727 for (j
= 0; j
< w
; j
++)
728 if (BitTst (bits
, i
* w
+ j
))
729 BitSet (bitmap
->baseAddr
, i
* bitmap
->rowBytes
* 8 + j
);
731 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
736 mac_free_bitmap (bitmap
)
739 xfree (bitmap
->baseAddr
);
742 /* Mac replacement for XFillRectangle. */
745 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
750 unsigned int width
, height
;
754 #if TARGET_API_MAC_CARBON
755 SetPort (GetWindowPort (w
));
761 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
763 PaintRect (&r
); /* using foreground color of gc */
767 /* Mac replacement for XDrawRectangle: dest is a window. */
770 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
775 unsigned int width
, height
;
779 #if TARGET_API_MAC_CARBON
780 SetPort (GetWindowPort (w
));
786 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
788 FrameRect (&r
); /* using foreground color of gc */
792 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
795 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
800 unsigned int width
, height
;
802 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
805 #if TARGET_API_MAC_CARBON
806 SetPort (GetWindowPort (w
));
812 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
814 FrameRect (&r
); /* using foreground color of gc */
820 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
827 int nchars
, mode
, bytes_per_char
;
829 #if TARGET_API_MAC_CARBON
830 SetPort (GetWindowPort (w
));
837 TextFont (gc
->font
->mac_fontnum
);
838 TextSize (gc
->font
->mac_fontsize
);
839 TextFace (gc
->font
->mac_fontface
);
843 DrawText (buf
, 0, nchars
* bytes_per_char
);
847 /* Mac replacement for XDrawString. */
850 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
858 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
862 /* Mac replacement for XDrawString16. */
865 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
873 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
878 /* Mac replacement for XDrawImageString. */
881 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
889 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
893 /* Mac replacement for XDrawString16. */
896 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
904 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
909 /* Mac replacement for XCopyArea: dest must be window. */
912 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
919 unsigned int width
, height
;
924 #if TARGET_API_MAC_CARBON
925 SetPort (GetWindowPort (dest
));
932 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
933 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
935 #if TARGET_API_MAC_CARBON
939 LockPortBits (GetWindowPort (dest
));
940 pmh
= GetPortPixMap (GetWindowPort (dest
));
941 CopyBits ((BitMap
*) &src
, (BitMap
*) *pmh
, &src_r
, &dest_r
, srcCopy
, 0);
942 UnlockPortBits (GetWindowPort (dest
));
944 #else /* not TARGET_API_MAC_CARBON */
945 CopyBits ((BitMap
*) &src
, &(dest
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
946 #endif /* not TARGET_API_MAC_CARBON */
951 /* Convert a pair of local coordinates to global (screen) coordinates.
952 Assume graphic port has been properly set. */
954 local_to_global_coord (short *h
, short *v
)
968 /* Mac replacement for XCopyArea: used only for scrolling. */
971 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
976 unsigned int width
, height
;
979 #if TARGET_API_MAC_CARBON
980 Rect gw_r
, src_r
, dest_r
;
983 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
984 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
986 SetPort (GetWindowPort (w
));
988 ForeColor (blackColor
);
989 BackColor (whiteColor
);
991 LockPortBits (GetWindowPort (w
));
992 pmh
= GetPortPixMap (GetWindowPort (w
));
993 CopyBits ((BitMap
*) *pmh
, (BitMap
*) *pmh
, &src_r
, &dest_r
, srcCopy
, 0);
994 UnlockPortBits (GetWindowPort (w
));
997 #else /* not TARGET_API_MAC_CARBON */
1002 mac_set_colors (gc
);
1005 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1006 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1009 /* Need to use global coordinates and screenBits since src and dest
1010 areas overlap in general. */
1011 local_to_global_coord (&src_r
.left
, &src_r
.top
);
1012 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
1013 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
1014 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
1016 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
1018 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1019 color mapping in CopyBits. Otherwise, it will be slow. */
1020 ForeColor (blackColor
);
1021 BackColor (whiteColor
);
1022 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1024 mac_set_colors (gc
);
1026 #endif /* not TARGET_API_MAC_CARBON */
1030 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1033 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
1040 unsigned int width
, height
;
1044 int src_right
= ((PixMap
*) src
)->bounds
.right
;
1045 int src_bottom
= ((PixMap
*) src
)->bounds
.bottom
;
1046 int w
= src_right
- src_x
;
1047 int h
= src_bottom
- src_y
;
1049 mac_set_colors (gc
);
1051 SetRect (&src_r
, src_x
, src_y
, src_right
, src_bottom
);
1052 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ w
, dest_y
+ h
);
1054 CopyBits ((BitMap
*) &src
, (BitMap
*) &dest
, &src_r
, &dest_r
, srcCopy
, 0);
1058 /* Mac replacement for XChangeGC. */
1061 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1064 if (mask
& GCForeground
)
1065 gc
->foreground
= xgcv
->foreground
;
1066 if (mask
& GCBackground
)
1067 gc
->background
= xgcv
->background
;
1069 gc
->font
= xgcv
->font
;
1073 /* Mac replacement for XCreateGC. */
1076 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1079 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1080 bzero (gc
, sizeof (XGCValues
));
1082 XChangeGC (ignore
, gc
, mask
, xgcv
);
1088 /* Used in xfaces.c. */
1091 XFreeGC (display
, gc
)
1099 /* Mac replacement for XGetGCValues. */
1102 XGetGCValues (void* ignore
, XGCValues
*gc
,
1103 unsigned long mask
, XGCValues
*xgcv
)
1105 XChangeGC (ignore
, xgcv
, mask
, gc
);
1109 /* Mac replacement for XSetForeground. */
1112 XSetForeground (display
, gc
, color
)
1115 unsigned long color
;
1117 gc
->foreground
= color
;
1121 /* Mac replacement for XSetFont. */
1124 XSetFont (display
, gc
, font
)
1134 XTextExtents16 (XFontStruct
*font
, XChar2b
*text
, int nchars
,
1135 int *direction
,int *font_ascent
,
1136 int *font_descent
, XCharStruct
*cs
)
1138 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1142 /* x_sync is a no-op on Mac. */
1150 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1151 Calls to XFlush should be unnecessary because the X output buffer
1152 is flushed automatically as needed by calls to XPending,
1153 XNextEvent, or XWindowEvent according to the XFlush man page.
1154 XTread_socket calls XPending. Removing XFlush improves
1157 #if TARGET_API_MAC_CARBON
1158 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1160 #define XFlush(DISPLAY) (void) 0
1163 /* Flush display of frame F, or of all frames if F is null. */
1169 #if TARGET_API_MAC_CARBON
1173 Lisp_Object rest
, frame
;
1174 FOR_EACH_FRAME (rest
, frame
)
1175 x_flush (XFRAME (frame
));
1177 else if (FRAME_X_P (f
))
1178 XFlush (FRAME_MAC_DISPLAY (f
));
1180 #endif /* TARGET_API_MAC_CARBON */
1185 /* Return the struct mac_display_info corresponding to DPY. There's
1188 struct mac_display_info
*
1189 mac_display_info_for_display (dpy
)
1192 return &one_mac_display_info
;
1197 /***********************************************************************
1198 Starting and ending an update
1199 ***********************************************************************/
1201 /* Start an update of frame F. This function is installed as a hook
1202 for update_begin, i.e. it is called when update_begin is called.
1203 This function is called prior to calls to x_update_window_begin for
1204 each window being updated. */
1210 /* Nothing to do. */
1214 /* Start update of window W. Set the global variable updated_window
1215 to the window being updated and set output_cursor to the cursor
1219 x_update_window_begin (w
)
1222 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1223 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1226 set_output_cursor (&w
->cursor
);
1230 if (f
== display_info
->mouse_face_mouse_frame
)
1232 /* Don't do highlighting for mouse motion during the update. */
1233 display_info
->mouse_face_defer
= 1;
1235 /* If F needs to be redrawn, simply forget about any prior mouse
1237 if (FRAME_GARBAGED_P (f
))
1238 display_info
->mouse_face_window
= Qnil
;
1240 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1241 their mouse_face_p flag set, which means that they are always
1242 unequal to rows in a desired matrix which never have that
1243 flag set. So, rows containing mouse-face glyphs are never
1244 scrolled, and we don't have to switch the mouse highlight off
1245 here to prevent it from being scrolled. */
1247 /* Can we tell that this update does not affect the window
1248 where the mouse highlight is? If so, no need to turn off.
1249 Likewise, don't do anything if the frame is garbaged;
1250 in that case, the frame's current matrix that we would use
1251 is all wrong, and we will redisplay that line anyway. */
1252 if (!NILP (display_info
->mouse_face_window
)
1253 && w
== XWINDOW (display_info
->mouse_face_window
))
1257 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1258 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1261 if (i
< w
->desired_matrix
->nrows
)
1262 clear_mouse_face (display_info
);
1271 /* Draw a vertical window border to the right of window W if W doesn't
1272 have vertical scroll bars. */
1275 x_draw_vertical_border (w
)
1278 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1280 /* Redraw borders between horizontally adjacent windows. Don't
1281 do it for frames with vertical scroll bars because either the
1282 right scroll bar of a window, or the left scroll bar of its
1283 neighbor will suffice as a border. */
1284 if (!WINDOW_RIGHTMOST_P (w
)
1285 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1289 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
1290 x1
+= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
1293 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1294 f
->output_data
.mac
->normal_gc
, x1
, y0
, x1
, y1
);
1299 /* End update of window W (which is equal to updated_window).
1301 Draw vertical borders between horizontally adjacent windows, and
1302 display W's cursor if CURSOR_ON_P is non-zero.
1304 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1305 glyphs in mouse-face were overwritten. In that case we have to
1306 make sure that the mouse-highlight is properly redrawn.
1308 W may be a menu bar pseudo-window in case we don't have X toolkit
1309 support. Such windows don't have a cursor, so don't display it
1313 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1315 int cursor_on_p
, mouse_face_overwritten_p
;
1317 struct mac_display_info
*dpyinfo
1318 = FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1320 if (!w
->pseudo_window_p
)
1325 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1327 output_cursor
.x
, output_cursor
.y
);
1329 x_draw_vertical_border (w
);
1333 /* If a row with mouse-face was overwritten, arrange for
1334 XTframe_up_to_date to redisplay the mouse highlight. */
1335 if (mouse_face_overwritten_p
)
1337 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1338 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1339 dpyinfo
->mouse_face_window
= Qnil
;
1343 /* Unhide the caret. This won't actually show the cursor, unless it
1344 was visible before the corresponding call to HideCaret in
1345 x_update_window_begin. */
1346 if (w32_use_visible_system_caret
)
1347 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1350 updated_window
= NULL
;
1354 /* End update of frame F. This function is installed as a hook in
1361 /* Reset the background color of Mac OS Window to that of the frame after
1362 update so that it is used by Mac Toolbox to clear the update region before
1363 an update event is generated. */
1364 #if TARGET_API_MAC_CARBON
1365 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
1367 SetPort (FRAME_MAC_WINDOW (f
));
1370 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
1372 /* Mouse highlight may be displayed again. */
1373 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1376 XFlush (FRAME_MAC_DISPLAY (f
));
1381 /* This function is called from various places in xdisp.c whenever a
1382 complete update has been performed. The global variable
1383 updated_window is not available here. */
1386 XTframe_up_to_date (f
)
1391 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1393 if (dpyinfo
->mouse_face_deferred_gc
1394 || f
== dpyinfo
->mouse_face_mouse_frame
)
1397 if (dpyinfo
->mouse_face_mouse_frame
)
1398 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1399 dpyinfo
->mouse_face_mouse_x
,
1400 dpyinfo
->mouse_face_mouse_y
);
1401 dpyinfo
->mouse_face_deferred_gc
= 0;
1408 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1409 arrow bitmaps, or clear the fringes if no bitmaps are required
1410 before DESIRED_ROW is made current. The window being updated is
1411 found in updated_window. This function is called from
1412 update_window_line only if it is known that there are differences
1413 between bitmaps to be drawn between current row and DESIRED_ROW. */
1416 x_after_update_window_line (desired_row
)
1417 struct glyph_row
*desired_row
;
1419 struct window
*w
= updated_window
;
1425 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1428 x_draw_row_fringe_bitmaps (w
, desired_row
);
1432 /* When a window has disappeared, make sure that no rest of
1433 full-width rows stays visible in the internal border. Could
1434 check here if updated_window is the leftmost/rightmost window,
1435 but I guess it's not worth doing since vertically split windows
1436 are almost never used, internal border is rarely set, and the
1437 overhead is very small. */
1438 if (windows_or_buffers_changed
1439 && desired_row
->full_width_p
1440 && (f
= XFRAME (w
->frame
),
1441 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1443 && (height
= desired_row
->visible_height
,
1446 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1447 /* Internal border is drawn below the tool bar. */
1448 if (WINDOWP (f
->tool_bar_window
)
1449 && w
== XWINDOW (f
->tool_bar_window
))
1454 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1455 0, y
, width
, height
, 0);
1456 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1457 f
->output_data
.mac
->pixel_width
- width
, y
,
1465 /* Draw the bitmap WHICH in one of the left or right fringes of
1466 window W. ROW is the glyph row for which to display the bitmap; it
1467 determines the vertical position at which the bitmap has to be
1471 x_draw_fringe_bitmap (w
, row
, which
, left_p
)
1473 struct glyph_row
*row
;
1474 enum fringe_bitmap_type which
;
1477 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1478 Display
*display
= FRAME_MAC_DISPLAY (f
);
1479 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1480 int x
, y
, wd
, h
, dy
;
1482 unsigned char *bits
;
1485 GC gc
= f
->output_data
.mac
->normal_gc
;
1488 /* Must clip because of partially visible lines. */
1489 x_clip_to_row (w
, row
, gc
, 1);
1491 /* Convert row to frame coordinates. */
1492 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1496 case NO_FRINGE_BITMAP
:
1501 case LEFT_TRUNCATION_BITMAP
:
1507 case OVERLAY_ARROW_BITMAP
:
1513 case RIGHT_TRUNCATION_BITMAP
:
1519 case CONTINUED_LINE_BITMAP
:
1520 wd
= continued_width
;
1521 h
= continued_height
;
1522 bits
= continued_bits
;
1525 case CONTINUATION_LINE_BITMAP
:
1526 wd
= continuation_width
;
1527 h
= continuation_height
;
1528 bits
= continuation_bits
;
1531 case ZV_LINE_BITMAP
:
1533 h
= zv_height
- (y
% zv_period
);
1534 bits
= zv_bits
+ (y
% zv_period
);
1541 /* Clip bitmap if too high. */
1542 if (h
> row
->height
)
1545 /* Set dy to the offset in the row to start drawing the bitmap. */
1546 dy
= (row
->height
- h
) / 2;
1548 /* Draw the bitmap. */
1549 face
= FACE_FROM_ID (f
, FRINGE_FACE_ID
);
1550 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1552 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1557 if (wd
> FRAME_X_LEFT_FRINGE_WIDTH (f
))
1558 wd
= FRAME_X_LEFT_FRINGE_WIDTH (f
);
1559 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
1561 - (FRAME_X_LEFT_FRINGE_WIDTH (f
) - wd
) / 2);
1562 if (wd
< FRAME_X_LEFT_FRINGE_WIDTH (f
) || row
->height
> h
)
1564 /* If W has a vertical border to its left, don't draw over it. */
1565 int border
= ((XFASTINT (w
->left
) > 0
1566 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1568 b1
= (window_box_left (w
, -1)
1569 - FRAME_X_LEFT_FRINGE_WIDTH (f
)
1571 b2
= (FRAME_X_LEFT_FRINGE_WIDTH (f
) - border
);
1576 if (wd
> FRAME_X_RIGHT_FRINGE_WIDTH (f
))
1577 wd
= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
1578 x
= (window_box_right (w
, -1)
1579 + (FRAME_X_RIGHT_FRINGE_WIDTH (f
) - wd
) / 2);
1580 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1582 if (wd
< FRAME_X_RIGHT_FRINGE_WIDTH (f
) || row
->height
> h
)
1584 b1
= window_box_right (w
, -1);
1585 b2
= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
1591 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
1593 gcv
.foreground
= face
->background
;
1595 #if 0 /* MAC_TODO: stipple */
1596 /* In case the same realized face is used for fringes and
1597 for something displayed in the text (e.g. face `region' on
1598 mono-displays, the fill style may have been changed to
1599 FillSolid in x_draw_glyph_string_background. */
1601 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1603 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1606 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1609 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
1612 row
->visible_height
);
1614 #if 0 /* MAC_TODO: stipple */
1616 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1620 if (which
== NO_FRINGE_BITMAP
)
1622 mac_reset_clipping (display
, window
);
1626 mac_create_bitmap_from_bitmap_data (&bitmap
, bits
, wd
, h
);
1627 gcv
.foreground
= face
->foreground
;
1628 gcv
.background
= face
->background
;
1630 mac_draw_bitmap (display
, window
, &gcv
, x
, y
+ dy
, &bitmap
);
1632 mac_free_bitmap (&bitmap
);
1633 mac_reset_clipping (display
, window
);
1637 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1638 function with input blocked. */
1641 x_draw_row_fringe_bitmaps (w
, row
)
1643 struct glyph_row
*row
;
1645 struct frame
*f
= XFRAME (w
->frame
);
1646 enum fringe_bitmap_type bitmap
;
1648 xassert (interrupt_input_blocked
);
1650 /* If row is completely invisible, because of vscrolling, we
1651 don't have to draw anything. */
1652 if (row
->visible_height
<= 0)
1655 if (FRAME_X_LEFT_FRINGE_WIDTH (f
) != 0)
1657 /* Decide which bitmap to draw in the left fringe. */
1658 if (row
->overlay_arrow_p
)
1659 bitmap
= OVERLAY_ARROW_BITMAP
;
1660 else if (row
->truncated_on_left_p
)
1661 bitmap
= LEFT_TRUNCATION_BITMAP
;
1662 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
1663 bitmap
= CONTINUATION_LINE_BITMAP
;
1664 else if (row
->indicate_empty_line_p
)
1665 bitmap
= ZV_LINE_BITMAP
;
1667 bitmap
= NO_FRINGE_BITMAP
;
1669 x_draw_fringe_bitmap (w
, row
, bitmap
, 1);
1672 if (FRAME_X_RIGHT_FRINGE_WIDTH (f
) != 0)
1674 /* Decide which bitmap to draw in the right fringe. */
1675 if (row
->truncated_on_right_p
)
1676 bitmap
= RIGHT_TRUNCATION_BITMAP
;
1677 else if (row
->continued_p
)
1678 bitmap
= CONTINUED_LINE_BITMAP
;
1679 else if (row
->indicate_empty_line_p
&& FRAME_X_LEFT_FRINGE_WIDTH (f
) == 0)
1680 bitmap
= ZV_LINE_BITMAP
;
1682 bitmap
= NO_FRINGE_BITMAP
;
1684 x_draw_fringe_bitmap (w
, row
, bitmap
, 0);
1689 /* This is called when starting Emacs and when restarting after
1690 suspend. When starting Emacs, no window is mapped. And nothing
1691 must be done to Emacs's own window if it is suspended (though that
1695 XTset_terminal_modes ()
1699 /* This is called when exiting or suspending Emacs. Exiting will make
1700 the windows go away, and suspending requires no action. */
1703 XTreset_terminal_modes ()
1709 /***********************************************************************
1711 ***********************************************************************/
1713 /* Set the global variable output_cursor to CURSOR. All cursor
1714 positions are relative to updated_window. */
1717 set_output_cursor (cursor
)
1718 struct cursor_pos
*cursor
;
1720 output_cursor
.hpos
= cursor
->hpos
;
1721 output_cursor
.vpos
= cursor
->vpos
;
1722 output_cursor
.x
= cursor
->x
;
1723 output_cursor
.y
= cursor
->y
;
1727 /* Set a nominal cursor position.
1729 HPOS and VPOS are column/row positions in a window glyph matrix. X
1730 and Y are window text area relative pixel positions.
1732 If this is done during an update, updated_window will contain the
1733 window that is being updated and the position is the future output
1734 cursor position for that window. If updated_window is null, use
1735 selected_window and display the cursor at the given position. */
1738 XTcursor_to (vpos
, hpos
, y
, x
)
1739 int vpos
, hpos
, y
, x
;
1743 /* If updated_window is not set, work on selected_window. */
1747 w
= XWINDOW (selected_window
);
1749 /* Set the output cursor. */
1750 output_cursor
.hpos
= hpos
;
1751 output_cursor
.vpos
= vpos
;
1752 output_cursor
.x
= x
;
1753 output_cursor
.y
= y
;
1755 /* If not called as part of an update, really display the cursor.
1756 This will also set the cursor position of W. */
1757 if (updated_window
== NULL
)
1760 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1761 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1768 /***********************************************************************
1770 ***********************************************************************/
1772 /* Function prototypes of this page. */
1774 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1778 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1779 int, XChar2b
*, int));
1780 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1781 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1782 static void x_append_glyph
P_ ((struct it
*));
1783 static void x_append_composite_glyph
P_ ((struct it
*));
1784 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1786 static void x_produce_glyphs
P_ ((struct it
*));
1787 static void x_produce_image_glyph
P_ ((struct it
*it
));
1790 /* Return a pointer to per-char metric information in FONT of a
1791 character pointed by B which is a pointer to an XChar2b. */
1793 #define PER_CHAR_METRIC(font, b) \
1795 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1796 + (((font)->min_byte1 || (font)->max_byte1) \
1797 ? (((b)->byte1 - (font)->min_byte1) \
1798 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1800 : &((font)->max_bounds))
1803 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1804 is not contained in the font. */
1806 static INLINE XCharStruct
*
1807 x_per_char_metric (font
, char2b
)
1811 /* The result metric information. */
1812 XCharStruct
*pcm
= NULL
;
1814 xassert (font
&& char2b
);
1816 if (font
->per_char
!= NULL
)
1818 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1820 /* min_char_or_byte2 specifies the linear character index
1821 corresponding to the first element of the per_char array,
1822 max_char_or_byte2 is the index of the last character. A
1823 character with non-zero CHAR2B->byte1 is not in the font.
1824 A character with byte2 less than min_char_or_byte2 or
1825 greater max_char_or_byte2 is not in the font. */
1826 if (char2b
->byte1
== 0
1827 && char2b
->byte2
>= font
->min_char_or_byte2
1828 && char2b
->byte2
<= font
->max_char_or_byte2
)
1829 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1833 /* If either min_byte1 or max_byte1 are nonzero, both
1834 min_char_or_byte2 and max_char_or_byte2 are less than
1835 256, and the 2-byte character index values corresponding
1836 to the per_char array element N (counting from 0) are:
1838 byte1 = N/D + min_byte1
1839 byte2 = N\D + min_char_or_byte2
1843 D = max_char_or_byte2 - min_char_or_byte2 + 1
1844 / = integer division
1845 \ = integer modulus */
1846 if (char2b
->byte1
>= font
->min_byte1
1847 && char2b
->byte1
<= font
->max_byte1
1848 && char2b
->byte2
>= font
->min_char_or_byte2
1849 && char2b
->byte2
<= font
->max_char_or_byte2
)
1851 pcm
= (font
->per_char
1852 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1853 * (char2b
->byte1
- font
->min_byte1
))
1854 + (char2b
->byte2
- font
->min_char_or_byte2
));
1860 /* If the per_char pointer is null, all glyphs between the first
1861 and last character indexes inclusive have the same
1862 information, as given by both min_bounds and max_bounds. */
1863 if (char2b
->byte2
>= font
->min_char_or_byte2
1864 && char2b
->byte2
<= font
->max_char_or_byte2
)
1865 pcm
= &font
->max_bounds
;
1868 return ((pcm
== NULL
1869 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1874 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1875 the two-byte form of C. Encoding is returned in *CHAR2B. */
1878 x_encode_char (c
, char2b
, font_info
)
1881 struct font_info
*font_info
;
1883 int charset
= CHAR_CHARSET (c
);
1884 XFontStruct
*font
= font_info
->font
;
1886 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1887 This may be either a program in a special encoder language or a
1889 if (font_info
->font_encoder
)
1891 /* It's a program. */
1892 struct ccl_program
*ccl
= font_info
->font_encoder
;
1894 if (CHARSET_DIMENSION (charset
) == 1)
1896 ccl
->reg
[0] = charset
;
1897 ccl
->reg
[1] = char2b
->byte2
;
1901 ccl
->reg
[0] = charset
;
1902 ccl
->reg
[1] = char2b
->byte1
;
1903 ccl
->reg
[2] = char2b
->byte2
;
1906 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1908 /* We assume that MSBs are appropriately set/reset by CCL
1910 if (font
->max_byte1
== 0) /* 1-byte font */
1911 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1913 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1915 else if (font_info
->encoding
[charset
])
1917 /* Fixed encoding scheme. See fontset.h for the meaning of the
1918 encoding numbers. */
1919 int enc
= font_info
->encoding
[charset
];
1921 if ((enc
== 1 || enc
== 2)
1922 && CHARSET_DIMENSION (charset
) == 2)
1923 char2b
->byte1
|= 0x80;
1925 if (enc
== 1 || enc
== 3)
1926 char2b
->byte2
|= 0x80;
1932 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1933 char2b
->byte1
= sjis1
;
1934 char2b
->byte2
= sjis2
;
1940 /* Get face and two-byte form of character C in face FACE_ID on frame
1941 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1942 means we want to display multibyte text. Value is a pointer to a
1943 realized face that is ready for display. */
1945 static INLINE
struct face
*
1946 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
)
1952 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1956 /* Unibyte case. We don't have to encode, but we have to make
1957 sure to use a face suitable for unibyte. */
1960 face_id
= FACE_FOR_CHAR (f
, face
, c
);
1961 face
= FACE_FROM_ID (f
, face_id
);
1963 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1965 /* Case of ASCII in a face known to fit ASCII. */
1971 int c1
, c2
, charset
;
1973 /* Split characters into bytes. If c2 is -1 afterwards, C is
1974 really a one-byte character so that byte1 is zero. */
1975 SPLIT_CHAR (c
, charset
, c1
, c2
);
1977 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1979 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1981 /* Maybe encode the character in *CHAR2B. */
1982 if (face
->font
!= NULL
)
1984 struct font_info
*font_info
1985 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1987 x_encode_char (c
, char2b
, font_info
);
1991 /* Make sure X resources of the face are allocated. */
1992 xassert (face
!= NULL
);
1993 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1999 /* Get face and two-byte form of character glyph GLYPH on frame F.
2000 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
2001 a pointer to a realized face that is ready for display. */
2003 static INLINE
struct face
*
2004 x_get_glyph_face_and_encoding (f
, glyph
, char2b
, two_byte_p
)
2006 struct glyph
*glyph
;
2012 xassert (glyph
->type
== CHAR_GLYPH
);
2013 face
= FACE_FROM_ID (f
, glyph
->face_id
);
2018 if (!glyph
->multibyte_p
)
2020 /* Unibyte case. We don't have to encode, but we have to make
2021 sure to use a face suitable for unibyte. */
2023 char2b
->byte2
= glyph
->u
.ch
;
2025 else if (glyph
->u
.ch
< 128
2026 && glyph
->face_id
< BASIC_FACE_ID_SENTINEL
)
2028 /* Case of ASCII in a face known to fit ASCII. */
2030 char2b
->byte2
= glyph
->u
.ch
;
2034 int c1
, c2
, charset
;
2036 /* Split characters into bytes. If c2 is -1 afterwards, C is
2037 really a one-byte character so that byte1 is zero. */
2038 SPLIT_CHAR (glyph
->u
.ch
, charset
, c1
, c2
);
2040 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
2042 char2b
->byte1
= 0, char2b
->byte2
= c1
;
2044 /* Maybe encode the character in *CHAR2B. */
2045 if (charset
!= CHARSET_ASCII
)
2047 struct font_info
*font_info
2048 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2051 x_encode_char (glyph
->u
.ch
, char2b
, font_info
);
2054 = ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2059 /* Make sure X resources of the face are allocated. */
2060 xassert (face
!= NULL
);
2061 PREPARE_FACE_FOR_DISPLAY (f
, face
);
2066 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2067 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2073 struct glyph
*glyph
;
2074 enum glyph_row_area area
= it
->area
;
2076 xassert (it
->glyph_row
);
2077 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
2079 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
2080 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
2082 glyph
->charpos
= CHARPOS (it
->position
);
2083 glyph
->object
= it
->object
;
2084 glyph
->pixel_width
= it
->pixel_width
;
2085 glyph
->voffset
= it
->voffset
;
2086 glyph
->type
= CHAR_GLYPH
;
2087 glyph
->multibyte_p
= it
->multibyte_p
;
2088 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
2089 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
2090 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
2091 || it
->phys_descent
> it
->descent
);
2092 glyph
->padding_p
= 0;
2093 glyph
->glyph_not_available_p
= it
->glyph_not_available_p
;
2094 glyph
->face_id
= it
->face_id
;
2095 glyph
->u
.ch
= it
->char_to_display
;
2096 ++it
->glyph_row
->used
[area
];
2100 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2101 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2104 x_append_composite_glyph (it
)
2107 struct glyph
*glyph
;
2108 enum glyph_row_area area
= it
->area
;
2110 xassert (it
->glyph_row
);
2112 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
2113 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
2115 glyph
->charpos
= CHARPOS (it
->position
);
2116 glyph
->object
= it
->object
;
2117 glyph
->pixel_width
= it
->pixel_width
;
2118 glyph
->voffset
= it
->voffset
;
2119 glyph
->type
= COMPOSITE_GLYPH
;
2120 glyph
->multibyte_p
= it
->multibyte_p
;
2121 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
2122 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
2123 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
2124 || it
->phys_descent
> it
->descent
);
2125 glyph
->padding_p
= 0;
2126 glyph
->glyph_not_available_p
= 0;
2127 glyph
->face_id
= it
->face_id
;
2128 glyph
->u
.cmp_id
= it
->cmp_id
;
2129 ++it
->glyph_row
->used
[area
];
2134 /* Change IT->ascent and IT->height according to the setting of
2138 take_vertical_position_into_account (it
)
2143 if (it
->voffset
< 0)
2144 /* Increase the ascent so that we can display the text higher
2146 it
->ascent
+= abs (it
->voffset
);
2148 /* Increase the descent so that we can display the text lower
2150 it
->descent
+= it
->voffset
;
2155 /* Produce glyphs/get display metrics for the image IT is loaded with.
2156 See the description of struct display_iterator in dispextern.h for
2157 an overview of struct display_iterator. */
2160 x_produce_image_glyph (it
)
2166 xassert (it
->what
== IT_IMAGE
);
2168 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2169 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
2172 /* Make sure X resources of the face and image are loaded. */
2173 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
2174 prepare_image_for_display (it
->f
, img
);
2176 it
->ascent
= it
->phys_ascent
= image_ascent (img
, face
);
2177 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->vmargin
- it
->ascent
;
2178 it
->pixel_width
= img
->width
+ 2 * img
->hmargin
;
2182 if (face
->box
!= FACE_NO_BOX
)
2184 if (face
->box_line_width
> 0)
2186 it
->ascent
+= face
->box_line_width
;
2187 it
->descent
+= face
->box_line_width
;
2190 if (it
->start_of_box_run_p
)
2191 it
->pixel_width
+= abs (face
->box_line_width
);
2192 if (it
->end_of_box_run_p
)
2193 it
->pixel_width
+= abs (face
->box_line_width
);
2196 take_vertical_position_into_account (it
);
2200 struct glyph
*glyph
;
2201 enum glyph_row_area area
= it
->area
;
2203 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
2204 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
2206 glyph
->charpos
= CHARPOS (it
->position
);
2207 glyph
->object
= it
->object
;
2208 glyph
->pixel_width
= it
->pixel_width
;
2209 glyph
->voffset
= it
->voffset
;
2210 glyph
->type
= IMAGE_GLYPH
;
2211 glyph
->multibyte_p
= it
->multibyte_p
;
2212 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
2213 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
2214 glyph
->overlaps_vertically_p
= 0;
2215 glyph
->padding_p
= 0;
2216 glyph
->glyph_not_available_p
= 0;
2217 glyph
->face_id
= it
->face_id
;
2218 glyph
->u
.img_id
= img
->id
;
2219 ++it
->glyph_row
->used
[area
];
2225 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2226 of the glyph, WIDTH and HEIGHT are the width and height of the
2227 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2228 ascent of the glyph (0 <= ASCENT <= 1). */
2231 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
2237 struct glyph
*glyph
;
2238 enum glyph_row_area area
= it
->area
;
2240 xassert (ascent
>= 0 && ascent
<= 1);
2242 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
2243 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
2245 glyph
->charpos
= CHARPOS (it
->position
);
2246 glyph
->object
= object
;
2247 glyph
->pixel_width
= width
;
2248 glyph
->voffset
= it
->voffset
;
2249 glyph
->type
= STRETCH_GLYPH
;
2250 glyph
->multibyte_p
= it
->multibyte_p
;
2251 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
2252 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
2253 glyph
->overlaps_vertically_p
= 0;
2254 glyph
->padding_p
= 0;
2255 glyph
->glyph_not_available_p
= 0;
2256 glyph
->face_id
= it
->face_id
;
2257 glyph
->u
.stretch
.ascent
= height
* ascent
;
2258 glyph
->u
.stretch
.height
= height
;
2259 ++it
->glyph_row
->used
[area
];
2264 /* Produce a stretch glyph for iterator IT. IT->object is the value
2265 of the glyph property displayed. The value must be a list
2266 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2269 1. `:width WIDTH' specifies that the space should be WIDTH *
2270 canonical char width wide. WIDTH may be an integer or floating
2273 2. `:relative-width FACTOR' specifies that the width of the stretch
2274 should be computed from the width of the first character having the
2275 `glyph' property, and should be FACTOR times that width.
2277 3. `:align-to HPOS' specifies that the space should be wide enough
2278 to reach HPOS, a value in canonical character units.
2280 Exactly one of the above pairs must be present.
2282 4. `:height HEIGHT' specifies that the height of the stretch produced
2283 should be HEIGHT, measured in canonical character units.
2285 5. `:relative-height FACTOR' specifies that the height of the
2286 stretch should be FACTOR times the height of the characters having
2289 Either none or exactly one of 4 or 5 must be present.
2291 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2292 of the stretch should be used for the ascent of the stretch.
2293 ASCENT must be in the range 0 <= ASCENT <= 100. */
2296 ((INTEGERP (X) || FLOATP (X)) \
2302 x_produce_stretch_glyph (it
)
2305 /* (space :width WIDTH :height HEIGHT. */
2307 extern Lisp_Object Qspace
;
2309 extern Lisp_Object QCwidth
, QCheight
, QCascent
;
2310 extern Lisp_Object QCrelative_width
, QCrelative_height
;
2311 extern Lisp_Object QCalign_to
;
2312 Lisp_Object prop
, plist
;
2313 double width
= 0, height
= 0, ascent
= 0;
2314 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2315 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
2317 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
2319 /* List should start with `space'. */
2320 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
2321 plist
= XCDR (it
->object
);
2323 /* Compute the width of the stretch. */
2324 if (prop
= Fplist_get (plist
, QCwidth
),
2326 /* Absolute width `:width WIDTH' specified and valid. */
2327 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
2328 else if (prop
= Fplist_get (plist
, QCrelative_width
),
2331 /* Relative width `:relative-width FACTOR' specified and valid.
2332 Compute the width of the characters having the `glyph'
2335 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
2338 if (it
->multibyte_p
)
2340 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
2341 - IT_BYTEPOS (*it
));
2342 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
2345 it2
.c
= *p
, it2
.len
= 1;
2347 it2
.glyph_row
= NULL
;
2348 it2
.what
= IT_CHARACTER
;
2349 x_produce_glyphs (&it2
);
2350 width
= NUMVAL (prop
) * it2
.pixel_width
;
2352 else if (prop
= Fplist_get (plist
, QCalign_to
),
2354 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
2356 /* Nothing specified -> width defaults to canonical char width. */
2357 width
= CANON_X_UNIT (it
->f
);
2359 /* Compute height. */
2360 if (prop
= Fplist_get (plist
, QCheight
),
2362 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
2363 else if (prop
= Fplist_get (plist
, QCrelative_height
),
2365 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
2367 height
= FONT_HEIGHT (font
);
2369 /* Compute percentage of height used for ascent. If
2370 `:ascent ASCENT' is present and valid, use that. Otherwise,
2371 derive the ascent from the font in use. */
2372 if (prop
= Fplist_get (plist
, QCascent
),
2373 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
2374 ascent
= NUMVAL (prop
) / 100.0;
2376 ascent
= (double) FONT_BASE (font
) / FONT_HEIGHT (font
);
2385 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
2386 if (!STRINGP (object
))
2387 object
= it
->w
->buffer
;
2388 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
2391 it
->pixel_width
= width
;
2392 it
->ascent
= it
->phys_ascent
= height
* ascent
;
2393 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
2396 if (face
->box
!= FACE_NO_BOX
)
2398 if (face
->box_line_width
> 0)
2400 it
->ascent
+= face
->box_line_width
;
2401 it
->descent
+= face
->box_line_width
;
2404 if (it
->start_of_box_run_p
)
2405 it
->pixel_width
+= abs (face
->box_line_width
);
2406 if (it
->end_of_box_run_p
)
2407 it
->pixel_width
+= abs (face
->box_line_width
);
2410 take_vertical_position_into_account (it
);
2413 /* Return proper value to be used as baseline offset of font that has
2414 ASCENT and DESCENT to draw characters by the font at the vertical
2415 center of the line of frame F.
2417 Here, out task is to find the value of BOFF in the following figure;
2419 -------------------------+-----------+-
2420 -+-+---------+-+ | |
2422 | | | | F_ASCENT F_HEIGHT
2425 | | |-|-+------+-----------|------- baseline
2427 | |---------|-+-+ | |
2429 -+-+---------+-+ F_DESCENT |
2430 -------------------------+-----------+-
2432 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2433 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2434 DESCENT = FONT->descent
2435 HEIGHT = FONT_HEIGHT (FONT)
2436 F_DESCENT = (F->output_data.x->font->descent
2437 - F->output_data.x->baseline_offset)
2438 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2441 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2442 (FONT_DESCENT (FONT) \
2443 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2444 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2445 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2447 /* Produce glyphs/get display metrics for the display element IT is
2448 loaded with. See the description of struct display_iterator in
2449 dispextern.h for an overview of struct display_iterator. */
2452 x_produce_glyphs (it
)
2455 it
->glyph_not_available_p
= 0;
2457 if (it
->what
== IT_CHARACTER
)
2461 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2463 int font_not_found_p
;
2464 struct font_info
*font_info
;
2465 int boff
; /* baseline offset */
2466 /* We may change it->multibyte_p upon unibyte<->multibyte
2467 conversion. So, save the current value now and restore it
2470 Note: It seems that we don't have to record multibyte_p in
2471 struct glyph because the character code itself tells if or
2472 not the character is multibyte. Thus, in the future, we must
2473 consider eliminating the field `multibyte_p' in the struct
2476 int saved_multibyte_p
= it
->multibyte_p
;
2478 /* Maybe translate single-byte characters to multibyte, or the
2480 it
->char_to_display
= it
->c
;
2481 if (!ASCII_BYTE_P (it
->c
))
2483 if (unibyte_display_via_language_environment
2484 && SINGLE_BYTE_CHAR_P (it
->c
)
2486 || !NILP (Vnonascii_translation_table
)))
2488 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2489 it
->multibyte_p
= 1;
2490 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2491 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2493 else if (!SINGLE_BYTE_CHAR_P (it
->c
)
2494 && !it
->multibyte_p
)
2496 it
->multibyte_p
= 1;
2497 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2498 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2502 /* Get font to use. Encode IT->char_to_display. */
2503 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2504 it
->face_id
, &char2b
,
2508 /* When no suitable font found, use the default font. */
2509 font_not_found_p
= font
== NULL
;
2510 if (font_not_found_p
)
2512 font
= FRAME_FONT (it
->f
);
2513 boff
= it
->f
->output_data
.mac
->baseline_offset
;
2518 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2519 boff
= font_info
->baseline_offset
;
2520 if (font_info
->vertical_centering
)
2521 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2524 if (it
->char_to_display
>= ' '
2525 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
2527 /* Either unibyte or ASCII. */
2532 pcm
= x_per_char_metric (font
, &char2b
);
2533 it
->ascent
= FONT_BASE (font
) + boff
;
2534 it
->descent
= FONT_DESCENT (font
) - boff
;
2538 it
->phys_ascent
= pcm
->ascent
+ boff
;
2539 it
->phys_descent
= pcm
->descent
- boff
;
2540 it
->pixel_width
= pcm
->width
;
2544 it
->glyph_not_available_p
= 1;
2545 it
->phys_ascent
= FONT_BASE (font
) + boff
;
2546 it
->phys_descent
= FONT_DESCENT (font
) - boff
;
2547 it
->pixel_width
= FONT_WIDTH (font
);
2550 /* If this is a space inside a region of text with
2551 `space-width' property, change its width. */
2552 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
2554 it
->pixel_width
*= XFLOATINT (it
->space_width
);
2556 /* If face has a box, add the box thickness to the character
2557 height. If character has a box line to the left and/or
2558 right, add the box line width to the character's width. */
2559 if (face
->box
!= FACE_NO_BOX
)
2561 int thick
= face
->box_line_width
;
2565 it
->ascent
+= thick
;
2566 it
->descent
+= thick
;
2571 if (it
->start_of_box_run_p
)
2572 it
->pixel_width
+= thick
;
2573 if (it
->end_of_box_run_p
)
2574 it
->pixel_width
+= thick
;
2577 /* If face has an overline, add the height of the overline
2578 (1 pixel) and a 1 pixel margin to the character height. */
2579 if (face
->overline_p
)
2582 take_vertical_position_into_account (it
);
2584 /* If we have to actually produce glyphs, do it. */
2589 /* Translate a space with a `space-width' property
2590 into a stretch glyph. */
2591 double ascent
= (double) FONT_BASE (font
)
2592 / FONT_HEIGHT (font
);
2593 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
2594 it
->ascent
+ it
->descent
, ascent
);
2597 x_append_glyph (it
);
2599 /* If characters with lbearing or rbearing are displayed
2600 in this line, record that fact in a flag of the
2601 glyph row. This is used to optimize X output code. */
2602 if (pcm
&& (pcm
->lbearing
< 0 || pcm
->rbearing
> pcm
->width
))
2603 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
2606 else if (it
->char_to_display
== '\n')
2608 /* A newline has no width but we need the height of the line. */
2609 it
->pixel_width
= 0;
2611 it
->ascent
= it
->phys_ascent
= FONT_BASE (font
) + boff
;
2612 it
->descent
= it
->phys_descent
= FONT_DESCENT (font
) - boff
;
2614 if (face
->box
!= FACE_NO_BOX
2615 && face
->box_line_width
> 0)
2617 it
->ascent
+= face
->box_line_width
;
2618 it
->descent
+= face
->box_line_width
;
2621 else if (it
->char_to_display
== '\t')
2623 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
2624 int x
= it
->current_x
+ it
->continuation_lines_width
;
2625 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
2627 /* If the distance from the current position to the next tab
2628 stop is less than a canonical character width, use the
2629 tab stop after that. */
2630 if (next_tab_x
- x
< CANON_X_UNIT (it
->f
))
2631 next_tab_x
+= tab_width
;
2633 it
->pixel_width
= next_tab_x
- x
;
2635 it
->ascent
= it
->phys_ascent
= FONT_BASE (font
) + boff
;
2636 it
->descent
= it
->phys_descent
= FONT_DESCENT (font
) - boff
;
2640 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
2641 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
2642 it
->ascent
+ it
->descent
, ascent
);
2647 /* A multi-byte character. Assume that the display width of the
2648 character is the width of the character multiplied by the
2649 width of the font. */
2651 /* If we found a font, this font should give us the right
2652 metrics. If we didn't find a font, use the frame's
2653 default font and calculate the width of the character
2654 from the charset width; this is what old redisplay code
2656 pcm
= x_per_char_metric (font
, &char2b
);
2657 if (font_not_found_p
|| !pcm
)
2659 int charset
= CHAR_CHARSET (it
->char_to_display
);
2661 it
->glyph_not_available_p
= 1;
2662 it
->pixel_width
= (FONT_WIDTH (FRAME_FONT (it
->f
))
2663 * CHARSET_WIDTH (charset
));
2664 it
->phys_ascent
= FONT_BASE (font
) + boff
;
2665 it
->phys_descent
= FONT_DESCENT (font
) - boff
;
2669 it
->pixel_width
= pcm
->width
;
2670 it
->phys_ascent
= pcm
->ascent
+ boff
;
2671 it
->phys_descent
= pcm
->descent
- boff
;
2673 && (pcm
->lbearing
< 0
2674 || pcm
->rbearing
> pcm
->width
))
2675 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
2678 it
->ascent
= FONT_BASE (font
) + boff
;
2679 it
->descent
= FONT_DESCENT (font
) - boff
;
2680 if (face
->box
!= FACE_NO_BOX
)
2682 int thick
= face
->box_line_width
;
2686 it
->ascent
+= thick
;
2687 it
->descent
+= thick
;
2692 if (it
->start_of_box_run_p
)
2693 it
->pixel_width
+= thick
;
2694 if (it
->end_of_box_run_p
)
2695 it
->pixel_width
+= thick
;
2698 /* If face has an overline, add the height of the overline
2699 (1 pixel) and a 1 pixel margin to the character height. */
2700 if (face
->overline_p
)
2703 take_vertical_position_into_account (it
);
2706 x_append_glyph (it
);
2708 it
->multibyte_p
= saved_multibyte_p
;
2710 else if (it
->what
== IT_COMPOSITION
)
2712 /* Note: A composition is represented as one glyph in the
2713 glyph matrix. There are no padding glyphs. */
2716 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2718 int font_not_found_p
;
2719 struct font_info
*font_info
;
2720 int boff
; /* baseline offset */
2721 struct composition
*cmp
= composition_table
[it
->cmp_id
];
2723 /* Maybe translate single-byte characters to multibyte. */
2724 it
->char_to_display
= it
->c
;
2725 if (unibyte_display_via_language_environment
2726 && SINGLE_BYTE_CHAR_P (it
->c
)
2729 && !NILP (Vnonascii_translation_table
))))
2731 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2734 /* Get face and font to use. Encode IT->char_to_display. */
2735 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2736 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2737 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2738 it
->face_id
, &char2b
, it
->multibyte_p
);
2741 /* When no suitable font found, use the default font. */
2742 font_not_found_p
= font
== NULL
;
2743 if (font_not_found_p
)
2745 font
= FRAME_FONT (it
->f
);
2746 boff
= it
->f
->output_data
.mac
->baseline_offset
;
2751 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2752 boff
= font_info
->baseline_offset
;
2753 if (font_info
->vertical_centering
)
2754 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2757 /* There are no padding glyphs, so there is only one glyph to
2758 produce for the composition. Important is that pixel_width,
2759 ascent and descent are the values of what is drawn by
2760 draw_glyphs (i.e. the values of the overall glyphs composed). */
2763 /* If we have not yet calculated pixel size data of glyphs of
2764 the composition for the current face font, calculate them
2765 now. Theoretically, we have to check all fonts for the
2766 glyphs, but that requires much time and memory space. So,
2767 here we check only the font of the first glyph. This leads
2768 to incorrect display very rarely, and C-l (recenter) can
2769 correct the display anyway. */
2770 if (cmp
->font
!= (void *) font
)
2772 /* Ascent and descent of the font of the first character of
2773 this composition (adjusted by baseline offset). Ascent
2774 and descent of overall glyphs should not be less than
2775 them respectively. */
2776 int font_ascent
= FONT_BASE (font
) + boff
;
2777 int font_descent
= FONT_DESCENT (font
) - boff
;
2778 /* Bounding box of the overall glyphs. */
2779 int leftmost
, rightmost
, lowest
, highest
;
2780 int i
, width
, ascent
, descent
;
2782 cmp
->font
= (void *) font
;
2784 /* Initialize the bounding box. */
2785 pcm
= x_per_char_metric (font
, &char2b
);
2789 ascent
= pcm
->ascent
;
2790 descent
= pcm
->descent
;
2794 width
= FONT_WIDTH (font
);
2795 ascent
= FONT_BASE (font
);
2796 descent
= FONT_DESCENT (font
);
2800 lowest
= - descent
+ boff
;
2801 highest
= ascent
+ boff
;
2805 && font_info
->default_ascent
2806 && CHAR_TABLE_P (Vuse_default_ascent
)
2807 && !NILP (Faref (Vuse_default_ascent
,
2808 make_number (it
->char_to_display
))))
2809 highest
= font_info
->default_ascent
+ boff
;
2811 /* Draw the first glyph at the normal position. It may be
2812 shifted to right later if some other glyphs are drawn at
2814 cmp
->offsets
[0] = 0;
2815 cmp
->offsets
[1] = boff
;
2817 /* Set cmp->offsets for the remaining glyphs. */
2818 for (i
= 1; i
< cmp
->glyph_len
; i
++)
2820 int left
, right
, btm
, top
;
2821 int ch
= COMPOSITION_GLYPH (cmp
, i
);
2822 int face_id
= FACE_FOR_CHAR (it
->f
, face
, ch
);
2824 face
= FACE_FROM_ID (it
->f
, face_id
);
2825 x_get_char_face_and_encoding (it
->f
, ch
, face
->id
, &char2b
,
2830 font
= FRAME_FONT (it
->f
);
2831 boff
= it
->f
->output_data
.mac
->baseline_offset
;
2837 = FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2838 boff
= font_info
->baseline_offset
;
2839 if (font_info
->vertical_centering
)
2840 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2843 pcm
= x_per_char_metric (font
, &char2b
);
2847 ascent
= pcm
->ascent
;
2848 descent
= pcm
->descent
;
2852 width
= FONT_WIDTH (font
);
2857 if (cmp
->method
!= COMPOSITION_WITH_RULE_ALTCHARS
)
2859 /* Relative composition with or without
2861 left
= (leftmost
+ rightmost
- width
) / 2;
2862 btm
= - descent
+ boff
;
2863 if (font_info
&& font_info
->relative_compose
2864 && (! CHAR_TABLE_P (Vignore_relative_composition
)
2865 || NILP (Faref (Vignore_relative_composition
,
2866 make_number (ch
)))))
2869 if (- descent
>= font_info
->relative_compose
)
2870 /* One extra pixel between two glyphs. */
2872 else if (ascent
<= 0)
2873 /* One extra pixel between two glyphs. */
2874 btm
= lowest
- 1 - ascent
- descent
;
2879 /* A composition rule is specified by an integer
2880 value that encodes global and new reference
2881 points (GREF and NREF). GREF and NREF are
2882 specified by numbers as below:
2890 ---3---4---5--- baseline
2892 6---7---8 -- descent
2894 int rule
= COMPOSITION_RULE (cmp
, i
);
2895 int gref
, nref
, grefx
, grefy
, nrefx
, nrefy
;
2897 COMPOSITION_DECODE_RULE (rule
, gref
, nref
);
2898 grefx
= gref
% 3, nrefx
= nref
% 3;
2899 grefy
= gref
/ 3, nrefy
= nref
/ 3;
2902 + grefx
* (rightmost
- leftmost
) / 2
2903 - nrefx
* width
/ 2);
2904 btm
= ((grefy
== 0 ? highest
2906 : grefy
== 2 ? lowest
2907 : (highest
+ lowest
) / 2)
2908 - (nrefy
== 0 ? ascent
+ descent
2909 : nrefy
== 1 ? descent
- boff
2911 : (ascent
+ descent
) / 2));
2914 cmp
->offsets
[i
* 2] = left
;
2915 cmp
->offsets
[i
* 2 + 1] = btm
+ descent
;
2917 /* Update the bounding box of the overall glyphs. */
2918 right
= left
+ width
;
2919 top
= btm
+ descent
+ ascent
;
2920 if (left
< leftmost
)
2922 if (right
> rightmost
)
2930 /* If there are glyphs whose x-offsets are negative,
2931 shift all glyphs to the right and make all x-offsets
2935 for (i
= 0; i
< cmp
->glyph_len
; i
++)
2936 cmp
->offsets
[i
* 2] -= leftmost
;
2937 rightmost
-= leftmost
;
2940 cmp
->pixel_width
= rightmost
;
2941 cmp
->ascent
= highest
;
2942 cmp
->descent
= - lowest
;
2943 if (cmp
->ascent
< font_ascent
)
2944 cmp
->ascent
= font_ascent
;
2945 if (cmp
->descent
< font_descent
)
2946 cmp
->descent
= font_descent
;
2949 it
->pixel_width
= cmp
->pixel_width
;
2950 it
->ascent
= it
->phys_ascent
= cmp
->ascent
;
2951 it
->descent
= it
->phys_descent
= cmp
->descent
;
2953 if (face
->box
!= FACE_NO_BOX
)
2955 int thick
= face
->box_line_width
;
2959 it
->ascent
+= thick
;
2960 it
->descent
+= thick
;
2965 if (it
->start_of_box_run_p
)
2966 it
->pixel_width
+= thick
;
2967 if (it
->end_of_box_run_p
)
2968 it
->pixel_width
+= thick
;
2971 /* If face has an overline, add the height of the overline
2972 (1 pixel) and a 1 pixel margin to the character height. */
2973 if (face
->overline_p
)
2976 take_vertical_position_into_account (it
);
2979 x_append_composite_glyph (it
);
2981 else if (it
->what
== IT_IMAGE
)
2982 x_produce_image_glyph (it
);
2983 else if (it
->what
== IT_STRETCH
)
2984 x_produce_stretch_glyph (it
);
2986 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2987 because this isn't true for images with `:ascent 100'. */
2988 xassert (it
->ascent
>= 0 && it
->descent
>= 0);
2989 if (it
->area
== TEXT_AREA
)
2990 it
->current_x
+= it
->pixel_width
;
2992 it
->descent
+= it
->extra_line_spacing
;
2994 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
2995 it
->max_descent
= max (it
->max_descent
, it
->descent
);
2996 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
2997 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
3001 /* Estimate the pixel height of the mode or top line on frame F.
3002 FACE_ID specifies what line's height to estimate. */
3005 x_estimate_mode_line_height (f
, face_id
)
3007 enum face_id face_id
;
3009 int height
= FONT_HEIGHT (FRAME_FONT (f
));
3011 /* This function is called so early when Emacs starts that the face
3012 cache and mode line face are not yet initialized. */
3013 if (FRAME_FACE_CACHE (f
))
3015 struct face
*face
= FACE_FROM_ID (f
, face_id
);
3019 height
= FONT_HEIGHT (face
->font
);
3020 if (face
->box_line_width
> 0)
3021 height
+= 2 * face
->box_line_width
;
3029 /***********************************************************************
3031 ***********************************************************************/
3033 /* A sequence of glyphs to be drawn in the same face.
3035 This data structure is not really completely X specific, so it
3036 could possibly, at least partially, be useful for other systems. It
3037 is currently not part of the external redisplay interface because
3038 it's not clear what other systems will need. */
3042 /* X-origin of the string. */
3045 /* Y-origin and y-position of the base line of this string. */
3048 /* The width of the string, not including a face extension. */
3051 /* The width of the string, including a face extension. */
3052 int background_width
;
3054 /* The height of this string. This is the height of the line this
3055 string is drawn in, and can be different from the height of the
3056 font the string is drawn in. */
3059 /* Number of pixels this string overwrites in front of its x-origin.
3060 This number is zero if the string has an lbearing >= 0; it is
3061 -lbearing, if the string has an lbearing < 0. */
3064 /* Number of pixels this string overwrites past its right-most
3065 nominal x-position, i.e. x + width. Zero if the string's
3066 rbearing is <= its nominal width, rbearing - width otherwise. */
3069 /* The frame on which the glyph string is drawn. */
3072 /* The window on which the glyph string is drawn. */
3075 /* X display and window for convenience. */
3079 /* The glyph row for which this string was built. It determines the
3080 y-origin and height of the string. */
3081 struct glyph_row
*row
;
3083 /* The area within row. */
3084 enum glyph_row_area area
;
3086 /* Characters to be drawn, and number of characters. */
3090 /* A face-override for drawing cursors, mouse face and similar. */
3091 enum draw_glyphs_face hl
;
3093 /* Face in which this string is to be drawn. */
3096 /* Font in which this string is to be drawn. */
3099 /* Font info for this string. */
3100 struct font_info
*font_info
;
3102 /* Non-null means this string describes (part of) a composition.
3103 All characters from char2b are drawn composed. */
3104 struct composition
*cmp
;
3106 /* Index of this glyph string's first character in the glyph
3107 definition of CMP. If this is zero, this glyph string describes
3108 the first character of a composition. */
3111 /* 1 means this glyph strings face has to be drawn to the right end
3112 of the window's drawing area. */
3113 unsigned extends_to_end_of_line_p
: 1;
3115 /* 1 means the background of this string has been drawn. */
3116 unsigned background_filled_p
: 1;
3118 /* 1 means glyph string must be drawn with 16-bit functions. */
3119 unsigned two_byte_p
: 1;
3121 /* 1 means that the original font determined for drawing this glyph
3122 string could not be loaded. The member `font' has been set to
3123 the frame's default font in this case. */
3124 unsigned font_not_found_p
: 1;
3126 /* 1 means that the face in which this glyph string is drawn has a
3128 unsigned stippled_p
: 1;
3130 /* 1 means only the foreground of this glyph string must be drawn,
3131 and we should use the physical height of the line this glyph
3132 string appears in as clip rect. */
3133 unsigned for_overlaps_p
: 1;
3135 /* The GC to use for drawing this glyph string. */
3138 /* A pointer to the first glyph in the string. This glyph
3139 corresponds to char2b[0]. Needed to draw rectangles if
3140 font_not_found_p is 1. */
3141 struct glyph
*first_glyph
;
3143 /* Image, if any. */
3146 struct glyph_string
*next
, *prev
;
3153 x_dump_glyph_string (s
)
3154 struct glyph_string
*s
;
3156 fprintf (stderr
, "glyph string\n");
3157 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
3158 s
->x
, s
->y
, s
->width
, s
->height
);
3159 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
3160 fprintf (stderr
, " hl = %d\n", s
->hl
);
3161 fprintf (stderr
, " left overhang = %d, right = %d\n",
3162 s
->left_overhang
, s
->right_overhang
);
3163 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
3164 fprintf (stderr
, " extends to end of line = %d\n",
3165 s
->extends_to_end_of_line_p
);
3166 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
3167 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
3170 #endif /* GLYPH_DEBUG */
3174 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
3175 struct glyph_string
**,
3176 struct glyph_string
*,
3177 struct glyph_string
*));
3178 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
3179 struct glyph_string
**,
3180 struct glyph_string
*,
3181 struct glyph_string
*));
3182 static void x_append_glyph_string
P_ ((struct glyph_string
**,
3183 struct glyph_string
**,
3184 struct glyph_string
*));
3185 static int x_left_overwritten
P_ ((struct glyph_string
*));
3186 static int x_left_overwriting
P_ ((struct glyph_string
*));
3187 static int x_right_overwritten
P_ ((struct glyph_string
*));
3188 static int x_right_overwriting
P_ ((struct glyph_string
*));
3189 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
3191 static void x_init_glyph_string
P_ ((struct glyph_string
*,
3192 XChar2b
*, struct window
*,
3194 enum glyph_row_area
, int,
3195 enum draw_glyphs_face
));
3196 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
3197 enum glyph_row_area
, int, int,
3198 enum draw_glyphs_face
, int));
3199 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
3200 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
3201 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
3203 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
3204 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
3205 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
3206 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
3207 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
3208 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
3209 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
3210 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
3211 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
3213 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
3214 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3215 unsigned long *, double, int));*/
3216 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
3217 double, int, unsigned long));
3218 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
3219 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
3220 static void x_draw_image_relief
P_ ((struct glyph_string
*));
3221 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
3222 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
3223 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
3224 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
3226 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
3227 int, int, int, int, Rect
*));
3228 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
3229 int, int, int, Rect
*));
3230 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
3231 enum glyph_row_area
));
3232 static int x_fill_stretch_glyph_string
P_ ((struct glyph_string
*,
3234 enum glyph_row_area
, int, int));
3237 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
3241 /* Append the list of glyph strings with head H and tail T to the list
3242 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3245 x_append_glyph_string_lists (head
, tail
, h
, t
)
3246 struct glyph_string
**head
, **tail
;
3247 struct glyph_string
*h
, *t
;
3261 /* Prepend the list of glyph strings with head H and tail T to the
3262 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3266 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
3267 struct glyph_string
**head
, **tail
;
3268 struct glyph_string
*h
, *t
;
3282 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3283 Set *HEAD and *TAIL to the resulting list. */
3286 x_append_glyph_string (head
, tail
, s
)
3287 struct glyph_string
**head
, **tail
;
3288 struct glyph_string
*s
;
3290 s
->next
= s
->prev
= NULL
;
3291 x_append_glyph_string_lists (head
, tail
, s
, s
);
3295 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3300 struct glyph_string
*s
;
3302 if (s
->font
== FRAME_FONT (s
->f
)
3303 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
3304 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
3306 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
3309 /* Cursor on non-default face: must merge. */
3313 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
3314 xgcv
.foreground
= s
->face
->background
;
3316 /* If the glyph would be invisible, try a different foreground. */
3317 if (xgcv
.foreground
== xgcv
.background
)
3318 xgcv
.foreground
= s
->face
->foreground
;
3319 if (xgcv
.foreground
== xgcv
.background
)
3320 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
3321 if (xgcv
.foreground
== xgcv
.background
)
3322 xgcv
.foreground
= s
->face
->foreground
;
3324 /* Make sure the cursor is distinct from text in this face. */
3325 if (xgcv
.background
== s
->face
->background
3326 && xgcv
.foreground
== s
->face
->foreground
)
3328 xgcv
.background
= s
->face
->foreground
;
3329 xgcv
.foreground
= s
->face
->background
;
3332 IF_DEBUG (x_check_font (s
->f
, s
->font
));
3333 xgcv
.font
= s
->font
;
3334 mask
= GCForeground
| GCBackground
| GCFont
;
3336 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
3337 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
3340 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
3341 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
3343 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
3348 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3351 x_set_mouse_face_gc (s
)
3352 struct glyph_string
*s
;
3357 /* What face has to be used last for the mouse face? */
3358 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
3359 face
= FACE_FROM_ID (s
->f
, face_id
);
3361 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
3363 if (s
->first_glyph
->type
== CHAR_GLYPH
)
3364 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
3366 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
3367 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
3368 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
3370 /* If font in this face is same as S->font, use it. */
3371 if (s
->font
== s
->face
->font
)
3372 s
->gc
= s
->face
->gc
;
3375 /* Otherwise construct scratch_cursor_gc with values from FACE
3380 xgcv
.background
= s
->face
->background
;
3381 xgcv
.foreground
= s
->face
->foreground
;
3382 IF_DEBUG (x_check_font (s
->f
, s
->font
));
3383 xgcv
.font
= s
->font
;
3384 mask
= GCForeground
| GCBackground
| GCFont
;
3386 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
3387 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
3390 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
3391 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
3393 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
3396 xassert (s
->gc
!= 0);
3400 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3401 Faces to use in the mode line have already been computed when the
3402 matrix was built, so there isn't much to do, here. */
3405 x_set_mode_line_face_gc (s
)
3406 struct glyph_string
*s
;
3408 s
->gc
= s
->face
->gc
;
3412 /* Set S->gc of glyph string S for drawing that glyph string. Set
3413 S->stippled_p to a non-zero value if the face of S has a stipple
3417 x_set_glyph_string_gc (s
)
3418 struct glyph_string
*s
;
3420 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
3422 if (s
->hl
== DRAW_NORMAL_TEXT
)
3424 s
->gc
= s
->face
->gc
;
3425 s
->stippled_p
= s
->face
->stipple
!= 0;
3427 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
3429 x_set_mode_line_face_gc (s
);
3430 s
->stippled_p
= s
->face
->stipple
!= 0;
3432 else if (s
->hl
== DRAW_CURSOR
)
3434 x_set_cursor_gc (s
);
3437 else if (s
->hl
== DRAW_MOUSE_FACE
)
3439 x_set_mouse_face_gc (s
);
3440 s
->stippled_p
= s
->face
->stipple
!= 0;
3442 else if (s
->hl
== DRAW_IMAGE_RAISED
3443 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3445 s
->gc
= s
->face
->gc
;
3446 s
->stippled_p
= s
->face
->stipple
!= 0;
3450 s
->gc
= s
->face
->gc
;
3451 s
->stippled_p
= s
->face
->stipple
!= 0;
3454 /* GC must have been set. */
3455 xassert (s
->gc
!= 0);
3459 /* Return in *R the clipping rectangle for glyph string S. */
3462 x_get_glyph_string_clip_rect (s
, r
)
3463 struct glyph_string
*s
;
3466 int r_height
, r_width
;
3468 if (s
->row
->full_width_p
)
3470 /* Draw full-width. X coordinates are relative to S->w->left. */
3471 int canon_x
= CANON_X_UNIT (s
->f
);
3473 r
->left
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
3474 r_width
= XFASTINT (s
->w
->width
) * canon_x
;
3476 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
3478 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
3479 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
3483 r
->left
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
3485 /* Unless displaying a mode or menu bar line, which are always
3486 fully visible, clip to the visible part of the row. */
3487 if (s
->w
->pseudo_window_p
)
3488 r_height
= s
->row
->visible_height
;
3490 r_height
= s
->height
;
3494 /* This is a text line that may be partially visible. */
3495 r
->left
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
3496 r_width
= window_box_width (s
->w
, s
->area
);
3497 r_height
= s
->row
->visible_height
;
3500 /* If S draws overlapping rows, it's sufficient to use the top and
3501 bottom of the window for clipping because this glyph string
3502 intentionally draws over other lines. */
3503 if (s
->for_overlaps_p
)
3505 r
->top
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
3506 r_height
= window_text_bottom_y (s
->w
) - r
->top
;
3510 /* Don't use S->y for clipping because it doesn't take partially
3511 visible lines into account. For example, it can be negative for
3512 partially visible lines at the top of a window. */
3513 if (!s
->row
->full_width_p
3514 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
3515 r
->top
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
3517 r
->top
= max (0, s
->row
->y
);
3519 /* If drawing a tool-bar window, draw it over the internal border
3520 at the top of the window. */
3521 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
3522 r
->top
-= s
->f
->output_data
.mac
->internal_border_width
;
3525 r
->top
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->top
);
3527 r
->bottom
= r
->top
+ r_height
;
3528 r
->right
= r
->left
+ r_width
;
3532 /* Set clipping for output of glyph string S. S may be part of a mode
3533 line or menu if we don't have X toolkit support. */
3536 x_set_glyph_string_clipping (s
)
3537 struct glyph_string
*s
;
3540 x_get_glyph_string_clip_rect (s
, &r
);
3541 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3545 /* Compute left and right overhang of glyph string S. If S is a glyph
3546 string for a composition, assume overhangs don't exist. */
3549 x_compute_glyph_string_overhangs (s
)
3550 struct glyph_string
*s
;
3553 && s
->first_glyph
->type
== CHAR_GLYPH
)
3556 int direction
, font_ascent
, font_descent
;
3557 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
3558 &font_ascent
, &font_descent
, &cs
);
3559 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
3560 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
3565 /* Compute overhangs and x-positions for glyph string S and its
3566 predecessors, or successors. X is the starting x-position for S.
3567 BACKWARD_P non-zero means process predecessors. */
3570 x_compute_overhangs_and_x (s
, x
, backward_p
)
3571 struct glyph_string
*s
;
3579 x_compute_glyph_string_overhangs (s
);
3589 x_compute_glyph_string_overhangs (s
);
3598 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3599 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3600 assumed to be zero. */
3603 x_get_glyph_overhangs (glyph
, f
, left
, right
)
3604 struct glyph
*glyph
;
3610 if (glyph
->type
== CHAR_GLYPH
)
3614 struct font_info
*font_info
;
3618 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
, NULL
);
3620 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
3622 && (pcm
= x_per_char_metric (font
, &char2b
)))
3624 if (pcm
->rbearing
> pcm
->width
)
3625 *right
= pcm
->rbearing
- pcm
->width
;
3626 if (pcm
->lbearing
< 0)
3627 *left
= -pcm
->lbearing
;
3633 /* Return the index of the first glyph preceding glyph string S that
3634 is overwritten by S because of S's left overhang. Value is -1
3635 if no glyphs are overwritten. */
3638 x_left_overwritten (s
)
3639 struct glyph_string
*s
;
3643 if (s
->left_overhang
)
3646 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3647 int first
= s
->first_glyph
- glyphs
;
3649 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
3650 x
-= glyphs
[i
].pixel_width
;
3661 /* Return the index of the first glyph preceding glyph string S that
3662 is overwriting S because of its right overhang. Value is -1 if no
3663 glyph in front of S overwrites S. */
3666 x_left_overwriting (s
)
3667 struct glyph_string
*s
;
3670 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3671 int first
= s
->first_glyph
- glyphs
;
3675 for (i
= first
- 1; i
>= 0; --i
)
3678 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3681 x
-= glyphs
[i
].pixel_width
;
3688 /* Return the index of the last glyph following glyph string S that is
3689 not overwritten by S because of S's right overhang. Value is -1 if
3690 no such glyph is found. */
3693 x_right_overwritten (s
)
3694 struct glyph_string
*s
;
3698 if (s
->right_overhang
)
3701 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3702 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3703 int end
= s
->row
->used
[s
->area
];
3705 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
3706 x
+= glyphs
[i
].pixel_width
;
3715 /* Return the index of the last glyph following glyph string S that
3716 overwrites S because of its left overhang. Value is negative
3717 if no such glyph is found. */
3720 x_right_overwriting (s
)
3721 struct glyph_string
*s
;
3724 int end
= s
->row
->used
[s
->area
];
3725 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3726 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3730 for (i
= first
; i
< end
; ++i
)
3733 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3736 x
+= glyphs
[i
].pixel_width
;
3743 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3746 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
3747 struct glyph_string
*s
;
3752 xgcv
.foreground
= s
->gc
->background
;
3753 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
3757 /* Draw the background of glyph_string S. If S->background_filled_p
3758 is non-zero don't draw it. FORCE_P non-zero means draw the
3759 background even if it wouldn't be drawn normally. This is used
3760 when a string preceding S draws into the background of S, or S
3761 contains the first component of a composition. */
3764 x_draw_glyph_string_background (s
, force_p
)
3765 struct glyph_string
*s
;
3768 /* Nothing to do if background has already been drawn or if it
3769 shouldn't be drawn in the first place. */
3770 if (!s
->background_filled_p
)
3772 int box_line_width
= max (s
->face
->box_line_width
, 0);
3774 #if 0 /* MAC_TODO: stipple */
3777 /* Fill background with a stipple pattern. */
3778 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3779 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
3780 s
->y
+ box_line_width
,
3781 s
->background_width
,
3782 s
->height
- 2 * box_line_width
);
3783 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3784 s
->background_filled_p
= 1;
3788 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
3789 || s
->font_not_found_p
3790 || s
->extends_to_end_of_line_p
3793 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
3794 s
->background_width
,
3795 s
->height
- 2 * box_line_width
);
3796 s
->background_filled_p
= 1;
3802 /* Draw the foreground of glyph string S. */
3805 x_draw_glyph_string_foreground (s
)
3806 struct glyph_string
*s
;
3810 /* If first glyph of S has a left box line, start drawing the text
3811 of S to the right of that box line. */
3812 if (s
->face
->box
!= FACE_NO_BOX
3813 && s
->first_glyph
->left_box_line_p
)
3814 x
= s
->x
+ abs (s
->face
->box_line_width
);
3818 /* Draw characters of S as rectangles if S's font could not be
3820 if (s
->font_not_found_p
)
3822 for (i
= 0; i
< s
->nchars
; ++i
)
3824 struct glyph
*g
= s
->first_glyph
+ i
;
3825 mac_draw_rectangle (s
->display
, s
->window
,
3826 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
3828 x
+= g
->pixel_width
;
3833 char *char1b
= (char *) s
->char2b
;
3834 int boff
= s
->font_info
->baseline_offset
;
3836 if (s
->font_info
->vertical_centering
)
3837 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3839 /* If we can use 8-bit functions, condense S->char2b. */
3841 for (i
= 0; i
< s
->nchars
; ++i
)
3842 char1b
[i
] = s
->char2b
[i
].byte2
;
3844 /* Draw text with XDrawString if background has already been
3845 filled. Otherwise, use XDrawImageString. (Note that
3846 XDrawImageString is usually faster than XDrawString.) Always
3847 use XDrawImageString when drawing the cursor so that there is
3848 no chance that characters under a box cursor are invisible. */
3849 if (s
->for_overlaps_p
3850 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3852 /* Draw characters with 16-bit or 8-bit functions. */
3854 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
3855 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3857 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
3858 s
->ybase
- boff
, char1b
, s
->nchars
);
3863 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
3864 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3866 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
3867 s
->ybase
- boff
, char1b
, s
->nchars
);
3872 /* Draw the foreground of composite glyph string S. */
3875 x_draw_composite_glyph_string_foreground (s
)
3876 struct glyph_string
*s
;
3880 /* If first glyph of S has a left box line, start drawing the text
3881 of S to the right of that box line. */
3882 if (s
->face
->box
!= FACE_NO_BOX
3883 && s
->first_glyph
->left_box_line_p
)
3884 x
= s
->x
+ abs (s
->face
->box_line_width
);
3888 /* S is a glyph string for a composition. S->gidx is the index of
3889 the first character drawn for glyphs of this composition.
3890 S->gidx == 0 means we are drawing the very first character of
3891 this composition. */
3893 /* Draw a rectangle for the composition if the font for the very
3894 first character of the composition could not be loaded. */
3895 if (s
->font_not_found_p
)
3898 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
3899 s
->width
- 1, s
->height
- 1);
3903 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3904 XDrawString16 (s
->display
, s
->window
, s
->gc
,
3905 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3906 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3912 #ifdef USE_X_TOOLKIT
3914 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3917 /* Return the frame on which widget WIDGET is used.. Abort if frame
3918 cannot be determined. */
3920 static struct frame
*
3921 x_frame_of_widget (widget
)
3924 struct x_display_info
*dpyinfo
;
3928 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3930 /* Find the top-level shell of the widget. Note that this function
3931 can be called when the widget is not yet realized, so XtWindow
3932 (widget) == 0. That's the reason we can't simply use
3933 x_any_window_to_frame. */
3934 while (!XtIsTopLevelShell (widget
))
3935 widget
= XtParent (widget
);
3937 /* Look for a frame with that top-level widget. Allocate the color
3938 on that frame to get the right gamma correction value. */
3939 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3940 if (GC_FRAMEP (XCAR (tail
))
3941 && (f
= XFRAME (XCAR (tail
)),
3942 (f
->output_data
.nothing
!= 1
3943 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3944 && f
->output_data
.x
->widget
== widget
)
3951 /* Allocate the color COLOR->pixel on the screen and display of
3952 widget WIDGET in colormap CMAP. If an exact match cannot be
3953 allocated, try the nearest color available. Value is non-zero
3954 if successful. This is called from lwlib. */
3957 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3962 struct frame
*f
= x_frame_of_widget (widget
);
3963 return x_alloc_nearest_color (f
, cmap
, color
);
3967 #endif /* USE_X_TOOLKIT */
3969 #if 0 /* MAC_TODO */
3971 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3972 CMAP. If an exact match can't be allocated, try the nearest color
3973 available. Value is non-zero if successful. Set *COLOR to the
3977 x_alloc_nearest_color (f
, cmap
, color
)
3982 Display
*display
= FRAME_X_DISPLAY (f
);
3983 Screen
*screen
= FRAME_X_SCREEN (f
);
3986 gamma_correct (f
, color
);
3987 rc
= XAllocColor (display
, cmap
, color
);
3990 /* If we got to this point, the colormap is full, so we're going
3991 to try to get the next closest color. The algorithm used is
3992 a least-squares matching, which is what X uses for closest
3993 color matching with StaticColor visuals. */
3995 unsigned long nearest_delta
= ~0;
3996 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3997 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3999 for (i
= 0; i
< ncells
; ++i
)
4001 XQueryColors (display
, cmap
, cells
, ncells
);
4003 for (nearest
= i
= 0; i
< ncells
; ++i
)
4005 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
4006 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
4007 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
4008 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
4010 if (delta
< nearest_delta
)
4013 nearest_delta
= delta
;
4017 color
->red
= cells
[nearest
].red
;
4018 color
->green
= cells
[nearest
].green
;
4019 color
->blue
= cells
[nearest
].blue
;
4020 rc
= XAllocColor (display
, cmap
, color
);
4023 #ifdef DEBUG_X_COLORS
4025 register_color (color
->pixel
);
4026 #endif /* DEBUG_X_COLORS */
4032 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4033 It's necessary to do this instead of just using PIXEL directly to
4034 get color reference counts right. */
4037 x_copy_color (f
, pixel
)
4039 unsigned long pixel
;
4043 color
.pixel
= pixel
;
4045 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
4046 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
4048 #ifdef DEBUG_X_COLORS
4049 register_color (pixel
);
4055 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4056 It's necessary to do this instead of just using PIXEL directly to
4057 get color reference counts right. */
4060 x_copy_dpy_color (dpy
, cmap
, pixel
)
4063 unsigned long pixel
;
4067 color
.pixel
= pixel
;
4069 XQueryColor (dpy
, cmap
, &color
);
4070 XAllocColor (dpy
, cmap
, &color
);
4072 #ifdef DEBUG_X_COLORS
4073 register_color (pixel
);
4078 #endif /* MAC_TODO */
4080 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4081 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4082 If this produces the same color as COLOR, try a color where all RGB
4083 values have DELTA added. Return the allocated color in *COLOR.
4084 DISPLAY is the X display, CMAP is the colormap to operate on.
4085 Value is non-zero if successful. */
4088 mac_alloc_lighter_color (f
, color
, factor
, delta
)
4090 unsigned long *color
;
4096 /* Change RGB values by specified FACTOR. Avoid overflow! */
4097 xassert (factor
>= 0);
4098 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
4099 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
4100 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
4102 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
4103 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
4104 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
4106 /* MAC_TODO: Map to palette and retry with delta if same? */
4107 /* MAC_TODO: Free colors (if using palette)? */
4118 /* Set up the foreground color for drawing relief lines of glyph
4119 string S. RELIEF is a pointer to a struct relief containing the GC
4120 with which lines will be drawn. Use a color that is FACTOR or
4121 DELTA lighter or darker than the relief's background which is found
4122 in S->f->output_data.x->relief_background. If such a color cannot
4123 be allocated, use DEFAULT_PIXEL, instead. */
4126 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
4128 struct relief
*relief
;
4131 unsigned long default_pixel
;
4134 struct mac_output
*di
= f
->output_data
.mac
;
4135 unsigned long mask
= GCForeground
;
4136 unsigned long pixel
;
4137 unsigned long background
= di
->relief_background
;
4138 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4140 /* MAC_TODO: Free colors (if using palette)? */
4142 /* Allocate new color. */
4143 xgcv
.foreground
= default_pixel
;
4145 if (mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
4147 relief
->allocated_p
= 1;
4148 xgcv
.foreground
= relief
->pixel
= pixel
;
4151 if (relief
->gc
== 0)
4153 #if 0 /* MAC_TODO: stipple */
4154 xgcv
.stipple
= dpyinfo
->gray
;
4157 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
4160 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
4164 /* Set up colors for the relief lines around glyph string S. */
4167 x_setup_relief_colors (s
)
4168 struct glyph_string
*s
;
4170 struct mac_output
*di
= s
->f
->output_data
.mac
;
4171 unsigned long color
;
4173 if (s
->face
->use_box_color_for_shadows_p
)
4174 color
= s
->face
->box_color
;
4179 /* Get the background color of the face. */
4180 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
4181 color
= xgcv
.background
;
4184 if (di
->white_relief
.gc
== 0
4185 || color
!= di
->relief_background
)
4187 di
->relief_background
= color
;
4188 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
4189 WHITE_PIX_DEFAULT (s
->f
));
4190 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
4191 BLACK_PIX_DEFAULT (s
->f
));
4196 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4197 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4198 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4199 relief. LEFT_P non-zero means draw a relief on the left side of
4200 the rectangle. RIGHT_P non-zero means draw a relief on the right
4201 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4205 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
4206 raised_p
, left_p
, right_p
, clip_rect
)
4208 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
4215 gc
= f
->output_data
.mac
->white_relief
.gc
;
4217 gc
= f
->output_data
.mac
->black_relief
.gc
;
4218 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), clip_rect
);
4221 for (i
= 0; i
< width
; ++i
)
4222 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
4223 left_x
+ i
* left_p
, top_y
+ i
,
4224 right_x
+ 1 - i
* right_p
, top_y
+ i
);
4228 for (i
= 0; i
< width
; ++i
)
4229 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
4230 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
4232 mac_reset_clipping (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
4234 gc
= f
->output_data
.mac
->black_relief
.gc
;
4236 gc
= f
->output_data
.mac
->white_relief
.gc
;
4237 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4241 for (i
= 0; i
< width
; ++i
)
4242 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
4243 left_x
+ i
* left_p
, bottom_y
- i
,
4244 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
4248 for (i
= 0; i
< width
; ++i
)
4249 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
4250 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
4252 mac_reset_clipping (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
4256 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4257 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4258 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4259 left side of the rectangle. RIGHT_P non-zero means draw a line
4260 on the right side of the rectangle. CLIP_RECT is the clipping
4261 rectangle to use when drawing. */
4264 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
4265 left_p
, right_p
, clip_rect
)
4266 struct glyph_string
*s
;
4267 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
4272 xgcv
.foreground
= s
->face
->box_color
;
4273 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
4276 XFillRectangle (s
->display
, s
->window
, &xgcv
,
4277 left_x
, top_y
, right_x
- left_x
, width
);
4281 XFillRectangle (s
->display
, s
->window
, &xgcv
,
4282 left_x
, top_y
, width
, bottom_y
- top_y
);
4285 XFillRectangle (s
->display
, s
->window
, &xgcv
,
4286 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
4290 XFillRectangle (s
->display
, s
->window
, &xgcv
,
4291 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
4293 mac_reset_clipping (s
->display
, s
->window
);
4297 /* Draw a box around glyph string S. */
4300 x_draw_glyph_string_box (s
)
4301 struct glyph_string
*s
;
4303 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
4304 int left_p
, right_p
;
4305 struct glyph
*last_glyph
;
4308 last_x
= window_box_right (s
->w
, s
->area
);
4309 if (s
->row
->full_width_p
4310 && !s
->w
->pseudo_window_p
)
4312 last_x
+= FRAME_X_RIGHT_FRINGE_WIDTH (s
->f
);
4313 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
4314 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
4317 /* The glyph that may have a right box line. */
4318 last_glyph
= (s
->cmp
|| s
->img
4320 : s
->first_glyph
+ s
->nchars
- 1);
4322 width
= abs (s
->face
->box_line_width
);
4323 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
4325 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
4327 : min (last_x
, s
->x
+ s
->background_width
) - 1));
4329 bottom_y
= top_y
+ s
->height
- 1;
4331 left_p
= (s
->first_glyph
->left_box_line_p
4332 || (s
->hl
== DRAW_MOUSE_FACE
4334 || s
->prev
->hl
!= s
->hl
)));
4335 right_p
= (last_glyph
->right_box_line_p
4336 || (s
->hl
== DRAW_MOUSE_FACE
4338 || s
->next
->hl
!= s
->hl
)));
4340 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4342 if (s
->face
->box
== FACE_SIMPLE_BOX
)
4343 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
4344 left_p
, right_p
, &clip_rect
);
4347 x_setup_relief_colors (s
);
4348 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
4349 width
, raised_p
, left_p
, right_p
, &clip_rect
);
4354 /* Draw foreground of image glyph string S. */
4357 x_draw_image_foreground (s
)
4358 struct glyph_string
*s
;
4361 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
4363 /* If first glyph of S has a left box line, start drawing it to the
4364 right of that line. */
4365 if (s
->face
->box
!= FACE_NO_BOX
4366 && s
->first_glyph
->left_box_line_p
)
4367 x
= s
->x
+ abs (s
->face
->box_line_width
);
4371 /* If there is a margin around the image, adjust x- and y-position
4373 x
+= s
->img
->hmargin
;
4374 y
+= s
->img
->vmargin
;
4378 #if 0 /* MAC_TODO: image mask */
4381 /* We can't set both a clip mask and use XSetClipRectangles
4382 because the latter also sets a clip mask. We also can't
4383 trust on the shape extension to be available
4384 (XShapeCombineRegion). So, compute the rectangle to draw
4386 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4389 XRectangle clip_rect
, image_rect
, r
;
4391 xgcv
.clip_mask
= s
->img
->mask
;
4392 xgcv
.clip_x_origin
= x
;
4393 xgcv
.clip_y_origin
= y
;
4394 xgcv
.function
= GXcopy
;
4395 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4397 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4400 image_rect
.width
= s
->img
->width
;
4401 image_rect
.height
= s
->img
->height
;
4402 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
4403 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
4404 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
4407 #endif /* MAC_TODO */
4409 mac_copy_area (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
4410 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4412 /* When the image has a mask, we can expect that at
4413 least part of a mouse highlight or a block cursor will
4414 be visible. If the image doesn't have a mask, make
4415 a block cursor visible by drawing a rectangle around
4416 the image. I believe it's looking better if we do
4417 nothing here for mouse-face. */
4418 if (s
->hl
== DRAW_CURSOR
)
4420 int r
= s
->img
->relief
;
4422 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
4423 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
4428 /* Draw a rectangle if image could not be loaded. */
4429 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
4430 s
->img
->width
- 1, s
->img
->height
- 1);
4435 /* Draw a relief around the image glyph string S. */
4438 x_draw_image_relief (s
)
4439 struct glyph_string
*s
;
4441 int x0
, y0
, x1
, y1
, thick
, raised_p
;
4444 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
4446 /* If first glyph of S has a left box line, start drawing it to the
4447 right of that line. */
4448 if (s
->face
->box
!= FACE_NO_BOX
4449 && s
->first_glyph
->left_box_line_p
)
4450 x
= s
->x
+ abs (s
->face
->box_line_width
);
4454 /* If there is a margin around the image, adjust x- and y-position
4456 x
+= s
->img
->hmargin
;
4457 y
+= s
->img
->vmargin
;
4459 if (s
->hl
== DRAW_IMAGE_SUNKEN
4460 || s
->hl
== DRAW_IMAGE_RAISED
)
4462 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
4463 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
4467 thick
= abs (s
->img
->relief
);
4468 raised_p
= s
->img
->relief
> 0;
4473 x1
= x
+ s
->img
->width
+ thick
- 1;
4474 y1
= y
+ s
->img
->height
+ thick
- 1;
4476 x_setup_relief_colors (s
);
4477 x_get_glyph_string_clip_rect (s
, &r
);
4478 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
4482 /* Draw the foreground of image glyph string S to PIXMAP. */
4485 x_draw_image_foreground_1 (s
, pixmap
)
4486 struct glyph_string
*s
;
4490 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
4492 /* If first glyph of S has a left box line, start drawing it to the
4493 right of that line. */
4494 if (s
->face
->box
!= FACE_NO_BOX
4495 && s
->first_glyph
->left_box_line_p
)
4496 x
= abs (s
->face
->box_line_width
);
4500 /* If there is a margin around the image, adjust x- and y-position
4502 x
+= s
->img
->hmargin
;
4503 y
+= s
->img
->vmargin
;
4507 #if 0 /* MAC_TODO: image mask */
4510 /* We can't set both a clip mask and use XSetClipRectangles
4511 because the latter also sets a clip mask. We also can't
4512 trust on the shape extension to be available
4513 (XShapeCombineRegion). So, compute the rectangle to draw
4515 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4519 xgcv
.clip_mask
= s
->img
->mask
;
4520 xgcv
.clip_x_origin
= x
;
4521 xgcv
.clip_y_origin
= y
;
4522 xgcv
.function
= GXcopy
;
4523 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4525 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4526 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4527 XSetClipMask (s
->display
, s
->gc
, None
);
4530 #endif /* MAC_TODO */
4532 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4533 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4535 /* When the image has a mask, we can expect that at
4536 least part of a mouse highlight or a block cursor will
4537 be visible. If the image doesn't have a mask, make
4538 a block cursor visible by drawing a rectangle around
4539 the image. I believe it's looking better if we do
4540 nothing here for mouse-face. */
4541 if (s
->hl
== DRAW_CURSOR
)
4543 int r
= s
->img
->relief
;
4545 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
- r
, y
- r
,
4546 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
4551 /* Draw a rectangle if image could not be loaded. */
4552 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
4553 s
->img
->width
- 1, s
->img
->height
- 1);
4557 /* Draw part of the background of glyph string S. X, Y, W, and H
4558 give the rectangle to draw. */
4561 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
4562 struct glyph_string
*s
;
4565 #if 0 /* MAC_TODO: stipple */
4568 /* Fill background with a stipple pattern. */
4569 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4570 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
4571 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4574 #endif /* MAC_TODO */
4575 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
4579 /* Draw image glyph string S.
4582 s->x +-------------------------
4585 | +-------------------------
4588 | | +-------------------
4594 x_draw_image_glyph_string (s
)
4595 struct glyph_string
*s
;
4598 int box_line_hwidth
= abs (s
->face
->box_line_width
);
4599 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
4603 height
= s
->height
- 2 * box_line_vwidth
;
4605 /* Fill background with face under the image. Do it only if row is
4606 taller than image or if image has a clip mask to reduce
4608 s
->stippled_p
= s
->face
->stipple
!= 0;
4609 if (height
> s
->img
->height
4612 #if 0 /* TODO: image mask */
4615 || s
->img
->pixmap
== 0
4616 || s
->width
!= s
->background_width
)
4618 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
4619 x
= s
->x
+ box_line_hwidth
;
4623 y
= s
->y
+ box_line_vwidth
;
4624 #if 0 /* TODO: image mask */
4627 /* Create a pixmap as large as the glyph string. Fill it
4628 with the background color. Copy the image to it, using
4629 its mask. Copy the temporary pixmap to the display. */
4630 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
4631 int depth
= DefaultDepthOfScreen (screen
);
4633 /* Create a pixmap as large as the glyph string. */
4634 pixmap
= XCreatePixmap (s
->display
, s
->window
,
4635 s
->background_width
,
4638 /* Don't clip in the following because we're working on the
4640 XSetClipMask (s
->display
, s
->gc
, None
);
4642 /* Fill the pixmap with the background color/stipple. */
4645 /* Fill background with a stipple pattern. */
4646 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4647 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4648 0, 0, s
->background_width
, s
->height
);
4649 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4654 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
4656 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
4657 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4658 0, 0, s
->background_width
, s
->height
);
4659 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4664 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
4666 s
->background_filled_p
= 1;
4669 /* Draw the foreground. */
4672 x_draw_image_foreground_1 (s
, pixmap
);
4673 x_set_glyph_string_clipping (s
);
4674 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
4675 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
4676 mac_reset_clipping (s
->display
, s
->window
);
4677 XFreePixmap (s
->display
, pixmap
);
4680 x_draw_image_foreground (s
);
4682 /* If we must draw a relief around the image, do it. */
4684 || s
->hl
== DRAW_IMAGE_RAISED
4685 || s
->hl
== DRAW_IMAGE_SUNKEN
)
4686 x_draw_image_relief (s
);
4690 /* Draw stretch glyph string S. */
4693 x_draw_stretch_glyph_string (s
)
4694 struct glyph_string
*s
;
4696 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4697 s
->stippled_p
= s
->face
->stipple
!= 0;
4699 if (s
->hl
== DRAW_CURSOR
4700 && !x_stretch_cursor_p
)
4702 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4703 as wide as the stretch glyph. */
4704 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
4707 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
4709 /* Clear rest using the GC of the original non-cursor face. */
4710 if (width
< s
->background_width
)
4712 GC gc
= s
->face
->gc
;
4713 int x
= s
->x
+ width
, y
= s
->y
;
4714 int w
= s
->background_width
- width
, h
= s
->height
;
4717 if (s
->row
->mouse_face_p
4718 && cursor_in_mouse_face_p (s
->w
))
4720 x_set_mouse_face_gc (s
);
4726 x_get_glyph_string_clip_rect (s
, &r
);
4727 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
4729 #if 0 /* MAC_TODO: stipple */
4730 if (s
->face
->stipple
)
4732 /* Fill background with a stipple pattern. */
4733 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
4734 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4735 XSetFillStyle (s
->display
, gc
, FillSolid
);
4738 #endif /* MAC_TODO */
4741 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
4742 XSetForeground (s
->display
, gc
, xgcv
.background
);
4743 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4744 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
4747 mac_reset_clipping (s
->display
, s
->window
);
4750 else if (!s
->background_filled_p
)
4751 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
4754 s
->background_filled_p
= 1;
4758 /* Draw glyph string S. */
4761 x_draw_glyph_string (s
)
4762 struct glyph_string
*s
;
4764 int relief_drawn_p
= 0;
4766 /* If S draws into the background of its successor, draw the
4767 background of the successor first so that S can draw into it.
4768 This makes S->next use XDrawString instead of XDrawImageString. */
4769 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
4771 xassert (s
->next
->img
== NULL
);
4772 x_set_glyph_string_gc (s
->next
);
4773 x_set_glyph_string_clipping (s
->next
);
4774 x_draw_glyph_string_background (s
->next
, 1);
4778 /* Set up S->gc, set clipping and draw S. */
4779 x_set_glyph_string_gc (s
);
4781 /* Draw relief (if any) in advance for char/composition so that the
4782 glyph string can be drawn over it. */
4783 if (!s
->for_overlaps_p
4784 && s
->face
->box
!= FACE_NO_BOX
4785 && (s
->first_glyph
->type
== CHAR_GLYPH
4786 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
4789 x_set_glyph_string_clipping (s
);
4790 x_draw_glyph_string_background (s
, 1);
4791 x_draw_glyph_string_box (s
);
4792 x_set_glyph_string_clipping (s
);
4796 x_set_glyph_string_clipping (s
);
4798 switch (s
->first_glyph
->type
)
4801 x_draw_image_glyph_string (s
);
4805 x_draw_stretch_glyph_string (s
);
4809 if (s
->for_overlaps_p
)
4810 s
->background_filled_p
= 1;
4812 x_draw_glyph_string_background (s
, 0);
4813 x_draw_glyph_string_foreground (s
);
4816 case COMPOSITE_GLYPH
:
4817 if (s
->for_overlaps_p
|| s
->gidx
> 0)
4818 s
->background_filled_p
= 1;
4820 x_draw_glyph_string_background (s
, 1);
4821 x_draw_composite_glyph_string_foreground (s
);
4828 if (!s
->for_overlaps_p
)
4830 /* Draw underline. */
4831 if (s
->face
->underline_p
)
4833 unsigned long h
= 1;
4834 unsigned long dy
= s
->height
- h
;
4836 if (s
->face
->underline_defaulted_p
)
4837 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4842 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4843 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4844 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4846 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4850 /* Draw overline. */
4851 if (s
->face
->overline_p
)
4853 unsigned long dy
= 0, h
= 1;
4855 if (s
->face
->overline_color_defaulted_p
)
4856 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4861 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4862 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4863 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4865 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4869 /* Draw strike-through. */
4870 if (s
->face
->strike_through_p
)
4872 unsigned long h
= 1;
4873 unsigned long dy
= (s
->height
- h
) / 2;
4875 if (s
->face
->strike_through_color_defaulted_p
)
4876 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4881 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4882 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4883 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4885 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4890 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4891 x_draw_glyph_string_box (s
);
4894 /* Reset clipping. */
4895 mac_reset_clipping (s
->display
, s
->window
);
4899 static int x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
4900 struct face
**, int));
4903 /* Fill glyph string S with composition components specified by S->cmp.
4905 FACES is an array of faces for all components of this composition.
4906 S->gidx is the index of the first component for S.
4907 OVERLAPS_P non-zero means S should draw the foreground only, and
4908 use its physical height for clipping.
4910 Value is the index of a component not in S. */
4913 x_fill_composite_glyph_string (s
, faces
, overlaps_p
)
4914 struct glyph_string
*s
;
4915 struct face
**faces
;
4922 s
->for_overlaps_p
= overlaps_p
;
4924 s
->face
= faces
[s
->gidx
];
4925 s
->font
= s
->face
->font
;
4926 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4928 /* For all glyphs of this composition, starting at the offset
4929 S->gidx, until we reach the end of the definition or encounter a
4930 glyph that requires the different face, add it to S. */
4932 for (i
= s
->gidx
+ 1; i
< s
->cmp
->glyph_len
&& faces
[i
] == s
->face
; ++i
)
4935 /* All glyph strings for the same composition has the same width,
4936 i.e. the width set for the first component of the composition. */
4938 s
->width
= s
->first_glyph
->pixel_width
;
4940 /* If the specified font could not be loaded, use the frame's
4941 default font, but record the fact that we couldn't load it in
4942 the glyph string so that we can draw rectangles for the
4943 characters of the glyph string. */
4944 if (s
->font
== NULL
)
4946 s
->font_not_found_p
= 1;
4947 s
->font
= FRAME_FONT (s
->f
);
4950 /* Adjust base line for subscript/superscript text. */
4951 s
->ybase
+= s
->first_glyph
->voffset
;
4953 xassert (s
->face
&& s
->face
->gc
);
4955 /* This glyph string must always be drawn with 16-bit functions. */
4958 return s
->gidx
+ s
->nchars
;
4962 /* Fill glyph string S from a sequence of character glyphs.
4964 FACE_ID is the face id of the string. START is the index of the
4965 first glyph to consider, END is the index of the last + 1.
4966 OVERLAPS_P non-zero means S should draw the foreground only, and
4967 use its physical height for clipping.
4969 Value is the index of the first glyph not in S. */
4972 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
4973 struct glyph_string
*s
;
4975 int start
, end
, overlaps_p
;
4977 struct glyph
*glyph
, *last
;
4979 int glyph_not_available_p
;
4981 xassert (s
->f
== XFRAME (s
->w
->frame
));
4982 xassert (s
->nchars
== 0);
4983 xassert (start
>= 0 && end
> start
);
4985 s
->for_overlaps_p
= overlaps_p
;
4986 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4987 last
= s
->row
->glyphs
[s
->area
] + end
;
4988 voffset
= glyph
->voffset
;
4990 glyph_not_available_p
= glyph
->glyph_not_available_p
;
4993 && glyph
->type
== CHAR_GLYPH
4994 && glyph
->voffset
== voffset
4995 /* Same face id implies same font, nowadays. */
4996 && glyph
->face_id
== face_id
4997 && glyph
->glyph_not_available_p
== glyph_not_available_p
)
5001 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
5002 s
->char2b
+ s
->nchars
,
5004 s
->two_byte_p
= two_byte_p
;
5006 xassert (s
->nchars
<= end
- start
);
5007 s
->width
+= glyph
->pixel_width
;
5011 s
->font
= s
->face
->font
;
5012 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
5014 /* If the specified font could not be loaded, use the frame's font,
5015 but record the fact that we couldn't load it in
5016 S->font_not_found_p so that we can draw rectangles for the
5017 characters of the glyph string. */
5018 if (s
->font
== NULL
|| glyph_not_available_p
)
5020 s
->font_not_found_p
= 1;
5021 s
->font
= FRAME_FONT (s
->f
);
5024 /* Adjust base line for subscript/superscript text. */
5025 s
->ybase
+= voffset
;
5027 xassert (s
->face
&& s
->face
->gc
);
5028 return glyph
- s
->row
->glyphs
[s
->area
];
5032 /* Fill glyph string S from image glyph S->first_glyph. */
5035 x_fill_image_glyph_string (s
)
5036 struct glyph_string
*s
;
5038 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
5039 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img_id
);
5041 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->face_id
);
5042 s
->font
= s
->face
->font
;
5043 s
->width
= s
->first_glyph
->pixel_width
;
5045 /* Adjust base line for subscript/superscript text. */
5046 s
->ybase
+= s
->first_glyph
->voffset
;
5050 /* Fill glyph string S from a sequence of stretch glyphs.
5052 ROW is the glyph row in which the glyphs are found, AREA is the
5053 area within the row. START is the index of the first glyph to
5054 consider, END is the index of the last + 1.
5056 Value is the index of the first glyph not in S. */
5059 x_fill_stretch_glyph_string (s
, row
, area
, start
, end
)
5060 struct glyph_string
*s
;
5061 struct glyph_row
*row
;
5062 enum glyph_row_area area
;
5065 struct glyph
*glyph
, *last
;
5066 int voffset
, face_id
;
5068 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
5070 glyph
= s
->row
->glyphs
[s
->area
] + start
;
5071 last
= s
->row
->glyphs
[s
->area
] + end
;
5072 face_id
= glyph
->face_id
;
5073 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
5074 s
->font
= s
->face
->font
;
5075 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
5076 s
->width
= glyph
->pixel_width
;
5077 voffset
= glyph
->voffset
;
5081 && glyph
->type
== STRETCH_GLYPH
5082 && glyph
->voffset
== voffset
5083 && glyph
->face_id
== face_id
);
5085 s
->width
+= glyph
->pixel_width
;
5087 /* Adjust base line for subscript/superscript text. */
5088 s
->ybase
+= voffset
;
5091 return glyph
- s
->row
->glyphs
[s
->area
];
5095 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5096 of XChar2b structures for S; it can't be allocated in
5097 x_init_glyph_string because it must be allocated via `alloca'. W
5098 is the window on which S is drawn. ROW and AREA are the glyph row
5099 and area within the row from which S is constructed. START is the
5100 index of the first glyph structure covered by S. HL is a
5101 face-override for drawing S. */
5104 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
5105 struct glyph_string
*s
;
5108 struct glyph_row
*row
;
5109 enum glyph_row_area area
;
5111 enum draw_glyphs_face hl
;
5113 bzero (s
, sizeof *s
);
5115 s
->f
= XFRAME (w
->frame
);
5116 s
->display
= FRAME_MAC_DISPLAY (s
->f
);
5117 s
->window
= FRAME_MAC_WINDOW (s
->f
);
5122 s
->first_glyph
= row
->glyphs
[area
] + start
;
5123 s
->height
= row
->height
;
5124 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5126 /* Display the internal border below the tool-bar window. */
5127 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
5128 s
->y
-= s
->f
->output_data
.mac
->internal_border_width
;
5130 s
->ybase
= s
->y
+ row
->ascent
;
5134 /* Set background width of glyph string S. START is the index of the
5135 first glyph following S. LAST_X is the right-most x-position + 1
5136 in the drawing area. */
5139 x_set_glyph_string_background_width (s
, start
, last_x
)
5140 struct glyph_string
*s
;
5144 /* If the face of this glyph string has to be drawn to the end of
5145 the drawing area, set S->extends_to_end_of_line_p. */
5146 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
5148 if (start
== s
->row
->used
[s
->area
]
5149 && s
->area
== TEXT_AREA
5150 && ((s
->hl
== DRAW_NORMAL_TEXT
5151 && (s
->row
->fill_line_p
5152 || s
->face
->background
!= default_face
->background
5153 || s
->face
->stipple
!= default_face
->stipple
5154 || s
->row
->mouse_face_p
))
5155 || s
->hl
== DRAW_MOUSE_FACE
5156 || ((s
->hl
== DRAW_IMAGE_RAISED
|| s
->hl
== DRAW_IMAGE_SUNKEN
)
5157 && s
->row
->fill_line_p
)))
5158 s
->extends_to_end_of_line_p
= 1;
5160 /* If S extends its face to the end of the line, set its
5161 background_width to the distance to the right edge of the drawing
5163 if (s
->extends_to_end_of_line_p
)
5164 s
->background_width
= last_x
- s
->x
+ 1;
5166 s
->background_width
= s
->width
;
5170 /* Add a glyph string for a stretch glyph to the list of strings
5171 between HEAD and TAIL. START is the index of the stretch glyph in
5172 row area AREA of glyph row ROW. END is the index of the last glyph
5173 in that glyph row area. X is the current output position assigned
5174 to the new glyph string constructed. HL overrides that face of the
5175 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5176 is the right-most x-position of the drawing area. */
5178 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5179 and below -- keep them on one line. */
5180 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5183 s = (struct glyph_string *) alloca (sizeof *s); \
5184 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5185 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5186 x_append_glyph_string (&HEAD, &TAIL, s); \
5192 /* Add a glyph string for an image glyph to the list of strings
5193 between HEAD and TAIL. START is the index of the image glyph in
5194 row area AREA of glyph row ROW. END is the index of the last glyph
5195 in that glyph row area. X is the current output position assigned
5196 to the new glyph string constructed. HL overrides that face of the
5197 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5198 is the right-most x-position of the drawing area. */
5200 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5203 s = (struct glyph_string *) alloca (sizeof *s); \
5204 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5205 x_fill_image_glyph_string (s); \
5206 x_append_glyph_string (&HEAD, &TAIL, s); \
5213 /* Add a glyph string for a sequence of character glyphs to the list
5214 of strings between HEAD and TAIL. START is the index of the first
5215 glyph in row area AREA of glyph row ROW that is part of the new
5216 glyph string. END is the index of the last glyph in that glyph row
5217 area. X is the current output position assigned to the new glyph
5218 string constructed. HL overrides that face of the glyph; e.g. it
5219 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5220 right-most x-position of the drawing area. */
5222 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5228 c = (ROW)->glyphs[AREA][START].u.ch; \
5229 face_id = (ROW)->glyphs[AREA][START].face_id; \
5231 s = (struct glyph_string *) alloca (sizeof *s); \
5232 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5233 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5234 x_append_glyph_string (&HEAD, &TAIL, s); \
5236 START = x_fill_glyph_string (s, face_id, START, END, \
5242 /* Add a glyph string for a composite sequence to the list of strings
5243 between HEAD and TAIL. START is the index of the first glyph in
5244 row area AREA of glyph row ROW that is part of the new glyph
5245 string. END is the index of the last glyph in that glyph row area.
5246 X is the current output position assigned to the new glyph string
5247 constructed. HL overrides that face of the glyph; e.g. it is
5248 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5249 x-position of the drawing area. */
5251 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5253 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5254 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5255 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5256 struct composition *cmp = composition_table[cmp_id]; \
5257 int glyph_len = cmp->glyph_len; \
5259 struct face **faces; \
5260 struct glyph_string *first_s = NULL; \
5263 base_face = base_face->ascii_face; \
5264 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5265 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5266 /* At first, fill in `char2b' and `faces'. */ \
5267 for (n = 0; n < glyph_len; n++) \
5269 int c = COMPOSITION_GLYPH (cmp, n); \
5270 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5271 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5272 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5273 this_face_id, char2b + n, 1); \
5276 /* Make glyph_strings for each glyph sequence that is drawable by \
5277 the same face, and append them to HEAD/TAIL. */ \
5278 for (n = 0; n < cmp->glyph_len;) \
5280 s = (struct glyph_string *) alloca (sizeof *s); \
5281 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5282 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5290 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5298 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5299 of AREA of glyph row ROW on window W between indices START and END.
5300 HL overrides the face for drawing glyph strings, e.g. it is
5301 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5302 x-positions of the drawing area.
5304 This is an ugly monster macro construct because we must use alloca
5305 to allocate glyph strings (because x_draw_glyphs can be called
5308 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5311 HEAD = TAIL = NULL; \
5312 while (START < END) \
5314 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5315 switch (first_glyph->type) \
5318 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5319 TAIL, HL, X, LAST_X, \
5323 case COMPOSITE_GLYPH: \
5324 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5325 HEAD, TAIL, HL, X, LAST_X,\
5329 case STRETCH_GLYPH: \
5330 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5331 HEAD, TAIL, HL, X, LAST_X); \
5335 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5336 TAIL, HL, X, LAST_X); \
5343 x_set_glyph_string_background_width (s, START, LAST_X); \
5350 /* Draw glyphs between START and END in AREA of ROW on window W,
5351 starting at x-position X. X is relative to AREA in W. HL is a
5352 face-override with the following meaning:
5354 DRAW_NORMAL_TEXT draw normally
5355 DRAW_CURSOR draw in cursor face
5356 DRAW_MOUSE_FACE draw in mouse face.
5357 DRAW_INVERSE_VIDEO draw in mode line face
5358 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5359 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5361 If OVERLAPS_P is non-zero, draw only the foreground of characters
5362 and clip to the physical height of ROW.
5364 Value is the x-position reached, relative to AREA of W. */
5367 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, overlaps_p
)
5370 struct glyph_row
*row
;
5371 enum glyph_row_area area
;
5373 enum draw_glyphs_face hl
;
5376 struct glyph_string
*head
, *tail
;
5377 struct glyph_string
*s
;
5378 int last_x
, area_width
;
5382 /* Let's rather be paranoid than getting a SEGV. */
5383 end
= min (end
, row
->used
[area
]);
5384 start
= max (0, start
);
5385 start
= min (end
, start
);
5387 /* Translate X to frame coordinates. Set last_x to the right
5388 end of the drawing area. */
5389 if (row
->full_width_p
)
5391 /* X is relative to the left edge of W, without scroll bars
5393 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5394 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
5397 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5398 last_x
= window_left_x
+ area_width
;
5400 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5402 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5403 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
5409 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
5410 last_x
-= FRAME_INTERNAL_BORDER_WIDTH (f
);
5414 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
5415 area_width
= window_box_width (w
, area
);
5416 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
5419 /* Build a doubly-linked list of glyph_string structures between
5420 head and tail from what we have to draw. Note that the macro
5421 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5422 the reason we use a separate variable `i'. */
5424 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
5427 x_reached
= tail
->x
+ tail
->background_width
;
5431 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5432 the row, redraw some glyphs in front or following the glyph
5433 strings built above. */
5434 if (head
&& !overlaps_p
&& row
->contains_overlapping_glyphs_p
)
5437 struct glyph_string
*h
, *t
;
5439 /* Compute overhangs for all glyph strings. */
5440 for (s
= head
; s
; s
= s
->next
)
5441 x_compute_glyph_string_overhangs (s
);
5443 /* Prepend glyph strings for glyphs in front of the first glyph
5444 string that are overwritten because of the first glyph
5445 string's left overhang. The background of all strings
5446 prepended must be drawn because the first glyph string
5448 i
= x_left_overwritten (head
);
5452 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
5453 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
5456 x_compute_overhangs_and_x (t
, head
->x
, 1);
5457 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
5460 /* Prepend glyph strings for glyphs in front of the first glyph
5461 string that overwrite that glyph string because of their
5462 right overhang. For these strings, only the foreground must
5463 be drawn, because it draws over the glyph string at `head'.
5464 The background must not be drawn because this would overwrite
5465 right overhangs of preceding glyphs for which no glyph
5467 i
= x_left_overwriting (head
);
5470 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
5471 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
5473 for (s
= h
; s
; s
= s
->next
)
5474 s
->background_filled_p
= 1;
5475 x_compute_overhangs_and_x (t
, head
->x
, 1);
5476 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
5479 /* Append glyphs strings for glyphs following the last glyph
5480 string tail that are overwritten by tail. The background of
5481 these strings has to be drawn because tail's foreground draws
5483 i
= x_right_overwritten (tail
);
5486 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
5487 DRAW_NORMAL_TEXT
, x
, last_x
,
5489 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
5490 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5493 /* Append glyph strings for glyphs following the last glyph
5494 string tail that overwrite tail. The foreground of such
5495 glyphs has to be drawn because it writes into the background
5496 of tail. The background must not be drawn because it could
5497 paint over the foreground of following glyphs. */
5498 i
= x_right_overwriting (tail
);
5501 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
5502 DRAW_NORMAL_TEXT
, x
, last_x
,
5504 for (s
= h
; s
; s
= s
->next
)
5505 s
->background_filled_p
= 1;
5506 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
5507 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5511 /* Draw all strings. */
5512 for (s
= head
; s
; s
= s
->next
)
5513 x_draw_glyph_string (s
);
5515 if (area
== TEXT_AREA
5516 && !row
->full_width_p
5517 /* When drawing overlapping rows, only the glyph strings'
5518 foreground is drawn, which doesn't erase a cursor
5522 int x0
= head
? head
->x
: x
;
5523 int x1
= tail
? tail
->x
+ tail
->background_width
: x
;
5525 x0
= FRAME_TO_WINDOW_PIXEL_X (w
, x0
);
5526 x1
= FRAME_TO_WINDOW_PIXEL_X (w
, x1
);
5528 if (!row
->full_width_p
&& XFASTINT (w
->left_margin_width
) != 0)
5530 int left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
5531 x0
-= left_area_width
;
5532 x1
-= left_area_width
;
5535 notice_overwritten_cursor (w
, area
, x0
, x1
,
5536 row
->y
, MATRIX_ROW_BOTTOM_Y (row
));
5539 /* Value is the x-position up to which drawn, relative to AREA of W.
5540 This doesn't include parts drawn because of overhangs. */
5541 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
5542 if (!row
->full_width_p
)
5544 if (area
> LEFT_MARGIN_AREA
)
5545 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
5546 if (area
> TEXT_AREA
)
5547 x_reached
-= window_box_width (w
, TEXT_AREA
);
5554 /* Fix the display of area AREA of overlapping row ROW in window W. */
5557 x_fix_overlapping_area (w
, row
, area
)
5559 struct glyph_row
*row
;
5560 enum glyph_row_area area
;
5566 if (area
== LEFT_MARGIN_AREA
)
5568 else if (area
== TEXT_AREA
)
5569 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5571 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5572 + window_box_width (w
, TEXT_AREA
));
5574 for (i
= 0; i
< row
->used
[area
];)
5576 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
5578 int start
= i
, start_x
= x
;
5582 x
+= row
->glyphs
[area
][i
].pixel_width
;
5585 while (i
< row
->used
[area
]
5586 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
5588 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
5589 DRAW_NORMAL_TEXT
, 1);
5593 x
+= row
->glyphs
[area
][i
].pixel_width
;
5602 /* Output LEN glyphs starting at START at the nominal cursor position.
5603 Advance the nominal cursor over the text. The global variable
5604 updated_window contains the window being updated, updated_row is
5605 the glyph row being updated, and updated_area is the area of that
5606 row being updated. */
5609 x_write_glyphs (start
, len
)
5610 struct glyph
*start
;
5615 xassert (updated_window
&& updated_row
);
5620 hpos
= start
- updated_row
->glyphs
[updated_area
];
5621 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
5622 updated_row
, updated_area
,
5624 DRAW_NORMAL_TEXT
, 0);
5628 /* Advance the output cursor. */
5629 output_cursor
.hpos
+= len
;
5630 output_cursor
.x
= x
;
5634 /* Insert LEN glyphs from START at the nominal cursor position. */
5637 x_insert_glyphs (start
, len
)
5638 struct glyph
*start
;
5643 int line_height
, shift_by_width
, shifted_region_width
;
5644 struct glyph_row
*row
;
5645 struct glyph
*glyph
;
5646 int frame_x
, frame_y
, hpos
;
5648 xassert (updated_window
&& updated_row
);
5651 f
= XFRAME (WINDOW_FRAME (w
));
5653 /* Get the height of the line we are in. */
5655 line_height
= row
->height
;
5657 /* Get the width of the glyphs to insert. */
5659 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
5660 shift_by_width
+= glyph
->pixel_width
;
5662 /* Get the width of the region to shift right. */
5663 shifted_region_width
= (window_box_width (w
, updated_area
)
5668 frame_x
= window_box_left (w
, updated_area
) + output_cursor
.x
;
5669 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
5671 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5672 f
->output_data
.mac
->normal_gc
,
5674 shifted_region_width
, line_height
,
5675 frame_x
+ shift_by_width
, frame_y
);
5677 /* Write the glyphs. */
5678 hpos
= start
- row
->glyphs
[updated_area
];
5679 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
5680 DRAW_NORMAL_TEXT
, 0);
5682 /* Advance the output cursor. */
5683 output_cursor
.hpos
+= len
;
5684 output_cursor
.x
+= shift_by_width
;
5689 /* Delete N glyphs at the nominal cursor position. Not implemented
5700 /* Erase the current text line from the nominal cursor position
5701 (inclusive) to pixel column TO_X (exclusive). The idea is that
5702 everything from TO_X onward is already erased.
5704 TO_X is a pixel position relative to updated_area of
5705 updated_window. TO_X == -1 means clear to the end of this area. */
5708 x_clear_end_of_line (to_x
)
5712 struct window
*w
= updated_window
;
5713 int max_x
, min_y
, max_y
;
5714 int from_x
, from_y
, to_y
;
5716 xassert (updated_window
&& updated_row
);
5717 f
= XFRAME (w
->frame
);
5719 if (updated_row
->full_width_p
)
5721 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5722 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5723 && !w
->pseudo_window_p
)
5724 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5727 max_x
= window_box_width (w
, updated_area
);
5728 max_y
= window_text_bottom_y (w
);
5730 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5731 of window. For TO_X > 0, truncate to end of drawing area. */
5737 to_x
= min (to_x
, max_x
);
5739 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
5741 /* Notice if the cursor will be cleared by this operation. */
5742 if (!updated_row
->full_width_p
)
5743 notice_overwritten_cursor (w
, updated_area
,
5744 output_cursor
.x
, -1,
5746 MATRIX_ROW_BOTTOM_Y (updated_row
));
5748 from_x
= output_cursor
.x
;
5750 /* Translate to frame coordinates. */
5751 if (updated_row
->full_width_p
)
5753 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
5754 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
5758 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
5759 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
5762 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
5763 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
5764 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
5766 /* Prevent inadvertently clearing to end of the X window. */
5767 if (to_x
> from_x
&& to_y
> from_y
)
5770 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5771 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
5778 /* Clear entire frame. If updating_frame is non-null, clear that
5779 frame. Otherwise clear the selected frame. */
5789 f
= SELECTED_FRAME ();
5791 /* Clearing the frame will erase any cursor, so mark them all as no
5793 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5794 output_cursor
.hpos
= output_cursor
.vpos
= 0;
5795 output_cursor
.x
= -1;
5797 /* We don't set the output cursor here because there will always
5798 follow an explicit cursor_to. */
5800 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
5802 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5803 /* We have to clear the scroll bars, too. If we have changed
5804 colors or something like that, then they should be notified. */
5805 x_scroll_bar_clear (f
);
5808 XFlush (FRAME_MAC_DISPLAY (f
));
5814 /* Invert the middle quarter of the frame for .15 sec. */
5816 /* We use the select system call to do the waiting, so we have to make
5817 sure it's available. If it isn't, we just won't do visual bells. */
5819 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5821 /* Subtract the `struct timeval' values X and Y, storing the result in
5822 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5825 timeval_subtract (result
, x
, y
)
5826 struct timeval
*result
, x
, y
;
5828 /* Perform the carry for the later subtraction by updating y. This
5829 is safer because on some systems the tv_sec member is unsigned. */
5830 if (x
.tv_usec
< y
.tv_usec
)
5832 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
5833 y
.tv_usec
-= 1000000 * nsec
;
5837 if (x
.tv_usec
- y
.tv_usec
> 1000000)
5839 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
5840 y
.tv_usec
+= 1000000 * nsec
;
5844 /* Compute the time remaining to wait. tv_usec is certainly
5846 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
5847 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
5849 /* Return indication of whether the result should be considered
5851 return x
.tv_sec
< y
.tv_sec
;
5863 struct timeval wakeup
;
5865 EMACS_GET_TIME (wakeup
);
5867 /* Compute time to wait until, propagating carry from usecs. */
5868 wakeup
.tv_usec
+= 150000;
5869 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
5870 wakeup
.tv_usec
%= 1000000;
5872 /* Keep waiting until past the time wakeup. */
5875 struct timeval timeout
;
5877 EMACS_GET_TIME (timeout
);
5879 /* In effect, timeout = wakeup - timeout.
5880 Break if result would be negative. */
5881 if (timeval_subtract (&timeout
, wakeup
, timeout
))
5884 /* Try to wait that long--but we might wake up sooner. */
5885 select (0, NULL
, NULL
, NULL
, &timeout
);
5894 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5897 /* Make audible bell. */
5902 struct frame
*f
= SELECTED_FRAME ();
5904 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5912 XFlush (FRAME_MAC_DISPLAY (f
));
5919 /* Specify how many text lines, from the top of the window,
5920 should be affected by insert-lines and delete-lines operations.
5921 This, and those operations, are used only within an update
5922 that is bounded by calls to x_update_begin and x_update_end. */
5925 XTset_terminal_window (n
)
5928 /* This function intentionally left blank. */
5933 /***********************************************************************
5935 ***********************************************************************/
5937 /* Perform an insert-lines or delete-lines operation, inserting N
5938 lines or deleting -N lines at vertical position VPOS. */
5941 x_ins_del_lines (vpos
, n
)
5948 /* Scroll part of the display as described by RUN. */
5951 x_scroll_run (w
, run
)
5955 struct frame
*f
= XFRAME (w
->frame
);
5956 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
5958 /* Get frame-relative bounding box of the text display area of W,
5959 without mode lines. Include in this box the left and right
5961 window_box (w
, -1, &x
, &y
, &width
, &height
);
5962 width
+= FRAME_X_FRINGE_WIDTH (f
);
5963 x
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
5965 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5966 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5967 bottom_y
= y
+ height
;
5971 /* Scrolling up. Make sure we don't copy part of the mode
5972 line at the bottom. */
5973 if (from_y
+ run
->height
> bottom_y
)
5974 height
= bottom_y
- from_y
;
5976 height
= run
->height
;
5980 /* Scolling down. Make sure we don't copy over the mode line.
5982 if (to_y
+ run
->height
> bottom_y
)
5983 height
= bottom_y
- to_y
;
5985 height
= run
->height
;
5990 /* Cursor off. Will be switched on again in x_update_window_end. */
5994 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5995 f
->output_data
.mac
->normal_gc
,
6005 /***********************************************************************
6007 ***********************************************************************/
6009 /* Redisplay an exposed area of frame F. X and Y are the upper-left
6010 corner of the exposed rectangle. W and H are width and height of
6011 the exposed area. All are pixel values. W or H zero means redraw
6012 the entire frame. */
6015 expose_frame (f
, x
, y
, w
, h
)
6020 int mouse_face_overwritten_p
= 0;
6022 TRACE ((stderr
, "expose_frame "));
6024 /* No need to redraw if frame will be redrawn soon. */
6025 if (FRAME_GARBAGED_P (f
))
6027 TRACE ((stderr
, " garbaged\n"));
6031 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6032 or deactivated here, for unknown reasons, activated scroll bars
6033 are shown in deactivated frames in some instances. */
6034 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
6035 activate_scroll_bars (f
);
6037 deactivate_scroll_bars (f
);
6039 /* If basic faces haven't been realized yet, there is no point in
6040 trying to redraw anything. This can happen when we get an expose
6041 event while Emacs is starting, e.g. by moving another window. */
6042 if (FRAME_FACE_CACHE (f
) == NULL
6043 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
6045 TRACE ((stderr
, " no faces\n"));
6049 if (w
== 0 || h
== 0)
6052 r
.right
= CANON_X_UNIT (f
) * f
->width
;
6053 r
.bottom
= CANON_Y_UNIT (f
) * f
->height
;
6063 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.left
, r
.top
, r
.right
, r
.bottom
));
6064 mouse_face_overwritten_p
= expose_window_tree (XWINDOW (f
->root_window
), &r
);
6066 if (WINDOWP (f
->tool_bar_window
))
6067 mouse_face_overwritten_p
6068 |= expose_window (XWINDOW (f
->tool_bar_window
), &r
);
6070 /* Some window managers support a focus-follows-mouse style with
6071 delayed raising of frames. Imagine a partially obscured frame,
6072 and moving the mouse into partially obscured mouse-face on that
6073 frame. The visible part of the mouse-face will be highlighted,
6074 then the WM raises the obscured frame. With at least one WM, KDE
6075 2.1, Emacs is not getting any event for the raising of the frame
6076 (even tried with SubstructureRedirectMask), only Expose events.
6077 These expose events will draw text normally, i.e. not
6078 highlighted. Which means we must redo the highlight here.
6079 Subsume it under ``we love X''. --gerd 2001-08-15 */
6080 /* Included in Windows version because Windows most likely does not
6081 do the right thing if any third party tool offers
6082 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6083 if (mouse_face_overwritten_p
&& !FRAME_GARBAGED_P (f
))
6085 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6086 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6088 int x
= dpyinfo
->mouse_face_mouse_x
;
6089 int y
= dpyinfo
->mouse_face_mouse_y
;
6090 clear_mouse_face (dpyinfo
);
6091 note_mouse_highlight (f
, x
, y
);
6097 /* Redraw (parts) of all windows in the window tree rooted at W that
6098 intersect R. R contains frame pixel coordinates. */
6101 expose_window_tree (w
, r
)
6105 struct frame
*f
= XFRAME (w
->frame
);
6106 int mouse_face_overwritten_p
= 0;
6108 while (w
&& !FRAME_GARBAGED_P (f
))
6110 if (!NILP (w
->hchild
))
6111 mouse_face_overwritten_p
6112 |= expose_window_tree (XWINDOW (w
->hchild
), r
);
6113 else if (!NILP (w
->vchild
))
6114 mouse_face_overwritten_p
6115 |= expose_window_tree (XWINDOW (w
->vchild
), r
);
6117 mouse_face_overwritten_p
|= expose_window (w
, r
);
6119 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
6122 return mouse_face_overwritten_p
;
6126 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6127 which intersects rectangle R. R is in window-relative coordinates. */
6130 expose_area (w
, row
, r
, area
)
6132 struct glyph_row
*row
;
6134 enum glyph_row_area area
;
6136 struct glyph
*first
= row
->glyphs
[area
];
6137 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
6139 int first_x
, start_x
, x
;
6141 if (area
== TEXT_AREA
&& row
->fill_line_p
)
6142 /* If row extends face to end of line write the whole line. */
6143 x_draw_glyphs (w
, 0, row
, area
,
6145 DRAW_NORMAL_TEXT
, 0);
6148 /* Set START_X to the window-relative start position for drawing glyphs of
6149 AREA. The first glyph of the text area can be partially visible.
6150 The first glyphs of other areas cannot. */
6151 if (area
== LEFT_MARGIN_AREA
)
6153 else if (area
== TEXT_AREA
)
6154 start_x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
6156 start_x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
6157 + window_box_width (w
, TEXT_AREA
));
6160 /* Find the first glyph that must be redrawn. */
6162 && x
+ first
->pixel_width
< r
->left
)
6164 x
+= first
->pixel_width
;
6168 /* Find the last one. */
6174 x
+= last
->pixel_width
;
6180 x_draw_glyphs (w
, first_x
- start_x
, row
, area
,
6181 first
- row
->glyphs
[area
],
6182 last
- row
->glyphs
[area
],
6183 DRAW_NORMAL_TEXT
, 0);
6188 /* Redraw the parts of the glyph row ROW on window W intersecting
6189 rectangle R. R is in window-relative coordinates. Value is
6190 non-zero if mouse face was overwritten. */
6193 expose_line (w
, row
, r
)
6195 struct glyph_row
*row
;
6198 xassert (row
->enabled_p
);
6200 if (row
->mode_line_p
|| w
->pseudo_window_p
)
6201 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
6202 DRAW_NORMAL_TEXT
, 0);
6205 if (row
->used
[LEFT_MARGIN_AREA
])
6206 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
6207 if (row
->used
[TEXT_AREA
])
6208 expose_area (w
, row
, r
, TEXT_AREA
);
6209 if (row
->used
[RIGHT_MARGIN_AREA
])
6210 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
6211 x_draw_row_fringe_bitmaps (w
, row
);
6214 return row
->mouse_face_p
;
6218 /* Return non-zero if W's cursor intersects rectangle R. */
6221 x_phys_cursor_in_rect_p (w
, r
)
6226 struct glyph
*cursor_glyph
;
6228 cursor_glyph
= get_phys_cursor_glyph (w
);
6231 cr
.left
= w
->phys_cursor
.x
;
6232 cr
.top
= w
->phys_cursor
.y
;
6233 cr
.right
= cr
.left
+ cursor_glyph
->pixel_width
;
6234 cr
.bottom
= cr
.top
+ w
->phys_cursor_height
;
6235 return x_intersect_rectangles (&cr
, r
, &result
);
6242 /* Redraw the part of window W intersection rectagle FR. Pixel
6243 coordinates in FR are frame relative. Call this function with
6244 input blocked. Value is non-zero if the exposure overwrites
6248 expose_window (w
, fr
)
6252 struct frame
*f
= XFRAME (w
->frame
);
6254 int mouse_face_overwritten_p
= 0;
6256 /* If window is not yet fully initialized, do nothing. This can
6257 happen when toolkit scroll bars are used and a window is split.
6258 Reconfiguring the scroll bar will generate an expose for a newly
6260 if (w
->current_matrix
== NULL
)
6263 /* When we're currently updating the window, display and current
6264 matrix usually don't agree. Arrange for a thorough display
6266 if (w
== updated_window
)
6268 SET_FRAME_GARBAGED (f
);
6272 /* Frame-relative pixel rectangle of W. */
6273 wr
.left
= XFASTINT (w
->left
) * CANON_X_UNIT (f
);
6274 wr
.top
= XFASTINT (w
->top
) * CANON_Y_UNIT (f
);
6275 wr
.right
= wr
.left
+ XFASTINT (w
->width
) * CANON_X_UNIT (f
);
6276 wr
.bottom
= wr
.top
+ XFASTINT (w
->height
) * CANON_Y_UNIT (f
);
6278 if (x_intersect_rectangles (fr
, &wr
, &r
))
6280 int yb
= window_text_bottom_y (w
);
6281 struct glyph_row
*row
;
6282 int cursor_cleared_p
;
6284 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
6285 r
.left
, r
.top
, r
.right
, r
.bottom
));
6287 /* Convert to window coordinates. */
6288 r
.left
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.left
);
6289 r
.right
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.right
);
6290 r
.top
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.top
);
6291 r
.bottom
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.bottom
);
6293 /* Turn off the cursor. */
6294 if (!w
->pseudo_window_p
6295 && x_phys_cursor_in_rect_p (w
, &r
))
6298 cursor_cleared_p
= 1;
6301 cursor_cleared_p
= 0;
6303 /* Find the first row intersecting the rectangle R. */
6304 for (row
= w
->current_matrix
->rows
;
6309 int y1
= MATRIX_ROW_BOTTOM_Y (row
);
6311 if ((y0
>= r
.top
&& y0
< r
.bottom
)
6312 || (y1
> r
.top
&& y1
< r
.bottom
)
6313 || (r
.top
>= y0
&& r
.top
< y1
)
6314 || (r
.bottom
> y0
&& r
.bottom
< y1
))
6316 if (expose_line (w
, row
, &r
))
6317 mouse_face_overwritten_p
= 1;
6324 /* Display the mode line if there is one. */
6325 if (WINDOW_WANTS_MODELINE_P (w
)
6326 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
6328 && row
->y
< r
.bottom
)
6330 if (expose_line (w
, row
, &r
))
6331 mouse_face_overwritten_p
= 1;
6334 if (!w
->pseudo_window_p
)
6336 /* Draw border between windows. */
6337 x_draw_vertical_border (w
);
6339 /* Turn the cursor on again. */
6340 if (cursor_cleared_p
)
6341 x_update_window_cursor (w
, 1);
6345 /* Display scroll bar for this window. */
6346 if (!NILP (w
->vertical_scroll_bar
))
6349 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w
->vertical_scroll_bar
));
6354 return mouse_face_overwritten_p
;
6358 x_intersect_rectangles (r1
, r2
, result
)
6359 Rect
*r1
, *r2
, *result
;
6362 Rect
*upper
, *lower
;
6363 int intersection_p
= 0;
6365 /* Rerrange so that R1 is the left-most rectangle. */
6366 if (r1
->left
< r2
->left
)
6367 left
= r1
, right
= r2
;
6369 left
= r2
, right
= r1
;
6371 /* X0 of the intersection is right.x0, if this is inside R1,
6372 otherwise there is no intersection. */
6373 if (right
->left
<= left
->right
)
6375 result
->left
= right
->left
;
6377 /* The right end of the intersection is the minimum of the
6378 the right ends of left and right. */
6379 result
->right
= min (left
->right
, right
->right
);
6381 /* Same game for Y. */
6382 if (r1
->top
< r2
->top
)
6383 upper
= r1
, lower
= r2
;
6385 upper
= r2
, lower
= r1
;
6387 /* The upper end of the intersection is lower.y0, if this is inside
6388 of upper. Otherwise, there is no intersection. */
6389 if (lower
->top
<= upper
->bottom
)
6391 result
->top
= lower
->top
;
6393 /* The lower end of the intersection is the minimum of the lower
6394 ends of upper and lower. */
6395 result
->bottom
= min (lower
->bottom
, upper
->bottom
);
6400 return intersection_p
;
6411 x_update_cursor (f
, 1);
6415 frame_unhighlight (f
)
6418 x_update_cursor (f
, 1);
6421 /* The focus has changed. Update the frames as necessary to reflect
6422 the new situation. Note that we can't change the selected frame
6423 here, because the Lisp code we are interrupting might become confused.
6424 Each event gets marked with the frame in which it occurred, so the
6425 Lisp code can tell when the switch took place by examining the events. */
6428 x_new_focus_frame (dpyinfo
, frame
)
6429 struct x_display_info
*dpyinfo
;
6430 struct frame
*frame
;
6432 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
6434 if (frame
!= dpyinfo
->x_focus_frame
)
6436 /* Set this before calling other routines, so that they see
6437 the correct value of x_focus_frame. */
6438 dpyinfo
->x_focus_frame
= frame
;
6440 if (old_focus
&& old_focus
->auto_lower
)
6441 x_lower_frame (old_focus
);
6444 selected_frame
= frame
;
6445 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
6447 Fselect_window (selected_frame
->selected_window
);
6448 choose_minibuf_frame ();
6451 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
6452 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
6454 pending_autoraise_frame
= 0;
6457 x_frame_rehighlight (dpyinfo
);
6460 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6463 x_mouse_leave (dpyinfo
)
6464 struct x_display_info
*dpyinfo
;
6466 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
6469 /* The focus has changed, or we have redirected a frame's focus to
6470 another frame (this happens when a frame uses a surrogate
6471 mini-buffer frame). Shift the highlight as appropriate.
6473 The FRAME argument doesn't necessarily have anything to do with which
6474 frame is being highlighted or un-highlighted; we only use it to find
6475 the appropriate X display info. */
6478 XTframe_rehighlight (frame
)
6479 struct frame
*frame
;
6481 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
6485 x_frame_rehighlight (dpyinfo
)
6486 struct x_display_info
*dpyinfo
;
6488 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
6490 if (dpyinfo
->x_focus_frame
)
6492 dpyinfo
->x_highlight_frame
6493 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
6494 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
6495 : dpyinfo
->x_focus_frame
);
6496 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
6498 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
6499 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
6503 dpyinfo
->x_highlight_frame
= 0;
6505 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
6508 frame_unhighlight (old_highlight
);
6509 if (dpyinfo
->x_highlight_frame
)
6510 frame_highlight (dpyinfo
->x_highlight_frame
);
6516 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6518 #if 0 /* MAC_TODO */
6519 /* Initialize mode_switch_bit and modifier_meaning. */
6521 x_find_modifier_meanings (dpyinfo
)
6522 struct x_display_info
*dpyinfo
;
6524 int min_code
, max_code
;
6527 XModifierKeymap
*mods
;
6529 dpyinfo
->meta_mod_mask
= 0;
6530 dpyinfo
->shift_lock_mask
= 0;
6531 dpyinfo
->alt_mod_mask
= 0;
6532 dpyinfo
->super_mod_mask
= 0;
6533 dpyinfo
->hyper_mod_mask
= 0;
6536 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
6538 min_code
= dpyinfo
->display
->min_keycode
;
6539 max_code
= dpyinfo
->display
->max_keycode
;
6542 syms
= XGetKeyboardMapping (dpyinfo
->display
,
6543 min_code
, max_code
- min_code
+ 1,
6545 mods
= XGetModifierMapping (dpyinfo
->display
);
6547 /* Scan the modifier table to see which modifier bits the Meta and
6548 Alt keysyms are on. */
6550 int row
, col
; /* The row and column in the modifier table. */
6552 for (row
= 3; row
< 8; row
++)
6553 for (col
= 0; col
< mods
->max_keypermod
; col
++)
6556 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
6558 /* Zeroes are used for filler. Skip them. */
6562 /* Are any of this keycode's keysyms a meta key? */
6566 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
6568 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
6574 dpyinfo
->meta_mod_mask
|= (1 << row
);
6579 dpyinfo
->alt_mod_mask
|= (1 << row
);
6584 dpyinfo
->hyper_mod_mask
|= (1 << row
);
6589 dpyinfo
->super_mod_mask
|= (1 << row
);
6593 /* Ignore this if it's not on the lock modifier. */
6594 if ((1 << row
) == LockMask
)
6595 dpyinfo
->shift_lock_mask
= LockMask
;
6603 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6604 if (! dpyinfo
->meta_mod_mask
)
6606 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
6607 dpyinfo
->alt_mod_mask
= 0;
6610 /* If some keys are both alt and meta,
6611 make them just meta, not alt. */
6612 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
6614 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
6617 XFree ((char *) syms
);
6618 XFreeModifiermap (mods
);
6621 #endif /* MAC_TODO */
6623 /* Convert between the modifier bits X uses and the modifier bits
6627 x_mac_to_emacs_modifiers (dpyinfo
, state
)
6628 struct x_display_info
*dpyinfo
;
6629 unsigned short state
;
6631 return (((state
& shiftKey
) ? shift_modifier
: 0)
6632 | ((state
& controlKey
) ? ctrl_modifier
: 0)
6633 | ((state
& cmdKey
) ? meta_modifier
: 0)
6634 | ((state
& optionKey
) ? alt_modifier
: 0));
6637 #if 0 /* MAC_TODO */
6638 static unsigned short
6639 x_emacs_to_x_modifiers (dpyinfo
, state
)
6640 struct x_display_info
*dpyinfo
;
6643 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
6644 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
6645 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
6646 | ((state
& shift_modifier
) ? ShiftMask
: 0)
6647 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
6648 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
6650 #endif /* MAC_TODO */
6652 /* Convert a keysym to its name. */
6655 x_get_keysym_name (keysym
)
6662 value
= XKeysymToString (keysym
);
6673 /* Mouse clicks and mouse movement. Rah. */
6675 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6676 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6677 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6678 not force the value into range. */
6681 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
6683 register int pix_x
, pix_y
;
6684 register int *x
, *y
;
6688 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6689 if (NILP (Vwindow_system
))
6696 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6697 even for negative values. */
6699 pix_x
-= FONT_WIDTH (FRAME_FONT (f
)) - 1;
6701 pix_y
-= (f
)->output_data
.mac
->line_height
- 1;
6703 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
6704 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
6708 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
6709 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
6710 bounds
->right
= bounds
->left
+ FONT_WIDTH (FRAME_FONT (f
)) - 1;
6711 bounds
->bottom
= bounds
->top
+ f
->output_data
.mac
->line_height
- 1;
6718 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
6719 pix_x
= FRAME_WINDOW_WIDTH (f
);
6723 else if (pix_y
> f
->height
)
6732 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6733 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6734 can't tell the positions because W's display is not up to date,
6738 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
6741 int *frame_x
, *frame_y
;
6745 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
6746 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
6748 if (display_completed
)
6750 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6751 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
6752 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
6758 *frame_x
+= glyph
->pixel_width
;
6766 *frame_y
= *frame_x
= 0;
6770 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
6771 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
6776 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6778 If the event is a button press, then note that we have grabbed
6782 construct_mouse_click (result
, event
, f
)
6783 struct input_event
*result
;
6789 result
->kind
= MOUSE_CLICK_EVENT
;
6790 result
->code
= 0; /* only one mouse button */
6791 result
->timestamp
= event
->when
;
6792 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
6794 mouseLoc
= event
->where
;
6796 #if TARGET_API_MAC_CARBON
6797 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
6799 SetPort (FRAME_MAC_WINDOW (f
));
6802 GlobalToLocal (&mouseLoc
);
6803 XSETINT (result
->x
, mouseLoc
.h
);
6804 XSETINT (result
->y
, mouseLoc
.v
);
6806 XSETFRAME (result
->frame_or_window
, f
);
6813 /* Function to report a mouse movement to the mainstream Emacs code.
6814 The input handler calls this.
6816 We have received a mouse movement event, which is given in *event.
6817 If the mouse is over a different glyph than it was last time, tell
6818 the mainstream emacs code by setting mouse_moved. If not, ask for
6819 another motion event, so we can check again the next time it moves. */
6821 static Point last_mouse_motion_position
;
6822 static Lisp_Object last_mouse_motion_frame
;
6825 note_mouse_movement (frame
, pos
)
6829 #if TARGET_API_MAC_CARBON
6833 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
6834 last_mouse_motion_position
= *pos
;
6835 XSETFRAME (last_mouse_motion_frame
, frame
);
6837 #if TARGET_API_MAC_CARBON
6838 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
6840 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
6843 frame
->mouse_moved
= 1;
6844 last_mouse_scroll_bar
= Qnil
;
6845 note_mouse_highlight (frame
, -1, -1);
6847 /* Has the mouse moved off the glyph it was on at the last sighting? */
6848 else if (pos
->h
< last_mouse_glyph
.left
6849 || pos
->h
>= last_mouse_glyph
.right
6850 || pos
->v
< last_mouse_glyph
.top
6851 || pos
->v
>= last_mouse_glyph
.bottom
)
6853 frame
->mouse_moved
= 1;
6854 last_mouse_scroll_bar
= Qnil
;
6855 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
6859 /* This is used for debugging, to turn off note_mouse_highlight. */
6861 int disable_mouse_highlight
;
6865 /************************************************************************
6867 ************************************************************************/
6869 /* Find the glyph under window-relative coordinates X/Y in window W.
6870 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6871 strings. Return in *HPOS and *VPOS the row and column number of
6872 the glyph found. Return in *AREA the glyph area containing X.
6873 Value is a pointer to the glyph found or null if X/Y is not on
6874 text, or we can't tell because W's current matrix is not up to
6877 static struct glyph
*
6878 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
, buffer_only_p
)
6881 int *hpos
, *vpos
, *area
;
6884 struct glyph
*glyph
, *end
;
6885 struct glyph_row
*row
= NULL
;
6886 int x0
, i
, left_area_width
;
6888 /* Find row containing Y. Give up if some row is not enabled. */
6889 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
6891 row
= MATRIX_ROW (w
->current_matrix
, i
);
6892 if (!row
->enabled_p
)
6894 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
6901 /* Give up if Y is not in the window. */
6902 if (i
== w
->current_matrix
->nrows
)
6905 /* Get the glyph area containing X. */
6906 if (w
->pseudo_window_p
)
6913 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
6914 if (x
< left_area_width
)
6916 *area
= LEFT_MARGIN_AREA
;
6919 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
6922 x0
= row
->x
+ left_area_width
;
6926 *area
= RIGHT_MARGIN_AREA
;
6927 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
6931 /* Find glyph containing X. */
6932 glyph
= row
->glyphs
[*area
];
6933 end
= glyph
+ row
->used
[*area
];
6936 if (x
< x0
+ glyph
->pixel_width
)
6938 if (w
->pseudo_window_p
)
6940 else if (!buffer_only_p
|| BUFFERP (glyph
->object
))
6944 x0
+= glyph
->pixel_width
;
6951 *hpos
= glyph
- row
->glyphs
[*area
];
6956 /* Convert frame-relative x/y to coordinates relative to window W.
6957 Takes pseudo-windows into account. */
6960 frame_to_window_pixel_xy (w
, x
, y
)
6964 if (w
->pseudo_window_p
)
6966 /* A pseudo-window is always full-width, and starts at the
6967 left edge of the frame, plus a frame border. */
6968 struct frame
*f
= XFRAME (w
->frame
);
6969 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
6970 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6974 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
6975 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6980 /* Take proper action when mouse has moved to the mode or header line of
6981 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6982 mode line. X is relative to the start of the text display area of
6983 W, so the width of fringes and scroll bars must be subtracted
6984 to get a position relative to the start of the mode line. */
6987 note_mode_line_highlight (w
, x
, mode_line_p
)
6991 struct frame
*f
= XFRAME (w
->frame
);
6992 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6993 struct Cursor
*cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
6994 struct glyph_row
*row
;
6997 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
6999 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
7003 struct glyph
*glyph
, *end
;
7004 Lisp_Object help
, map
;
7007 /* Find the glyph under X. */
7008 glyph
= row
->glyphs
[TEXT_AREA
];
7009 end
= glyph
+ row
->used
[TEXT_AREA
];
7010 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
7011 + FRAME_X_LEFT_FRINGE_WIDTH (f
));
7014 && x
>= x0
+ glyph
->pixel_width
)
7016 x0
+= glyph
->pixel_width
;
7021 && STRINGP (glyph
->object
)
7022 && STRING_INTERVALS (glyph
->object
)
7023 && glyph
->charpos
>= 0
7024 && glyph
->charpos
< SCHARS (glyph
->object
))
7026 /* If we're on a string with `help-echo' text property,
7027 arrange for the help to be displayed. This is done by
7028 setting the global variable help_echo to the help string. */
7029 help
= Fget_text_property (make_number (glyph
->charpos
),
7030 Qhelp_echo
, glyph
->object
);
7034 XSETWINDOW (help_echo_window
, w
);
7035 help_echo_object
= glyph
->object
;
7036 help_echo_pos
= glyph
->charpos
;
7039 /* Change the mouse pointer according to what is under X/Y. */
7040 map
= Fget_text_property (make_number (glyph
->charpos
),
7041 Qlocal_map
, glyph
->object
);
7043 cursor
= f
->output_data
.mac
->nontext_cursor
;
7046 map
= Fget_text_property (make_number (glyph
->charpos
),
7047 Qkeymap
, glyph
->object
);
7049 cursor
= f
->output_data
.mac
->nontext_cursor
;
7054 #if 0 /* MAC_TODO: mouse cursor */
7055 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7060 /* Take proper action when the mouse has moved to position X, Y on
7061 frame F as regards highlighting characters that have mouse-face
7062 properties. Also de-highlighting chars where the mouse was before.
7063 X and Y can be negative or out of range. */
7066 note_mouse_highlight (f
, x
, y
)
7070 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7077 /* When a menu is active, don't highlight because this looks odd. */
7078 if (popup_activated ())
7082 if (NILP (Vmouse_highlight
)
7083 || !f
->glyphs_initialized_p
)
7086 dpyinfo
->mouse_face_mouse_x
= x
;
7087 dpyinfo
->mouse_face_mouse_y
= y
;
7088 dpyinfo
->mouse_face_mouse_frame
= f
;
7090 if (dpyinfo
->mouse_face_defer
)
7095 dpyinfo
->mouse_face_deferred_gc
= 1;
7099 /* Which window is that in? */
7100 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
7102 /* If we were displaying active text in another window, clear that. */
7103 if (! EQ (window
, dpyinfo
->mouse_face_window
))
7104 clear_mouse_face (dpyinfo
);
7106 /* Not on a window -> return. */
7107 if (!WINDOWP (window
))
7110 /* Reset help_echo. It will get recomputed below. */
7113 /* Convert to window-relative pixel coordinates. */
7114 w
= XWINDOW (window
);
7115 frame_to_window_pixel_xy (w
, &x
, &y
);
7117 /* Handle tool-bar window differently since it doesn't display a
7119 if (EQ (window
, f
->tool_bar_window
))
7121 note_tool_bar_highlight (f
, x
, y
);
7125 /* Mouse is on the mode or header line? */
7126 if (portion
== 1 || portion
== 3)
7128 note_mode_line_highlight (w
, x
, portion
== 1);
7131 #if 0 /* TODO: mouse cursor */
7133 cursor
= f
->output_data
.x
->horizontal_drag_cursor
;
7135 cursor
= f
->output_data
.x
->text_cursor
;
7137 /* Are we in a window whose display is up to date?
7138 And verify the buffer's text has not changed. */
7139 b
= XBUFFER (w
->buffer
);
7140 if (/* Within text portion of the window. */
7142 && EQ (w
->window_end_valid
, w
->buffer
)
7143 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
7144 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
7146 int hpos
, vpos
, pos
, i
, area
;
7147 struct glyph
*glyph
;
7149 Lisp_Object mouse_face
= Qnil
, overlay
= Qnil
, position
;
7150 Lisp_Object
*overlay_vec
= NULL
;
7152 struct buffer
*obuf
;
7153 int obegv
, ozv
, same_region
;
7155 /* Find the glyph under X/Y. */
7156 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
, 0);
7158 /* Clear mouse face if X/Y not over text. */
7160 || area
!= TEXT_AREA
7161 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
7163 clear_mouse_face (dpyinfo
);
7164 /* TODO: mouse cursor */
7168 pos
= glyph
->charpos
;
7169 object
= glyph
->object
;
7170 if (!STRINGP (object
) && !BUFFERP (object
))
7173 /* If we get an out-of-range value, return now; avoid an error. */
7174 if (BUFFERP (object
) && pos
> BUF_Z (b
))
7177 /* Make the window's buffer temporarily current for
7178 overlays_at and compute_char_face. */
7179 obuf
= current_buffer
;
7186 /* Is this char mouse-active or does it have help-echo? */
7187 position
= make_number (pos
);
7189 if (BUFFERP (object
))
7191 /* Put all the overlays we want in a vector in overlay_vec.
7192 Store the length in len. If there are more than 10, make
7193 enough space for all, and try again. */
7195 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
7196 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
, 0);
7197 if (noverlays
> len
)
7200 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
7201 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
,0);
7204 /* Sort overlays into increasing priority order. */
7205 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
7210 same_region
= (EQ (window
, dpyinfo
->mouse_face_window
)
7211 && vpos
>= dpyinfo
->mouse_face_beg_row
7212 && vpos
<= dpyinfo
->mouse_face_end_row
7213 && (vpos
> dpyinfo
->mouse_face_beg_row
7214 || hpos
>= dpyinfo
->mouse_face_beg_col
)
7215 && (vpos
< dpyinfo
->mouse_face_end_row
7216 || hpos
< dpyinfo
->mouse_face_end_col
7217 || dpyinfo
->mouse_face_past_end
));
7219 /* TODO: if (same_region)
7222 /* Check mouse-face highlighting. */
7224 /* If there exists an overlay with mouse-face overlapping
7225 the one we are currently highlighting, we have to
7226 check if we enter the overlapping overlay, and then
7228 || (OVERLAYP (dpyinfo
->mouse_face_overlay
)
7229 && mouse_face_overlay_overlaps (dpyinfo
->mouse_face_overlay
)))
7231 /* Find the highest priority overlay that has a mouse-face
7234 for (i
= noverlays
- 1; i
>= 0 && NILP (overlay
); --i
)
7236 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
7237 if (!NILP (mouse_face
))
7238 overlay
= overlay_vec
[i
];
7241 /* If we're actually highlighting the same overlay as
7242 before, there's no need to do that again. */
7244 && EQ (overlay
, dpyinfo
->mouse_face_overlay
))
7245 goto check_help_echo
;
7247 dpyinfo
->mouse_face_overlay
= overlay
;
7249 /* Clear the display of the old active region, if any. */
7250 clear_mouse_face (dpyinfo
);
7251 /* TODO: mouse cursor changes. */
7253 /* If no overlay applies, get a text property. */
7255 mouse_face
= Fget_text_property (position
, Qmouse_face
, object
);
7257 /* Handle the overlay case. */
7258 if (!NILP (overlay
))
7260 /* Find the range of text around this char that
7261 should be active. */
7262 Lisp_Object before
, after
;
7265 before
= Foverlay_start (overlay
);
7266 after
= Foverlay_end (overlay
);
7267 /* Record this as the current active region. */
7268 fast_find_position (w
, XFASTINT (before
),
7269 &dpyinfo
->mouse_face_beg_col
,
7270 &dpyinfo
->mouse_face_beg_row
,
7271 &dpyinfo
->mouse_face_beg_x
,
7272 &dpyinfo
->mouse_face_beg_y
, Qnil
);
7274 dpyinfo
->mouse_face_past_end
7275 = !fast_find_position (w
, XFASTINT (after
),
7276 &dpyinfo
->mouse_face_end_col
,
7277 &dpyinfo
->mouse_face_end_row
,
7278 &dpyinfo
->mouse_face_end_x
,
7279 &dpyinfo
->mouse_face_end_y
, Qnil
);
7280 dpyinfo
->mouse_face_window
= window
;
7282 dpyinfo
->mouse_face_face_id
7283 = face_at_buffer_position (w
, pos
, 0, 0,
7284 &ignore
, pos
+ 1, 1);
7286 /* Display it as active. */
7287 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7288 /* TODO: mouse cursor changes. */
7290 /* Handle the text property case. */
7291 else if (! NILP (mouse_face
) && BUFFERP (object
))
7293 /* Find the range of text around this char that
7294 should be active. */
7295 Lisp_Object before
, after
, beginning
, end
;
7298 beginning
= Fmarker_position (w
->start
);
7299 end
= make_number (BUF_Z (XBUFFER (object
))
7300 - XFASTINT (w
->window_end_pos
));
7302 = Fprevious_single_property_change (make_number (pos
+ 1),
7306 = Fnext_single_property_change (position
, Qmouse_face
,
7309 /* Record this as the current active region. */
7310 fast_find_position (w
, XFASTINT (before
),
7311 &dpyinfo
->mouse_face_beg_col
,
7312 &dpyinfo
->mouse_face_beg_row
,
7313 &dpyinfo
->mouse_face_beg_x
,
7314 &dpyinfo
->mouse_face_beg_y
, Qnil
);
7315 dpyinfo
->mouse_face_past_end
7316 = !fast_find_position (w
, XFASTINT (after
),
7317 &dpyinfo
->mouse_face_end_col
,
7318 &dpyinfo
->mouse_face_end_row
,
7319 &dpyinfo
->mouse_face_end_x
,
7320 &dpyinfo
->mouse_face_end_y
, Qnil
);
7321 dpyinfo
->mouse_face_window
= window
;
7323 if (BUFFERP (object
))
7324 dpyinfo
->mouse_face_face_id
7325 = face_at_buffer_position (w
, pos
, 0, 0,
7326 &ignore
, pos
+ 1, 1);
7328 /* Display it as active. */
7329 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7330 /* TODO: mouse cursor changes. */
7332 else if (!NILP (mouse_face
) && STRINGP (object
))
7337 b
= Fprevious_single_property_change (make_number (pos
+ 1),
7340 e
= Fnext_single_property_change (position
, Qmouse_face
,
7343 b
= make_number (0);
7345 e
= make_number (SCHARS (object
) - 1);
7346 fast_find_string_pos (w
, XINT (b
), object
,
7347 &dpyinfo
->mouse_face_beg_col
,
7348 &dpyinfo
->mouse_face_beg_row
,
7349 &dpyinfo
->mouse_face_beg_x
,
7350 &dpyinfo
->mouse_face_beg_y
, 0);
7351 fast_find_string_pos (w
, XINT (e
), object
,
7352 &dpyinfo
->mouse_face_end_col
,
7353 &dpyinfo
->mouse_face_end_row
,
7354 &dpyinfo
->mouse_face_end_x
,
7355 &dpyinfo
->mouse_face_end_y
, 1);
7356 dpyinfo
->mouse_face_past_end
= 0;
7357 dpyinfo
->mouse_face_window
= window
;
7358 dpyinfo
->mouse_face_face_id
7359 = face_at_string_position (w
, object
, pos
, 0, 0, 0, &ignore
,
7361 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7362 /* TODO: mouse cursor changes. */
7364 else if (STRINGP (object
) && NILP (mouse_face
))
7366 /* A string which doesn't have mouse-face, but
7367 the text ``under'' it might have. */
7368 struct glyph_row
*r
= MATRIX_ROW (w
->current_matrix
, vpos
);
7369 int start
= MATRIX_ROW_START_CHARPOS (r
);
7371 pos
= string_buffer_position (w
, object
, start
);
7373 mouse_face
= get_char_property_and_overlay (make_number (pos
),
7377 if (!NILP (mouse_face
) && !NILP (overlay
))
7379 Lisp_Object before
= Foverlay_start (overlay
);
7380 Lisp_Object after
= Foverlay_end (overlay
);
7383 /* Note that we might not be able to find position
7384 BEFORE in the glyph matrix if the overlay is
7385 entirely covered by a `display' property. In
7386 this case, we overshoot. So let's stop in
7387 the glyph matrix before glyphs for OBJECT. */
7388 fast_find_position (w
, XFASTINT (before
),
7389 &dpyinfo
->mouse_face_beg_col
,
7390 &dpyinfo
->mouse_face_beg_row
,
7391 &dpyinfo
->mouse_face_beg_x
,
7392 &dpyinfo
->mouse_face_beg_y
,
7395 dpyinfo
->mouse_face_past_end
7396 = !fast_find_position (w
, XFASTINT (after
),
7397 &dpyinfo
->mouse_face_end_col
,
7398 &dpyinfo
->mouse_face_end_row
,
7399 &dpyinfo
->mouse_face_end_x
,
7400 &dpyinfo
->mouse_face_end_y
,
7402 dpyinfo
->mouse_face_window
= window
;
7403 dpyinfo
->mouse_face_face_id
7404 = face_at_buffer_position (w
, pos
, 0, 0,
7405 &ignore
, pos
+ 1, 1);
7407 /* Display it as active. */
7408 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7409 /* TODO: mouse cursor changes. */
7416 /* Look for a `help-echo' property. */
7418 Lisp_Object help
, overlay
;
7420 /* Check overlays first. */
7421 help
= overlay
= Qnil
;
7422 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
7424 overlay
= overlay_vec
[i
];
7425 help
= Foverlay_get (overlay
, Qhelp_echo
);
7431 help_echo_window
= window
;
7432 help_echo_object
= overlay
;
7433 help_echo_pos
= pos
;
7437 Lisp_Object object
= glyph
->object
;
7438 int charpos
= glyph
->charpos
;
7440 /* Try text properties. */
7441 if (STRINGP (object
)
7443 && charpos
< SCHARS (object
))
7445 help
= Fget_text_property (make_number (charpos
),
7446 Qhelp_echo
, object
);
7449 /* If the string itself doesn't specify a help-echo,
7450 see if the buffer text ``under'' it does. */
7452 = MATRIX_ROW (w
->current_matrix
, vpos
);
7453 int start
= MATRIX_ROW_START_CHARPOS (r
);
7454 int pos
= string_buffer_position (w
, object
, start
);
7457 help
= Fget_char_property (make_number (pos
),
7458 Qhelp_echo
, w
->buffer
);
7467 else if (BUFFERP (object
)
7470 help
= Fget_text_property (make_number (charpos
), Qhelp_echo
,
7476 help_echo_window
= window
;
7477 help_echo_object
= object
;
7478 help_echo_pos
= charpos
;
7485 current_buffer
= obuf
;
7489 /* TODO: mouse cursor changes. */
7494 redo_mouse_highlight ()
7496 if (!NILP (last_mouse_motion_frame
)
7497 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
7498 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
7499 last_mouse_motion_position
.h
,
7500 last_mouse_motion_position
.v
);
7505 /***********************************************************************
7507 ***********************************************************************/
7509 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
7510 struct glyph
**, int *, int *, int *));
7512 /* Tool-bar item index of the item on which a mouse button was pressed
7515 static int last_tool_bar_item
;
7518 /* Get information about the tool-bar item at position X/Y on frame F.
7519 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7520 the current matrix of the tool-bar window of F, or NULL if not
7521 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7522 item in F->current_tool_bar_items. Value is
7524 -1 if X/Y is not on a tool-bar item
7525 0 if X/Y is on the same item that was highlighted before.
7529 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
7532 struct glyph
**glyph
;
7533 int *hpos
, *vpos
, *prop_idx
;
7535 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7536 struct window
*w
= XWINDOW (f
->tool_bar_window
);
7539 /* Find the glyph under X/Y. */
7540 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
, 0);
7544 /* Get the start of this tool-bar item's properties in
7545 f->current_tool_bar_items. */
7546 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
7549 /* Is mouse on the highlighted item? */
7550 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
7551 && *vpos
>= dpyinfo
->mouse_face_beg_row
7552 && *vpos
<= dpyinfo
->mouse_face_end_row
7553 && (*vpos
> dpyinfo
->mouse_face_beg_row
7554 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
7555 && (*vpos
< dpyinfo
->mouse_face_end_row
7556 || *hpos
< dpyinfo
->mouse_face_end_col
7557 || dpyinfo
->mouse_face_past_end
))
7564 /* Handle mouse button event on the tool-bar of frame F, at
7565 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7569 x_handle_tool_bar_click (f
, button_event
)
7571 EventRecord
*button_event
;
7573 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7574 struct window
*w
= XWINDOW (f
->tool_bar_window
);
7575 int hpos
, vpos
, prop_idx
;
7576 struct glyph
*glyph
;
7577 Lisp_Object enabled_p
;
7578 int x
= button_event
->where
.h
;
7579 int y
= button_event
->where
.v
;
7581 /* If not on the highlighted tool-bar item, return. */
7582 frame_to_window_pixel_xy (w
, &x
, &y
);
7583 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
7586 /* If item is disabled, do nothing. */
7587 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7588 if (NILP (enabled_p
))
7591 if (button_event
->what
== mouseDown
)
7593 /* Show item in pressed state. */
7594 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
7595 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
7596 last_tool_bar_item
= prop_idx
;
7600 Lisp_Object key
, frame
;
7601 struct input_event event
;
7603 /* Show item in released state. */
7604 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
7605 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
7607 key
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_KEY
);
7609 XSETFRAME (frame
, f
);
7610 event
.kind
= TOOL_BAR_EVENT
;
7611 event
.frame_or_window
= frame
;
7613 kbd_buffer_store_event (&event
);
7615 event
.kind
= TOOL_BAR_EVENT
;
7616 event
.frame_or_window
= frame
;
7618 event
.modifiers
= x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
7619 button_event
->modifiers
);
7620 kbd_buffer_store_event (&event
);
7621 last_tool_bar_item
= -1;
7626 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7627 tool-bar window-relative coordinates X/Y. Called from
7628 note_mouse_highlight. */
7631 note_tool_bar_highlight (f
, x
, y
)
7635 Lisp_Object window
= f
->tool_bar_window
;
7636 struct window
*w
= XWINDOW (window
);
7637 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7639 struct glyph
*glyph
;
7640 struct glyph_row
*row
;
7642 Lisp_Object enabled_p
;
7644 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
7645 int mouse_down_p
, rc
;
7647 /* Function note_mouse_highlight is called with negative x(y
7648 values when mouse moves outside of the frame. */
7649 if (x
<= 0 || y
<= 0)
7651 clear_mouse_face (dpyinfo
);
7655 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
7658 /* Not on tool-bar item. */
7659 clear_mouse_face (dpyinfo
);
7663 /* On same tool-bar item as before. */
7666 clear_mouse_face (dpyinfo
);
7668 /* Mouse is down, but on different tool-bar item? */
7669 mouse_down_p
= (dpyinfo
->grabbed
7670 && f
== last_mouse_frame
7671 && FRAME_LIVE_P (f
));
7673 && last_tool_bar_item
!= prop_idx
)
7676 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
7677 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
7679 /* If tool-bar item is not enabled, don't highlight it. */
7680 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7681 if (!NILP (enabled_p
))
7683 /* Compute the x-position of the glyph. In front and past the
7684 image is a space. We include this is the highlighted area. */
7685 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
7686 for (i
= x
= 0; i
< hpos
; ++i
)
7687 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
7689 /* Record this as the current active region. */
7690 dpyinfo
->mouse_face_beg_col
= hpos
;
7691 dpyinfo
->mouse_face_beg_row
= vpos
;
7692 dpyinfo
->mouse_face_beg_x
= x
;
7693 dpyinfo
->mouse_face_beg_y
= row
->y
;
7694 dpyinfo
->mouse_face_past_end
= 0;
7696 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
7697 dpyinfo
->mouse_face_end_row
= vpos
;
7698 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
7699 dpyinfo
->mouse_face_end_y
= row
->y
;
7700 dpyinfo
->mouse_face_window
= window
;
7701 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
7703 /* Display it as active. */
7704 show_mouse_face (dpyinfo
, draw
);
7705 dpyinfo
->mouse_face_image_state
= draw
;
7710 /* Set help_echo to a help string.to display for this tool-bar item.
7711 XTread_socket does the rest. */
7712 help_echo_object
= help_echo_window
= Qnil
;
7714 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_HELP
);
7715 if (NILP (help_echo
))
7716 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_CAPTION
);
7721 /* Find the glyph matrix position of buffer position CHARPOS in window
7722 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7723 current glyphs must be up to date. If CHARPOS is above window
7724 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7725 of last line in W. In the row containing CHARPOS, stop before glyphs
7726 having STOP as object. */
7728 #if 0 /* This is a version of fast_find_position that's more correct
7729 in the presence of hscrolling, for example. I didn't install
7730 it right away because the problem fixed is minor, it failed
7731 in 20.x as well, and I think it's too risky to install
7732 so near the release of 21.1. 2001-09-25 gerd. */
7735 fast_find_position (w
, charpos
, hpos
, vpos
, x
, y
, stop
)
7738 int *hpos
, *vpos
, *x
, *y
;
7741 struct glyph_row
*row
, *first
;
7742 struct glyph
*glyph
, *end
;
7743 int i
, past_end
= 0;
7745 first
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7746 row
= row_containing_pos (w
, charpos
, first
, NULL
, 0);
7749 if (charpos
< MATRIX_ROW_START_CHARPOS (first
))
7751 *x
= *y
= *hpos
= *vpos
= 0;
7756 row
= MATRIX_ROW (w
->current_matrix
, XFASTINT (w
->window_end_vpos
));
7763 *vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
7765 glyph
= row
->glyphs
[TEXT_AREA
];
7766 end
= glyph
+ row
->used
[TEXT_AREA
];
7768 /* Skip over glyphs not having an object at the start of the row.
7769 These are special glyphs like truncation marks on terminal
7771 if (row
->displays_text_p
)
7773 && INTEGERP (glyph
->object
)
7774 && !EQ (stop
, glyph
->object
)
7775 && glyph
->charpos
< 0)
7777 *x
+= glyph
->pixel_width
;
7782 && !INTEGERP (glyph
->object
)
7783 && !EQ (stop
, glyph
->object
)
7784 && (!BUFFERP (glyph
->object
)
7785 || glyph
->charpos
< charpos
))
7787 *x
+= glyph
->pixel_width
;
7791 *hpos
= glyph
- row
->glyphs
[TEXT_AREA
];
7798 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
, stop
)
7801 int *hpos
, *vpos
, *x
, *y
;
7806 int maybe_next_line_p
= 0;
7807 int line_start_position
;
7808 int yb
= window_text_bottom_y (w
);
7809 struct glyph_row
*row
, *best_row
;
7810 int row_vpos
, best_row_vpos
;
7813 row
= best_row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7814 row_vpos
= best_row_vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
7818 if (row
->used
[TEXT_AREA
])
7819 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
7821 line_start_position
= 0;
7823 if (line_start_position
> pos
)
7825 /* If the position sought is the end of the buffer,
7826 don't include the blank lines at the bottom of the window. */
7827 else if (line_start_position
== pos
7828 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
7830 maybe_next_line_p
= 1;
7833 else if (line_start_position
> 0)
7836 best_row_vpos
= row_vpos
;
7839 if (row
->y
+ row
->height
>= yb
)
7846 /* Find the right column within BEST_ROW. */
7848 current_x
= best_row
->x
;
7849 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
7851 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
7852 int charpos
= glyph
->charpos
;
7854 if (BUFFERP (glyph
->object
))
7859 *vpos
= best_row_vpos
;
7864 else if (charpos
> pos
)
7867 else if (EQ (glyph
->object
, stop
))
7872 current_x
+= glyph
->pixel_width
;
7875 /* If we're looking for the end of the buffer,
7876 and we didn't find it in the line we scanned,
7877 use the start of the following line. */
7878 if (maybe_next_line_p
)
7883 current_x
= best_row
->x
;
7886 *vpos
= best_row_vpos
;
7887 *hpos
= lastcol
+ 1;
7896 /* Find the position of the glyph for position POS in OBJECT in
7897 window W's current matrix, and return in *X/*Y the pixel
7898 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7900 RIGHT_P non-zero means return the position of the right edge of the
7901 glyph, RIGHT_P zero means return the left edge position.
7903 If no glyph for POS exists in the matrix, return the position of
7904 the glyph with the next smaller position that is in the matrix, if
7905 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7906 exists in the matrix, return the position of the glyph with the
7907 next larger position in OBJECT.
7909 Value is non-zero if a glyph was found. */
7912 fast_find_string_pos (w
, pos
, object
, hpos
, vpos
, x
, y
, right_p
)
7916 int *hpos
, *vpos
, *x
, *y
;
7919 int yb
= window_text_bottom_y (w
);
7920 struct glyph_row
*r
;
7921 struct glyph
*best_glyph
= NULL
;
7922 struct glyph_row
*best_row
= NULL
;
7925 for (r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7926 r
->enabled_p
&& r
->y
< yb
;
7929 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
7930 struct glyph
*e
= g
+ r
->used
[TEXT_AREA
];
7933 for (gx
= r
->x
; g
< e
; gx
+= g
->pixel_width
, ++g
)
7934 if (EQ (g
->object
, object
))
7936 if (g
->charpos
== pos
)
7943 else if (best_glyph
== NULL
7944 || ((abs (g
->charpos
- pos
)
7945 < abs (best_glyph
->charpos
- pos
))
7948 : g
->charpos
> pos
)))
7962 *hpos
= best_glyph
- best_row
->glyphs
[TEXT_AREA
];
7966 *x
+= best_glyph
->pixel_width
;
7971 *vpos
= best_row
- w
->current_matrix
->rows
;
7974 return best_glyph
!= NULL
;
7978 /* Display the active region described by mouse_face_*
7979 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7982 show_mouse_face (dpyinfo
, draw
)
7983 struct mac_display_info
*dpyinfo
;
7984 enum draw_glyphs_face draw
;
7986 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
7987 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7989 if (/* If window is in the process of being destroyed, don't bother
7991 w
->current_matrix
!= NULL
7992 /* Don't update mouse highlight if hidden */
7993 && (draw
!= DRAW_MOUSE_FACE
|| !dpyinfo
->mouse_face_hidden
)
7994 /* Recognize when we are called to operate on rows that don't exist
7995 anymore. This can happen when a window is split. */
7996 && dpyinfo
->mouse_face_end_row
< w
->current_matrix
->nrows
)
7998 int phys_cursor_on_p
= w
->phys_cursor_on_p
;
7999 struct glyph_row
*row
, *first
, *last
;
8001 first
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_beg_row
);
8002 last
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_end_row
);
8004 for (row
= first
; row
<= last
&& row
->enabled_p
; ++row
)
8006 int start_hpos
, end_hpos
, start_x
;
8008 /* For all but the first row, the highlight starts at column 0. */
8011 start_hpos
= dpyinfo
->mouse_face_beg_col
;
8012 start_x
= dpyinfo
->mouse_face_beg_x
;
8021 end_hpos
= dpyinfo
->mouse_face_end_col
;
8023 end_hpos
= row
->used
[TEXT_AREA
];
8025 if (end_hpos
> start_hpos
)
8027 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
8028 start_hpos
, end_hpos
, draw
, 0);
8031 = draw
== DRAW_MOUSE_FACE
|| draw
== DRAW_IMAGE_RAISED
;
8035 /* When we've written over the cursor, arrange for it to
8036 be displayed again. */
8037 if (phys_cursor_on_p
&& !w
->phys_cursor_on_p
)
8038 x_display_cursor (w
, 1,
8039 w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
8040 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
8043 #if 0 /* MAC_TODO: mouse cursor */
8044 /* Change the mouse cursor. */
8045 if (draw
== DRAW_NORMAL_TEXT
)
8046 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8047 f
->output_data
.x
->text_cursor
);
8048 else if (draw
== DRAW_MOUSE_FACE
)
8049 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8050 f
->output_data
.x
->cross_cursor
);
8052 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8053 f
->output_data
.x
->nontext_cursor
);
8057 /* Clear out the mouse-highlighted active region.
8058 Redraw it un-highlighted first. */
8061 clear_mouse_face (dpyinfo
)
8062 struct mac_display_info
*dpyinfo
;
8066 if (! NILP (dpyinfo
->mouse_face_window
))
8068 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
8072 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8073 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8074 dpyinfo
->mouse_face_window
= Qnil
;
8075 dpyinfo
->mouse_face_overlay
= Qnil
;
8080 /* Clear any mouse-face on window W. This function is part of the
8081 redisplay interface, and is called from try_window_id and similar
8082 functions to ensure the mouse-highlight is off. */
8085 x_clear_mouse_face (w
)
8088 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
8092 XSETWINDOW (window
, w
);
8093 if (EQ (window
, dpyinfo
->mouse_face_window
))
8094 clear_mouse_face (dpyinfo
);
8099 /* Just discard the mouse face information for frame F, if any.
8100 This is used when the size of F is changed. */
8103 cancel_mouse_face (f
)
8107 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8109 window
= dpyinfo
->mouse_face_window
;
8110 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
8112 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8113 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8114 dpyinfo
->mouse_face_window
= Qnil
;
8118 static struct scroll_bar
*x_window_to_scroll_bar ();
8119 static void x_scroll_bar_report_motion ();
8120 static void x_check_fullscreen
P_ ((struct frame
*));
8121 static void x_check_fullscreen_move
P_ ((struct frame
*));
8122 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
8125 /* Try to determine frame pixel position and size of the glyph under
8126 frame pixel coordinates X/Y on frame F . Return the position and
8127 size in *RECT. Value is non-zero if we could compute these
8131 glyph_rect (f
, x
, y
, rect
)
8139 window
= window_from_coordinates (f
, x
, y
, &part
, 0);
8142 struct window
*w
= XWINDOW (window
);
8143 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
8144 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
8146 frame_to_window_pixel_xy (w
, &x
, &y
);
8148 for (; r
< end
&& r
->enabled_p
; ++r
)
8149 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
8151 /* Found the row at y. */
8152 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
8153 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
8156 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
8157 rect
->bottom
= rect
->top
+ r
->height
;
8161 /* x is to the left of the first glyph in the row. */
8162 rect
->left
= XINT (w
->left
);
8163 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
8167 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
8168 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
8170 /* x is on a glyph. */
8171 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
8172 rect
->right
= rect
->left
+ g
->pixel_width
;
8176 /* x is to the right of the last glyph in the row. */
8177 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
8178 rect
->right
= XINT (w
->left
) + XINT (w
->width
);
8183 /* The y is not on any row. */
8187 /* Record the position of the mouse in last_mouse_glyph. */
8189 remember_mouse_glyph (f1
, gx
, gy
)
8193 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
8195 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
8196 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
8198 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8199 round down even for negative values. */
8205 /* This was the original code from XTmouse_position, but it seems
8206 to give the position of the glyph diagonally next to the one
8207 the mouse is over. */
8208 gx
= (gx
+ width
- 1) / width
* width
;
8209 gy
= (gy
+ height
- 1) / height
* height
;
8211 gx
= gx
/ width
* width
;
8212 gy
= gy
/ height
* height
;
8215 last_mouse_glyph
.left
= gx
;
8216 last_mouse_glyph
.top
= gy
;
8217 last_mouse_glyph
.right
= gx
+ width
;
8218 last_mouse_glyph
.bottom
= gy
+ height
;
8222 /* Return the current position of the mouse.
8223 *fp should be a frame which indicates which display to ask about.
8225 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8226 and *part to the frame, window, and scroll bar part that the mouse
8227 is over. Set *x and *y to the portion and whole of the mouse's
8228 position on the scroll bar.
8230 If the mouse movement started elsewhere, set *fp to the frame the
8231 mouse is on, *bar_window to nil, and *x and *y to the character cell
8234 Set *time to the server time-stamp for the time at which the mouse
8235 was at this position.
8237 Don't store anything if we don't have a valid set of values to report.
8239 This clears the mouse_moved flag, so we can wait for the next mouse
8243 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
8246 Lisp_Object
*bar_window
;
8247 enum scroll_bar_part
*part
;
8249 unsigned long *time
;
8252 int ignore1
, ignore2
;
8253 WindowPtr wp
= FrontWindow ();
8254 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
8255 Lisp_Object frame
, tail
;
8259 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
8260 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
8263 /* Clear the mouse-moved flag for every frame on this display. */
8264 FOR_EACH_FRAME (tail
, frame
)
8265 XFRAME (frame
)->mouse_moved
= 0;
8267 last_mouse_scroll_bar
= Qnil
;
8269 #if TARGET_API_MAC_CARBON
8270 SetPort (GetWindowPort (wp
));
8275 GetMouse (&mouse_pos
);
8277 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
8278 &last_mouse_glyph
, insist
);
8281 *part
= scroll_bar_handle
;
8283 XSETINT (*x
, mouse_pos
.h
);
8284 XSETINT (*y
, mouse_pos
.v
);
8285 *time
= last_mouse_movement_time
;
8292 /************************************************************************
8293 Scroll bars, general
8294 ************************************************************************/
8296 /* Create a scroll bar and return the scroll bar vector for it. W is
8297 the Emacs window on which to create the scroll bar. TOP, LEFT,
8298 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8301 static struct scroll_bar
*
8302 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
8304 int top
, left
, width
, height
, disp_top
, disp_height
;
8306 struct frame
*f
= XFRAME (w
->frame
);
8307 struct scroll_bar
*bar
8308 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
8316 r
.right
= left
+ width
;
8317 r
.bottom
= disp_top
+ disp_height
;
8319 #ifdef TARGET_API_MAC_CARBON
8320 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
8321 kControlScrollBarProc
, 0L);
8323 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
8326 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
8327 SetControlReference (ch
, (long) bar
);
8329 XSETWINDOW (bar
->window
, w
);
8330 XSETINT (bar
->top
, top
);
8331 XSETINT (bar
->left
, left
);
8332 XSETINT (bar
->width
, width
);
8333 XSETINT (bar
->height
, height
);
8334 XSETINT (bar
->start
, 0);
8335 XSETINT (bar
->end
, 0);
8336 bar
->dragging
= Qnil
;
8338 /* Add bar to its frame's list of scroll bars. */
8339 bar
->next
= FRAME_SCROLL_BARS (f
);
8341 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8342 if (!NILP (bar
->next
))
8343 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8350 /* Draw BAR's handle in the proper position.
8352 If the handle is already drawn from START to END, don't bother
8353 redrawing it, unless REBUILD is non-zero; in that case, always
8354 redraw it. (REBUILD is handy for drawing the handle after expose
8357 Normally, we want to constrain the start and end of the handle to
8358 fit inside its rectangle, but if the user is dragging the scroll
8359 bar handle, we want to let them drag it down all the way, so that
8360 the bar's top is as far down as it goes; otherwise, there's no way
8361 to move to the very end of the buffer. */
8364 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
8365 struct scroll_bar
*bar
;
8369 int dragging
= ! NILP (bar
->dragging
);
8370 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
8371 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8372 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8373 int length
= end
- start
;
8375 /* If the display is already accurate, do nothing. */
8377 && start
== XINT (bar
->start
)
8378 && end
== XINT (bar
->end
))
8383 /* Make sure the values are reasonable, and try to preserve the
8384 distance between start and end. */
8387 else if (start
> top_range
)
8389 end
= start
+ length
;
8393 else if (end
> top_range
&& ! dragging
)
8396 /* Store the adjusted setting in the scroll bar. */
8397 XSETINT (bar
->start
, start
);
8398 XSETINT (bar
->end
, end
);
8400 /* Clip the end position, just for display. */
8401 if (end
> top_range
)
8404 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8405 top positions, to make sure the handle is always at least that
8406 many pixels tall. */
8407 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
8409 SetControlMinimum (ch
, 0);
8410 /* Don't inadvertently activate deactivated scroll bars */
8411 if (GetControlMaximum (ch
) != -1)
8412 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
8414 SetControlValue (ch
, start
);
8415 #if TARGET_API_MAC_CARBON
8416 SetControlViewSize (ch
, end
- start
);
8423 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8427 x_scroll_bar_remove (bar
)
8428 struct scroll_bar
*bar
;
8430 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8434 /* Destroy the Mac scroll bar control */
8435 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
8437 /* Disassociate this scroll bar from its window. */
8438 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
8443 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8444 that we are displaying PORTION characters out of a total of WHOLE
8445 characters, starting at POSITION. If WINDOW has no scroll bar,
8448 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
8450 int portion
, whole
, position
;
8452 struct frame
*f
= XFRAME (w
->frame
);
8453 struct scroll_bar
*bar
;
8454 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
8455 int window_x
, window_y
, window_width
, window_height
;
8457 /* Get window dimensions. */
8458 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
8463 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
8465 height
= window_height
;
8467 /* Compute the left edge of the scroll bar area. */
8468 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8469 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
8471 left
= XFASTINT (w
->left
);
8472 left
*= CANON_X_UNIT (f
);
8473 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
8475 /* Compute the width of the scroll bar which might be less than
8476 the width of the area reserved for the scroll bar. */
8477 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
8478 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
8482 /* Compute the left edge of the scroll bar. */
8483 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8484 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
8486 sb_left
= left
+ (width
- sb_width
) / 2;
8488 /* Adjustments according to Inside Macintosh to make it look nice */
8490 disp_height
= height
;
8496 else if (disp_top
== PIXEL_HEIGHT (f
) - 16)
8502 if (sb_left
+ sb_width
== PIXEL_WIDTH (f
))
8505 /* Does the scroll bar exist yet? */
8506 if (NILP (w
->vertical_scroll_bar
))
8509 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
8510 left
, top
, width
, height
, 0);
8512 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
8514 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
8518 /* It may just need to be moved and resized. */
8521 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
8522 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
8526 /* If already correctly positioned, do nothing. */
8527 if (XINT (bar
->left
) == sb_left
8528 && XINT (bar
->top
) == top
8529 && XINT (bar
->width
) == sb_width
8530 && XINT (bar
->height
) == height
)
8534 /* Clear areas not covered by the scroll bar because it's not as
8535 wide as the area reserved for it . This makes sure a
8536 previous mode line display is cleared after C-x 2 C-x 1, for
8538 int area_width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
8539 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
8540 left
, top
, area_width
, height
, 0);
8543 if (sb_left
+ sb_width
>= PIXEL_WIDTH (f
))
8544 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
8545 sb_left
- 1, top
, 1, height
, 0);
8549 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
8550 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8554 /* Remember new settings. */
8555 XSETINT (bar
->left
, sb_left
);
8556 XSETINT (bar
->top
, top
);
8557 XSETINT (bar
->width
, sb_width
);
8558 XSETINT (bar
->height
, height
);
8564 /* Set the scroll bar's current state, unless we're currently being
8566 if (NILP (bar
->dragging
))
8568 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
8571 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
8574 int start
= ((double) position
* top_range
) / whole
;
8575 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
8576 x_scroll_bar_set_handle (bar
, start
, end
, 0);
8582 /* The following three hooks are used when we're doing a thorough
8583 redisplay of the frame. We don't explicitly know which scroll bars
8584 are going to be deleted, because keeping track of when windows go
8585 away is a real pain - "Can you say set-window-configuration, boys
8586 and girls?" Instead, we just assert at the beginning of redisplay
8587 that *all* scroll bars are to be removed, and then save a scroll bar
8588 from the fiery pit when we actually redisplay its window. */
8590 /* Arrange for all scroll bars on FRAME to be removed at the next call
8591 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8592 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8595 XTcondemn_scroll_bars (frame
)
8598 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8599 while (! NILP (FRAME_SCROLL_BARS (frame
)))
8602 bar
= FRAME_SCROLL_BARS (frame
);
8603 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
8604 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
8605 XSCROLL_BAR (bar
)->prev
= Qnil
;
8606 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
8607 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
8608 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
8613 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8614 Note that WINDOW isn't necessarily condemned at all. */
8617 XTredeem_scroll_bar (window
)
8618 struct window
*window
;
8620 struct scroll_bar
*bar
;
8622 /* We can't redeem this window's scroll bar if it doesn't have one. */
8623 if (NILP (window
->vertical_scroll_bar
))
8626 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
8628 /* Unlink it from the condemned list. */
8630 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
8632 if (NILP (bar
->prev
))
8634 /* If the prev pointer is nil, it must be the first in one of
8636 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
8637 /* It's not condemned. Everything's fine. */
8639 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
8640 window
->vertical_scroll_bar
))
8641 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
8643 /* If its prev pointer is nil, it must be at the front of
8644 one or the other! */
8648 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
8650 if (! NILP (bar
->next
))
8651 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
8653 bar
->next
= FRAME_SCROLL_BARS (f
);
8655 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8656 if (! NILP (bar
->next
))
8657 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8661 /* Remove all scroll bars on FRAME that haven't been saved since the
8662 last call to `*condemn_scroll_bars_hook'. */
8665 XTjudge_scroll_bars (f
)
8668 Lisp_Object bar
, next
;
8670 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
8672 /* Clear out the condemned list now so we won't try to process any
8673 more events on the hapless scroll bars. */
8674 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
8676 for (; ! NILP (bar
); bar
= next
)
8678 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
8680 x_scroll_bar_remove (b
);
8683 b
->next
= b
->prev
= Qnil
;
8686 /* Now there should be no references to the condemned scroll bars,
8687 and they should get garbage-collected. */
8692 activate_scroll_bars (frame
)
8698 bar
= FRAME_SCROLL_BARS (frame
);
8699 while (! NILP (bar
))
8701 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
8702 #ifdef TARGET_API_MAC_CARBON
8703 ActivateControl (ch
);
8705 SetControlMaximum (ch
,
8706 VERTICAL_SCROLL_BAR_TOP_RANGE (frame
,
8707 XINT (XSCROLL_BAR (bar
)
8710 bar
= XSCROLL_BAR (bar
)->next
;
8716 deactivate_scroll_bars (frame
)
8722 bar
= FRAME_SCROLL_BARS (frame
);
8723 while (! NILP (bar
))
8725 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
8726 #ifdef TARGET_API_MAC_CARBON
8727 DeactivateControl (ch
);
8729 SetControlMaximum (ch
, XINT (-1));
8731 bar
= XSCROLL_BAR (bar
)->next
;
8735 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8736 is set to something other than NO_EVENT, it is enqueued.
8738 This may be called from a signal handler, so we have to ignore GC
8742 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
8743 struct scroll_bar
*bar
;
8746 struct input_event
*bufp
;
8748 if (! GC_WINDOWP (bar
->window
))
8751 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
8752 bufp
->frame_or_window
= bar
->window
;
8755 bar
->dragging
= Qnil
;
8759 case kControlUpButtonPart
:
8760 bufp
->part
= scroll_bar_up_arrow
;
8762 case kControlDownButtonPart
:
8763 bufp
->part
= scroll_bar_down_arrow
;
8765 case kControlPageUpPart
:
8766 bufp
->part
= scroll_bar_above_handle
;
8768 case kControlPageDownPart
:
8769 bufp
->part
= scroll_bar_below_handle
;
8771 #ifdef TARGET_API_MAC_CARBON
8774 case kControlIndicatorPart
:
8776 if (er
->what
== mouseDown
)
8777 bar
->dragging
= make_number (0);
8778 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8779 bufp
->part
= scroll_bar_handle
;
8785 /* Handle some mouse motion while someone is dragging the scroll bar.
8787 This may be called from a signal handler, so we have to ignore GC
8791 x_scroll_bar_note_movement (bar
, y_pos
, t
)
8792 struct scroll_bar
*bar
;
8796 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
8798 last_mouse_movement_time
= t
;
8801 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8803 /* If we're dragging the bar, display it. */
8804 if (! GC_NILP (bar
->dragging
))
8806 /* Where should the handle be now? */
8807 int new_start
= y_pos
- 24;
8809 if (new_start
!= XINT (bar
->start
))
8811 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8813 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8819 /* Return information to the user about the current position of the
8820 mouse on the scroll bar. */
8823 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
8825 Lisp_Object
*bar_window
;
8826 enum scroll_bar_part
*part
;
8828 unsigned long *time
;
8830 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
8831 WindowPtr wp
= FrontWindow ();
8833 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
8834 int win_y
, top_range
;
8836 #if TARGET_API_MAC_CARBON
8837 SetPort (GetWindowPort (wp
));
8842 GetMouse (&mouse_pos
);
8844 win_y
= mouse_pos
.v
- XINT (bar
->top
);
8845 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8847 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
8851 if (! NILP (bar
->dragging
))
8852 win_y
-= XINT (bar
->dragging
);
8856 if (win_y
> top_range
)
8860 *bar_window
= bar
->window
;
8862 if (! NILP (bar
->dragging
))
8863 *part
= scroll_bar_handle
;
8864 else if (win_y
< XINT (bar
->start
))
8865 *part
= scroll_bar_above_handle
;
8866 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8867 *part
= scroll_bar_handle
;
8869 *part
= scroll_bar_below_handle
;
8871 XSETINT (*x
, win_y
);
8872 XSETINT (*y
, top_range
);
8875 last_mouse_scroll_bar
= Qnil
;
8877 *time
= last_mouse_movement_time
;
8880 /***********************************************************************
8882 ***********************************************************************/
8884 /* Notice if the text cursor of window W has been overwritten by a
8885 drawing operation that outputs glyphs starting at START_X and
8886 ending at END_X in the line given by output_cursor.vpos.
8887 Coordinates are area-relative. END_X < 0 means all the rest
8888 of the line after START_X has been written. */
8891 notice_overwritten_cursor (w
, area
, x0
, x1
, y0
, y1
)
8893 enum glyph_row_area area
;
8896 if (area
== TEXT_AREA
8897 && w
->phys_cursor_on_p
8898 && y0
<= w
->phys_cursor
.y
8899 && y1
>= w
->phys_cursor
.y
+ w
->phys_cursor_height
8900 && x0
<= w
->phys_cursor
.x
8901 && (x1
< 0 || x1
> w
->phys_cursor
.x
))
8902 w
->phys_cursor_on_p
= 0;
8906 /* Set clipping for output in glyph row ROW. W is the window in which
8907 we operate. GC is the graphics context to set clipping in.
8908 WHOLE_LINE_P non-zero means include the areas used for truncation
8909 mark display and alike in the clipping rectangle.
8911 ROW may be a text row or, e.g., a mode line. Text rows must be
8912 clipped to the interior of the window dedicated to text display,
8913 mode lines must be clipped to the whole window. */
8916 x_clip_to_row (w
, row
, gc
, whole_line_p
)
8918 struct glyph_row
*row
;
8922 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
8924 int window_x
, window_y
, window_width
, window_height
;
8926 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
8928 clip_rect
.left
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
8929 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
8930 clip_rect
.top
= max (clip_rect
.top
, window_y
);
8931 clip_rect
.right
= clip_rect
.left
+ window_width
;
8932 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
8934 /* If clipping to the whole line, including trunc marks, extend
8935 the rectangle to the left and increase its width. */
8938 clip_rect
.left
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
8939 clip_rect
.right
+= FRAME_X_FRINGE_WIDTH (f
);
8942 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
8946 /* Draw a hollow box cursor on window W in glyph row ROW. */
8949 x_draw_hollow_cursor (w
, row
)
8951 struct glyph_row
*row
;
8953 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
8954 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8955 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
8958 struct glyph
*cursor_glyph
;
8961 /* Compute frame-relative coordinates from window-relative
8963 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
8964 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
8965 + row
->ascent
- w
->phys_cursor_ascent
);
8966 h
= row
->height
- 1;
8968 /* Get the glyph the cursor is on. If we can't tell because
8969 the current matrix is invalid or such, give up. */
8970 cursor_glyph
= get_phys_cursor_glyph (w
);
8971 if (cursor_glyph
== NULL
)
8974 /* Compute the width of the rectangle to draw. If on a stretch
8975 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8976 rectangle as wide as the glyph, but use a canonical character
8978 wd
= cursor_glyph
->pixel_width
- 1;
8979 if (cursor_glyph
->type
== STRETCH_GLYPH
8980 && !x_stretch_cursor_p
)
8981 wd
= min (CANON_X_UNIT (f
), wd
);
8983 /* The foreground of cursor_gc is typically the same as the normal
8984 background color, which can cause the cursor box to be invisible. */
8985 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
8986 if (dpyinfo
->scratch_cursor_gc
)
8987 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
8989 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
8990 GCForeground
, &xgcv
);
8991 gc
= dpyinfo
->scratch_cursor_gc
;
8993 /* Set clipping, draw the rectangle, and reset clipping again. */
8994 x_clip_to_row (w
, row
, gc
, 0);
8995 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
8996 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
9000 /* Draw a bar cursor on window W in glyph row ROW.
9002 Implementation note: One would like to draw a bar cursor with an
9003 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9004 Unfortunately, I didn't find a font yet that has this property set.
9008 x_draw_bar_cursor (w
, row
, width
)
9010 struct glyph_row
*row
;
9013 /* If cursor hpos is out of bounds, don't draw garbage. This can
9014 happen in mini-buffer windows when switching between echo area
9015 glyphs and mini-buffer. */
9016 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
9018 struct frame
*f
= XFRAME (w
->frame
);
9019 struct glyph
*cursor_glyph
;
9027 cursor_glyph
= get_phys_cursor_glyph (w
);
9028 if (cursor_glyph
== NULL
)
9031 xgcv
.background
= f
->output_data
.mac
->cursor_pixel
;
9032 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
9033 mask
= GCForeground
| GCBackground
;
9034 dpy
= FRAME_MAC_DISPLAY (f
);
9035 window
= FRAME_MAC_WINDOW (f
);
9036 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
9039 XChangeGC (dpy
, gc
, mask
, &xgcv
);
9042 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
9043 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
9047 width
= f
->output_data
.mac
->cursor_width
;
9049 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
9050 x_clip_to_row (w
, row
, gc
, 0);
9051 XFillRectangle (dpy
, window
, gc
,
9053 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
9054 min (cursor_glyph
->pixel_width
, width
),
9056 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
9061 /* Clear the cursor of window W to background color, and mark the
9062 cursor as not shown. This is used when the text where the cursor
9063 is is about to be rewritten. */
9069 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
9070 x_update_window_cursor (w
, 0);
9074 /* Draw the cursor glyph of window W in glyph row ROW. See the
9075 comment of x_draw_glyphs for the meaning of HL. */
9078 x_draw_phys_cursor_glyph (w
, row
, hl
)
9080 struct glyph_row
*row
;
9081 enum draw_glyphs_face hl
;
9083 /* If cursor hpos is out of bounds, don't draw garbage. This can
9084 happen in mini-buffer windows when switching between echo area
9085 glyphs and mini-buffer. */
9086 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
9088 int on_p
= w
->phys_cursor_on_p
;
9089 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
9090 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
9092 w
->phys_cursor_on_p
= on_p
;
9094 /* When we erase the cursor, and ROW is overlapped by other
9095 rows, make sure that these overlapping parts of other rows
9097 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
9099 if (row
> w
->current_matrix
->rows
9100 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
9101 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
9103 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
9104 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
9105 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
9111 /* Erase the image of a cursor of window W from the screen. */
9114 x_erase_phys_cursor (w
)
9117 struct frame
*f
= XFRAME (w
->frame
);
9118 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9119 int hpos
= w
->phys_cursor
.hpos
;
9120 int vpos
= w
->phys_cursor
.vpos
;
9121 int mouse_face_here_p
= 0;
9122 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
9123 struct glyph_row
*cursor_row
;
9124 struct glyph
*cursor_glyph
;
9125 enum draw_glyphs_face hl
;
9127 /* No cursor displayed or row invalidated => nothing to do on the
9129 if (w
->phys_cursor_type
== NO_CURSOR
)
9130 goto mark_cursor_off
;
9132 /* VPOS >= active_glyphs->nrows means that window has been resized.
9133 Don't bother to erase the cursor. */
9134 if (vpos
>= active_glyphs
->nrows
)
9135 goto mark_cursor_off
;
9137 /* If row containing cursor is marked invalid, there is nothing we
9139 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
9140 if (!cursor_row
->enabled_p
)
9141 goto mark_cursor_off
;
9143 /* If row is completely invisible, don't attempt to delete a cursor which
9144 isn't there. This may happen if cursor is at top of window, and
9145 we switch to a buffer with a header line in that window. */
9146 if (cursor_row
->visible_height
<= 0)
9147 goto mark_cursor_off
;
9149 /* This can happen when the new row is shorter than the old one.
9150 In this case, either x_draw_glyphs or clear_end_of_line
9151 should have cleared the cursor. Note that we wouldn't be
9152 able to erase the cursor in this case because we don't have a
9153 cursor glyph at hand. */
9154 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
9155 goto mark_cursor_off
;
9157 /* If the cursor is in the mouse face area, redisplay that when
9158 we clear the cursor. */
9159 if (! NILP (dpyinfo
->mouse_face_window
)
9160 && w
== XWINDOW (dpyinfo
->mouse_face_window
)
9161 && (vpos
> dpyinfo
->mouse_face_beg_row
9162 || (vpos
== dpyinfo
->mouse_face_beg_row
9163 && hpos
>= dpyinfo
->mouse_face_beg_col
))
9164 && (vpos
< dpyinfo
->mouse_face_end_row
9165 || (vpos
== dpyinfo
->mouse_face_end_row
9166 && hpos
< dpyinfo
->mouse_face_end_col
))
9167 /* Don't redraw the cursor's spot in mouse face if it is at the
9168 end of a line (on a newline). The cursor appears there, but
9169 mouse highlighting does not. */
9170 && cursor_row
->used
[TEXT_AREA
] > hpos
)
9171 mouse_face_here_p
= 1;
9173 /* Maybe clear the display under the cursor. */
9174 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
9177 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
9179 cursor_glyph
= get_phys_cursor_glyph (w
);
9180 if (cursor_glyph
== NULL
)
9181 goto mark_cursor_off
;
9183 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
9185 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
9187 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
9189 cursor_glyph
->pixel_width
,
9190 cursor_row
->visible_height
,
9194 /* Erase the cursor by redrawing the character underneath it. */
9195 if (mouse_face_here_p
)
9196 hl
= DRAW_MOUSE_FACE
;
9198 hl
= DRAW_NORMAL_TEXT
;
9199 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
9202 w
->phys_cursor_on_p
= 0;
9203 w
->phys_cursor_type
= NO_CURSOR
;
9207 /* Non-zero if physical cursor of window W is within mouse face. */
9210 cursor_in_mouse_face_p (w
)
9213 struct mac_display_info
*dpyinfo
9214 = FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
9215 int in_mouse_face
= 0;
9217 if (WINDOWP (dpyinfo
->mouse_face_window
)
9218 && XWINDOW (dpyinfo
->mouse_face_window
) == w
)
9220 int hpos
= w
->phys_cursor
.hpos
;
9221 int vpos
= w
->phys_cursor
.vpos
;
9223 if (vpos
>= dpyinfo
->mouse_face_beg_row
9224 && vpos
<= dpyinfo
->mouse_face_end_row
9225 && (vpos
> dpyinfo
->mouse_face_beg_row
9226 || hpos
>= dpyinfo
->mouse_face_beg_col
)
9227 && (vpos
< dpyinfo
->mouse_face_end_row
9228 || hpos
< dpyinfo
->mouse_face_end_col
9229 || dpyinfo
->mouse_face_past_end
))
9233 return in_mouse_face
;
9237 /* Display or clear cursor of window W. If ON is zero, clear the
9238 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9239 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9242 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
9244 int on
, hpos
, vpos
, x
, y
;
9246 struct frame
*f
= XFRAME (w
->frame
);
9247 int new_cursor_type
;
9248 int new_cursor_width
;
9249 struct glyph_matrix
*current_glyphs
;
9250 struct glyph_row
*glyph_row
;
9251 struct glyph
*glyph
;
9252 int cursor_non_selected
;
9253 int active_cursor
= 1;
9255 /* This is pointless on invisible frames, and dangerous on garbaged
9256 windows and frames; in the latter case, the frame or window may
9257 be in the midst of changing its size, and x and y may be off the
9259 if (! FRAME_VISIBLE_P (f
)
9260 || FRAME_GARBAGED_P (f
)
9261 || vpos
>= w
->current_matrix
->nrows
9262 || hpos
>= w
->current_matrix
->matrix_w
)
9265 /* If cursor is off and we want it off, return quickly. */
9266 if (!on
&& !w
->phys_cursor_on_p
)
9269 current_glyphs
= w
->current_matrix
;
9270 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
9271 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
9273 /* If cursor row is not enabled, we don't really know where to
9274 display the cursor. */
9275 if (!glyph_row
->enabled_p
)
9277 w
->phys_cursor_on_p
= 0;
9281 xassert (interrupt_input_blocked
);
9283 /* Set new_cursor_type to the cursor we want to be displayed. In a
9284 mini-buffer window, we want the cursor only to appear if we are
9285 reading input from this window. For the selected window, we want
9286 the cursor type given by the frame parameter. If explicitly
9287 marked off, draw no cursor. In all other cases, we want a hollow
9290 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows
,
9292 new_cursor_width
= -1;
9293 if (cursor_in_echo_area
9294 && FRAME_HAS_MINIBUF_P (f
)
9295 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
))
9297 if (w
== XWINDOW (echo_area_window
))
9298 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
9301 if (cursor_non_selected
)
9302 new_cursor_type
= HOLLOW_BOX_CURSOR
;
9304 new_cursor_type
= NO_CURSOR
;
9310 if (f
!= FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
9311 || w
!= XWINDOW (f
->selected_window
))
9315 if (MINI_WINDOW_P (w
)
9316 || !cursor_non_selected
9317 || NILP (XBUFFER (w
->buffer
)->cursor_type
))
9318 new_cursor_type
= NO_CURSOR
;
9320 new_cursor_type
= HOLLOW_BOX_CURSOR
;
9324 struct buffer
*b
= XBUFFER (w
->buffer
);
9326 if (EQ (b
->cursor_type
, Qt
))
9327 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
9329 new_cursor_type
= x_specified_cursor_type (b
->cursor_type
,
9331 if (w
->cursor_off_p
)
9333 if (new_cursor_type
== FILLED_BOX_CURSOR
)
9334 new_cursor_type
= HOLLOW_BOX_CURSOR
;
9335 else if (new_cursor_type
== BAR_CURSOR
&& new_cursor_width
> 1)
9336 new_cursor_width
= 1;
9338 new_cursor_type
= NO_CURSOR
;
9343 /* If cursor is currently being shown and we don't want it to be or
9344 it is in the wrong place, or the cursor type is not what we want,
9346 if (w
->phys_cursor_on_p
9348 || w
->phys_cursor
.x
!= x
9349 || w
->phys_cursor
.y
!= y
9350 || new_cursor_type
!= w
->phys_cursor_type
9351 || (new_cursor_type
== BAR_CURSOR
9352 && new_cursor_width
!= w
->phys_cursor_width
)))
9353 x_erase_phys_cursor (w
);
9355 /* If the cursor is now invisible and we want it to be visible,
9357 if (on
&& !w
->phys_cursor_on_p
)
9359 w
->phys_cursor_ascent
= glyph_row
->ascent
;
9360 w
->phys_cursor_height
= glyph_row
->height
;
9362 /* Set phys_cursor_.* before x_draw_.* is called because some
9363 of them may need the information. */
9364 w
->phys_cursor
.x
= x
;
9365 w
->phys_cursor
.y
= glyph_row
->y
;
9366 w
->phys_cursor
.hpos
= hpos
;
9367 w
->phys_cursor
.vpos
= vpos
;
9368 w
->phys_cursor_type
= new_cursor_type
;
9369 w
->phys_cursor_width
= new_cursor_width
;
9370 w
->phys_cursor_on_p
= 1;
9372 switch (new_cursor_type
)
9374 case HOLLOW_BOX_CURSOR
:
9375 x_draw_hollow_cursor (w
, glyph_row
);
9378 case FILLED_BOX_CURSOR
:
9379 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
9383 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
);
9396 /* Display the cursor on window W, or clear it. X and Y are window
9397 relative pixel coordinates. HPOS and VPOS are glyph matrix
9398 positions. If W is not the selected window, display a hollow
9399 cursor. ON non-zero means display the cursor at X, Y which
9400 correspond to HPOS, VPOS, otherwise it is cleared. */
9403 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
9405 int on
, hpos
, vpos
, x
, y
;
9408 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
9413 /* Display the cursor on window W, or clear it, according to ON_P.
9414 Don't change the cursor's position. */
9417 x_update_cursor (f
, on_p
)
9421 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
9425 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9426 in the window tree rooted at W. */
9429 x_update_cursor_in_window_tree (w
, on_p
)
9435 if (!NILP (w
->hchild
))
9436 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
9437 else if (!NILP (w
->vchild
))
9438 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
9440 x_update_window_cursor (w
, on_p
);
9442 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
9447 /* Switch the display of W's cursor on or off, according to the value
9451 x_update_window_cursor (w
, on
)
9455 /* Don't update cursor in windows whose frame is in the process
9456 of being deleted. */
9457 if (w
->current_matrix
)
9460 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
,
9461 w
->phys_cursor
.vpos
, w
->phys_cursor
.x
,
9472 #if 0 /* MAC_TODO: no icon support yet. */
9474 x_bitmap_icon (f
, icon
)
9480 if (FRAME_W32_WINDOW (f
) == 0)
9484 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
9485 else if (STRINGP (icon
))
9486 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
9487 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
9488 else if (SYMBOLP (icon
))
9492 if (EQ (icon
, intern ("application")))
9493 name
= (LPCTSTR
) IDI_APPLICATION
;
9494 else if (EQ (icon
, intern ("hand")))
9495 name
= (LPCTSTR
) IDI_HAND
;
9496 else if (EQ (icon
, intern ("question")))
9497 name
= (LPCTSTR
) IDI_QUESTION
;
9498 else if (EQ (icon
, intern ("exclamation")))
9499 name
= (LPCTSTR
) IDI_EXCLAMATION
;
9500 else if (EQ (icon
, intern ("asterisk")))
9501 name
= (LPCTSTR
) IDI_ASTERISK
;
9502 else if (EQ (icon
, intern ("winlogo")))
9503 name
= (LPCTSTR
) IDI_WINLOGO
;
9507 hicon
= LoadIcon (NULL
, name
);
9515 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
9520 #endif /* MAC_TODO */
9522 /************************************************************************
9524 ************************************************************************/
9526 /* Display Error Handling functions not used on W32. Listing them here
9527 helps diff stay in step when comparing w32term.c with xterm.c.
9529 x_error_catcher (display, error)
9530 x_catch_errors (dpy)
9531 x_catch_errors_unwind (old_val)
9532 x_check_errors (dpy, format)
9533 x_had_errors_p (dpy)
9534 x_clear_errors (dpy)
9535 x_uncatch_errors (dpy, count)
9537 x_connection_signal (signalnum)
9538 x_connection_closed (dpy, error_message)
9539 x_error_quitter (display, error)
9540 x_error_handler (display, error)
9541 x_io_error_quitter (display)
9546 /* Changing the font of the frame. */
9548 /* Give frame F the font named FONTNAME as its default font, and
9549 return the full name of that font. FONTNAME may be a wildcard
9550 pattern; in that case, we choose some font that fits the pattern.
9551 The return value shows which font we chose. */
9554 x_new_font (f
, fontname
)
9556 register char *fontname
;
9558 struct font_info
*fontp
9559 = FS_LOAD_FONT (f
, 0, fontname
, -1);
9564 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
9565 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
9566 FRAME_FONTSET (f
) = -1;
9568 /* Compute the scroll bar width in character columns. */
9569 if (f
->scroll_bar_pixel_width
> 0)
9571 int wid
= FONT_WIDTH (FRAME_FONT (f
));
9572 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
9576 int wid
= FONT_WIDTH (FRAME_FONT (f
));
9577 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
9580 /* Now make the frame display the given font. */
9581 if (FRAME_MAC_WINDOW (f
) != 0)
9583 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
9584 f
->output_data
.mac
->font
);
9585 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
9586 f
->output_data
.mac
->font
);
9587 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
9588 f
->output_data
.mac
->font
);
9590 frame_update_line_height (f
);
9591 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
9592 x_set_window_size (f
, 0, f
->width
, f
->height
);
9595 /* If we are setting a new frame's font for the first time,
9596 there are no faces yet, so this font's height is the line height. */
9597 f
->output_data
.mac
->line_height
= FONT_HEIGHT (FRAME_FONT (f
));
9599 return build_string (fontp
->full_name
);
9602 /* Give frame F the fontset named FONTSETNAME as its default font, and
9603 return the full name of that fontset. FONTSETNAME may be a wildcard
9604 pattern; in that case, we choose some fontset that fits the pattern.
9605 The return value shows which fontset we chose. */
9608 x_new_fontset (f
, fontsetname
)
9612 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
9618 if (FRAME_FONTSET (f
) == fontset
)
9619 /* This fontset is already set in frame F. There's nothing more
9621 return fontset_name (fontset
);
9623 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
9625 if (!STRINGP (result
))
9626 /* Can't load ASCII font. */
9629 /* Since x_new_font doesn't update any fontset information, do it now. */
9630 FRAME_FONTSET(f
) = fontset
;
9632 return build_string (fontsetname
);
9635 /* Compute actual fringe widths */
9638 x_compute_fringe_widths (f
, redraw
)
9642 int o_left
= f
->output_data
.mac
->left_fringe_width
;
9643 int o_right
= f
->output_data
.mac
->right_fringe_width
;
9644 int o_cols
= f
->output_data
.mac
->fringe_cols
;
9646 Lisp_Object left_fringe
= Fassq (Qleft_fringe
, f
->param_alist
);
9647 Lisp_Object right_fringe
= Fassq (Qright_fringe
, f
->param_alist
);
9648 int left_fringe_width
, right_fringe_width
;
9650 if (!NILP (left_fringe
))
9651 left_fringe
= Fcdr (left_fringe
);
9652 if (!NILP (right_fringe
))
9653 right_fringe
= Fcdr (right_fringe
);
9655 left_fringe_width
= ((NILP (left_fringe
) || !INTEGERP (left_fringe
)) ? 8 :
9656 XINT (left_fringe
));
9657 right_fringe_width
= ((NILP (right_fringe
) || !INTEGERP (right_fringe
)) ? 8 :
9658 XINT (right_fringe
));
9660 if (left_fringe_width
|| right_fringe_width
)
9662 int left_wid
= left_fringe_width
>= 0 ? left_fringe_width
: -left_fringe_width
;
9663 int right_wid
= right_fringe_width
>= 0 ? right_fringe_width
: -right_fringe_width
;
9664 int conf_wid
= left_wid
+ right_wid
;
9665 int font_wid
= FONT_WIDTH (f
->output_data
.mac
->font
);
9666 int cols
= (left_wid
+ right_wid
+ font_wid
-1) / font_wid
;
9667 int real_wid
= cols
* font_wid
;
9668 if (left_wid
&& right_wid
)
9670 if (left_fringe_width
< 0)
9672 /* Left fringe width is fixed, adjust right fringe if necessary */
9673 f
->output_data
.mac
->left_fringe_width
= left_wid
;
9674 f
->output_data
.mac
->right_fringe_width
= real_wid
- left_wid
;
9676 else if (right_fringe_width
< 0)
9678 /* Right fringe width is fixed, adjust left fringe if necessary */
9679 f
->output_data
.mac
->left_fringe_width
= real_wid
- right_wid
;
9680 f
->output_data
.mac
->right_fringe_width
= right_wid
;
9684 /* Adjust both fringes with an equal amount.
9685 Note that we are doing integer arithmetic here, so don't
9686 lose a pixel if the total width is an odd number. */
9687 int fill
= real_wid
- conf_wid
;
9688 f
->output_data
.mac
->left_fringe_width
= left_wid
+ fill
/2;
9689 f
->output_data
.mac
->right_fringe_width
= right_wid
+ fill
- fill
/2;
9692 else if (left_fringe_width
)
9694 f
->output_data
.mac
->left_fringe_width
= real_wid
;
9695 f
->output_data
.mac
->right_fringe_width
= 0;
9699 f
->output_data
.mac
->left_fringe_width
= 0;
9700 f
->output_data
.mac
->right_fringe_width
= real_wid
;
9702 f
->output_data
.mac
->fringe_cols
= cols
;
9703 f
->output_data
.mac
->fringes_extra
= real_wid
;
9707 f
->output_data
.mac
->left_fringe_width
= 0;
9708 f
->output_data
.mac
->right_fringe_width
= 0;
9709 f
->output_data
.mac
->fringe_cols
= 0;
9710 f
->output_data
.mac
->fringes_extra
= 0;
9713 if (redraw
&& FRAME_VISIBLE_P (f
))
9714 if (o_left
!= f
->output_data
.mac
->left_fringe_width
||
9715 o_right
!= f
->output_data
.mac
->right_fringe_width
||
9716 o_cols
!= f
->output_data
.mac
->fringe_cols
)
9720 /***********************************************************************
9721 TODO: W32 Input Methods
9722 ***********************************************************************/
9723 /* Listing missing functions from xterm.c helps diff stay in step.
9725 xim_destroy_callback (xim, client_data, call_data)
9726 xim_open_dpy (dpyinfo, resource_name)
9728 xim_instantiate_callback (display, client_data, call_data)
9729 xim_initialize (dpyinfo, resource_name)
9730 xim_close_dpy (dpyinfo)
9735 /* Calculate the absolute position in frame F
9736 from its current recorded position values and gravity. */
9739 x_calc_absolute_position (f
)
9743 int flags
= f
->output_data
.mac
->size_hint_flags
;
9747 /* Find the position of the outside upper-left corner of
9748 the inner window, with respect to the outer window. */
9749 if (f
->output_data
.mac
->parent_desc
!= FRAME_MAC_DISPLAY_INFO (f
)->root_window
)
9752 GetPort (&savePort
);
9754 #if TARGET_API_MAC_CARBON
9755 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
9757 SetPort (FRAME_MAC_WINDOW (f
));
9760 #if TARGET_API_MAC_CARBON
9764 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
9765 SetPt(&pt
, r
.left
, r
.top
);
9767 #else /* not TARGET_API_MAC_CARBON */
9768 SetPt(&pt
, FRAME_MAC_WINDOW (f
)->portRect
.left
, FRAME_MAC_WINDOW (f
)->portRect
.top
);
9769 #endif /* not TARGET_API_MAC_CARBON */
9770 LocalToGlobal (&pt
);
9774 /* Treat negative positions as relative to the leftmost bottommost
9775 position that fits on the screen. */
9776 if (flags
& XNegative
)
9777 f
->output_data
.mac
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
9778 - 2 * f
->output_data
.mac
->border_width
- pt
.h
9780 + f
->output_data
.mac
->left_pos
);
9781 /* NTEMACS_TODO: Subtract menubar height? */
9782 if (flags
& YNegative
)
9783 f
->output_data
.mac
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
9784 - 2 * f
->output_data
.mac
->border_width
- pt
.v
9786 + f
->output_data
.mac
->top_pos
);
9787 /* The left_pos and top_pos
9788 are now relative to the top and left screen edges,
9789 so the flags should correspond. */
9790 f
->output_data
.mac
->size_hint_flags
&= ~ (XNegative
| YNegative
);
9793 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9794 to really change the position, and 0 when calling from
9795 x_make_frame_visible (in that case, XOFF and YOFF are the current
9796 position values). It is -1 when calling from x_set_frame_parameters,
9797 which means, do adjust for borders but don't change the gravity. */
9800 x_set_offset (f
, xoff
, yoff
, change_gravity
)
9802 register int xoff
, yoff
;
9805 int modified_top
, modified_left
;
9807 if (change_gravity
> 0)
9809 f
->output_data
.mac
->top_pos
= yoff
;
9810 f
->output_data
.mac
->left_pos
= xoff
;
9811 f
->output_data
.mac
->size_hint_flags
&= ~ (XNegative
| YNegative
);
9813 f
->output_data
.mac
->size_hint_flags
|= XNegative
;
9815 f
->output_data
.mac
->size_hint_flags
|= YNegative
;
9816 f
->output_data
.mac
->win_gravity
= NorthWestGravity
;
9818 x_calc_absolute_position (f
);
9821 x_wm_set_size_hint (f
, (long) 0, 0);
9823 modified_left
= f
->output_data
.mac
->left_pos
;
9824 modified_top
= f
->output_data
.mac
->top_pos
;
9826 MoveWindow (f
->output_data
.mac
->mWP
, modified_left
+ 6,
9827 modified_top
+ 42, false);
9832 /* Call this to change the size of frame F's x-window.
9833 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9834 for this size change and subsequent size changes.
9835 Otherwise we leave the window gravity unchanged. */
9838 x_set_window_size (f
, change_gravity
, cols
, rows
)
9843 int pixelwidth
, pixelheight
;
9847 check_frame_size (f
, &rows
, &cols
);
9848 f
->output_data
.mac
->vertical_scroll_bar_extra
9849 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
9851 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.mac
->font
)));
9853 x_compute_fringe_widths (f
, 0);
9855 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
9856 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
9858 f
->output_data
.mac
->win_gravity
= NorthWestGravity
;
9859 x_wm_set_size_hint (f
, (long) 0, 0);
9861 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
9863 /* Now, strictly speaking, we can't be sure that this is accurate,
9864 but the window manager will get around to dealing with the size
9865 change request eventually, and we'll hear how it went when the
9866 ConfigureNotify event gets here.
9868 We could just not bother storing any of this information here,
9869 and let the ConfigureNotify event set everything up, but that
9870 might be kind of confusing to the Lisp code, since size changes
9871 wouldn't be reported in the frame parameters until some random
9872 point in the future when the ConfigureNotify event arrives.
9874 We pass 1 for DELAY since we can't run Lisp code inside of
9876 change_frame_size (f
, rows
, cols
, 0, 1, 0);
9877 PIXEL_WIDTH (f
) = pixelwidth
;
9878 PIXEL_HEIGHT (f
) = pixelheight
;
9880 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9881 receive in the ConfigureNotify event; if we get what we asked
9882 for, then the event won't cause the screen to become garbaged, so
9883 we have to make sure to do it here. */
9884 SET_FRAME_GARBAGED (f
);
9886 XFlush (FRAME_X_DISPLAY (f
));
9888 /* If cursor was outside the new size, mark it as off. */
9889 mark_window_cursors_off (XWINDOW (f
->root_window
));
9891 /* Clear out any recollection of where the mouse highlighting was,
9892 since it might be in a place that's outside the new frame size.
9893 Actually checking whether it is outside is a pain in the neck,
9894 so don't try--just let the highlighting be done afresh with new size. */
9895 cancel_mouse_face (f
);
9900 /* Mouse warping. */
9902 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
9905 x_set_mouse_position (f
, x
, y
)
9911 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.mac
->font
) / 2;
9912 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.mac
->line_height
/ 2;
9914 if (pix_x
< 0) pix_x
= 0;
9915 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
9917 if (pix_y
< 0) pix_y
= 0;
9918 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
9920 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
9924 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
9928 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9931 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
9932 0, 0, 0, 0, pix_x
, pix_y
);
9938 /* focus shifting, raising and lowering. */
9941 x_focus_on_frame (f
)
9944 #if 0 /* This proves to be unpleasant. */
9948 /* I don't think that the ICCCM allows programs to do things like this
9949 without the interaction of the window manager. Whatever you end up
9950 doing with this code, do it to x_unfocus_frame too. */
9951 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9952 RevertToPointerRoot
, CurrentTime
);
9962 /* Raise frame F. */
9967 if (f
->async_visible
)
9968 SelectWindow (FRAME_MAC_WINDOW (f
));
9971 /* Lower frame F. */
9976 if (f
->async_visible
)
9977 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
9981 XTframe_raise_lower (f
, raise_flag
)
9991 /* Change of visibility. */
9993 /* This tries to wait until the frame is really visible.
9994 However, if the window manager asks the user where to position
9995 the frame, this will return before the user finishes doing that.
9996 The frame will not actually be visible at that time,
9997 but it will become visible later when the window manager
9998 finishes with it. */
10001 x_make_frame_visible (f
)
10005 int original_top
, original_left
;
10009 if (! FRAME_VISIBLE_P (f
))
10011 /* We test FRAME_GARBAGED_P here to make sure we don't
10012 call x_set_offset a second time
10013 if we get to x_make_frame_visible a second time
10014 before the window gets really visible. */
10015 if (! FRAME_ICONIFIED_P (f
)
10016 && ! f
->output_data
.mac
->asked_for_visible
)
10017 x_set_offset (f
, f
->output_data
.mac
->left_pos
,
10018 f
->output_data
.mac
->top_pos
, 0);
10020 f
->output_data
.mac
->asked_for_visible
= 1;
10022 ShowWindow (FRAME_MAC_WINDOW (f
));
10025 XFlush (FRAME_MAC_DISPLAY (f
));
10027 #if 0 /* MAC_TODO */
10028 /* Synchronize to ensure Emacs knows the frame is visible
10029 before we do anything else. We do this loop with input not blocked
10030 so that incoming events are handled. */
10035 /* This must come after we set COUNT. */
10038 XSETFRAME (frame
, f
);
10040 /* Wait until the frame is visible. Process X events until a
10041 MapNotify event has been seen, or until we think we won't get a
10042 MapNotify at all.. */
10043 for (count
= input_signal_count
+ 10;
10044 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
10046 /* Force processing of queued events. */
10049 /* Machines that do polling rather than SIGIO have been
10050 observed to go into a busy-wait here. So we'll fake an
10051 alarm signal to let the handler know that there's something
10052 to be read. We used to raise a real alarm, but it seems
10053 that the handler isn't always enabled here. This is
10055 if (input_polling_used ())
10057 /* It could be confusing if a real alarm arrives while
10058 processing the fake one. Turn it off and let the
10059 handler reset it. */
10060 extern void poll_for_input_1
P_ ((void));
10061 int old_poll_suppress_count
= poll_suppress_count
;
10062 poll_suppress_count
= 1;
10063 poll_for_input_1 ();
10064 poll_suppress_count
= old_poll_suppress_count
;
10067 /* See if a MapNotify event has been processed. */
10068 FRAME_SAMPLE_VISIBILITY (f
);
10071 #endif /* MAC_TODO */
10074 /* Change from mapped state to withdrawn state. */
10076 /* Make the frame visible (mapped and not iconified). */
10079 x_make_frame_invisible (f
)
10082 /* Don't keep the highlight on an invisible frame. */
10083 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
10084 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
10088 HideWindow (FRAME_MAC_WINDOW (f
));
10090 /* We can't distinguish this from iconification
10091 just by the event that we get from the server.
10092 So we can't win using the usual strategy of letting
10093 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10094 and synchronize with the server to make sure we agree. */
10096 FRAME_ICONIFIED_P (f
) = 0;
10097 f
->async_visible
= 0;
10098 f
->async_iconified
= 0;
10103 /* Change window state from mapped to iconified. */
10106 x_iconify_frame (f
)
10109 /* Don't keep the highlight on an invisible frame. */
10110 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
10111 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
10114 /* Review: Since window is still visible in dock, still allow updates? */
10115 if (f
->async_iconified
)
10121 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
10127 /* Destroy the X window of frame F. */
10130 x_destroy_window (f
)
10133 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10137 DisposeWindow (FRAME_MAC_WINDOW (f
));
10139 free_frame_menubar (f
);
10140 free_frame_faces (f
);
10142 xfree (f
->output_data
.mac
);
10143 f
->output_data
.mac
= 0;
10144 if (f
== dpyinfo
->x_focus_frame
)
10145 dpyinfo
->x_focus_frame
= 0;
10146 if (f
== dpyinfo
->x_focus_event_frame
)
10147 dpyinfo
->x_focus_event_frame
= 0;
10148 if (f
== dpyinfo
->x_highlight_frame
)
10149 dpyinfo
->x_highlight_frame
= 0;
10151 dpyinfo
->reference_count
--;
10153 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10155 dpyinfo
->mouse_face_beg_row
10156 = dpyinfo
->mouse_face_beg_col
= -1;
10157 dpyinfo
->mouse_face_end_row
10158 = dpyinfo
->mouse_face_end_col
= -1;
10159 dpyinfo
->mouse_face_window
= Qnil
;
10160 dpyinfo
->mouse_face_deferred_gc
= 0;
10161 dpyinfo
->mouse_face_mouse_frame
= 0;
10167 /* Setting window manager hints. */
10169 /* Set the normal size hints for the window manager, for frame F.
10170 FLAGS is the flags word to use--or 0 meaning preserve the flags
10171 that the window now has.
10172 If USER_POSITION is nonzero, we set the USPosition
10173 flag (this is useful when FLAGS is 0). */
10175 x_wm_set_size_hint (f
, flags
, user_position
)
10180 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10181 XSizeHints size_hints
;
10183 #ifdef USE_X_TOOLKIT
10186 Dimension widget_width
, widget_height
;
10187 Window window
= XtWindow (f
->output_data
.x
->widget
);
10188 #else /* not USE_X_TOOLKIT */
10189 Window window
= FRAME_X_WINDOW (f
);
10190 #endif /* not USE_X_TOOLKIT */
10192 /* Setting PMaxSize caused various problems. */
10193 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
10195 size_hints
.x
= f
->output_data
.x
->left_pos
;
10196 size_hints
.y
= f
->output_data
.x
->top_pos
;
10198 #ifdef USE_X_TOOLKIT
10199 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
10200 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
10201 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
10202 size_hints
.height
= widget_height
;
10203 size_hints
.width
= widget_width
;
10204 #else /* not USE_X_TOOLKIT */
10205 size_hints
.height
= PIXEL_HEIGHT (f
);
10206 size_hints
.width
= PIXEL_WIDTH (f
);
10207 #endif /* not USE_X_TOOLKIT */
10209 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
10210 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
10211 size_hints
.max_width
10212 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
10213 size_hints
.max_height
10214 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
10216 /* Calculate the base and minimum sizes.
10218 (When we use the X toolkit, we don't do it here.
10219 Instead we copy the values that the widgets are using, below.) */
10220 #ifndef USE_X_TOOLKIT
10222 int base_width
, base_height
;
10223 int min_rows
= 0, min_cols
= 0;
10225 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
10226 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
10228 check_frame_size (f
, &min_rows
, &min_cols
);
10230 /* The window manager uses the base width hints to calculate the
10231 current number of rows and columns in the frame while
10232 resizing; min_width and min_height aren't useful for this
10233 purpose, since they might not give the dimensions for a
10234 zero-row, zero-column frame.
10236 We use the base_width and base_height members if we have
10237 them; otherwise, we set the min_width and min_height members
10238 to the size for a zero x zero frame. */
10241 size_hints
.flags
|= PBaseSize
;
10242 size_hints
.base_width
= base_width
;
10243 size_hints
.base_height
= base_height
;
10244 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
10245 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
10247 size_hints
.min_width
= base_width
;
10248 size_hints
.min_height
= base_height
;
10252 /* If we don't need the old flags, we don't need the old hint at all. */
10255 size_hints
.flags
|= flags
;
10258 #endif /* not USE_X_TOOLKIT */
10261 XSizeHints hints
; /* Sometimes I hate X Windows... */
10262 long supplied_return
;
10266 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
10269 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
10272 #ifdef USE_X_TOOLKIT
10273 size_hints
.base_height
= hints
.base_height
;
10274 size_hints
.base_width
= hints
.base_width
;
10275 size_hints
.min_height
= hints
.min_height
;
10276 size_hints
.min_width
= hints
.min_width
;
10280 size_hints
.flags
|= flags
;
10285 if (hints
.flags
& PSize
)
10286 size_hints
.flags
|= PSize
;
10287 if (hints
.flags
& PPosition
)
10288 size_hints
.flags
|= PPosition
;
10289 if (hints
.flags
& USPosition
)
10290 size_hints
.flags
|= USPosition
;
10291 if (hints
.flags
& USSize
)
10292 size_hints
.flags
|= USSize
;
10296 #ifndef USE_X_TOOLKIT
10301 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
10302 size_hints
.flags
|= PWinGravity
;
10306 size_hints
.flags
&= ~ PPosition
;
10307 size_hints
.flags
|= USPosition
;
10309 #endif /* PWinGravity */
10312 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
10314 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
10316 #endif /* MAC_TODO */
10319 #if 0 /* MAC_TODO: hide application instead of iconify? */
10320 /* Used for IconicState or NormalState */
10323 x_wm_set_window_state (f
, state
)
10327 #ifdef USE_X_TOOLKIT
10330 XtSetArg (al
[0], XtNinitialState
, state
);
10331 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
10332 #else /* not USE_X_TOOLKIT */
10333 Window window
= FRAME_X_WINDOW (f
);
10335 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
10336 f
->output_data
.x
->wm_hints
.initial_state
= state
;
10338 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
10339 #endif /* not USE_X_TOOLKIT */
10343 x_wm_set_icon_pixmap (f
, pixmap_id
)
10347 Pixmap icon_pixmap
;
10349 #ifndef USE_X_TOOLKIT
10350 Window window
= FRAME_X_WINDOW (f
);
10355 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
10356 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
10360 /* It seems there is no way to turn off use of an icon pixmap.
10361 The following line does it, only if no icon has yet been created,
10362 for some window managers. But with mwm it crashes.
10363 Some people say it should clear the IconPixmapHint bit in this case,
10364 but that doesn't work, and the X consortium said it isn't the
10365 right thing at all. Since there is no way to win,
10366 best to explicitly give up. */
10368 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
10374 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10378 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
10379 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
10382 #else /* not USE_X_TOOLKIT */
10384 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
10385 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
10387 #endif /* not USE_X_TOOLKIT */
10390 #endif /* MAC_TODO */
10393 x_wm_set_icon_position (f
, icon_x
, icon_y
)
10395 int icon_x
, icon_y
;
10397 #if 0 /* MAC_TODO: no icons on Mac */
10398 #ifdef USE_X_TOOLKIT
10399 Window window
= XtWindow (f
->output_data
.x
->widget
);
10401 Window window
= FRAME_X_WINDOW (f
);
10404 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
10405 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
10406 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
10408 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
10409 #endif /* MAC_TODO */
10413 /***********************************************************************
10415 ***********************************************************************/
10417 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10420 x_get_font_info (f
, font_idx
)
10424 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
10427 /* the global font name table */
10428 char **font_name_table
= NULL
;
10429 int font_name_table_size
= 0;
10430 int font_name_count
= 0;
10432 /* compare two strings ignoring case */
10434 stricmp (const char *s
, const char *t
)
10436 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
10439 return tolower (*s
) - tolower (*t
);
10442 /* compare two strings ignoring case and handling wildcard */
10444 wildstrieq (char *s1
, char *s2
)
10446 if (strcmp (s1
, "*") == 0 || strcmp (s2
, "*") == 0)
10449 return stricmp (s1
, s2
) == 0;
10452 /* Assume parameter 1 is fully qualified, no wildcards. */
10454 mac_font_pattern_match (fontname
, pattern
)
10458 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
10459 char *font_name_copy
= (char *) alloca (strlen (fontname
) + 1);
10462 /* Copy fontname so we can modify it during comparison. */
10463 strcpy (font_name_copy
, fontname
);
10468 /* Turn pattern into a regexp and do a regexp match. */
10469 for (; *pattern
; pattern
++)
10471 if (*pattern
== '?')
10473 else if (*pattern
== '*')
10484 return (fast_c_string_match_ignore_case (build_string (regex
),
10485 font_name_copy
) >= 0);
10488 /* Two font specs are considered to match if their foundry, family,
10489 weight, slant, and charset match. */
10491 mac_font_match (char *mf
, char *xf
)
10493 char m_foundry
[50], m_family
[50], m_weight
[20], m_slant
[2], m_charset
[20];
10494 char x_foundry
[50], x_family
[50], x_weight
[20], x_slant
[2], x_charset
[20];
10496 if (sscanf (mf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10497 m_foundry
, m_family
, m_weight
, m_slant
, m_charset
) != 5)
10498 return mac_font_pattern_match (mf
, xf
);
10500 if (sscanf (xf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10501 x_foundry
, x_family
, x_weight
, x_slant
, x_charset
) != 5)
10502 return mac_font_pattern_match (mf
, xf
);
10504 return (wildstrieq (m_foundry
, x_foundry
)
10505 && wildstrieq (m_family
, x_family
)
10506 && wildstrieq (m_weight
, x_weight
)
10507 && wildstrieq (m_slant
, x_slant
)
10508 && wildstrieq (m_charset
, x_charset
))
10509 || mac_font_pattern_match (mf
, xf
);
10514 mac_to_x_fontname (char *name
, int size
, Style style
, short scriptcode
)
10516 char foundry
[32], family
[32], cs
[32];
10517 char xf
[255], *result
, *p
;
10519 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) != 3)
10521 strcpy(foundry
, "Apple");
10522 strcpy(family
, name
);
10524 switch (scriptcode
)
10526 case smTradChinese
:
10527 strcpy(cs
, "big5-0");
10529 case smSimpChinese
:
10530 strcpy(cs
, "gb2312.1980-0");
10533 strcpy(cs
, "jisx0208.1983-sjis");
10536 /* Each Apple Japanese font is entered into the font table
10537 twice: once as a jisx0208.1983-sjis font and once as a
10538 jisx0201.1976-0 font. The latter can be used to display
10539 the ascii charset and katakana-jisx0201 charset. A
10540 negative script code signals that the name of this latter
10541 font is being built. */
10542 strcpy(cs
, "jisx0201.1976-0");
10545 strcpy(cs
, "ksc5601.1989-0");
10548 strcpy(cs
, "mac-roman");
10553 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10554 foundry
, family
, style
& bold
? "bold" : "medium",
10555 style
& italic
? 'i' : 'r', size
, size
* 10, size
* 10, cs
);
10557 result
= (char *) xmalloc (strlen (xf
) + 1);
10558 strcpy (result
, xf
);
10559 for (p
= result
; *p
; p
++)
10565 /* Convert an X font spec to the corresponding mac font name, which
10566 can then be passed to GetFNum after conversion to a Pascal string.
10567 For ordinary Mac fonts, this should just be their names, like
10568 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10569 collection contain their charset designation in their names, like
10570 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10571 names are handled accordingly. */
10573 x_font_name_to_mac_font_name (char *xf
, char *mf
)
10575 char foundry
[32], family
[32], weight
[20], slant
[2], cs
[32];
10579 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10580 foundry
, family
, weight
, slant
, cs
) != 5 &&
10581 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10582 foundry
, family
, weight
, slant
, cs
) != 5)
10585 if (strcmp (cs
, "big5-0") == 0 || strcmp (cs
, "gb2312.1980-0") == 0
10586 || strcmp (cs
, "jisx0208.1983-sjis") == 0
10587 || strcmp (cs
, "jisx0201.1976-0") == 0
10588 || strcmp (cs
, "ksc5601.1989-0") == 0 || strcmp (cs
, "mac-roman") == 0)
10589 strcpy(mf
, family
);
10591 sprintf(mf
, "%s-%s-%s", foundry
, family
, cs
);
10596 add_font_name_table_entry (char *font_name
)
10598 if (font_name_table_size
== 0)
10600 font_name_table_size
= 16;
10601 font_name_table
= (char **)
10602 xmalloc (font_name_table_size
* sizeof (char *));
10604 else if (font_name_count
+ 1 >= font_name_table_size
)
10606 font_name_table_size
+= 16;
10607 font_name_table
= (char **)
10608 xrealloc (font_name_table
,
10609 font_name_table_size
* sizeof (char *));
10612 font_name_table
[font_name_count
++] = font_name
;
10615 /* Sets up the table font_name_table to contain the list of all fonts
10616 in the system the first time the table is used so that the Resource
10617 Manager need not be accessed every time this information is
10621 init_font_name_table ()
10623 #if TARGET_API_MAC_CARBON
10626 if (Gestalt (gestaltSystemVersion
, &sv
) == noErr
&& sv
>= 0x1000)
10628 FMFontFamilyIterator ffi
;
10629 FMFontFamilyInstanceIterator ffii
;
10632 /* Create a dummy instance iterator here to avoid creating and
10633 destroying it in the loop. */
10634 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
10636 /* Create an iterator to enumerate the font families. */
10637 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
10640 FMDisposeFontFamilyInstanceIterator (&ffii
);
10644 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
10652 if (FMGetFontFamilyName (ff
, name
) != noErr
)
10656 sc
= FontToScript (ff
);
10658 /* Point the instance iterator at the current font family. */
10659 if (FMResetFontFamilyInstanceIterator(ff
, &ffii
) != noErr
)
10662 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
10666 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
10668 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
10670 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
10672 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
10678 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
10680 if (smJapanese
== sc
)
10681 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
10687 /* Dispose of the iterators. */
10688 FMDisposeFontFamilyIterator (&ffi
);
10689 FMDisposeFontFamilyInstanceIterator (&ffii
);
10693 #endif /* TARGET_API_MAC_CARBON */
10695 SInt16 fontnum
, old_fontnum
;
10696 int num_mac_fonts
= CountResources('FOND');
10698 Handle font_handle
, font_handle_2
;
10699 short id
, scriptcode
;
10702 struct FontAssoc
*fat
;
10703 struct AsscEntry
*assc_entry
;
10705 GetPort (&port
); /* save the current font number used */
10706 #if TARGET_API_MAC_CARBON
10707 old_fontnum
= GetPortTextFont (port
);
10709 old_fontnum
= port
->txFont
;
10712 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
10714 font_handle
= GetIndResource ('FOND', i
);
10718 GetResInfo (font_handle
, &id
, &type
, name
);
10719 GetFNum (name
, &fontnum
);
10724 TextFont (fontnum
);
10725 scriptcode
= FontToScript (fontnum
);
10728 HLock (font_handle
);
10730 if (GetResourceSizeOnDisk (font_handle
)
10731 >= sizeof (struct FamRec
))
10733 fat
= (struct FontAssoc
*) (*font_handle
10734 + sizeof (struct FamRec
));
10736 = (struct AsscEntry
*) (*font_handle
10737 + sizeof (struct FamRec
)
10738 + sizeof (struct FontAssoc
));
10740 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
10742 if (font_name_table_size
== 0)
10744 font_name_table_size
= 16;
10745 font_name_table
= (char **)
10746 xmalloc (font_name_table_size
* sizeof (char *));
10748 else if (font_name_count
>= font_name_table_size
)
10750 font_name_table_size
+= 16;
10751 font_name_table
= (char **)
10752 xrealloc (font_name_table
,
10753 font_name_table_size
* sizeof (char *));
10755 font_name_table
[font_name_count
++]
10756 = mac_to_x_fontname (name
,
10757 assc_entry
->fontSize
,
10758 assc_entry
->fontStyle
,
10760 /* Both jisx0208.1983-sjis and
10761 jisx0201.1976-sjis parts are contained in
10762 Apple Japanese (SJIS) font. */
10763 if (smJapanese
== scriptcode
)
10765 font_name_table
[font_name_count
++]
10766 = mac_to_x_fontname (name
,
10767 assc_entry
->fontSize
,
10768 assc_entry
->fontStyle
,
10774 HUnlock (font_handle
);
10775 font_handle_2
= GetNextFOND (font_handle
);
10776 ReleaseResource (font_handle
);
10777 font_handle
= font_handle_2
;
10779 while (ResError () == noErr
&& font_handle
);
10782 TextFont (old_fontnum
);
10783 #if TARGET_API_MAC_CARBON
10785 #endif /* TARGET_API_MAC_CARBON */
10789 /* Return a list of at most MAXNAMES font specs matching the one in
10790 PATTERN. Cache matching fonts for patterns in
10791 dpyinfo->name_list_element to avoid looking them up again by
10792 calling mac_font_pattern_match (slow). */
10795 x_list_fonts (struct frame
*f
,
10796 Lisp_Object pattern
,
10801 Lisp_Object newlist
= Qnil
, tem
, key
;
10804 struct gcpro gcpro1
, gcpro2
;
10805 struct mac_display_info
*dpyinfo
= f
? FRAME_MAC_DISPLAY_INFO (f
) : NULL
;
10807 if (font_name_table
== NULL
) /* Initialize when first used. */
10808 init_font_name_table ();
10812 tem
= XCDR (dpyinfo
->name_list_element
);
10813 key
= Fcons (pattern
, make_number (maxnames
));
10815 newlist
= Fassoc (key
, tem
);
10816 if (!NILP (newlist
))
10818 newlist
= Fcdr_safe (newlist
);
10823 ptnstr
= SDATA (pattern
);
10825 GCPRO2 (pattern
, newlist
);
10827 /* Scan and matching bitmap fonts. */
10828 for (i
= 0; i
< font_name_count
; i
++)
10830 if (mac_font_pattern_match (font_name_table
[i
], ptnstr
))
10832 newlist
= Fcons (build_string (font_name_table
[i
]), newlist
);
10835 if (n_fonts
>= maxnames
)
10840 /* MAC_TODO: add code for matching outline fonts here */
10846 XSETCDR (dpyinfo
->name_list_element
,
10847 Fcons (Fcons (key
, newlist
),
10848 XCDR (dpyinfo
->name_list_element
)));
10858 /* Check that FONT is valid on frame F. It is if it can be found in F's
10862 x_check_font (f
, font
)
10867 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10869 xassert (font
!= NULL
);
10871 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10872 if (dpyinfo
->font_table
[i
].name
10873 && font
== dpyinfo
->font_table
[i
].font
)
10876 xassert (i
< dpyinfo
->n_fonts
);
10879 #endif /* GLYPH_DEBUG != 0 */
10881 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10882 Note: There are (broken) X fonts out there with invalid XFontStruct
10883 min_bounds contents. For example, handa@etl.go.jp reports that
10884 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10885 have font->min_bounds.width == 0. */
10888 x_font_min_bounds (font
, w
, h
)
10889 MacFontStruct
*font
;
10893 * TODO: Windows does not appear to offer min bound, only
10894 * average and maximum width, and maximum height.
10896 *h
= FONT_HEIGHT (font
);
10897 *w
= FONT_WIDTH (font
);
10901 /* Compute the smallest character width and smallest font height over
10902 all fonts available on frame F. Set the members smallest_char_width
10903 and smallest_font_height in F's x_display_info structure to
10904 the values computed. Value is non-zero if smallest_font_height or
10905 smallest_char_width become smaller than they were before. */
10908 x_compute_min_glyph_bounds (f
)
10912 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
10913 MacFontStruct
*font
;
10914 int old_width
= dpyinfo
->smallest_char_width
;
10915 int old_height
= dpyinfo
->smallest_font_height
;
10917 dpyinfo
->smallest_font_height
= 100000;
10918 dpyinfo
->smallest_char_width
= 100000;
10920 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
10921 if (dpyinfo
->font_table
[i
].name
)
10923 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
10926 font
= (MacFontStruct
*) fontp
->font
;
10927 xassert (font
!= (MacFontStruct
*) ~0);
10928 x_font_min_bounds (font
, &w
, &h
);
10930 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
10931 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
10934 xassert (dpyinfo
->smallest_char_width
> 0
10935 && dpyinfo
->smallest_font_height
> 0);
10937 return (dpyinfo
->n_fonts
== 1
10938 || dpyinfo
->smallest_char_width
< old_width
10939 || dpyinfo
->smallest_font_height
< old_height
);
10943 /* Determine whether given string is a fully-specified XLFD: all 14
10944 fields are present, none is '*'. */
10947 is_fully_specified_xlfd (char *p
)
10955 for (i
= 0; i
< 13; i
++)
10957 q
= strchr (p
+ 1, '-');
10960 if (q
- p
== 2 && *(p
+ 1) == '*')
10965 if (strchr (p
+ 1, '-') != NULL
)
10968 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
10975 const int kDefaultFontSize
= 9;
10978 /* XLoadQueryFont creates and returns an internal representation for a
10979 font in a MacFontStruct struct. There is really no concept
10980 corresponding to "loading" a font on the Mac. But we check its
10981 existence and find the font number and all other information for it
10982 and store them in the returned MacFontStruct. */
10984 static MacFontStruct
*
10985 XLoadQueryFont (Display
*dpy
, char *fontname
)
10987 int i
, size
, is_two_byte_font
, char_width
;
10990 SInt16 old_fontnum
, old_fontsize
;
10991 Style old_fontface
;
10994 Style fontface
= normal
;
10995 MacFontStruct
*font
;
10996 FontInfo the_fontinfo
;
10997 char s_weight
[7], c_slant
;
10999 if (is_fully_specified_xlfd (fontname
))
11003 for (i
= 0; i
< font_name_count
; i
++)
11004 if (mac_font_pattern_match (font_name_table
[i
], fontname
))
11007 if (i
>= font_name_count
)
11010 name
= font_name_table
[i
];
11013 GetPort (&port
); /* save the current font number used */
11014 #if TARGET_API_MAC_CARBON
11015 old_fontnum
= GetPortTextFont (port
);
11016 old_fontsize
= GetPortTextSize (port
);
11017 old_fontface
= GetPortTextFace (port
);
11019 old_fontnum
= port
->txFont
;
11020 old_fontsize
= port
->txSize
;
11021 old_fontface
= port
->txFace
;
11024 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size
) != 1)
11025 size
= kDefaultFontSize
;
11027 if (sscanf (name
, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight
) == 1)
11028 if (strcmp (s_weight
, "bold") == 0)
11031 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant
) == 1)
11032 if (c_slant
== 'i')
11033 fontface
|= italic
;
11035 x_font_name_to_mac_font_name (name
, mfontname
);
11036 c2pstr (mfontname
);
11037 GetFNum (mfontname
, &fontnum
);
11041 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
11043 font
->fontname
= (char *) xmalloc (strlen (name
) + 1);
11044 bcopy (name
, font
->fontname
, strlen (name
) + 1);
11046 font
->mac_fontnum
= fontnum
;
11047 font
->mac_fontsize
= size
;
11048 font
->mac_fontface
= fontface
;
11049 font
->mac_scriptcode
= FontToScript (fontnum
);
11051 /* Apple Japanese (SJIS) font is listed as both
11052 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
11053 (Roman script) in init_font_name_table (). The latter should be
11054 treated as a one-byte font. */
11059 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11061 && 0 == strcmp (cs
, "jisx0201.1976-0"))
11062 font
->mac_scriptcode
= smRoman
;
11065 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
11066 font
->mac_scriptcode
== smTradChinese
||
11067 font
->mac_scriptcode
== smSimpChinese
||
11068 font
->mac_scriptcode
== smKorean
;
11070 TextFont (fontnum
);
11072 TextFace (fontface
);
11074 GetFontInfo (&the_fontinfo
);
11076 font
->ascent
= the_fontinfo
.ascent
;
11077 font
->descent
= the_fontinfo
.descent
;
11079 font
->min_byte1
= 0;
11080 if (is_two_byte_font
)
11081 font
->max_byte1
= 1;
11083 font
->max_byte1
= 0;
11084 font
->min_char_or_byte2
= 0x20;
11085 font
->max_char_or_byte2
= 0xff;
11087 if (is_two_byte_font
)
11089 /* Use the width of an "ideographic space" of that font because
11090 the_fontinfo.widMax returns the wrong width for some fonts. */
11091 switch (font
->mac_scriptcode
)
11094 char_width
= StringWidth("\p\x81\x40");
11096 case smTradChinese
:
11097 char_width
= StringWidth("\p\xa1\x40");
11099 case smSimpChinese
:
11100 char_width
= StringWidth("\p\xa1\xa1");
11103 char_width
= StringWidth("\p\xa1\xa1");
11108 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11109 returns 15 for 12-point Monaco! */
11110 char_width
= CharWidth ('m');
11112 font
->max_bounds
.rbearing
= char_width
;
11113 font
->max_bounds
.lbearing
= 0;
11114 font
->max_bounds
.width
= char_width
;
11115 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
11116 font
->max_bounds
.descent
= the_fontinfo
.descent
;
11118 font
->min_bounds
= font
->max_bounds
;
11120 if (is_two_byte_font
|| CharWidth ('m') == CharWidth ('i'))
11121 font
->per_char
= NULL
;
11124 font
->per_char
= (XCharStruct
*)
11125 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
11129 for (c
= 0x20; c
<= 0xff; c
++)
11131 font
->per_char
[c
- 0x20] = font
->max_bounds
;
11132 font
->per_char
[c
- 0x20].width
= CharWidth (c
);
11137 TextFont (old_fontnum
); /* restore previous font number, size and face */
11138 TextSize (old_fontsize
);
11139 TextFace (old_fontface
);
11145 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11146 pointer to the structure font_info while allocating it dynamically.
11147 If SIZE is 0, load any size of font.
11148 If loading is failed, return NULL. */
11151 x_load_font (f
, fontname
, size
)
11153 register char *fontname
;
11156 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
11157 Lisp_Object font_names
;
11159 /* Get a list of all the fonts that match this name. Once we
11160 have a list of matching fonts, we compare them against the fonts
11161 we already have by comparing names. */
11162 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
11164 if (!NILP (font_names
))
11169 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11170 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
11171 if (dpyinfo
->font_table
[i
].name
11172 && (!strcmp (dpyinfo
->font_table
[i
].name
,
11173 SDATA (XCAR (tail
)))
11174 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
11175 SDATA (XCAR (tail
)))))
11176 return (dpyinfo
->font_table
+ i
);
11179 /* Load the font and add it to the table. */
11182 struct MacFontStruct
*font
;
11183 struct font_info
*fontp
;
11184 unsigned long value
;
11187 /* If we have found fonts by x_list_font, load one of them. If
11188 not, we still try to load a font by the name given as FONTNAME
11189 because XListFonts (called in x_list_font) of some X server has
11190 a bug of not finding a font even if the font surely exists and
11191 is loadable by XLoadQueryFont. */
11192 if (size
> 0 && !NILP (font_names
))
11193 fontname
= (char *) SDATA (XCAR (font_names
));
11195 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
11199 /* Find a free slot in the font table. */
11200 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
11201 if (dpyinfo
->font_table
[i
].name
== NULL
)
11204 /* If no free slot found, maybe enlarge the font table. */
11205 if (i
== dpyinfo
->n_fonts
11206 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
11209 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
11210 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
11211 dpyinfo
->font_table
11212 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
11215 fontp
= dpyinfo
->font_table
+ i
;
11216 if (i
== dpyinfo
->n_fonts
)
11217 ++dpyinfo
->n_fonts
;
11219 /* Now fill in the slots of *FONTP. */
11221 fontp
->font
= font
;
11222 fontp
->font_idx
= i
;
11223 fontp
->name
= (char *) xmalloc (strlen (font
->fontname
) + 1);
11224 bcopy (font
->fontname
, fontp
->name
, strlen (font
->fontname
) + 1);
11226 fontp
->full_name
= fontp
->name
;
11228 fontp
->size
= font
->max_bounds
.width
;
11229 fontp
->height
= FONT_HEIGHT (font
);
11231 /* For some font, ascent and descent in max_bounds field is
11232 larger than the above value. */
11233 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
11234 if (max_height
> fontp
->height
)
11235 fontp
->height
= max_height
;
11238 /* The slot `encoding' specifies how to map a character
11239 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11240 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11241 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11242 2:0xA020..0xFF7F). For the moment, we don't know which charset
11243 uses this font. So, we set information in fontp->encoding[1]
11244 which is never used by any charset. If mapping can't be
11245 decided, set FONT_ENCODING_NOT_DECIDED. */
11246 if (font
->mac_scriptcode
== smJapanese
)
11247 fontp
->encoding
[1] = 4;
11251 = (font
->max_byte1
== 0
11253 ? (font
->min_char_or_byte2
< 0x80
11254 ? (font
->max_char_or_byte2
< 0x80
11255 ? 0 /* 0x20..0x7F */
11256 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
11257 : 1) /* 0xA0..0xFF */
11259 : (font
->min_byte1
< 0x80
11260 ? (font
->max_byte1
< 0x80
11261 ? (font
->min_char_or_byte2
< 0x80
11262 ? (font
->max_char_or_byte2
< 0x80
11263 ? 0 /* 0x2020..0x7F7F */
11264 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
11265 : 3) /* 0x20A0..0x7FFF */
11266 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
11267 : (font
->min_char_or_byte2
< 0x80
11268 ? (font
->max_char_or_byte2
< 0x80
11269 ? 2 /* 0xA020..0xFF7F */
11270 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
11271 : 1))); /* 0xA0A0..0xFFFF */
11274 #if 0 /* MAC_TODO: fill these out with more reasonably values */
11275 fontp
->baseline_offset
11276 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
11277 ? (long) value
: 0);
11278 fontp
->relative_compose
11279 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
11280 ? (long) value
: 0);
11281 fontp
->default_ascent
11282 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
11283 ? (long) value
: 0);
11285 fontp
->baseline_offset
= 0;
11286 fontp
->relative_compose
= 0;
11287 fontp
->default_ascent
= 0;
11290 /* Set global flag fonts_changed_p to non-zero if the font loaded
11291 has a character with a smaller width than any other character
11292 before, or if the font loaded has a smalle>r height than any
11293 other font loaded before. If this happens, it will make a
11294 glyph matrix reallocation necessary. */
11295 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
11302 /* Return a pointer to struct font_info of a font named FONTNAME for
11303 frame F. If no such font is loaded, return NULL. */
11306 x_query_font (f
, fontname
)
11308 register char *fontname
;
11310 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
11313 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11314 if (dpyinfo
->font_table
[i
].name
11315 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
11316 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
11317 return (dpyinfo
->font_table
+ i
);
11322 /* Find a CCL program for a font specified by FONTP, and set the member
11323 `encoder' of the structure. */
11326 x_find_ccl_program (fontp
)
11327 struct font_info
*fontp
;
11329 Lisp_Object list
, elt
;
11331 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
11335 && STRINGP (XCAR (elt
))
11336 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
11342 struct ccl_program
*ccl
11343 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
11345 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
11348 fontp
->font_encoder
= ccl
;
11354 /***********************************************************************
11356 ***********************************************************************/
11358 #ifdef USE_X_TOOLKIT
11359 static XrmOptionDescRec emacs_options
[] = {
11360 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
11361 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
11363 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11364 XrmoptionSepArg
, NULL
},
11365 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
11367 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
11368 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
11369 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
11370 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
11371 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
11372 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
11373 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
11375 #endif /* USE_X_TOOLKIT */
11377 static int x_initialized
;
11379 #ifdef MULTI_KBOARD
11380 /* Test whether two display-name strings agree up to the dot that separates
11381 the screen number from the server number. */
11383 same_x_server (name1
, name2
)
11384 char *name1
, *name2
;
11386 int seen_colon
= 0;
11387 unsigned char *system_name
= SDATA (Vsystem_name
);
11388 int system_name_length
= strlen (system_name
);
11389 int length_until_period
= 0;
11391 while (system_name
[length_until_period
] != 0
11392 && system_name
[length_until_period
] != '.')
11393 length_until_period
++;
11395 /* Treat `unix' like an empty host name. */
11396 if (! strncmp (name1
, "unix:", 5))
11398 if (! strncmp (name2
, "unix:", 5))
11400 /* Treat this host's name like an empty host name. */
11401 if (! strncmp (name1
, system_name
, system_name_length
)
11402 && name1
[system_name_length
] == ':')
11403 name1
+= system_name_length
;
11404 if (! strncmp (name2
, system_name
, system_name_length
)
11405 && name2
[system_name_length
] == ':')
11406 name2
+= system_name_length
;
11407 /* Treat this host's domainless name like an empty host name. */
11408 if (! strncmp (name1
, system_name
, length_until_period
)
11409 && name1
[length_until_period
] == ':')
11410 name1
+= length_until_period
;
11411 if (! strncmp (name2
, system_name
, length_until_period
)
11412 && name2
[length_until_period
] == ':')
11413 name2
+= length_until_period
;
11415 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
11419 if (seen_colon
&& *name1
== '.')
11423 && (*name1
== '.' || *name1
== '\0')
11424 && (*name2
== '.' || *name2
== '\0'));
11429 /* The Mac Event loop code */
11432 #include <Events.h>
11433 #include <Quickdraw.h>
11434 #include <Balloons.h>
11435 #include <Devices.h>
11437 #include <Gestalt.h>
11439 #include <Processes.h>
11441 #include <ToolUtils.h>
11442 #include <TextUtils.h>
11443 #include <Dialogs.h>
11444 #include <Script.h>
11446 #include <TextEncodingConverter.h>
11447 #include <Resources.h>
11452 #endif /* ! MAC_OSX */
11454 #define M_APPLE 128
11457 #define WINDOW_RESOURCE 128
11458 #define TERM_WINDOW_RESOURCE 129
11460 #define DEFAULT_NUM_COLS 80
11462 #define MIN_DOC_SIZE 64
11463 #define MAX_DOC_SIZE 32767
11465 /* sleep time for WaitNextEvent */
11466 #define WNE_SLEEP_AT_SUSPEND 10
11467 #define WNE_SLEEP_AT_RESUME 1
11469 /* true when cannot handle any Mac OS events */
11470 static int handling_window_update
= 0;
11472 /* the flag appl_is_suspended is used both for determining the sleep
11473 time to be passed to WaitNextEvent and whether the cursor should be
11474 drawn when updating the display. The cursor is turned off when
11475 Emacs is suspended. Redrawing it is unnecessary and what needs to
11476 be done depends on whether the cursor lies inside or outside the
11477 redraw region. So we might as well skip drawing it when Emacs is
11479 static Boolean app_is_suspended
= false;
11480 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
11482 #define EXTRA_STACK_ALLOC (256 * 1024)
11484 #define ARGV_STRING_LIST_ID 129
11485 #define ABOUT_ALERT_ID 128
11486 #define RAM_TOO_LARGE_ALERT_ID 129
11488 Boolean terminate_flag
= false;
11490 /* True if using command key as meta key. */
11491 Lisp_Object Vmac_command_key_is_meta
;
11493 /* True if the ctrl and meta keys should be reversed. */
11494 Lisp_Object Vmac_reverse_ctrl_meta
;
11496 #if USE_CARBON_EVENTS
11497 /* True if the mouse wheel button (i.e. button 4) should map to
11498 mouse-2, instead of mouse-3. */
11499 Lisp_Object Vmac_wheel_button_is_mouse_2
;
11502 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11503 to this text encoding */
11504 int mac_keyboard_text_encoding
;
11505 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
11507 /* Set in term/mac-win.el to indicate that event loop can now generate
11508 drag and drop events. */
11509 Lisp_Object Qmac_ready_for_drag_n_drop
;
11511 Lisp_Object drag_and_drop_file_list
;
11513 Point saved_menu_event_location
;
11516 static void init_required_apple_events (void);
11517 static pascal OSErr
11518 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
11519 static pascal OSErr
11520 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
11521 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
11522 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
11524 /* Drag and Drop */
11525 static OSErr
init_mac_drag_n_drop ();
11526 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
11528 #if USE_CARBON_EVENTS
11529 /* Preliminary Support for the OSX Services Menu */
11530 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
11531 static void init_service_handler ();
11534 extern void init_emacs_passwd_dir ();
11535 extern int emacs_main (int, char **, char **);
11536 extern void check_alarm ();
11538 extern void initialize_applescript();
11539 extern void terminate_applescript();
11541 static unsigned int
11542 #if USE_CARBON_EVENTS
11543 mac_to_emacs_modifiers (UInt32 mods
)
11545 mac_to_emacs_modifiers (EventModifiers mods
)
11548 unsigned int result
= 0;
11549 if (mods
& macShiftKey
)
11550 result
|= shift_modifier
;
11551 if (mods
& macCtrlKey
)
11552 result
|= ctrl_modifier
;
11553 if (mods
& macMetaKey
)
11554 result
|= meta_modifier
;
11555 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
11556 result
|= alt_modifier
;
11560 #if USE_CARBON_EVENTS
11561 /* Obtains the event modifiers from the event ref and then calls
11562 mac_to_emacs_modifiers. */
11564 mac_event_to_emacs_modifiers (EventRef eventRef
)
11567 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
11568 sizeof (UInt32
), NULL
, &mods
);
11569 return mac_to_emacs_modifiers (mods
);
11572 /* Given an event ref, return the code to use for the mouse button
11573 code in the emacs input_event. */
11575 mac_get_mouse_btn (EventRef ref
)
11577 EventMouseButton result
= kEventMouseButtonPrimary
;
11578 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
11579 sizeof (EventMouseButton
), NULL
, &result
);
11582 case kEventMouseButtonPrimary
:
11584 case kEventMouseButtonSecondary
:
11585 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
11586 case kEventMouseButtonTertiary
:
11587 case 4: /* 4 is the number for the mouse wheel button */
11588 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
11594 /* Normally, ConvertEventRefToEventRecord will correctly handle all
11595 events. However the click of the mouse wheel is not converted to a
11596 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11597 checks to see if it is a mouse up or down carbon event that has not
11598 been converted, and if so, converts it by hand (to be picked up in
11599 the XTread_socket loop). */
11600 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
11602 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
11603 /* Do special case for mouse wheel button. */
11604 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
11606 UInt32 kind
= GetEventKind (eventRef
);
11607 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
11609 eventRec
->what
= mouseDown
;
11612 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
11614 eventRec
->what
= mouseUp
;
11619 /* Need where and when. */
11621 GetEventParameter (eventRef
, kEventParamMouseLocation
,
11622 typeQDPoint
, NULL
, sizeof (Point
),
11623 NULL
, &eventRec
->where
);
11624 /* Use two step process because new event modifiers are
11625 32-bit and old are 16-bit. Currently, only loss is
11627 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
11628 typeUInt32
, NULL
, sizeof (UInt32
),
11630 eventRec
->modifiers
= mods
;
11632 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
11641 do_get_menus (void)
11643 Handle menubar_handle
;
11644 MenuHandle menu_handle
;
11646 menubar_handle
= GetNewMBar (128);
11647 if(menubar_handle
== NULL
)
11649 SetMenuBar (menubar_handle
);
11652 menu_handle
= GetMenuHandle (M_APPLE
);
11653 if(menu_handle
!= NULL
)
11654 AppendResMenu (menu_handle
,'DRVR');
11661 do_init_managers (void)
11663 #if !TARGET_API_MAC_CARBON
11664 InitGraf (&qd
.thePort
);
11666 FlushEvents (everyEvent
, 0);
11670 InitDialogs (NULL
);
11671 #endif /* !TARGET_API_MAC_CARBON */
11674 #if !TARGET_API_MAC_CARBON
11675 /* set up some extra stack space for use by emacs */
11676 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
11678 /* MaxApplZone must be called for AppleScript to execute more
11679 complicated scripts */
11682 #endif /* !TARGET_API_MAC_CARBON */
11686 do_check_ram_size (void)
11688 SInt32 physical_ram_size
, logical_ram_size
;
11690 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
11691 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
11692 || physical_ram_size
> 256 * 1024 * 1024
11693 || logical_ram_size
> 256 * 1024 * 1024)
11695 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
11701 do_window_update (WindowPtr win
)
11703 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (win
);
11704 struct frame
*f
= mwp
->mFP
;
11708 if (f
->async_visible
== 0)
11710 f
->async_visible
= 1;
11711 f
->async_iconified
= 0;
11712 SET_FRAME_GARBAGED (f
);
11714 /* An update event is equivalent to MapNotify on X, so report
11715 visibility changes properly. */
11716 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
11717 /* Force a redisplay sooner or later to update the
11718 frame titles in case this is the second frame. */
11719 record_asynch_buffer_change ();
11724 handling_window_update
= 1;
11726 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
11728 expose_frame (f
, 0, 0, 0, 0);
11730 handling_window_update
= 0;
11737 is_emacs_window (WindowPtr win
)
11739 Lisp_Object tail
, frame
;
11744 FOR_EACH_FRAME (tail
, frame
)
11745 if (FRAME_MAC_P (XFRAME (frame
)))
11746 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
11753 do_window_activate (WindowPtr win
)
11758 if (is_emacs_window (win
))
11760 mwp
= (mac_output
*) GetWRefCon (win
);
11765 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
11766 activate_scroll_bars (f
);
11772 do_window_deactivate (WindowPtr win
)
11777 if (is_emacs_window (win
))
11779 mwp
= (mac_output
*) GetWRefCon (win
);
11782 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
11784 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
11785 deactivate_scroll_bars (f
);
11797 wp
= FrontWindow();
11798 if (is_emacs_window (wp
))
11800 mwp
= (mac_output
*) GetWRefCon (wp
);
11805 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
11806 activate_scroll_bars (f
);
11810 app_is_suspended
= false;
11811 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
11821 wp
= FrontWindow();
11822 if (is_emacs_window (wp
))
11824 mwp
= (mac_output
*) GetWRefCon (wp
);
11827 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
11829 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
11830 deactivate_scroll_bars (f
);
11834 app_is_suspended
= true;
11835 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
11840 do_mouse_moved (Point mouse_pos
)
11842 WindowPtr wp
= FrontWindow ();
11843 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
11845 #if TARGET_API_MAC_CARBON
11846 SetPort (GetWindowPort (wp
));
11851 GlobalToLocal (&mouse_pos
);
11853 note_mouse_movement (f
, &mouse_pos
);
11858 do_os_event (EventRecord
*erp
)
11860 switch((erp
->message
>> 24) & 0x000000FF)
11862 case suspendResumeMessage
:
11863 if((erp
->message
& resumeFlag
) == 1)
11869 case mouseMovedMessage
:
11870 do_mouse_moved (erp
->where
);
11876 do_events (EventRecord
*erp
)
11881 do_window_update ((WindowPtr
) erp
->message
);
11889 if ((erp
->modifiers
& activeFlag
) != 0)
11890 do_window_activate ((WindowPtr
) erp
->message
);
11892 do_window_deactivate ((WindowPtr
) erp
->message
);
11898 do_apple_menu (SInt16 menu_item
)
11900 #if !TARGET_API_MAC_CARBON
11902 SInt16 da_driver_refnum
;
11904 if (menu_item
== I_ABOUT
)
11905 NoteAlert (ABOUT_ALERT_ID
, NULL
);
11908 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
11909 da_driver_refnum
= OpenDeskAcc (item_name
);
11911 #endif /* !TARGET_API_MAC_CARBON */
11915 do_menu_choice (SInt32 menu_choice
)
11917 SInt16 menu_id
, menu_item
;
11919 menu_id
= HiWord (menu_choice
);
11920 menu_item
= LoWord (menu_choice
);
11928 do_apple_menu (menu_item
);
11933 WindowPtr wp
= FrontWindow ();
11934 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
11935 MenuHandle menu
= GetMenuHandle (menu_id
);
11940 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
11941 menubar_selection_callback (f
, refcon
);
11950 /* Handle drags in size box. Based on code contributed by Ben
11951 Mesander and IM - Window Manager A. */
11954 do_grow_window (WindowPtr w
, EventRecord
*e
)
11959 mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
11960 struct frame
*f
= mwp
->mFP
;
11962 SetRect(&limit_rect
, MIN_DOC_SIZE
, MIN_DOC_SIZE
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
11964 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
11966 /* see if it really changed size */
11967 if (grow_size
!= 0)
11969 rows
= PIXEL_TO_CHAR_HEIGHT (f
, HiWord (grow_size
));
11970 columns
= PIXEL_TO_CHAR_WIDTH (f
, LoWord (grow_size
));
11972 x_set_window_size (f
, 0, columns
, rows
);
11977 /* Handle clicks in zoom box. Calculation of "standard state" based
11978 on code in IM - Window Manager A and code contributed by Ben
11979 Mesander. The standard state of an Emacs window is 80-characters
11980 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11983 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
11986 Rect zoom_rect
, port_rect
;
11988 int w_title_height
, columns
, rows
, width
, height
, dummy
, x
, y
;
11989 mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
11990 struct frame
*f
= mwp
->mFP
;
11992 GetPort (&save_port
);
11994 #if TARGET_API_MAC_CARBON
11995 SetPort (GetWindowPort (w
));
12000 /* Clear window to avoid flicker. */
12001 #if TARGET_API_MAC_CARBON
12006 GetWindowPortBounds (w
, &r
);
12009 if (zoom_in_or_out
== inZoomOut
)
12011 /* calculate height of window's title bar (hard card it for now). */
12012 w_title_height
= 20 + GetMBarHeight ();
12014 /* get maximum height of window into zoom_rect.bottom -
12016 GetQDGlobalsScreenBits (&bm
);
12017 zoom_rect
= bm
.bounds
;
12018 zoom_rect
.top
+= w_title_height
;
12019 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
12021 zoom_rect
.right
= zoom_rect
.left
12022 + CHAR_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
12024 SetWindowStandardState (w
, &zoom_rect
);
12027 #else /* not TARGET_API_MAC_CARBON */
12028 EraseRect (&(w
->portRect
));
12029 if (zoom_in_or_out
== inZoomOut
)
12031 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
12032 LocalToGlobal (&top_left
);
12034 /* calculate height of window's title bar */
12035 w_title_height
= top_left
.v
- 1
12036 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
12038 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
12039 zoom_rect
= qd
.screenBits
.bounds
;
12040 zoom_rect
.top
+= w_title_height
;
12041 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
12043 zoom_rect
.right
= zoom_rect
.left
12044 + CHAR_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
12046 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
12049 #endif /* not TARGET_API_MAC_CARBON */
12051 ZoomWindow (w
, zoom_in_or_out
, w
== FrontWindow ());
12053 /* retrieve window size and update application values */
12054 #if TARGET_API_MAC_CARBON
12055 GetWindowPortBounds (w
, &port_rect
);
12057 port_rect
= w
->portRect
;
12059 rows
= PIXEL_TO_CHAR_HEIGHT (f
, port_rect
.bottom
- port_rect
.top
);
12060 columns
= PIXEL_TO_CHAR_WIDTH (f
, port_rect
.right
- port_rect
.left
);
12061 x_set_window_size (mwp
->mFP
, 0, columns
, rows
);
12063 SetPort (save_port
);
12066 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
12068 init_mac_drag_n_drop ()
12070 OSErr result
= InstallReceiveHandler (mac_do_receive_drag
, 0L, NULL
);
12074 /* Intialize AppleEvent dispatcher table for the required events. */
12076 init_required_apple_events ()
12081 /* Make sure we have apple events before starting. */
12082 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
12086 if (!(result
& (1 << gestaltAppleEventsPresent
)))
12089 #if TARGET_API_MAC_CARBON
12090 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
12091 NewAEEventHandlerUPP
12092 ((AEEventHandlerProcPtr
) do_ae_open_application
),
12095 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
12096 NewAEEventHandlerProc
12097 ((AEEventHandlerProcPtr
) do_ae_open_application
),
12103 #if TARGET_API_MAC_CARBON
12104 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
12105 NewAEEventHandlerUPP
12106 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
12109 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
12110 NewAEEventHandlerProc
12111 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
12117 #if TARGET_API_MAC_CARBON
12118 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
12119 NewAEEventHandlerUPP
12120 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
12123 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
12124 NewAEEventHandlerProc
12125 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
12131 #if TARGET_API_MAC_CARBON
12132 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
12133 NewAEEventHandlerUPP
12134 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
12137 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
12138 NewAEEventHandlerProc
12139 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
12146 #if USE_CARBON_EVENTS
12148 void init_service_handler()
12150 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
12151 {kEventClassService
, kEventServiceCopy
},
12152 {kEventClassService
, kEventServicePaste
}};
12153 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
12154 3, specs
, NULL
, NULL
);
12158 MAC_TODO: Check to see if this is called by AEProcessDesc...
12160 OSStatus
mac_handle_service_event (EventHandlerCallRef callRef
,
12161 EventRef event
, void *data
)
12163 OSStatus err
= noErr
;
12164 switch (GetEventKind (event
))
12166 case kEventServiceGetTypes
:
12168 CFMutableArrayRef copyTypes
, pasteTypes
;
12170 Boolean selection
= true;
12172 GetEventParameter(event, kEventParamServicePasteTypes,
12173 typeCFMutableArrayRef, NULL,
12174 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
12176 GetEventParameter(event
, kEventParamServiceCopyTypes
,
12177 typeCFMutableArrayRef
, NULL
,
12178 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
12179 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
12181 CFArrayAppendValue (copyTypes
, type
);
12182 //CFArrayAppendValue (pasteTypes, type);
12186 case kEventServiceCopy
:
12188 ScrapRef currentScrap
, specificScrap
;
12190 Size byteCount
= 0;
12192 GetCurrentScrap (¤tScrap
);
12194 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
12197 void *buffer
= xmalloc (byteCount
);
12198 if (buffer
!= NULL
)
12200 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
12201 sizeof (ScrapRef
), NULL
, &specificScrap
);
12203 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
12204 &byteCount
, buffer
);
12206 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
12207 kScrapFlavorMaskNone
, byteCount
, buffer
);
12213 case kEventServicePaste
:
12216 // Get the current location
12218 ScrapRef specificScrap;
12219 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
12220 sizeof(ScrapRef), NULL, &specificScrap);
12221 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
12222 if (err == noErr) {
12223 void * buffer = xmalloc(byteCount);
12224 if (buffer != NULL ) {
12225 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
12226 &byteCount, buffer);
12227 if (err == noErr) {
12228 // Actually place in the buffer
12230 // Get the current "selection" string here
12243 /* Open Application Apple Event */
12244 static pascal OSErr
12245 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
12251 /* Defined in mac.c. */
12253 path_from_vol_dir_name (char *, int, short, long, char *);
12256 /* Called when we receive an AppleEvent with an ID of
12257 "kAEOpenDocuments". This routine gets the direct parameter,
12258 extracts the FSSpecs in it, and puts their names on a list. */
12259 static pascal OSErr
12260 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
12265 DescType actual_type
;
12268 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
12270 goto descriptor_error_exit
;
12272 /* Check to see that we got all of the required parameters from the
12273 event descriptor. For an 'odoc' event this should just be the
12275 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
12276 &actual_type
, (Ptr
) &keyword
,
12277 sizeof (keyword
), &actual_size
);
12278 /* No error means that we found some unused parameters.
12279 errAEDescNotFound means that there are no more parameters. If we
12280 get an error code other than that, flag it. */
12281 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
12283 err
= errAEEventNotHandled
;
12288 /* Got all the parameters we need. Now, go through the direct
12289 object list and parse it up. */
12291 long num_files_to_open
;
12293 err
= AECountItems (&the_desc
, &num_files_to_open
);
12298 /* AE file list is one based so just use that for indexing here. */
12299 for (i
= 1; (err
== noErr
) && (i
<= num_files_to_open
); i
++)
12302 Str255 path_name
, unix_path_name
;
12307 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
12308 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
12309 if (err
!= noErr
) break;
12312 err
= FSpMakeFSRef (&fs
, &fref
);
12313 if (err
!= noErr
) break;
12315 if (FSRefMakePath (&fref
, unix_path_name
, 255) == noErr
)
12317 if (path_from_vol_dir_name (path_name
, 255, fs
.vRefNum
, fs
.parID
,
12319 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
12321 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
12322 drag_and_drop_file_list
);
12328 /* Nuke the coerced file list in any case */
12329 err2
= AEDisposeDesc(&the_desc
);
12331 descriptor_error_exit
:
12332 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12337 static pascal OSErr
mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
12338 DragReference theDrag
)
12342 FlavorFlags theFlags
;
12345 ItemReference theItem
;
12348 Size size
= sizeof (HFSFlavor
);
12350 drag_and_drop_file_list
= Qnil
;
12351 GetDragMouse (theDrag
, &mouse
, 0L);
12352 CountDragItems (theDrag
, &items
);
12353 for (index
= 1; index
<= items
; index
++)
12355 /* Only handle file references. */
12356 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
12357 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
12358 if (result
== noErr
)
12365 Str255 unix_path_name
;
12366 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
12368 /* Use Carbon routines, otherwise it converts the file name
12369 to /Macintosh HD/..., which is not correct. */
12370 FSpMakeFSRef (&data
.fileSpec
, &fref
);
12371 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
12373 if (path_from_vol_dir_name (path_name
, 255, data
.fileSpec
.vRefNum
,
12374 data
.fileSpec
.parID
, data
.fileSpec
.name
) &&
12375 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
12377 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
12378 drag_and_drop_file_list
);
12383 /* If there are items in the list, construct an event and post it to
12384 the queue like an interrupt using kbd_buffer_store_event. */
12385 if (!NILP (drag_and_drop_file_list
))
12387 struct input_event event
;
12389 struct frame
*f
= ((mac_output
*) GetWRefCon(window
))->mFP
;
12390 SetPort (GetWindowPort (window
));
12391 GlobalToLocal (&mouse
);
12393 event
.kind
= DRAG_N_DROP_EVENT
;
12395 event
.modifiers
= 0;
12396 event
.timestamp
= TickCount () * (1000 / 60);
12397 XSETINT (event
.x
, mouse
.h
);
12398 XSETINT (event
.y
, mouse
.v
);
12399 XSETFRAME (frame
, f
);
12400 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
12402 /* Post to the interrupt queue */
12403 kbd_buffer_store_event (&event
);
12404 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12406 ProcessSerialNumber psn
;
12407 GetCurrentProcess (&psn
);
12408 SetFrontProcess (&psn
);
12414 /* Print Document Apple Event */
12415 static pascal OSErr
12416 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
12418 return errAEEventNotHandled
;
12422 static pascal OSErr
12423 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
12425 /* FixMe: Do we need an unwind-protect or something here? And what
12426 do we do about unsaved files. Currently just forces quit rather
12427 than doing recursive callback to get user input. */
12429 terminate_flag
= true;
12431 /* Fkill_emacs doesn't return. We have to return. (TI) */
12438 profiler_exit_proc ()
12440 ProfilerDump ("\pEmacs.prof");
12445 /* These few functions implement Emacs as a normal Mac application
12446 (almost): set up the heap and the Toolbox, handle necessary
12447 system events plus a few simple menu events. They also set up
12448 Emacs's access to functions defined in the rest of this file.
12449 Emacs uses function hooks to perform all its terminal I/O. A
12450 complete list of these functions appear in termhooks.h. For what
12451 they do, read the comments there and see also w32term.c and
12452 xterm.c. What's noticeably missing here is the event loop, which
12453 is normally present in most Mac application. After performing the
12454 necessary Mac initializations, main passes off control to
12455 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12456 mac_read_socket (defined further below) to read input. This is
12457 where WaitNextEvent is called to process Mac events. This is also
12458 where check_alarm in sysdep.c is called to simulate alarm signals.
12459 This makes the cursor jump back to its correct position after
12460 briefly jumping to that of the matching parenthesis, print useful
12461 hints and prompts in the minibuffer after the user stops typing for
12464 #if !TARGET_API_MAC_CARBON
12469 #if __profile__ /* is the profiler on? */
12470 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
12475 /* set creator and type for files created by MSL */
12476 _fcreator
= 'EMAx';
12480 do_init_managers ();
12484 do_check_ram_size ();
12486 init_emacs_passwd_dir ();
12490 initialize_applescript ();
12492 init_required_apple_events ();
12498 /* set up argv array from STR# resource */
12499 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
12503 /* free up AppleScript resources on exit */
12504 atexit (terminate_applescript
);
12506 #if __profile__ /* is the profiler on? */
12507 atexit (profiler_exit_proc
);
12510 /* 3rd param "envp" never used in emacs_main */
12511 (void) emacs_main (argc
, argv
, 0);
12514 /* Never reached - real exit in Fkill_emacs */
12519 /* Table for translating Mac keycode to X keysym values. Contributed
12520 by Sudhir Shenoy. */
12521 static unsigned char keycode_to_xkeysym_table
[] = {
12523 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12524 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12525 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12526 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12528 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12529 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12530 0, 0, 0, '\xaf' /* kp/ */,
12531 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12533 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12534 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12535 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12536 '\xb9' /* kp9 */, 0, 0, 0,
12538 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12539 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12540 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12541 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12543 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12544 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12545 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12546 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12550 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
12552 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
12553 return *xKeySym
!= 0;
12556 /* Emacs calls this whenever it wants to read an input event from the
12559 XTread_socket (int sd
, struct input_event
*bufp
, int numchars
, int expected
)
12562 #if USE_CARBON_EVENTS
12563 OSStatus rneResult
;
12565 EventMouseButton mouseBtn
;
12569 EventMask event_mask
;
12572 if (interrupt_input_blocked
)
12574 interrupt_input_pending
= 1;
12579 interrupt_input_pending
= 0;
12582 /* So people can tell when we have read the available input. */
12583 input_signal_count
++;
12588 /* Don't poll for events to process (specifically updateEvt) if
12589 window update currently already in progress. A call to redisplay
12590 (in do_window_update) can be preempted by another call to
12591 redisplay, causing blank regions to be left on the screen and the
12592 cursor to be left at strange places. */
12593 if (handling_window_update
)
12599 if (terminate_flag
)
12600 Fkill_emacs (make_number (1));
12602 /* It is necessary to set this (additional) argument slot of an
12603 event to nil because keyboard.c protects incompletely processed
12604 event from being garbage collected by placing them in the
12605 kbd_buffer_gcpro vector. */
12608 event_mask
= everyEvent
;
12609 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
12610 event_mask
-= highLevelEventMask
;
12612 #if USE_CARBON_EVENTS
12613 rneResult
= ReceiveNextEvent (0, NULL
,
12615 ? TicksToEventTime (app_sleep_time
)
12620 /* Handle new events */
12621 if (!mac_convert_event_ref (eventRef
, &er
))
12622 switch (GetEventClass (eventRef
))
12624 case kEventClassMouse
:
12625 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
12629 WindowPtr window_ptr
= FrontWindow ();
12630 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (window_ptr
);
12631 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
12632 typeSInt32
, NULL
, sizeof (SInt32
),
12634 GetEventParameter(eventRef
, kEventParamMouseLocation
,
12635 typeQDPoint
, NULL
, sizeof (Point
),
12637 bufp
->kind
= MOUSE_WHEEL_EVENT
;
12638 bufp
->code
= delta
;
12639 bufp
->modifiers
= mac_event_to_emacs_modifiers(eventRef
);
12640 SetPort (GetWindowPort (window_ptr
));
12641 GlobalToLocal (&point
);
12642 XSETINT (bufp
->x
, point
.h
);
12643 XSETINT (bufp
->y
, point
.v
);
12644 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
12645 bufp
->timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
12649 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
12653 /* Send the event to the appropriate receiver. */
12654 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
12658 if (WaitNextEvent (event_mask
, &er
, (expected
? app_sleep_time
: 0L), NULL
))
12659 #endif /* USE_CARBON_EVENTS */
12665 WindowPtr window_ptr
= FrontWindow ();
12668 #if USE_CARBON_EVENTS
12669 /* This is needed to correctly */
12670 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
12673 if (mouse_tracking_in_progress
== mouse_tracking_scroll_bar
12674 && er
.what
== mouseUp
)
12676 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (window_ptr
);
12677 Point mouse_loc
= er
.where
;
12679 /* Convert to local coordinates of new window. */
12680 #if TARGET_API_MAC_CARBON
12681 SetPort (GetWindowPort (window_ptr
));
12683 SetPort (window_ptr
);
12686 GlobalToLocal (&mouse_loc
);
12688 #if USE_CARBON_EVENTS
12689 bufp
->code
= mac_get_mouse_btn (eventRef
);
12691 bufp
->code
= 0; /* only one mouse button */
12693 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
12694 bufp
->frame_or_window
= tracked_scroll_bar
->window
;
12695 bufp
->part
= scroll_bar_handle
;
12696 #if USE_CARBON_EVENTS
12697 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12699 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12701 bufp
->modifiers
|= up_modifier
;
12702 bufp
->timestamp
= er
.when
* (1000 / 60);
12703 /* ticks to milliseconds */
12705 XSETINT (bufp
->x
, tracked_scroll_bar
->left
+ 2);
12706 XSETINT (bufp
->y
, mouse_loc
.v
- 24);
12707 tracked_scroll_bar
->dragging
= Qnil
;
12708 mouse_tracking_in_progress
= mouse_tracking_none
;
12709 tracked_scroll_bar
= NULL
;
12714 part_code
= FindWindow (er
.where
, &window_ptr
);
12720 struct frame
*f
= ((mac_output
*)
12721 GetWRefCon (FrontWindow ()))->mFP
;
12722 saved_menu_event_location
= er
.where
;
12723 bufp
->kind
= MENU_BAR_ACTIVATE_EVENT
;
12724 XSETFRAME (bufp
->frame_or_window
, f
);
12730 if (window_ptr
!= FrontWindow ())
12731 SelectWindow (window_ptr
);
12734 SInt16 control_part_code
;
12736 struct mac_output
*mwp
= (mac_output
*)
12737 GetWRefCon (window_ptr
);
12738 Point mouse_loc
= er
.where
;
12740 /* convert to local coordinates of new window */
12741 #if TARGET_API_MAC_CARBON
12742 SetPort (GetWindowPort (window_ptr
));
12744 SetPort (window_ptr
);
12747 GlobalToLocal (&mouse_loc
);
12748 #if TARGET_API_MAC_CARBON
12749 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
12750 &control_part_code
);
12752 control_part_code
= FindControl (mouse_loc
, window_ptr
, &ch
);
12755 #if USE_CARBON_EVENTS
12756 bufp
->code
= mac_get_mouse_btn (eventRef
);
12758 bufp
->code
= 0; /* only one mouse button */
12760 XSETINT (bufp
->x
, mouse_loc
.h
);
12761 XSETINT (bufp
->y
, mouse_loc
.v
);
12762 bufp
->timestamp
= er
.when
* (1000 / 60);
12763 /* ticks to milliseconds */
12765 #if TARGET_API_MAC_CARBON
12768 if (control_part_code
!= 0)
12771 struct scroll_bar
*bar
= (struct scroll_bar
*)
12772 GetControlReference (ch
);
12773 x_scroll_bar_handle_click (bar
, control_part_code
, &er
,
12775 if (er
.what
== mouseDown
12776 && control_part_code
== kControlIndicatorPart
)
12778 mouse_tracking_in_progress
12779 = mouse_tracking_scroll_bar
;
12780 tracked_scroll_bar
= bar
;
12784 mouse_tracking_in_progress
= mouse_tracking_none
;
12785 tracked_scroll_bar
= NULL
;
12790 bufp
->kind
= MOUSE_CLICK_EVENT
;
12791 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
12792 if (er
.what
== mouseDown
)
12793 mouse_tracking_in_progress
12794 = mouse_tracking_mouse_movement
;
12796 mouse_tracking_in_progress
= mouse_tracking_none
;
12799 #if USE_CARBON_EVENTS
12800 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12802 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12808 bufp
->modifiers
|= down_modifier
;
12811 bufp
->modifiers
|= up_modifier
;
12820 #if TARGET_API_MAC_CARBON
12824 GetQDGlobalsScreenBits (&bm
);
12825 DragWindow (window_ptr
, er
.where
, &bm
.bounds
);
12827 #else /* not TARGET_API_MAC_CARBON */
12828 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12829 #endif /* not TARGET_API_MAC_CARBON */
12833 if (TrackGoAway (window_ptr
, er
.where
))
12835 bufp
->kind
= DELETE_WINDOW_EVENT
;
12836 XSETFRAME (bufp
->frame_or_window
,
12837 ((mac_output
*) GetWRefCon (window_ptr
))->mFP
);
12842 /* window resize handling added --ben */
12844 do_grow_window(window_ptr
, &er
);
12847 /* window zoom handling added --ben */
12850 if (TrackBox (window_ptr
, er
.where
, part_code
))
12851 do_zoom_window (window_ptr
, part_code
);
12863 #if USE_CARBON_EVENTS
12864 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
12872 int keycode
= (er
.message
& keyCodeMask
) >> 8;
12875 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12884 if (keycode
== 0x33) /* delete key (charCode translated to 0x8) */
12887 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
12889 else if (keycode_to_xkeysym (keycode
, &xkeysym
))
12891 bufp
->code
= 0xff00 | xkeysym
;
12892 bufp
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
12894 else if (!NILP (Vmac_reverse_ctrl_meta
) && (er
.modifiers
& controlKey
))
12896 /* This is a special case to deal with converting from
12897 a control character to non-control character */
12898 int new_modifiers
= er
.modifiers
& ~controlKey
;
12899 int new_keycode
= keycode
| new_modifiers
;
12900 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
12901 unsigned long some_state
= 0;
12902 bufp
->code
= KeyTranslate (kchr_ptr
, new_keycode
, &some_state
) & 0xff;
12903 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
12907 if (er
.modifiers
& macMetaKey
)
12909 /* This code comes from Keyboard Resource, Appendix
12910 C of IM - Text. This is necessary since shift is
12911 ignored in KCHR table translation when option or
12912 command is pressed. */
12913 int new_modifiers
= er
.modifiers
& 0xf600;
12914 /* mask off option and command */
12915 int new_keycode
= keycode
| new_modifiers
;
12916 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
12917 unsigned long some_state
= 0;
12918 bufp
->code
= KeyTranslate (kchr_ptr
, new_keycode
,
12919 &some_state
) & 0xff;
12921 #if USE_CARBON_EVENTS
12922 else if (er
.modifiers
& cmdKey
&&
12923 (NILP (Vmac_command_key_is_meta
)))
12925 /* If this is a command key (and we are not overriding it),
12926 send back to the operating system */
12927 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
12932 bufp
->code
= er
.message
& charCodeMask
;
12933 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
12937 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12938 convert non-ASCII characters typed at the Mac keyboard
12939 (presumed to be in the Mac Roman encoding) to iso-latin-1
12940 encoding before they are passed to Emacs. This enables the
12941 Mac keyboard to be used to enter non-ASCII iso-latin-1
12942 characters directly. */
12943 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
12944 && bufp
->kind
== ASCII_KEYSTROKE_EVENT
&& bufp
->code
>= 128)
12946 static TECObjectRef converter
= NULL
;
12947 OSStatus the_err
= noErr
;
12948 OSStatus convert_status
= noErr
;
12950 if (converter
== NULL
)
12952 the_err
= TECCreateConverter (&converter
,
12953 kTextEncodingMacRoman
,
12954 mac_keyboard_text_encoding
);
12955 current_mac_keyboard_text_encoding
12956 = mac_keyboard_text_encoding
;
12958 else if (mac_keyboard_text_encoding
12959 != current_mac_keyboard_text_encoding
)
12961 /* Free the converter for the current encoding before
12962 creating a new one. */
12963 TECDisposeConverter (converter
);
12964 the_err
= TECCreateConverter (&converter
,
12965 kTextEncodingMacRoman
,
12966 mac_keyboard_text_encoding
);
12967 current_mac_keyboard_text_encoding
12968 = mac_keyboard_text_encoding
;
12971 if (the_err
== noErr
)
12973 unsigned char ch
= bufp
->code
;
12974 ByteCount actual_input_length
, actual_output_length
;
12975 unsigned char outch
;
12977 convert_status
= TECConvertText (converter
, &ch
, 1,
12978 &actual_input_length
,
12980 &actual_output_length
);
12981 if (convert_status
== noErr
12982 && actual_input_length
== 1
12983 && actual_output_length
== 1)
12984 bufp
->code
= outch
;
12988 #if USE_CARBON_EVENTS
12989 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12991 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12996 = (mac_output
*) GetWRefCon (FrontNonFloatingWindow ());
12997 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
13000 bufp
->timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
13005 case kHighLevelEvent
:
13006 drag_and_drop_file_list
= Qnil
;
13008 AEProcessAppleEvent(&er
);
13010 /* Build a DRAG_N_DROP_EVENT type event as is done in
13011 constuct_drag_n_drop in w32term.c. */
13012 if (!NILP (drag_and_drop_file_list
))
13018 wp
= FrontWindow ();
13022 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
13024 bufp
->kind
= DRAG_N_DROP_EVENT
;
13026 bufp
->timestamp
= er
.when
* (1000 / 60);
13027 /* ticks to milliseconds */
13028 #if USE_CARBON_EVENTS
13029 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
13031 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
13034 XSETINT (bufp
->x
, 0);
13035 XSETINT (bufp
->y
, 0);
13037 XSETFRAME (frame
, f
);
13038 bufp
->frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
13040 /* Regardless of whether Emacs was suspended or in the
13041 foreground, ask it to redraw its entire screen.
13042 Otherwise parts of the screen can be left in an
13043 inconsistent state. */
13045 #if TARGET_API_MAC_CARBON
13049 GetWindowPortBounds (wp
, &r
);
13050 InvalWindowRect (wp
, &r
);
13052 #else /* not TARGET_API_MAC_CARBON */
13053 InvalRect (&(wp
->portRect
));
13054 #endif /* not TARGET_API_MAC_CARBON */
13061 #if USE_CARBON_EVENTS
13062 ReleaseEvent (eventRef
);
13066 /* If the focus was just given to an autoraising frame,
13068 /* ??? This ought to be able to handle more than one such frame. */
13069 if (pending_autoraise_frame
)
13071 x_raise_frame (pending_autoraise_frame
);
13072 pending_autoraise_frame
= 0;
13075 #if !TARGET_API_MAC_CARBON
13076 check_alarm (); /* simulate the handling of a SIGALRM */
13080 static Point old_mouse_pos
= { -1, -1 };
13082 if (app_is_suspended
)
13084 old_mouse_pos
.h
= -1;
13085 old_mouse_pos
.v
= -1;
13093 struct scroll_bar
*sb
;
13095 wp
= FrontWindow ();
13096 if (is_emacs_window (wp
))
13098 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
13100 #if TARGET_API_MAC_CARBON
13101 SetPort (GetWindowPort (wp
));
13106 GetMouse (&mouse_pos
);
13108 if (!EqualPt (mouse_pos
, old_mouse_pos
))
13110 if (mouse_tracking_in_progress
== mouse_tracking_scroll_bar
13111 && tracked_scroll_bar
)
13112 x_scroll_bar_note_movement (tracked_scroll_bar
,
13114 - XINT (tracked_scroll_bar
->top
),
13115 TickCount() * (1000 / 60));
13117 note_mouse_movement (f
, &mouse_pos
);
13119 old_mouse_pos
= mouse_pos
;
13131 /* Need to override CodeWarrior's input function so no conversion is
13132 done on newlines Otherwise compiled functions in .elc files will be
13133 read incorrectly. Defined in ...:MSL C:MSL
13134 Common:Source:buffer_io.c. */
13137 __convert_to_newlines (unsigned char * p
, size_t * n
)
13139 #pragma unused(p,n)
13143 __convert_from_newlines (unsigned char * p
, size_t * n
)
13145 #pragma unused(p,n)
13150 /* Initialize the struct pointed to by MW to represent a new COLS x
13151 ROWS Macintosh window, using font with name FONTNAME and size
13154 NewMacWindow (FRAME_PTR fp
)
13157 #if TARGET_API_MAC_CARBON
13158 static int making_terminal_window
= 0;
13160 static int making_terminal_window
= 1;
13163 mwp
= fp
->output_data
.mac
;
13165 if (making_terminal_window
)
13167 if (!(mwp
->mWP
= GetNewCWindow (TERM_WINDOW_RESOURCE
, NULL
,
13170 making_terminal_window
= 0;
13173 if (!(mwp
->mWP
= GetNewCWindow (WINDOW_RESOURCE
, NULL
, (WindowPtr
) -1)))
13176 SetWRefCon (mwp
->mWP
, (long) mwp
);
13177 /* so that update events can find this mac_output struct */
13178 mwp
->mFP
= fp
; /* point back to emacs frame */
13180 #if TARGET_API_MAC_CARBON
13181 SetPort (GetWindowPort (mwp
->mWP
));
13183 SetPort (mwp
->mWP
);
13188 SizeWindow (mwp
->mWP
, mwp
->pixel_width
, mwp
->pixel_height
, false);
13189 ShowWindow (mwp
->mWP
);
13194 void make_mac_frame (struct frame
*f
)
13196 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
13197 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
13201 f
->output_data
.mac
->cursor_pixel
= 0;
13202 f
->output_data
.mac
->border_pixel
= 0x00ff00;
13203 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
13204 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
13206 f
->output_data
.mac
->desired_cursor
= FILLED_BOX_CURSOR
;
13208 f
->output_data
.mac
->fontset
= -1;
13209 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
13210 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
13211 f
->output_data
.mac
->left_pos
= 4;
13212 f
->output_data
.mac
->top_pos
= 4;
13213 f
->output_data
.mac
->border_width
= 0;
13214 f
->output_data
.mac
->explicit_parent
= 0;
13216 f
->output_data
.mac
->internal_border_width
= 0;
13218 f
->output_method
= output_mac
;
13227 void make_mac_terminal_frame (struct frame
*f
)
13231 XSETFRAME (frame
, f
);
13233 f
->output_method
= output_mac
;
13234 f
->output_data
.mac
= (struct mac_output
*)
13235 xmalloc (sizeof (struct mac_output
));
13236 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
13237 f
->output_data
.mac
->fontset
= -1;
13238 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
13239 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
13241 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
13246 make_mac_frame (f
);
13250 /* Need to be initialized for unshow_buffer in window.c. */
13251 selected_window
= f
->selected_window
;
13253 Fmodify_frame_parameters (frame
,
13254 Fcons (Fcons (Qfont
,
13255 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
13256 Fmodify_frame_parameters (frame
,
13257 Fcons (Fcons (Qforeground_color
,
13258 build_string ("black")), Qnil
));
13259 Fmodify_frame_parameters (frame
,
13260 Fcons (Fcons (Qbackground_color
,
13261 build_string ("white")), Qnil
));
13265 /***********************************************************************
13267 ***********************************************************************/
13269 #ifdef USE_X_TOOLKIT
13270 static XrmOptionDescRec emacs_options
[] = {
13271 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
13272 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
13274 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13275 XrmoptionSepArg
, NULL
},
13276 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
13278 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13279 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13280 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13281 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
13282 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
13283 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
13284 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
13286 #endif /* USE_X_TOOLKIT */
13288 #ifdef MULTI_KBOARD
13289 /* Test whether two display-name strings agree up to the dot that separates
13290 the screen number from the server number. */
13292 same_x_server (name1
, name2
)
13293 char *name1
, *name2
;
13295 int seen_colon
= 0;
13296 unsigned char *system_name
= SDATA (Vsystem_name
);
13297 int system_name_length
= strlen (system_name
);
13298 int length_until_period
= 0;
13300 while (system_name
[length_until_period
] != 0
13301 && system_name
[length_until_period
] != '.')
13302 length_until_period
++;
13304 /* Treat `unix' like an empty host name. */
13305 if (! strncmp (name1
, "unix:", 5))
13307 if (! strncmp (name2
, "unix:", 5))
13309 /* Treat this host's name like an empty host name. */
13310 if (! strncmp (name1
, system_name
, system_name_length
)
13311 && name1
[system_name_length
] == ':')
13312 name1
+= system_name_length
;
13313 if (! strncmp (name2
, system_name
, system_name_length
)
13314 && name2
[system_name_length
] == ':')
13315 name2
+= system_name_length
;
13316 /* Treat this host's domainless name like an empty host name. */
13317 if (! strncmp (name1
, system_name
, length_until_period
)
13318 && name1
[length_until_period
] == ':')
13319 name1
+= length_until_period
;
13320 if (! strncmp (name2
, system_name
, length_until_period
)
13321 && name2
[length_until_period
] == ':')
13322 name2
+= length_until_period
;
13324 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
13328 if (seen_colon
&& *name1
== '.')
13332 && (*name1
== '.' || *name1
== '\0')
13333 && (*name2
== '.' || *name2
== '\0'));
13337 int mac_initialized
= 0;
13340 mac_initialize_display_info ()
13342 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
13343 GDHandle main_device_handle
;
13345 bzero (dpyinfo
, sizeof (*dpyinfo
));
13347 /* Put it on x_display_name_list. */
13348 x_display_name_list
= Fcons (Fcons (build_string ("Mac"), Qnil
),
13349 x_display_name_list
);
13350 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
13353 dpyinfo
->mac_id_name
13354 = (char *) xmalloc (SCHARS (Vinvocation_name
)
13355 + SCHARS (Vsystem_name
)
13357 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
13358 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
13360 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
13361 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
13364 main_device_handle
= LMGetMainDevice();
13366 dpyinfo
->reference_count
= 0;
13367 dpyinfo
->resx
= 75.0;
13368 dpyinfo
->resy
= 75.0;
13369 dpyinfo
->n_planes
= 1;
13370 dpyinfo
->n_cbits
= 16;
13371 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
13372 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
13373 dpyinfo
->grabbed
= 0;
13374 dpyinfo
->root_window
= NULL
;
13376 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
13377 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
13378 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
13379 dpyinfo
->mouse_face_window
= Qnil
;
13382 struct mac_display_info
*
13383 mac_term_init (display_name
, xrm_option
, resource_name
)
13384 Lisp_Object display_name
;
13386 char *resource_name
;
13388 struct mac_display_info
*dpyinfo
;
13389 GDHandle main_device_handle
;
13391 if (!mac_initialized
)
13394 mac_initialized
= 1;
13397 mac_initialize_display_info (display_name
);
13399 dpyinfo
= &one_mac_display_info
;
13401 main_device_handle
= LMGetMainDevice();
13403 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
13404 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
13410 void MakeMeTheFrontProcess ()
13412 ProcessSerialNumber psn
;
13415 err
= GetCurrentProcess (&psn
);
13417 (void) SetFrontProcess (&psn
);
13419 #endif /* MAC_OSX */
13421 /* Set up use of X before we make the first connection. */
13423 static struct redisplay_interface x_redisplay_interface
=
13428 x_clear_end_of_line
,
13430 x_after_update_window_line
,
13431 x_update_window_begin
,
13432 x_update_window_end
,
13435 x_clear_mouse_face
,
13436 x_get_glyph_overhangs
,
13437 x_fix_overlapping_area
13443 rif
= &x_redisplay_interface
;
13445 clear_frame_hook
= x_clear_frame
;
13446 ins_del_lines_hook
= x_ins_del_lines
;
13447 delete_glyphs_hook
= x_delete_glyphs
;
13448 ring_bell_hook
= XTring_bell
;
13449 reset_terminal_modes_hook
= XTreset_terminal_modes
;
13450 set_terminal_modes_hook
= XTset_terminal_modes
;
13451 update_begin_hook
= x_update_begin
;
13452 update_end_hook
= x_update_end
;
13453 set_terminal_window_hook
= XTset_terminal_window
;
13454 read_socket_hook
= XTread_socket
;
13455 frame_up_to_date_hook
= XTframe_up_to_date
;
13456 mouse_position_hook
= XTmouse_position
;
13457 frame_rehighlight_hook
= XTframe_rehighlight
;
13458 frame_raise_lower_hook
= XTframe_raise_lower
;
13460 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13461 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13462 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13463 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13465 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
13467 scroll_region_ok
= 1; /* we'll scroll partial frames */
13468 char_ins_del_ok
= 1;
13469 line_ins_del_ok
= 1; /* we'll just blt 'em */
13470 fast_clear_end_of_line
= 1; /* X does this well */
13471 memory_below_frame
= 0; /* we don't remember what scrolls
13476 last_tool_bar_item
= -1;
13477 any_help_event_p
= 0;
13479 /* Try to use interrupt input; if we can't, then start polling. */
13480 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
13482 #ifdef USE_X_TOOLKIT
13483 XtToolkitInitialize ();
13484 Xt_app_con
= XtCreateApplicationContext ();
13485 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
13487 /* Install an asynchronous timer that processes Xt timeout events
13488 every 0.1s. This is necessary because some widget sets use
13489 timeouts internally, for example the LessTif menu bar, or the
13490 Xaw3d scroll bar. When Xt timouts aren't processed, these
13491 widgets don't behave normally. */
13493 EMACS_TIME interval
;
13494 EMACS_SET_SECS_USECS (interval
, 0, 100000);
13495 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
13499 #if USE_TOOLKIT_SCROLL_BARS
13500 xaw3d_arrow_scroll
= False
;
13501 xaw3d_pick_top
= True
;
13505 /* Note that there is no real way portable across R3/R4 to get the
13506 original error handler. */
13507 XSetErrorHandler (x_error_handler
);
13508 XSetIOErrorHandler (x_io_error_quitter
);
13510 /* Disable Window Change signals; they are handled by X events. */
13512 signal (SIGWINCH
, SIG_DFL
);
13513 #endif /* ! defined (SIGWINCH) */
13515 signal (SIGPIPE
, x_connection_signal
);
13518 mac_initialize_display_info ();
13520 #if TARGET_API_MAC_CARBON
13521 init_required_apple_events ();
13523 init_mac_drag_n_drop ();
13525 #if USE_CARBON_EVENTS
13526 init_service_handler ();
13529 DisableMenuCommand (NULL
, kHICommandQuit
);
13531 if (!inhibit_window_system
)
13532 MakeMeTheFrontProcess ();
13541 staticpro (&x_error_message_string
);
13542 x_error_message_string
= Qnil
;
13545 staticpro (&x_display_name_list
);
13546 x_display_name_list
= Qnil
;
13548 staticpro (&last_mouse_scroll_bar
);
13549 last_mouse_scroll_bar
= Qnil
;
13551 staticpro (&Qvendor_specific_keysyms
);
13552 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
13554 staticpro (&last_mouse_press_frame
);
13555 last_mouse_press_frame
= Qnil
;
13557 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
13558 staticpro (&Qmac_ready_for_drag_n_drop
);
13561 staticpro (&help_echo
);
13562 help_echo_object
= Qnil
;
13563 staticpro (&help_echo_object
);
13564 help_echo_window
= Qnil
;
13565 staticpro (&help_echo_window
);
13566 previous_help_echo
= Qnil
;
13567 staticpro (&previous_help_echo
);
13568 help_echo_pos
= -1;
13570 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
13571 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
13572 x_autoselect_window_p
= 0;
13574 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
13575 doc
: /* *Non-nil means draw block cursor as wide as the glyph under it.
13576 For example, if a block cursor is over a tab, it will be drawn as
13577 wide as that tab on the display. */);
13578 x_stretch_cursor_p
= 0;
13580 #if 0 /* TODO: Setting underline position from font properties. */
13581 DEFVAR_BOOL ("x-use-underline-position-properties",
13582 &x_use_underline_position_properties
,
13583 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13584 nil means ignore them. If you encounter fonts with bogus
13585 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13586 to 4.1, set this to nil. */);
13587 x_use_underline_position_properties
= 1;
13590 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
13591 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
13592 Vx_toolkit_scroll_bars
= Qt
;
13594 staticpro (&last_mouse_motion_frame
);
13595 last_mouse_motion_frame
= Qnil
;
13597 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
13598 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
13599 Otherwise the option key is used. */);
13600 Vmac_command_key_is_meta
= Qt
;
13602 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
13603 doc
: /* Non-nil means that the control and meta keys are reversed. This is
13604 useful for non-standard keyboard layouts. */);
13605 Vmac_reverse_ctrl_meta
= Qnil
;
13607 #if USE_CARBON_EVENTS
13608 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
13609 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
13610 the right click will be mouse-3.
13611 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13612 Vmac_wheel_button_is_mouse_2
= Qt
;
13615 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
13616 doc
: /* One of the Text Encoding Base constant values defined in the
13617 Basic Text Constants section of Inside Macintosh - Text Encoding
13618 Conversion Manager. Its value determines the encoding characters
13619 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13620 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13621 its default value, no conversion takes place. If it is set to
13622 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13623 characters typed on Mac keyboard are first converted into the
13624 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13625 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13626 command, this enables the Mac keyboard to be used to enter non-ASCII
13627 characters directly. */);
13628 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;