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 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
424 enum draw_glyphs_face
));
425 static void x_update_end
P_ ((struct frame
*));
426 static void XTframe_up_to_date
P_ ((struct frame
*));
427 static void XTreassert_line_highlight
P_ ((int, int));
428 static void x_change_line_highlight
P_ ((int, int, int, int));
429 static void XTset_terminal_modes
P_ ((void));
430 static void XTreset_terminal_modes
P_ ((void));
431 static void XTcursor_to
P_ ((int, int, int, int));
432 static void x_write_glyphs
P_ ((struct glyph
*, int));
433 static void x_clear_end_of_line
P_ ((int));
434 static void x_clear_frame
P_ ((void));
435 static void x_clear_cursor
P_ ((struct window
*));
436 static void frame_highlight
P_ ((struct frame
*));
437 static void frame_unhighlight
P_ ((struct frame
*));
438 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
439 static void XTframe_rehighlight
P_ ((struct frame
*));
440 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
441 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
442 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int));
443 static int x_intersect_rectangles
P_ ((Rect
*, Rect
*, Rect
*));
444 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
445 static int expose_window_tree
P_ ((struct window
*, Rect
*));
446 static void expose_overlaps
P_ ((struct window
*, struct glyph_row
*,
447 struct glyph_row
*));
448 static int expose_window
P_ ((struct window
*, Rect
*));
449 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
450 Rect
*, enum glyph_row_area
));
451 static int expose_line
P_ ((struct window
*, struct glyph_row
*,
453 void x_display_cursor (struct window
*, int, int, int, int, int);
454 void x_update_cursor
P_ ((struct frame
*, int));
455 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
456 static void x_update_window_cursor
P_ ((struct window
*, int));
457 static void x_erase_phys_cursor
P_ ((struct window
*));
458 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
459 static void x_draw_fringe_bitmap
P_ ((struct window
*, struct glyph_row
*,
460 enum fringe_bitmap_type
, int left_p
));
461 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
463 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, Rect
*));
464 static void x_draw_row_fringe_bitmaps
P_ ((struct window
*, struct glyph_row
*));
465 static void notice_overwritten_cursor
P_ ((struct window
*,
467 int, int, int, int));
468 static void x_flush
P_ ((struct frame
*f
));
469 static void x_update_begin
P_ ((struct frame
*));
470 static void x_update_window_begin
P_ ((struct window
*));
471 static void x_draw_vertical_border
P_ ((struct window
*));
472 static void x_after_update_window_line
P_ ((struct glyph_row
*));
473 static INLINE
void take_vertical_position_into_account
P_ ((struct it
*));
474 static void x_produce_stretch_glyph
P_ ((struct it
*));
476 static void activate_scroll_bars (FRAME_PTR
);
477 static void deactivate_scroll_bars (FRAME_PTR
);
479 static int is_emacs_window (WindowPtr
);
481 extern int image_ascent (struct image
*, struct face
*);
482 void x_set_offset (struct frame
*, int, int, int);
483 int x_bitmap_icon (struct frame
*, Lisp_Object
);
484 void x_make_frame_visible (struct frame
*);
486 extern void window_scroll (Lisp_Object
, int, int, int);
488 /* Defined in macmenu.h. */
489 extern void menubar_selection_callback (FRAME_PTR
, int);
490 extern void set_frame_menubar (FRAME_PTR
, int, int);
492 /* X display function emulation */
494 /* Structure borrowed from Xlib.h to represent two-byte characters in
503 XFreePixmap (display
, pixmap
)
507 PixMap
*p
= (PixMap
*) pixmap
;
514 /* Set foreground color for subsequent QuickDraw commands. Assume
515 graphic port has already been set. */
518 mac_set_forecolor (unsigned long color
)
522 fg_color
.red
= RED_FROM_ULONG (color
) * 256;
523 fg_color
.green
= GREEN_FROM_ULONG (color
) * 256;
524 fg_color
.blue
= BLUE_FROM_ULONG (color
) * 256;
526 RGBForeColor (&fg_color
);
530 /* Set background color for subsequent QuickDraw commands. Assume
531 graphic port has already been set. */
534 mac_set_backcolor (unsigned long color
)
538 bg_color
.red
= RED_FROM_ULONG (color
) * 256;
539 bg_color
.green
= GREEN_FROM_ULONG (color
) * 256;
540 bg_color
.blue
= BLUE_FROM_ULONG (color
) * 256;
542 RGBBackColor (&bg_color
);
545 /* Set foreground and background color for subsequent QuickDraw
546 commands. Assume that the graphic port has already been set. */
549 mac_set_colors (GC gc
)
551 mac_set_forecolor (gc
->foreground
);
552 mac_set_backcolor (gc
->background
);
555 /* Mac version of XDrawLine. */
558 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
564 #if TARGET_API_MAC_CARBON
565 SetPort (GetWindowPort (w
));
576 /* Mac version of XClearArea. */
579 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
583 unsigned int width
, height
;
586 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
590 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
591 xgc
.background
= mwp
->x_compatible
.background_pixel
;
593 #if TARGET_API_MAC_CARBON
594 SetPort (GetWindowPort (w
));
599 mac_set_colors (&xgc
);
600 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
605 /* Mac version of XClearWindow. */
608 XClearWindow (display
, w
)
612 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
615 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
616 xgc
.background
= mwp
->x_compatible
.background_pixel
;
618 #if TARGET_API_MAC_CARBON
619 SetPort (GetWindowPort (w
));
624 mac_set_colors (&xgc
);
626 #if TARGET_API_MAC_CARBON
630 GetWindowPortBounds (w
, &r
);
633 #else /* not TARGET_API_MAC_CARBON */
634 EraseRect (&(w
->portRect
));
635 #endif /* not TARGET_API_MAC_CARBON */
639 /* Mac replacement for XCopyArea. */
642 mac_draw_bitmap (display
, w
, gc
, x
, y
, bitmap
)
651 #if TARGET_API_MAC_CARBON
652 SetPort (GetWindowPort (w
));
658 SetRect (&r
, x
, y
, x
+ bitmap
->bounds
.right
, y
+ bitmap
->bounds
.bottom
);
660 #if TARGET_API_MAC_CARBON
664 LockPortBits (GetWindowPort (w
));
665 pmh
= GetPortPixMap (GetWindowPort (w
));
666 CopyBits (bitmap
, (BitMap
*) *pmh
, &(bitmap
->bounds
), &r
, srcCopy
, 0);
667 UnlockPortBits (GetWindowPort (w
));
669 #else /* not TARGET_API_MAC_CARBON */
670 CopyBits (bitmap
, &(w
->portBits
), &(bitmap
->bounds
), &r
, srcCopy
, 0);
671 #endif /* not TARGET_API_MAC_CARBON */
675 /* Mac replacement for XSetClipRectangles. */
678 mac_set_clip_rectangle (display
, w
, r
)
683 #if TARGET_API_MAC_CARBON
684 SetPort (GetWindowPort (w
));
693 /* Mac replacement for XSetClipMask. */
696 mac_reset_clipping (display
, w
)
702 #if TARGET_API_MAC_CARBON
703 SetPort (GetWindowPort (w
));
708 SetRect (&r
, -32767, -32767, 32767, 32767);
713 /* Mac replacement for XCreateBitmapFromBitmapData. */
716 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
721 int bytes_per_row
, i
, j
;
723 bitmap
->rowBytes
= (w
+ 15) / 16 * 2; /* must be on word boundary */
724 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
725 if (!bitmap
->baseAddr
)
728 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
729 for (i
= 0; i
< h
; i
++)
730 for (j
= 0; j
< w
; j
++)
731 if (BitTst (bits
, i
* w
+ j
))
732 BitSet (bitmap
->baseAddr
, i
* bitmap
->rowBytes
* 8 + j
);
734 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
739 mac_free_bitmap (bitmap
)
742 xfree (bitmap
->baseAddr
);
745 /* Mac replacement for XFillRectangle. */
748 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
753 unsigned int width
, height
;
757 #if TARGET_API_MAC_CARBON
758 SetPort (GetWindowPort (w
));
764 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
766 PaintRect (&r
); /* using foreground color of gc */
770 /* Mac replacement for XDrawRectangle: dest is a window. */
773 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
778 unsigned int width
, height
;
782 #if TARGET_API_MAC_CARBON
783 SetPort (GetWindowPort (w
));
789 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
791 FrameRect (&r
); /* using foreground color of gc */
795 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
798 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
803 unsigned int width
, height
;
805 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
808 #if TARGET_API_MAC_CARBON
809 SetPort (GetWindowPort (w
));
815 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
817 FrameRect (&r
); /* using foreground color of gc */
823 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
830 int nchars
, mode
, bytes_per_char
;
832 #if TARGET_API_MAC_CARBON
833 SetPort (GetWindowPort (w
));
840 TextFont (gc
->font
->mac_fontnum
);
841 TextSize (gc
->font
->mac_fontsize
);
842 TextFace (gc
->font
->mac_fontface
);
846 DrawText (buf
, 0, nchars
* bytes_per_char
);
850 /* Mac replacement for XDrawString. */
853 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
861 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
865 /* Mac replacement for XDrawString16. */
868 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
876 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
881 /* Mac replacement for XDrawImageString. */
884 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
892 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
896 /* Mac replacement for XDrawString16. */
899 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
907 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
912 /* Mac replacement for XCopyArea: dest must be window. */
915 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
922 unsigned int width
, height
;
927 #if TARGET_API_MAC_CARBON
928 SetPort (GetWindowPort (dest
));
935 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
936 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
938 #if TARGET_API_MAC_CARBON
942 LockPortBits (GetWindowPort (dest
));
943 pmh
= GetPortPixMap (GetWindowPort (dest
));
944 CopyBits ((BitMap
*) &src
, (BitMap
*) *pmh
, &src_r
, &dest_r
, srcCopy
, 0);
945 UnlockPortBits (GetWindowPort (dest
));
947 #else /* not TARGET_API_MAC_CARBON */
948 CopyBits ((BitMap
*) &src
, &(dest
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
949 #endif /* not TARGET_API_MAC_CARBON */
954 /* Convert a pair of local coordinates to global (screen) coordinates.
955 Assume graphic port has been properly set. */
957 local_to_global_coord (short *h
, short *v
)
971 /* Mac replacement for XCopyArea: used only for scrolling. */
974 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
979 unsigned int width
, height
;
982 #if TARGET_API_MAC_CARBON
983 Rect gw_r
, src_r
, dest_r
;
986 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
987 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
989 SetPort (GetWindowPort (w
));
991 ForeColor (blackColor
);
992 BackColor (whiteColor
);
994 LockPortBits (GetWindowPort (w
));
995 pmh
= GetPortPixMap (GetWindowPort (w
));
996 CopyBits ((BitMap
*) *pmh
, (BitMap
*) *pmh
, &src_r
, &dest_r
, srcCopy
, 0);
997 UnlockPortBits (GetWindowPort (w
));
1000 #else /* not TARGET_API_MAC_CARBON */
1005 mac_set_colors (gc
);
1008 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1009 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1012 /* Need to use global coordinates and screenBits since src and dest
1013 areas overlap in general. */
1014 local_to_global_coord (&src_r
.left
, &src_r
.top
);
1015 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
1016 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
1017 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
1019 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
1021 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1022 color mapping in CopyBits. Otherwise, it will be slow. */
1023 ForeColor (blackColor
);
1024 BackColor (whiteColor
);
1025 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1027 mac_set_colors (gc
);
1029 #endif /* not TARGET_API_MAC_CARBON */
1033 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1036 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
1043 unsigned int width
, height
;
1047 int src_right
= ((PixMap
*) src
)->bounds
.right
;
1048 int src_bottom
= ((PixMap
*) src
)->bounds
.bottom
;
1049 int w
= src_right
- src_x
;
1050 int h
= src_bottom
- src_y
;
1052 mac_set_colors (gc
);
1054 SetRect (&src_r
, src_x
, src_y
, src_right
, src_bottom
);
1055 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ w
, dest_y
+ h
);
1057 CopyBits ((BitMap
*) &src
, (BitMap
*) &dest
, &src_r
, &dest_r
, srcCopy
, 0);
1061 /* Mac replacement for XChangeGC. */
1064 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1067 if (mask
& GCForeground
)
1068 gc
->foreground
= xgcv
->foreground
;
1069 if (mask
& GCBackground
)
1070 gc
->background
= xgcv
->background
;
1072 gc
->font
= xgcv
->font
;
1076 /* Mac replacement for XCreateGC. */
1079 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1082 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1083 bzero (gc
, sizeof (XGCValues
));
1085 XChangeGC (ignore
, gc
, mask
, xgcv
);
1091 /* Used in xfaces.c. */
1094 XFreeGC (display
, gc
)
1102 /* Mac replacement for XGetGCValues. */
1105 XGetGCValues (void* ignore
, XGCValues
*gc
,
1106 unsigned long mask
, XGCValues
*xgcv
)
1108 XChangeGC (ignore
, xgcv
, mask
, gc
);
1112 /* Mac replacement for XSetForeground. */
1115 XSetForeground (display
, gc
, color
)
1118 unsigned long color
;
1120 gc
->foreground
= color
;
1124 /* Mac replacement for XSetFont. */
1127 XSetFont (display
, gc
, font
)
1137 XTextExtents16 (XFontStruct
*font
, XChar2b
*text
, int nchars
,
1138 int *direction
,int *font_ascent
,
1139 int *font_descent
, XCharStruct
*cs
)
1141 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1145 /* x_sync is a no-op on Mac. */
1153 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1154 Calls to XFlush should be unnecessary because the X output buffer
1155 is flushed automatically as needed by calls to XPending,
1156 XNextEvent, or XWindowEvent according to the XFlush man page.
1157 XTread_socket calls XPending. Removing XFlush improves
1160 #if TARGET_API_MAC_CARBON
1161 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1163 #define XFlush(DISPLAY) (void) 0
1166 /* Flush display of frame F, or of all frames if F is null. */
1172 #if TARGET_API_MAC_CARBON
1176 Lisp_Object rest
, frame
;
1177 FOR_EACH_FRAME (rest
, frame
)
1178 x_flush (XFRAME (frame
));
1180 else if (FRAME_X_P (f
))
1181 XFlush (FRAME_MAC_DISPLAY (f
));
1183 #endif /* TARGET_API_MAC_CARBON */
1188 /* Return the struct mac_display_info corresponding to DPY. There's
1191 struct mac_display_info
*
1192 mac_display_info_for_display (dpy
)
1195 return &one_mac_display_info
;
1200 /***********************************************************************
1201 Starting and ending an update
1202 ***********************************************************************/
1204 /* Start an update of frame F. This function is installed as a hook
1205 for update_begin, i.e. it is called when update_begin is called.
1206 This function is called prior to calls to x_update_window_begin for
1207 each window being updated. */
1213 /* Nothing to do. */
1217 /* Start update of window W. Set the global variable updated_window
1218 to the window being updated and set output_cursor to the cursor
1222 x_update_window_begin (w
)
1225 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1226 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1229 set_output_cursor (&w
->cursor
);
1233 if (f
== display_info
->mouse_face_mouse_frame
)
1235 /* Don't do highlighting for mouse motion during the update. */
1236 display_info
->mouse_face_defer
= 1;
1238 /* If F needs to be redrawn, simply forget about any prior mouse
1240 if (FRAME_GARBAGED_P (f
))
1241 display_info
->mouse_face_window
= Qnil
;
1243 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1244 their mouse_face_p flag set, which means that they are always
1245 unequal to rows in a desired matrix which never have that
1246 flag set. So, rows containing mouse-face glyphs are never
1247 scrolled, and we don't have to switch the mouse highlight off
1248 here to prevent it from being scrolled. */
1250 /* Can we tell that this update does not affect the window
1251 where the mouse highlight is? If so, no need to turn off.
1252 Likewise, don't do anything if the frame is garbaged;
1253 in that case, the frame's current matrix that we would use
1254 is all wrong, and we will redisplay that line anyway. */
1255 if (!NILP (display_info
->mouse_face_window
)
1256 && w
== XWINDOW (display_info
->mouse_face_window
))
1260 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1261 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1264 if (i
< w
->desired_matrix
->nrows
)
1265 clear_mouse_face (display_info
);
1274 /* Draw a vertical window border to the right of window W if W doesn't
1275 have vertical scroll bars. */
1278 x_draw_vertical_border (w
)
1281 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1283 /* Redraw borders between horizontally adjacent windows. Don't
1284 do it for frames with vertical scroll bars because either the
1285 right scroll bar of a window, or the left scroll bar of its
1286 neighbor will suffice as a border. */
1287 if (!WINDOW_RIGHTMOST_P (w
)
1288 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1292 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
1293 x1
+= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
1296 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1297 f
->output_data
.mac
->normal_gc
, x1
, y0
, x1
, y1
);
1302 /* End update of window W (which is equal to updated_window).
1304 Draw vertical borders between horizontally adjacent windows, and
1305 display W's cursor if CURSOR_ON_P is non-zero.
1307 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1308 glyphs in mouse-face were overwritten. In that case we have to
1309 make sure that the mouse-highlight is properly redrawn.
1311 W may be a menu bar pseudo-window in case we don't have X toolkit
1312 support. Such windows don't have a cursor, so don't display it
1316 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1318 int cursor_on_p
, mouse_face_overwritten_p
;
1320 struct mac_display_info
*dpyinfo
1321 = FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1323 if (!w
->pseudo_window_p
)
1328 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1330 output_cursor
.x
, output_cursor
.y
);
1332 x_draw_vertical_border (w
);
1336 /* If a row with mouse-face was overwritten, arrange for
1337 XTframe_up_to_date to redisplay the mouse highlight. */
1338 if (mouse_face_overwritten_p
)
1340 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1341 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1342 dpyinfo
->mouse_face_window
= Qnil
;
1346 /* Unhide the caret. This won't actually show the cursor, unless it
1347 was visible before the corresponding call to HideCaret in
1348 x_update_window_begin. */
1349 if (w32_use_visible_system_caret
)
1350 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1353 updated_window
= NULL
;
1357 /* End update of frame F. This function is installed as a hook in
1364 /* Reset the background color of Mac OS Window to that of the frame after
1365 update so that it is used by Mac Toolbox to clear the update region before
1366 an update event is generated. */
1367 #if TARGET_API_MAC_CARBON
1368 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
1370 SetPort (FRAME_MAC_WINDOW (f
));
1373 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
1375 /* Mouse highlight may be displayed again. */
1376 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1379 XFlush (FRAME_MAC_DISPLAY (f
));
1384 /* This function is called from various places in xdisp.c whenever a
1385 complete update has been performed. The global variable
1386 updated_window is not available here. */
1389 XTframe_up_to_date (f
)
1394 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1396 if (dpyinfo
->mouse_face_deferred_gc
1397 || f
== dpyinfo
->mouse_face_mouse_frame
)
1400 if (dpyinfo
->mouse_face_mouse_frame
)
1401 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1402 dpyinfo
->mouse_face_mouse_x
,
1403 dpyinfo
->mouse_face_mouse_y
);
1404 dpyinfo
->mouse_face_deferred_gc
= 0;
1411 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1412 arrow bitmaps, or clear the fringes if no bitmaps are required
1413 before DESIRED_ROW is made current. The window being updated is
1414 found in updated_window. This function is called from
1415 update_window_line only if it is known that there are differences
1416 between bitmaps to be drawn between current row and DESIRED_ROW. */
1419 x_after_update_window_line (desired_row
)
1420 struct glyph_row
*desired_row
;
1422 struct window
*w
= updated_window
;
1428 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1431 x_draw_row_fringe_bitmaps (w
, desired_row
);
1435 /* When a window has disappeared, make sure that no rest of
1436 full-width rows stays visible in the internal border. Could
1437 check here if updated_window is the leftmost/rightmost window,
1438 but I guess it's not worth doing since vertically split windows
1439 are almost never used, internal border is rarely set, and the
1440 overhead is very small. */
1441 if (windows_or_buffers_changed
1442 && desired_row
->full_width_p
1443 && (f
= XFRAME (w
->frame
),
1444 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1446 && (height
= desired_row
->visible_height
,
1449 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1450 /* Internal border is drawn below the tool bar. */
1451 if (WINDOWP (f
->tool_bar_window
)
1452 && w
== XWINDOW (f
->tool_bar_window
))
1457 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1458 0, y
, width
, height
, 0);
1459 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1460 f
->output_data
.mac
->pixel_width
- width
, y
,
1468 /* Draw the bitmap WHICH in one of the left or right fringes of
1469 window W. ROW is the glyph row for which to display the bitmap; it
1470 determines the vertical position at which the bitmap has to be
1474 x_draw_fringe_bitmap (w
, row
, which
, left_p
)
1476 struct glyph_row
*row
;
1477 enum fringe_bitmap_type which
;
1480 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1481 Display
*display
= FRAME_MAC_DISPLAY (f
);
1482 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1483 int x
, y
, wd
, h
, dy
;
1485 unsigned char *bits
;
1488 GC gc
= f
->output_data
.mac
->normal_gc
;
1491 /* Must clip because of partially visible lines. */
1492 x_clip_to_row (w
, row
, gc
, 1);
1494 /* Convert row to frame coordinates. */
1495 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1499 case NO_FRINGE_BITMAP
:
1504 case LEFT_TRUNCATION_BITMAP
:
1510 case OVERLAY_ARROW_BITMAP
:
1516 case RIGHT_TRUNCATION_BITMAP
:
1522 case CONTINUED_LINE_BITMAP
:
1523 wd
= continued_width
;
1524 h
= continued_height
;
1525 bits
= continued_bits
;
1528 case CONTINUATION_LINE_BITMAP
:
1529 wd
= continuation_width
;
1530 h
= continuation_height
;
1531 bits
= continuation_bits
;
1534 case ZV_LINE_BITMAP
:
1536 h
= zv_height
- (y
% zv_period
);
1537 bits
= zv_bits
+ (y
% zv_period
);
1544 /* Clip bitmap if too high. */
1545 if (h
> row
->height
)
1548 /* Set dy to the offset in the row to start drawing the bitmap. */
1549 dy
= (row
->height
- h
) / 2;
1551 /* Draw the bitmap. */
1552 face
= FACE_FROM_ID (f
, FRINGE_FACE_ID
);
1553 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1555 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1560 if (wd
> FRAME_X_LEFT_FRINGE_WIDTH (f
))
1561 wd
= FRAME_X_LEFT_FRINGE_WIDTH (f
);
1562 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
1564 - (FRAME_X_LEFT_FRINGE_WIDTH (f
) - wd
) / 2);
1565 if (wd
< FRAME_X_LEFT_FRINGE_WIDTH (f
) || row
->height
> h
)
1567 /* If W has a vertical border to its left, don't draw over it. */
1568 int border
= ((XFASTINT (w
->left
) > 0
1569 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1571 b1
= (window_box_left (w
, -1)
1572 - FRAME_X_LEFT_FRINGE_WIDTH (f
)
1574 b2
= (FRAME_X_LEFT_FRINGE_WIDTH (f
) - border
);
1579 if (wd
> FRAME_X_RIGHT_FRINGE_WIDTH (f
))
1580 wd
= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
1581 x
= (window_box_right (w
, -1)
1582 + (FRAME_X_RIGHT_FRINGE_WIDTH (f
) - wd
) / 2);
1583 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1585 if (wd
< FRAME_X_RIGHT_FRINGE_WIDTH (f
) || row
->height
> h
)
1587 b1
= window_box_right (w
, -1);
1588 b2
= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
1594 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
1596 gcv
.foreground
= face
->background
;
1598 #if 0 /* MAC_TODO: stipple */
1599 /* In case the same realized face is used for fringes and
1600 for something displayed in the text (e.g. face `region' on
1601 mono-displays, the fill style may have been changed to
1602 FillSolid in x_draw_glyph_string_background. */
1604 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1606 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1609 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1612 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
1615 row
->visible_height
);
1617 #if 0 /* MAC_TODO: stipple */
1619 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1623 if (which
== NO_FRINGE_BITMAP
)
1625 mac_reset_clipping (display
, window
);
1629 mac_create_bitmap_from_bitmap_data (&bitmap
, bits
, wd
, h
);
1630 gcv
.foreground
= face
->foreground
;
1631 gcv
.background
= face
->background
;
1633 mac_draw_bitmap (display
, window
, &gcv
, x
, y
+ dy
, &bitmap
);
1635 mac_free_bitmap (&bitmap
);
1636 mac_reset_clipping (display
, window
);
1640 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1641 function with input blocked. */
1644 x_draw_row_fringe_bitmaps (w
, row
)
1646 struct glyph_row
*row
;
1648 struct frame
*f
= XFRAME (w
->frame
);
1649 enum fringe_bitmap_type bitmap
;
1651 xassert (interrupt_input_blocked
);
1653 /* If row is completely invisible, because of vscrolling, we
1654 don't have to draw anything. */
1655 if (row
->visible_height
<= 0)
1658 if (FRAME_X_LEFT_FRINGE_WIDTH (f
) != 0)
1660 /* Decide which bitmap to draw in the left fringe. */
1661 if (row
->overlay_arrow_p
)
1662 bitmap
= OVERLAY_ARROW_BITMAP
;
1663 else if (row
->truncated_on_left_p
)
1664 bitmap
= LEFT_TRUNCATION_BITMAP
;
1665 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
1666 bitmap
= CONTINUATION_LINE_BITMAP
;
1667 else if (row
->indicate_empty_line_p
)
1668 bitmap
= ZV_LINE_BITMAP
;
1670 bitmap
= NO_FRINGE_BITMAP
;
1672 x_draw_fringe_bitmap (w
, row
, bitmap
, 1);
1675 if (FRAME_X_RIGHT_FRINGE_WIDTH (f
) != 0)
1677 /* Decide which bitmap to draw in the right fringe. */
1678 if (row
->truncated_on_right_p
)
1679 bitmap
= RIGHT_TRUNCATION_BITMAP
;
1680 else if (row
->continued_p
)
1681 bitmap
= CONTINUED_LINE_BITMAP
;
1682 else if (row
->indicate_empty_line_p
&& FRAME_X_LEFT_FRINGE_WIDTH (f
) == 0)
1683 bitmap
= ZV_LINE_BITMAP
;
1685 bitmap
= NO_FRINGE_BITMAP
;
1687 x_draw_fringe_bitmap (w
, row
, bitmap
, 0);
1692 /* This is called when starting Emacs and when restarting after
1693 suspend. When starting Emacs, no window is mapped. And nothing
1694 must be done to Emacs's own window if it is suspended (though that
1698 XTset_terminal_modes ()
1702 /* This is called when exiting or suspending Emacs. Exiting will make
1703 the windows go away, and suspending requires no action. */
1706 XTreset_terminal_modes ()
1712 /***********************************************************************
1714 ***********************************************************************/
1716 /* Set the global variable output_cursor to CURSOR. All cursor
1717 positions are relative to updated_window. */
1720 set_output_cursor (cursor
)
1721 struct cursor_pos
*cursor
;
1723 output_cursor
.hpos
= cursor
->hpos
;
1724 output_cursor
.vpos
= cursor
->vpos
;
1725 output_cursor
.x
= cursor
->x
;
1726 output_cursor
.y
= cursor
->y
;
1730 /* Set a nominal cursor position.
1732 HPOS and VPOS are column/row positions in a window glyph matrix. X
1733 and Y are window text area relative pixel positions.
1735 If this is done during an update, updated_window will contain the
1736 window that is being updated and the position is the future output
1737 cursor position for that window. If updated_window is null, use
1738 selected_window and display the cursor at the given position. */
1741 XTcursor_to (vpos
, hpos
, y
, x
)
1742 int vpos
, hpos
, y
, x
;
1746 /* If updated_window is not set, work on selected_window. */
1750 w
= XWINDOW (selected_window
);
1752 /* Set the output cursor. */
1753 output_cursor
.hpos
= hpos
;
1754 output_cursor
.vpos
= vpos
;
1755 output_cursor
.x
= x
;
1756 output_cursor
.y
= y
;
1758 /* If not called as part of an update, really display the cursor.
1759 This will also set the cursor position of W. */
1760 if (updated_window
== NULL
)
1763 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1764 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1771 /***********************************************************************
1773 ***********************************************************************/
1775 /* Function prototypes of this page. */
1777 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1781 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1782 int, XChar2b
*, int));
1783 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1784 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1785 static void x_append_glyph
P_ ((struct it
*));
1786 static void x_append_composite_glyph
P_ ((struct it
*));
1787 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1789 static void x_produce_glyphs
P_ ((struct it
*));
1790 static void x_produce_image_glyph
P_ ((struct it
*it
));
1793 /* Return a pointer to per-char metric information in FONT of a
1794 character pointed by B which is a pointer to an XChar2b. */
1796 #define PER_CHAR_METRIC(font, b) \
1798 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1799 + (((font)->min_byte1 || (font)->max_byte1) \
1800 ? (((b)->byte1 - (font)->min_byte1) \
1801 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1803 : &((font)->max_bounds))
1806 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1807 is not contained in the font. */
1809 static INLINE XCharStruct
*
1810 x_per_char_metric (font
, char2b
)
1814 /* The result metric information. */
1815 XCharStruct
*pcm
= NULL
;
1817 xassert (font
&& char2b
);
1819 if (font
->per_char
!= NULL
)
1821 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1823 /* min_char_or_byte2 specifies the linear character index
1824 corresponding to the first element of the per_char array,
1825 max_char_or_byte2 is the index of the last character. A
1826 character with non-zero CHAR2B->byte1 is not in the font.
1827 A character with byte2 less than min_char_or_byte2 or
1828 greater max_char_or_byte2 is not in the font. */
1829 if (char2b
->byte1
== 0
1830 && char2b
->byte2
>= font
->min_char_or_byte2
1831 && char2b
->byte2
<= font
->max_char_or_byte2
)
1832 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1836 /* If either min_byte1 or max_byte1 are nonzero, both
1837 min_char_or_byte2 and max_char_or_byte2 are less than
1838 256, and the 2-byte character index values corresponding
1839 to the per_char array element N (counting from 0) are:
1841 byte1 = N/D + min_byte1
1842 byte2 = N\D + min_char_or_byte2
1846 D = max_char_or_byte2 - min_char_or_byte2 + 1
1847 / = integer division
1848 \ = integer modulus */
1849 if (char2b
->byte1
>= font
->min_byte1
1850 && char2b
->byte1
<= font
->max_byte1
1851 && char2b
->byte2
>= font
->min_char_or_byte2
1852 && char2b
->byte2
<= font
->max_char_or_byte2
)
1854 pcm
= (font
->per_char
1855 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1856 * (char2b
->byte1
- font
->min_byte1
))
1857 + (char2b
->byte2
- font
->min_char_or_byte2
));
1863 /* If the per_char pointer is null, all glyphs between the first
1864 and last character indexes inclusive have the same
1865 information, as given by both min_bounds and max_bounds. */
1866 if (char2b
->byte2
>= font
->min_char_or_byte2
1867 && char2b
->byte2
<= font
->max_char_or_byte2
)
1868 pcm
= &font
->max_bounds
;
1871 return ((pcm
== NULL
1872 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1877 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1878 the two-byte form of C. Encoding is returned in *CHAR2B. */
1881 x_encode_char (c
, char2b
, font_info
)
1884 struct font_info
*font_info
;
1886 int charset
= CHAR_CHARSET (c
);
1887 XFontStruct
*font
= font_info
->font
;
1889 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1890 This may be either a program in a special encoder language or a
1892 if (font_info
->font_encoder
)
1894 /* It's a program. */
1895 struct ccl_program
*ccl
= font_info
->font_encoder
;
1897 if (CHARSET_DIMENSION (charset
) == 1)
1899 ccl
->reg
[0] = charset
;
1900 ccl
->reg
[1] = char2b
->byte2
;
1904 ccl
->reg
[0] = charset
;
1905 ccl
->reg
[1] = char2b
->byte1
;
1906 ccl
->reg
[2] = char2b
->byte2
;
1909 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1911 /* We assume that MSBs are appropriately set/reset by CCL
1913 if (font
->max_byte1
== 0) /* 1-byte font */
1914 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1916 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1918 else if (font_info
->encoding
[charset
])
1920 /* Fixed encoding scheme. See fontset.h for the meaning of the
1921 encoding numbers. */
1922 int enc
= font_info
->encoding
[charset
];
1924 if ((enc
== 1 || enc
== 2)
1925 && CHARSET_DIMENSION (charset
) == 2)
1926 char2b
->byte1
|= 0x80;
1928 if (enc
== 1 || enc
== 3)
1929 char2b
->byte2
|= 0x80;
1935 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1936 char2b
->byte1
= sjis1
;
1937 char2b
->byte2
= sjis2
;
1943 /* Get face and two-byte form of character C in face FACE_ID on frame
1944 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1945 means we want to display multibyte text. Value is a pointer to a
1946 realized face that is ready for display. */
1948 static INLINE
struct face
*
1949 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
)
1955 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1959 /* Unibyte case. We don't have to encode, but we have to make
1960 sure to use a face suitable for unibyte. */
1963 face_id
= FACE_FOR_CHAR (f
, face
, c
);
1964 face
= FACE_FROM_ID (f
, face_id
);
1966 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1968 /* Case of ASCII in a face known to fit ASCII. */
1974 int c1
, c2
, charset
;
1976 /* Split characters into bytes. If c2 is -1 afterwards, C is
1977 really a one-byte character so that byte1 is zero. */
1978 SPLIT_CHAR (c
, charset
, c1
, c2
);
1980 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1982 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1984 /* Maybe encode the character in *CHAR2B. */
1985 if (face
->font
!= NULL
)
1987 struct font_info
*font_info
1988 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1990 x_encode_char (c
, char2b
, font_info
);
1994 /* Make sure X resources of the face are allocated. */
1995 xassert (face
!= NULL
);
1996 PREPARE_FACE_FOR_DISPLAY (f
, face
);
2002 /* Get face and two-byte form of character glyph GLYPH on frame F.
2003 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
2004 a pointer to a realized face that is ready for display. */
2006 static INLINE
struct face
*
2007 x_get_glyph_face_and_encoding (f
, glyph
, char2b
, two_byte_p
)
2009 struct glyph
*glyph
;
2015 xassert (glyph
->type
== CHAR_GLYPH
);
2016 face
= FACE_FROM_ID (f
, glyph
->face_id
);
2021 if (!glyph
->multibyte_p
)
2023 /* Unibyte case. We don't have to encode, but we have to make
2024 sure to use a face suitable for unibyte. */
2026 char2b
->byte2
= glyph
->u
.ch
;
2028 else if (glyph
->u
.ch
< 128
2029 && glyph
->face_id
< BASIC_FACE_ID_SENTINEL
)
2031 /* Case of ASCII in a face known to fit ASCII. */
2033 char2b
->byte2
= glyph
->u
.ch
;
2037 int c1
, c2
, charset
;
2039 /* Split characters into bytes. If c2 is -1 afterwards, C is
2040 really a one-byte character so that byte1 is zero. */
2041 SPLIT_CHAR (glyph
->u
.ch
, charset
, c1
, c2
);
2043 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
2045 char2b
->byte1
= 0, char2b
->byte2
= c1
;
2047 /* Maybe encode the character in *CHAR2B. */
2048 if (charset
!= CHARSET_ASCII
)
2050 struct font_info
*font_info
2051 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2054 x_encode_char (glyph
->u
.ch
, char2b
, font_info
);
2057 = ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2062 /* Make sure X resources of the face are allocated. */
2063 xassert (face
!= NULL
);
2064 PREPARE_FACE_FOR_DISPLAY (f
, face
);
2069 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2070 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2076 struct glyph
*glyph
;
2077 enum glyph_row_area area
= it
->area
;
2079 xassert (it
->glyph_row
);
2080 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
2082 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
2083 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
2085 glyph
->charpos
= CHARPOS (it
->position
);
2086 glyph
->object
= it
->object
;
2087 glyph
->pixel_width
= it
->pixel_width
;
2088 glyph
->voffset
= it
->voffset
;
2089 glyph
->type
= CHAR_GLYPH
;
2090 glyph
->multibyte_p
= it
->multibyte_p
;
2091 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
2092 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
2093 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
2094 || it
->phys_descent
> it
->descent
);
2095 glyph
->padding_p
= 0;
2096 glyph
->glyph_not_available_p
= it
->glyph_not_available_p
;
2097 glyph
->face_id
= it
->face_id
;
2098 glyph
->u
.ch
= it
->char_to_display
;
2099 ++it
->glyph_row
->used
[area
];
2103 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2104 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2107 x_append_composite_glyph (it
)
2110 struct glyph
*glyph
;
2111 enum glyph_row_area area
= it
->area
;
2113 xassert (it
->glyph_row
);
2115 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
2116 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
2118 glyph
->charpos
= CHARPOS (it
->position
);
2119 glyph
->object
= it
->object
;
2120 glyph
->pixel_width
= it
->pixel_width
;
2121 glyph
->voffset
= it
->voffset
;
2122 glyph
->type
= COMPOSITE_GLYPH
;
2123 glyph
->multibyte_p
= it
->multibyte_p
;
2124 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
2125 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
2126 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
2127 || it
->phys_descent
> it
->descent
);
2128 glyph
->padding_p
= 0;
2129 glyph
->glyph_not_available_p
= 0;
2130 glyph
->face_id
= it
->face_id
;
2131 glyph
->u
.cmp_id
= it
->cmp_id
;
2132 ++it
->glyph_row
->used
[area
];
2137 /* Change IT->ascent and IT->height according to the setting of
2141 take_vertical_position_into_account (it
)
2146 if (it
->voffset
< 0)
2147 /* Increase the ascent so that we can display the text higher
2149 it
->ascent
+= abs (it
->voffset
);
2151 /* Increase the descent so that we can display the text lower
2153 it
->descent
+= it
->voffset
;
2158 /* Produce glyphs/get display metrics for the image IT is loaded with.
2159 See the description of struct display_iterator in dispextern.h for
2160 an overview of struct display_iterator. */
2163 x_produce_image_glyph (it
)
2169 xassert (it
->what
== IT_IMAGE
);
2171 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2172 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
2175 /* Make sure X resources of the face and image are loaded. */
2176 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
2177 prepare_image_for_display (it
->f
, img
);
2179 it
->ascent
= it
->phys_ascent
= image_ascent (img
, face
);
2180 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->vmargin
- it
->ascent
;
2181 it
->pixel_width
= img
->width
+ 2 * img
->hmargin
;
2185 if (face
->box
!= FACE_NO_BOX
)
2187 if (face
->box_line_width
> 0)
2189 it
->ascent
+= face
->box_line_width
;
2190 it
->descent
+= face
->box_line_width
;
2193 if (it
->start_of_box_run_p
)
2194 it
->pixel_width
+= abs (face
->box_line_width
);
2195 if (it
->end_of_box_run_p
)
2196 it
->pixel_width
+= abs (face
->box_line_width
);
2199 take_vertical_position_into_account (it
);
2203 struct glyph
*glyph
;
2204 enum glyph_row_area area
= it
->area
;
2206 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
2207 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
2209 glyph
->charpos
= CHARPOS (it
->position
);
2210 glyph
->object
= it
->object
;
2211 glyph
->pixel_width
= it
->pixel_width
;
2212 glyph
->voffset
= it
->voffset
;
2213 glyph
->type
= IMAGE_GLYPH
;
2214 glyph
->multibyte_p
= it
->multibyte_p
;
2215 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
2216 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
2217 glyph
->overlaps_vertically_p
= 0;
2218 glyph
->padding_p
= 0;
2219 glyph
->glyph_not_available_p
= 0;
2220 glyph
->face_id
= it
->face_id
;
2221 glyph
->u
.img_id
= img
->id
;
2222 ++it
->glyph_row
->used
[area
];
2228 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2229 of the glyph, WIDTH and HEIGHT are the width and height of the
2230 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2231 ascent of the glyph (0 <= ASCENT <= 1). */
2234 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
2240 struct glyph
*glyph
;
2241 enum glyph_row_area area
= it
->area
;
2243 xassert (ascent
>= 0 && ascent
<= 1);
2245 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
2246 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
2248 glyph
->charpos
= CHARPOS (it
->position
);
2249 glyph
->object
= object
;
2250 glyph
->pixel_width
= width
;
2251 glyph
->voffset
= it
->voffset
;
2252 glyph
->type
= STRETCH_GLYPH
;
2253 glyph
->multibyte_p
= it
->multibyte_p
;
2254 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
2255 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
2256 glyph
->overlaps_vertically_p
= 0;
2257 glyph
->padding_p
= 0;
2258 glyph
->glyph_not_available_p
= 0;
2259 glyph
->face_id
= it
->face_id
;
2260 glyph
->u
.stretch
.ascent
= height
* ascent
;
2261 glyph
->u
.stretch
.height
= height
;
2262 ++it
->glyph_row
->used
[area
];
2267 /* Produce a stretch glyph for iterator IT. IT->object is the value
2268 of the glyph property displayed. The value must be a list
2269 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2272 1. `:width WIDTH' specifies that the space should be WIDTH *
2273 canonical char width wide. WIDTH may be an integer or floating
2276 2. `:relative-width FACTOR' specifies that the width of the stretch
2277 should be computed from the width of the first character having the
2278 `glyph' property, and should be FACTOR times that width.
2280 3. `:align-to HPOS' specifies that the space should be wide enough
2281 to reach HPOS, a value in canonical character units.
2283 Exactly one of the above pairs must be present.
2285 4. `:height HEIGHT' specifies that the height of the stretch produced
2286 should be HEIGHT, measured in canonical character units.
2288 5. `:relative-height FACTOR' specifies that the height of the
2289 stretch should be FACTOR times the height of the characters having
2292 Either none or exactly one of 4 or 5 must be present.
2294 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2295 of the stretch should be used for the ascent of the stretch.
2296 ASCENT must be in the range 0 <= ASCENT <= 100. */
2299 ((INTEGERP (X) || FLOATP (X)) \
2305 x_produce_stretch_glyph (it
)
2308 /* (space :width WIDTH :height HEIGHT. */
2310 extern Lisp_Object Qspace
;
2312 extern Lisp_Object QCwidth
, QCheight
, QCascent
;
2313 extern Lisp_Object QCrelative_width
, QCrelative_height
;
2314 extern Lisp_Object QCalign_to
;
2315 Lisp_Object prop
, plist
;
2316 double width
= 0, height
= 0, ascent
= 0;
2317 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2318 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
2320 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
2322 /* List should start with `space'. */
2323 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
2324 plist
= XCDR (it
->object
);
2326 /* Compute the width of the stretch. */
2327 if (prop
= Fplist_get (plist
, QCwidth
),
2329 /* Absolute width `:width WIDTH' specified and valid. */
2330 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
2331 else if (prop
= Fplist_get (plist
, QCrelative_width
),
2334 /* Relative width `:relative-width FACTOR' specified and valid.
2335 Compute the width of the characters having the `glyph'
2338 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
2341 if (it
->multibyte_p
)
2343 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
2344 - IT_BYTEPOS (*it
));
2345 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
2348 it2
.c
= *p
, it2
.len
= 1;
2350 it2
.glyph_row
= NULL
;
2351 it2
.what
= IT_CHARACTER
;
2352 x_produce_glyphs (&it2
);
2353 width
= NUMVAL (prop
) * it2
.pixel_width
;
2355 else if (prop
= Fplist_get (plist
, QCalign_to
),
2357 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
2359 /* Nothing specified -> width defaults to canonical char width. */
2360 width
= CANON_X_UNIT (it
->f
);
2362 /* Compute height. */
2363 if (prop
= Fplist_get (plist
, QCheight
),
2365 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
2366 else if (prop
= Fplist_get (plist
, QCrelative_height
),
2368 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
2370 height
= FONT_HEIGHT (font
);
2372 /* Compute percentage of height used for ascent. If
2373 `:ascent ASCENT' is present and valid, use that. Otherwise,
2374 derive the ascent from the font in use. */
2375 if (prop
= Fplist_get (plist
, QCascent
),
2376 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
2377 ascent
= NUMVAL (prop
) / 100.0;
2379 ascent
= (double) FONT_BASE (font
) / FONT_HEIGHT (font
);
2388 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
2389 if (!STRINGP (object
))
2390 object
= it
->w
->buffer
;
2391 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
2394 it
->pixel_width
= width
;
2395 it
->ascent
= it
->phys_ascent
= height
* ascent
;
2396 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
2399 if (face
->box
!= FACE_NO_BOX
)
2401 if (face
->box_line_width
> 0)
2403 it
->ascent
+= face
->box_line_width
;
2404 it
->descent
+= face
->box_line_width
;
2407 if (it
->start_of_box_run_p
)
2408 it
->pixel_width
+= abs (face
->box_line_width
);
2409 if (it
->end_of_box_run_p
)
2410 it
->pixel_width
+= abs (face
->box_line_width
);
2413 take_vertical_position_into_account (it
);
2416 /* Return proper value to be used as baseline offset of font that has
2417 ASCENT and DESCENT to draw characters by the font at the vertical
2418 center of the line of frame F.
2420 Here, out task is to find the value of BOFF in the following figure;
2422 -------------------------+-----------+-
2423 -+-+---------+-+ | |
2425 | | | | F_ASCENT F_HEIGHT
2428 | | |-|-+------+-----------|------- baseline
2430 | |---------|-+-+ | |
2432 -+-+---------+-+ F_DESCENT |
2433 -------------------------+-----------+-
2435 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2436 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2437 DESCENT = FONT->descent
2438 HEIGHT = FONT_HEIGHT (FONT)
2439 F_DESCENT = (F->output_data.x->font->descent
2440 - F->output_data.x->baseline_offset)
2441 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2444 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2445 (FONT_DESCENT (FONT) \
2446 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2447 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2448 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2450 /* Produce glyphs/get display metrics for the display element IT is
2451 loaded with. See the description of struct display_iterator in
2452 dispextern.h for an overview of struct display_iterator. */
2455 x_produce_glyphs (it
)
2458 it
->glyph_not_available_p
= 0;
2460 if (it
->what
== IT_CHARACTER
)
2464 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2466 int font_not_found_p
;
2467 struct font_info
*font_info
;
2468 int boff
; /* baseline offset */
2469 /* We may change it->multibyte_p upon unibyte<->multibyte
2470 conversion. So, save the current value now and restore it
2473 Note: It seems that we don't have to record multibyte_p in
2474 struct glyph because the character code itself tells if or
2475 not the character is multibyte. Thus, in the future, we must
2476 consider eliminating the field `multibyte_p' in the struct
2479 int saved_multibyte_p
= it
->multibyte_p
;
2481 /* Maybe translate single-byte characters to multibyte, or the
2483 it
->char_to_display
= it
->c
;
2484 if (!ASCII_BYTE_P (it
->c
))
2486 if (unibyte_display_via_language_environment
2487 && SINGLE_BYTE_CHAR_P (it
->c
)
2489 || !NILP (Vnonascii_translation_table
)))
2491 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2492 it
->multibyte_p
= 1;
2493 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2494 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2496 else if (!SINGLE_BYTE_CHAR_P (it
->c
)
2497 && !it
->multibyte_p
)
2499 it
->multibyte_p
= 1;
2500 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2501 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2505 /* Get font to use. Encode IT->char_to_display. */
2506 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2507 it
->face_id
, &char2b
,
2511 /* When no suitable font found, use the default font. */
2512 font_not_found_p
= font
== NULL
;
2513 if (font_not_found_p
)
2515 font
= FRAME_FONT (it
->f
);
2516 boff
= it
->f
->output_data
.mac
->baseline_offset
;
2521 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2522 boff
= font_info
->baseline_offset
;
2523 if (font_info
->vertical_centering
)
2524 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2527 if (it
->char_to_display
>= ' '
2528 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
2530 /* Either unibyte or ASCII. */
2535 pcm
= x_per_char_metric (font
, &char2b
);
2536 it
->ascent
= FONT_BASE (font
) + boff
;
2537 it
->descent
= FONT_DESCENT (font
) - boff
;
2541 it
->phys_ascent
= pcm
->ascent
+ boff
;
2542 it
->phys_descent
= pcm
->descent
- boff
;
2543 it
->pixel_width
= pcm
->width
;
2547 it
->glyph_not_available_p
= 1;
2548 it
->phys_ascent
= FONT_BASE (font
) + boff
;
2549 it
->phys_descent
= FONT_DESCENT (font
) - boff
;
2550 it
->pixel_width
= FONT_WIDTH (font
);
2553 /* If this is a space inside a region of text with
2554 `space-width' property, change its width. */
2555 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
2557 it
->pixel_width
*= XFLOATINT (it
->space_width
);
2559 /* If face has a box, add the box thickness to the character
2560 height. If character has a box line to the left and/or
2561 right, add the box line width to the character's width. */
2562 if (face
->box
!= FACE_NO_BOX
)
2564 int thick
= face
->box_line_width
;
2568 it
->ascent
+= thick
;
2569 it
->descent
+= thick
;
2574 if (it
->start_of_box_run_p
)
2575 it
->pixel_width
+= thick
;
2576 if (it
->end_of_box_run_p
)
2577 it
->pixel_width
+= thick
;
2580 /* If face has an overline, add the height of the overline
2581 (1 pixel) and a 1 pixel margin to the character height. */
2582 if (face
->overline_p
)
2585 take_vertical_position_into_account (it
);
2587 /* If we have to actually produce glyphs, do it. */
2592 /* Translate a space with a `space-width' property
2593 into a stretch glyph. */
2594 double ascent
= (double) FONT_BASE (font
)
2595 / FONT_HEIGHT (font
);
2596 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
2597 it
->ascent
+ it
->descent
, ascent
);
2600 x_append_glyph (it
);
2602 /* If characters with lbearing or rbearing are displayed
2603 in this line, record that fact in a flag of the
2604 glyph row. This is used to optimize X output code. */
2605 if (pcm
&& (pcm
->lbearing
< 0 || pcm
->rbearing
> pcm
->width
))
2606 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
2609 else if (it
->char_to_display
== '\n')
2611 /* A newline has no width but we need the height of the line. */
2612 it
->pixel_width
= 0;
2614 it
->ascent
= it
->phys_ascent
= FONT_BASE (font
) + boff
;
2615 it
->descent
= it
->phys_descent
= FONT_DESCENT (font
) - boff
;
2617 if (face
->box
!= FACE_NO_BOX
2618 && face
->box_line_width
> 0)
2620 it
->ascent
+= face
->box_line_width
;
2621 it
->descent
+= face
->box_line_width
;
2624 else if (it
->char_to_display
== '\t')
2626 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
2627 int x
= it
->current_x
+ it
->continuation_lines_width
;
2628 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
2630 /* If the distance from the current position to the next tab
2631 stop is less than a canonical character width, use the
2632 tab stop after that. */
2633 if (next_tab_x
- x
< CANON_X_UNIT (it
->f
))
2634 next_tab_x
+= tab_width
;
2636 it
->pixel_width
= next_tab_x
- x
;
2638 it
->ascent
= it
->phys_ascent
= FONT_BASE (font
) + boff
;
2639 it
->descent
= it
->phys_descent
= FONT_DESCENT (font
) - boff
;
2643 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
2644 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
2645 it
->ascent
+ it
->descent
, ascent
);
2650 /* A multi-byte character. Assume that the display width of the
2651 character is the width of the character multiplied by the
2652 width of the font. */
2654 /* If we found a font, this font should give us the right
2655 metrics. If we didn't find a font, use the frame's
2656 default font and calculate the width of the character
2657 from the charset width; this is what old redisplay code
2659 pcm
= x_per_char_metric (font
, &char2b
);
2660 if (font_not_found_p
|| !pcm
)
2662 int charset
= CHAR_CHARSET (it
->char_to_display
);
2664 it
->glyph_not_available_p
= 1;
2665 it
->pixel_width
= (FONT_WIDTH (FRAME_FONT (it
->f
))
2666 * CHARSET_WIDTH (charset
));
2667 it
->phys_ascent
= FONT_BASE (font
) + boff
;
2668 it
->phys_descent
= FONT_DESCENT (font
) - boff
;
2672 it
->pixel_width
= pcm
->width
;
2673 it
->phys_ascent
= pcm
->ascent
+ boff
;
2674 it
->phys_descent
= pcm
->descent
- boff
;
2676 && (pcm
->lbearing
< 0
2677 || pcm
->rbearing
> pcm
->width
))
2678 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
2681 it
->ascent
= FONT_BASE (font
) + boff
;
2682 it
->descent
= FONT_DESCENT (font
) - boff
;
2683 if (face
->box
!= FACE_NO_BOX
)
2685 int thick
= face
->box_line_width
;
2689 it
->ascent
+= thick
;
2690 it
->descent
+= thick
;
2695 if (it
->start_of_box_run_p
)
2696 it
->pixel_width
+= thick
;
2697 if (it
->end_of_box_run_p
)
2698 it
->pixel_width
+= thick
;
2701 /* If face has an overline, add the height of the overline
2702 (1 pixel) and a 1 pixel margin to the character height. */
2703 if (face
->overline_p
)
2706 take_vertical_position_into_account (it
);
2709 x_append_glyph (it
);
2711 it
->multibyte_p
= saved_multibyte_p
;
2713 else if (it
->what
== IT_COMPOSITION
)
2715 /* Note: A composition is represented as one glyph in the
2716 glyph matrix. There are no padding glyphs. */
2719 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2721 int font_not_found_p
;
2722 struct font_info
*font_info
;
2723 int boff
; /* baseline offset */
2724 struct composition
*cmp
= composition_table
[it
->cmp_id
];
2726 /* Maybe translate single-byte characters to multibyte. */
2727 it
->char_to_display
= it
->c
;
2728 if (unibyte_display_via_language_environment
2729 && SINGLE_BYTE_CHAR_P (it
->c
)
2732 && !NILP (Vnonascii_translation_table
))))
2734 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2737 /* Get face and font to use. Encode IT->char_to_display. */
2738 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2739 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2740 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2741 it
->face_id
, &char2b
, it
->multibyte_p
);
2744 /* When no suitable font found, use the default font. */
2745 font_not_found_p
= font
== NULL
;
2746 if (font_not_found_p
)
2748 font
= FRAME_FONT (it
->f
);
2749 boff
= it
->f
->output_data
.mac
->baseline_offset
;
2754 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2755 boff
= font_info
->baseline_offset
;
2756 if (font_info
->vertical_centering
)
2757 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2760 /* There are no padding glyphs, so there is only one glyph to
2761 produce for the composition. Important is that pixel_width,
2762 ascent and descent are the values of what is drawn by
2763 draw_glyphs (i.e. the values of the overall glyphs composed). */
2766 /* If we have not yet calculated pixel size data of glyphs of
2767 the composition for the current face font, calculate them
2768 now. Theoretically, we have to check all fonts for the
2769 glyphs, but that requires much time and memory space. So,
2770 here we check only the font of the first glyph. This leads
2771 to incorrect display very rarely, and C-l (recenter) can
2772 correct the display anyway. */
2773 if (cmp
->font
!= (void *) font
)
2775 /* Ascent and descent of the font of the first character of
2776 this composition (adjusted by baseline offset). Ascent
2777 and descent of overall glyphs should not be less than
2778 them respectively. */
2779 int font_ascent
= FONT_BASE (font
) + boff
;
2780 int font_descent
= FONT_DESCENT (font
) - boff
;
2781 /* Bounding box of the overall glyphs. */
2782 int leftmost
, rightmost
, lowest
, highest
;
2783 int i
, width
, ascent
, descent
;
2785 cmp
->font
= (void *) font
;
2787 /* Initialize the bounding box. */
2788 pcm
= x_per_char_metric (font
, &char2b
);
2792 ascent
= pcm
->ascent
;
2793 descent
= pcm
->descent
;
2797 width
= FONT_WIDTH (font
);
2798 ascent
= FONT_BASE (font
);
2799 descent
= FONT_DESCENT (font
);
2803 lowest
= - descent
+ boff
;
2804 highest
= ascent
+ boff
;
2808 && font_info
->default_ascent
2809 && CHAR_TABLE_P (Vuse_default_ascent
)
2810 && !NILP (Faref (Vuse_default_ascent
,
2811 make_number (it
->char_to_display
))))
2812 highest
= font_info
->default_ascent
+ boff
;
2814 /* Draw the first glyph at the normal position. It may be
2815 shifted to right later if some other glyphs are drawn at
2817 cmp
->offsets
[0] = 0;
2818 cmp
->offsets
[1] = boff
;
2820 /* Set cmp->offsets for the remaining glyphs. */
2821 for (i
= 1; i
< cmp
->glyph_len
; i
++)
2823 int left
, right
, btm
, top
;
2824 int ch
= COMPOSITION_GLYPH (cmp
, i
);
2825 int face_id
= FACE_FOR_CHAR (it
->f
, face
, ch
);
2827 face
= FACE_FROM_ID (it
->f
, face_id
);
2828 x_get_char_face_and_encoding (it
->f
, ch
, face
->id
, &char2b
,
2833 font
= FRAME_FONT (it
->f
);
2834 boff
= it
->f
->output_data
.mac
->baseline_offset
;
2840 = FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2841 boff
= font_info
->baseline_offset
;
2842 if (font_info
->vertical_centering
)
2843 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2846 pcm
= x_per_char_metric (font
, &char2b
);
2850 ascent
= pcm
->ascent
;
2851 descent
= pcm
->descent
;
2855 width
= FONT_WIDTH (font
);
2860 if (cmp
->method
!= COMPOSITION_WITH_RULE_ALTCHARS
)
2862 /* Relative composition with or without
2864 left
= (leftmost
+ rightmost
- width
) / 2;
2865 btm
= - descent
+ boff
;
2866 if (font_info
&& font_info
->relative_compose
2867 && (! CHAR_TABLE_P (Vignore_relative_composition
)
2868 || NILP (Faref (Vignore_relative_composition
,
2869 make_number (ch
)))))
2872 if (- descent
>= font_info
->relative_compose
)
2873 /* One extra pixel between two glyphs. */
2875 else if (ascent
<= 0)
2876 /* One extra pixel between two glyphs. */
2877 btm
= lowest
- 1 - ascent
- descent
;
2882 /* A composition rule is specified by an integer
2883 value that encodes global and new reference
2884 points (GREF and NREF). GREF and NREF are
2885 specified by numbers as below:
2893 ---3---4---5--- baseline
2895 6---7---8 -- descent
2897 int rule
= COMPOSITION_RULE (cmp
, i
);
2898 int gref
, nref
, grefx
, grefy
, nrefx
, nrefy
;
2900 COMPOSITION_DECODE_RULE (rule
, gref
, nref
);
2901 grefx
= gref
% 3, nrefx
= nref
% 3;
2902 grefy
= gref
/ 3, nrefy
= nref
/ 3;
2905 + grefx
* (rightmost
- leftmost
) / 2
2906 - nrefx
* width
/ 2);
2907 btm
= ((grefy
== 0 ? highest
2909 : grefy
== 2 ? lowest
2910 : (highest
+ lowest
) / 2)
2911 - (nrefy
== 0 ? ascent
+ descent
2912 : nrefy
== 1 ? descent
- boff
2914 : (ascent
+ descent
) / 2));
2917 cmp
->offsets
[i
* 2] = left
;
2918 cmp
->offsets
[i
* 2 + 1] = btm
+ descent
;
2920 /* Update the bounding box of the overall glyphs. */
2921 right
= left
+ width
;
2922 top
= btm
+ descent
+ ascent
;
2923 if (left
< leftmost
)
2925 if (right
> rightmost
)
2933 /* If there are glyphs whose x-offsets are negative,
2934 shift all glyphs to the right and make all x-offsets
2938 for (i
= 0; i
< cmp
->glyph_len
; i
++)
2939 cmp
->offsets
[i
* 2] -= leftmost
;
2940 rightmost
-= leftmost
;
2943 cmp
->pixel_width
= rightmost
;
2944 cmp
->ascent
= highest
;
2945 cmp
->descent
= - lowest
;
2946 if (cmp
->ascent
< font_ascent
)
2947 cmp
->ascent
= font_ascent
;
2948 if (cmp
->descent
< font_descent
)
2949 cmp
->descent
= font_descent
;
2952 it
->pixel_width
= cmp
->pixel_width
;
2953 it
->ascent
= it
->phys_ascent
= cmp
->ascent
;
2954 it
->descent
= it
->phys_descent
= cmp
->descent
;
2956 if (face
->box
!= FACE_NO_BOX
)
2958 int thick
= face
->box_line_width
;
2962 it
->ascent
+= thick
;
2963 it
->descent
+= thick
;
2968 if (it
->start_of_box_run_p
)
2969 it
->pixel_width
+= thick
;
2970 if (it
->end_of_box_run_p
)
2971 it
->pixel_width
+= thick
;
2974 /* If face has an overline, add the height of the overline
2975 (1 pixel) and a 1 pixel margin to the character height. */
2976 if (face
->overline_p
)
2979 take_vertical_position_into_account (it
);
2982 x_append_composite_glyph (it
);
2984 else if (it
->what
== IT_IMAGE
)
2985 x_produce_image_glyph (it
);
2986 else if (it
->what
== IT_STRETCH
)
2987 x_produce_stretch_glyph (it
);
2989 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2990 because this isn't true for images with `:ascent 100'. */
2991 xassert (it
->ascent
>= 0 && it
->descent
>= 0);
2992 if (it
->area
== TEXT_AREA
)
2993 it
->current_x
+= it
->pixel_width
;
2995 it
->descent
+= it
->extra_line_spacing
;
2997 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
2998 it
->max_descent
= max (it
->max_descent
, it
->descent
);
2999 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
3000 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
3004 /* Estimate the pixel height of the mode or top line on frame F.
3005 FACE_ID specifies what line's height to estimate. */
3008 x_estimate_mode_line_height (f
, face_id
)
3010 enum face_id face_id
;
3012 int height
= FONT_HEIGHT (FRAME_FONT (f
));
3014 /* This function is called so early when Emacs starts that the face
3015 cache and mode line face are not yet initialized. */
3016 if (FRAME_FACE_CACHE (f
))
3018 struct face
*face
= FACE_FROM_ID (f
, face_id
);
3022 height
= FONT_HEIGHT (face
->font
);
3023 if (face
->box_line_width
> 0)
3024 height
+= 2 * face
->box_line_width
;
3032 /***********************************************************************
3034 ***********************************************************************/
3036 /* A sequence of glyphs to be drawn in the same face.
3038 This data structure is not really completely X specific, so it
3039 could possibly, at least partially, be useful for other systems. It
3040 is currently not part of the external redisplay interface because
3041 it's not clear what other systems will need. */
3045 /* X-origin of the string. */
3048 /* Y-origin and y-position of the base line of this string. */
3051 /* The width of the string, not including a face extension. */
3054 /* The width of the string, including a face extension. */
3055 int background_width
;
3057 /* The height of this string. This is the height of the line this
3058 string is drawn in, and can be different from the height of the
3059 font the string is drawn in. */
3062 /* Number of pixels this string overwrites in front of its x-origin.
3063 This number is zero if the string has an lbearing >= 0; it is
3064 -lbearing, if the string has an lbearing < 0. */
3067 /* Number of pixels this string overwrites past its right-most
3068 nominal x-position, i.e. x + width. Zero if the string's
3069 rbearing is <= its nominal width, rbearing - width otherwise. */
3072 /* The frame on which the glyph string is drawn. */
3075 /* The window on which the glyph string is drawn. */
3078 /* X display and window for convenience. */
3082 /* The glyph row for which this string was built. It determines the
3083 y-origin and height of the string. */
3084 struct glyph_row
*row
;
3086 /* The area within row. */
3087 enum glyph_row_area area
;
3089 /* Characters to be drawn, and number of characters. */
3093 /* A face-override for drawing cursors, mouse face and similar. */
3094 enum draw_glyphs_face hl
;
3096 /* Face in which this string is to be drawn. */
3099 /* Font in which this string is to be drawn. */
3102 /* Font info for this string. */
3103 struct font_info
*font_info
;
3105 /* Non-null means this string describes (part of) a composition.
3106 All characters from char2b are drawn composed. */
3107 struct composition
*cmp
;
3109 /* Index of this glyph string's first character in the glyph
3110 definition of CMP. If this is zero, this glyph string describes
3111 the first character of a composition. */
3114 /* 1 means this glyph strings face has to be drawn to the right end
3115 of the window's drawing area. */
3116 unsigned extends_to_end_of_line_p
: 1;
3118 /* 1 means the background of this string has been drawn. */
3119 unsigned background_filled_p
: 1;
3121 /* 1 means glyph string must be drawn with 16-bit functions. */
3122 unsigned two_byte_p
: 1;
3124 /* 1 means that the original font determined for drawing this glyph
3125 string could not be loaded. The member `font' has been set to
3126 the frame's default font in this case. */
3127 unsigned font_not_found_p
: 1;
3129 /* 1 means that the face in which this glyph string is drawn has a
3131 unsigned stippled_p
: 1;
3133 /* 1 means only the foreground of this glyph string must be drawn,
3134 and we should use the physical height of the line this glyph
3135 string appears in as clip rect. */
3136 unsigned for_overlaps_p
: 1;
3138 /* The GC to use for drawing this glyph string. */
3141 /* A pointer to the first glyph in the string. This glyph
3142 corresponds to char2b[0]. Needed to draw rectangles if
3143 font_not_found_p is 1. */
3144 struct glyph
*first_glyph
;
3146 /* Image, if any. */
3149 struct glyph_string
*next
, *prev
;
3156 x_dump_glyph_string (s
)
3157 struct glyph_string
*s
;
3159 fprintf (stderr
, "glyph string\n");
3160 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
3161 s
->x
, s
->y
, s
->width
, s
->height
);
3162 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
3163 fprintf (stderr
, " hl = %d\n", s
->hl
);
3164 fprintf (stderr
, " left overhang = %d, right = %d\n",
3165 s
->left_overhang
, s
->right_overhang
);
3166 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
3167 fprintf (stderr
, " extends to end of line = %d\n",
3168 s
->extends_to_end_of_line_p
);
3169 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
3170 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
3173 #endif /* GLYPH_DEBUG */
3177 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
3178 struct glyph_string
**,
3179 struct glyph_string
*,
3180 struct glyph_string
*));
3181 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
3182 struct glyph_string
**,
3183 struct glyph_string
*,
3184 struct glyph_string
*));
3185 static void x_append_glyph_string
P_ ((struct glyph_string
**,
3186 struct glyph_string
**,
3187 struct glyph_string
*));
3188 static int x_left_overwritten
P_ ((struct glyph_string
*));
3189 static int x_left_overwriting
P_ ((struct glyph_string
*));
3190 static int x_right_overwritten
P_ ((struct glyph_string
*));
3191 static int x_right_overwriting
P_ ((struct glyph_string
*));
3192 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
3194 static void x_init_glyph_string
P_ ((struct glyph_string
*,
3195 XChar2b
*, struct window
*,
3197 enum glyph_row_area
, int,
3198 enum draw_glyphs_face
));
3199 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
3200 enum glyph_row_area
, int, int,
3201 enum draw_glyphs_face
, int));
3202 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
3203 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
3204 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
3206 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
3207 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
3208 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
3209 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
3210 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
3211 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
3212 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
3213 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
3214 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
3216 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
3217 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3218 unsigned long *, double, int));*/
3219 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
3220 double, int, unsigned long));
3221 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
3222 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
3223 static void x_draw_image_relief
P_ ((struct glyph_string
*));
3224 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
3225 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
3226 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
3227 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
3229 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
3230 int, int, int, int, Rect
*));
3231 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
3232 int, int, int, Rect
*));
3233 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
3234 enum glyph_row_area
));
3235 static int x_fill_stretch_glyph_string
P_ ((struct glyph_string
*,
3237 enum glyph_row_area
, int, int));
3240 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
3244 /* Append the list of glyph strings with head H and tail T to the list
3245 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3248 x_append_glyph_string_lists (head
, tail
, h
, t
)
3249 struct glyph_string
**head
, **tail
;
3250 struct glyph_string
*h
, *t
;
3264 /* Prepend the list of glyph strings with head H and tail T to the
3265 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3269 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
3270 struct glyph_string
**head
, **tail
;
3271 struct glyph_string
*h
, *t
;
3285 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3286 Set *HEAD and *TAIL to the resulting list. */
3289 x_append_glyph_string (head
, tail
, s
)
3290 struct glyph_string
**head
, **tail
;
3291 struct glyph_string
*s
;
3293 s
->next
= s
->prev
= NULL
;
3294 x_append_glyph_string_lists (head
, tail
, s
, s
);
3298 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3303 struct glyph_string
*s
;
3305 if (s
->font
== FRAME_FONT (s
->f
)
3306 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
3307 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
3309 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
3312 /* Cursor on non-default face: must merge. */
3316 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
3317 xgcv
.foreground
= s
->face
->background
;
3319 /* If the glyph would be invisible, try a different foreground. */
3320 if (xgcv
.foreground
== xgcv
.background
)
3321 xgcv
.foreground
= s
->face
->foreground
;
3322 if (xgcv
.foreground
== xgcv
.background
)
3323 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
3324 if (xgcv
.foreground
== xgcv
.background
)
3325 xgcv
.foreground
= s
->face
->foreground
;
3327 /* Make sure the cursor is distinct from text in this face. */
3328 if (xgcv
.background
== s
->face
->background
3329 && xgcv
.foreground
== s
->face
->foreground
)
3331 xgcv
.background
= s
->face
->foreground
;
3332 xgcv
.foreground
= s
->face
->background
;
3335 IF_DEBUG (x_check_font (s
->f
, s
->font
));
3336 xgcv
.font
= s
->font
;
3337 mask
= GCForeground
| GCBackground
| GCFont
;
3339 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
3340 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
3343 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
3344 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
3346 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
3351 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3354 x_set_mouse_face_gc (s
)
3355 struct glyph_string
*s
;
3360 /* What face has to be used last for the mouse face? */
3361 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
3362 face
= FACE_FROM_ID (s
->f
, face_id
);
3364 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
3366 if (s
->first_glyph
->type
== CHAR_GLYPH
)
3367 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
3369 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
3370 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
3371 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
3373 /* If font in this face is same as S->font, use it. */
3374 if (s
->font
== s
->face
->font
)
3375 s
->gc
= s
->face
->gc
;
3378 /* Otherwise construct scratch_cursor_gc with values from FACE
3383 xgcv
.background
= s
->face
->background
;
3384 xgcv
.foreground
= s
->face
->foreground
;
3385 IF_DEBUG (x_check_font (s
->f
, s
->font
));
3386 xgcv
.font
= s
->font
;
3387 mask
= GCForeground
| GCBackground
| GCFont
;
3389 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
3390 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
3393 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
3394 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
3396 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
3399 xassert (s
->gc
!= 0);
3403 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3404 Faces to use in the mode line have already been computed when the
3405 matrix was built, so there isn't much to do, here. */
3408 x_set_mode_line_face_gc (s
)
3409 struct glyph_string
*s
;
3411 s
->gc
= s
->face
->gc
;
3415 /* Set S->gc of glyph string S for drawing that glyph string. Set
3416 S->stippled_p to a non-zero value if the face of S has a stipple
3420 x_set_glyph_string_gc (s
)
3421 struct glyph_string
*s
;
3423 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
3425 if (s
->hl
== DRAW_NORMAL_TEXT
)
3427 s
->gc
= s
->face
->gc
;
3428 s
->stippled_p
= s
->face
->stipple
!= 0;
3430 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
3432 x_set_mode_line_face_gc (s
);
3433 s
->stippled_p
= s
->face
->stipple
!= 0;
3435 else if (s
->hl
== DRAW_CURSOR
)
3437 x_set_cursor_gc (s
);
3440 else if (s
->hl
== DRAW_MOUSE_FACE
)
3442 x_set_mouse_face_gc (s
);
3443 s
->stippled_p
= s
->face
->stipple
!= 0;
3445 else if (s
->hl
== DRAW_IMAGE_RAISED
3446 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3448 s
->gc
= s
->face
->gc
;
3449 s
->stippled_p
= s
->face
->stipple
!= 0;
3453 s
->gc
= s
->face
->gc
;
3454 s
->stippled_p
= s
->face
->stipple
!= 0;
3457 /* GC must have been set. */
3458 xassert (s
->gc
!= 0);
3462 /* Return in *R the clipping rectangle for glyph string S. */
3465 x_get_glyph_string_clip_rect (s
, r
)
3466 struct glyph_string
*s
;
3469 int r_height
, r_width
;
3471 if (s
->row
->full_width_p
)
3473 /* Draw full-width. X coordinates are relative to S->w->left. */
3474 int canon_x
= CANON_X_UNIT (s
->f
);
3476 r
->left
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
3477 r_width
= XFASTINT (s
->w
->width
) * canon_x
;
3479 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
3481 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
3482 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
3486 r
->left
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
3488 /* Unless displaying a mode or menu bar line, which are always
3489 fully visible, clip to the visible part of the row. */
3490 if (s
->w
->pseudo_window_p
)
3491 r_height
= s
->row
->visible_height
;
3493 r_height
= s
->height
;
3497 /* This is a text line that may be partially visible. */
3498 r
->left
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
3499 r_width
= window_box_width (s
->w
, s
->area
);
3500 r_height
= s
->row
->visible_height
;
3503 /* If S draws overlapping rows, it's sufficient to use the top and
3504 bottom of the window for clipping because this glyph string
3505 intentionally draws over other lines. */
3506 if (s
->for_overlaps_p
)
3508 r
->top
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
3509 r_height
= window_text_bottom_y (s
->w
) - r
->top
;
3513 /* Don't use S->y for clipping because it doesn't take partially
3514 visible lines into account. For example, it can be negative for
3515 partially visible lines at the top of a window. */
3516 if (!s
->row
->full_width_p
3517 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
3518 r
->top
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
3520 r
->top
= max (0, s
->row
->y
);
3522 /* If drawing a tool-bar window, draw it over the internal border
3523 at the top of the window. */
3524 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
3525 r
->top
-= s
->f
->output_data
.mac
->internal_border_width
;
3528 r
->top
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->top
);
3530 r
->bottom
= r
->top
+ r_height
;
3531 r
->right
= r
->left
+ r_width
;
3535 /* Set clipping for output of glyph string S. S may be part of a mode
3536 line or menu if we don't have X toolkit support. */
3539 x_set_glyph_string_clipping (s
)
3540 struct glyph_string
*s
;
3543 x_get_glyph_string_clip_rect (s
, &r
);
3544 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3548 /* Compute left and right overhang of glyph string S. If S is a glyph
3549 string for a composition, assume overhangs don't exist. */
3552 x_compute_glyph_string_overhangs (s
)
3553 struct glyph_string
*s
;
3556 && s
->first_glyph
->type
== CHAR_GLYPH
)
3559 int direction
, font_ascent
, font_descent
;
3560 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
3561 &font_ascent
, &font_descent
, &cs
);
3562 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
3563 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
3568 /* Compute overhangs and x-positions for glyph string S and its
3569 predecessors, or successors. X is the starting x-position for S.
3570 BACKWARD_P non-zero means process predecessors. */
3573 x_compute_overhangs_and_x (s
, x
, backward_p
)
3574 struct glyph_string
*s
;
3582 x_compute_glyph_string_overhangs (s
);
3592 x_compute_glyph_string_overhangs (s
);
3601 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3602 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3603 assumed to be zero. */
3606 x_get_glyph_overhangs (glyph
, f
, left
, right
)
3607 struct glyph
*glyph
;
3613 if (glyph
->type
== CHAR_GLYPH
)
3617 struct font_info
*font_info
;
3621 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
, NULL
);
3623 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
3625 && (pcm
= x_per_char_metric (font
, &char2b
)))
3627 if (pcm
->rbearing
> pcm
->width
)
3628 *right
= pcm
->rbearing
- pcm
->width
;
3629 if (pcm
->lbearing
< 0)
3630 *left
= -pcm
->lbearing
;
3636 /* Return the index of the first glyph preceding glyph string S that
3637 is overwritten by S because of S's left overhang. Value is -1
3638 if no glyphs are overwritten. */
3641 x_left_overwritten (s
)
3642 struct glyph_string
*s
;
3646 if (s
->left_overhang
)
3649 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3650 int first
= s
->first_glyph
- glyphs
;
3652 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
3653 x
-= glyphs
[i
].pixel_width
;
3664 /* Return the index of the first glyph preceding glyph string S that
3665 is overwriting S because of its right overhang. Value is -1 if no
3666 glyph in front of S overwrites S. */
3669 x_left_overwriting (s
)
3670 struct glyph_string
*s
;
3673 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3674 int first
= s
->first_glyph
- glyphs
;
3678 for (i
= first
- 1; i
>= 0; --i
)
3681 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3684 x
-= glyphs
[i
].pixel_width
;
3691 /* Return the index of the last glyph following glyph string S that is
3692 not overwritten by S because of S's right overhang. Value is -1 if
3693 no such glyph is found. */
3696 x_right_overwritten (s
)
3697 struct glyph_string
*s
;
3701 if (s
->right_overhang
)
3704 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3705 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3706 int end
= s
->row
->used
[s
->area
];
3708 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
3709 x
+= glyphs
[i
].pixel_width
;
3718 /* Return the index of the last glyph following glyph string S that
3719 overwrites S because of its left overhang. Value is negative
3720 if no such glyph is found. */
3723 x_right_overwriting (s
)
3724 struct glyph_string
*s
;
3727 int end
= s
->row
->used
[s
->area
];
3728 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3729 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3733 for (i
= first
; i
< end
; ++i
)
3736 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3739 x
+= glyphs
[i
].pixel_width
;
3746 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3749 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
3750 struct glyph_string
*s
;
3755 xgcv
.foreground
= s
->gc
->background
;
3756 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
3760 /* Draw the background of glyph_string S. If S->background_filled_p
3761 is non-zero don't draw it. FORCE_P non-zero means draw the
3762 background even if it wouldn't be drawn normally. This is used
3763 when a string preceding S draws into the background of S, or S
3764 contains the first component of a composition. */
3767 x_draw_glyph_string_background (s
, force_p
)
3768 struct glyph_string
*s
;
3771 /* Nothing to do if background has already been drawn or if it
3772 shouldn't be drawn in the first place. */
3773 if (!s
->background_filled_p
)
3775 int box_line_width
= max (s
->face
->box_line_width
, 0);
3777 #if 0 /* MAC_TODO: stipple */
3780 /* Fill background with a stipple pattern. */
3781 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3782 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
3783 s
->y
+ box_line_width
,
3784 s
->background_width
,
3785 s
->height
- 2 * box_line_width
);
3786 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3787 s
->background_filled_p
= 1;
3791 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
3792 || s
->font_not_found_p
3793 || s
->extends_to_end_of_line_p
3796 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
3797 s
->background_width
,
3798 s
->height
- 2 * box_line_width
);
3799 s
->background_filled_p
= 1;
3805 /* Draw the foreground of glyph string S. */
3808 x_draw_glyph_string_foreground (s
)
3809 struct glyph_string
*s
;
3813 /* If first glyph of S has a left box line, start drawing the text
3814 of S to the right of that box line. */
3815 if (s
->face
->box
!= FACE_NO_BOX
3816 && s
->first_glyph
->left_box_line_p
)
3817 x
= s
->x
+ abs (s
->face
->box_line_width
);
3821 /* Draw characters of S as rectangles if S's font could not be
3823 if (s
->font_not_found_p
)
3825 for (i
= 0; i
< s
->nchars
; ++i
)
3827 struct glyph
*g
= s
->first_glyph
+ i
;
3828 mac_draw_rectangle (s
->display
, s
->window
,
3829 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
3831 x
+= g
->pixel_width
;
3836 char *char1b
= (char *) s
->char2b
;
3837 int boff
= s
->font_info
->baseline_offset
;
3839 if (s
->font_info
->vertical_centering
)
3840 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3842 /* If we can use 8-bit functions, condense S->char2b. */
3844 for (i
= 0; i
< s
->nchars
; ++i
)
3845 char1b
[i
] = s
->char2b
[i
].byte2
;
3847 /* Draw text with XDrawString if background has already been
3848 filled. Otherwise, use XDrawImageString. (Note that
3849 XDrawImageString is usually faster than XDrawString.) Always
3850 use XDrawImageString when drawing the cursor so that there is
3851 no chance that characters under a box cursor are invisible. */
3852 if (s
->for_overlaps_p
3853 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3855 /* Draw characters with 16-bit or 8-bit functions. */
3857 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
3858 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3860 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
3861 s
->ybase
- boff
, char1b
, s
->nchars
);
3866 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
3867 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3869 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
3870 s
->ybase
- boff
, char1b
, s
->nchars
);
3875 /* Draw the foreground of composite glyph string S. */
3878 x_draw_composite_glyph_string_foreground (s
)
3879 struct glyph_string
*s
;
3883 /* If first glyph of S has a left box line, start drawing the text
3884 of S to the right of that box line. */
3885 if (s
->face
->box
!= FACE_NO_BOX
3886 && s
->first_glyph
->left_box_line_p
)
3887 x
= s
->x
+ abs (s
->face
->box_line_width
);
3891 /* S is a glyph string for a composition. S->gidx is the index of
3892 the first character drawn for glyphs of this composition.
3893 S->gidx == 0 means we are drawing the very first character of
3894 this composition. */
3896 /* Draw a rectangle for the composition if the font for the very
3897 first character of the composition could not be loaded. */
3898 if (s
->font_not_found_p
)
3901 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
3902 s
->width
- 1, s
->height
- 1);
3906 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3907 XDrawString16 (s
->display
, s
->window
, s
->gc
,
3908 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3909 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3915 #ifdef USE_X_TOOLKIT
3917 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3920 /* Return the frame on which widget WIDGET is used.. Abort if frame
3921 cannot be determined. */
3923 static struct frame
*
3924 x_frame_of_widget (widget
)
3927 struct x_display_info
*dpyinfo
;
3931 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3933 /* Find the top-level shell of the widget. Note that this function
3934 can be called when the widget is not yet realized, so XtWindow
3935 (widget) == 0. That's the reason we can't simply use
3936 x_any_window_to_frame. */
3937 while (!XtIsTopLevelShell (widget
))
3938 widget
= XtParent (widget
);
3940 /* Look for a frame with that top-level widget. Allocate the color
3941 on that frame to get the right gamma correction value. */
3942 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3943 if (GC_FRAMEP (XCAR (tail
))
3944 && (f
= XFRAME (XCAR (tail
)),
3945 (f
->output_data
.nothing
!= 1
3946 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3947 && f
->output_data
.x
->widget
== widget
)
3954 /* Allocate the color COLOR->pixel on the screen and display of
3955 widget WIDGET in colormap CMAP. If an exact match cannot be
3956 allocated, try the nearest color available. Value is non-zero
3957 if successful. This is called from lwlib. */
3960 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3965 struct frame
*f
= x_frame_of_widget (widget
);
3966 return x_alloc_nearest_color (f
, cmap
, color
);
3970 #endif /* USE_X_TOOLKIT */
3972 #if 0 /* MAC_TODO */
3974 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3975 CMAP. If an exact match can't be allocated, try the nearest color
3976 available. Value is non-zero if successful. Set *COLOR to the
3980 x_alloc_nearest_color (f
, cmap
, color
)
3985 Display
*display
= FRAME_X_DISPLAY (f
);
3986 Screen
*screen
= FRAME_X_SCREEN (f
);
3989 gamma_correct (f
, color
);
3990 rc
= XAllocColor (display
, cmap
, color
);
3993 /* If we got to this point, the colormap is full, so we're going
3994 to try to get the next closest color. The algorithm used is
3995 a least-squares matching, which is what X uses for closest
3996 color matching with StaticColor visuals. */
3998 unsigned long nearest_delta
= ~0;
3999 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
4000 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
4002 for (i
= 0; i
< ncells
; ++i
)
4004 XQueryColors (display
, cmap
, cells
, ncells
);
4006 for (nearest
= i
= 0; i
< ncells
; ++i
)
4008 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
4009 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
4010 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
4011 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
4013 if (delta
< nearest_delta
)
4016 nearest_delta
= delta
;
4020 color
->red
= cells
[nearest
].red
;
4021 color
->green
= cells
[nearest
].green
;
4022 color
->blue
= cells
[nearest
].blue
;
4023 rc
= XAllocColor (display
, cmap
, color
);
4026 #ifdef DEBUG_X_COLORS
4028 register_color (color
->pixel
);
4029 #endif /* DEBUG_X_COLORS */
4035 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4036 It's necessary to do this instead of just using PIXEL directly to
4037 get color reference counts right. */
4040 x_copy_color (f
, pixel
)
4042 unsigned long pixel
;
4046 color
.pixel
= pixel
;
4048 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
4049 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
4051 #ifdef DEBUG_X_COLORS
4052 register_color (pixel
);
4058 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4059 It's necessary to do this instead of just using PIXEL directly to
4060 get color reference counts right. */
4063 x_copy_dpy_color (dpy
, cmap
, pixel
)
4066 unsigned long pixel
;
4070 color
.pixel
= pixel
;
4072 XQueryColor (dpy
, cmap
, &color
);
4073 XAllocColor (dpy
, cmap
, &color
);
4075 #ifdef DEBUG_X_COLORS
4076 register_color (pixel
);
4081 #endif /* MAC_TODO */
4083 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4084 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4085 If this produces the same color as COLOR, try a color where all RGB
4086 values have DELTA added. Return the allocated color in *COLOR.
4087 DISPLAY is the X display, CMAP is the colormap to operate on.
4088 Value is non-zero if successful. */
4091 mac_alloc_lighter_color (f
, color
, factor
, delta
)
4093 unsigned long *color
;
4099 /* Change RGB values by specified FACTOR. Avoid overflow! */
4100 xassert (factor
>= 0);
4101 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
4102 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
4103 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
4105 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
4106 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
4107 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
4109 /* MAC_TODO: Map to palette and retry with delta if same? */
4110 /* MAC_TODO: Free colors (if using palette)? */
4121 /* Set up the foreground color for drawing relief lines of glyph
4122 string S. RELIEF is a pointer to a struct relief containing the GC
4123 with which lines will be drawn. Use a color that is FACTOR or
4124 DELTA lighter or darker than the relief's background which is found
4125 in S->f->output_data.x->relief_background. If such a color cannot
4126 be allocated, use DEFAULT_PIXEL, instead. */
4129 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
4131 struct relief
*relief
;
4134 unsigned long default_pixel
;
4137 struct mac_output
*di
= f
->output_data
.mac
;
4138 unsigned long mask
= GCForeground
;
4139 unsigned long pixel
;
4140 unsigned long background
= di
->relief_background
;
4141 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4143 /* MAC_TODO: Free colors (if using palette)? */
4145 /* Allocate new color. */
4146 xgcv
.foreground
= default_pixel
;
4148 if (mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
4150 relief
->allocated_p
= 1;
4151 xgcv
.foreground
= relief
->pixel
= pixel
;
4154 if (relief
->gc
== 0)
4156 #if 0 /* MAC_TODO: stipple */
4157 xgcv
.stipple
= dpyinfo
->gray
;
4160 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
4163 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
4167 /* Set up colors for the relief lines around glyph string S. */
4170 x_setup_relief_colors (s
)
4171 struct glyph_string
*s
;
4173 struct mac_output
*di
= s
->f
->output_data
.mac
;
4174 unsigned long color
;
4176 if (s
->face
->use_box_color_for_shadows_p
)
4177 color
= s
->face
->box_color
;
4182 /* Get the background color of the face. */
4183 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
4184 color
= xgcv
.background
;
4187 if (di
->white_relief
.gc
== 0
4188 || color
!= di
->relief_background
)
4190 di
->relief_background
= color
;
4191 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
4192 WHITE_PIX_DEFAULT (s
->f
));
4193 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
4194 BLACK_PIX_DEFAULT (s
->f
));
4199 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4200 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4201 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4202 relief. LEFT_P non-zero means draw a relief on the left side of
4203 the rectangle. RIGHT_P non-zero means draw a relief on the right
4204 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4208 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
4209 raised_p
, left_p
, right_p
, clip_rect
)
4211 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
4218 gc
= f
->output_data
.mac
->white_relief
.gc
;
4220 gc
= f
->output_data
.mac
->black_relief
.gc
;
4221 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), clip_rect
);
4224 for (i
= 0; i
< width
; ++i
)
4225 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
4226 left_x
+ i
* left_p
, top_y
+ i
,
4227 right_x
+ 1 - i
* right_p
, top_y
+ i
);
4231 for (i
= 0; i
< width
; ++i
)
4232 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
4233 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
4235 mac_reset_clipping (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
4237 gc
= f
->output_data
.mac
->black_relief
.gc
;
4239 gc
= f
->output_data
.mac
->white_relief
.gc
;
4240 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4244 for (i
= 0; i
< width
; ++i
)
4245 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
4246 left_x
+ i
* left_p
, bottom_y
- i
,
4247 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
4251 for (i
= 0; i
< width
; ++i
)
4252 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), gc
,
4253 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
4255 mac_reset_clipping (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
4259 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4260 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4261 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4262 left side of the rectangle. RIGHT_P non-zero means draw a line
4263 on the right side of the rectangle. CLIP_RECT is the clipping
4264 rectangle to use when drawing. */
4267 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
4268 left_p
, right_p
, clip_rect
)
4269 struct glyph_string
*s
;
4270 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
4275 xgcv
.foreground
= s
->face
->box_color
;
4276 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
4279 XFillRectangle (s
->display
, s
->window
, &xgcv
,
4280 left_x
, top_y
, right_x
- left_x
, width
);
4284 XFillRectangle (s
->display
, s
->window
, &xgcv
,
4285 left_x
, top_y
, width
, bottom_y
- top_y
);
4288 XFillRectangle (s
->display
, s
->window
, &xgcv
,
4289 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
4293 XFillRectangle (s
->display
, s
->window
, &xgcv
,
4294 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
4296 mac_reset_clipping (s
->display
, s
->window
);
4300 /* Draw a box around glyph string S. */
4303 x_draw_glyph_string_box (s
)
4304 struct glyph_string
*s
;
4306 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
4307 int left_p
, right_p
;
4308 struct glyph
*last_glyph
;
4311 last_x
= window_box_right (s
->w
, s
->area
);
4312 if (s
->row
->full_width_p
4313 && !s
->w
->pseudo_window_p
)
4315 last_x
+= FRAME_X_RIGHT_FRINGE_WIDTH (s
->f
);
4316 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
4317 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
4320 /* The glyph that may have a right box line. */
4321 last_glyph
= (s
->cmp
|| s
->img
4323 : s
->first_glyph
+ s
->nchars
- 1);
4325 width
= abs (s
->face
->box_line_width
);
4326 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
4328 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
4330 : min (last_x
, s
->x
+ s
->background_width
) - 1));
4332 bottom_y
= top_y
+ s
->height
- 1;
4334 left_p
= (s
->first_glyph
->left_box_line_p
4335 || (s
->hl
== DRAW_MOUSE_FACE
4337 || s
->prev
->hl
!= s
->hl
)));
4338 right_p
= (last_glyph
->right_box_line_p
4339 || (s
->hl
== DRAW_MOUSE_FACE
4341 || s
->next
->hl
!= s
->hl
)));
4343 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4345 if (s
->face
->box
== FACE_SIMPLE_BOX
)
4346 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
4347 left_p
, right_p
, &clip_rect
);
4350 x_setup_relief_colors (s
);
4351 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
4352 width
, raised_p
, left_p
, right_p
, &clip_rect
);
4357 /* Draw foreground of image glyph string S. */
4360 x_draw_image_foreground (s
)
4361 struct glyph_string
*s
;
4364 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
4366 /* If first glyph of S has a left box line, start drawing it to the
4367 right of that line. */
4368 if (s
->face
->box
!= FACE_NO_BOX
4369 && s
->first_glyph
->left_box_line_p
)
4370 x
= s
->x
+ abs (s
->face
->box_line_width
);
4374 /* If there is a margin around the image, adjust x- and y-position
4376 x
+= s
->img
->hmargin
;
4377 y
+= s
->img
->vmargin
;
4381 #if 0 /* MAC_TODO: image mask */
4384 /* We can't set both a clip mask and use XSetClipRectangles
4385 because the latter also sets a clip mask. We also can't
4386 trust on the shape extension to be available
4387 (XShapeCombineRegion). So, compute the rectangle to draw
4389 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4392 XRectangle clip_rect
, image_rect
, r
;
4394 xgcv
.clip_mask
= s
->img
->mask
;
4395 xgcv
.clip_x_origin
= x
;
4396 xgcv
.clip_y_origin
= y
;
4397 xgcv
.function
= GXcopy
;
4398 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4400 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4403 image_rect
.width
= s
->img
->width
;
4404 image_rect
.height
= s
->img
->height
;
4405 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
4406 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
4407 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
4410 #endif /* MAC_TODO */
4412 mac_copy_area (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
4413 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4415 /* When the image has a mask, we can expect that at
4416 least part of a mouse highlight or a block cursor will
4417 be visible. If the image doesn't have a mask, make
4418 a block cursor visible by drawing a rectangle around
4419 the image. I believe it's looking better if we do
4420 nothing here for mouse-face. */
4421 if (s
->hl
== DRAW_CURSOR
)
4423 int r
= s
->img
->relief
;
4425 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
4426 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
4431 /* Draw a rectangle if image could not be loaded. */
4432 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
4433 s
->img
->width
- 1, s
->img
->height
- 1);
4438 /* Draw a relief around the image glyph string S. */
4441 x_draw_image_relief (s
)
4442 struct glyph_string
*s
;
4444 int x0
, y0
, x1
, y1
, thick
, raised_p
;
4447 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
4449 /* If first glyph of S has a left box line, start drawing it to the
4450 right of that line. */
4451 if (s
->face
->box
!= FACE_NO_BOX
4452 && s
->first_glyph
->left_box_line_p
)
4453 x
= s
->x
+ abs (s
->face
->box_line_width
);
4457 /* If there is a margin around the image, adjust x- and y-position
4459 x
+= s
->img
->hmargin
;
4460 y
+= s
->img
->vmargin
;
4462 if (s
->hl
== DRAW_IMAGE_SUNKEN
4463 || s
->hl
== DRAW_IMAGE_RAISED
)
4465 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
4466 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
4470 thick
= abs (s
->img
->relief
);
4471 raised_p
= s
->img
->relief
> 0;
4476 x1
= x
+ s
->img
->width
+ thick
- 1;
4477 y1
= y
+ s
->img
->height
+ thick
- 1;
4479 x_setup_relief_colors (s
);
4480 x_get_glyph_string_clip_rect (s
, &r
);
4481 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
4485 /* Draw the foreground of image glyph string S to PIXMAP. */
4488 x_draw_image_foreground_1 (s
, pixmap
)
4489 struct glyph_string
*s
;
4493 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
4495 /* If first glyph of S has a left box line, start drawing it to the
4496 right of that line. */
4497 if (s
->face
->box
!= FACE_NO_BOX
4498 && s
->first_glyph
->left_box_line_p
)
4499 x
= abs (s
->face
->box_line_width
);
4503 /* If there is a margin around the image, adjust x- and y-position
4505 x
+= s
->img
->hmargin
;
4506 y
+= s
->img
->vmargin
;
4510 #if 0 /* MAC_TODO: image mask */
4513 /* We can't set both a clip mask and use XSetClipRectangles
4514 because the latter also sets a clip mask. We also can't
4515 trust on the shape extension to be available
4516 (XShapeCombineRegion). So, compute the rectangle to draw
4518 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4522 xgcv
.clip_mask
= s
->img
->mask
;
4523 xgcv
.clip_x_origin
= x
;
4524 xgcv
.clip_y_origin
= y
;
4525 xgcv
.function
= GXcopy
;
4526 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4528 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4529 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4530 XSetClipMask (s
->display
, s
->gc
, None
);
4533 #endif /* MAC_TODO */
4535 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4536 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4538 /* When the image has a mask, we can expect that at
4539 least part of a mouse highlight or a block cursor will
4540 be visible. If the image doesn't have a mask, make
4541 a block cursor visible by drawing a rectangle around
4542 the image. I believe it's looking better if we do
4543 nothing here for mouse-face. */
4544 if (s
->hl
== DRAW_CURSOR
)
4546 int r
= s
->img
->relief
;
4548 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
- r
, y
- r
,
4549 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
4554 /* Draw a rectangle if image could not be loaded. */
4555 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
4556 s
->img
->width
- 1, s
->img
->height
- 1);
4560 /* Draw part of the background of glyph string S. X, Y, W, and H
4561 give the rectangle to draw. */
4564 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
4565 struct glyph_string
*s
;
4568 #if 0 /* MAC_TODO: stipple */
4571 /* Fill background with a stipple pattern. */
4572 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4573 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
4574 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4577 #endif /* MAC_TODO */
4578 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
4582 /* Draw image glyph string S.
4585 s->x +-------------------------
4588 | +-------------------------
4591 | | +-------------------
4597 x_draw_image_glyph_string (s
)
4598 struct glyph_string
*s
;
4601 int box_line_hwidth
= abs (s
->face
->box_line_width
);
4602 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
4606 height
= s
->height
- 2 * box_line_vwidth
;
4608 /* Fill background with face under the image. Do it only if row is
4609 taller than image or if image has a clip mask to reduce
4611 s
->stippled_p
= s
->face
->stipple
!= 0;
4612 if (height
> s
->img
->height
4615 #if 0 /* TODO: image mask */
4618 || s
->img
->pixmap
== 0
4619 || s
->width
!= s
->background_width
)
4621 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
4622 x
= s
->x
+ box_line_hwidth
;
4626 y
= s
->y
+ box_line_vwidth
;
4627 #if 0 /* TODO: image mask */
4630 /* Create a pixmap as large as the glyph string. Fill it
4631 with the background color. Copy the image to it, using
4632 its mask. Copy the temporary pixmap to the display. */
4633 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
4634 int depth
= DefaultDepthOfScreen (screen
);
4636 /* Create a pixmap as large as the glyph string. */
4637 pixmap
= XCreatePixmap (s
->display
, s
->window
,
4638 s
->background_width
,
4641 /* Don't clip in the following because we're working on the
4643 XSetClipMask (s
->display
, s
->gc
, None
);
4645 /* Fill the pixmap with the background color/stipple. */
4648 /* Fill background with a stipple pattern. */
4649 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4650 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4651 0, 0, s
->background_width
, s
->height
);
4652 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4657 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
4659 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
4660 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4661 0, 0, s
->background_width
, s
->height
);
4662 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4667 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
4669 s
->background_filled_p
= 1;
4672 /* Draw the foreground. */
4675 x_draw_image_foreground_1 (s
, pixmap
);
4676 x_set_glyph_string_clipping (s
);
4677 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
4678 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
4679 mac_reset_clipping (s
->display
, s
->window
);
4680 XFreePixmap (s
->display
, pixmap
);
4683 x_draw_image_foreground (s
);
4685 /* If we must draw a relief around the image, do it. */
4687 || s
->hl
== DRAW_IMAGE_RAISED
4688 || s
->hl
== DRAW_IMAGE_SUNKEN
)
4689 x_draw_image_relief (s
);
4693 /* Draw stretch glyph string S. */
4696 x_draw_stretch_glyph_string (s
)
4697 struct glyph_string
*s
;
4699 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4700 s
->stippled_p
= s
->face
->stipple
!= 0;
4702 if (s
->hl
== DRAW_CURSOR
4703 && !x_stretch_cursor_p
)
4705 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4706 as wide as the stretch glyph. */
4707 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
4710 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
4712 /* Clear rest using the GC of the original non-cursor face. */
4713 if (width
< s
->background_width
)
4715 GC gc
= s
->face
->gc
;
4716 int x
= s
->x
+ width
, y
= s
->y
;
4717 int w
= s
->background_width
- width
, h
= s
->height
;
4720 if (s
->row
->mouse_face_p
4721 && cursor_in_mouse_face_p (s
->w
))
4723 x_set_mouse_face_gc (s
);
4729 x_get_glyph_string_clip_rect (s
, &r
);
4730 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
4732 #if 0 /* MAC_TODO: stipple */
4733 if (s
->face
->stipple
)
4735 /* Fill background with a stipple pattern. */
4736 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
4737 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4738 XSetFillStyle (s
->display
, gc
, FillSolid
);
4741 #endif /* MAC_TODO */
4744 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
4745 XSetForeground (s
->display
, gc
, xgcv
.background
);
4746 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4747 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
4750 mac_reset_clipping (s
->display
, s
->window
);
4753 else if (!s
->background_filled_p
)
4754 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
4757 s
->background_filled_p
= 1;
4761 /* Draw glyph string S. */
4764 x_draw_glyph_string (s
)
4765 struct glyph_string
*s
;
4767 int relief_drawn_p
= 0;
4769 /* If S draws into the background of its successor, draw the
4770 background of the successor first so that S can draw into it.
4771 This makes S->next use XDrawString instead of XDrawImageString. */
4772 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
4774 xassert (s
->next
->img
== NULL
);
4775 x_set_glyph_string_gc (s
->next
);
4776 x_set_glyph_string_clipping (s
->next
);
4777 x_draw_glyph_string_background (s
->next
, 1);
4781 /* Set up S->gc, set clipping and draw S. */
4782 x_set_glyph_string_gc (s
);
4784 /* Draw relief (if any) in advance for char/composition so that the
4785 glyph string can be drawn over it. */
4786 if (!s
->for_overlaps_p
4787 && s
->face
->box
!= FACE_NO_BOX
4788 && (s
->first_glyph
->type
== CHAR_GLYPH
4789 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
4792 x_set_glyph_string_clipping (s
);
4793 x_draw_glyph_string_background (s
, 1);
4794 x_draw_glyph_string_box (s
);
4795 x_set_glyph_string_clipping (s
);
4799 x_set_glyph_string_clipping (s
);
4801 switch (s
->first_glyph
->type
)
4804 x_draw_image_glyph_string (s
);
4808 x_draw_stretch_glyph_string (s
);
4812 if (s
->for_overlaps_p
)
4813 s
->background_filled_p
= 1;
4815 x_draw_glyph_string_background (s
, 0);
4816 x_draw_glyph_string_foreground (s
);
4819 case COMPOSITE_GLYPH
:
4820 if (s
->for_overlaps_p
|| s
->gidx
> 0)
4821 s
->background_filled_p
= 1;
4823 x_draw_glyph_string_background (s
, 1);
4824 x_draw_composite_glyph_string_foreground (s
);
4831 if (!s
->for_overlaps_p
)
4833 /* Draw underline. */
4834 if (s
->face
->underline_p
)
4836 unsigned long h
= 1;
4837 unsigned long dy
= s
->height
- h
;
4839 if (s
->face
->underline_defaulted_p
)
4840 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4845 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4846 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4847 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4849 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4853 /* Draw overline. */
4854 if (s
->face
->overline_p
)
4856 unsigned long dy
= 0, h
= 1;
4858 if (s
->face
->overline_color_defaulted_p
)
4859 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4864 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4865 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4866 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4868 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4872 /* Draw strike-through. */
4873 if (s
->face
->strike_through_p
)
4875 unsigned long h
= 1;
4876 unsigned long dy
= (s
->height
- h
) / 2;
4878 if (s
->face
->strike_through_color_defaulted_p
)
4879 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4884 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4885 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4886 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4888 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4893 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4894 x_draw_glyph_string_box (s
);
4897 /* Reset clipping. */
4898 mac_reset_clipping (s
->display
, s
->window
);
4902 static int x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
4903 struct face
**, int));
4906 /* Fill glyph string S with composition components specified by S->cmp.
4908 FACES is an array of faces for all components of this composition.
4909 S->gidx is the index of the first component for S.
4910 OVERLAPS_P non-zero means S should draw the foreground only, and
4911 use its physical height for clipping.
4913 Value is the index of a component not in S. */
4916 x_fill_composite_glyph_string (s
, faces
, overlaps_p
)
4917 struct glyph_string
*s
;
4918 struct face
**faces
;
4925 s
->for_overlaps_p
= overlaps_p
;
4927 s
->face
= faces
[s
->gidx
];
4928 s
->font
= s
->face
->font
;
4929 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4931 /* For all glyphs of this composition, starting at the offset
4932 S->gidx, until we reach the end of the definition or encounter a
4933 glyph that requires the different face, add it to S. */
4935 for (i
= s
->gidx
+ 1; i
< s
->cmp
->glyph_len
&& faces
[i
] == s
->face
; ++i
)
4938 /* All glyph strings for the same composition has the same width,
4939 i.e. the width set for the first component of the composition. */
4941 s
->width
= s
->first_glyph
->pixel_width
;
4943 /* If the specified font could not be loaded, use the frame's
4944 default font, but record the fact that we couldn't load it in
4945 the glyph string so that we can draw rectangles for the
4946 characters of the glyph string. */
4947 if (s
->font
== NULL
)
4949 s
->font_not_found_p
= 1;
4950 s
->font
= FRAME_FONT (s
->f
);
4953 /* Adjust base line for subscript/superscript text. */
4954 s
->ybase
+= s
->first_glyph
->voffset
;
4956 xassert (s
->face
&& s
->face
->gc
);
4958 /* This glyph string must always be drawn with 16-bit functions. */
4961 return s
->gidx
+ s
->nchars
;
4965 /* Fill glyph string S from a sequence of character glyphs.
4967 FACE_ID is the face id of the string. START is the index of the
4968 first glyph to consider, END is the index of the last + 1.
4969 OVERLAPS_P non-zero means S should draw the foreground only, and
4970 use its physical height for clipping.
4972 Value is the index of the first glyph not in S. */
4975 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
4976 struct glyph_string
*s
;
4978 int start
, end
, overlaps_p
;
4980 struct glyph
*glyph
, *last
;
4982 int glyph_not_available_p
;
4984 xassert (s
->f
== XFRAME (s
->w
->frame
));
4985 xassert (s
->nchars
== 0);
4986 xassert (start
>= 0 && end
> start
);
4988 s
->for_overlaps_p
= overlaps_p
;
4989 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4990 last
= s
->row
->glyphs
[s
->area
] + end
;
4991 voffset
= glyph
->voffset
;
4993 glyph_not_available_p
= glyph
->glyph_not_available_p
;
4996 && glyph
->type
== CHAR_GLYPH
4997 && glyph
->voffset
== voffset
4998 /* Same face id implies same font, nowadays. */
4999 && glyph
->face_id
== face_id
5000 && glyph
->glyph_not_available_p
== glyph_not_available_p
)
5004 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
5005 s
->char2b
+ s
->nchars
,
5007 s
->two_byte_p
= two_byte_p
;
5009 xassert (s
->nchars
<= end
- start
);
5010 s
->width
+= glyph
->pixel_width
;
5014 s
->font
= s
->face
->font
;
5015 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
5017 /* If the specified font could not be loaded, use the frame's font,
5018 but record the fact that we couldn't load it in
5019 S->font_not_found_p so that we can draw rectangles for the
5020 characters of the glyph string. */
5021 if (s
->font
== NULL
|| glyph_not_available_p
)
5023 s
->font_not_found_p
= 1;
5024 s
->font
= FRAME_FONT (s
->f
);
5027 /* Adjust base line for subscript/superscript text. */
5028 s
->ybase
+= voffset
;
5030 xassert (s
->face
&& s
->face
->gc
);
5031 return glyph
- s
->row
->glyphs
[s
->area
];
5035 /* Fill glyph string S from image glyph S->first_glyph. */
5038 x_fill_image_glyph_string (s
)
5039 struct glyph_string
*s
;
5041 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
5042 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img_id
);
5044 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->face_id
);
5045 s
->font
= s
->face
->font
;
5046 s
->width
= s
->first_glyph
->pixel_width
;
5048 /* Adjust base line for subscript/superscript text. */
5049 s
->ybase
+= s
->first_glyph
->voffset
;
5053 /* Fill glyph string S from a sequence of stretch glyphs.
5055 ROW is the glyph row in which the glyphs are found, AREA is the
5056 area within the row. START is the index of the first glyph to
5057 consider, END is the index of the last + 1.
5059 Value is the index of the first glyph not in S. */
5062 x_fill_stretch_glyph_string (s
, row
, area
, start
, end
)
5063 struct glyph_string
*s
;
5064 struct glyph_row
*row
;
5065 enum glyph_row_area area
;
5068 struct glyph
*glyph
, *last
;
5069 int voffset
, face_id
;
5071 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
5073 glyph
= s
->row
->glyphs
[s
->area
] + start
;
5074 last
= s
->row
->glyphs
[s
->area
] + end
;
5075 face_id
= glyph
->face_id
;
5076 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
5077 s
->font
= s
->face
->font
;
5078 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
5079 s
->width
= glyph
->pixel_width
;
5080 voffset
= glyph
->voffset
;
5084 && glyph
->type
== STRETCH_GLYPH
5085 && glyph
->voffset
== voffset
5086 && glyph
->face_id
== face_id
);
5088 s
->width
+= glyph
->pixel_width
;
5090 /* Adjust base line for subscript/superscript text. */
5091 s
->ybase
+= voffset
;
5094 return glyph
- s
->row
->glyphs
[s
->area
];
5098 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5099 of XChar2b structures for S; it can't be allocated in
5100 x_init_glyph_string because it must be allocated via `alloca'. W
5101 is the window on which S is drawn. ROW and AREA are the glyph row
5102 and area within the row from which S is constructed. START is the
5103 index of the first glyph structure covered by S. HL is a
5104 face-override for drawing S. */
5107 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
5108 struct glyph_string
*s
;
5111 struct glyph_row
*row
;
5112 enum glyph_row_area area
;
5114 enum draw_glyphs_face hl
;
5116 bzero (s
, sizeof *s
);
5118 s
->f
= XFRAME (w
->frame
);
5119 s
->display
= FRAME_MAC_DISPLAY (s
->f
);
5120 s
->window
= FRAME_MAC_WINDOW (s
->f
);
5125 s
->first_glyph
= row
->glyphs
[area
] + start
;
5126 s
->height
= row
->height
;
5127 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5129 /* Display the internal border below the tool-bar window. */
5130 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
5131 s
->y
-= s
->f
->output_data
.mac
->internal_border_width
;
5133 s
->ybase
= s
->y
+ row
->ascent
;
5137 /* Set background width of glyph string S. START is the index of the
5138 first glyph following S. LAST_X is the right-most x-position + 1
5139 in the drawing area. */
5142 x_set_glyph_string_background_width (s
, start
, last_x
)
5143 struct glyph_string
*s
;
5147 /* If the face of this glyph string has to be drawn to the end of
5148 the drawing area, set S->extends_to_end_of_line_p. */
5149 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
5151 if (start
== s
->row
->used
[s
->area
]
5152 && s
->area
== TEXT_AREA
5153 && ((s
->hl
== DRAW_NORMAL_TEXT
5154 && (s
->row
->fill_line_p
5155 || s
->face
->background
!= default_face
->background
5156 || s
->face
->stipple
!= default_face
->stipple
5157 || s
->row
->mouse_face_p
))
5158 || s
->hl
== DRAW_MOUSE_FACE
5159 || ((s
->hl
== DRAW_IMAGE_RAISED
|| s
->hl
== DRAW_IMAGE_SUNKEN
)
5160 && s
->row
->fill_line_p
)))
5161 s
->extends_to_end_of_line_p
= 1;
5163 /* If S extends its face to the end of the line, set its
5164 background_width to the distance to the right edge of the drawing
5166 if (s
->extends_to_end_of_line_p
)
5167 s
->background_width
= last_x
- s
->x
+ 1;
5169 s
->background_width
= s
->width
;
5173 /* Add a glyph string for a stretch glyph to the list of strings
5174 between HEAD and TAIL. START is the index of the stretch glyph in
5175 row area AREA of glyph row ROW. END is the index of the last glyph
5176 in that glyph row area. X is the current output position assigned
5177 to the new glyph string constructed. HL overrides that face of the
5178 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5179 is the right-most x-position of the drawing area. */
5181 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5182 and below -- keep them on one line. */
5183 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5186 s = (struct glyph_string *) alloca (sizeof *s); \
5187 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5188 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5189 x_append_glyph_string (&HEAD, &TAIL, s); \
5195 /* Add a glyph string for an image glyph to the list of strings
5196 between HEAD and TAIL. START is the index of the image glyph in
5197 row area AREA of glyph row ROW. END is the index of the last glyph
5198 in that glyph row area. X is the current output position assigned
5199 to the new glyph string constructed. HL overrides that face of the
5200 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5201 is the right-most x-position of the drawing area. */
5203 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5206 s = (struct glyph_string *) alloca (sizeof *s); \
5207 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5208 x_fill_image_glyph_string (s); \
5209 x_append_glyph_string (&HEAD, &TAIL, s); \
5216 /* Add a glyph string for a sequence of character glyphs to the list
5217 of strings between HEAD and TAIL. START is the index of the first
5218 glyph in row area AREA of glyph row ROW that is part of the new
5219 glyph string. END is the index of the last glyph in that glyph row
5220 area. X is the current output position assigned to the new glyph
5221 string constructed. HL overrides that face of the glyph; e.g. it
5222 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5223 right-most x-position of the drawing area. */
5225 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5231 c = (ROW)->glyphs[AREA][START].u.ch; \
5232 face_id = (ROW)->glyphs[AREA][START].face_id; \
5234 s = (struct glyph_string *) alloca (sizeof *s); \
5235 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5236 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5237 x_append_glyph_string (&HEAD, &TAIL, s); \
5239 START = x_fill_glyph_string (s, face_id, START, END, \
5245 /* Add a glyph string for a composite sequence to the list of strings
5246 between HEAD and TAIL. START is the index of the first glyph in
5247 row area AREA of glyph row ROW that is part of the new glyph
5248 string. END is the index of the last glyph in that glyph row area.
5249 X is the current output position assigned to the new glyph string
5250 constructed. HL overrides that face of the glyph; e.g. it is
5251 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5252 x-position of the drawing area. */
5254 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5256 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5257 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5258 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5259 struct composition *cmp = composition_table[cmp_id]; \
5260 int glyph_len = cmp->glyph_len; \
5262 struct face **faces; \
5263 struct glyph_string *first_s = NULL; \
5266 base_face = base_face->ascii_face; \
5267 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5268 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5269 /* At first, fill in `char2b' and `faces'. */ \
5270 for (n = 0; n < glyph_len; n++) \
5272 int c = COMPOSITION_GLYPH (cmp, n); \
5273 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5274 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5275 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5276 this_face_id, char2b + n, 1); \
5279 /* Make glyph_strings for each glyph sequence that is drawable by \
5280 the same face, and append them to HEAD/TAIL. */ \
5281 for (n = 0; n < cmp->glyph_len;) \
5283 s = (struct glyph_string *) alloca (sizeof *s); \
5284 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5285 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5293 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5301 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5302 of AREA of glyph row ROW on window W between indices START and END.
5303 HL overrides the face for drawing glyph strings, e.g. it is
5304 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5305 x-positions of the drawing area.
5307 This is an ugly monster macro construct because we must use alloca
5308 to allocate glyph strings (because x_draw_glyphs can be called
5311 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5314 HEAD = TAIL = NULL; \
5315 while (START < END) \
5317 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5318 switch (first_glyph->type) \
5321 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5322 TAIL, HL, X, LAST_X, \
5326 case COMPOSITE_GLYPH: \
5327 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5328 HEAD, TAIL, HL, X, LAST_X,\
5332 case STRETCH_GLYPH: \
5333 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5334 HEAD, TAIL, HL, X, LAST_X); \
5338 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5339 TAIL, HL, X, LAST_X); \
5346 x_set_glyph_string_background_width (s, START, LAST_X); \
5353 /* Draw glyphs between START and END in AREA of ROW on window W,
5354 starting at x-position X. X is relative to AREA in W. HL is a
5355 face-override with the following meaning:
5357 DRAW_NORMAL_TEXT draw normally
5358 DRAW_CURSOR draw in cursor face
5359 DRAW_MOUSE_FACE draw in mouse face.
5360 DRAW_INVERSE_VIDEO draw in mode line face
5361 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5362 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5364 If OVERLAPS_P is non-zero, draw only the foreground of characters
5365 and clip to the physical height of ROW.
5367 Value is the x-position reached, relative to AREA of W. */
5370 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, overlaps_p
)
5373 struct glyph_row
*row
;
5374 enum glyph_row_area area
;
5376 enum draw_glyphs_face hl
;
5379 struct glyph_string
*head
, *tail
;
5380 struct glyph_string
*s
;
5381 int last_x
, area_width
;
5385 /* Let's rather be paranoid than getting a SEGV. */
5386 end
= min (end
, row
->used
[area
]);
5387 start
= max (0, start
);
5388 start
= min (end
, start
);
5390 /* Translate X to frame coordinates. Set last_x to the right
5391 end of the drawing area. */
5392 if (row
->full_width_p
)
5394 /* X is relative to the left edge of W, without scroll bars
5396 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5397 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
5400 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5401 last_x
= window_left_x
+ area_width
;
5403 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5405 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5406 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
5412 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
5413 last_x
-= FRAME_INTERNAL_BORDER_WIDTH (f
);
5417 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
5418 area_width
= window_box_width (w
, area
);
5419 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
5422 /* Build a doubly-linked list of glyph_string structures between
5423 head and tail from what we have to draw. Note that the macro
5424 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5425 the reason we use a separate variable `i'. */
5427 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
5430 x_reached
= tail
->x
+ tail
->background_width
;
5434 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5435 the row, redraw some glyphs in front or following the glyph
5436 strings built above. */
5437 if (head
&& !overlaps_p
&& row
->contains_overlapping_glyphs_p
)
5440 struct glyph_string
*h
, *t
;
5442 /* Compute overhangs for all glyph strings. */
5443 for (s
= head
; s
; s
= s
->next
)
5444 x_compute_glyph_string_overhangs (s
);
5446 /* Prepend glyph strings for glyphs in front of the first glyph
5447 string that are overwritten because of the first glyph
5448 string's left overhang. The background of all strings
5449 prepended must be drawn because the first glyph string
5451 i
= x_left_overwritten (head
);
5455 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
5456 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
5459 x_compute_overhangs_and_x (t
, head
->x
, 1);
5460 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
5463 /* Prepend glyph strings for glyphs in front of the first glyph
5464 string that overwrite that glyph string because of their
5465 right overhang. For these strings, only the foreground must
5466 be drawn, because it draws over the glyph string at `head'.
5467 The background must not be drawn because this would overwrite
5468 right overhangs of preceding glyphs for which no glyph
5470 i
= x_left_overwriting (head
);
5473 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
5474 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
5476 for (s
= h
; s
; s
= s
->next
)
5477 s
->background_filled_p
= 1;
5478 x_compute_overhangs_and_x (t
, head
->x
, 1);
5479 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
5482 /* Append glyphs strings for glyphs following the last glyph
5483 string tail that are overwritten by tail. The background of
5484 these strings has to be drawn because tail's foreground draws
5486 i
= x_right_overwritten (tail
);
5489 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
5490 DRAW_NORMAL_TEXT
, x
, last_x
,
5492 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
5493 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5496 /* Append glyph strings for glyphs following the last glyph
5497 string tail that overwrite tail. The foreground of such
5498 glyphs has to be drawn because it writes into the background
5499 of tail. The background must not be drawn because it could
5500 paint over the foreground of following glyphs. */
5501 i
= x_right_overwriting (tail
);
5504 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
5505 DRAW_NORMAL_TEXT
, x
, last_x
,
5507 for (s
= h
; s
; s
= s
->next
)
5508 s
->background_filled_p
= 1;
5509 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
5510 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5514 /* Draw all strings. */
5515 for (s
= head
; s
; s
= s
->next
)
5516 x_draw_glyph_string (s
);
5518 if (area
== TEXT_AREA
5519 && !row
->full_width_p
5520 /* When drawing overlapping rows, only the glyph strings'
5521 foreground is drawn, which doesn't erase a cursor
5525 int x0
= head
? head
->x
: x
;
5526 int x1
= tail
? tail
->x
+ tail
->background_width
: x
;
5528 x0
= FRAME_TO_WINDOW_PIXEL_X (w
, x0
);
5529 x1
= FRAME_TO_WINDOW_PIXEL_X (w
, x1
);
5531 if (!row
->full_width_p
&& XFASTINT (w
->left_margin_width
) != 0)
5533 int left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
5534 x0
-= left_area_width
;
5535 x1
-= left_area_width
;
5538 notice_overwritten_cursor (w
, area
, x0
, x1
,
5539 row
->y
, MATRIX_ROW_BOTTOM_Y (row
));
5542 /* Value is the x-position up to which drawn, relative to AREA of W.
5543 This doesn't include parts drawn because of overhangs. */
5544 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
5545 if (!row
->full_width_p
)
5547 if (area
> LEFT_MARGIN_AREA
)
5548 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
5549 if (area
> TEXT_AREA
)
5550 x_reached
-= window_box_width (w
, TEXT_AREA
);
5557 /* Fix the display of area AREA of overlapping row ROW in window W. */
5560 x_fix_overlapping_area (w
, row
, area
)
5562 struct glyph_row
*row
;
5563 enum glyph_row_area area
;
5569 if (area
== LEFT_MARGIN_AREA
)
5571 else if (area
== TEXT_AREA
)
5572 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5574 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5575 + window_box_width (w
, TEXT_AREA
));
5577 for (i
= 0; i
< row
->used
[area
];)
5579 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
5581 int start
= i
, start_x
= x
;
5585 x
+= row
->glyphs
[area
][i
].pixel_width
;
5588 while (i
< row
->used
[area
]
5589 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
5591 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
5592 DRAW_NORMAL_TEXT
, 1);
5596 x
+= row
->glyphs
[area
][i
].pixel_width
;
5605 /* Output LEN glyphs starting at START at the nominal cursor position.
5606 Advance the nominal cursor over the text. The global variable
5607 updated_window contains the window being updated, updated_row is
5608 the glyph row being updated, and updated_area is the area of that
5609 row being updated. */
5612 x_write_glyphs (start
, len
)
5613 struct glyph
*start
;
5618 xassert (updated_window
&& updated_row
);
5623 hpos
= start
- updated_row
->glyphs
[updated_area
];
5624 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
5625 updated_row
, updated_area
,
5627 DRAW_NORMAL_TEXT
, 0);
5631 /* Advance the output cursor. */
5632 output_cursor
.hpos
+= len
;
5633 output_cursor
.x
= x
;
5637 /* Insert LEN glyphs from START at the nominal cursor position. */
5640 x_insert_glyphs (start
, len
)
5641 struct glyph
*start
;
5646 int line_height
, shift_by_width
, shifted_region_width
;
5647 struct glyph_row
*row
;
5648 struct glyph
*glyph
;
5649 int frame_x
, frame_y
, hpos
;
5651 xassert (updated_window
&& updated_row
);
5654 f
= XFRAME (WINDOW_FRAME (w
));
5656 /* Get the height of the line we are in. */
5658 line_height
= row
->height
;
5660 /* Get the width of the glyphs to insert. */
5662 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
5663 shift_by_width
+= glyph
->pixel_width
;
5665 /* Get the width of the region to shift right. */
5666 shifted_region_width
= (window_box_width (w
, updated_area
)
5671 frame_x
= window_box_left (w
, updated_area
) + output_cursor
.x
;
5672 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
5674 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5675 f
->output_data
.mac
->normal_gc
,
5677 shifted_region_width
, line_height
,
5678 frame_x
+ shift_by_width
, frame_y
);
5680 /* Write the glyphs. */
5681 hpos
= start
- row
->glyphs
[updated_area
];
5682 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
5683 DRAW_NORMAL_TEXT
, 0);
5685 /* Advance the output cursor. */
5686 output_cursor
.hpos
+= len
;
5687 output_cursor
.x
+= shift_by_width
;
5692 /* Delete N glyphs at the nominal cursor position. Not implemented
5703 /* Erase the current text line from the nominal cursor position
5704 (inclusive) to pixel column TO_X (exclusive). The idea is that
5705 everything from TO_X onward is already erased.
5707 TO_X is a pixel position relative to updated_area of
5708 updated_window. TO_X == -1 means clear to the end of this area. */
5711 x_clear_end_of_line (to_x
)
5715 struct window
*w
= updated_window
;
5716 int max_x
, min_y
, max_y
;
5717 int from_x
, from_y
, to_y
;
5719 xassert (updated_window
&& updated_row
);
5720 f
= XFRAME (w
->frame
);
5722 if (updated_row
->full_width_p
)
5724 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5725 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5726 && !w
->pseudo_window_p
)
5727 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5730 max_x
= window_box_width (w
, updated_area
);
5731 max_y
= window_text_bottom_y (w
);
5733 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5734 of window. For TO_X > 0, truncate to end of drawing area. */
5740 to_x
= min (to_x
, max_x
);
5742 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
5744 /* Notice if the cursor will be cleared by this operation. */
5745 if (!updated_row
->full_width_p
)
5746 notice_overwritten_cursor (w
, updated_area
,
5747 output_cursor
.x
, -1,
5749 MATRIX_ROW_BOTTOM_Y (updated_row
));
5751 from_x
= output_cursor
.x
;
5753 /* Translate to frame coordinates. */
5754 if (updated_row
->full_width_p
)
5756 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
5757 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
5761 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
5762 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
5765 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
5766 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
5767 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
5769 /* Prevent inadvertently clearing to end of the X window. */
5770 if (to_x
> from_x
&& to_y
> from_y
)
5773 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5774 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
5781 /* Clear entire frame. If updating_frame is non-null, clear that
5782 frame. Otherwise clear the selected frame. */
5792 f
= SELECTED_FRAME ();
5794 /* Clearing the frame will erase any cursor, so mark them all as no
5796 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5797 output_cursor
.hpos
= output_cursor
.vpos
= 0;
5798 output_cursor
.x
= -1;
5800 /* We don't set the output cursor here because there will always
5801 follow an explicit cursor_to. */
5803 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
5805 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5806 /* We have to clear the scroll bars, too. If we have changed
5807 colors or something like that, then they should be notified. */
5808 x_scroll_bar_clear (f
);
5811 XFlush (FRAME_MAC_DISPLAY (f
));
5817 /* Invert the middle quarter of the frame for .15 sec. */
5819 /* We use the select system call to do the waiting, so we have to make
5820 sure it's available. If it isn't, we just won't do visual bells. */
5822 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5824 /* Subtract the `struct timeval' values X and Y, storing the result in
5825 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5828 timeval_subtract (result
, x
, y
)
5829 struct timeval
*result
, x
, y
;
5831 /* Perform the carry for the later subtraction by updating y. This
5832 is safer because on some systems the tv_sec member is unsigned. */
5833 if (x
.tv_usec
< y
.tv_usec
)
5835 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
5836 y
.tv_usec
-= 1000000 * nsec
;
5840 if (x
.tv_usec
- y
.tv_usec
> 1000000)
5842 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
5843 y
.tv_usec
+= 1000000 * nsec
;
5847 /* Compute the time remaining to wait. tv_usec is certainly
5849 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
5850 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
5852 /* Return indication of whether the result should be considered
5854 return x
.tv_sec
< y
.tv_sec
;
5866 struct timeval wakeup
;
5868 EMACS_GET_TIME (wakeup
);
5870 /* Compute time to wait until, propagating carry from usecs. */
5871 wakeup
.tv_usec
+= 150000;
5872 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
5873 wakeup
.tv_usec
%= 1000000;
5875 /* Keep waiting until past the time wakeup. */
5878 struct timeval timeout
;
5880 EMACS_GET_TIME (timeout
);
5882 /* In effect, timeout = wakeup - timeout.
5883 Break if result would be negative. */
5884 if (timeval_subtract (&timeout
, wakeup
, timeout
))
5887 /* Try to wait that long--but we might wake up sooner. */
5888 select (0, NULL
, NULL
, NULL
, &timeout
);
5897 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5900 /* Make audible bell. */
5905 struct frame
*f
= SELECTED_FRAME ();
5907 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5915 XFlush (FRAME_MAC_DISPLAY (f
));
5922 /* Specify how many text lines, from the top of the window,
5923 should be affected by insert-lines and delete-lines operations.
5924 This, and those operations, are used only within an update
5925 that is bounded by calls to x_update_begin and x_update_end. */
5928 XTset_terminal_window (n
)
5931 /* This function intentionally left blank. */
5936 /***********************************************************************
5938 ***********************************************************************/
5940 /* Perform an insert-lines or delete-lines operation, inserting N
5941 lines or deleting -N lines at vertical position VPOS. */
5944 x_ins_del_lines (vpos
, n
)
5951 /* Scroll part of the display as described by RUN. */
5954 x_scroll_run (w
, run
)
5958 struct frame
*f
= XFRAME (w
->frame
);
5959 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
5961 /* Get frame-relative bounding box of the text display area of W,
5962 without mode lines. Include in this box the left and right
5964 window_box (w
, -1, &x
, &y
, &width
, &height
);
5965 width
+= FRAME_X_FRINGE_WIDTH (f
);
5966 x
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
5968 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5969 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5970 bottom_y
= y
+ height
;
5974 /* Scrolling up. Make sure we don't copy part of the mode
5975 line at the bottom. */
5976 if (from_y
+ run
->height
> bottom_y
)
5977 height
= bottom_y
- from_y
;
5979 height
= run
->height
;
5983 /* Scolling down. Make sure we don't copy over the mode line.
5985 if (to_y
+ run
->height
> bottom_y
)
5986 height
= bottom_y
- to_y
;
5988 height
= run
->height
;
5993 /* Cursor off. Will be switched on again in x_update_window_end. */
5997 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5998 f
->output_data
.mac
->normal_gc
,
6008 /***********************************************************************
6010 ***********************************************************************/
6012 /* Redisplay an exposed area of frame F. X and Y are the upper-left
6013 corner of the exposed rectangle. W and H are width and height of
6014 the exposed area. All are pixel values. W or H zero means redraw
6015 the entire frame. */
6018 expose_frame (f
, x
, y
, w
, h
)
6023 int mouse_face_overwritten_p
= 0;
6025 TRACE ((stderr
, "expose_frame "));
6027 /* No need to redraw if frame will be redrawn soon. */
6028 if (FRAME_GARBAGED_P (f
))
6030 TRACE ((stderr
, " garbaged\n"));
6034 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6035 or deactivated here, for unknown reasons, activated scroll bars
6036 are shown in deactivated frames in some instances. */
6037 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
6038 activate_scroll_bars (f
);
6040 deactivate_scroll_bars (f
);
6042 /* If basic faces haven't been realized yet, there is no point in
6043 trying to redraw anything. This can happen when we get an expose
6044 event while Emacs is starting, e.g. by moving another window. */
6045 if (FRAME_FACE_CACHE (f
) == NULL
6046 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
6048 TRACE ((stderr
, " no faces\n"));
6052 if (w
== 0 || h
== 0)
6055 r
.right
= CANON_X_UNIT (f
) * f
->width
;
6056 r
.bottom
= CANON_Y_UNIT (f
) * f
->height
;
6066 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.left
, r
.top
, r
.right
, r
.bottom
));
6067 mouse_face_overwritten_p
= expose_window_tree (XWINDOW (f
->root_window
), &r
);
6069 if (WINDOWP (f
->tool_bar_window
))
6070 mouse_face_overwritten_p
6071 |= expose_window (XWINDOW (f
->tool_bar_window
), &r
);
6073 /* Some window managers support a focus-follows-mouse style with
6074 delayed raising of frames. Imagine a partially obscured frame,
6075 and moving the mouse into partially obscured mouse-face on that
6076 frame. The visible part of the mouse-face will be highlighted,
6077 then the WM raises the obscured frame. With at least one WM, KDE
6078 2.1, Emacs is not getting any event for the raising of the frame
6079 (even tried with SubstructureRedirectMask), only Expose events.
6080 These expose events will draw text normally, i.e. not
6081 highlighted. Which means we must redo the highlight here.
6082 Subsume it under ``we love X''. --gerd 2001-08-15 */
6083 /* Included in Windows version because Windows most likely does not
6084 do the right thing if any third party tool offers
6085 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6086 if (mouse_face_overwritten_p
&& !FRAME_GARBAGED_P (f
))
6088 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6089 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6091 int x
= dpyinfo
->mouse_face_mouse_x
;
6092 int y
= dpyinfo
->mouse_face_mouse_y
;
6093 clear_mouse_face (dpyinfo
);
6094 note_mouse_highlight (f
, x
, y
);
6100 /* Redraw (parts) of all windows in the window tree rooted at W that
6101 intersect R. R contains frame pixel coordinates. */
6104 expose_window_tree (w
, r
)
6108 struct frame
*f
= XFRAME (w
->frame
);
6109 int mouse_face_overwritten_p
= 0;
6111 while (w
&& !FRAME_GARBAGED_P (f
))
6113 if (!NILP (w
->hchild
))
6114 mouse_face_overwritten_p
6115 |= expose_window_tree (XWINDOW (w
->hchild
), r
);
6116 else if (!NILP (w
->vchild
))
6117 mouse_face_overwritten_p
6118 |= expose_window_tree (XWINDOW (w
->vchild
), r
);
6120 mouse_face_overwritten_p
|= expose_window (w
, r
);
6122 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
6125 return mouse_face_overwritten_p
;
6129 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6130 which intersects rectangle R. R is in window-relative coordinates. */
6133 expose_area (w
, row
, r
, area
)
6135 struct glyph_row
*row
;
6137 enum glyph_row_area area
;
6139 struct glyph
*first
= row
->glyphs
[area
];
6140 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
6142 int first_x
, start_x
, x
;
6144 if (area
== TEXT_AREA
&& row
->fill_line_p
)
6145 /* If row extends face to end of line write the whole line. */
6146 x_draw_glyphs (w
, 0, row
, area
,
6148 DRAW_NORMAL_TEXT
, 0);
6151 /* Set START_X to the window-relative start position for drawing glyphs of
6152 AREA. The first glyph of the text area can be partially visible.
6153 The first glyphs of other areas cannot. */
6154 if (area
== LEFT_MARGIN_AREA
)
6156 else if (area
== TEXT_AREA
)
6157 start_x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
6159 start_x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
6160 + window_box_width (w
, TEXT_AREA
));
6163 /* Find the first glyph that must be redrawn. */
6165 && x
+ first
->pixel_width
< r
->left
)
6167 x
+= first
->pixel_width
;
6171 /* Find the last one. */
6177 x
+= last
->pixel_width
;
6183 x_draw_glyphs (w
, first_x
- start_x
, row
, area
,
6184 first
- row
->glyphs
[area
],
6185 last
- row
->glyphs
[area
],
6186 DRAW_NORMAL_TEXT
, 0);
6191 /* Redraw the parts of the glyph row ROW on window W intersecting
6192 rectangle R. R is in window-relative coordinates. Value is
6193 non-zero if mouse face was overwritten. */
6196 expose_line (w
, row
, r
)
6198 struct glyph_row
*row
;
6201 xassert (row
->enabled_p
);
6203 if (row
->mode_line_p
|| w
->pseudo_window_p
)
6204 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
6205 DRAW_NORMAL_TEXT
, 0);
6208 if (row
->used
[LEFT_MARGIN_AREA
])
6209 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
6210 if (row
->used
[TEXT_AREA
])
6211 expose_area (w
, row
, r
, TEXT_AREA
);
6212 if (row
->used
[RIGHT_MARGIN_AREA
])
6213 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
6214 x_draw_row_fringe_bitmaps (w
, row
);
6217 return row
->mouse_face_p
;
6221 /* Return non-zero if W's cursor intersects rectangle R. */
6224 x_phys_cursor_in_rect_p (w
, r
)
6229 struct glyph
*cursor_glyph
;
6231 cursor_glyph
= get_phys_cursor_glyph (w
);
6234 cr
.left
= w
->phys_cursor
.x
;
6235 cr
.top
= w
->phys_cursor
.y
;
6236 cr
.right
= cr
.left
+ cursor_glyph
->pixel_width
;
6237 cr
.bottom
= cr
.top
+ w
->phys_cursor_height
;
6238 return x_intersect_rectangles (&cr
, r
, &result
);
6245 /* Redraw those parts of glyphs rows during expose event handling that
6246 overlap other rows. Redrawing of an exposed line writes over parts
6247 of lines overlapping that exposed line; this function fixes that.
6249 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
6250 row in W's current matrix that is exposed and overlaps other rows.
6251 LAST_OVERLAPPING_ROW is the last such row. */
6254 expose_overlaps (w
, first_overlapping_row
, last_overlapping_row
)
6256 struct glyph_row
*first_overlapping_row
;
6257 struct glyph_row
*last_overlapping_row
;
6259 struct glyph_row
*row
;
6261 for (row
= first_overlapping_row
; row
<= last_overlapping_row
; ++row
)
6262 if (row
->overlapping_p
)
6264 xassert (row
->enabled_p
&& !row
->mode_line_p
);
6266 if (row
->used
[LEFT_MARGIN_AREA
])
6267 x_fix_overlapping_area (w
, row
, LEFT_MARGIN_AREA
);
6269 if (row
->used
[TEXT_AREA
])
6270 x_fix_overlapping_area (w
, row
, TEXT_AREA
);
6272 if (row
->used
[RIGHT_MARGIN_AREA
])
6273 x_fix_overlapping_area (w
, row
, RIGHT_MARGIN_AREA
);
6278 /* Redraw the part of window W intersection rectangle FR. Pixel
6279 coordinates in FR are frame-relative. Call this function with
6280 input blocked. Value is non-zero if the exposure overwrites
6284 expose_window (w
, fr
)
6288 struct frame
*f
= XFRAME (w
->frame
);
6290 int mouse_face_overwritten_p
= 0;
6292 /* If window is not yet fully initialized, do nothing. This can
6293 happen when toolkit scroll bars are used and a window is split.
6294 Reconfiguring the scroll bar will generate an expose for a newly
6296 if (w
->current_matrix
== NULL
)
6299 /* When we're currently updating the window, display and current
6300 matrix usually don't agree. Arrange for a thorough display
6302 if (w
== updated_window
)
6304 SET_FRAME_GARBAGED (f
);
6308 /* Frame-relative pixel rectangle of W. */
6309 wr
.left
= XFASTINT (w
->left
) * CANON_X_UNIT (f
);
6310 wr
.top
= XFASTINT (w
->top
) * CANON_Y_UNIT (f
);
6311 wr
.right
= wr
.left
+ XFASTINT (w
->width
) * CANON_X_UNIT (f
);
6312 wr
.bottom
= wr
.top
+ XFASTINT (w
->height
) * CANON_Y_UNIT (f
);
6314 if (x_intersect_rectangles (fr
, &wr
, &r
))
6316 int yb
= window_text_bottom_y (w
);
6317 struct glyph_row
*row
;
6318 int cursor_cleared_p
;
6319 struct glyph_row
*first_overlapping_row
, *last_overlapping_row
;
6321 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
6322 r
.left
, r
.top
, r
.right
, r
.bottom
));
6324 /* Convert to window coordinates. */
6325 r
.left
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.left
);
6326 r
.right
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.right
);
6327 r
.top
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.top
);
6328 r
.bottom
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.bottom
);
6330 /* Turn off the cursor. */
6331 if (!w
->pseudo_window_p
6332 && x_phys_cursor_in_rect_p (w
, &r
))
6335 cursor_cleared_p
= 1;
6338 cursor_cleared_p
= 0;
6340 /* Update lines intersecting rectangle R. */
6341 first_overlapping_row
= last_overlapping_row
= NULL
;
6342 for (row
= w
->current_matrix
->rows
;
6347 int y1
= MATRIX_ROW_BOTTOM_Y (row
);
6349 if ((y0
>= r
.top
&& y0
< r
.bottom
)
6350 || (y1
> r
.top
&& y1
< r
.bottom
)
6351 || (r
.top
>= y0
&& r
.top
< y1
)
6352 || (r
.bottom
> y0
&& r
.bottom
< y1
))
6354 if (row
->overlapping_p
)
6356 if (first_overlapping_row
== NULL
)
6357 first_overlapping_row
= row
;
6358 last_overlapping_row
= row
;
6361 if (expose_line (w
, row
, &r
))
6362 mouse_face_overwritten_p
= 1;
6369 /* Display the mode line if there is one. */
6370 if (WINDOW_WANTS_MODELINE_P (w
)
6371 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
6373 && row
->y
< r
.bottom
)
6375 if (expose_line (w
, row
, &r
))
6376 mouse_face_overwritten_p
= 1;
6379 if (!w
->pseudo_window_p
)
6381 /* Fix the display of overlapping rows. */
6382 if (first_overlapping_row
)
6383 expose_overlaps (w
, first_overlapping_row
, last_overlapping_row
);
6385 /* Draw border between windows. */
6386 x_draw_vertical_border (w
);
6388 /* Turn the cursor on again. */
6389 if (cursor_cleared_p
)
6390 x_update_window_cursor (w
, 1);
6394 /* Display scroll bar for this window. */
6395 if (!NILP (w
->vertical_scroll_bar
))
6398 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w
->vertical_scroll_bar
));
6403 return mouse_face_overwritten_p
;
6407 x_intersect_rectangles (r1
, r2
, result
)
6408 Rect
*r1
, *r2
, *result
;
6411 Rect
*upper
, *lower
;
6412 int intersection_p
= 0;
6414 /* Rerrange so that R1 is the left-most rectangle. */
6415 if (r1
->left
< r2
->left
)
6416 left
= r1
, right
= r2
;
6418 left
= r2
, right
= r1
;
6420 /* X0 of the intersection is right.x0, if this is inside R1,
6421 otherwise there is no intersection. */
6422 if (right
->left
<= left
->right
)
6424 result
->left
= right
->left
;
6426 /* The right end of the intersection is the minimum of the
6427 the right ends of left and right. */
6428 result
->right
= min (left
->right
, right
->right
);
6430 /* Same game for Y. */
6431 if (r1
->top
< r2
->top
)
6432 upper
= r1
, lower
= r2
;
6434 upper
= r2
, lower
= r1
;
6436 /* The upper end of the intersection is lower.y0, if this is inside
6437 of upper. Otherwise, there is no intersection. */
6438 if (lower
->top
<= upper
->bottom
)
6440 result
->top
= lower
->top
;
6442 /* The lower end of the intersection is the minimum of the lower
6443 ends of upper and lower. */
6444 result
->bottom
= min (lower
->bottom
, upper
->bottom
);
6449 return intersection_p
;
6460 x_update_cursor (f
, 1);
6464 frame_unhighlight (f
)
6467 x_update_cursor (f
, 1);
6470 /* The focus has changed. Update the frames as necessary to reflect
6471 the new situation. Note that we can't change the selected frame
6472 here, because the Lisp code we are interrupting might become confused.
6473 Each event gets marked with the frame in which it occurred, so the
6474 Lisp code can tell when the switch took place by examining the events. */
6477 x_new_focus_frame (dpyinfo
, frame
)
6478 struct x_display_info
*dpyinfo
;
6479 struct frame
*frame
;
6481 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
6483 if (frame
!= dpyinfo
->x_focus_frame
)
6485 /* Set this before calling other routines, so that they see
6486 the correct value of x_focus_frame. */
6487 dpyinfo
->x_focus_frame
= frame
;
6489 if (old_focus
&& old_focus
->auto_lower
)
6490 x_lower_frame (old_focus
);
6493 selected_frame
= frame
;
6494 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
6496 Fselect_window (selected_frame
->selected_window
);
6497 choose_minibuf_frame ();
6500 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
6501 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
6503 pending_autoraise_frame
= 0;
6506 x_frame_rehighlight (dpyinfo
);
6509 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6512 x_mouse_leave (dpyinfo
)
6513 struct x_display_info
*dpyinfo
;
6515 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
6518 /* The focus has changed, or we have redirected a frame's focus to
6519 another frame (this happens when a frame uses a surrogate
6520 mini-buffer frame). Shift the highlight as appropriate.
6522 The FRAME argument doesn't necessarily have anything to do with which
6523 frame is being highlighted or un-highlighted; we only use it to find
6524 the appropriate X display info. */
6527 XTframe_rehighlight (frame
)
6528 struct frame
*frame
;
6530 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
6534 x_frame_rehighlight (dpyinfo
)
6535 struct x_display_info
*dpyinfo
;
6537 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
6539 if (dpyinfo
->x_focus_frame
)
6541 dpyinfo
->x_highlight_frame
6542 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
6543 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
6544 : dpyinfo
->x_focus_frame
);
6545 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
6547 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
6548 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
6552 dpyinfo
->x_highlight_frame
= 0;
6554 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
6557 frame_unhighlight (old_highlight
);
6558 if (dpyinfo
->x_highlight_frame
)
6559 frame_highlight (dpyinfo
->x_highlight_frame
);
6565 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6567 #if 0 /* MAC_TODO */
6568 /* Initialize mode_switch_bit and modifier_meaning. */
6570 x_find_modifier_meanings (dpyinfo
)
6571 struct x_display_info
*dpyinfo
;
6573 int min_code
, max_code
;
6576 XModifierKeymap
*mods
;
6578 dpyinfo
->meta_mod_mask
= 0;
6579 dpyinfo
->shift_lock_mask
= 0;
6580 dpyinfo
->alt_mod_mask
= 0;
6581 dpyinfo
->super_mod_mask
= 0;
6582 dpyinfo
->hyper_mod_mask
= 0;
6585 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
6587 min_code
= dpyinfo
->display
->min_keycode
;
6588 max_code
= dpyinfo
->display
->max_keycode
;
6591 syms
= XGetKeyboardMapping (dpyinfo
->display
,
6592 min_code
, max_code
- min_code
+ 1,
6594 mods
= XGetModifierMapping (dpyinfo
->display
);
6596 /* Scan the modifier table to see which modifier bits the Meta and
6597 Alt keysyms are on. */
6599 int row
, col
; /* The row and column in the modifier table. */
6601 for (row
= 3; row
< 8; row
++)
6602 for (col
= 0; col
< mods
->max_keypermod
; col
++)
6605 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
6607 /* Zeroes are used for filler. Skip them. */
6611 /* Are any of this keycode's keysyms a meta key? */
6615 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
6617 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
6623 dpyinfo
->meta_mod_mask
|= (1 << row
);
6628 dpyinfo
->alt_mod_mask
|= (1 << row
);
6633 dpyinfo
->hyper_mod_mask
|= (1 << row
);
6638 dpyinfo
->super_mod_mask
|= (1 << row
);
6642 /* Ignore this if it's not on the lock modifier. */
6643 if ((1 << row
) == LockMask
)
6644 dpyinfo
->shift_lock_mask
= LockMask
;
6652 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6653 if (! dpyinfo
->meta_mod_mask
)
6655 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
6656 dpyinfo
->alt_mod_mask
= 0;
6659 /* If some keys are both alt and meta,
6660 make them just meta, not alt. */
6661 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
6663 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
6666 XFree ((char *) syms
);
6667 XFreeModifiermap (mods
);
6670 #endif /* MAC_TODO */
6672 /* Convert between the modifier bits X uses and the modifier bits
6676 x_mac_to_emacs_modifiers (dpyinfo
, state
)
6677 struct x_display_info
*dpyinfo
;
6678 unsigned short state
;
6680 return (((state
& shiftKey
) ? shift_modifier
: 0)
6681 | ((state
& controlKey
) ? ctrl_modifier
: 0)
6682 | ((state
& cmdKey
) ? meta_modifier
: 0)
6683 | ((state
& optionKey
) ? alt_modifier
: 0));
6686 #if 0 /* MAC_TODO */
6687 static unsigned short
6688 x_emacs_to_x_modifiers (dpyinfo
, state
)
6689 struct x_display_info
*dpyinfo
;
6692 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
6693 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
6694 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
6695 | ((state
& shift_modifier
) ? ShiftMask
: 0)
6696 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
6697 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
6699 #endif /* MAC_TODO */
6701 /* Convert a keysym to its name. */
6704 x_get_keysym_name (keysym
)
6711 value
= XKeysymToString (keysym
);
6722 /* Mouse clicks and mouse movement. Rah. */
6724 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6725 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6726 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6727 not force the value into range. */
6730 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
6732 register int pix_x
, pix_y
;
6733 register int *x
, *y
;
6737 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6738 if (NILP (Vwindow_system
))
6745 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6746 even for negative values. */
6748 pix_x
-= FONT_WIDTH (FRAME_FONT (f
)) - 1;
6750 pix_y
-= (f
)->output_data
.mac
->line_height
- 1;
6752 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
6753 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
6757 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
6758 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
6759 bounds
->right
= bounds
->left
+ FONT_WIDTH (FRAME_FONT (f
)) - 1;
6760 bounds
->bottom
= bounds
->top
+ f
->output_data
.mac
->line_height
- 1;
6767 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
6768 pix_x
= FRAME_WINDOW_WIDTH (f
);
6772 else if (pix_y
> f
->height
)
6781 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6782 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6783 can't tell the positions because W's display is not up to date,
6787 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
6790 int *frame_x
, *frame_y
;
6794 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
6795 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
6797 if (display_completed
)
6799 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6800 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
6801 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
6807 *frame_x
+= glyph
->pixel_width
;
6815 *frame_y
= *frame_x
= 0;
6819 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
6820 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
6825 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6827 If the event is a button press, then note that we have grabbed
6831 construct_mouse_click (result
, event
, f
)
6832 struct input_event
*result
;
6838 result
->kind
= MOUSE_CLICK_EVENT
;
6839 result
->code
= 0; /* only one mouse button */
6840 result
->timestamp
= event
->when
;
6841 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
6843 mouseLoc
= event
->where
;
6845 #if TARGET_API_MAC_CARBON
6846 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f
)));
6848 SetPort (FRAME_MAC_WINDOW (f
));
6851 GlobalToLocal (&mouseLoc
);
6852 XSETINT (result
->x
, mouseLoc
.h
);
6853 XSETINT (result
->y
, mouseLoc
.v
);
6855 XSETFRAME (result
->frame_or_window
, f
);
6862 /* Function to report a mouse movement to the mainstream Emacs code.
6863 The input handler calls this.
6865 We have received a mouse movement event, which is given in *event.
6866 If the mouse is over a different glyph than it was last time, tell
6867 the mainstream emacs code by setting mouse_moved. If not, ask for
6868 another motion event, so we can check again the next time it moves. */
6870 static Point last_mouse_motion_position
;
6871 static Lisp_Object last_mouse_motion_frame
;
6874 note_mouse_movement (frame
, pos
)
6878 #if TARGET_API_MAC_CARBON
6882 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
6883 last_mouse_motion_position
= *pos
;
6884 XSETFRAME (last_mouse_motion_frame
, frame
);
6886 #if TARGET_API_MAC_CARBON
6887 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
6889 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
6892 frame
->mouse_moved
= 1;
6893 last_mouse_scroll_bar
= Qnil
;
6894 note_mouse_highlight (frame
, -1, -1);
6896 /* Has the mouse moved off the glyph it was on at the last sighting? */
6897 else if (pos
->h
< last_mouse_glyph
.left
6898 || pos
->h
>= last_mouse_glyph
.right
6899 || pos
->v
< last_mouse_glyph
.top
6900 || pos
->v
>= last_mouse_glyph
.bottom
)
6902 frame
->mouse_moved
= 1;
6903 last_mouse_scroll_bar
= Qnil
;
6904 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
6908 /* This is used for debugging, to turn off note_mouse_highlight. */
6910 int disable_mouse_highlight
;
6914 /************************************************************************
6916 ************************************************************************/
6918 /* Find the glyph under window-relative coordinates X/Y in window W.
6919 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6920 strings. Return in *HPOS and *VPOS the row and column number of
6921 the glyph found. Return in *AREA the glyph area containing X.
6922 Value is a pointer to the glyph found or null if X/Y is not on
6923 text, or we can't tell because W's current matrix is not up to
6926 static struct glyph
*
6927 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
, buffer_only_p
)
6930 int *hpos
, *vpos
, *area
;
6933 struct glyph
*glyph
, *end
;
6934 struct glyph_row
*row
= NULL
;
6935 int x0
, i
, left_area_width
;
6937 /* Find row containing Y. Give up if some row is not enabled. */
6938 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
6940 row
= MATRIX_ROW (w
->current_matrix
, i
);
6941 if (!row
->enabled_p
)
6943 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
6950 /* Give up if Y is not in the window. */
6951 if (i
== w
->current_matrix
->nrows
)
6954 /* Get the glyph area containing X. */
6955 if (w
->pseudo_window_p
)
6962 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
6963 if (x
< left_area_width
)
6965 *area
= LEFT_MARGIN_AREA
;
6968 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
6971 x0
= row
->x
+ left_area_width
;
6975 *area
= RIGHT_MARGIN_AREA
;
6976 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
6980 /* Find glyph containing X. */
6981 glyph
= row
->glyphs
[*area
];
6982 end
= glyph
+ row
->used
[*area
];
6985 if (x
< x0
+ glyph
->pixel_width
)
6987 if (w
->pseudo_window_p
)
6989 else if (!buffer_only_p
|| BUFFERP (glyph
->object
))
6993 x0
+= glyph
->pixel_width
;
7000 *hpos
= glyph
- row
->glyphs
[*area
];
7005 /* Convert frame-relative x/y to coordinates relative to window W.
7006 Takes pseudo-windows into account. */
7009 frame_to_window_pixel_xy (w
, x
, y
)
7013 if (w
->pseudo_window_p
)
7015 /* A pseudo-window is always full-width, and starts at the
7016 left edge of the frame, plus a frame border. */
7017 struct frame
*f
= XFRAME (w
->frame
);
7018 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
7019 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
7023 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
7024 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
7029 /* Take proper action when mouse has moved to the mode or header line of
7030 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
7031 mode line. X is relative to the start of the text display area of
7032 W, so the width of fringes and scroll bars must be subtracted
7033 to get a position relative to the start of the mode line. */
7036 note_mode_line_highlight (w
, x
, mode_line_p
)
7040 struct frame
*f
= XFRAME (w
->frame
);
7041 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7042 struct Cursor
*cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
7043 struct glyph_row
*row
;
7046 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
7048 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
7052 struct glyph
*glyph
, *end
;
7053 Lisp_Object help
, map
;
7056 /* Find the glyph under X. */
7057 glyph
= row
->glyphs
[TEXT_AREA
];
7058 end
= glyph
+ row
->used
[TEXT_AREA
];
7059 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
7060 + FRAME_X_LEFT_FRINGE_WIDTH (f
));
7063 && x
>= x0
+ glyph
->pixel_width
)
7065 x0
+= glyph
->pixel_width
;
7070 && STRINGP (glyph
->object
)
7071 && STRING_INTERVALS (glyph
->object
)
7072 && glyph
->charpos
>= 0
7073 && glyph
->charpos
< SCHARS (glyph
->object
))
7075 /* If we're on a string with `help-echo' text property,
7076 arrange for the help to be displayed. This is done by
7077 setting the global variable help_echo to the help string. */
7078 help
= Fget_text_property (make_number (glyph
->charpos
),
7079 Qhelp_echo
, glyph
->object
);
7083 XSETWINDOW (help_echo_window
, w
);
7084 help_echo_object
= glyph
->object
;
7085 help_echo_pos
= glyph
->charpos
;
7088 /* Change the mouse pointer according to what is under X/Y. */
7089 map
= Fget_text_property (make_number (glyph
->charpos
),
7090 Qlocal_map
, glyph
->object
);
7092 cursor
= f
->output_data
.mac
->nontext_cursor
;
7095 map
= Fget_text_property (make_number (glyph
->charpos
),
7096 Qkeymap
, glyph
->object
);
7098 cursor
= f
->output_data
.mac
->nontext_cursor
;
7103 #if 0 /* MAC_TODO: mouse cursor */
7104 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7109 /* Take proper action when the mouse has moved to position X, Y on
7110 frame F as regards highlighting characters that have mouse-face
7111 properties. Also de-highlighting chars where the mouse was before.
7112 X and Y can be negative or out of range. */
7115 note_mouse_highlight (f
, x
, y
)
7119 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7126 /* When a menu is active, don't highlight because this looks odd. */
7127 if (popup_activated ())
7131 if (NILP (Vmouse_highlight
)
7132 || !f
->glyphs_initialized_p
)
7135 dpyinfo
->mouse_face_mouse_x
= x
;
7136 dpyinfo
->mouse_face_mouse_y
= y
;
7137 dpyinfo
->mouse_face_mouse_frame
= f
;
7139 if (dpyinfo
->mouse_face_defer
)
7144 dpyinfo
->mouse_face_deferred_gc
= 1;
7148 /* Which window is that in? */
7149 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
7151 /* If we were displaying active text in another window, clear that. */
7152 if (! EQ (window
, dpyinfo
->mouse_face_window
))
7153 clear_mouse_face (dpyinfo
);
7155 /* Not on a window -> return. */
7156 if (!WINDOWP (window
))
7159 /* Reset help_echo. It will get recomputed below. */
7162 /* Convert to window-relative pixel coordinates. */
7163 w
= XWINDOW (window
);
7164 frame_to_window_pixel_xy (w
, &x
, &y
);
7166 /* Handle tool-bar window differently since it doesn't display a
7168 if (EQ (window
, f
->tool_bar_window
))
7170 note_tool_bar_highlight (f
, x
, y
);
7174 /* Mouse is on the mode or header line? */
7175 if (portion
== 1 || portion
== 3)
7177 note_mode_line_highlight (w
, x
, portion
== 1);
7180 #if 0 /* TODO: mouse cursor */
7182 cursor
= f
->output_data
.x
->horizontal_drag_cursor
;
7184 cursor
= f
->output_data
.x
->text_cursor
;
7186 /* Are we in a window whose display is up to date?
7187 And verify the buffer's text has not changed. */
7188 b
= XBUFFER (w
->buffer
);
7189 if (/* Within text portion of the window. */
7191 && EQ (w
->window_end_valid
, w
->buffer
)
7192 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
7193 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
7195 int hpos
, vpos
, pos
, i
, area
;
7196 struct glyph
*glyph
;
7198 Lisp_Object mouse_face
= Qnil
, overlay
= Qnil
, position
;
7199 Lisp_Object
*overlay_vec
= NULL
;
7201 struct buffer
*obuf
;
7202 int obegv
, ozv
, same_region
;
7204 /* Find the glyph under X/Y. */
7205 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
, 0);
7207 /* Clear mouse face if X/Y not over text. */
7209 || area
!= TEXT_AREA
7210 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
7212 clear_mouse_face (dpyinfo
);
7213 /* TODO: mouse cursor */
7217 pos
= glyph
->charpos
;
7218 object
= glyph
->object
;
7219 if (!STRINGP (object
) && !BUFFERP (object
))
7222 /* If we get an out-of-range value, return now; avoid an error. */
7223 if (BUFFERP (object
) && pos
> BUF_Z (b
))
7226 /* Make the window's buffer temporarily current for
7227 overlays_at and compute_char_face. */
7228 obuf
= current_buffer
;
7235 /* Is this char mouse-active or does it have help-echo? */
7236 position
= make_number (pos
);
7238 if (BUFFERP (object
))
7240 /* Put all the overlays we want in a vector in overlay_vec.
7241 Store the length in len. If there are more than 10, make
7242 enough space for all, and try again. */
7244 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
7245 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
, 0);
7246 if (noverlays
> len
)
7249 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
7250 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
,0);
7253 /* Sort overlays into increasing priority order. */
7254 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
7259 same_region
= (EQ (window
, dpyinfo
->mouse_face_window
)
7260 && vpos
>= dpyinfo
->mouse_face_beg_row
7261 && vpos
<= dpyinfo
->mouse_face_end_row
7262 && (vpos
> dpyinfo
->mouse_face_beg_row
7263 || hpos
>= dpyinfo
->mouse_face_beg_col
)
7264 && (vpos
< dpyinfo
->mouse_face_end_row
7265 || hpos
< dpyinfo
->mouse_face_end_col
7266 || dpyinfo
->mouse_face_past_end
));
7268 /* TODO: if (same_region)
7271 /* Check mouse-face highlighting. */
7273 /* If there exists an overlay with mouse-face overlapping
7274 the one we are currently highlighting, we have to
7275 check if we enter the overlapping overlay, and then
7277 || (OVERLAYP (dpyinfo
->mouse_face_overlay
)
7278 && mouse_face_overlay_overlaps (dpyinfo
->mouse_face_overlay
)))
7280 /* Find the highest priority overlay that has a mouse-face
7283 for (i
= noverlays
- 1; i
>= 0 && NILP (overlay
); --i
)
7285 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
7286 if (!NILP (mouse_face
))
7287 overlay
= overlay_vec
[i
];
7290 /* If we're actually highlighting the same overlay as
7291 before, there's no need to do that again. */
7293 && EQ (overlay
, dpyinfo
->mouse_face_overlay
))
7294 goto check_help_echo
;
7296 dpyinfo
->mouse_face_overlay
= overlay
;
7298 /* Clear the display of the old active region, if any. */
7299 clear_mouse_face (dpyinfo
);
7300 /* TODO: mouse cursor changes. */
7302 /* If no overlay applies, get a text property. */
7304 mouse_face
= Fget_text_property (position
, Qmouse_face
, object
);
7306 /* Handle the overlay case. */
7307 if (!NILP (overlay
))
7309 /* Find the range of text around this char that
7310 should be active. */
7311 Lisp_Object before
, after
;
7314 before
= Foverlay_start (overlay
);
7315 after
= Foverlay_end (overlay
);
7316 /* Record this as the current active region. */
7317 fast_find_position (w
, XFASTINT (before
),
7318 &dpyinfo
->mouse_face_beg_col
,
7319 &dpyinfo
->mouse_face_beg_row
,
7320 &dpyinfo
->mouse_face_beg_x
,
7321 &dpyinfo
->mouse_face_beg_y
, Qnil
);
7323 dpyinfo
->mouse_face_past_end
7324 = !fast_find_position (w
, XFASTINT (after
),
7325 &dpyinfo
->mouse_face_end_col
,
7326 &dpyinfo
->mouse_face_end_row
,
7327 &dpyinfo
->mouse_face_end_x
,
7328 &dpyinfo
->mouse_face_end_y
, Qnil
);
7329 dpyinfo
->mouse_face_window
= window
;
7331 dpyinfo
->mouse_face_face_id
7332 = face_at_buffer_position (w
, pos
, 0, 0,
7334 !dpyinfo
->mouse_face_hidden
);
7336 /* Display it as active. */
7337 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7338 /* TODO: mouse cursor changes. */
7340 /* Handle the text property case. */
7341 else if (! NILP (mouse_face
) && BUFFERP (object
))
7343 /* Find the range of text around this char that
7344 should be active. */
7345 Lisp_Object before
, after
, beginning
, end
;
7348 beginning
= Fmarker_position (w
->start
);
7349 end
= make_number (BUF_Z (XBUFFER (object
))
7350 - XFASTINT (w
->window_end_pos
));
7352 = Fprevious_single_property_change (make_number (pos
+ 1),
7356 = Fnext_single_property_change (position
, Qmouse_face
,
7359 /* Record this as the current active region. */
7360 fast_find_position (w
, XFASTINT (before
),
7361 &dpyinfo
->mouse_face_beg_col
,
7362 &dpyinfo
->mouse_face_beg_row
,
7363 &dpyinfo
->mouse_face_beg_x
,
7364 &dpyinfo
->mouse_face_beg_y
, Qnil
);
7365 dpyinfo
->mouse_face_past_end
7366 = !fast_find_position (w
, XFASTINT (after
),
7367 &dpyinfo
->mouse_face_end_col
,
7368 &dpyinfo
->mouse_face_end_row
,
7369 &dpyinfo
->mouse_face_end_x
,
7370 &dpyinfo
->mouse_face_end_y
, Qnil
);
7371 dpyinfo
->mouse_face_window
= window
;
7373 if (BUFFERP (object
))
7374 dpyinfo
->mouse_face_face_id
7375 = face_at_buffer_position (w
, pos
, 0, 0,
7377 !dpyinfo
->mouse_face_hidden
);
7379 /* Display it as active. */
7380 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7381 /* TODO: mouse cursor changes. */
7383 else if (!NILP (mouse_face
) && STRINGP (object
))
7388 b
= Fprevious_single_property_change (make_number (pos
+ 1),
7391 e
= Fnext_single_property_change (position
, Qmouse_face
,
7394 b
= make_number (0);
7396 e
= make_number (SCHARS (object
) - 1);
7397 fast_find_string_pos (w
, XINT (b
), object
,
7398 &dpyinfo
->mouse_face_beg_col
,
7399 &dpyinfo
->mouse_face_beg_row
,
7400 &dpyinfo
->mouse_face_beg_x
,
7401 &dpyinfo
->mouse_face_beg_y
, 0);
7402 fast_find_string_pos (w
, XINT (e
), object
,
7403 &dpyinfo
->mouse_face_end_col
,
7404 &dpyinfo
->mouse_face_end_row
,
7405 &dpyinfo
->mouse_face_end_x
,
7406 &dpyinfo
->mouse_face_end_y
, 1);
7407 dpyinfo
->mouse_face_past_end
= 0;
7408 dpyinfo
->mouse_face_window
= window
;
7409 dpyinfo
->mouse_face_face_id
7410 = face_at_string_position (w
, object
, pos
, 0, 0, 0, &ignore
,
7412 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7413 /* TODO: mouse cursor changes. */
7415 else if (STRINGP (object
) && NILP (mouse_face
))
7417 /* A string which doesn't have mouse-face, but
7418 the text ``under'' it might have. */
7419 struct glyph_row
*r
= MATRIX_ROW (w
->current_matrix
, vpos
);
7420 int start
= MATRIX_ROW_START_CHARPOS (r
);
7422 pos
= string_buffer_position (w
, object
, start
);
7424 mouse_face
= get_char_property_and_overlay (make_number (pos
),
7428 if (!NILP (mouse_face
) && !NILP (overlay
))
7430 Lisp_Object before
= Foverlay_start (overlay
);
7431 Lisp_Object after
= Foverlay_end (overlay
);
7434 /* Note that we might not be able to find position
7435 BEFORE in the glyph matrix if the overlay is
7436 entirely covered by a `display' property. In
7437 this case, we overshoot. So let's stop in
7438 the glyph matrix before glyphs for OBJECT. */
7439 fast_find_position (w
, XFASTINT (before
),
7440 &dpyinfo
->mouse_face_beg_col
,
7441 &dpyinfo
->mouse_face_beg_row
,
7442 &dpyinfo
->mouse_face_beg_x
,
7443 &dpyinfo
->mouse_face_beg_y
,
7446 dpyinfo
->mouse_face_past_end
7447 = !fast_find_position (w
, XFASTINT (after
),
7448 &dpyinfo
->mouse_face_end_col
,
7449 &dpyinfo
->mouse_face_end_row
,
7450 &dpyinfo
->mouse_face_end_x
,
7451 &dpyinfo
->mouse_face_end_y
,
7453 dpyinfo
->mouse_face_window
= window
;
7454 dpyinfo
->mouse_face_face_id
7455 = face_at_buffer_position (w
, pos
, 0, 0,
7457 !dpyinfo
->mouse_face_hidden
);
7459 /* Display it as active. */
7460 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7461 /* TODO: mouse cursor changes. */
7468 /* Look for a `help-echo' property. */
7470 Lisp_Object help
, overlay
;
7472 /* Check overlays first. */
7473 help
= overlay
= Qnil
;
7474 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
7476 overlay
= overlay_vec
[i
];
7477 help
= Foverlay_get (overlay
, Qhelp_echo
);
7483 help_echo_window
= window
;
7484 help_echo_object
= overlay
;
7485 help_echo_pos
= pos
;
7489 Lisp_Object object
= glyph
->object
;
7490 int charpos
= glyph
->charpos
;
7492 /* Try text properties. */
7493 if (STRINGP (object
)
7495 && charpos
< SCHARS (object
))
7497 help
= Fget_text_property (make_number (charpos
),
7498 Qhelp_echo
, object
);
7501 /* If the string itself doesn't specify a help-echo,
7502 see if the buffer text ``under'' it does. */
7504 = MATRIX_ROW (w
->current_matrix
, vpos
);
7505 int start
= MATRIX_ROW_START_CHARPOS (r
);
7506 int pos
= string_buffer_position (w
, object
, start
);
7509 help
= Fget_char_property (make_number (pos
),
7510 Qhelp_echo
, w
->buffer
);
7519 else if (BUFFERP (object
)
7522 help
= Fget_text_property (make_number (charpos
), Qhelp_echo
,
7528 help_echo_window
= window
;
7529 help_echo_object
= object
;
7530 help_echo_pos
= charpos
;
7537 current_buffer
= obuf
;
7541 /* TODO: mouse cursor changes. */
7546 redo_mouse_highlight ()
7548 if (!NILP (last_mouse_motion_frame
)
7549 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
7550 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
7551 last_mouse_motion_position
.h
,
7552 last_mouse_motion_position
.v
);
7557 /***********************************************************************
7559 ***********************************************************************/
7561 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
7562 struct glyph
**, int *, int *, int *));
7564 /* Tool-bar item index of the item on which a mouse button was pressed
7567 static int last_tool_bar_item
;
7570 /* Get information about the tool-bar item at position X/Y on frame F.
7571 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7572 the current matrix of the tool-bar window of F, or NULL if not
7573 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7574 item in F->current_tool_bar_items. Value is
7576 -1 if X/Y is not on a tool-bar item
7577 0 if X/Y is on the same item that was highlighted before.
7581 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
7584 struct glyph
**glyph
;
7585 int *hpos
, *vpos
, *prop_idx
;
7587 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7588 struct window
*w
= XWINDOW (f
->tool_bar_window
);
7591 /* Find the glyph under X/Y. */
7592 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
, 0);
7596 /* Get the start of this tool-bar item's properties in
7597 f->current_tool_bar_items. */
7598 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
7601 /* Is mouse on the highlighted item? */
7602 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
7603 && *vpos
>= dpyinfo
->mouse_face_beg_row
7604 && *vpos
<= dpyinfo
->mouse_face_end_row
7605 && (*vpos
> dpyinfo
->mouse_face_beg_row
7606 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
7607 && (*vpos
< dpyinfo
->mouse_face_end_row
7608 || *hpos
< dpyinfo
->mouse_face_end_col
7609 || dpyinfo
->mouse_face_past_end
))
7616 /* Handle mouse button event on the tool-bar of frame F, at
7617 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7621 x_handle_tool_bar_click (f
, button_event
)
7623 EventRecord
*button_event
;
7625 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7626 struct window
*w
= XWINDOW (f
->tool_bar_window
);
7627 int hpos
, vpos
, prop_idx
;
7628 struct glyph
*glyph
;
7629 Lisp_Object enabled_p
;
7630 int x
= button_event
->where
.h
;
7631 int y
= button_event
->where
.v
;
7633 /* If not on the highlighted tool-bar item, return. */
7634 frame_to_window_pixel_xy (w
, &x
, &y
);
7635 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
7638 /* If item is disabled, do nothing. */
7639 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7640 if (NILP (enabled_p
))
7643 if (button_event
->what
== mouseDown
)
7645 /* Show item in pressed state. */
7646 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
7647 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
7648 last_tool_bar_item
= prop_idx
;
7652 Lisp_Object key
, frame
;
7653 struct input_event event
;
7655 /* Show item in released state. */
7656 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
7657 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
7659 key
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_KEY
);
7661 XSETFRAME (frame
, f
);
7662 event
.kind
= TOOL_BAR_EVENT
;
7663 event
.frame_or_window
= frame
;
7665 kbd_buffer_store_event (&event
);
7667 event
.kind
= TOOL_BAR_EVENT
;
7668 event
.frame_or_window
= frame
;
7670 event
.modifiers
= x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
7671 button_event
->modifiers
);
7672 kbd_buffer_store_event (&event
);
7673 last_tool_bar_item
= -1;
7678 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7679 tool-bar window-relative coordinates X/Y. Called from
7680 note_mouse_highlight. */
7683 note_tool_bar_highlight (f
, x
, y
)
7687 Lisp_Object window
= f
->tool_bar_window
;
7688 struct window
*w
= XWINDOW (window
);
7689 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7691 struct glyph
*glyph
;
7692 struct glyph_row
*row
;
7694 Lisp_Object enabled_p
;
7696 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
7697 int mouse_down_p
, rc
;
7699 /* Function note_mouse_highlight is called with negative x(y
7700 values when mouse moves outside of the frame. */
7701 if (x
<= 0 || y
<= 0)
7703 clear_mouse_face (dpyinfo
);
7707 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
7710 /* Not on tool-bar item. */
7711 clear_mouse_face (dpyinfo
);
7715 /* On same tool-bar item as before. */
7718 clear_mouse_face (dpyinfo
);
7720 /* Mouse is down, but on different tool-bar item? */
7721 mouse_down_p
= (dpyinfo
->grabbed
7722 && f
== last_mouse_frame
7723 && FRAME_LIVE_P (f
));
7725 && last_tool_bar_item
!= prop_idx
)
7728 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
7729 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
7731 /* If tool-bar item is not enabled, don't highlight it. */
7732 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7733 if (!NILP (enabled_p
))
7735 /* Compute the x-position of the glyph. In front and past the
7736 image is a space. We include this is the highlighted area. */
7737 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
7738 for (i
= x
= 0; i
< hpos
; ++i
)
7739 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
7741 /* Record this as the current active region. */
7742 dpyinfo
->mouse_face_beg_col
= hpos
;
7743 dpyinfo
->mouse_face_beg_row
= vpos
;
7744 dpyinfo
->mouse_face_beg_x
= x
;
7745 dpyinfo
->mouse_face_beg_y
= row
->y
;
7746 dpyinfo
->mouse_face_past_end
= 0;
7748 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
7749 dpyinfo
->mouse_face_end_row
= vpos
;
7750 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
7751 dpyinfo
->mouse_face_end_y
= row
->y
;
7752 dpyinfo
->mouse_face_window
= window
;
7753 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
7755 /* Display it as active. */
7756 show_mouse_face (dpyinfo
, draw
);
7757 dpyinfo
->mouse_face_image_state
= draw
;
7762 /* Set help_echo to a help string.to display for this tool-bar item.
7763 XTread_socket does the rest. */
7764 help_echo_object
= help_echo_window
= Qnil
;
7766 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_HELP
);
7767 if (NILP (help_echo
))
7768 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_CAPTION
);
7773 /* Find the glyph matrix position of buffer position CHARPOS in window
7774 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7775 current glyphs must be up to date. If CHARPOS is above window
7776 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7777 of last line in W. In the row containing CHARPOS, stop before glyphs
7778 having STOP as object. */
7780 #if 0 /* This is a version of fast_find_position that's more correct
7781 in the presence of hscrolling, for example. I didn't install
7782 it right away because the problem fixed is minor, it failed
7783 in 20.x as well, and I think it's too risky to install
7784 so near the release of 21.1. 2001-09-25 gerd. */
7787 fast_find_position (w
, charpos
, hpos
, vpos
, x
, y
, stop
)
7790 int *hpos
, *vpos
, *x
, *y
;
7793 struct glyph_row
*row
, *first
;
7794 struct glyph
*glyph
, *end
;
7795 int i
, past_end
= 0;
7797 first
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7798 row
= row_containing_pos (w
, charpos
, first
, NULL
, 0);
7801 if (charpos
< MATRIX_ROW_START_CHARPOS (first
))
7803 *x
= *y
= *hpos
= *vpos
= 0;
7808 row
= MATRIX_ROW (w
->current_matrix
, XFASTINT (w
->window_end_vpos
));
7815 *vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
7817 glyph
= row
->glyphs
[TEXT_AREA
];
7818 end
= glyph
+ row
->used
[TEXT_AREA
];
7820 /* Skip over glyphs not having an object at the start of the row.
7821 These are special glyphs like truncation marks on terminal
7823 if (row
->displays_text_p
)
7825 && INTEGERP (glyph
->object
)
7826 && !EQ (stop
, glyph
->object
)
7827 && glyph
->charpos
< 0)
7829 *x
+= glyph
->pixel_width
;
7834 && !INTEGERP (glyph
->object
)
7835 && !EQ (stop
, glyph
->object
)
7836 && (!BUFFERP (glyph
->object
)
7837 || glyph
->charpos
< charpos
))
7839 *x
+= glyph
->pixel_width
;
7843 *hpos
= glyph
- row
->glyphs
[TEXT_AREA
];
7850 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
, stop
)
7853 int *hpos
, *vpos
, *x
, *y
;
7858 int maybe_next_line_p
= 0;
7859 int line_start_position
;
7860 int yb
= window_text_bottom_y (w
);
7861 struct glyph_row
*row
, *best_row
;
7862 int row_vpos
, best_row_vpos
;
7865 row
= best_row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7866 row_vpos
= best_row_vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
7870 if (row
->used
[TEXT_AREA
])
7871 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
7873 line_start_position
= 0;
7875 if (line_start_position
> pos
)
7877 /* If the position sought is the end of the buffer,
7878 don't include the blank lines at the bottom of the window. */
7879 else if (line_start_position
== pos
7880 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
7882 maybe_next_line_p
= 1;
7885 else if (line_start_position
> 0)
7888 best_row_vpos
= row_vpos
;
7891 if (row
->y
+ row
->height
>= yb
)
7898 /* Find the right column within BEST_ROW. */
7900 current_x
= best_row
->x
;
7901 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
7903 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
7904 int charpos
= glyph
->charpos
;
7906 if (BUFFERP (glyph
->object
))
7911 *vpos
= best_row_vpos
;
7916 else if (charpos
> pos
)
7919 else if (EQ (glyph
->object
, stop
))
7924 current_x
+= glyph
->pixel_width
;
7927 /* If we're looking for the end of the buffer,
7928 and we didn't find it in the line we scanned,
7929 use the start of the following line. */
7930 if (maybe_next_line_p
)
7935 current_x
= best_row
->x
;
7938 *vpos
= best_row_vpos
;
7939 *hpos
= lastcol
+ 1;
7948 /* Find the position of the glyph for position POS in OBJECT in
7949 window W's current matrix, and return in *X/*Y the pixel
7950 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7952 RIGHT_P non-zero means return the position of the right edge of the
7953 glyph, RIGHT_P zero means return the left edge position.
7955 If no glyph for POS exists in the matrix, return the position of
7956 the glyph with the next smaller position that is in the matrix, if
7957 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7958 exists in the matrix, return the position of the glyph with the
7959 next larger position in OBJECT.
7961 Value is non-zero if a glyph was found. */
7964 fast_find_string_pos (w
, pos
, object
, hpos
, vpos
, x
, y
, right_p
)
7968 int *hpos
, *vpos
, *x
, *y
;
7971 int yb
= window_text_bottom_y (w
);
7972 struct glyph_row
*r
;
7973 struct glyph
*best_glyph
= NULL
;
7974 struct glyph_row
*best_row
= NULL
;
7977 for (r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7978 r
->enabled_p
&& r
->y
< yb
;
7981 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
7982 struct glyph
*e
= g
+ r
->used
[TEXT_AREA
];
7985 for (gx
= r
->x
; g
< e
; gx
+= g
->pixel_width
, ++g
)
7986 if (EQ (g
->object
, object
))
7988 if (g
->charpos
== pos
)
7995 else if (best_glyph
== NULL
7996 || ((abs (g
->charpos
- pos
)
7997 < abs (best_glyph
->charpos
- pos
))
8000 : g
->charpos
> pos
)))
8014 *hpos
= best_glyph
- best_row
->glyphs
[TEXT_AREA
];
8018 *x
+= best_glyph
->pixel_width
;
8023 *vpos
= best_row
- w
->current_matrix
->rows
;
8026 return best_glyph
!= NULL
;
8030 /* Display the active region described by mouse_face_*
8031 in its mouse-face if HL > 0, in its normal face if HL = 0. */
8034 show_mouse_face (dpyinfo
, draw
)
8035 struct mac_display_info
*dpyinfo
;
8036 enum draw_glyphs_face draw
;
8038 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
8039 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
8041 if (/* If window is in the process of being destroyed, don't bother
8043 w
->current_matrix
!= NULL
8044 /* Don't update mouse highlight if hidden */
8045 && (draw
!= DRAW_MOUSE_FACE
|| !dpyinfo
->mouse_face_hidden
)
8046 /* Recognize when we are called to operate on rows that don't exist
8047 anymore. This can happen when a window is split. */
8048 && dpyinfo
->mouse_face_end_row
< w
->current_matrix
->nrows
)
8050 int phys_cursor_on_p
= w
->phys_cursor_on_p
;
8051 struct glyph_row
*row
, *first
, *last
;
8053 first
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_beg_row
);
8054 last
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_end_row
);
8056 for (row
= first
; row
<= last
&& row
->enabled_p
; ++row
)
8058 int start_hpos
, end_hpos
, start_x
;
8060 /* For all but the first row, the highlight starts at column 0. */
8063 start_hpos
= dpyinfo
->mouse_face_beg_col
;
8064 start_x
= dpyinfo
->mouse_face_beg_x
;
8073 end_hpos
= dpyinfo
->mouse_face_end_col
;
8075 end_hpos
= row
->used
[TEXT_AREA
];
8077 if (end_hpos
> start_hpos
)
8079 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
8080 start_hpos
, end_hpos
, draw
, 0);
8083 = draw
== DRAW_MOUSE_FACE
|| draw
== DRAW_IMAGE_RAISED
;
8087 /* When we've written over the cursor, arrange for it to
8088 be displayed again. */
8089 if (phys_cursor_on_p
&& !w
->phys_cursor_on_p
)
8090 x_display_cursor (w
, 1,
8091 w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
8092 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
8095 #if 0 /* MAC_TODO: mouse cursor */
8096 /* Change the mouse cursor. */
8097 if (draw
== DRAW_NORMAL_TEXT
)
8098 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8099 f
->output_data
.x
->text_cursor
);
8100 else if (draw
== DRAW_MOUSE_FACE
)
8101 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8102 f
->output_data
.x
->cross_cursor
);
8104 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8105 f
->output_data
.x
->nontext_cursor
);
8109 /* Clear out the mouse-highlighted active region.
8110 Redraw it un-highlighted first. */
8113 clear_mouse_face (dpyinfo
)
8114 struct mac_display_info
*dpyinfo
;
8118 if (! NILP (dpyinfo
->mouse_face_window
))
8120 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
8124 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8125 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8126 dpyinfo
->mouse_face_window
= Qnil
;
8127 dpyinfo
->mouse_face_overlay
= Qnil
;
8132 /* Clear any mouse-face on window W. This function is part of the
8133 redisplay interface, and is called from try_window_id and similar
8134 functions to ensure the mouse-highlight is off. */
8137 x_clear_mouse_face (w
)
8140 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
8144 XSETWINDOW (window
, w
);
8145 if (EQ (window
, dpyinfo
->mouse_face_window
))
8146 clear_mouse_face (dpyinfo
);
8151 /* Just discard the mouse face information for frame F, if any.
8152 This is used when the size of F is changed. */
8155 cancel_mouse_face (f
)
8159 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8161 window
= dpyinfo
->mouse_face_window
;
8162 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
8164 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8165 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8166 dpyinfo
->mouse_face_window
= Qnil
;
8170 static struct scroll_bar
*x_window_to_scroll_bar ();
8171 static void x_scroll_bar_report_motion ();
8172 static void x_check_fullscreen
P_ ((struct frame
*));
8173 static void x_check_fullscreen_move
P_ ((struct frame
*));
8174 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
8177 /* Try to determine frame pixel position and size of the glyph under
8178 frame pixel coordinates X/Y on frame F . Return the position and
8179 size in *RECT. Value is non-zero if we could compute these
8183 glyph_rect (f
, x
, y
, rect
)
8191 window
= window_from_coordinates (f
, x
, y
, &part
, 0);
8194 struct window
*w
= XWINDOW (window
);
8195 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
8196 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
8198 frame_to_window_pixel_xy (w
, &x
, &y
);
8200 for (; r
< end
&& r
->enabled_p
; ++r
)
8201 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
8203 /* Found the row at y. */
8204 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
8205 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
8208 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
8209 rect
->bottom
= rect
->top
+ r
->height
;
8213 /* x is to the left of the first glyph in the row. */
8214 rect
->left
= XINT (w
->left
);
8215 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
8219 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
8220 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
8222 /* x is on a glyph. */
8223 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
8224 rect
->right
= rect
->left
+ g
->pixel_width
;
8228 /* x is to the right of the last glyph in the row. */
8229 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
8230 rect
->right
= XINT (w
->left
) + XINT (w
->width
);
8235 /* The y is not on any row. */
8239 /* Record the position of the mouse in last_mouse_glyph. */
8241 remember_mouse_glyph (f1
, gx
, gy
)
8245 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
8247 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
8248 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
8250 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8251 round down even for negative values. */
8257 /* This was the original code from XTmouse_position, but it seems
8258 to give the position of the glyph diagonally next to the one
8259 the mouse is over. */
8260 gx
= (gx
+ width
- 1) / width
* width
;
8261 gy
= (gy
+ height
- 1) / height
* height
;
8263 gx
= gx
/ width
* width
;
8264 gy
= gy
/ height
* height
;
8267 last_mouse_glyph
.left
= gx
;
8268 last_mouse_glyph
.top
= gy
;
8269 last_mouse_glyph
.right
= gx
+ width
;
8270 last_mouse_glyph
.bottom
= gy
+ height
;
8274 /* Return the current position of the mouse.
8275 *fp should be a frame which indicates which display to ask about.
8277 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8278 and *part to the frame, window, and scroll bar part that the mouse
8279 is over. Set *x and *y to the portion and whole of the mouse's
8280 position on the scroll bar.
8282 If the mouse movement started elsewhere, set *fp to the frame the
8283 mouse is on, *bar_window to nil, and *x and *y to the character cell
8286 Set *time to the server time-stamp for the time at which the mouse
8287 was at this position.
8289 Don't store anything if we don't have a valid set of values to report.
8291 This clears the mouse_moved flag, so we can wait for the next mouse
8295 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
8298 Lisp_Object
*bar_window
;
8299 enum scroll_bar_part
*part
;
8301 unsigned long *time
;
8304 int ignore1
, ignore2
;
8305 WindowPtr wp
= FrontWindow ();
8307 Lisp_Object frame
, tail
;
8309 if (is_emacs_window(wp
))
8310 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
8314 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
8315 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
8318 /* Clear the mouse-moved flag for every frame on this display. */
8319 FOR_EACH_FRAME (tail
, frame
)
8320 XFRAME (frame
)->mouse_moved
= 0;
8322 last_mouse_scroll_bar
= Qnil
;
8324 #if TARGET_API_MAC_CARBON
8325 SetPort (GetWindowPort (wp
));
8330 GetMouse (&mouse_pos
);
8332 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
8333 &last_mouse_glyph
, insist
);
8336 *part
= scroll_bar_handle
;
8338 XSETINT (*x
, mouse_pos
.h
);
8339 XSETINT (*y
, mouse_pos
.v
);
8340 *time
= last_mouse_movement_time
;
8347 /************************************************************************
8348 Scroll bars, general
8349 ************************************************************************/
8351 /* Create a scroll bar and return the scroll bar vector for it. W is
8352 the Emacs window on which to create the scroll bar. TOP, LEFT,
8353 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8356 static struct scroll_bar
*
8357 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
8359 int top
, left
, width
, height
, disp_top
, disp_height
;
8361 struct frame
*f
= XFRAME (w
->frame
);
8362 struct scroll_bar
*bar
8363 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
8371 r
.right
= left
+ width
;
8372 r
.bottom
= disp_top
+ disp_height
;
8374 #ifdef TARGET_API_MAC_CARBON
8375 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
8376 kControlScrollBarProc
, 0L);
8378 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
8381 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
8382 SetControlReference (ch
, (long) bar
);
8384 XSETWINDOW (bar
->window
, w
);
8385 XSETINT (bar
->top
, top
);
8386 XSETINT (bar
->left
, left
);
8387 XSETINT (bar
->width
, width
);
8388 XSETINT (bar
->height
, height
);
8389 XSETINT (bar
->start
, 0);
8390 XSETINT (bar
->end
, 0);
8391 bar
->dragging
= Qnil
;
8393 /* Add bar to its frame's list of scroll bars. */
8394 bar
->next
= FRAME_SCROLL_BARS (f
);
8396 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8397 if (!NILP (bar
->next
))
8398 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8405 /* Draw BAR's handle in the proper position.
8407 If the handle is already drawn from START to END, don't bother
8408 redrawing it, unless REBUILD is non-zero; in that case, always
8409 redraw it. (REBUILD is handy for drawing the handle after expose
8412 Normally, we want to constrain the start and end of the handle to
8413 fit inside its rectangle, but if the user is dragging the scroll
8414 bar handle, we want to let them drag it down all the way, so that
8415 the bar's top is as far down as it goes; otherwise, there's no way
8416 to move to the very end of the buffer. */
8419 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
8420 struct scroll_bar
*bar
;
8424 int dragging
= ! NILP (bar
->dragging
);
8425 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
8426 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8427 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8428 int length
= end
- start
;
8430 /* If the display is already accurate, do nothing. */
8432 && start
== XINT (bar
->start
)
8433 && end
== XINT (bar
->end
))
8438 /* Make sure the values are reasonable, and try to preserve the
8439 distance between start and end. */
8442 else if (start
> top_range
)
8444 end
= start
+ length
;
8448 else if (end
> top_range
&& ! dragging
)
8451 /* Store the adjusted setting in the scroll bar. */
8452 XSETINT (bar
->start
, start
);
8453 XSETINT (bar
->end
, end
);
8455 /* Clip the end position, just for display. */
8456 if (end
> top_range
)
8459 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8460 top positions, to make sure the handle is always at least that
8461 many pixels tall. */
8462 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
8464 SetControlMinimum (ch
, 0);
8465 /* Don't inadvertently activate deactivated scroll bars */
8466 if (GetControlMaximum (ch
) != -1)
8467 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
8469 SetControlValue (ch
, start
);
8470 #if TARGET_API_MAC_CARBON
8471 SetControlViewSize (ch
, end
- start
);
8478 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8482 x_scroll_bar_remove (bar
)
8483 struct scroll_bar
*bar
;
8485 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8489 /* Destroy the Mac scroll bar control */
8490 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
8492 /* Disassociate this scroll bar from its window. */
8493 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
8498 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8499 that we are displaying PORTION characters out of a total of WHOLE
8500 characters, starting at POSITION. If WINDOW has no scroll bar,
8503 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
8505 int portion
, whole
, position
;
8507 struct frame
*f
= XFRAME (w
->frame
);
8508 struct scroll_bar
*bar
;
8509 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
8510 int window_x
, window_y
, window_width
, window_height
;
8512 /* Get window dimensions. */
8513 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
8518 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
8520 height
= window_height
;
8522 /* Compute the left edge of the scroll bar area. */
8523 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8524 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
8526 left
= XFASTINT (w
->left
);
8527 left
*= CANON_X_UNIT (f
);
8528 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
8530 /* Compute the width of the scroll bar which might be less than
8531 the width of the area reserved for the scroll bar. */
8532 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
8533 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
8537 /* Compute the left edge of the scroll bar. */
8538 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8539 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
8541 sb_left
= left
+ (width
- sb_width
) / 2;
8543 /* Adjustments according to Inside Macintosh to make it look nice */
8545 disp_height
= height
;
8551 else if (disp_top
== PIXEL_HEIGHT (f
) - 16)
8557 if (sb_left
+ sb_width
== PIXEL_WIDTH (f
))
8560 /* Does the scroll bar exist yet? */
8561 if (NILP (w
->vertical_scroll_bar
))
8564 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
8565 left
, top
, width
, height
, 0);
8567 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
8569 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
8573 /* It may just need to be moved and resized. */
8576 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
8577 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
8581 /* If already correctly positioned, do nothing. */
8582 if (XINT (bar
->left
) == sb_left
8583 && XINT (bar
->top
) == top
8584 && XINT (bar
->width
) == sb_width
8585 && XINT (bar
->height
) == height
)
8589 /* Clear areas not covered by the scroll bar because it's not as
8590 wide as the area reserved for it . This makes sure a
8591 previous mode line display is cleared after C-x 2 C-x 1, for
8593 int area_width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
8594 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
8595 left
, top
, area_width
, height
, 0);
8598 if (sb_left
+ sb_width
>= PIXEL_WIDTH (f
))
8599 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
8600 sb_left
- 1, top
, 1, height
, 0);
8604 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
8605 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8609 /* Remember new settings. */
8610 XSETINT (bar
->left
, sb_left
);
8611 XSETINT (bar
->top
, top
);
8612 XSETINT (bar
->width
, sb_width
);
8613 XSETINT (bar
->height
, height
);
8619 /* Set the scroll bar's current state, unless we're currently being
8621 if (NILP (bar
->dragging
))
8623 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
8626 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
8629 int start
= ((double) position
* top_range
) / whole
;
8630 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
8631 x_scroll_bar_set_handle (bar
, start
, end
, 0);
8637 /* The following three hooks are used when we're doing a thorough
8638 redisplay of the frame. We don't explicitly know which scroll bars
8639 are going to be deleted, because keeping track of when windows go
8640 away is a real pain - "Can you say set-window-configuration, boys
8641 and girls?" Instead, we just assert at the beginning of redisplay
8642 that *all* scroll bars are to be removed, and then save a scroll bar
8643 from the fiery pit when we actually redisplay its window. */
8645 /* Arrange for all scroll bars on FRAME to be removed at the next call
8646 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8647 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8650 XTcondemn_scroll_bars (frame
)
8653 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8654 while (! NILP (FRAME_SCROLL_BARS (frame
)))
8657 bar
= FRAME_SCROLL_BARS (frame
);
8658 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
8659 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
8660 XSCROLL_BAR (bar
)->prev
= Qnil
;
8661 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
8662 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
8663 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
8668 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8669 Note that WINDOW isn't necessarily condemned at all. */
8672 XTredeem_scroll_bar (window
)
8673 struct window
*window
;
8675 struct scroll_bar
*bar
;
8677 /* We can't redeem this window's scroll bar if it doesn't have one. */
8678 if (NILP (window
->vertical_scroll_bar
))
8681 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
8683 /* Unlink it from the condemned list. */
8685 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
8687 if (NILP (bar
->prev
))
8689 /* If the prev pointer is nil, it must be the first in one of
8691 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
8692 /* It's not condemned. Everything's fine. */
8694 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
8695 window
->vertical_scroll_bar
))
8696 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
8698 /* If its prev pointer is nil, it must be at the front of
8699 one or the other! */
8703 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
8705 if (! NILP (bar
->next
))
8706 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
8708 bar
->next
= FRAME_SCROLL_BARS (f
);
8710 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8711 if (! NILP (bar
->next
))
8712 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8716 /* Remove all scroll bars on FRAME that haven't been saved since the
8717 last call to `*condemn_scroll_bars_hook'. */
8720 XTjudge_scroll_bars (f
)
8723 Lisp_Object bar
, next
;
8725 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
8727 /* Clear out the condemned list now so we won't try to process any
8728 more events on the hapless scroll bars. */
8729 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
8731 for (; ! NILP (bar
); bar
= next
)
8733 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
8735 x_scroll_bar_remove (b
);
8738 b
->next
= b
->prev
= Qnil
;
8741 /* Now there should be no references to the condemned scroll bars,
8742 and they should get garbage-collected. */
8747 activate_scroll_bars (frame
)
8753 bar
= FRAME_SCROLL_BARS (frame
);
8754 while (! NILP (bar
))
8756 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
8757 #ifdef TARGET_API_MAC_CARBON
8758 ActivateControl (ch
);
8760 SetControlMaximum (ch
,
8761 VERTICAL_SCROLL_BAR_TOP_RANGE (frame
,
8762 XINT (XSCROLL_BAR (bar
)
8765 bar
= XSCROLL_BAR (bar
)->next
;
8771 deactivate_scroll_bars (frame
)
8777 bar
= FRAME_SCROLL_BARS (frame
);
8778 while (! NILP (bar
))
8780 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
8781 #ifdef TARGET_API_MAC_CARBON
8782 DeactivateControl (ch
);
8784 SetControlMaximum (ch
, XINT (-1));
8786 bar
= XSCROLL_BAR (bar
)->next
;
8790 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8791 is set to something other than NO_EVENT, it is enqueued.
8793 This may be called from a signal handler, so we have to ignore GC
8797 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
8798 struct scroll_bar
*bar
;
8801 struct input_event
*bufp
;
8803 if (! GC_WINDOWP (bar
->window
))
8806 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
8807 bufp
->frame_or_window
= bar
->window
;
8810 bar
->dragging
= Qnil
;
8814 case kControlUpButtonPart
:
8815 bufp
->part
= scroll_bar_up_arrow
;
8817 case kControlDownButtonPart
:
8818 bufp
->part
= scroll_bar_down_arrow
;
8820 case kControlPageUpPart
:
8821 bufp
->part
= scroll_bar_above_handle
;
8823 case kControlPageDownPart
:
8824 bufp
->part
= scroll_bar_below_handle
;
8826 #ifdef TARGET_API_MAC_CARBON
8829 case kControlIndicatorPart
:
8831 if (er
->what
== mouseDown
)
8832 bar
->dragging
= make_number (0);
8833 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8834 bufp
->part
= scroll_bar_handle
;
8840 /* Handle some mouse motion while someone is dragging the scroll bar.
8842 This may be called from a signal handler, so we have to ignore GC
8846 x_scroll_bar_note_movement (bar
, y_pos
, t
)
8847 struct scroll_bar
*bar
;
8851 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
8853 last_mouse_movement_time
= t
;
8856 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8858 /* If we're dragging the bar, display it. */
8859 if (! GC_NILP (bar
->dragging
))
8861 /* Where should the handle be now? */
8862 int new_start
= y_pos
- 24;
8864 if (new_start
!= XINT (bar
->start
))
8866 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8868 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8874 /* Return information to the user about the current position of the
8875 mouse on the scroll bar. */
8878 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
8880 Lisp_Object
*bar_window
;
8881 enum scroll_bar_part
*part
;
8883 unsigned long *time
;
8885 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
8886 WindowPtr wp
= FrontWindow ();
8888 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
8889 int win_y
, top_range
;
8891 #if TARGET_API_MAC_CARBON
8892 SetPort (GetWindowPort (wp
));
8897 GetMouse (&mouse_pos
);
8899 win_y
= mouse_pos
.v
- XINT (bar
->top
);
8900 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8902 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
8906 if (! NILP (bar
->dragging
))
8907 win_y
-= XINT (bar
->dragging
);
8911 if (win_y
> top_range
)
8915 *bar_window
= bar
->window
;
8917 if (! NILP (bar
->dragging
))
8918 *part
= scroll_bar_handle
;
8919 else if (win_y
< XINT (bar
->start
))
8920 *part
= scroll_bar_above_handle
;
8921 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8922 *part
= scroll_bar_handle
;
8924 *part
= scroll_bar_below_handle
;
8926 XSETINT (*x
, win_y
);
8927 XSETINT (*y
, top_range
);
8930 last_mouse_scroll_bar
= Qnil
;
8932 *time
= last_mouse_movement_time
;
8935 /***********************************************************************
8937 ***********************************************************************/
8939 /* Notice if the text cursor of window W has been overwritten by a
8940 drawing operation that outputs glyphs starting at START_X and
8941 ending at END_X in the line given by output_cursor.vpos.
8942 Coordinates are area-relative. END_X < 0 means all the rest
8943 of the line after START_X has been written. */
8946 notice_overwritten_cursor (w
, area
, x0
, x1
, y0
, y1
)
8948 enum glyph_row_area area
;
8951 if (area
== TEXT_AREA
8952 && w
->phys_cursor_on_p
8953 && y0
<= w
->phys_cursor
.y
8954 && y1
>= w
->phys_cursor
.y
+ w
->phys_cursor_height
8955 && x0
<= w
->phys_cursor
.x
8956 && (x1
< 0 || x1
> w
->phys_cursor
.x
))
8957 w
->phys_cursor_on_p
= 0;
8961 /* Set clipping for output in glyph row ROW. W is the window in which
8962 we operate. GC is the graphics context to set clipping in.
8963 WHOLE_LINE_P non-zero means include the areas used for truncation
8964 mark display and alike in the clipping rectangle.
8966 ROW may be a text row or, e.g., a mode line. Text rows must be
8967 clipped to the interior of the window dedicated to text display,
8968 mode lines must be clipped to the whole window. */
8971 x_clip_to_row (w
, row
, gc
, whole_line_p
)
8973 struct glyph_row
*row
;
8977 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
8979 int window_x
, window_y
, window_width
, window_height
;
8981 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
8983 clip_rect
.left
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
8984 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
8985 clip_rect
.top
= max (clip_rect
.top
, window_y
);
8986 clip_rect
.right
= clip_rect
.left
+ window_width
;
8987 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
8989 /* If clipping to the whole line, including trunc marks, extend
8990 the rectangle to the left and increase its width. */
8993 clip_rect
.left
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
8994 clip_rect
.right
+= FRAME_X_FRINGE_WIDTH (f
);
8997 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
9001 /* Draw a hollow box cursor on window W in glyph row ROW. */
9004 x_draw_hollow_cursor (w
, row
)
9006 struct glyph_row
*row
;
9008 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9009 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
9010 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
9013 struct glyph
*cursor_glyph
;
9016 /* Compute frame-relative coordinates from window-relative
9018 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
9019 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
9020 + row
->ascent
- w
->phys_cursor_ascent
);
9021 h
= row
->height
- 1;
9023 /* Get the glyph the cursor is on. If we can't tell because
9024 the current matrix is invalid or such, give up. */
9025 cursor_glyph
= get_phys_cursor_glyph (w
);
9026 if (cursor_glyph
== NULL
)
9029 /* Compute the width of the rectangle to draw. If on a stretch
9030 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9031 rectangle as wide as the glyph, but use a canonical character
9033 wd
= cursor_glyph
->pixel_width
- 1;
9034 if (cursor_glyph
->type
== STRETCH_GLYPH
9035 && !x_stretch_cursor_p
)
9036 wd
= min (CANON_X_UNIT (f
), wd
);
9038 /* The foreground of cursor_gc is typically the same as the normal
9039 background color, which can cause the cursor box to be invisible. */
9040 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
9041 if (dpyinfo
->scratch_cursor_gc
)
9042 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
9044 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
9045 GCForeground
, &xgcv
);
9046 gc
= dpyinfo
->scratch_cursor_gc
;
9048 /* Set clipping, draw the rectangle, and reset clipping again. */
9049 x_clip_to_row (w
, row
, gc
, 0);
9050 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
9051 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
9055 /* Draw a bar cursor on window W in glyph row ROW.
9057 Implementation note: One would like to draw a bar cursor with an
9058 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9059 Unfortunately, I didn't find a font yet that has this property set.
9063 x_draw_bar_cursor (w
, row
, width
)
9065 struct glyph_row
*row
;
9068 /* If cursor hpos is out of bounds, don't draw garbage. This can
9069 happen in mini-buffer windows when switching between echo area
9070 glyphs and mini-buffer. */
9071 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
9073 struct frame
*f
= XFRAME (w
->frame
);
9074 struct glyph
*cursor_glyph
;
9082 cursor_glyph
= get_phys_cursor_glyph (w
);
9083 if (cursor_glyph
== NULL
)
9086 xgcv
.background
= f
->output_data
.mac
->cursor_pixel
;
9087 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
9088 mask
= GCForeground
| GCBackground
;
9089 dpy
= FRAME_MAC_DISPLAY (f
);
9090 window
= FRAME_MAC_WINDOW (f
);
9091 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
9094 XChangeGC (dpy
, gc
, mask
, &xgcv
);
9097 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
9098 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
9102 width
= FRAME_CURSOR_WIDTH (f
);
9104 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
9105 x_clip_to_row (w
, row
, gc
, 0);
9106 XFillRectangle (dpy
, window
, gc
,
9108 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
9109 min (cursor_glyph
->pixel_width
, width
),
9111 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
9116 /* Clear the cursor of window W to background color, and mark the
9117 cursor as not shown. This is used when the text where the cursor
9118 is is about to be rewritten. */
9124 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
9125 x_update_window_cursor (w
, 0);
9129 /* Draw the cursor glyph of window W in glyph row ROW. See the
9130 comment of x_draw_glyphs for the meaning of HL. */
9133 x_draw_phys_cursor_glyph (w
, row
, hl
)
9135 struct glyph_row
*row
;
9136 enum draw_glyphs_face hl
;
9138 /* If cursor hpos is out of bounds, don't draw garbage. This can
9139 happen in mini-buffer windows when switching between echo area
9140 glyphs and mini-buffer. */
9141 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
9143 int on_p
= w
->phys_cursor_on_p
;
9144 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
9145 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
9147 w
->phys_cursor_on_p
= on_p
;
9149 /* When we erase the cursor, and ROW is overlapped by other
9150 rows, make sure that these overlapping parts of other rows
9152 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
9154 if (row
> w
->current_matrix
->rows
9155 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
9156 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
9158 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
9159 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
9160 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
9166 /* Erase the image of a cursor of window W from the screen. */
9169 x_erase_phys_cursor (w
)
9172 struct frame
*f
= XFRAME (w
->frame
);
9173 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9174 int hpos
= w
->phys_cursor
.hpos
;
9175 int vpos
= w
->phys_cursor
.vpos
;
9176 int mouse_face_here_p
= 0;
9177 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
9178 struct glyph_row
*cursor_row
;
9179 struct glyph
*cursor_glyph
;
9180 enum draw_glyphs_face hl
;
9182 /* No cursor displayed or row invalidated => nothing to do on the
9184 if (w
->phys_cursor_type
== NO_CURSOR
)
9185 goto mark_cursor_off
;
9187 /* VPOS >= active_glyphs->nrows means that window has been resized.
9188 Don't bother to erase the cursor. */
9189 if (vpos
>= active_glyphs
->nrows
)
9190 goto mark_cursor_off
;
9192 /* If row containing cursor is marked invalid, there is nothing we
9194 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
9195 if (!cursor_row
->enabled_p
)
9196 goto mark_cursor_off
;
9198 /* If row is completely invisible, don't attempt to delete a cursor which
9199 isn't there. This may happen if cursor is at top of window, and
9200 we switch to a buffer with a header line in that window. */
9201 if (cursor_row
->visible_height
<= 0)
9202 goto mark_cursor_off
;
9204 /* This can happen when the new row is shorter than the old one.
9205 In this case, either x_draw_glyphs or clear_end_of_line
9206 should have cleared the cursor. Note that we wouldn't be
9207 able to erase the cursor in this case because we don't have a
9208 cursor glyph at hand. */
9209 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
9210 goto mark_cursor_off
;
9212 /* If the cursor is in the mouse face area, redisplay that when
9213 we clear the cursor. */
9214 if (! NILP (dpyinfo
->mouse_face_window
)
9215 && w
== XWINDOW (dpyinfo
->mouse_face_window
)
9216 && (vpos
> dpyinfo
->mouse_face_beg_row
9217 || (vpos
== dpyinfo
->mouse_face_beg_row
9218 && hpos
>= dpyinfo
->mouse_face_beg_col
))
9219 && (vpos
< dpyinfo
->mouse_face_end_row
9220 || (vpos
== dpyinfo
->mouse_face_end_row
9221 && hpos
< dpyinfo
->mouse_face_end_col
))
9222 /* Don't redraw the cursor's spot in mouse face if it is at the
9223 end of a line (on a newline). The cursor appears there, but
9224 mouse highlighting does not. */
9225 && cursor_row
->used
[TEXT_AREA
] > hpos
)
9226 mouse_face_here_p
= 1;
9228 /* Maybe clear the display under the cursor. */
9229 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
9232 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
9234 cursor_glyph
= get_phys_cursor_glyph (w
);
9235 if (cursor_glyph
== NULL
)
9236 goto mark_cursor_off
;
9238 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
9240 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
9242 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
9244 cursor_glyph
->pixel_width
,
9245 cursor_row
->visible_height
,
9249 /* Erase the cursor by redrawing the character underneath it. */
9250 if (mouse_face_here_p
)
9251 hl
= DRAW_MOUSE_FACE
;
9253 hl
= DRAW_NORMAL_TEXT
;
9254 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
9257 w
->phys_cursor_on_p
= 0;
9258 w
->phys_cursor_type
= NO_CURSOR
;
9262 /* Non-zero if physical cursor of window W is within mouse face. */
9265 cursor_in_mouse_face_p (w
)
9268 struct mac_display_info
*dpyinfo
9269 = FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
9270 int in_mouse_face
= 0;
9272 if (WINDOWP (dpyinfo
->mouse_face_window
)
9273 && XWINDOW (dpyinfo
->mouse_face_window
) == w
)
9275 int hpos
= w
->phys_cursor
.hpos
;
9276 int vpos
= w
->phys_cursor
.vpos
;
9278 if (vpos
>= dpyinfo
->mouse_face_beg_row
9279 && vpos
<= dpyinfo
->mouse_face_end_row
9280 && (vpos
> dpyinfo
->mouse_face_beg_row
9281 || hpos
>= dpyinfo
->mouse_face_beg_col
)
9282 && (vpos
< dpyinfo
->mouse_face_end_row
9283 || hpos
< dpyinfo
->mouse_face_end_col
9284 || dpyinfo
->mouse_face_past_end
))
9288 return in_mouse_face
;
9292 /* Display or clear cursor of window W. If ON is zero, clear the
9293 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9294 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9297 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
9299 int on
, hpos
, vpos
, x
, y
;
9301 struct frame
*f
= XFRAME (w
->frame
);
9302 int new_cursor_type
;
9303 int new_cursor_width
;
9305 struct glyph_matrix
*current_glyphs
;
9306 struct glyph_row
*glyph_row
;
9307 struct glyph
*glyph
;
9309 /* This is pointless on invisible frames, and dangerous on garbaged
9310 windows and frames; in the latter case, the frame or window may
9311 be in the midst of changing its size, and x and y may be off the
9313 if (! FRAME_VISIBLE_P (f
)
9314 || FRAME_GARBAGED_P (f
)
9315 || vpos
>= w
->current_matrix
->nrows
9316 || hpos
>= w
->current_matrix
->matrix_w
)
9319 /* If cursor is off and we want it off, return quickly. */
9320 if (!on
&& !w
->phys_cursor_on_p
)
9323 current_glyphs
= w
->current_matrix
;
9324 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
9325 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
9327 /* If cursor row is not enabled, we don't really know where to
9328 display the cursor. */
9329 if (!glyph_row
->enabled_p
)
9331 w
->phys_cursor_on_p
= 0;
9335 xassert (interrupt_input_blocked
);
9337 /* Set new_cursor_type to the cursor we want to be displayed. */
9338 new_cursor_type
= get_window_cursor_type (w
, &new_cursor_width
, &active_cursor
);
9341 /* If cursor is currently being shown and we don't want it to be or
9342 it is in the wrong place, or the cursor type is not what we want,
9344 if (w
->phys_cursor_on_p
9346 || w
->phys_cursor
.x
!= x
9347 || w
->phys_cursor
.y
!= y
9348 || new_cursor_type
!= w
->phys_cursor_type
9349 || ((new_cursor_type
== BAR_CURSOR
|| new_cursor_type
== HBAR_CURSOR
)
9350 && new_cursor_width
!= w
->phys_cursor_width
)))
9351 x_erase_phys_cursor (w
);
9353 /* If the cursor is now invisible and we want it to be visible,
9355 if (on
&& !w
->phys_cursor_on_p
)
9357 w
->phys_cursor_ascent
= glyph_row
->ascent
;
9358 w
->phys_cursor_height
= glyph_row
->height
;
9360 /* Set phys_cursor_.* before x_draw_.* is called because some
9361 of them may need the information. */
9362 w
->phys_cursor
.x
= x
;
9363 w
->phys_cursor
.y
= glyph_row
->y
;
9364 w
->phys_cursor
.hpos
= hpos
;
9365 w
->phys_cursor
.vpos
= vpos
;
9366 w
->phys_cursor_type
= new_cursor_type
;
9367 w
->phys_cursor_width
= new_cursor_width
;
9368 w
->phys_cursor_on_p
= 1;
9370 switch (new_cursor_type
)
9372 case HOLLOW_BOX_CURSOR
:
9373 x_draw_hollow_cursor (w
, glyph_row
);
9376 case FILLED_BOX_CURSOR
:
9377 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
9381 /* TODO. For now, just draw bar 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
;
11501 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
11502 for processing before Emacs sees it. */
11503 Lisp_Object Vmac_pass_command_to_system
;
11505 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
11506 for processing before Emacs sees it. */
11507 Lisp_Object Vmac_pass_control_to_system
;
11510 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11511 to this text encoding */
11512 int mac_keyboard_text_encoding
;
11513 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
11515 /* Set in term/mac-win.el to indicate that event loop can now generate
11516 drag and drop events. */
11517 Lisp_Object Qmac_ready_for_drag_n_drop
;
11519 Lisp_Object drag_and_drop_file_list
;
11521 Point saved_menu_event_location
;
11524 static void init_required_apple_events (void);
11525 static pascal OSErr
11526 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
11527 static pascal OSErr
11528 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
11529 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
11530 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
11532 /* Drag and Drop */
11533 static OSErr
init_mac_drag_n_drop ();
11534 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
11536 #if USE_CARBON_EVENTS
11537 /* Preliminary Support for the OSX Services Menu */
11538 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
11539 static void init_service_handler ();
11542 extern void init_emacs_passwd_dir ();
11543 extern int emacs_main (int, char **, char **);
11544 extern void check_alarm ();
11546 extern void initialize_applescript();
11547 extern void terminate_applescript();
11549 static unsigned int
11550 #if USE_CARBON_EVENTS
11551 mac_to_emacs_modifiers (UInt32 mods
)
11553 mac_to_emacs_modifiers (EventModifiers mods
)
11556 unsigned int result
= 0;
11557 if (mods
& macShiftKey
)
11558 result
|= shift_modifier
;
11559 if (mods
& macCtrlKey
)
11560 result
|= ctrl_modifier
;
11561 if (mods
& macMetaKey
)
11562 result
|= meta_modifier
;
11563 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
11564 result
|= alt_modifier
;
11568 #if USE_CARBON_EVENTS
11569 /* Obtains the event modifiers from the event ref and then calls
11570 mac_to_emacs_modifiers. */
11572 mac_event_to_emacs_modifiers (EventRef eventRef
)
11575 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
11576 sizeof (UInt32
), NULL
, &mods
);
11577 return mac_to_emacs_modifiers (mods
);
11580 /* Given an event ref, return the code to use for the mouse button
11581 code in the emacs input_event. */
11583 mac_get_mouse_btn (EventRef ref
)
11585 EventMouseButton result
= kEventMouseButtonPrimary
;
11586 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
11587 sizeof (EventMouseButton
), NULL
, &result
);
11590 case kEventMouseButtonPrimary
:
11592 case kEventMouseButtonSecondary
:
11593 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
11594 case kEventMouseButtonTertiary
:
11595 case 4: /* 4 is the number for the mouse wheel button */
11596 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
11602 /* Normally, ConvertEventRefToEventRecord will correctly handle all
11603 events. However the click of the mouse wheel is not converted to a
11604 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11605 checks to see if it is a mouse up or down carbon event that has not
11606 been converted, and if so, converts it by hand (to be picked up in
11607 the XTread_socket loop). */
11608 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
11610 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
11611 /* Do special case for mouse wheel button. */
11612 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
11614 UInt32 kind
= GetEventKind (eventRef
);
11615 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
11617 eventRec
->what
= mouseDown
;
11620 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
11622 eventRec
->what
= mouseUp
;
11627 /* Need where and when. */
11629 GetEventParameter (eventRef
, kEventParamMouseLocation
,
11630 typeQDPoint
, NULL
, sizeof (Point
),
11631 NULL
, &eventRec
->where
);
11632 /* Use two step process because new event modifiers are
11633 32-bit and old are 16-bit. Currently, only loss is
11635 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
11636 typeUInt32
, NULL
, sizeof (UInt32
),
11638 eventRec
->modifiers
= mods
;
11640 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
11649 do_get_menus (void)
11651 Handle menubar_handle
;
11652 MenuHandle menu_handle
;
11654 menubar_handle
= GetNewMBar (128);
11655 if(menubar_handle
== NULL
)
11657 SetMenuBar (menubar_handle
);
11660 menu_handle
= GetMenuHandle (M_APPLE
);
11661 if(menu_handle
!= NULL
)
11662 AppendResMenu (menu_handle
,'DRVR');
11669 do_init_managers (void)
11671 #if !TARGET_API_MAC_CARBON
11672 InitGraf (&qd
.thePort
);
11674 FlushEvents (everyEvent
, 0);
11678 InitDialogs (NULL
);
11679 #endif /* !TARGET_API_MAC_CARBON */
11682 #if !TARGET_API_MAC_CARBON
11683 /* set up some extra stack space for use by emacs */
11684 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
11686 /* MaxApplZone must be called for AppleScript to execute more
11687 complicated scripts */
11690 #endif /* !TARGET_API_MAC_CARBON */
11694 do_check_ram_size (void)
11696 SInt32 physical_ram_size
, logical_ram_size
;
11698 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
11699 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
11700 || physical_ram_size
> 256 * 1024 * 1024
11701 || logical_ram_size
> 256 * 1024 * 1024)
11703 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
11709 do_window_update (WindowPtr win
)
11711 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (win
);
11712 struct frame
*f
= mwp
->mFP
;
11716 if (f
->async_visible
== 0)
11718 f
->async_visible
= 1;
11719 f
->async_iconified
= 0;
11720 SET_FRAME_GARBAGED (f
);
11722 /* An update event is equivalent to MapNotify on X, so report
11723 visibility changes properly. */
11724 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
11725 /* Force a redisplay sooner or later to update the
11726 frame titles in case this is the second frame. */
11727 record_asynch_buffer_change ();
11732 handling_window_update
= 1;
11734 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
11736 expose_frame (f
, 0, 0, 0, 0);
11738 handling_window_update
= 0;
11745 is_emacs_window (WindowPtr win
)
11747 Lisp_Object tail
, frame
;
11752 FOR_EACH_FRAME (tail
, frame
)
11753 if (FRAME_MAC_P (XFRAME (frame
)))
11754 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
11761 do_window_activate (WindowPtr win
)
11766 if (is_emacs_window (win
))
11768 mwp
= (mac_output
*) GetWRefCon (win
);
11773 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
11774 activate_scroll_bars (f
);
11780 do_window_deactivate (WindowPtr win
)
11785 if (is_emacs_window (win
))
11787 mwp
= (mac_output
*) GetWRefCon (win
);
11790 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
11792 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
11793 deactivate_scroll_bars (f
);
11805 wp
= FrontWindow();
11806 if (is_emacs_window (wp
))
11808 mwp
= (mac_output
*) GetWRefCon (wp
);
11813 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
11814 activate_scroll_bars (f
);
11818 app_is_suspended
= false;
11819 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
11829 wp
= FrontWindow();
11830 if (is_emacs_window (wp
))
11832 mwp
= (mac_output
*) GetWRefCon (wp
);
11835 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
11837 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
11838 deactivate_scroll_bars (f
);
11842 app_is_suspended
= true;
11843 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
11848 do_mouse_moved (Point mouse_pos
)
11850 WindowPtr wp
= FrontWindow ();
11853 if (is_emacs_window (wp
))
11855 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
11857 #if TARGET_API_MAC_CARBON
11858 SetPort (GetWindowPort (wp
));
11863 GlobalToLocal (&mouse_pos
);
11865 note_mouse_movement (f
, &mouse_pos
);
11871 do_os_event (EventRecord
*erp
)
11873 switch((erp
->message
>> 24) & 0x000000FF)
11875 case suspendResumeMessage
:
11876 if((erp
->message
& resumeFlag
) == 1)
11882 case mouseMovedMessage
:
11883 do_mouse_moved (erp
->where
);
11889 do_events (EventRecord
*erp
)
11894 do_window_update ((WindowPtr
) erp
->message
);
11902 if ((erp
->modifiers
& activeFlag
) != 0)
11903 do_window_activate ((WindowPtr
) erp
->message
);
11905 do_window_deactivate ((WindowPtr
) erp
->message
);
11911 do_apple_menu (SInt16 menu_item
)
11913 #if !TARGET_API_MAC_CARBON
11915 SInt16 da_driver_refnum
;
11917 if (menu_item
== I_ABOUT
)
11918 NoteAlert (ABOUT_ALERT_ID
, NULL
);
11921 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
11922 da_driver_refnum
= OpenDeskAcc (item_name
);
11924 #endif /* !TARGET_API_MAC_CARBON */
11928 do_menu_choice (SInt32 menu_choice
)
11930 SInt16 menu_id
, menu_item
;
11932 menu_id
= HiWord (menu_choice
);
11933 menu_item
= LoWord (menu_choice
);
11941 do_apple_menu (menu_item
);
11946 WindowPtr wp
= FrontWindow ();
11947 struct frame
*f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
11948 MenuHandle menu
= GetMenuHandle (menu_id
);
11953 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
11954 menubar_selection_callback (f
, refcon
);
11963 /* Handle drags in size box. Based on code contributed by Ben
11964 Mesander and IM - Window Manager A. */
11967 do_grow_window (WindowPtr w
, EventRecord
*e
)
11972 mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
11973 struct frame
*f
= mwp
->mFP
;
11975 SetRect(&limit_rect
, MIN_DOC_SIZE
, MIN_DOC_SIZE
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
11977 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
11979 /* see if it really changed size */
11980 if (grow_size
!= 0)
11982 rows
= PIXEL_TO_CHAR_HEIGHT (f
, HiWord (grow_size
));
11983 columns
= PIXEL_TO_CHAR_WIDTH (f
, LoWord (grow_size
));
11985 x_set_window_size (f
, 0, columns
, rows
);
11990 /* Handle clicks in zoom box. Calculation of "standard state" based
11991 on code in IM - Window Manager A and code contributed by Ben
11992 Mesander. The standard state of an Emacs window is 80-characters
11993 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11996 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
11999 Rect zoom_rect
, port_rect
;
12001 int w_title_height
, columns
, rows
, width
, height
, dummy
, x
, y
;
12002 mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
12003 struct frame
*f
= mwp
->mFP
;
12005 GetPort (&save_port
);
12007 #if TARGET_API_MAC_CARBON
12008 SetPort (GetWindowPort (w
));
12013 /* Clear window to avoid flicker. */
12014 #if TARGET_API_MAC_CARBON
12019 GetWindowPortBounds (w
, &r
);
12022 if (zoom_in_or_out
== inZoomOut
)
12024 /* calculate height of window's title bar (hard card it for now). */
12025 w_title_height
= 20 + GetMBarHeight ();
12027 /* get maximum height of window into zoom_rect.bottom -
12029 GetQDGlobalsScreenBits (&bm
);
12030 zoom_rect
= bm
.bounds
;
12031 zoom_rect
.top
+= w_title_height
;
12032 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
12034 zoom_rect
.right
= zoom_rect
.left
12035 + CHAR_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
12037 SetWindowStandardState (w
, &zoom_rect
);
12040 #else /* not TARGET_API_MAC_CARBON */
12041 EraseRect (&(w
->portRect
));
12042 if (zoom_in_or_out
== inZoomOut
)
12044 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
12045 LocalToGlobal (&top_left
);
12047 /* calculate height of window's title bar */
12048 w_title_height
= top_left
.v
- 1
12049 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
12051 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
12052 zoom_rect
= qd
.screenBits
.bounds
;
12053 zoom_rect
.top
+= w_title_height
;
12054 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
12056 zoom_rect
.right
= zoom_rect
.left
12057 + CHAR_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
12059 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
12062 #endif /* not TARGET_API_MAC_CARBON */
12064 ZoomWindow (w
, zoom_in_or_out
, w
== FrontWindow ());
12066 /* retrieve window size and update application values */
12067 #if TARGET_API_MAC_CARBON
12068 GetWindowPortBounds (w
, &port_rect
);
12070 port_rect
= w
->portRect
;
12072 rows
= PIXEL_TO_CHAR_HEIGHT (f
, port_rect
.bottom
- port_rect
.top
);
12073 columns
= PIXEL_TO_CHAR_WIDTH (f
, port_rect
.right
- port_rect
.left
);
12074 x_set_window_size (mwp
->mFP
, 0, columns
, rows
);
12076 SetPort (save_port
);
12079 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
12081 init_mac_drag_n_drop ()
12083 OSErr result
= InstallReceiveHandler (mac_do_receive_drag
, 0L, NULL
);
12087 /* Intialize AppleEvent dispatcher table for the required events. */
12089 init_required_apple_events ()
12094 /* Make sure we have apple events before starting. */
12095 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
12099 if (!(result
& (1 << gestaltAppleEventsPresent
)))
12102 #if TARGET_API_MAC_CARBON
12103 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
12104 NewAEEventHandlerUPP
12105 ((AEEventHandlerProcPtr
) do_ae_open_application
),
12108 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
12109 NewAEEventHandlerProc
12110 ((AEEventHandlerProcPtr
) do_ae_open_application
),
12116 #if TARGET_API_MAC_CARBON
12117 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
12118 NewAEEventHandlerUPP
12119 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
12122 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
12123 NewAEEventHandlerProc
12124 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
12130 #if TARGET_API_MAC_CARBON
12131 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
12132 NewAEEventHandlerUPP
12133 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
12136 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
12137 NewAEEventHandlerProc
12138 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
12144 #if TARGET_API_MAC_CARBON
12145 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
12146 NewAEEventHandlerUPP
12147 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
12150 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
12151 NewAEEventHandlerProc
12152 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
12159 #if USE_CARBON_EVENTS
12162 init_service_handler ()
12164 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
12165 {kEventClassService
, kEventServiceCopy
},
12166 {kEventClassService
, kEventServicePaste
}};
12167 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
12168 3, specs
, NULL
, NULL
);
12172 MAC_TODO: Check to see if this is called by AEProcessDesc...
12175 mac_handle_service_event (EventHandlerCallRef callRef
,
12176 EventRef event
, void *data
)
12178 OSStatus err
= noErr
;
12179 switch (GetEventKind (event
))
12181 case kEventServiceGetTypes
:
12183 CFMutableArrayRef copyTypes
, pasteTypes
;
12185 Boolean selection
= true;
12187 GetEventParameter(event, kEventParamServicePasteTypes,
12188 typeCFMutableArrayRef, NULL,
12189 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
12191 GetEventParameter(event
, kEventParamServiceCopyTypes
,
12192 typeCFMutableArrayRef
, NULL
,
12193 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
12194 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
12196 CFArrayAppendValue (copyTypes
, type
);
12197 //CFArrayAppendValue (pasteTypes, type);
12201 case kEventServiceCopy
:
12203 ScrapRef currentScrap
, specificScrap
;
12205 Size byteCount
= 0;
12207 GetCurrentScrap (¤tScrap
);
12209 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
12212 void *buffer
= xmalloc (byteCount
);
12213 if (buffer
!= NULL
)
12215 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
12216 sizeof (ScrapRef
), NULL
, &specificScrap
);
12218 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
12219 &byteCount
, buffer
);
12221 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
12222 kScrapFlavorMaskNone
, byteCount
, buffer
);
12228 case kEventServicePaste
:
12231 // Get the current location
12233 ScrapRef specificScrap;
12234 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
12235 sizeof(ScrapRef), NULL, &specificScrap);
12236 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
12237 if (err == noErr) {
12238 void * buffer = xmalloc(byteCount);
12239 if (buffer != NULL ) {
12240 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
12241 &byteCount, buffer);
12242 if (err == noErr) {
12243 // Actually place in the buffer
12245 // Get the current "selection" string here
12258 /* Open Application Apple Event */
12259 static pascal OSErr
12260 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
12266 /* Defined in mac.c. */
12268 path_from_vol_dir_name (char *, int, short, long, char *);
12271 /* Called when we receive an AppleEvent with an ID of
12272 "kAEOpenDocuments". This routine gets the direct parameter,
12273 extracts the FSSpecs in it, and puts their names on a list. */
12274 static pascal OSErr
12275 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
12280 DescType actual_type
;
12283 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
12285 goto descriptor_error_exit
;
12287 /* Check to see that we got all of the required parameters from the
12288 event descriptor. For an 'odoc' event this should just be the
12290 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
12291 &actual_type
, (Ptr
) &keyword
,
12292 sizeof (keyword
), &actual_size
);
12293 /* No error means that we found some unused parameters.
12294 errAEDescNotFound means that there are no more parameters. If we
12295 get an error code other than that, flag it. */
12296 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
12298 err
= errAEEventNotHandled
;
12303 /* Got all the parameters we need. Now, go through the direct
12304 object list and parse it up. */
12306 long num_files_to_open
;
12308 err
= AECountItems (&the_desc
, &num_files_to_open
);
12313 /* AE file list is one based so just use that for indexing here. */
12314 for (i
= 1; (err
== noErr
) && (i
<= num_files_to_open
); i
++)
12317 Str255 path_name
, unix_path_name
;
12322 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
12323 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
12324 if (err
!= noErr
) break;
12327 err
= FSpMakeFSRef (&fs
, &fref
);
12328 if (err
!= noErr
) break;
12330 if (FSRefMakePath (&fref
, unix_path_name
, 255) == noErr
)
12332 if (path_from_vol_dir_name (path_name
, 255, fs
.vRefNum
, fs
.parID
,
12334 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
12336 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
12337 drag_and_drop_file_list
);
12343 /* Nuke the coerced file list in any case */
12344 err2
= AEDisposeDesc(&the_desc
);
12346 descriptor_error_exit
:
12347 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12352 static pascal OSErr
12353 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
12354 DragReference theDrag
)
12358 FlavorFlags theFlags
;
12361 ItemReference theItem
;
12364 Size size
= sizeof (HFSFlavor
);
12366 drag_and_drop_file_list
= Qnil
;
12367 GetDragMouse (theDrag
, &mouse
, 0L);
12368 CountDragItems (theDrag
, &items
);
12369 for (index
= 1; index
<= items
; index
++)
12371 /* Only handle file references. */
12372 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
12373 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
12374 if (result
== noErr
)
12381 Str255 unix_path_name
;
12382 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
12384 /* Use Carbon routines, otherwise it converts the file name
12385 to /Macintosh HD/..., which is not correct. */
12386 FSpMakeFSRef (&data
.fileSpec
, &fref
);
12387 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
12389 if (path_from_vol_dir_name (path_name
, 255, data
.fileSpec
.vRefNum
,
12390 data
.fileSpec
.parID
, data
.fileSpec
.name
) &&
12391 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
12393 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
12394 drag_and_drop_file_list
);
12399 /* If there are items in the list, construct an event and post it to
12400 the queue like an interrupt using kbd_buffer_store_event. */
12401 if (!NILP (drag_and_drop_file_list
))
12403 struct input_event event
;
12405 struct frame
*f
= ((mac_output
*) GetWRefCon(window
))->mFP
;
12406 SetPort (GetWindowPort (window
));
12407 GlobalToLocal (&mouse
);
12409 event
.kind
= DRAG_N_DROP_EVENT
;
12411 event
.modifiers
= 0;
12412 event
.timestamp
= TickCount () * (1000 / 60);
12413 XSETINT (event
.x
, mouse
.h
);
12414 XSETINT (event
.y
, mouse
.v
);
12415 XSETFRAME (frame
, f
);
12416 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
12418 /* Post to the interrupt queue */
12419 kbd_buffer_store_event (&event
);
12420 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12422 ProcessSerialNumber psn
;
12423 GetCurrentProcess (&psn
);
12424 SetFrontProcess (&psn
);
12430 /* Print Document Apple Event */
12431 static pascal OSErr
12432 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
12434 return errAEEventNotHandled
;
12438 static pascal OSErr
12439 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
12441 /* FixMe: Do we need an unwind-protect or something here? And what
12442 do we do about unsaved files. Currently just forces quit rather
12443 than doing recursive callback to get user input. */
12445 terminate_flag
= true;
12447 /* Fkill_emacs doesn't return. We have to return. (TI) */
12454 profiler_exit_proc ()
12456 ProfilerDump ("\pEmacs.prof");
12461 /* These few functions implement Emacs as a normal Mac application
12462 (almost): set up the heap and the Toolbox, handle necessary
12463 system events plus a few simple menu events. They also set up
12464 Emacs's access to functions defined in the rest of this file.
12465 Emacs uses function hooks to perform all its terminal I/O. A
12466 complete list of these functions appear in termhooks.h. For what
12467 they do, read the comments there and see also w32term.c and
12468 xterm.c. What's noticeably missing here is the event loop, which
12469 is normally present in most Mac application. After performing the
12470 necessary Mac initializations, main passes off control to
12471 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12472 mac_read_socket (defined further below) to read input. This is
12473 where WaitNextEvent is called to process Mac events. This is also
12474 where check_alarm in sysdep.c is called to simulate alarm signals.
12475 This makes the cursor jump back to its correct position after
12476 briefly jumping to that of the matching parenthesis, print useful
12477 hints and prompts in the minibuffer after the user stops typing for
12480 #if !TARGET_API_MAC_CARBON
12485 #if __profile__ /* is the profiler on? */
12486 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
12491 /* set creator and type for files created by MSL */
12492 _fcreator
= 'EMAx';
12496 do_init_managers ();
12500 do_check_ram_size ();
12502 init_emacs_passwd_dir ();
12506 initialize_applescript ();
12508 init_required_apple_events ();
12514 /* set up argv array from STR# resource */
12515 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
12519 /* free up AppleScript resources on exit */
12520 atexit (terminate_applescript
);
12522 #if __profile__ /* is the profiler on? */
12523 atexit (profiler_exit_proc
);
12526 /* 3rd param "envp" never used in emacs_main */
12527 (void) emacs_main (argc
, argv
, 0);
12530 /* Never reached - real exit in Fkill_emacs */
12535 /* Table for translating Mac keycode to X keysym values. Contributed
12536 by Sudhir Shenoy. */
12537 static unsigned char keycode_to_xkeysym_table
[] = {
12539 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12540 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12541 0, 0, 0, 0, '\x0d', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12542 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12544 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12545 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12546 0, 0, 0, '\xaf' /* kp/ */,
12547 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12549 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12550 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12551 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12552 '\xb9' /* kp9 */, 0, 0, 0,
12554 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12555 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12556 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12557 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12559 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12560 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12561 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12562 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12566 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
12568 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
12569 return *xKeySym
!= 0;
12572 /* Emacs calls this whenever it wants to read an input event from the
12575 XTread_socket (int sd
, struct input_event
*bufp
, int numchars
, int expected
)
12578 #if USE_CARBON_EVENTS
12579 OSStatus rneResult
;
12581 EventMouseButton mouseBtn
;
12585 EventMask event_mask
;
12588 if (interrupt_input_blocked
)
12590 interrupt_input_pending
= 1;
12595 interrupt_input_pending
= 0;
12598 /* So people can tell when we have read the available input. */
12599 input_signal_count
++;
12604 /* Don't poll for events to process (specifically updateEvt) if
12605 window update currently already in progress. A call to redisplay
12606 (in do_window_update) can be preempted by another call to
12607 redisplay, causing blank regions to be left on the screen and the
12608 cursor to be left at strange places. */
12609 if (handling_window_update
)
12615 if (terminate_flag
)
12616 Fkill_emacs (make_number (1));
12618 /* It is necessary to set this (additional) argument slot of an
12619 event to nil because keyboard.c protects incompletely processed
12620 event from being garbage collected by placing them in the
12621 kbd_buffer_gcpro vector. */
12624 event_mask
= everyEvent
;
12625 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
12626 event_mask
-= highLevelEventMask
;
12628 #if USE_CARBON_EVENTS
12629 rneResult
= ReceiveNextEvent (0, NULL
,
12631 ? TicksToEventTime (app_sleep_time
)
12633 kEventRemoveFromQueue
, &eventRef
);
12636 /* Handle new events */
12637 if (!mac_convert_event_ref (eventRef
, &er
))
12638 switch (GetEventClass (eventRef
))
12640 case kEventClassMouse
:
12641 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
12645 WindowPtr window_ptr
= FrontNonFloatingWindow ();
12646 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (window_ptr
);
12647 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
12648 typeSInt32
, NULL
, sizeof (SInt32
),
12650 GetEventParameter(eventRef
, kEventParamMouseLocation
,
12651 typeQDPoint
, NULL
, sizeof (Point
),
12653 bufp
->kind
= MOUSE_WHEEL_EVENT
;
12654 bufp
->code
= delta
;
12655 bufp
->modifiers
= mac_event_to_emacs_modifiers(eventRef
);
12656 SetPort (GetWindowPort (window_ptr
));
12657 GlobalToLocal (&point
);
12658 XSETINT (bufp
->x
, point
.h
);
12659 XSETINT (bufp
->y
, point
.v
);
12660 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
12661 bufp
->timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
12665 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
12669 /* Send the event to the appropriate receiver. */
12670 SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ());
12674 if (WaitNextEvent (event_mask
, &er
, (expected
? app_sleep_time
: 0L), NULL
))
12675 #endif /* USE_CARBON_EVENTS */
12681 WindowPtr window_ptr
= FrontWindow ();
12684 #if USE_CARBON_EVENTS
12685 /* This is needed to send mouse events like aqua window buttons
12686 to the correct handler. */
12687 if (eventNotHandledErr
!= SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ())) {
12691 if (!is_emacs_window(window_ptr
))
12695 if (mouse_tracking_in_progress
== mouse_tracking_scroll_bar
12696 && er
.what
== mouseUp
)
12698 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (window_ptr
);
12699 Point mouse_loc
= er
.where
;
12701 /* Convert to local coordinates of new window. */
12702 #if TARGET_API_MAC_CARBON
12703 SetPort (GetWindowPort (window_ptr
));
12705 SetPort (window_ptr
);
12708 GlobalToLocal (&mouse_loc
);
12710 #if USE_CARBON_EVENTS
12711 bufp
->code
= mac_get_mouse_btn (eventRef
);
12713 bufp
->code
= 0; /* only one mouse button */
12715 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
12716 bufp
->frame_or_window
= tracked_scroll_bar
->window
;
12717 bufp
->part
= scroll_bar_handle
;
12718 #if USE_CARBON_EVENTS
12719 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12721 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12723 bufp
->modifiers
|= up_modifier
;
12724 bufp
->timestamp
= er
.when
* (1000 / 60);
12725 /* ticks to milliseconds */
12727 XSETINT (bufp
->x
, tracked_scroll_bar
->left
+ 2);
12728 XSETINT (bufp
->y
, mouse_loc
.v
- 24);
12729 tracked_scroll_bar
->dragging
= Qnil
;
12730 mouse_tracking_in_progress
= mouse_tracking_none
;
12731 tracked_scroll_bar
= NULL
;
12736 part_code
= FindWindow (er
.where
, &window_ptr
);
12742 struct frame
*f
= ((mac_output
*)
12743 GetWRefCon (FrontWindow ()))->mFP
;
12744 saved_menu_event_location
= er
.where
;
12745 bufp
->kind
= MENU_BAR_ACTIVATE_EVENT
;
12746 XSETFRAME (bufp
->frame_or_window
, f
);
12752 if (window_ptr
!= FrontWindow ())
12753 SelectWindow (window_ptr
);
12756 SInt16 control_part_code
;
12758 struct mac_output
*mwp
= (mac_output
*)
12759 GetWRefCon (window_ptr
);
12760 Point mouse_loc
= er
.where
;
12762 /* convert to local coordinates of new window */
12763 #if TARGET_API_MAC_CARBON
12764 SetPort (GetWindowPort (window_ptr
));
12766 SetPort (window_ptr
);
12769 GlobalToLocal (&mouse_loc
);
12770 #if TARGET_API_MAC_CARBON
12771 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
12772 &control_part_code
);
12774 control_part_code
= FindControl (mouse_loc
, window_ptr
, &ch
);
12777 #if USE_CARBON_EVENTS
12778 bufp
->code
= mac_get_mouse_btn (eventRef
);
12780 bufp
->code
= 0; /* only one mouse button */
12782 XSETINT (bufp
->x
, mouse_loc
.h
);
12783 XSETINT (bufp
->y
, mouse_loc
.v
);
12784 bufp
->timestamp
= er
.when
* (1000 / 60);
12785 /* ticks to milliseconds */
12787 #if TARGET_API_MAC_CARBON
12790 if (control_part_code
!= 0)
12793 struct scroll_bar
*bar
= (struct scroll_bar
*)
12794 GetControlReference (ch
);
12795 x_scroll_bar_handle_click (bar
, control_part_code
, &er
,
12797 if (er
.what
== mouseDown
12798 && control_part_code
== kControlIndicatorPart
)
12800 mouse_tracking_in_progress
12801 = mouse_tracking_scroll_bar
;
12802 tracked_scroll_bar
= bar
;
12806 mouse_tracking_in_progress
= mouse_tracking_none
;
12807 tracked_scroll_bar
= NULL
;
12812 bufp
->kind
= MOUSE_CLICK_EVENT
;
12813 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
12814 if (er
.what
== mouseDown
)
12815 mouse_tracking_in_progress
12816 = mouse_tracking_mouse_movement
;
12818 mouse_tracking_in_progress
= mouse_tracking_none
;
12821 #if USE_CARBON_EVENTS
12822 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
12824 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
12830 bufp
->modifiers
|= down_modifier
;
12833 bufp
->modifiers
|= up_modifier
;
12842 #if TARGET_API_MAC_CARBON
12846 GetQDGlobalsScreenBits (&bm
);
12847 DragWindow (window_ptr
, er
.where
, &bm
.bounds
);
12849 #else /* not TARGET_API_MAC_CARBON */
12850 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
12851 #endif /* not TARGET_API_MAC_CARBON */
12855 if (TrackGoAway (window_ptr
, er
.where
))
12857 bufp
->kind
= DELETE_WINDOW_EVENT
;
12858 XSETFRAME (bufp
->frame_or_window
,
12859 ((mac_output
*) GetWRefCon (window_ptr
))->mFP
);
12864 /* window resize handling added --ben */
12866 do_grow_window(window_ptr
, &er
);
12869 /* window zoom handling added --ben */
12872 if (TrackBox (window_ptr
, er
.where
, part_code
))
12873 do_zoom_window (window_ptr
, part_code
);
12885 #if USE_CARBON_EVENTS
12886 if (eventNotHandledErr
== SendEventToEventTarget (eventRef
, GetEventDispatcherTarget ()))
12894 int keycode
= (er
.message
& keyCodeMask
) >> 8;
12897 #if USE_CARBON_EVENTS
12898 /* When using Carbon Events, we need to pass raw keyboard events
12899 to the TSM ourselves. If TSM handles it, it will pass back
12900 noErr, otherwise it will pass back "eventNotHandledErr" and
12901 we can process it normally. */
12902 if ((!NILP (Vmac_pass_command_to_system
)
12903 || !(er
.modifiers
& cmdKey
))
12904 && (!NILP (Vmac_pass_control_to_system
)
12905 || !(er
.modifiers
& controlKey
)))
12908 err
= SendEventToEventTarget (eventRef
,
12909 GetEventDispatcherTarget ());
12910 if (err
!= eventNotHandledErr
)
12915 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12924 if (keycode
== 0x33) /* delete key (charCode translated to 0x8) */
12927 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
12929 else if (keycode_to_xkeysym (keycode
, &xkeysym
))
12931 bufp
->code
= 0xff00 | xkeysym
;
12932 bufp
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
12936 if (er
.modifiers
& (controlKey
|
12937 (NILP (Vmac_command_key_is_meta
) ? optionKey
12940 /* This code comes from Keyboard Resource, Appendix
12941 C of IM - Text. This is necessary since shift is
12942 ignored in KCHR table translation when option or
12943 command is pressed. It also does not translate
12944 correctly control-shift chars like C-% so mask off
12946 int new_modifiers
= er
.modifiers
& 0xe600;
12947 /* mask off option and command */
12948 int new_keycode
= keycode
| new_modifiers
;
12949 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
12950 unsigned long some_state
= 0;
12951 bufp
->code
= KeyTranslate (kchr_ptr
, new_keycode
,
12952 &some_state
) & 0xff;
12955 bufp
->code
= er
.message
& charCodeMask
;
12956 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
12960 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12961 convert non-ASCII characters typed at the Mac keyboard
12962 (presumed to be in the Mac Roman encoding) to iso-latin-1
12963 encoding before they are passed to Emacs. This enables the
12964 Mac keyboard to be used to enter non-ASCII iso-latin-1
12965 characters directly. */
12966 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
12967 && bufp
->kind
== ASCII_KEYSTROKE_EVENT
&& bufp
->code
>= 128)
12969 static TECObjectRef converter
= NULL
;
12970 OSStatus the_err
= noErr
;
12971 OSStatus convert_status
= noErr
;
12973 if (converter
== NULL
)
12975 the_err
= TECCreateConverter (&converter
,
12976 kTextEncodingMacRoman
,
12977 mac_keyboard_text_encoding
);
12978 current_mac_keyboard_text_encoding
12979 = mac_keyboard_text_encoding
;
12981 else if (mac_keyboard_text_encoding
12982 != current_mac_keyboard_text_encoding
)
12984 /* Free the converter for the current encoding before
12985 creating a new one. */
12986 TECDisposeConverter (converter
);
12987 the_err
= TECCreateConverter (&converter
,
12988 kTextEncodingMacRoman
,
12989 mac_keyboard_text_encoding
);
12990 current_mac_keyboard_text_encoding
12991 = mac_keyboard_text_encoding
;
12994 if (the_err
== noErr
)
12996 unsigned char ch
= bufp
->code
;
12997 ByteCount actual_input_length
, actual_output_length
;
12998 unsigned char outch
;
13000 convert_status
= TECConvertText (converter
, &ch
, 1,
13001 &actual_input_length
,
13003 &actual_output_length
);
13004 if (convert_status
== noErr
13005 && actual_input_length
== 1
13006 && actual_output_length
== 1)
13007 bufp
->code
= outch
;
13011 #if USE_CARBON_EVENTS
13012 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
13014 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
13019 = (mac_output
*) GetWRefCon (FrontNonFloatingWindow ());
13020 XSETFRAME (bufp
->frame_or_window
, mwp
->mFP
);
13023 bufp
->timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
13028 case kHighLevelEvent
:
13029 drag_and_drop_file_list
= Qnil
;
13031 AEProcessAppleEvent(&er
);
13033 /* Build a DRAG_N_DROP_EVENT type event as is done in
13034 constuct_drag_n_drop in w32term.c. */
13035 if (!NILP (drag_and_drop_file_list
))
13037 struct frame
*f
= NULL
;
13041 wp
= FrontNonFloatingWindow ();
13045 struct frame
*f
= XFRAME (XCAR (Vframe_list
));
13046 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
13047 wp
= FrontNonFloatingWindow ();
13050 if (wp
&& is_emacs_window(wp
))
13051 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
13053 bufp
->kind
= DRAG_N_DROP_EVENT
;
13055 bufp
->timestamp
= er
.when
* (1000 / 60);
13056 /* ticks to milliseconds */
13057 #if USE_CARBON_EVENTS
13058 bufp
->modifiers
= mac_event_to_emacs_modifiers (eventRef
);
13060 bufp
->modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
13063 XSETINT (bufp
->x
, 0);
13064 XSETINT (bufp
->y
, 0);
13066 XSETFRAME (frame
, f
);
13067 bufp
->frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
13069 /* Regardless of whether Emacs was suspended or in the
13070 foreground, ask it to redraw its entire screen.
13071 Otherwise parts of the screen can be left in an
13072 inconsistent state. */
13074 #if TARGET_API_MAC_CARBON
13078 GetWindowPortBounds (wp
, &r
);
13079 InvalWindowRect (wp
, &r
);
13081 #else /* not TARGET_API_MAC_CARBON */
13082 InvalRect (&(wp
->portRect
));
13083 #endif /* not TARGET_API_MAC_CARBON */
13090 #if USE_CARBON_EVENTS
13091 ReleaseEvent (eventRef
);
13095 /* If the focus was just given to an autoraising frame,
13097 /* ??? This ought to be able to handle more than one such frame. */
13098 if (pending_autoraise_frame
)
13100 x_raise_frame (pending_autoraise_frame
);
13101 pending_autoraise_frame
= 0;
13104 #if !TARGET_API_MAC_CARBON
13105 check_alarm (); /* simulate the handling of a SIGALRM */
13109 static Point old_mouse_pos
= { -1, -1 };
13111 if (app_is_suspended
)
13113 old_mouse_pos
.h
= -1;
13114 old_mouse_pos
.v
= -1;
13122 struct scroll_bar
*sb
;
13124 wp
= FrontWindow ();
13125 if (is_emacs_window (wp
))
13127 f
= ((mac_output
*) GetWRefCon (wp
))->mFP
;
13129 #if TARGET_API_MAC_CARBON
13130 SetPort (GetWindowPort (wp
));
13135 GetMouse (&mouse_pos
);
13137 if (!EqualPt (mouse_pos
, old_mouse_pos
))
13139 if (mouse_tracking_in_progress
== mouse_tracking_scroll_bar
13140 && tracked_scroll_bar
)
13141 x_scroll_bar_note_movement (tracked_scroll_bar
,
13143 - XINT (tracked_scroll_bar
->top
),
13144 TickCount() * (1000 / 60));
13146 note_mouse_movement (f
, &mouse_pos
);
13148 old_mouse_pos
= mouse_pos
;
13160 /* Need to override CodeWarrior's input function so no conversion is
13161 done on newlines Otherwise compiled functions in .elc files will be
13162 read incorrectly. Defined in ...:MSL C:MSL
13163 Common:Source:buffer_io.c. */
13166 __convert_to_newlines (unsigned char * p
, size_t * n
)
13168 #pragma unused(p,n)
13172 __convert_from_newlines (unsigned char * p
, size_t * n
)
13174 #pragma unused(p,n)
13179 /* Initialize the struct pointed to by MW to represent a new COLS x
13180 ROWS Macintosh window, using font with name FONTNAME and size
13183 NewMacWindow (FRAME_PTR fp
)
13186 #if TARGET_API_MAC_CARBON
13187 static int making_terminal_window
= 0;
13189 static int making_terminal_window
= 1;
13192 mwp
= fp
->output_data
.mac
;
13194 if (making_terminal_window
)
13196 if (!(mwp
->mWP
= GetNewCWindow (TERM_WINDOW_RESOURCE
, NULL
,
13199 making_terminal_window
= 0;
13202 if (!(mwp
->mWP
= GetNewCWindow (WINDOW_RESOURCE
, NULL
, (WindowPtr
) -1)))
13205 SetWRefCon (mwp
->mWP
, (long) mwp
);
13206 /* so that update events can find this mac_output struct */
13207 mwp
->mFP
= fp
; /* point back to emacs frame */
13209 #if TARGET_API_MAC_CARBON
13210 SetPort (GetWindowPort (mwp
->mWP
));
13212 SetPort (mwp
->mWP
);
13217 SizeWindow (mwp
->mWP
, mwp
->pixel_width
, mwp
->pixel_height
, false);
13218 ShowWindow (mwp
->mWP
);
13224 make_mac_frame (struct frame
*f
)
13226 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
13227 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
13229 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
13233 f
->output_data
.mac
->cursor_pixel
= 0;
13234 f
->output_data
.mac
->border_pixel
= 0x00ff00;
13235 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
13236 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
13238 f
->output_data
.mac
->fontset
= -1;
13239 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
13240 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
13241 f
->output_data
.mac
->left_pos
= 4;
13242 f
->output_data
.mac
->top_pos
= 4;
13243 f
->output_data
.mac
->border_width
= 0;
13244 f
->output_data
.mac
->explicit_parent
= 0;
13246 f
->output_data
.mac
->internal_border_width
= 0;
13248 f
->output_method
= output_mac
;
13258 make_mac_terminal_frame (struct frame
*f
)
13262 XSETFRAME (frame
, f
);
13264 f
->output_method
= output_mac
;
13265 f
->output_data
.mac
= (struct mac_output
*)
13266 xmalloc (sizeof (struct mac_output
));
13267 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
13268 f
->output_data
.mac
->fontset
= -1;
13269 f
->output_data
.mac
->scroll_bar_foreground_pixel
= -1;
13270 f
->output_data
.mac
->scroll_bar_background_pixel
= -1;
13272 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
13277 make_mac_frame (f
);
13281 /* Need to be initialized for unshow_buffer in window.c. */
13282 selected_window
= f
->selected_window
;
13284 Fmodify_frame_parameters (frame
,
13285 Fcons (Fcons (Qfont
,
13286 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
13287 Fmodify_frame_parameters (frame
,
13288 Fcons (Fcons (Qforeground_color
,
13289 build_string ("black")), Qnil
));
13290 Fmodify_frame_parameters (frame
,
13291 Fcons (Fcons (Qbackground_color
,
13292 build_string ("white")), Qnil
));
13296 /***********************************************************************
13298 ***********************************************************************/
13300 #ifdef USE_X_TOOLKIT
13301 static XrmOptionDescRec emacs_options
[] = {
13302 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
13303 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
13305 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13306 XrmoptionSepArg
, NULL
},
13307 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
13309 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13310 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13311 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13312 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
13313 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
13314 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
13315 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
13317 #endif /* USE_X_TOOLKIT */
13319 #ifdef MULTI_KBOARD
13320 /* Test whether two display-name strings agree up to the dot that separates
13321 the screen number from the server number. */
13323 same_x_server (name1
, name2
)
13324 char *name1
, *name2
;
13326 int seen_colon
= 0;
13327 unsigned char *system_name
= SDATA (Vsystem_name
);
13328 int system_name_length
= strlen (system_name
);
13329 int length_until_period
= 0;
13331 while (system_name
[length_until_period
] != 0
13332 && system_name
[length_until_period
] != '.')
13333 length_until_period
++;
13335 /* Treat `unix' like an empty host name. */
13336 if (! strncmp (name1
, "unix:", 5))
13338 if (! strncmp (name2
, "unix:", 5))
13340 /* Treat this host's name like an empty host name. */
13341 if (! strncmp (name1
, system_name
, system_name_length
)
13342 && name1
[system_name_length
] == ':')
13343 name1
+= system_name_length
;
13344 if (! strncmp (name2
, system_name
, system_name_length
)
13345 && name2
[system_name_length
] == ':')
13346 name2
+= system_name_length
;
13347 /* Treat this host's domainless name like an empty host name. */
13348 if (! strncmp (name1
, system_name
, length_until_period
)
13349 && name1
[length_until_period
] == ':')
13350 name1
+= length_until_period
;
13351 if (! strncmp (name2
, system_name
, length_until_period
)
13352 && name2
[length_until_period
] == ':')
13353 name2
+= length_until_period
;
13355 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
13359 if (seen_colon
&& *name1
== '.')
13363 && (*name1
== '.' || *name1
== '\0')
13364 && (*name2
== '.' || *name2
== '\0'));
13368 int mac_initialized
= 0;
13371 mac_initialize_display_info ()
13373 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
13374 GDHandle main_device_handle
;
13376 bzero (dpyinfo
, sizeof (*dpyinfo
));
13378 /* Put it on x_display_name_list. */
13379 x_display_name_list
= Fcons (Fcons (build_string ("Mac"), Qnil
),
13380 x_display_name_list
);
13381 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
13384 dpyinfo
->mac_id_name
13385 = (char *) xmalloc (SCHARS (Vinvocation_name
)
13386 + SCHARS (Vsystem_name
)
13388 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
13389 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
13391 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
13392 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
13395 main_device_handle
= LMGetMainDevice();
13397 dpyinfo
->reference_count
= 0;
13398 dpyinfo
->resx
= 75.0;
13399 dpyinfo
->resy
= 75.0;
13400 dpyinfo
->n_planes
= 1;
13401 dpyinfo
->n_cbits
= 16;
13402 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
13403 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
13404 dpyinfo
->grabbed
= 0;
13405 dpyinfo
->root_window
= NULL
;
13407 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
13408 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
13409 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
13410 dpyinfo
->mouse_face_window
= Qnil
;
13413 struct mac_display_info
*
13414 mac_term_init (display_name
, xrm_option
, resource_name
)
13415 Lisp_Object display_name
;
13417 char *resource_name
;
13419 struct mac_display_info
*dpyinfo
;
13420 GDHandle main_device_handle
;
13422 if (!mac_initialized
)
13425 mac_initialized
= 1;
13428 mac_initialize_display_info (display_name
);
13430 dpyinfo
= &one_mac_display_info
;
13432 main_device_handle
= LMGetMainDevice();
13434 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
13435 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
13444 extern int inhibit_window_system
;
13445 extern int noninteractive
;
13446 CFBundleRef appsBundle
;
13449 /* No need to test if already -nw*/
13450 if (inhibit_window_system
|| noninteractive
)
13453 appsBundle
= CFBundleGetMainBundle();
13454 if (appsBundle
!= NULL
)
13456 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
13457 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
13458 /* We found the bundle identifier, now we know we are valid. */
13465 /* MAC_TODO: Have this start the bundled executable */
13467 /* For now, prevent the fatal error by bringing it up in the terminal */
13468 inhibit_window_system
= 1;
13472 MakeMeTheFrontProcess ()
13474 ProcessSerialNumber psn
;
13477 err
= GetCurrentProcess (&psn
);
13479 (void) SetFrontProcess (&psn
);
13482 /***** Code to handle C-g testing *****/
13484 /* Contains the Mac modifier formed from quit_char */
13485 static mac_quit_char_modifiers
= 0;
13486 static mac_quit_char_keycode
;
13487 extern int quit_char
;
13490 mac_determine_quit_char_modifiers()
13492 /* Todo: Determine modifiers from quit_char. */
13493 UInt32 qc_modifiers
= ctrl_modifier
;
13495 /* Map modifiers */
13496 mac_quit_char_modifiers
= 0;
13497 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
13498 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
13499 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
13500 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
13504 init_quit_char_handler ()
13506 /* TODO: Let this support keys other the 'g' */
13507 mac_quit_char_keycode
= 5;
13508 /* Look at <architecture/adb_kb_map.h> for details */
13509 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
13511 mac_determine_quit_char_modifiers();
13515 quit_char_comp (EventRef inEvent
, void *inCompData
)
13517 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
13519 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
13523 UInt32 keyModifiers
;
13524 GetEventParameter(inEvent
, kEventParamKeyCode
,
13525 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
13526 if (keyCode
!= mac_quit_char_keycode
)
13528 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
13529 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
13530 if (keyModifiers
!= mac_quit_char_modifiers
)
13537 mac_check_for_quit_char()
13540 /* If windows are not initialized, return immediately (keep it bouncin')*/
13541 if (!mac_quit_char_modifiers
)
13544 /* Redetermine modifiers because they are based on lisp variables */
13545 mac_determine_quit_char_modifiers();
13547 /* Fill the queue with events */
13548 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
13549 event
= FindSpecificEventInQueue (GetMainEventQueue(), quit_char_comp
, NULL
);
13552 struct input_event e
;
13553 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (FrontNonFloatingWindow ());
13554 /* Use an input_event to emulate what the interrupt handler does. */
13555 e
.kind
= ASCII_KEYSTROKE_EVENT
;
13556 e
.code
= quit_char
;
13558 e
.modifiers
= NULL
;
13559 e
.timestamp
= EventTimeToTicks(GetEventTime(event
))*(1000/60);
13560 XSETFRAME(e
.frame_or_window
, mwp
->mFP
);
13561 /* Remove event from queue to prevent looping. */
13562 RemoveEventFromQueue(GetMainEventQueue(), event
);
13563 ReleaseEvent(event
);
13564 kbd_buffer_store_event(&e
);
13568 #endif /* MAC_OSX */
13570 /* Set up use of X before we make the first connection. */
13572 static struct redisplay_interface x_redisplay_interface
=
13577 x_clear_end_of_line
,
13579 x_after_update_window_line
,
13580 x_update_window_begin
,
13581 x_update_window_end
,
13584 x_clear_mouse_face
,
13585 x_get_glyph_overhangs
,
13586 x_fix_overlapping_area
13592 rif
= &x_redisplay_interface
;
13594 clear_frame_hook
= x_clear_frame
;
13595 ins_del_lines_hook
= x_ins_del_lines
;
13596 delete_glyphs_hook
= x_delete_glyphs
;
13597 ring_bell_hook
= XTring_bell
;
13598 reset_terminal_modes_hook
= XTreset_terminal_modes
;
13599 set_terminal_modes_hook
= XTset_terminal_modes
;
13600 update_begin_hook
= x_update_begin
;
13601 update_end_hook
= x_update_end
;
13602 set_terminal_window_hook
= XTset_terminal_window
;
13603 read_socket_hook
= XTread_socket
;
13604 frame_up_to_date_hook
= XTframe_up_to_date
;
13605 mouse_position_hook
= XTmouse_position
;
13606 frame_rehighlight_hook
= XTframe_rehighlight
;
13607 frame_raise_lower_hook
= XTframe_raise_lower
;
13609 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13610 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13611 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13612 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13614 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
13616 scroll_region_ok
= 1; /* we'll scroll partial frames */
13617 char_ins_del_ok
= 1;
13618 line_ins_del_ok
= 1; /* we'll just blt 'em */
13619 fast_clear_end_of_line
= 1; /* X does this well */
13620 memory_below_frame
= 0; /* we don't remember what scrolls
13625 last_tool_bar_item
= -1;
13626 any_help_event_p
= 0;
13628 /* Try to use interrupt input; if we can't, then start polling. */
13629 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
13631 #ifdef USE_X_TOOLKIT
13632 XtToolkitInitialize ();
13633 Xt_app_con
= XtCreateApplicationContext ();
13634 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
13636 /* Install an asynchronous timer that processes Xt timeout events
13637 every 0.1s. This is necessary because some widget sets use
13638 timeouts internally, for example the LessTif menu bar, or the
13639 Xaw3d scroll bar. When Xt timouts aren't processed, these
13640 widgets don't behave normally. */
13642 EMACS_TIME interval
;
13643 EMACS_SET_SECS_USECS (interval
, 0, 100000);
13644 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
13648 #if USE_TOOLKIT_SCROLL_BARS
13649 xaw3d_arrow_scroll
= False
;
13650 xaw3d_pick_top
= True
;
13654 /* Note that there is no real way portable across R3/R4 to get the
13655 original error handler. */
13656 XSetErrorHandler (x_error_handler
);
13657 XSetIOErrorHandler (x_io_error_quitter
);
13659 /* Disable Window Change signals; they are handled by X events. */
13661 signal (SIGWINCH
, SIG_DFL
);
13662 #endif /* ! defined (SIGWINCH) */
13664 signal (SIGPIPE
, x_connection_signal
);
13667 mac_initialize_display_info ();
13669 #if TARGET_API_MAC_CARBON
13670 init_required_apple_events ();
13672 init_mac_drag_n_drop ();
13674 #if USE_CARBON_EVENTS
13675 init_service_handler ();
13677 init_quit_char_handler ();
13680 DisableMenuCommand (NULL
, kHICommandQuit
);
13682 if (!inhibit_window_system
)
13683 MakeMeTheFrontProcess ();
13692 staticpro (&x_error_message_string
);
13693 x_error_message_string
= Qnil
;
13696 Fprovide (intern ("mac-carbon"), Qnil
);
13698 staticpro (&x_display_name_list
);
13699 x_display_name_list
= Qnil
;
13701 staticpro (&last_mouse_scroll_bar
);
13702 last_mouse_scroll_bar
= Qnil
;
13704 staticpro (&Qvendor_specific_keysyms
);
13705 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
13707 staticpro (&last_mouse_press_frame
);
13708 last_mouse_press_frame
= Qnil
;
13710 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
13711 staticpro (&Qmac_ready_for_drag_n_drop
);
13714 staticpro (&help_echo
);
13715 help_echo_object
= Qnil
;
13716 staticpro (&help_echo_object
);
13717 help_echo_window
= Qnil
;
13718 staticpro (&help_echo_window
);
13719 previous_help_echo
= Qnil
;
13720 staticpro (&previous_help_echo
);
13721 help_echo_pos
= -1;
13723 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
13724 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
13725 x_autoselect_window_p
= 0;
13727 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
13728 doc
: /* *Non-nil means draw block cursor as wide as the glyph under it.
13729 For example, if a block cursor is over a tab, it will be drawn as
13730 wide as that tab on the display. */);
13731 x_stretch_cursor_p
= 0;
13733 #if 0 /* TODO: Setting underline position from font properties. */
13734 DEFVAR_BOOL ("x-use-underline-position-properties",
13735 &x_use_underline_position_properties
,
13736 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13737 nil means ignore them. If you encounter fonts with bogus
13738 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13739 to 4.1, set this to nil. */);
13740 x_use_underline_position_properties
= 1;
13743 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
13744 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
13745 Vx_toolkit_scroll_bars
= Qt
;
13747 staticpro (&last_mouse_motion_frame
);
13748 last_mouse_motion_frame
= Qnil
;
13750 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
13751 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
13752 Otherwise the option key is used. */);
13753 Vmac_command_key_is_meta
= Qt
;
13755 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
13756 doc
: /* Non-nil means that the control and meta keys are reversed. This is
13757 useful for non-standard keyboard layouts. */);
13758 Vmac_reverse_ctrl_meta
= Qnil
;
13760 #if USE_CARBON_EVENTS
13761 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
13762 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
13763 the right click will be mouse-3.
13764 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13765 Vmac_wheel_button_is_mouse_2
= Qt
;
13767 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
13768 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
13769 Toolbox for processing before Emacs sees it. */);
13770 Vmac_pass_command_to_system
= Qt
;
13772 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
13773 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
13774 Toolbox for processing before Emacs sees it. */);
13775 Vmac_pass_control_to_system
= Qt
;
13778 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
13779 doc
: /* One of the Text Encoding Base constant values defined in the
13780 Basic Text Constants section of Inside Macintosh - Text Encoding
13781 Conversion Manager. Its value determines the encoding characters
13782 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13783 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13784 its default value, no conversion takes place. If it is set to
13785 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13786 characters typed on Mac keyboard are first converted into the
13787 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13788 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13789 command, this enables the Mac keyboard to be used to enter non-ASCII
13790 characters directly. */);
13791 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;