(defgroup lisp-shadow): New group name. Previous group name shadow is
[emacs.git] / src / macterm.c
blob2646b28618dd88c7949f6b7e6df7fbd7b1ba784d
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)
9 any later version.
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). */
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
31 #include "macterm.h"
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
37 #ifdef MAC_OSX
38 #undef mktime
39 #undef DEBUG
40 #undef free
41 #undef malloc
42 #undef realloc
43 /* Macros max and min defined in lisp.h conflict with those in
44 precompiled header Carbon.h. */
45 #undef max
46 #undef min
47 #undef init_process
48 #include <Carbon/Carbon.h>
49 #undef free
50 #define free unexec_free
51 #undef malloc
52 #define malloc unexec_malloc
53 #undef realloc
54 #define realloc unexec_realloc
55 #undef min
56 #define min(a, b) ((a) < (b) ? (a) : (b))
57 #undef max
58 #define max(a, b) ((a) > (b) ? (a) : (b))
59 #undef init_process
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
63 used instead. */
64 #define USE_CARBON_EVENTS 1
65 #else /* not MAC_OSX */
66 #include <Quickdraw.h>
67 #include <ToolUtils.h>
68 #include <Sound.h>
69 #include <Events.h>
70 #include <Script.h>
71 #include <Resources.h>
72 #include <Fonts.h>
73 #include <TextUtils.h>
74 #include <LowMem.h>
75 #include <Controls.h>
76 #if defined (__MRC__) || (__MSL__ >= 0x6000)
77 #include <ControlDefinitions.h>
78 #endif
79 #include <Gestalt.h>
81 #if __profile__
82 #include <profiler.h>
83 #endif
84 #endif /* not MAC_OSX */
86 #include "systty.h"
87 #include "systime.h"
88 #include "atimer.h"
89 #include "keymap.h"
91 #include <ctype.h>
92 #include <errno.h>
93 #include <setjmp.h>
94 #include <sys/stat.h>
96 #include "keyboard.h"
97 #include "frame.h"
98 #include "dispextern.h"
99 #include "fontset.h"
100 #include "termhooks.h"
101 #include "termopts.h"
102 #include "termchar.h"
103 #include "gnu.h"
104 #include "disptab.h"
105 #include "buffer.h"
106 #include "window.h"
107 #include "intervals.h"
108 #include "composite.h"
109 #include "coding.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) \
119 : controlKey)
120 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
123 /* Fringe bitmaps. */
125 enum fringe_bitmap_type
127 NO_FRINGE_BITMAP,
128 LEFT_TRUNCATION_BITMAP,
129 RIGHT_TRUNCATION_BITMAP,
130 OVERLAY_ARROW_BITMAP,
131 CONTINUED_LINE_BITMAP,
132 CONTINUATION_LINE_BITMAP,
133 ZV_LINE_BITMAP
136 /* Bitmap drawn to indicate lines not displaying text if
137 `indicate-empty-lines' is non-nil. */
139 #define zv_width 8
140 #define zv_height 72
141 #define zv_period 3
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: `<-'. */
154 #define left_width 8
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. */
182 #if 0
183 /* A bomb. */
184 #define ov_width 8
185 #define ov_height 8
186 static unsigned char ov_bits[] = {
187 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
188 #else
189 /* A triangular arrow. */
190 #define ov_width 8
191 #define ov_height 8
192 static unsigned char ov_bits[] = {
193 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
194 #endif
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
216 start. */
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
235 use. */
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;
272 /* Mouse movement.
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
290 is off. */
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
302 an ordinary motion.
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
306 event. */
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 {
320 mouse_tracking_none,
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
330 events. */
332 #ifdef __STDC__
333 static int volatile input_signal_count;
334 #else
335 static int input_signal_count;
336 #endif
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;
355 extern int errno;
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;
363 #if 0
364 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
365 #endif
367 extern Lisp_Object x_icon_type P_ ((struct frame *));
369 extern int inhibit_window_system;
371 #if __MRC__
372 QDGlobals qd; /* QuickDraw global information structure. */
373 #endif
376 /* Enumeration for overriding/changing the face to use for drawing
377 glyphs in x_draw_glyphs. */
379 enum draw_glyphs_face
381 DRAW_NORMAL_TEXT,
382 DRAW_INVERSE_VIDEO,
383 DRAW_CURSOR,
384 DRAW_MOUSE_FACE,
385 DRAW_IMAGE_RAISED,
386 DRAW_IMAGE_SUNKEN
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 *,
423 struct glyph_row *,
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 *,
452 Rect *));
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 *,
462 GC, int));
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 *,
466 enum glyph_row_area,
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
495 dumpglyphs. */
497 typedef struct {
498 unsigned char byte1;
499 unsigned char byte2;
500 } XChar2b;
502 static void
503 XFreePixmap (display, pixmap)
504 Display *display;
505 Pixmap pixmap;
507 PixMap *p = (PixMap *) pixmap;
509 xfree (p->baseAddr);
510 xfree (p);
514 /* Set foreground color for subsequent QuickDraw commands. Assume
515 graphic port has already been set. */
517 static void
518 mac_set_forecolor (unsigned long color)
520 RGBColor fg_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. */
533 static void
534 mac_set_backcolor (unsigned long color)
536 RGBColor bg_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. */
548 static void
549 mac_set_colors (GC gc)
551 mac_set_forecolor (gc->foreground);
552 mac_set_backcolor (gc->background);
555 /* Mac version of XDrawLine. */
557 static void
558 XDrawLine (display, w, gc, x1, y1, x2, y2)
559 Display *display;
560 WindowPtr w;
561 GC gc;
562 int x1, y1, x2, y2;
564 #if TARGET_API_MAC_CARBON
565 SetPort (GetWindowPort (w));
566 #else
567 SetPort (w);
568 #endif
570 mac_set_colors (gc);
572 MoveTo (x1, y1);
573 LineTo (x2, y2);
576 /* Mac version of XClearArea. */
578 void
579 XClearArea (display, w, x, y, width, height, exposures)
580 Display *display;
581 WindowPtr w;
582 int x, y;
583 unsigned int width, height;
584 int exposures;
586 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
587 Rect r;
588 XGCValues xgc;
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));
595 #else
596 SetPort (w);
597 #endif
599 mac_set_colors (&xgc);
600 SetRect (&r, x, y, x + width, y + height);
602 EraseRect (&r);
605 /* Mac version of XClearWindow. */
607 static void
608 XClearWindow (display, w)
609 Display *display;
610 WindowPtr w;
612 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
613 XGCValues xgc;
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));
620 #else
621 SetPort (w);
622 #endif
624 mac_set_colors (&xgc);
626 #if TARGET_API_MAC_CARBON
628 Rect r;
630 GetWindowPortBounds (w, &r);
631 EraseRect (&r);
633 #else /* not TARGET_API_MAC_CARBON */
634 EraseRect (&(w->portRect));
635 #endif /* not TARGET_API_MAC_CARBON */
639 /* Mac replacement for XCopyArea. */
641 static void
642 mac_draw_bitmap (display, w, gc, x, y, bitmap)
643 Display *display;
644 WindowPtr w;
645 GC gc;
646 int x, y;
647 BitMap *bitmap;
649 Rect r;
651 #if TARGET_API_MAC_CARBON
652 SetPort (GetWindowPort (w));
653 #else
654 SetPort (w);
655 #endif
657 mac_set_colors (gc);
658 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
660 #if TARGET_API_MAC_CARBON
662 PixMapHandle pmh;
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. */
677 static void
678 mac_set_clip_rectangle (display, w, r)
679 Display *display;
680 WindowPtr w;
681 Rect *r;
683 #if TARGET_API_MAC_CARBON
684 SetPort (GetWindowPort (w));
685 #else
686 SetPort (w);
687 #endif
689 ClipRect (r);
693 /* Mac replacement for XSetClipMask. */
695 static void
696 mac_reset_clipping (display, w)
697 Display *display;
698 WindowPtr w;
700 Rect r;
702 #if TARGET_API_MAC_CARBON
703 SetPort (GetWindowPort (w));
704 #else
705 SetPort (w);
706 #endif
708 SetRect (&r, -32767, -32767, 32767, 32767);
709 ClipRect (&r);
713 /* Mac replacement for XCreateBitmapFromBitmapData. */
715 static void
716 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
717 BitMap *bitmap;
718 char *bits;
719 int 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)
726 abort ();
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);
738 static void
739 mac_free_bitmap (bitmap)
740 BitMap *bitmap;
742 xfree (bitmap->baseAddr);
745 /* Mac replacement for XFillRectangle. */
747 static void
748 XFillRectangle (display, w, gc, x, y, width, height)
749 Display *display;
750 WindowPtr w;
751 GC gc;
752 int x, y;
753 unsigned int width, height;
755 Rect r;
757 #if TARGET_API_MAC_CARBON
758 SetPort (GetWindowPort (w));
759 #else
760 SetPort (w);
761 #endif
763 mac_set_colors (gc);
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. */
772 static void
773 mac_draw_rectangle (display, w, gc, x, y, width, height)
774 Display *display;
775 WindowPtr w;
776 GC gc;
777 int x, y;
778 unsigned int width, height;
780 Rect r;
782 #if TARGET_API_MAC_CARBON
783 SetPort (GetWindowPort (w));
784 #else
785 SetPort (w);
786 #endif
788 mac_set_colors (gc);
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. */
797 static void
798 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
799 Display *display;
800 Pixmap p;
801 GC gc;
802 int x, y;
803 unsigned int width, height;
805 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
806 Rect r;
808 #if TARGET_API_MAC_CARBON
809 SetPort (GetWindowPort (w));
810 #else
811 SetPort (w);
812 #endif
814 mac_set_colors (gc);
815 SetRect (&r, x, y, x + width, y + height);
817 FrameRect (&r); /* using foreground color of gc */
818 #endif /* 0 */
822 static void
823 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
824 bytes_per_char)
825 Display *display;
826 WindowPtr w;
827 GC gc;
828 int x, y;
829 char *buf;
830 int nchars, mode, bytes_per_char;
832 #if TARGET_API_MAC_CARBON
833 SetPort (GetWindowPort (w));
834 #else
835 SetPort (w);
836 #endif
838 mac_set_colors (gc);
840 TextFont (gc->font->mac_fontnum);
841 TextSize (gc->font->mac_fontsize);
842 TextFace (gc->font->mac_fontface);
843 TextMode (mode);
845 MoveTo (x, y);
846 DrawText (buf, 0, nchars * bytes_per_char);
850 /* Mac replacement for XDrawString. */
852 static void
853 XDrawString (display, w, gc, x, y, buf, nchars)
854 Display *display;
855 WindowPtr w;
856 GC gc;
857 int x, y;
858 char *buf;
859 int nchars;
861 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
865 /* Mac replacement for XDrawString16. */
867 static void
868 XDrawString16 (display, w, gc, x, y, buf, nchars)
869 Display *display;
870 WindowPtr w;
871 GC gc;
872 int x, y;
873 XChar2b *buf;
874 int nchars;
876 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
881 /* Mac replacement for XDrawImageString. */
883 static void
884 XDrawImageString (display, w, gc, x, y, buf, nchars)
885 Display *display;
886 WindowPtr w;
887 GC gc;
888 int x, y;
889 char *buf;
890 int nchars;
892 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
896 /* Mac replacement for XDrawString16. */
898 static void
899 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
900 Display *display;
901 WindowPtr w;
902 GC gc;
903 int x, y;
904 XChar2b *buf;
905 int nchars;
907 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
912 /* Mac replacement for XCopyArea: dest must be window. */
914 static void
915 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
916 dest_y)
917 Display *display;
918 Pixmap src;
919 WindowPtr dest;
920 GC gc;
921 int src_x, src_y;
922 unsigned int width, height;
923 int dest_x, dest_y;
925 Rect src_r, dest_r;
927 #if TARGET_API_MAC_CARBON
928 SetPort (GetWindowPort (dest));
929 #else
930 SetPort (dest);
931 #endif
933 mac_set_colors (gc);
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
940 PixMapHandle pmh;
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 */
953 #if 0
954 /* Convert a pair of local coordinates to global (screen) coordinates.
955 Assume graphic port has been properly set. */
956 static void
957 local_to_global_coord (short *h, short *v)
959 Point p;
961 p.h = *h;
962 p.v = *v;
964 LocalToGlobal (&p);
966 *h = p.h;
967 *v = p.v;
969 #endif
971 /* Mac replacement for XCopyArea: used only for scrolling. */
973 static void
974 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
975 Display *display;
976 WindowPtr w;
977 GC gc;
978 int src_x, src_y;
979 unsigned int width, height;
980 int dest_x, dest_y;
982 #if TARGET_API_MAC_CARBON
983 Rect gw_r, src_r, dest_r;
984 PixMapHandle pmh;
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));
999 mac_set_colors (gc);
1000 #else /* not TARGET_API_MAC_CARBON */
1001 Rect src_r, dest_r;
1003 SetPort (w);
1004 #if 0
1005 mac_set_colors (gc);
1006 #endif
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);
1011 #if 0
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);
1020 #else
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);
1028 #endif
1029 #endif /* not TARGET_API_MAC_CARBON */
1033 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1035 static void
1036 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1037 dest_x, dest_y)
1038 Display *display;
1039 Pixmap src;
1040 Pixmap dest;
1041 GC gc;
1042 int src_x, src_y;
1043 unsigned int width, height;
1044 int dest_x, dest_y;
1046 Rect src_r, dest_r;
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. */
1063 static void
1064 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1065 XGCValues *xgcv)
1067 if (mask & GCForeground)
1068 gc->foreground = xgcv->foreground;
1069 if (mask & GCBackground)
1070 gc->background = xgcv->background;
1071 if (mask & GCFont)
1072 gc->font = xgcv->font;
1076 /* Mac replacement for XCreateGC. */
1078 XGCValues *
1079 XCreateGC (void * ignore, Window window, unsigned long mask,
1080 XGCValues *xgcv)
1082 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1083 bzero (gc, sizeof (XGCValues));
1085 XChangeGC (ignore, gc, mask, xgcv);
1087 return gc;
1091 /* Used in xfaces.c. */
1093 void
1094 XFreeGC (display, gc)
1095 Display *display;
1096 GC gc;
1098 xfree (gc);
1102 /* Mac replacement for XGetGCValues. */
1104 static void
1105 XGetGCValues (void* ignore, XGCValues *gc,
1106 unsigned long mask, XGCValues *xgcv)
1108 XChangeGC (ignore, xgcv, mask, gc);
1112 /* Mac replacement for XSetForeground. */
1114 static void
1115 XSetForeground (display, gc, color)
1116 Display *display;
1117 GC gc;
1118 unsigned long color;
1120 gc->foreground = color;
1124 /* Mac replacement for XSetFont. */
1126 static void
1127 XSetFont (display, gc, font)
1128 Display *display;
1129 GC gc;
1130 XFontStruct *font;
1132 gc->font = font;
1136 static void
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. */
1146 void
1147 x_sync (f)
1148 void *f;
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
1158 performance. */
1160 #if TARGET_API_MAC_CARBON
1161 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1162 #else
1163 #define XFlush(DISPLAY) (void) 0
1164 #endif
1166 /* Flush display of frame F, or of all frames if F is null. */
1168 void
1169 x_flush (f)
1170 struct frame *f;
1172 #if TARGET_API_MAC_CARBON
1173 BLOCK_INPUT;
1174 if (f == NULL)
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));
1182 UNBLOCK_INPUT;
1183 #endif /* TARGET_API_MAC_CARBON */
1188 /* Return the struct mac_display_info corresponding to DPY. There's
1189 only one. */
1191 struct mac_display_info *
1192 mac_display_info_for_display (dpy)
1193 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. */
1209 static void
1210 x_update_begin (f)
1211 struct frame *f;
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
1219 position of W. */
1221 static void
1222 x_update_window_begin (w)
1223 struct window *w;
1225 struct frame *f = XFRAME (WINDOW_FRAME (w));
1226 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1228 updated_window = w;
1229 set_output_cursor (&w->cursor);
1231 BLOCK_INPUT;
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
1239 highlighting. */
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))
1258 int i;
1260 for (i = 0; i < w->desired_matrix->nrows; ++i)
1261 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1262 break;
1264 if (i < w->desired_matrix->nrows)
1265 clear_mouse_face (display_info);
1267 #endif /* 0 */
1270 UNBLOCK_INPUT;
1274 /* Draw a vertical window border to the right of window W if W doesn't
1275 have vertical scroll bars. */
1277 static void
1278 x_draw_vertical_border (w)
1279 struct window *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))
1290 int x0, x1, y0, y1;
1292 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1293 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1294 y1 -= 1;
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
1313 here. */
1315 static void
1316 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1317 struct window *w;
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)
1325 BLOCK_INPUT;
1327 if (cursor_on_p)
1328 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1329 output_cursor.vpos,
1330 output_cursor.x, output_cursor.y);
1332 x_draw_vertical_border (w);
1333 UNBLOCK_INPUT;
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;
1345 #if 0
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);
1351 #endif
1353 updated_window = NULL;
1357 /* End update of frame F. This function is installed as a hook in
1358 update_end. */
1360 static void
1361 x_update_end (f)
1362 struct frame *f;
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)));
1369 #else
1370 SetPort (FRAME_MAC_WINDOW (f));
1371 #endif
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;
1378 BLOCK_INPUT;
1379 XFlush (FRAME_MAC_DISPLAY (f));
1380 UNBLOCK_INPUT;
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. */
1388 static void
1389 XTframe_up_to_date (f)
1390 struct frame *f;
1392 if (FRAME_X_P (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)
1399 BLOCK_INPUT;
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;
1405 UNBLOCK_INPUT;
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. */
1418 static void
1419 x_after_update_window_line (desired_row)
1420 struct glyph_row *desired_row;
1422 struct window *w = updated_window;
1423 struct frame *f;
1424 int width, height;
1426 xassert (w);
1428 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1430 BLOCK_INPUT;
1431 x_draw_row_fringe_bitmaps (w, desired_row);
1432 UNBLOCK_INPUT;
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),
1445 width != 0)
1446 && (height = desired_row->visible_height,
1447 height > 0))
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))
1453 y -= width;
1455 BLOCK_INPUT;
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,
1461 width, height, 0);
1463 UNBLOCK_INPUT;
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
1471 drawn. */
1473 static void
1474 x_draw_fringe_bitmap (w, row, which, left_p)
1475 struct window *w;
1476 struct glyph_row *row;
1477 enum fringe_bitmap_type which;
1478 int left_p;
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;
1484 int b1, b2;
1485 unsigned char *bits;
1486 BitMap bitmap;
1487 XGCValues gcv;
1488 GC gc = f->output_data.mac->normal_gc;
1489 struct face *face;
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);
1497 switch (which)
1499 case NO_FRINGE_BITMAP:
1500 wd = 0;
1501 h = 0;
1502 break;
1504 case LEFT_TRUNCATION_BITMAP:
1505 wd = left_width;
1506 h = left_height;
1507 bits = left_bits;
1508 break;
1510 case OVERLAY_ARROW_BITMAP:
1511 wd = ov_width;
1512 h = ov_height;
1513 bits = ov_bits;
1514 break;
1516 case RIGHT_TRUNCATION_BITMAP:
1517 wd = right_width;
1518 h = right_height;
1519 bits = right_bits;
1520 break;
1522 case CONTINUED_LINE_BITMAP:
1523 wd = continued_width;
1524 h = continued_height;
1525 bits = continued_bits;
1526 break;
1528 case CONTINUATION_LINE_BITMAP:
1529 wd = continuation_width;
1530 h = continuation_height;
1531 bits = continuation_bits;
1532 break;
1534 case ZV_LINE_BITMAP:
1535 wd = zv_width;
1536 h = zv_height - (y % zv_period);
1537 bits = zv_bits + (y % zv_period);
1538 break;
1540 default:
1541 abort ();
1544 /* Clip bitmap if too high. */
1545 if (h > row->height)
1546 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
1556 the fringe. */
1557 b1 = -1;
1558 if (left_p)
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)
1563 - wd
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))
1570 ? 1 : 0);
1571 b1 = (window_box_left (w, -1)
1572 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1573 + border);
1574 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1577 else
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
1584 the fringe. */
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);
1592 if (b1 >= 0)
1594 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1595 XGCValues gcv;
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. */
1603 if (face->stipple)
1604 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1605 else
1606 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1607 #endif
1609 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1610 &gcv,
1612 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1613 row->y)),
1615 row->visible_height);
1617 #if 0 /* MAC_TODO: stipple */
1618 if (!face->stipple)
1619 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1620 #endif
1623 if (which == NO_FRINGE_BITMAP)
1625 mac_reset_clipping (display, window);
1626 return;
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. */
1643 static void
1644 x_draw_row_fringe_bitmaps (w, row)
1645 struct window *w;
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)
1656 return;
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;
1669 else
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;
1684 else
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
1695 rarely happens). */
1697 static void
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. */
1705 static void
1706 XTreset_terminal_modes ()
1712 /***********************************************************************
1713 Output Cursor
1714 ***********************************************************************/
1716 /* Set the global variable output_cursor to CURSOR. All cursor
1717 positions are relative to updated_window. */
1719 static void
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. */
1740 static void
1741 XTcursor_to (vpos, hpos, y, x)
1742 int vpos, hpos, y, x;
1744 struct window *w;
1746 /* If updated_window is not set, work on selected_window. */
1747 if (updated_window)
1748 w = updated_window;
1749 else
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)
1762 BLOCK_INPUT;
1763 x_display_cursor (w, 1, hpos, vpos, x, y);
1764 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1765 UNBLOCK_INPUT;
1771 /***********************************************************************
1772 Display Iterator
1773 ***********************************************************************/
1775 /* Function prototypes of this page. */
1777 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1778 struct glyph *,
1779 XChar2b *,
1780 int *));
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,
1788 int, int, double));
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) \
1797 ((font)->per_char \
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)) \
1802 : 0)) \
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)
1811 XFontStruct *font;
1812 XChar2b *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;
1834 else
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
1844 where:
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));
1861 else
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))
1873 ? NULL : pcm);
1877 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1878 the two-byte form of C. Encoding is returned in *CHAR2B. */
1880 static INLINE void
1881 x_encode_char (c, char2b, font_info)
1882 int c;
1883 XChar2b *char2b;
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
1891 fixed encoding. */
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;
1902 else
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
1912 program. */
1913 if (font->max_byte1 == 0) /* 1-byte font */
1914 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1915 else
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;
1931 if (enc == 4)
1933 int sjis1, sjis2;
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)
1950 struct frame *f;
1951 int c, face_id;
1952 XChar2b *char2b;
1953 int multibyte_p;
1955 struct face *face = FACE_FROM_ID (f, face_id);
1957 if (!multibyte_p)
1959 /* Unibyte case. We don't have to encode, but we have to make
1960 sure to use a face suitable for unibyte. */
1961 char2b->byte1 = 0;
1962 char2b->byte2 = c;
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. */
1969 char2b->byte1 = 0;
1970 char2b->byte2 = c;
1972 else
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);
1979 if (c2 > 0)
1980 char2b->byte1 = c1, char2b->byte2 = c2;
1981 else
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);
1989 if (font_info)
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);
1998 return 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)
2008 struct frame *f;
2009 struct glyph *glyph;
2010 XChar2b *char2b;
2011 int *two_byte_p;
2013 struct face *face;
2015 xassert (glyph->type == CHAR_GLYPH);
2016 face = FACE_FROM_ID (f, glyph->face_id);
2018 if (two_byte_p)
2019 *two_byte_p = 0;
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. */
2025 char2b->byte1 = 0;
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. */
2032 char2b->byte1 = 0;
2033 char2b->byte2 = glyph->u.ch;
2035 else
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);
2042 if (c2 > 0)
2043 char2b->byte1 = c1, char2b->byte2 = c2;
2044 else
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);
2052 if (font_info)
2054 x_encode_char (glyph->u.ch, char2b, font_info);
2055 if (two_byte_p)
2056 *two_byte_p
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);
2065 return 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. */
2072 static INLINE void
2073 x_append_glyph (it)
2074 struct it *it;
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. */
2106 static INLINE void
2107 x_append_composite_glyph (it)
2108 struct it *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
2138 IT->voffset. */
2140 static INLINE void
2141 take_vertical_position_into_account (it)
2142 struct it *it;
2144 if (it->voffset)
2146 if (it->voffset < 0)
2147 /* Increase the ascent so that we can display the text higher
2148 in the line. */
2149 it->ascent += abs (it->voffset);
2150 else
2151 /* Increase the descent so that we can display the text lower
2152 in the line. */
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. */
2162 static void
2163 x_produce_image_glyph (it)
2164 struct it *it;
2166 struct image *img;
2167 struct face *face;
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);
2173 xassert (img);
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;
2183 it->nglyphs = 1;
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);
2201 if (it->glyph_row)
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). */
2233 static void
2234 x_append_stretch_glyph (it, object, width, height, ascent)
2235 struct it *it;
2236 Lisp_Object object;
2237 int width, height;
2238 double 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
2270 being recognized:
2272 1. `:width WIDTH' specifies that the space should be WIDTH *
2273 canonical char width wide. WIDTH may be an integer or floating
2274 point number.
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
2290 the glyph property.
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. */
2298 #define NUMVAL(X) \
2299 ((INTEGERP (X) || FLOATP (X)) \
2300 ? XFLOATINT (X) \
2301 : - 1)
2304 static void
2305 x_produce_stretch_glyph (it)
2306 struct it *it;
2308 /* (space :width WIDTH :height HEIGHT. */
2309 #if GLYPH_DEBUG
2310 extern Lisp_Object Qspace;
2311 #endif
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),
2328 NUMVAL (prop) > 0)
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),
2332 NUMVAL (prop) > 0)
2334 /* Relative width `:relative-width FACTOR' specified and valid.
2335 Compute the width of the characters having the `glyph'
2336 property. */
2337 struct it it2;
2338 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2340 it2 = *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);
2347 else
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),
2356 NUMVAL (prop) > 0)
2357 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2358 else
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),
2364 NUMVAL (prop) > 0)
2365 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2366 else if (prop = Fplist_get (plist, QCrelative_height),
2367 NUMVAL (prop) > 0)
2368 height = FONT_HEIGHT (font) * NUMVAL (prop);
2369 else
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;
2378 else
2379 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2381 if (width <= 0)
2382 width = 1;
2383 if (height <= 0)
2384 height = 1;
2386 if (it->glyph_row)
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;
2397 it->nglyphs = 1;
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 -+-+---------+-+ | |
2424 | | | | | |
2425 | | | | F_ASCENT F_HEIGHT
2426 | | | ASCENT | |
2427 HEIGHT | | | | |
2428 | | |-|-+------+-----------|------- baseline
2429 | | | | BOFF | |
2430 | |---------|-+-+ | |
2431 | | | DESCENT | |
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. */
2454 static void
2455 x_produce_glyphs (it)
2456 struct it *it;
2458 it->glyph_not_available_p = 0;
2460 if (it->what == IT_CHARACTER)
2462 XChar2b char2b;
2463 XFontStruct *font;
2464 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2465 XCharStruct *pcm;
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
2471 later.
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
2477 glyph.
2479 int saved_multibyte_p = it->multibyte_p;
2481 /* Maybe translate single-byte characters to multibyte, or the
2482 other way. */
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)
2488 && (it->c >= 0240
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,
2508 it->multibyte_p);
2509 font = face->font;
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;
2517 font_info = NULL;
2519 else
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. */
2531 int stretched_p;
2533 it->nglyphs = 1;
2535 pcm = x_per_char_metric (font, &char2b);
2536 it->ascent = FONT_BASE (font) + boff;
2537 it->descent = FONT_DESCENT (font) - boff;
2539 if (pcm)
2541 it->phys_ascent = pcm->ascent + boff;
2542 it->phys_descent = pcm->descent - boff;
2543 it->pixel_width = pcm->width;
2545 else
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);
2556 if (stretched_p)
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;
2566 if (thick > 0)
2568 it->ascent += thick;
2569 it->descent += thick;
2571 else
2572 thick = -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)
2583 it->ascent += 2;
2585 take_vertical_position_into_account (it);
2587 /* If we have to actually produce glyphs, do it. */
2588 if (it->glyph_row)
2590 if (stretched_p)
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);
2599 else
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;
2613 it->nglyphs = 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;
2637 it->nglyphs = 1;
2638 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2639 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2641 if (it->glyph_row)
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);
2648 else
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
2658 did. */
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;
2670 else
2672 it->pixel_width = pcm->width;
2673 it->phys_ascent = pcm->ascent + boff;
2674 it->phys_descent = pcm->descent - boff;
2675 if (it->glyph_row
2676 && (pcm->lbearing < 0
2677 || pcm->rbearing > pcm->width))
2678 it->glyph_row->contains_overlapping_glyphs_p = 1;
2680 it->nglyphs = 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;
2687 if (thick > 0)
2689 it->ascent += thick;
2690 it->descent += thick;
2692 else
2693 thick = - 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)
2704 it->ascent += 2;
2706 take_vertical_position_into_account (it);
2708 if (it->glyph_row)
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. */
2717 XChar2b char2b;
2718 XFontStruct *font;
2719 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2720 XCharStruct *pcm;
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)
2730 && (it->c >= 0240
2731 || (it->c >= 0200
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);
2742 font = face->font;
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;
2750 font_info = NULL;
2752 else
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). */
2764 it->nglyphs = 1;
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);
2789 if (pcm)
2791 width = pcm->width;
2792 ascent = pcm->ascent;
2793 descent = pcm->descent;
2795 else
2797 width = FONT_WIDTH (font);
2798 ascent = FONT_BASE (font);
2799 descent = FONT_DESCENT (font);
2802 rightmost = width;
2803 lowest = - descent + boff;
2804 highest = ascent + boff;
2805 leftmost = 0;
2807 if (font_info
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
2816 the left. */
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,
2829 it->multibyte_p);
2830 font = face->font;
2831 if (font == NULL)
2833 font = FRAME_FONT (it->f);
2834 boff = it->f->output_data.mac->baseline_offset;
2835 font_info = NULL;
2837 else
2839 font_info
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);
2847 if (pcm)
2849 width = pcm->width;
2850 ascent = pcm->ascent;
2851 descent = pcm->descent;
2853 else
2855 width = FONT_WIDTH (font);
2856 ascent = 1;
2857 descent = 0;
2860 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2862 /* Relative composition with or without
2863 alternate chars. */
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. */
2874 btm = highest + 1;
2875 else if (ascent <= 0)
2876 /* One extra pixel between two glyphs. */
2877 btm = lowest - 1 - ascent - descent;
2880 else
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:
2887 0---1---2 -- ascent
2891 9--10--11 -- center
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;
2904 left = (leftmost
2905 + grefx * (rightmost - leftmost) / 2
2906 - nrefx * width / 2);
2907 btm = ((grefy == 0 ? highest
2908 : grefy == 1 ? 0
2909 : grefy == 2 ? lowest
2910 : (highest + lowest) / 2)
2911 - (nrefy == 0 ? ascent + descent
2912 : nrefy == 1 ? descent - boff
2913 : nrefy == 2 ? 0
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)
2924 leftmost = left;
2925 if (right > rightmost)
2926 rightmost = right;
2927 if (top > highest)
2928 highest = top;
2929 if (btm < lowest)
2930 lowest = btm;
2933 /* If there are glyphs whose x-offsets are negative,
2934 shift all glyphs to the right and make all x-offsets
2935 non-negative. */
2936 if (leftmost < 0)
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;
2960 if (thick > 0)
2962 it->ascent += thick;
2963 it->descent += thick;
2965 else
2966 thick = - 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)
2977 it->ascent += 2;
2979 take_vertical_position_into_account (it);
2981 if (it->glyph_row)
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)
3009 struct frame *f;
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);
3019 if (face)
3021 if (face->font)
3022 height = FONT_HEIGHT (face->font);
3023 if (face->box_line_width > 0)
3024 height += 2 * face->box_line_width;
3028 return height;
3032 /***********************************************************************
3033 Glyph display
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. */
3043 struct glyph_string
3045 /* X-origin of the string. */
3046 int x;
3048 /* Y-origin and y-position of the base line of this string. */
3049 int y, ybase;
3051 /* The width of the string, not including a face extension. */
3052 int width;
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. */
3060 int height;
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. */
3065 int left_overhang;
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. */
3070 int right_overhang;
3072 /* The frame on which the glyph string is drawn. */
3073 struct frame *f;
3075 /* The window on which the glyph string is drawn. */
3076 struct window *w;
3078 /* X display and window for convenience. */
3079 Display *display;
3080 Window window;
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. */
3090 XChar2b *char2b;
3091 int nchars;
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. */
3097 struct face *face;
3099 /* Font in which this string is to be drawn. */
3100 XFontStruct *font;
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. */
3112 int gidx;
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
3130 stipple pattern. */
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. */
3139 GC gc;
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. */
3147 struct image *img;
3149 struct glyph_string *next, *prev;
3153 #if 0
3155 static void
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,
3193 int));
3194 static void x_init_glyph_string P_ ((struct glyph_string *,
3195 XChar2b *, struct window *,
3196 struct glyph_row *,
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 *,
3205 int));
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 *,
3215 int *, int *));
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,
3228 int, int, 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 *,
3236 struct glyph_row *,
3237 enum glyph_row_area, int, int));
3239 #if GLYPH_DEBUG
3240 static void x_check_font P_ ((struct frame *, XFontStruct *));
3241 #endif
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. */
3247 static INLINE void
3248 x_append_glyph_string_lists (head, tail, h, t)
3249 struct glyph_string **head, **tail;
3250 struct glyph_string *h, *t;
3252 if (h)
3254 if (*head)
3255 (*tail)->next = h;
3256 else
3257 *head = h;
3258 h->prev = *tail;
3259 *tail = 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
3266 result. */
3268 static INLINE void
3269 x_prepend_glyph_string_lists (head, tail, h, t)
3270 struct glyph_string **head, **tail;
3271 struct glyph_string *h, *t;
3273 if (h)
3275 if (*head)
3276 (*head)->prev = t;
3277 else
3278 *tail = t;
3279 t->next = *head;
3280 *head = h;
3285 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3286 Set *HEAD and *TAIL to the resulting list. */
3288 static INLINE void
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
3299 face. */
3301 static void
3302 x_set_cursor_gc (s)
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)
3308 && !s->cmp)
3309 s->gc = s->f->output_data.mac->cursor_gc;
3310 else
3312 /* Cursor on non-default face: must merge. */
3313 XGCValues xgcv;
3314 unsigned long mask;
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,
3341 mask, &xgcv);
3342 else
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. */
3353 static void
3354 x_set_mouse_face_gc (s)
3355 struct glyph_string *s;
3357 int face_id;
3358 struct face *face;
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);
3363 if (face == NULL)
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);
3368 else
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;
3376 else
3378 /* Otherwise construct scratch_cursor_gc with values from FACE
3379 but font FONT. */
3380 XGCValues xgcv;
3381 unsigned long mask;
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,
3391 mask, &xgcv);
3392 else
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. */
3407 static INLINE void
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
3417 pattern. */
3419 static INLINE void
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);
3438 s->stippled_p = 0;
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;
3451 else
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. */
3464 static void
3465 x_get_glyph_string_clip_rect (s, r)
3466 struct glyph_string *s;
3467 Rect *r;
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))
3483 r->left -= width;
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;
3492 else
3493 r_height = s->height;
3495 else
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;
3511 else
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);
3519 else
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. */
3538 static INLINE void
3539 x_set_glyph_string_clipping (s)
3540 struct glyph_string *s;
3542 Rect r;
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. */
3551 static INLINE void
3552 x_compute_glyph_string_overhangs (s)
3553 struct glyph_string *s;
3555 if (s->cmp == NULL
3556 && s->first_glyph->type == CHAR_GLYPH)
3558 XCharStruct cs;
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. */
3572 static void
3573 x_compute_overhangs_and_x (s, x, backward_p)
3574 struct glyph_string *s;
3575 int x;
3576 int backward_p;
3578 if (backward_p)
3580 while (s)
3582 x_compute_glyph_string_overhangs (s);
3583 x -= s->width;
3584 s->x = x;
3585 s = s->prev;
3588 else
3590 while (s)
3592 x_compute_glyph_string_overhangs (s);
3593 s->x = x;
3594 x += s->width;
3595 s = s->next;
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. */
3605 void
3606 x_get_glyph_overhangs (glyph, f, left, right)
3607 struct glyph *glyph;
3608 struct frame *f;
3609 int *left, *right;
3611 *left = *right = 0;
3613 if (glyph->type == CHAR_GLYPH)
3615 XFontStruct *font;
3616 struct face *face;
3617 struct font_info *font_info;
3618 XChar2b char2b;
3619 XCharStruct *pcm;
3621 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3622 font = face->font;
3623 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3624 if (font
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. */
3640 static int
3641 x_left_overwritten (s)
3642 struct glyph_string *s;
3644 int k;
3646 if (s->left_overhang)
3648 int x = 0, i;
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;
3655 k = i + 1;
3657 else
3658 k = -1;
3660 return k;
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. */
3668 static int
3669 x_left_overwriting (s)
3670 struct glyph_string *s;
3672 int i, k, x;
3673 struct glyph *glyphs = s->row->glyphs[s->area];
3674 int first = s->first_glyph - glyphs;
3676 k = -1;
3677 x = 0;
3678 for (i = first - 1; i >= 0; --i)
3680 int left, right;
3681 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3682 if (x + right > 0)
3683 k = i;
3684 x -= glyphs[i].pixel_width;
3687 return k;
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. */
3695 static int
3696 x_right_overwritten (s)
3697 struct glyph_string *s;
3699 int k = -1;
3701 if (s->right_overhang)
3703 int x = 0, i;
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;
3711 k = i;
3714 return k;
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. */
3722 static int
3723 x_right_overwriting (s)
3724 struct glyph_string *s;
3726 int i, k, x;
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);
3731 k = -1;
3732 x = 0;
3733 for (i = first; i < end; ++i)
3735 int left, right;
3736 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3737 if (x - left < 0)
3738 k = i;
3739 x += glyphs[i].pixel_width;
3742 return k;
3746 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3748 static INLINE void
3749 x_clear_glyph_string_rect (s, x, y, w, h)
3750 struct glyph_string *s;
3751 int x, y, w, h;
3753 XGCValues xgcv;
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. */
3766 static void
3767 x_draw_glyph_string_background (s, force_p)
3768 struct glyph_string *s;
3769 int force_p;
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 */
3778 if (s->stippled_p)
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;
3789 else
3790 #endif
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
3794 || force_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. */
3807 static void
3808 x_draw_glyph_string_foreground (s)
3809 struct glyph_string *s;
3811 int i, x;
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);
3818 else
3819 x = s->x;
3821 /* Draw characters of S as rectangles if S's font could not be
3822 loaded. */
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,
3830 s->height - 1);
3831 x += g->pixel_width;
3834 else
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. */
3843 if (!s->two_byte_p)
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. */
3856 if (s->two_byte_p)
3857 XDrawString16 (s->display, s->window, s->gc, x,
3858 s->ybase - boff, s->char2b, s->nchars);
3859 else
3860 XDrawString (s->display, s->window, s->gc, x,
3861 s->ybase - boff, char1b, s->nchars);
3863 else
3865 if (s->two_byte_p)
3866 XDrawImageString16 (s->display, s->window, s->gc, x,
3867 s->ybase - boff, s->char2b, s->nchars);
3868 else
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. */
3877 static void
3878 x_draw_composite_glyph_string_foreground (s)
3879 struct glyph_string *s;
3881 int i, x;
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);
3888 else
3889 x = s->x;
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)
3900 if (s->gidx == 0)
3901 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3902 s->width - 1, s->height - 1);
3904 else
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],
3910 s->char2b + i, 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)
3925 Widget widget;
3927 struct x_display_info *dpyinfo;
3928 Lisp_Object tail;
3929 struct frame *f;
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)
3948 return f;
3950 abort ();
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)
3961 Widget widget;
3962 Colormap cmap;
3963 XColor *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
3977 color allocated. */
3980 x_alloc_nearest_color (f, cmap, color)
3981 struct frame *f;
3982 Colormap cmap;
3983 XColor *color;
3985 Display *display = FRAME_X_DISPLAY (f);
3986 Screen *screen = FRAME_X_SCREEN (f);
3987 int rc;
3989 gamma_correct (f, color);
3990 rc = XAllocColor (display, cmap, color);
3991 if (rc == 0)
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. */
3997 int nearest, i;
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)
4003 cells[i].pixel = 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)
4015 nearest = i;
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
4027 if (rc)
4028 register_color (color->pixel);
4029 #endif /* DEBUG_X_COLORS */
4031 return rc;
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. */
4039 unsigned long
4040 x_copy_color (f, pixel)
4041 struct frame *f;
4042 unsigned long pixel;
4044 XColor color;
4046 color.pixel = pixel;
4047 BLOCK_INPUT;
4048 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4049 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4050 UNBLOCK_INPUT;
4051 #ifdef DEBUG_X_COLORS
4052 register_color (pixel);
4053 #endif
4054 return 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. */
4062 unsigned long
4063 x_copy_dpy_color (dpy, cmap, pixel)
4064 Display *dpy;
4065 Colormap cmap;
4066 unsigned long pixel;
4068 XColor color;
4070 color.pixel = pixel;
4071 BLOCK_INPUT;
4072 XQueryColor (dpy, cmap, &color);
4073 XAllocColor (dpy, cmap, &color);
4074 UNBLOCK_INPUT;
4075 #ifdef DEBUG_X_COLORS
4076 register_color (pixel);
4077 #endif
4078 return 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. */
4090 static int
4091 mac_alloc_lighter_color (f, color, factor, delta)
4092 struct frame *f;
4093 unsigned long *color;
4094 double factor;
4095 int delta;
4097 unsigned long new;
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))));
4104 if (new == *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)? */
4112 if (new == *color)
4113 return 0;
4115 *color = new;
4117 return 1;
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. */
4128 static void
4129 x_setup_relief_color (f, relief, factor, delta, default_pixel)
4130 struct frame *f;
4131 struct relief *relief;
4132 double factor;
4133 int delta;
4134 unsigned long default_pixel;
4136 XGCValues xgcv;
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;
4147 pixel = background;
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;
4158 mask |= GCStipple;
4159 #endif
4160 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4162 else
4163 XChangeGC (NULL, relief->gc, mask, &xgcv);
4167 /* Set up colors for the relief lines around glyph string S. */
4169 static void
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;
4178 else
4180 XGCValues xgcv;
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
4205 when drawing. */
4207 static void
4208 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4209 raised_p, left_p, right_p, clip_rect)
4210 struct frame *f;
4211 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4212 Rect *clip_rect;
4214 int i;
4215 GC gc;
4217 if (raised_p)
4218 gc = f->output_data.mac->white_relief.gc;
4219 else
4220 gc = f->output_data.mac->black_relief.gc;
4221 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4223 /* Top. */
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);
4229 /* Left. */
4230 if (left_p)
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));
4236 if (raised_p)
4237 gc = f->output_data.mac->black_relief.gc;
4238 else
4239 gc = f->output_data.mac->white_relief.gc;
4240 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4241 clip_rect);
4243 /* Bottom. */
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);
4249 /* Right. */
4250 if (right_p)
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. */
4266 static void
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;
4271 Rect *clip_rect;
4273 XGCValues xgcv;
4275 xgcv.foreground = s->face->box_color;
4276 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4278 /* Top. */
4279 XFillRectangle (s->display, s->window, &xgcv,
4280 left_x, top_y, right_x - left_x, width);
4282 /* Left. */
4283 if (left_p)
4284 XFillRectangle (s->display, s->window, &xgcv,
4285 left_x, top_y, width, bottom_y - top_y);
4287 /* Bottom. */
4288 XFillRectangle (s->display, s->window, &xgcv,
4289 left_x, bottom_y - width, right_x - left_x, width);
4291 /* Right. */
4292 if (right_p)
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. */
4302 static void
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;
4309 Rect clip_rect;
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
4322 ? s->first_glyph
4323 : s->first_glyph + s->nchars - 1);
4325 width = abs (s->face->box_line_width);
4326 raised_p = s->face->box == FACE_RAISED_BOX;
4327 left_x = s->x;
4328 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4329 ? last_x - 1
4330 : min (last_x, s->x + s->background_width) - 1));
4331 top_y = s->y;
4332 bottom_y = top_y + s->height - 1;
4334 left_p = (s->first_glyph->left_box_line_p
4335 || (s->hl == DRAW_MOUSE_FACE
4336 && (s->prev == NULL
4337 || s->prev->hl != s->hl)));
4338 right_p = (last_glyph->right_box_line_p
4339 || (s->hl == DRAW_MOUSE_FACE
4340 && (s->next == NULL
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);
4348 else
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. */
4359 static void
4360 x_draw_image_foreground (s)
4361 struct glyph_string *s;
4363 int x;
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);
4371 else
4372 x = s->x;
4374 /* If there is a margin around the image, adjust x- and y-position
4375 by that margin. */
4376 x += s->img->hmargin;
4377 y += s->img->vmargin;
4379 if (s->img->pixmap)
4381 #if 0 /* MAC_TODO: image mask */
4382 if (s->img->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
4388 manually. */
4389 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4390 | GCFunction);
4391 XGCValues xgcv;
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);
4401 image_rect.x = x;
4402 image_rect.y = y;
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);
4409 else
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;
4424 if (r < 0) r = -r;
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);
4430 else
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. */
4440 static void
4441 x_draw_image_relief (s)
4442 struct glyph_string *s;
4444 int x0, y0, x1, y1, thick, raised_p;
4445 Rect r;
4446 int x;
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);
4454 else
4455 x = s->x;
4457 /* If there is a margin around the image, adjust x- and y-position
4458 by that margin. */
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;
4468 else
4470 thick = abs (s->img->relief);
4471 raised_p = s->img->relief > 0;
4474 x0 = x - thick;
4475 y0 = y - thick;
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. */
4487 static void
4488 x_draw_image_foreground_1 (s, pixmap)
4489 struct glyph_string *s;
4490 Pixmap pixmap;
4492 int x;
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);
4500 else
4501 x = 0;
4503 /* If there is a margin around the image, adjust x- and y-position
4504 by that margin. */
4505 x += s->img->hmargin;
4506 y += s->img->vmargin;
4508 if (s->img->pixmap)
4510 #if 0 /* MAC_TODO: image mask */
4511 if (s->img->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
4517 manually. */
4518 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4519 | GCFunction);
4520 XGCValues xgcv;
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);
4532 else
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;
4547 if (r < 0) r = -r;
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);
4553 else
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. */
4563 static void
4564 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4565 struct glyph_string *s;
4566 int x, y, w, h;
4568 #if 0 /* MAC_TODO: stipple */
4569 if (s->stippled_p)
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);
4576 else
4577 #endif /* MAC_TODO */
4578 x_clear_glyph_string_rect (s, x, y, w, h);
4582 /* Draw image glyph string S.
4584 s->y
4585 s->x +-------------------------
4586 | s->face->box
4588 | +-------------------------
4589 | | s->img->vmargin
4591 | | +-------------------
4592 | | | the image
4596 static void
4597 x_draw_image_glyph_string (s)
4598 struct glyph_string *s;
4600 int x, y;
4601 int box_line_hwidth = abs (s->face->box_line_width);
4602 int box_line_vwidth = max (s->face->box_line_width, 0);
4603 int height;
4604 Pixmap pixmap = 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
4610 flickering. */
4611 s->stippled_p = s->face->stipple != 0;
4612 if (height > s->img->height
4613 || s->img->hmargin
4614 || s->img->vmargin
4615 #if 0 /* TODO: image mask */
4616 || s->img->mask
4617 #endif
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;
4623 else
4624 x = s->x;
4626 y = s->y + box_line_vwidth;
4627 #if 0 /* TODO: image mask */
4628 if (s->img->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,
4639 s->height, depth);
4641 /* Don't clip in the following because we're working on the
4642 pixmap. */
4643 XSetClipMask (s->display, s->gc, None);
4645 /* Fill the pixmap with the background color/stipple. */
4646 if (s->stippled_p)
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);
4654 else
4656 XGCValues xgcv;
4657 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4658 &xgcv);
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);
4665 else
4666 #endif
4667 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4669 s->background_filled_p = 1;
4672 /* Draw the foreground. */
4673 if (pixmap != 0)
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);
4682 else
4683 x_draw_image_foreground (s);
4685 /* If we must draw a relief around the image, do it. */
4686 if (s->img->relief
4687 || s->hl == DRAW_IMAGE_RAISED
4688 || s->hl == DRAW_IMAGE_SUNKEN)
4689 x_draw_image_relief (s);
4693 /* Draw stretch glyph string S. */
4695 static void
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);
4709 /* Draw cursor. */
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;
4718 Rect r;
4720 if (s->row->mouse_face_p
4721 && cursor_in_mouse_face_p (s->w))
4723 x_set_mouse_face_gc (s);
4724 gc = s->gc;
4726 else
4727 gc = s->face->gc;
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);
4740 else
4741 #endif /* MAC_TODO */
4743 XGCValues xgcv;
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,
4755 s->height);
4757 s->background_filled_p = 1;
4761 /* Draw glyph string S. */
4763 static void
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);
4796 relief_drawn_p = 1;
4798 else
4799 x_set_glyph_string_clipping (s);
4801 switch (s->first_glyph->type)
4803 case IMAGE_GLYPH:
4804 x_draw_image_glyph_string (s);
4805 break;
4807 case STRETCH_GLYPH:
4808 x_draw_stretch_glyph_string (s);
4809 break;
4811 case CHAR_GLYPH:
4812 if (s->for_overlaps_p)
4813 s->background_filled_p = 1;
4814 else
4815 x_draw_glyph_string_background (s, 0);
4816 x_draw_glyph_string_foreground (s);
4817 break;
4819 case COMPOSITE_GLYPH:
4820 if (s->for_overlaps_p || s->gidx > 0)
4821 s->background_filled_p = 1;
4822 else
4823 x_draw_glyph_string_background (s, 1);
4824 x_draw_composite_glyph_string_foreground (s);
4825 break;
4827 default:
4828 abort ();
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,
4841 s->width, h);
4842 else
4844 XGCValues xgcv;
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,
4848 s->width, h);
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,
4860 s->width, h);
4861 else
4863 XGCValues xgcv;
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,
4867 s->width, h);
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,
4880 s->width, h);
4881 else
4883 XGCValues xgcv;
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,
4887 s->width, h);
4888 XSetForeground (s->display, s->gc, xgcv.foreground);
4892 /* Draw relief. */
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. */
4915 static int
4916 x_fill_composite_glyph_string (s, faces, overlaps_p)
4917 struct glyph_string *s;
4918 struct face **faces;
4919 int overlaps_p;
4921 int i;
4923 xassert (s);
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. */
4934 ++s->nchars;
4935 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4936 ++s->nchars;
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. */
4959 s->two_byte_p = 1;
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. */
4974 static int
4975 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4976 struct glyph_string *s;
4977 int face_id;
4978 int start, end, overlaps_p;
4980 struct glyph *glyph, *last;
4981 int voffset;
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;
4995 while (glyph < last
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)
5002 int two_byte_p;
5004 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
5005 s->char2b + s->nchars,
5006 &two_byte_p);
5007 s->two_byte_p = two_byte_p;
5008 ++s->nchars;
5009 xassert (s->nchars <= end - start);
5010 s->width += glyph->pixel_width;
5011 ++glyph;
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. */
5037 static void
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);
5043 xassert (s->img);
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. */
5061 static int
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;
5066 int start, end;
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;
5082 for (++glyph;
5083 (glyph < last
5084 && glyph->type == STRETCH_GLYPH
5085 && glyph->voffset == voffset
5086 && glyph->face_id == face_id);
5087 ++glyph)
5088 s->width += glyph->pixel_width;
5090 /* Adjust base line for subscript/superscript text. */
5091 s->ybase += voffset;
5093 xassert (s->face);
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. */
5106 static void
5107 x_init_glyph_string (s, char2b, w, row, area, start, hl)
5108 struct glyph_string *s;
5109 XChar2b *char2b;
5110 struct window *w;
5111 struct glyph_row *row;
5112 enum glyph_row_area area;
5113 int start;
5114 enum draw_glyphs_face hl;
5116 bzero (s, sizeof *s);
5117 s->w = w;
5118 s->f = XFRAME (w->frame);
5119 s->display = FRAME_MAC_DISPLAY (s->f);
5120 s->window = FRAME_MAC_WINDOW (s->f);
5121 s->char2b = char2b;
5122 s->hl = hl;
5123 s->row = row;
5124 s->area = area;
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. */
5141 static INLINE void
5142 x_set_glyph_string_background_width (s, start, last_x)
5143 struct glyph_string *s;
5144 int start;
5145 int last_x;
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
5165 area. */
5166 if (s->extends_to_end_of_line_p)
5167 s->background_width = last_x - s->x + 1;
5168 else
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) \
5184 do \
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); \
5190 s->x = (X); \
5192 while (0)
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) \
5204 do \
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); \
5210 ++START; \
5211 s->x = (X); \
5213 while (0)
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) \
5226 do \
5228 int c, face_id; \
5229 XChar2b *char2b; \
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); \
5238 s->x = (X); \
5239 START = x_fill_glyph_string (s, face_id, START, END, \
5240 OVERLAPS_P); \
5242 while (0)
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) \
5255 do { \
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; \
5261 XChar2b *char2b; \
5262 struct face **faces; \
5263 struct glyph_string *first_s = NULL; \
5264 int n; \
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); \
5286 s->cmp = cmp; \
5287 s->gidx = n; \
5288 s->x = (X); \
5290 if (n == 0) \
5291 first_s = s; \
5293 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5296 ++START; \
5297 s = first_s; \
5298 } while (0)
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
5309 asynchronously). */
5311 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5312 do \
5314 HEAD = TAIL = NULL; \
5315 while (START < END) \
5317 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5318 switch (first_glyph->type) \
5320 case CHAR_GLYPH: \
5321 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5322 TAIL, HL, X, LAST_X, \
5323 OVERLAPS_P); \
5324 break; \
5326 case COMPOSITE_GLYPH: \
5327 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5328 HEAD, TAIL, HL, X, LAST_X,\
5329 OVERLAPS_P); \
5330 break; \
5332 case STRETCH_GLYPH: \
5333 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5334 HEAD, TAIL, HL, X, LAST_X); \
5335 break; \
5337 case IMAGE_GLYPH: \
5338 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5339 TAIL, HL, X, LAST_X); \
5340 break; \
5342 default: \
5343 abort (); \
5346 x_set_glyph_string_background_width (s, START, LAST_X); \
5347 (X) += s->width; \
5350 while (0)
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. */
5369 static int
5370 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5371 struct window *w;
5372 int x;
5373 struct glyph_row *row;
5374 enum glyph_row_area area;
5375 int start, end;
5376 enum draw_glyphs_face hl;
5377 int overlaps_p;
5379 struct glyph_string *head, *tail;
5380 struct glyph_string *s;
5381 int last_x, area_width;
5382 int x_reached;
5383 int i, j;
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
5395 or fringes. */
5396 struct frame *f = XFRAME (WINDOW_FRAME (w));
5397 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5399 x += window_left_x;
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))
5407 last_x += width;
5408 else
5409 x -= width;
5412 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5413 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5415 else
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'. */
5426 i = start;
5427 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5428 overlaps_p);
5429 if (tail)
5430 x_reached = tail->x + tail->background_width;
5431 else
5432 x_reached = x;
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)
5439 int dummy_x = 0;
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
5450 draws over it. */
5451 i = x_left_overwritten (head);
5452 if (i >= 0)
5454 j = i;
5455 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5456 DRAW_NORMAL_TEXT, dummy_x, last_x,
5457 overlaps_p);
5458 start = i;
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
5469 strings exist. */
5470 i = x_left_overwriting (head);
5471 if (i >= 0)
5473 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5474 DRAW_NORMAL_TEXT, dummy_x, last_x,
5475 overlaps_p);
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
5485 over it. */
5486 i = x_right_overwritten (tail);
5487 if (i >= 0)
5489 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5490 DRAW_NORMAL_TEXT, x, last_x,
5491 overlaps_p);
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);
5502 if (i >= 0)
5504 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5505 DRAW_NORMAL_TEXT, x, last_x,
5506 overlaps_p);
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
5522 completely. */
5523 && !overlaps_p)
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);
5553 return x_reached;
5557 /* Fix the display of area AREA of overlapping row ROW in window W. */
5559 static void
5560 x_fix_overlapping_area (w, row, area)
5561 struct window *w;
5562 struct glyph_row *row;
5563 enum glyph_row_area area;
5565 int i, x;
5567 BLOCK_INPUT;
5569 if (area == LEFT_MARGIN_AREA)
5570 x = 0;
5571 else if (area == TEXT_AREA)
5572 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5573 else
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;
5586 ++i;
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);
5594 else
5596 x += row->glyphs[area][i].pixel_width;
5597 ++i;
5601 UNBLOCK_INPUT;
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. */
5611 static void
5612 x_write_glyphs (start, len)
5613 struct glyph *start;
5614 int len;
5616 int x, hpos;
5618 xassert (updated_window && updated_row);
5619 BLOCK_INPUT;
5621 /* Write glyphs. */
5623 hpos = start - updated_row->glyphs[updated_area];
5624 x = x_draw_glyphs (updated_window, output_cursor.x,
5625 updated_row, updated_area,
5626 hpos, hpos + len,
5627 DRAW_NORMAL_TEXT, 0);
5629 UNBLOCK_INPUT;
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. */
5639 static void
5640 x_insert_glyphs (start, len)
5641 struct glyph *start;
5642 register int len;
5644 struct frame *f;
5645 struct window *w;
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);
5652 BLOCK_INPUT;
5653 w = updated_window;
5654 f = XFRAME (WINDOW_FRAME (w));
5656 /* Get the height of the line we are in. */
5657 row = updated_row;
5658 line_height = row->height;
5660 /* Get the width of the glyphs to insert. */
5661 shift_by_width = 0;
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)
5667 - output_cursor.x
5668 - shift_by_width);
5670 /* Shift right. */
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,
5676 frame_x, frame_y,
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;
5688 UNBLOCK_INPUT;
5692 /* Delete N glyphs at the nominal cursor position. Not implemented
5693 for X frames. */
5695 static void
5696 x_delete_glyphs (n)
5697 register int n;
5699 abort ();
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. */
5710 static void
5711 x_clear_end_of_line (to_x)
5712 int to_x;
5714 struct frame *f;
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);
5729 else
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. */
5735 if (to_x == 0)
5736 return;
5737 else if (to_x < 0)
5738 to_x = max_x;
5739 else
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,
5748 updated_row->y,
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);
5759 else
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)
5772 BLOCK_INPUT;
5773 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5774 from_x, from_y, to_x - from_x, to_y - from_y,
5776 UNBLOCK_INPUT;
5781 /* Clear entire frame. If updating_frame is non-null, clear that
5782 frame. Otherwise clear the selected frame. */
5784 static void
5785 x_clear_frame ()
5787 struct frame *f;
5789 if (updating_frame)
5790 f = updating_frame;
5791 else
5792 f = SELECTED_FRAME ();
5794 /* Clearing the frame will erase any cursor, so mark them all as no
5795 longer visible. */
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. */
5802 BLOCK_INPUT;
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);
5809 #endif
5811 XFlush (FRAME_MAC_DISPLAY (f));
5812 UNBLOCK_INPUT;
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. */
5827 static int
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;
5837 y.tv_sec += 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;
5844 y.tv_sec -= nsec;
5847 /* Compute the time remaining to wait. tv_usec is certainly
5848 positive. */
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
5853 negative. */
5854 return x.tv_sec < y.tv_sec;
5857 void
5858 XTflash (f)
5859 struct frame *f;
5861 BLOCK_INPUT;
5863 FlashMenuBar (0);
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. */
5876 while (1)
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))
5885 break;
5887 /* Try to wait that long--but we might wake up sooner. */
5888 select (0, NULL, NULL, NULL, &timeout);
5892 FlashMenuBar (0);
5894 UNBLOCK_INPUT;
5897 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5900 /* Make audible bell. */
5902 void
5903 XTring_bell ()
5905 struct frame *f = SELECTED_FRAME ();
5907 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5908 if (visible_bell)
5909 XTflash (f);
5910 else
5911 #endif
5913 BLOCK_INPUT;
5914 SysBeep (1);
5915 XFlush (FRAME_MAC_DISPLAY (f));
5916 UNBLOCK_INPUT;
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. */
5927 void
5928 XTset_terminal_window (n)
5929 register int n;
5931 /* This function intentionally left blank. */
5936 /***********************************************************************
5937 Line Dance
5938 ***********************************************************************/
5940 /* Perform an insert-lines or delete-lines operation, inserting N
5941 lines or deleting -N lines at vertical position VPOS. */
5943 static void
5944 x_ins_del_lines (vpos, n)
5945 int vpos, n;
5947 abort ();
5951 /* Scroll part of the display as described by RUN. */
5953 static void
5954 x_scroll_run (w, run)
5955 struct window *w;
5956 struct run *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
5963 fringes of W. */
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;
5972 if (to_y < from_y)
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;
5978 else
5979 height = run->height;
5981 else
5983 /* Scolling down. Make sure we don't copy over the mode line.
5984 at the bottom. */
5985 if (to_y + run->height > bottom_y)
5986 height = bottom_y - to_y;
5987 else
5988 height = run->height;
5991 BLOCK_INPUT;
5993 /* Cursor off. Will be switched on again in x_update_window_end. */
5994 updated_window = w;
5995 x_clear_cursor (w);
5997 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5998 f->output_data.mac->normal_gc,
5999 x, from_y,
6000 width, height,
6001 x, to_y);
6003 UNBLOCK_INPUT;
6008 /***********************************************************************
6009 Exposure Events
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. */
6017 static void
6018 expose_frame (f, x, y, w, h)
6019 struct frame *f;
6020 int x, y, w, h;
6022 Rect r;
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"));
6031 return;
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);
6039 else
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"));
6049 return;
6052 if (w == 0 || h == 0)
6054 r.left = r.top = 0;
6055 r.right = CANON_X_UNIT (f) * f->width;
6056 r.bottom = CANON_Y_UNIT (f) * f->height;
6058 else
6060 r.left = x;
6061 r.top = y;
6062 r.right = x + w;
6063 r.bottom = y + h;
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. */
6103 static int
6104 expose_window_tree (w, r)
6105 struct window *w;
6106 Rect *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);
6119 else
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. */
6132 static void
6133 expose_area (w, row, r, area)
6134 struct window *w;
6135 struct glyph_row *row;
6136 Rect *r;
6137 enum glyph_row_area area;
6139 struct glyph *first = row->glyphs[area];
6140 struct glyph *end = row->glyphs[area] + row->used[area];
6141 struct glyph *last;
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,
6147 0, row->used[area],
6148 DRAW_NORMAL_TEXT, 0);
6149 else
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)
6155 start_x = 0;
6156 else if (area == TEXT_AREA)
6157 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6158 else
6159 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6160 + window_box_width (w, TEXT_AREA));
6161 x = start_x;
6163 /* Find the first glyph that must be redrawn. */
6164 while (first < end
6165 && x + first->pixel_width < r->left)
6167 x += first->pixel_width;
6168 ++first;
6171 /* Find the last one. */
6172 last = first;
6173 first_x = x;
6174 while (last < end
6175 && x < r->right)
6177 x += last->pixel_width;
6178 ++last;
6181 /* Repaint. */
6182 if (last > first)
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. */
6195 static int
6196 expose_line (w, row, r)
6197 struct window *w;
6198 struct glyph_row *row;
6199 Rect *r;
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);
6206 else
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. */
6223 static int
6224 x_phys_cursor_in_rect_p (w, r)
6225 struct window *w;
6226 Rect *r;
6228 Rect cr, result;
6229 struct glyph *cursor_glyph;
6231 cursor_glyph = get_phys_cursor_glyph (w);
6232 if (cursor_glyph)
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);
6240 else
6241 return 0;
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. */
6253 static void
6254 expose_overlaps (w, first_overlapping_row, last_overlapping_row)
6255 struct window *w;
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
6281 mouse-face. */
6283 static int
6284 expose_window (w, fr)
6285 struct window *w;
6286 Rect *fr;
6288 struct frame *f = XFRAME (w->frame);
6289 Rect wr, r;
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
6295 created window. */
6296 if (w->current_matrix == NULL)
6297 return 0;
6299 /* When we're currently updating the window, display and current
6300 matrix usually don't agree. Arrange for a thorough display
6301 later. */
6302 if (w == updated_window)
6304 SET_FRAME_GARBAGED (f);
6305 return 0;
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))
6334 x_clear_cursor (w);
6335 cursor_cleared_p = 1;
6337 else
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;
6343 row->enabled_p;
6344 ++row)
6346 int y0 = row->y;
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;
6365 if (y1 >= yb)
6366 break;
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),
6372 row->enabled_p)
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))
6397 ControlHandle ch
6398 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6400 Draw1Control (ch);
6403 return mouse_face_overwritten_p;
6406 static int
6407 x_intersect_rectangles (r1, r2, result)
6408 Rect *r1, *r2, *result;
6410 Rect *left, *right;
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;
6417 else
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;
6433 else
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);
6445 intersection_p = 1;
6449 return intersection_p;
6456 static void
6457 frame_highlight (f)
6458 struct frame *f;
6460 x_update_cursor (f, 1);
6463 static void
6464 frame_unhighlight (f)
6465 struct frame *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. */
6476 static void
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);
6492 #if 0
6493 selected_frame = frame;
6494 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6495 selected_frame);
6496 Fselect_window (selected_frame->selected_window);
6497 choose_minibuf_frame ();
6498 #endif /* ! 0 */
6500 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6501 pending_autoraise_frame = dpyinfo->x_focus_frame;
6502 else
6503 pending_autoraise_frame = 0;
6506 x_frame_rehighlight (dpyinfo);
6509 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6511 void
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. */
6526 static void
6527 XTframe_rehighlight (frame)
6528 struct frame *frame;
6530 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6533 static void
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;
6551 else
6552 dpyinfo->x_highlight_frame = 0;
6554 if (dpyinfo->x_highlight_frame != old_highlight)
6556 if (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. */
6569 static void
6570 x_find_modifier_meanings (dpyinfo)
6571 struct x_display_info *dpyinfo;
6573 int min_code, max_code;
6574 KeySym *syms;
6575 int syms_per_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;
6584 #ifdef HAVE_X11R4
6585 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6586 #else
6587 min_code = dpyinfo->display->min_keycode;
6588 max_code = dpyinfo->display->max_keycode;
6589 #endif
6591 syms = XGetKeyboardMapping (dpyinfo->display,
6592 min_code, max_code - min_code + 1,
6593 &syms_per_code);
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++)
6604 KeyCode code
6605 = mods->modifiermap[(row * mods->max_keypermod) + col];
6607 /* Zeroes are used for filler. Skip them. */
6608 if (code == 0)
6609 continue;
6611 /* Are any of this keycode's keysyms a meta key? */
6613 int code_col;
6615 for (code_col = 0; code_col < syms_per_code; code_col++)
6617 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6619 switch (sym)
6621 case XK_Meta_L:
6622 case XK_Meta_R:
6623 dpyinfo->meta_mod_mask |= (1 << row);
6624 break;
6626 case XK_Alt_L:
6627 case XK_Alt_R:
6628 dpyinfo->alt_mod_mask |= (1 << row);
6629 break;
6631 case XK_Hyper_L:
6632 case XK_Hyper_R:
6633 dpyinfo->hyper_mod_mask |= (1 << row);
6634 break;
6636 case XK_Super_L:
6637 case XK_Super_R:
6638 dpyinfo->super_mod_mask |= (1 << row);
6639 break;
6641 case XK_Shift_Lock:
6642 /* Ignore this if it's not on the lock modifier. */
6643 if ((1 << row) == LockMask)
6644 dpyinfo->shift_lock_mask = LockMask;
6645 break;
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
6673 Emacs uses. */
6675 static unsigned int
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;
6690 unsigned int state;
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. */
6703 char *
6704 x_get_keysym_name (keysym)
6705 int keysym;
6707 char *value;
6709 BLOCK_INPUT;
6710 #if 0
6711 value = XKeysymToString (keysym);
6712 #else
6713 value = 0;
6714 #endif
6715 UNBLOCK_INPUT;
6717 return value;
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. */
6729 void
6730 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6731 FRAME_PTR f;
6732 register int pix_x, pix_y;
6733 register int *x, *y;
6734 Rect *bounds;
6735 int noclip;
6737 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6738 if (NILP (Vwindow_system))
6740 *x = pix_x;
6741 *y = pix_y;
6742 return;
6745 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6746 even for negative values. */
6747 if (pix_x < 0)
6748 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6749 if (pix_y < 0)
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);
6755 if (bounds)
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;
6763 if (!noclip)
6765 if (pix_x < 0)
6766 pix_x = 0;
6767 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6768 pix_x = FRAME_WINDOW_WIDTH (f);
6770 if (pix_y < 0)
6771 pix_y = 0;
6772 else if (pix_y > f->height)
6773 pix_y = f->height;
6776 *x = pix_x;
6777 *y = pix_y;
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,
6784 return 0. */
6787 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6788 struct window *w;
6789 int hpos, vpos;
6790 int *frame_x, *frame_y;
6792 int success_p;
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]);
6803 *frame_y = row->y;
6804 *frame_x = row->x;
6805 while (glyph < end)
6807 *frame_x += glyph->pixel_width;
6808 ++glyph;
6811 success_p = 1;
6813 else
6815 *frame_y = *frame_x = 0;
6816 success_p = 0;
6819 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6820 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6821 return success_p;
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
6828 the mouse. */
6830 static Lisp_Object
6831 construct_mouse_click (result, event, f)
6832 struct input_event *result;
6833 EventRecord *event;
6834 struct frame *f;
6836 Point mouseLoc;
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)));
6847 #else
6848 SetPort (FRAME_MAC_WINDOW (f));
6849 #endif
6851 GlobalToLocal (&mouseLoc);
6852 XSETINT (result->x, mouseLoc.h);
6853 XSETINT (result->y, mouseLoc.v);
6855 XSETFRAME (result->frame_or_window, f);
6857 result->arg = Qnil;
6858 return Qnil;
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;
6873 static void
6874 note_mouse_movement (frame, pos)
6875 FRAME_PTR frame;
6876 Point *pos;
6878 #if TARGET_API_MAC_CARBON
6879 Rect r;
6880 #endif
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)))
6888 #else
6889 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6890 #endif
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 /************************************************************************
6915 Mouse Face
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
6924 date. */
6926 static struct glyph *
6927 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6928 struct window *w;
6929 int x, y;
6930 int *hpos, *vpos, *area;
6931 int buffer_only_p;
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)
6942 return NULL;
6943 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6944 break;
6947 *vpos = i;
6948 *hpos = 0;
6950 /* Give up if Y is not in the window. */
6951 if (i == w->current_matrix->nrows)
6952 return NULL;
6954 /* Get the glyph area containing X. */
6955 if (w->pseudo_window_p)
6957 *area = TEXT_AREA;
6958 x0 = 0;
6960 else
6962 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6963 if (x < left_area_width)
6965 *area = LEFT_MARGIN_AREA;
6966 x0 = 0;
6968 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6970 *area = TEXT_AREA;
6971 x0 = row->x + left_area_width;
6973 else
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];
6983 while (glyph < end)
6985 if (x < x0 + glyph->pixel_width)
6987 if (w->pseudo_window_p)
6988 break;
6989 else if (!buffer_only_p || BUFFERP (glyph->object))
6990 break;
6993 x0 += glyph->pixel_width;
6994 ++glyph;
6997 if (glyph == end)
6998 return NULL;
7000 *hpos = glyph - row->glyphs[*area];
7001 return glyph;
7005 /* Convert frame-relative x/y to coordinates relative to window W.
7006 Takes pseudo-windows into account. */
7008 static void
7009 frame_to_window_pixel_xy (w, x, y)
7010 struct window *w;
7011 int *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);
7021 else
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. */
7035 static void
7036 note_mode_line_highlight (w, x, mode_line_p)
7037 struct window *w;
7038 int 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;
7045 if (mode_line_p)
7046 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
7047 else
7048 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
7050 if (row->enabled_p)
7052 struct glyph *glyph, *end;
7053 Lisp_Object help, map;
7054 int x0;
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));
7062 while (glyph < end
7063 && x >= x0 + glyph->pixel_width)
7065 x0 += glyph->pixel_width;
7066 ++glyph;
7069 if (glyph < end
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);
7080 if (!NILP (help))
7082 help_echo = help;
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);
7091 if (KEYMAPP (map))
7092 cursor = f->output_data.mac->nontext_cursor;
7093 else
7095 map = Fget_text_property (make_number (glyph->charpos),
7096 Qkeymap, glyph->object);
7097 if (KEYMAPP (map))
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);
7105 #endif
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. */
7114 static void
7115 note_mouse_highlight (f, x, y)
7116 struct frame *f;
7117 int x, y;
7119 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7120 int portion;
7121 Lisp_Object window;
7122 struct window *w;
7123 struct buffer *b;
7125 #if 0
7126 /* When a menu is active, don't highlight because this looks odd. */
7127 if (popup_activated ())
7128 return;
7129 #endif
7131 if (NILP (Vmouse_highlight)
7132 || !f->glyphs_initialized_p)
7133 return;
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)
7140 return;
7142 if (gc_in_progress)
7144 dpyinfo->mouse_face_deferred_gc = 1;
7145 return;
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))
7157 return;
7159 /* Reset help_echo. It will get recomputed below. */
7160 help_echo = Qnil;
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
7167 buffer. */
7168 if (EQ (window, f->tool_bar_window))
7170 note_tool_bar_highlight (f, x, y);
7171 return;
7174 /* Mouse is on the mode or header line? */
7175 if (portion == 1 || portion == 3)
7177 note_mode_line_highlight (w, x, portion == 1);
7178 return;
7180 #if 0 /* TODO: mouse cursor */
7181 if (portion == 2)
7182 cursor = f->output_data.x->horizontal_drag_cursor;
7183 else
7184 cursor = f->output_data.x->text_cursor;
7185 #endif
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. */
7190 portion == 0
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;
7197 Lisp_Object object;
7198 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7199 Lisp_Object *overlay_vec = NULL;
7200 int len, noverlays;
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. */
7208 if (glyph == NULL
7209 || area != TEXT_AREA
7210 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7212 clear_mouse_face (dpyinfo);
7213 /* TODO: mouse cursor */
7214 goto set_cursor;
7217 pos = glyph->charpos;
7218 object = glyph->object;
7219 if (!STRINGP (object) && !BUFFERP (object))
7220 goto set_cursor;
7222 /* If we get an out-of-range value, return now; avoid an error. */
7223 if (BUFFERP (object) && pos > BUF_Z (b))
7224 goto set_cursor;
7226 /* Make the window's buffer temporarily current for
7227 overlays_at and compute_char_face. */
7228 obuf = current_buffer;
7229 current_buffer = b;
7230 obegv = BEGV;
7231 ozv = ZV;
7232 BEGV = BEG;
7233 ZV = Z;
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. */
7243 len = 10;
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)
7248 len = noverlays;
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);
7256 else
7257 noverlays = 0;
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)
7269 mouse cursor */
7271 /* Check mouse-face highlighting. */
7272 if (! same_region
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
7276 highlight that. */
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
7281 property. */
7282 overlay = Qnil;
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. */
7292 if (!NILP (overlay)
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. */
7303 if (NILP (overlay))
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;
7312 int ignore;
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,
7333 &ignore, pos + 1,
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;
7346 int ignore;
7348 beginning = Fmarker_position (w->start);
7349 end = make_number (BUF_Z (XBUFFER (object))
7350 - XFASTINT (w->window_end_pos));
7351 before
7352 = Fprevious_single_property_change (make_number (pos + 1),
7353 Qmouse_face,
7354 object, beginning);
7355 after
7356 = Fnext_single_property_change (position, Qmouse_face,
7357 object, end);
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,
7376 &ignore, pos + 1,
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))
7385 Lisp_Object b, e;
7386 int ignore;
7388 b = Fprevious_single_property_change (make_number (pos + 1),
7389 Qmouse_face,
7390 object, Qnil);
7391 e = Fnext_single_property_change (position, Qmouse_face,
7392 object, Qnil);
7393 if (NILP (b))
7394 b = make_number (0);
7395 if (NILP (e))
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,
7411 glyph->face_id, 1);
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);
7423 if (pos > 0)
7424 mouse_face = get_char_property_and_overlay (make_number (pos),
7425 Qmouse_face,
7426 w->buffer,
7427 &overlay);
7428 if (!NILP (mouse_face) && !NILP (overlay))
7430 Lisp_Object before = Foverlay_start (overlay);
7431 Lisp_Object after = Foverlay_end (overlay);
7432 int ignore;
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,
7444 object);
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,
7452 Qnil);
7453 dpyinfo->mouse_face_window = window;
7454 dpyinfo->mouse_face_face_id
7455 = face_at_buffer_position (w, pos, 0, 0,
7456 &ignore, pos + 1,
7457 !dpyinfo->mouse_face_hidden);
7459 /* Display it as active. */
7460 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7461 /* TODO: mouse cursor changes. */
7466 check_help_echo:
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);
7480 if (!NILP (help))
7482 help_echo = help;
7483 help_echo_window = window;
7484 help_echo_object = overlay;
7485 help_echo_pos = pos;
7487 else
7489 Lisp_Object object = glyph->object;
7490 int charpos = glyph->charpos;
7492 /* Try text properties. */
7493 if (STRINGP (object)
7494 && charpos >= 0
7495 && charpos < SCHARS (object))
7497 help = Fget_text_property (make_number (charpos),
7498 Qhelp_echo, object);
7499 if (NILP (help))
7501 /* If the string itself doesn't specify a help-echo,
7502 see if the buffer text ``under'' it does. */
7503 struct glyph_row *r
7504 = MATRIX_ROW (w->current_matrix, vpos);
7505 int start = MATRIX_ROW_START_CHARPOS (r);
7506 int pos = string_buffer_position (w, object, start);
7507 if (pos > 0)
7509 help = Fget_char_property (make_number (pos),
7510 Qhelp_echo, w->buffer);
7511 if (!NILP (help))
7513 charpos = pos;
7514 object = w->buffer;
7519 else if (BUFFERP (object)
7520 && charpos >= BEGV
7521 && charpos < ZV)
7522 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7523 object);
7525 if (!NILP (help))
7527 help_echo = help;
7528 help_echo_window = window;
7529 help_echo_object = object;
7530 help_echo_pos = charpos;
7535 BEGV = obegv;
7536 ZV = ozv;
7537 current_buffer = obuf;
7540 set_cursor:
7541 /* TODO: mouse cursor changes. */
7545 static void
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 /***********************************************************************
7558 Tool-bars
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
7565 or -1. */
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.
7578 1 otherwise. */
7580 static int
7581 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7582 struct frame *f;
7583 int x, y;
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);
7589 int area;
7591 /* Find the glyph under X/Y. */
7592 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7593 if (*glyph == NULL)
7594 return -1;
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))
7599 return -1;
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))
7610 return 0;
7612 return 1;
7616 /* Handle mouse button event on the tool-bar of frame F, at
7617 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7618 or ButtonRelase. */
7620 static void
7621 x_handle_tool_bar_click (f, button_event)
7622 struct frame *f;
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)
7636 return;
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))
7641 return;
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;
7650 else
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;
7664 event.arg = frame;
7665 kbd_buffer_store_event (&event);
7667 event.kind = TOOL_BAR_EVENT;
7668 event.frame_or_window = frame;
7669 event.arg = key;
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. */
7682 static void
7683 note_tool_bar_highlight (f, x, y)
7684 struct frame *f;
7685 int 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);
7690 int hpos, vpos;
7691 struct glyph *glyph;
7692 struct glyph_row *row;
7693 int i;
7694 Lisp_Object enabled_p;
7695 int prop_idx;
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);
7704 return;
7707 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7708 if (rc < 0)
7710 /* Not on tool-bar item. */
7711 clear_mouse_face (dpyinfo);
7712 return;
7714 else if (rc == 0)
7715 /* On same tool-bar item as before. */
7716 goto set_help_echo;
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));
7724 if (mouse_down_p
7725 && last_tool_bar_item != prop_idx)
7726 return;
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;
7760 set_help_echo:
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;
7765 help_echo_pos = -1;
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. */
7786 static int
7787 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7788 struct window *w;
7789 int charpos;
7790 int *hpos, *vpos, *x, *y;
7791 Lisp_Object stop;
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);
7799 if (row == NULL)
7801 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7803 *x = *y = *hpos = *vpos = 0;
7804 return 0;
7806 else
7808 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7809 past_end = 1;
7813 *x = row->x;
7814 *y = row->y;
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
7822 frames. */
7823 if (row->displays_text_p)
7824 while (glyph < end
7825 && INTEGERP (glyph->object)
7826 && !EQ (stop, glyph->object)
7827 && glyph->charpos < 0)
7829 *x += glyph->pixel_width;
7830 ++glyph;
7833 while (glyph < end
7834 && !INTEGERP (glyph->object)
7835 && !EQ (stop, glyph->object)
7836 && (!BUFFERP (glyph->object)
7837 || glyph->charpos < charpos))
7839 *x += glyph->pixel_width;
7840 ++glyph;
7843 *hpos = glyph - row->glyphs[TEXT_AREA];
7844 return past_end;
7847 #else /* not 0 */
7849 static int
7850 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7851 struct window *w;
7852 int pos;
7853 int *hpos, *vpos, *x, *y;
7854 Lisp_Object stop;
7856 int i;
7857 int lastcol;
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;
7863 int current_x;
7865 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7866 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7868 while (row->y < yb)
7870 if (row->used[TEXT_AREA])
7871 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7872 else
7873 line_start_position = 0;
7875 if (line_start_position > pos)
7876 break;
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;
7883 break;
7885 else if (line_start_position > 0)
7887 best_row = row;
7888 best_row_vpos = row_vpos;
7891 if (row->y + row->height >= yb)
7892 break;
7894 ++row;
7895 ++row_vpos;
7898 /* Find the right column within BEST_ROW. */
7899 lastcol = 0;
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))
7908 if (charpos == pos)
7910 *hpos = i;
7911 *vpos = best_row_vpos;
7912 *x = current_x;
7913 *y = best_row->y;
7914 return 1;
7916 else if (charpos > pos)
7917 break;
7919 else if (EQ (glyph->object, stop))
7920 break;
7922 if (charpos > 0)
7923 lastcol = i;
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)
7932 ++best_row;
7933 ++best_row_vpos;
7934 lastcol = 0;
7935 current_x = best_row->x;
7938 *vpos = best_row_vpos;
7939 *hpos = lastcol + 1;
7940 *x = current_x;
7941 *y = best_row->y;
7942 return 0;
7945 #endif /* not 0 */
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. */
7963 static int
7964 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7965 struct window *w;
7966 int pos;
7967 Lisp_Object object;
7968 int *hpos, *vpos, *x, *y;
7969 int right_p;
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;
7975 int best_x = 0;
7977 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7978 r->enabled_p && r->y < yb;
7979 ++r)
7981 struct glyph *g = r->glyphs[TEXT_AREA];
7982 struct glyph *e = g + r->used[TEXT_AREA];
7983 int gx;
7985 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7986 if (EQ (g->object, object))
7988 if (g->charpos == pos)
7990 best_glyph = g;
7991 best_x = gx;
7992 best_row = r;
7993 goto found;
7995 else if (best_glyph == NULL
7996 || ((abs (g->charpos - pos)
7997 < abs (best_glyph->charpos - pos))
7998 && (right_p
7999 ? g->charpos < pos
8000 : g->charpos > pos)))
8002 best_glyph = g;
8003 best_x = gx;
8004 best_row = r;
8009 found:
8011 if (best_glyph)
8013 *x = best_x;
8014 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
8016 if (right_p)
8018 *x += best_glyph->pixel_width;
8019 ++*hpos;
8022 *y = best_row->y;
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. */
8033 static void
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
8042 to do anything. */
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. */
8061 if (row == first)
8063 start_hpos = dpyinfo->mouse_face_beg_col;
8064 start_x = dpyinfo->mouse_face_beg_x;
8066 else
8068 start_hpos = 0;
8069 start_x = 0;
8072 if (row == last)
8073 end_hpos = dpyinfo->mouse_face_end_col;
8074 else
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);
8082 row->mouse_face_p
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);
8103 else
8104 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8105 f->output_data.x->nontext_cursor);
8106 #endif
8109 /* Clear out the mouse-highlighted active region.
8110 Redraw it un-highlighted first. */
8112 static int
8113 clear_mouse_face (dpyinfo)
8114 struct mac_display_info *dpyinfo;
8116 int cleared = 0;
8118 if (! NILP (dpyinfo->mouse_face_window))
8120 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8121 cleared = 1;
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;
8128 return cleared;
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. */
8136 static void
8137 x_clear_mouse_face (w)
8138 struct window *w;
8140 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8141 Lisp_Object window;
8143 BLOCK_INPUT;
8144 XSETWINDOW (window, w);
8145 if (EQ (window, dpyinfo->mouse_face_window))
8146 clear_mouse_face (dpyinfo);
8147 UNBLOCK_INPUT;
8151 /* Just discard the mouse face information for frame F, if any.
8152 This is used when the size of F is changed. */
8154 void
8155 cancel_mouse_face (f)
8156 FRAME_PTR f;
8158 Lisp_Object window;
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
8180 values. */
8182 static int
8183 glyph_rect (f, x, y, rect)
8184 struct frame *f;
8185 int x, y;
8186 Rect *rect;
8188 Lisp_Object window;
8189 int part;
8191 window = window_from_coordinates (f, x, y, &part, 0);
8192 if (!NILP (window))
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];
8206 int gx;
8208 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8209 rect->bottom = rect->top + r->height;
8211 if (x < r->x)
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);
8216 return 1;
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;
8225 return 1;
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);
8231 return 1;
8235 /* The y is not on any row. */
8236 return 0;
8239 /* Record the position of the mouse in last_mouse_glyph. */
8240 static void
8241 remember_mouse_glyph (f1, gx, gy)
8242 struct frame * f1;
8243 int 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. */
8252 if (gx < 0)
8253 gx -= width - 1;
8254 if (gy < 0)
8255 gy -= height - 1;
8256 #if 0
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;
8262 #else
8263 gx = gx / width * width;
8264 gy = gy / height * height;
8265 #endif
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
8284 the mouse is over.
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
8292 movement. */
8294 static void
8295 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8296 FRAME_PTR *fp;
8297 int insist;
8298 Lisp_Object *bar_window;
8299 enum scroll_bar_part *part;
8300 Lisp_Object *x, *y;
8301 unsigned long *time;
8303 Point mouse_pos;
8304 int ignore1, ignore2;
8305 WindowPtr wp = FrontWindow ();
8306 struct frame *f;
8307 Lisp_Object frame, tail;
8309 if (is_emacs_window(wp))
8310 f = ((mac_output *) GetWRefCon (wp))->mFP;
8312 BLOCK_INPUT;
8314 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8315 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8316 else
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));
8326 #else
8327 SetPort (wp);
8328 #endif
8330 GetMouse (&mouse_pos);
8332 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8333 &last_mouse_glyph, insist);
8335 *bar_window = Qnil;
8336 *part = scroll_bar_handle;
8337 *fp = f;
8338 XSETINT (*x, mouse_pos.h);
8339 XSETINT (*y, mouse_pos.v);
8340 *time = last_mouse_movement_time;
8343 UNBLOCK_INPUT;
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
8354 scroll bar. */
8356 static struct scroll_bar *
8357 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8358 struct window *w;
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));
8364 Rect r;
8365 ControlHandle ch;
8367 BLOCK_INPUT;
8369 r.left = left;
8370 r.top = disp_top;
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);
8377 #else
8378 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8379 0L);
8380 #endif
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);
8395 bar->prev = Qnil;
8396 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8397 if (!NILP (bar->next))
8398 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8400 UNBLOCK_INPUT;
8401 return 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
8410 events.)
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. */
8418 static void
8419 x_scroll_bar_set_handle (bar, start, end, rebuild)
8420 struct scroll_bar *bar;
8421 int start, end;
8422 int rebuild;
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. */
8431 if (! rebuild
8432 && start == XINT (bar->start)
8433 && end == XINT (bar->end))
8434 return;
8436 BLOCK_INPUT;
8438 /* Make sure the values are reasonable, and try to preserve the
8439 distance between start and end. */
8440 if (start < 0)
8441 start = 0;
8442 else if (start > top_range)
8443 start = top_range;
8444 end = start + length;
8446 if (end < start)
8447 end = start;
8448 else if (end > top_range && ! dragging)
8449 end = top_range;
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)
8457 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
8468 - (end - start));
8469 SetControlValue (ch, start);
8470 #if TARGET_API_MAC_CARBON
8471 SetControlViewSize (ch, end - start);
8472 #endif
8474 UNBLOCK_INPUT;
8478 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8479 nil. */
8481 static void
8482 x_scroll_bar_remove (bar)
8483 struct scroll_bar *bar;
8485 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8487 BLOCK_INPUT;
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;
8495 UNBLOCK_INPUT;
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,
8501 create one. */
8502 static void
8503 XTset_vertical_scroll_bar (w, portion, whole, position)
8504 struct window *w;
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);
8514 top = window_y;
8515 #ifdef MAC_OSX
8516 width = 16;
8517 #else
8518 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8519 #endif
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);
8525 else
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);
8534 else
8535 sb_width = width;
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;
8540 else
8541 sb_left = left + (width - sb_width) / 2;
8543 /* Adjustments according to Inside Macintosh to make it look nice */
8544 disp_top = top;
8545 disp_height = height;
8546 if (disp_top == 0)
8548 disp_top = -1;
8549 disp_height++;
8551 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8553 disp_top++;
8554 disp_height--;
8557 if (sb_left + sb_width == PIXEL_WIDTH (f))
8558 sb_left++;
8560 /* Does the scroll bar exist yet? */
8561 if (NILP (w->vertical_scroll_bar))
8563 BLOCK_INPUT;
8564 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8565 left, top, width, height, 0);
8566 UNBLOCK_INPUT;
8567 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8568 disp_height);
8569 XSETVECTOR (w->vertical_scroll_bar, bar);
8571 else
8573 /* It may just need to be moved and resized. */
8574 ControlHandle ch;
8576 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8577 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8579 BLOCK_INPUT;
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)
8586 Draw1Control (ch);
8587 else
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
8592 example. */
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);
8597 #if 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);
8601 #endif
8603 HideControl (ch);
8604 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8605 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8606 disp_height);
8607 ShowControl (ch);
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);
8616 UNBLOCK_INPUT;
8619 /* Set the scroll bar's current state, unless we're currently being
8620 dragged. */
8621 if (NILP (bar->dragging))
8623 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8625 if (whole == 0)
8626 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8627 else
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. */
8649 static void
8650 XTcondemn_scroll_bars (frame)
8651 FRAME_PTR frame;
8653 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8654 while (! NILP (FRAME_SCROLL_BARS (frame)))
8656 Lisp_Object bar;
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. */
8671 static void
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))
8679 abort ();
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
8690 the lists. */
8691 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8692 /* It's not condemned. Everything's fine. */
8693 return;
8694 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8695 window->vertical_scroll_bar))
8696 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8697 else
8698 /* If its prev pointer is nil, it must be at the front of
8699 one or the other! */
8700 abort ();
8702 else
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);
8709 bar->prev = Qnil;
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'. */
8719 static void
8720 XTjudge_scroll_bars (f)
8721 FRAME_PTR 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);
8737 next = b->next;
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. */
8746 static void
8747 activate_scroll_bars (frame)
8748 FRAME_PTR frame;
8750 Lisp_Object bar;
8751 ControlHandle ch;
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);
8759 #else
8760 SetControlMaximum (ch,
8761 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8762 XINT (XSCROLL_BAR (bar)
8763 ->height)) - 1);
8764 #endif
8765 bar = XSCROLL_BAR (bar)->next;
8770 static void
8771 deactivate_scroll_bars (frame)
8772 FRAME_PTR frame;
8774 Lisp_Object bar;
8775 ControlHandle ch;
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);
8783 #else
8784 SetControlMaximum (ch, XINT (-1));
8785 #endif
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
8794 mark bits. */
8796 static void
8797 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8798 struct scroll_bar *bar;
8799 int part_code;
8800 EventRecord *er;
8801 struct input_event *bufp;
8803 if (! GC_WINDOWP (bar->window))
8804 abort ();
8806 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8807 bufp->frame_or_window = bar->window;
8808 bufp->arg = Qnil;
8810 bar->dragging = Qnil;
8812 switch (part_code)
8814 case kControlUpButtonPart:
8815 bufp->part = scroll_bar_up_arrow;
8816 break;
8817 case kControlDownButtonPart:
8818 bufp->part = scroll_bar_down_arrow;
8819 break;
8820 case kControlPageUpPart:
8821 bufp->part = scroll_bar_above_handle;
8822 break;
8823 case kControlPageDownPart:
8824 bufp->part = scroll_bar_below_handle;
8825 break;
8826 #ifdef TARGET_API_MAC_CARBON
8827 default:
8828 #else
8829 case kControlIndicatorPart:
8830 #endif
8831 if (er->what == mouseDown)
8832 bar->dragging = make_number (0);
8833 XSETVECTOR (last_mouse_scroll_bar, bar);
8834 bufp->part = scroll_bar_handle;
8835 break;
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
8843 mark bits. */
8845 static void
8846 x_scroll_bar_note_movement (bar, y_pos, t)
8847 struct scroll_bar *bar;
8848 int y_pos;
8849 Time t;
8851 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8853 last_mouse_movement_time = t;
8855 f->mouse_moved = 1;
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. */
8877 static void
8878 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8879 FRAME_PTR *fp;
8880 Lisp_Object *bar_window;
8881 enum scroll_bar_part *part;
8882 Lisp_Object *x, *y;
8883 unsigned long *time;
8885 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8886 WindowPtr wp = FrontWindow ();
8887 Point mouse_pos;
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));
8893 #else
8894 SetPort (wp);
8895 #endif
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;
8904 win_y -= 24;
8906 if (! NILP (bar->dragging))
8907 win_y -= XINT (bar->dragging);
8909 if (win_y < 0)
8910 win_y = 0;
8911 if (win_y > top_range)
8912 win_y = top_range;
8914 *fp = f;
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;
8923 else
8924 *part = scroll_bar_below_handle;
8926 XSETINT (*x, win_y);
8927 XSETINT (*y, top_range);
8929 f->mouse_moved = 0;
8930 last_mouse_scroll_bar = Qnil;
8932 *time = last_mouse_movement_time;
8935 /***********************************************************************
8936 Text Cursor
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. */
8945 static void
8946 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8947 struct window *w;
8948 enum glyph_row_area area;
8949 int x0, x1, y0, y1;
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. */
8970 static void
8971 x_clip_to_row (w, row, gc, whole_line_p)
8972 struct window *w;
8973 struct glyph_row *row;
8974 GC gc;
8975 int whole_line_p;
8977 struct frame *f = XFRAME (WINDOW_FRAME (w));
8978 Rect clip_rect;
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. */
8991 if (whole_line_p)
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. */
9003 static void
9004 x_draw_hollow_cursor (w, row)
9005 struct window *w;
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);
9011 int x, y, wd, h;
9012 XGCValues xgcv;
9013 struct glyph *cursor_glyph;
9014 GC gc;
9016 /* Compute frame-relative coordinates from window-relative
9017 coordinates. */
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)
9027 return;
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
9032 width instead. */
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);
9043 else
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.
9060 --gerd. */
9062 static void
9063 x_draw_bar_cursor (w, row, width)
9064 struct window *w;
9065 struct glyph_row *row;
9066 int width;
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;
9075 GC gc;
9076 int x;
9077 unsigned long mask;
9078 XGCValues xgcv;
9079 Display *dpy;
9080 Window window;
9082 cursor_glyph = get_phys_cursor_glyph (w);
9083 if (cursor_glyph == NULL)
9084 return;
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;
9093 if (gc)
9094 XChangeGC (dpy, gc, mask, &xgcv);
9095 else
9097 gc = XCreateGC (dpy, window, mask, &xgcv);
9098 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9101 if (width < 0)
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),
9110 row->height);
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. */
9120 static void
9121 x_clear_cursor (w)
9122 struct window *w;
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. */
9132 static void
9133 x_draw_phys_cursor_glyph (w, row, hl)
9134 struct window *w;
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,
9146 hl, 0);
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
9151 are redrawn. */
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. */
9168 static void
9169 x_erase_phys_cursor (w)
9170 struct window *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
9183 screen. */
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
9193 can do. */
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)
9231 int x;
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,
9243 cursor_row->y)),
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;
9252 else
9253 hl = DRAW_NORMAL_TEXT;
9254 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9256 mark_cursor_off:
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. */
9264 static int
9265 cursor_in_mouse_face_p (w)
9266 struct window *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))
9285 in_mouse_face = 1;
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. */
9296 void
9297 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9298 struct window *w;
9299 int on, hpos, vpos, x, y;
9301 struct frame *f = XFRAME (w->frame);
9302 int new_cursor_type;
9303 int new_cursor_width;
9304 int active_cursor;
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
9312 window. */
9313 if (! FRAME_VISIBLE_P (f)
9314 || FRAME_GARBAGED_P (f)
9315 || vpos >= w->current_matrix->nrows
9316 || hpos >= w->current_matrix->matrix_w)
9317 return;
9319 /* If cursor is off and we want it off, return quickly. */
9320 if (!on && !w->phys_cursor_on_p)
9321 return;
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;
9332 return;
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,
9343 erase it. */
9344 if (w->phys_cursor_on_p
9345 && (!on
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,
9354 display it. */
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);
9374 break;
9376 case FILLED_BOX_CURSOR:
9377 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9378 break;
9380 case HBAR_CURSOR:
9381 /* TODO. For now, just draw bar cursor. */
9382 case BAR_CURSOR:
9383 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9384 break;
9386 case NO_CURSOR:
9387 break;
9389 default:
9390 abort ();
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. */
9402 void
9403 x_display_cursor (w, on, hpos, vpos, x, y)
9404 struct window *w;
9405 int on, hpos, vpos, x, y;
9407 BLOCK_INPUT;
9408 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9409 UNBLOCK_INPUT;
9413 /* Display the cursor on window W, or clear it, according to ON_P.
9414 Don't change the cursor's position. */
9416 void
9417 x_update_cursor (f, on_p)
9418 struct frame *f;
9419 int 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. */
9428 static void
9429 x_update_cursor_in_window_tree (w, on_p)
9430 struct window *w;
9431 int on_p;
9433 while (w)
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);
9439 else
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
9448 of ON. */
9450 static void
9451 x_update_window_cursor (w, on)
9452 struct window *w;
9453 int on;
9455 /* Don't update cursor in windows whose frame is in the process
9456 of being deleted. */
9457 if (w->current_matrix)
9459 BLOCK_INPUT;
9460 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9461 w->phys_cursor.vpos, w->phys_cursor.x,
9462 w->phys_cursor.y);
9463 UNBLOCK_INPUT;
9470 /* Icons. */
9472 #if 0 /* MAC_TODO: no icon support yet. */
9474 x_bitmap_icon (f, icon)
9475 struct frame *f;
9476 Lisp_Object icon;
9478 HANDLE hicon;
9480 if (FRAME_W32_WINDOW (f) == 0)
9481 return 1;
9483 if (NILP (icon))
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))
9490 LPCTSTR name;
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;
9504 else
9505 return 1;
9507 hicon = LoadIcon (NULL, name);
9509 else
9510 return 1;
9512 if (hicon == NULL)
9513 return 1;
9515 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9516 (LPARAM) hicon);
9518 return 0;
9520 #endif /* MAC_TODO */
9522 /************************************************************************
9523 Handling X errors
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)
9536 x_trace_wire ()
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. */
9553 Lisp_Object
9554 x_new_font (f, fontname)
9555 struct frame *f;
9556 register char *fontname;
9558 struct font_info *fontp
9559 = FS_LOAD_FONT (f, 0, fontname, -1);
9561 if (!fontp)
9562 return Qnil;
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;
9574 else
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);
9594 else
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. */
9607 Lisp_Object
9608 x_new_fontset (f, fontsetname)
9609 struct frame *f;
9610 char *fontsetname;
9612 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9613 Lisp_Object result;
9615 if (fontset < 0)
9616 return Qnil;
9618 if (FRAME_FONTSET (f) == fontset)
9619 /* This fontset is already set in frame F. There's nothing more
9620 to do. */
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. */
9627 return Qnil;
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 */
9637 void
9638 x_compute_fringe_widths (f, redraw)
9639 struct frame *f;
9640 int 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;
9682 else
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;
9697 else
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;
9705 else
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)
9717 redraw_frame (f);
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)
9727 struct xim_inst_t
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. */
9738 void
9739 x_calc_absolute_position (f)
9740 struct frame *f;
9742 Point pt;
9743 int flags = f->output_data.mac->size_hint_flags;
9745 pt.h = pt.v = 0;
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)
9751 GrafPtr savePort;
9752 GetPort (&savePort);
9754 #if TARGET_API_MAC_CARBON
9755 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9756 #else
9757 SetPort (FRAME_MAC_WINDOW (f));
9758 #endif
9760 #if TARGET_API_MAC_CARBON
9762 Rect r;
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);
9771 SetPort (savePort);
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
9779 - PIXEL_WIDTH (f)
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
9785 - PIXEL_HEIGHT (f)
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. */
9799 void
9800 x_set_offset (f, xoff, yoff, change_gravity)
9801 struct frame *f;
9802 register int xoff, yoff;
9803 int change_gravity;
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);
9812 if (xoff < 0)
9813 f->output_data.mac->size_hint_flags |= XNegative;
9814 if (yoff < 0)
9815 f->output_data.mac->size_hint_flags |= YNegative;
9816 f->output_data.mac->win_gravity = NorthWestGravity;
9818 x_calc_absolute_position (f);
9820 BLOCK_INPUT;
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);
9829 UNBLOCK_INPUT;
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. */
9837 void
9838 x_set_window_size (f, change_gravity, cols, rows)
9839 struct frame *f;
9840 int change_gravity;
9841 int cols, rows;
9843 int pixelwidth, pixelheight;
9845 BLOCK_INPUT;
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
9875 a BLOCK_INPUT. */
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);
9897 UNBLOCK_INPUT;
9900 /* Mouse warping. */
9902 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9904 void
9905 x_set_mouse_position (f, x, y)
9906 struct frame *f;
9907 int x, y;
9909 int pix_x, pix_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);
9923 void
9924 x_set_mouse_pixel_position (f, pix_x, pix_y)
9925 struct frame *f;
9926 int pix_x, pix_y;
9928 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9929 BLOCK_INPUT;
9931 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9932 0, 0, 0, 0, pix_x, pix_y);
9933 UNBLOCK_INPUT;
9934 #endif
9938 /* focus shifting, raising and lowering. */
9940 void
9941 x_focus_on_frame (f)
9942 struct frame *f;
9944 #if 0 /* This proves to be unpleasant. */
9945 x_raise_frame (f);
9946 #endif
9947 #if 0
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);
9953 #endif /* ! 0 */
9956 void
9957 x_unfocus_frame (f)
9958 struct frame *f;
9962 /* Raise frame F. */
9963 void
9964 x_raise_frame (f)
9965 struct frame *f;
9967 if (f->async_visible)
9968 SelectWindow (FRAME_MAC_WINDOW (f));
9971 /* Lower frame F. */
9972 void
9973 x_lower_frame (f)
9974 struct frame *f;
9976 if (f->async_visible)
9977 SendBehind (FRAME_MAC_WINDOW (f), nil);
9980 static void
9981 XTframe_raise_lower (f, raise_flag)
9982 FRAME_PTR f;
9983 int raise_flag;
9985 if (raise_flag)
9986 x_raise_frame (f);
9987 else
9988 x_lower_frame (f);
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. */
10000 void
10001 x_make_frame_visible (f)
10002 struct frame *f;
10004 Lisp_Object type;
10005 int original_top, original_left;
10007 BLOCK_INPUT;
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. */
10032 Lisp_Object frame;
10033 int count;
10035 /* This must come after we set COUNT. */
10036 UNBLOCK_INPUT;
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. */
10047 x_sync (f);
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
10054 probably a bug. */
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). */
10078 void
10079 x_make_frame_invisible (f)
10080 struct frame *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;
10086 BLOCK_INPUT;
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. */
10095 f->visible = 0;
10096 FRAME_ICONIFIED_P (f) = 0;
10097 f->async_visible = 0;
10098 f->async_iconified = 0;
10100 UNBLOCK_INPUT;
10103 /* Change window state from mapped to iconified. */
10105 void
10106 x_iconify_frame (f)
10107 struct 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;
10113 #if 0
10114 /* Review: Since window is still visible in dock, still allow updates? */
10115 if (f->async_iconified)
10116 return;
10117 #endif
10119 BLOCK_INPUT;
10121 CollapseWindow (FRAME_MAC_WINDOW (f), true);
10123 UNBLOCK_INPUT;
10127 /* Destroy the X window of frame F. */
10129 void
10130 x_destroy_window (f)
10131 struct frame *f;
10133 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10135 BLOCK_INPUT;
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;
10164 UNBLOCK_INPUT;
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). */
10174 void
10175 x_wm_set_size_hint (f, flags, user_position)
10176 struct frame *f;
10177 long flags;
10178 int user_position;
10180 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10181 XSizeHints size_hints;
10183 #ifdef USE_X_TOOLKIT
10184 Arg al[2];
10185 int ac = 0;
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. */
10240 #ifdef HAVE_X11R4
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;
10246 #else
10247 size_hints.min_width = base_width;
10248 size_hints.min_height = base_height;
10249 #endif
10252 /* If we don't need the old flags, we don't need the old hint at all. */
10253 if (flags)
10255 size_hints.flags |= flags;
10256 goto no_read;
10258 #endif /* not USE_X_TOOLKIT */
10261 XSizeHints hints; /* Sometimes I hate X Windows... */
10262 long supplied_return;
10263 int value;
10265 #ifdef HAVE_X11R4
10266 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10267 &supplied_return);
10268 #else
10269 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10270 #endif
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;
10277 #endif
10279 if (flags)
10280 size_hints.flags |= flags;
10281 else
10283 if (value == 0)
10284 hints.flags = 0;
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
10297 no_read:
10298 #endif
10300 #ifdef PWinGravity
10301 size_hints.win_gravity = f->output_data.x->win_gravity;
10302 size_hints.flags |= PWinGravity;
10304 if (user_position)
10306 size_hints.flags &= ~ PPosition;
10307 size_hints.flags |= USPosition;
10309 #endif /* PWinGravity */
10311 #ifdef HAVE_X11R4
10312 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10313 #else
10314 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10315 #endif
10316 #endif /* MAC_TODO */
10319 #if 0 /* MAC_TODO: hide application instead of iconify? */
10320 /* Used for IconicState or NormalState */
10322 void
10323 x_wm_set_window_state (f, state)
10324 struct frame *f;
10325 int state;
10327 #ifdef USE_X_TOOLKIT
10328 Arg al[1];
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 */
10342 void
10343 x_wm_set_icon_pixmap (f, pixmap_id)
10344 struct frame *f;
10345 int pixmap_id;
10347 Pixmap icon_pixmap;
10349 #ifndef USE_X_TOOLKIT
10350 Window window = FRAME_X_WINDOW (f);
10351 #endif
10353 if (pixmap_id > 0)
10355 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10356 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10358 else
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. */
10367 #if 0
10368 f->output_data.x->wm_hints.icon_pixmap = None;
10369 #else
10370 return;
10371 #endif
10374 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10377 Arg al[1];
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 */
10392 void
10393 x_wm_set_icon_position (f, icon_x, icon_y)
10394 struct frame *f;
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);
10400 #else
10401 Window window = FRAME_X_WINDOW (f);
10402 #endif
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 /***********************************************************************
10414 Fonts
10415 ***********************************************************************/
10417 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10419 struct font_info *
10420 x_get_font_info (f, font_idx)
10421 FRAME_PTR f;
10422 int 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 */
10433 static int
10434 stricmp (const char *s, const char *t)
10436 for ( ; tolower (*s) == tolower (*t); s++, t++)
10437 if (*s == '\0')
10438 return 0;
10439 return tolower (*s) - tolower (*t);
10442 /* compare two strings ignoring case and handling wildcard */
10443 static int
10444 wildstrieq (char *s1, char *s2)
10446 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10447 return true;
10449 return stricmp (s1, s2) == 0;
10452 /* Assume parameter 1 is fully qualified, no wildcards. */
10453 static int
10454 mac_font_pattern_match (fontname, pattern)
10455 char * fontname;
10456 char * pattern;
10458 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10459 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10460 char *ptr;
10462 /* Copy fontname so we can modify it during comparison. */
10463 strcpy (font_name_copy, fontname);
10465 ptr = regex;
10466 *ptr++ = '^';
10468 /* Turn pattern into a regexp and do a regexp match. */
10469 for (; *pattern; pattern++)
10471 if (*pattern == '?')
10472 *ptr++ = '.';
10473 else if (*pattern == '*')
10475 *ptr++ = '.';
10476 *ptr++ = '*';
10478 else
10479 *ptr++ = *pattern;
10481 *ptr = '$';
10482 *(ptr + 1) = '\0';
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. */
10490 static int
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);
10513 static char *
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");
10528 break;
10529 case smSimpChinese:
10530 strcpy(cs, "gb2312.1980-0");
10531 break;
10532 case smJapanese:
10533 strcpy(cs, "jisx0208.1983-sjis");
10534 break;
10535 case -smJapanese:
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");
10543 break;
10544 case smKorean:
10545 strcpy(cs, "ksc5601.1989-0");
10546 break;
10547 default:
10548 strcpy(cs, "mac-roman");
10549 break;
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++)
10560 *p = tolower(*p);
10561 return result;
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. */
10572 static void
10573 x_font_name_to_mac_font_name (char *xf, char *mf)
10575 char foundry[32], family[32], weight[20], slant[2], cs[32];
10577 strcpy (mf, "");
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)
10583 return;
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);
10590 else
10591 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10595 static void
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
10618 needed. */
10620 static void
10621 init_font_name_table ()
10623 #if TARGET_API_MAC_CARBON
10624 SInt32 sv;
10626 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10628 FMFontFamilyIterator ffi;
10629 FMFontFamilyInstanceIterator ffii;
10630 FMFontFamily ff;
10632 /* Create a dummy instance iterator here to avoid creating and
10633 destroying it in the loop. */
10634 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10635 return;
10636 /* Create an iterator to enumerate the font families. */
10637 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10638 != noErr)
10640 FMDisposeFontFamilyInstanceIterator (&ffii);
10641 return;
10644 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10646 Str255 name;
10647 FMFont font;
10648 FMFontStyle style;
10649 FMFontSize size;
10650 SInt16 sc;
10652 if (FMGetFontFamilyName (ff, name) != noErr)
10653 break;
10654 p2cstr (name);
10656 sc = FontToScript (ff);
10658 /* Point the instance iterator at the current font family. */
10659 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10660 break;
10662 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10663 == noErr)
10664 if (size == 0)
10666 add_font_name_table_entry (mac_to_x_fontname (name, size,
10667 style, sc));
10668 add_font_name_table_entry (mac_to_x_fontname (name, size,
10669 italic, sc));
10670 add_font_name_table_entry (mac_to_x_fontname (name, size,
10671 bold, sc));
10672 add_font_name_table_entry (mac_to_x_fontname (name, size,
10673 italic | bold,
10674 sc));
10676 else
10678 add_font_name_table_entry (mac_to_x_fontname (name, size,
10679 style, sc));
10680 if (smJapanese == sc)
10681 add_font_name_table_entry (mac_to_x_fontname (name, size,
10682 style,
10683 -smJapanese));
10687 /* Dispose of the iterators. */
10688 FMDisposeFontFamilyIterator (&ffi);
10689 FMDisposeFontFamilyInstanceIterator (&ffii);
10691 else
10693 #endif /* TARGET_API_MAC_CARBON */
10694 GrafPtr port;
10695 SInt16 fontnum, old_fontnum;
10696 int num_mac_fonts = CountResources('FOND');
10697 int i, j;
10698 Handle font_handle, font_handle_2;
10699 short id, scriptcode;
10700 ResType type;
10701 Str32 name;
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);
10708 #else
10709 old_fontnum = port->txFont;
10710 #endif
10712 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10714 font_handle = GetIndResource ('FOND', i);
10715 if (!font_handle)
10716 continue;
10718 GetResInfo (font_handle, &id, &type, name);
10719 GetFNum (name, &fontnum);
10720 p2cstr (name);
10721 if (fontnum == 0)
10722 continue;
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));
10735 assc_entry
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,
10759 scriptcode);
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,
10769 -smJapanese);
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). */
10794 Lisp_Object
10795 x_list_fonts (struct frame *f,
10796 Lisp_Object pattern,
10797 int size,
10798 int maxnames)
10800 char *ptnstr;
10801 Lisp_Object newlist = Qnil, tem, key;
10802 int n_fonts = 0;
10803 int i;
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 ();
10810 if (dpyinfo)
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);
10819 goto label_cached;
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);
10834 n_fonts++;
10835 if (n_fonts >= maxnames)
10836 break;
10840 /* MAC_TODO: add code for matching outline fonts here */
10842 UNGCPRO;
10844 if (dpyinfo)
10846 XSETCDR (dpyinfo->name_list_element,
10847 Fcons (Fcons (key, newlist),
10848 XCDR (dpyinfo->name_list_element)));
10850 label_cached:
10852 return newlist;
10856 #if GLYPH_DEBUG
10858 /* Check that FONT is valid on frame F. It is if it can be found in F's
10859 font table. */
10861 static void
10862 x_check_font (f, font)
10863 struct frame *f;
10864 XFontStruct *font;
10866 int i;
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)
10874 break;
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. */
10887 static INLINE void
10888 x_font_min_bounds (font, w, h)
10889 MacFontStruct *font;
10890 int *w, *h;
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)
10909 struct frame *f;
10911 int i;
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;
10924 int w, h;
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 '*'. */
10946 static int
10947 is_fully_specified_xlfd (char *p)
10949 int i;
10950 char *q;
10952 if (*p != '-')
10953 return 0;
10955 for (i = 0; i < 13; i++)
10957 q = strchr (p + 1, '-');
10958 if (q == NULL)
10959 return 0;
10960 if (q - p == 2 && *(p + 1) == '*')
10961 return 0;
10962 p = q;
10965 if (strchr (p + 1, '-') != NULL)
10966 return 0;
10968 if (*(p + 1) == '*' && *(p + 2) == '\0')
10969 return 0;
10971 return 1;
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;
10988 char *name;
10989 GrafPtr port;
10990 SInt16 old_fontnum, old_fontsize;
10991 Style old_fontface;
10992 Str32 mfontname;
10993 SInt16 fontnum;
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))
11000 name = fontname;
11001 else
11003 for (i = 0; i < font_name_count; i++)
11004 if (mac_font_pattern_match (font_name_table[i], fontname))
11005 break;
11007 if (i >= font_name_count)
11008 return NULL;
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);
11018 #else
11019 old_fontnum = port->txFont;
11020 old_fontsize = port->txSize;
11021 old_fontface = port->txFace;
11022 #endif
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)
11029 fontface |= bold;
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);
11038 if (fontnum == 0)
11039 return NULL;
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. */
11056 char cs[32];
11058 if (sscanf (name,
11059 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11060 cs) == 1
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);
11071 TextSize (size);
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;
11082 else
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)
11093 case smJapanese:
11094 char_width = StringWidth("\p\x81\x40");
11095 break;
11096 case smTradChinese:
11097 char_width = StringWidth("\p\xa1\x40");
11098 break;
11099 case smSimpChinese:
11100 char_width = StringWidth("\p\xa1\xa1");
11101 break;
11102 case smKorean:
11103 char_width = StringWidth("\p\xa1\xa1");
11104 break;
11107 else
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;
11122 else
11124 font->per_char = (XCharStruct *)
11125 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11127 int c;
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);
11141 return font;
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. */
11150 struct font_info *
11151 x_load_font (f, fontname, size)
11152 struct frame *f;
11153 register char *fontname;
11154 int size;
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))
11166 Lisp_Object tail;
11167 int i;
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. */
11181 char *full_name;
11182 struct MacFontStruct *font;
11183 struct font_info *fontp;
11184 unsigned long value;
11185 int i;
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);
11196 if (!font)
11197 return NULL;
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)
11202 break;
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)
11208 int sz;
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. */
11220 BLOCK_INPUT;
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;
11248 else
11250 fontp->encoding[1]
11251 = (font->max_byte1 == 0
11252 /* 1-byte font */
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 */
11258 /* 2-byte font */
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);
11284 #else
11285 fontp->baseline_offset = 0;
11286 fontp->relative_compose = 0;
11287 fontp->default_ascent = 0;
11288 #endif
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);
11296 UNBLOCK_INPUT;
11297 return fontp;
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. */
11305 struct font_info *
11306 x_query_font (f, fontname)
11307 struct frame *f;
11308 register char *fontname;
11310 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11311 int i;
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);
11318 return NULL;
11322 /* Find a CCL program for a font specified by FONTP, and set the member
11323 `encoder' of the structure. */
11325 void
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))
11333 elt = XCAR (list);
11334 if (CONSP (elt)
11335 && STRINGP (XCAR (elt))
11336 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11337 >= 0))
11338 break;
11340 if (! NILP (list))
11342 struct ccl_program *ccl
11343 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11345 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11346 xfree (ccl);
11347 else
11348 fontp->font_encoder = ccl;
11354 /***********************************************************************
11355 Initialization
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. */
11382 static int
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))
11397 name1 += 4;
11398 if (! strncmp (name2, "unix:", 5))
11399 name2 += 4;
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++)
11417 if (*name1 == ':')
11418 seen_colon++;
11419 if (seen_colon && *name1 == '.')
11420 return 1;
11422 return (seen_colon
11423 && (*name1 == '.' || *name1 == '\0')
11424 && (*name2 == '.' || *name2 == '\0'));
11426 #endif
11429 /* The Mac Event loop code */
11431 #ifndef MAC_OSX
11432 #include <Events.h>
11433 #include <Quickdraw.h>
11434 #include <Balloons.h>
11435 #include <Devices.h>
11436 #include <Fonts.h>
11437 #include <Gestalt.h>
11438 #include <Menus.h>
11439 #include <Processes.h>
11440 #include <Sound.h>
11441 #include <ToolUtils.h>
11442 #include <TextUtils.h>
11443 #include <Dialogs.h>
11444 #include <Script.h>
11445 #include <Types.h>
11446 #include <TextEncodingConverter.h>
11447 #include <Resources.h>
11449 #if __MWERKS__
11450 #include <unix.h>
11451 #endif
11452 #endif /* ! MAC_OSX */
11454 #define M_APPLE 128
11455 #define I_ABOUT 1
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
11478 suspended. */
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;
11508 #endif
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;
11523 /* Apple Events */
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 ();
11540 #endif
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)
11552 #else
11553 mac_to_emacs_modifiers (EventModifiers mods)
11554 #endif
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;
11565 return result;
11568 #if USE_CARBON_EVENTS
11569 /* Obtains the event modifiers from the event ref and then calls
11570 mac_to_emacs_modifiers. */
11571 static int
11572 mac_event_to_emacs_modifiers (EventRef eventRef)
11574 UInt32 mods = 0;
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. */
11582 static int
11583 mac_get_mouse_btn (EventRef ref)
11585 EventMouseButton result = kEventMouseButtonPrimary;
11586 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
11587 sizeof (EventMouseButton), NULL, &result);
11588 switch (result)
11590 case kEventMouseButtonPrimary:
11591 return 0;
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;
11597 default:
11598 return 0;
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;
11618 result=1;
11620 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
11622 eventRec->what = mouseUp;
11623 result=1;
11625 if (result)
11627 /* Need where and when. */
11628 UInt32 mods;
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
11634 NumLock & Fn. */
11635 GetEventParameter (eventRef, kEventParamKeyModifiers,
11636 typeUInt32, NULL, sizeof (UInt32),
11637 NULL, &mods);
11638 eventRec->modifiers = mods;
11640 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
11643 return result;
11646 #endif
11648 static void
11649 do_get_menus (void)
11651 Handle menubar_handle;
11652 MenuHandle menu_handle;
11654 menubar_handle = GetNewMBar (128);
11655 if(menubar_handle == NULL)
11656 abort ();
11657 SetMenuBar (menubar_handle);
11658 DrawMenuBar ();
11660 menu_handle = GetMenuHandle (M_APPLE);
11661 if(menu_handle != NULL)
11662 AppendResMenu (menu_handle,'DRVR');
11663 else
11664 abort ();
11668 static void
11669 do_init_managers (void)
11671 #if !TARGET_API_MAC_CARBON
11672 InitGraf (&qd.thePort);
11673 InitFonts ();
11674 FlushEvents (everyEvent, 0);
11675 InitWindows ();
11676 InitMenus ();
11677 TEInit ();
11678 InitDialogs (NULL);
11679 #endif /* !TARGET_API_MAC_CARBON */
11680 InitCursor ();
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 */
11688 MaxApplZone ();
11689 MoreMasters ();
11690 #endif /* !TARGET_API_MAC_CARBON */
11693 static void
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);
11704 exit (1);
11708 static void
11709 do_window_update (WindowPtr win)
11711 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11712 struct frame *f = mwp->mFP;
11714 if (f)
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 ();
11729 else
11731 BeginUpdate (win);
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;
11739 EndUpdate (win);
11744 static int
11745 is_emacs_window (WindowPtr win)
11747 Lisp_Object tail, frame;
11749 if (!win)
11750 return 0;
11752 FOR_EACH_FRAME (tail, frame)
11753 if (FRAME_MAC_P (XFRAME (frame)))
11754 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11755 return 1;
11757 return 0;
11760 static void
11761 do_window_activate (WindowPtr win)
11763 mac_output *mwp;
11764 struct frame *f;
11766 if (is_emacs_window (win))
11768 mwp = (mac_output *) GetWRefCon (win);
11769 f = mwp->mFP;
11771 if (f)
11773 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11774 activate_scroll_bars (f);
11779 static void
11780 do_window_deactivate (WindowPtr win)
11782 mac_output *mwp;
11783 struct frame *f;
11785 if (is_emacs_window (win))
11787 mwp = (mac_output *) GetWRefCon (win);
11788 f = mwp->mFP;
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);
11798 static void
11799 do_app_resume ()
11801 WindowPtr wp;
11802 mac_output *mwp;
11803 struct frame *f;
11805 wp = FrontWindow();
11806 if (is_emacs_window (wp))
11808 mwp = (mac_output *) GetWRefCon (wp);
11809 f = mwp->mFP;
11811 if (f)
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;
11822 static void
11823 do_app_suspend ()
11825 WindowPtr wp;
11826 mac_output *mwp;
11827 struct frame *f;
11829 wp = FrontWindow();
11830 if (is_emacs_window (wp))
11832 mwp = (mac_output *) GetWRefCon (wp);
11833 f = mwp->mFP;
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;
11847 static void
11848 do_mouse_moved (Point mouse_pos)
11850 WindowPtr wp = FrontWindow ();
11851 struct frame *f;
11853 if (is_emacs_window (wp))
11855 f = ((mac_output *) GetWRefCon (wp))->mFP;
11857 #if TARGET_API_MAC_CARBON
11858 SetPort (GetWindowPort (wp));
11859 #else
11860 SetPort (wp);
11861 #endif
11863 GlobalToLocal (&mouse_pos);
11865 note_mouse_movement (f, &mouse_pos);
11870 static void
11871 do_os_event (EventRecord *erp)
11873 switch((erp->message >> 24) & 0x000000FF)
11875 case suspendResumeMessage:
11876 if((erp->message & resumeFlag) == 1)
11877 do_app_resume ();
11878 else
11879 do_app_suspend ();
11880 break;
11882 case mouseMovedMessage:
11883 do_mouse_moved (erp->where);
11884 break;
11888 static void
11889 do_events (EventRecord *erp)
11891 switch (erp->what)
11893 case updateEvt:
11894 do_window_update ((WindowPtr) erp->message);
11895 break;
11897 case osEvt:
11898 do_os_event (erp);
11899 break;
11901 case activateEvt:
11902 if ((erp->modifiers & activeFlag) != 0)
11903 do_window_activate ((WindowPtr) erp->message);
11904 else
11905 do_window_deactivate ((WindowPtr) erp->message);
11906 break;
11910 static void
11911 do_apple_menu (SInt16 menu_item)
11913 #if !TARGET_API_MAC_CARBON
11914 Str255 item_name;
11915 SInt16 da_driver_refnum;
11917 if (menu_item == I_ABOUT)
11918 NoteAlert (ABOUT_ALERT_ID, NULL);
11919 else
11921 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11922 da_driver_refnum = OpenDeskAcc (item_name);
11924 #endif /* !TARGET_API_MAC_CARBON */
11927 void
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);
11935 if (menu_id == 0)
11936 return;
11938 switch (menu_id)
11940 case M_APPLE:
11941 do_apple_menu (menu_item);
11942 break;
11944 default:
11946 WindowPtr wp = FrontWindow ();
11947 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11948 MenuHandle menu = GetMenuHandle (menu_id);
11949 if (menu)
11951 UInt32 refcon;
11953 GetMenuItemRefCon (menu, menu_item, &refcon);
11954 menubar_selection_callback (f, refcon);
11959 HiliteMenu (0);
11963 /* Handle drags in size box. Based on code contributed by Ben
11964 Mesander and IM - Window Manager A. */
11966 static void
11967 do_grow_window (WindowPtr w, EventRecord *e)
11969 long grow_size;
11970 Rect limit_rect;
11971 int rows, columns;
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. */
11995 static void
11996 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11998 GrafPtr save_port;
11999 Rect zoom_rect, port_rect;
12000 Point top_left;
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));
12009 #else
12010 SetPort (w);
12011 #endif
12013 /* Clear window to avoid flicker. */
12014 #if TARGET_API_MAC_CARBON
12016 Rect r;
12017 BitMap bm;
12019 GetWindowPortBounds (w, &r);
12020 EraseRect (&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 -
12028 zoom_rect.top */
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
12060 = zoom_rect;
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);
12069 #else
12070 port_rect = w->portRect;
12071 #endif
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 */
12080 static OSErr
12081 init_mac_drag_n_drop ()
12083 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
12084 return result;
12087 /* Intialize AppleEvent dispatcher table for the required events. */
12088 void
12089 init_required_apple_events ()
12091 OSErr err;
12092 long result;
12094 /* Make sure we have apple events before starting. */
12095 err = Gestalt (gestaltAppleEventsAttr, &result);
12096 if (err != noErr)
12097 abort ();
12099 if (!(result & (1 << gestaltAppleEventsPresent)))
12100 abort ();
12102 #if TARGET_API_MAC_CARBON
12103 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12104 NewAEEventHandlerUPP
12105 ((AEEventHandlerProcPtr) do_ae_open_application),
12106 0L, false);
12107 #else
12108 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12109 NewAEEventHandlerProc
12110 ((AEEventHandlerProcPtr) do_ae_open_application),
12111 0L, false);
12112 #endif
12113 if (err != noErr)
12114 abort ();
12116 #if TARGET_API_MAC_CARBON
12117 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12118 NewAEEventHandlerUPP
12119 ((AEEventHandlerProcPtr) do_ae_open_documents),
12120 0L, false);
12121 #else
12122 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12123 NewAEEventHandlerProc
12124 ((AEEventHandlerProcPtr) do_ae_open_documents),
12125 0L, false);
12126 #endif
12127 if (err != noErr)
12128 abort ();
12130 #if TARGET_API_MAC_CARBON
12131 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12132 NewAEEventHandlerUPP
12133 ((AEEventHandlerProcPtr) do_ae_print_documents),
12134 0L, false);
12135 #else
12136 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12137 NewAEEventHandlerProc
12138 ((AEEventHandlerProcPtr) do_ae_print_documents),
12139 0L, false);
12140 #endif
12141 if (err != noErr)
12142 abort ();
12144 #if TARGET_API_MAC_CARBON
12145 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12146 NewAEEventHandlerUPP
12147 ((AEEventHandlerProcPtr) do_ae_quit_application),
12148 0L, false);
12149 #else
12150 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12151 NewAEEventHandlerProc
12152 ((AEEventHandlerProcPtr) do_ae_quit_application),
12153 0L, false);
12154 #endif
12155 if (err != noErr)
12156 abort ();
12159 #if USE_CARBON_EVENTS
12161 void
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...
12174 OSStatus
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;
12184 CFStringRef type;
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, &copyTypes);
12194 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
12195 if (type) {
12196 CFArrayAppendValue (copyTypes, type);
12197 //CFArrayAppendValue (pasteTypes, type);
12198 CFRelease (type);
12201 case kEventServiceCopy:
12203 ScrapRef currentScrap, specificScrap;
12204 char * buf = "";
12205 Size byteCount = 0;
12207 GetCurrentScrap (&currentScrap);
12209 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
12210 if (err == noErr)
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);
12220 if (err == noErr)
12221 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
12222 kScrapFlavorMaskNone, byteCount, buffer);
12223 xfree (buffer);
12226 err = noErr;
12228 case kEventServicePaste:
12231 // Get the current location
12232 Size byteCount;
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
12244 BLOCK_INPUT;
12245 // Get the current "selection" string here
12246 UNBLOCK_INPUT;
12249 xfree(buffer);
12254 return err;
12256 #endif
12258 /* Open Application Apple Event */
12259 static pascal OSErr
12260 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12262 return noErr;
12266 /* Defined in mac.c. */
12267 extern int
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)
12277 OSErr err, err2;
12278 AEDesc the_desc;
12279 AEKeyword keyword;
12280 DescType actual_type;
12281 Size actual_size;
12283 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12284 if (err != noErr)
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
12289 file list. */
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;
12299 goto error_exit;
12301 err = noErr;
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);
12309 if (err == noErr)
12311 int i;
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++)
12316 FSSpec fs;
12317 Str255 path_name, unix_path_name;
12318 #ifdef MAC_OSX
12319 FSRef fref;
12320 #endif
12322 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12323 (Ptr) &fs, sizeof (fs), &actual_size);
12324 if (err != noErr) break;
12326 #ifdef MAC_OSX
12327 err = FSpMakeFSRef (&fs, &fref);
12328 if (err != noErr) break;
12330 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12331 #else
12332 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12333 fs.name) &&
12334 mac_to_posix_pathname (path_name, unix_path_name, 255))
12335 #endif
12336 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12337 drag_and_drop_file_list);
12342 error_exit:
12343 /* Nuke the coerced file list in any case */
12344 err2 = AEDisposeDesc(&the_desc);
12346 descriptor_error_exit:
12347 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12348 return err;
12352 static pascal OSErr
12353 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
12354 DragReference theDrag)
12356 short items;
12357 short index;
12358 FlavorFlags theFlags;
12359 Point mouse;
12360 OSErr result;
12361 ItemReference theItem;
12362 HFSFlavor data;
12363 FSRef fref;
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)
12376 #ifdef MAC_OSX
12377 FSRef frref;
12378 #else
12379 Str255 path_name;
12380 #endif
12381 Str255 unix_path_name;
12382 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
12383 #ifdef MAC_OSX
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)));
12388 #else
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))
12392 #endif
12393 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12394 drag_and_drop_file_list);
12396 else
12397 return;
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;
12404 Lisp_Object frame;
12405 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
12406 SetPort (GetWindowPort (window));
12407 GlobalToLocal (&mouse);
12409 event.kind = DRAG_N_DROP_EVENT;
12410 event.code = 0;
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);
12417 event.arg = Qnil;
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) */
12448 return noErr;
12452 #if __profile__
12453 void
12454 profiler_exit_proc ()
12456 ProfilerDump ("\pEmacs.prof");
12457 ProfilerTerm ();
12459 #endif
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
12478 a wait, etc. */
12480 #if !TARGET_API_MAC_CARBON
12481 #undef main
12482 int
12483 main (void)
12485 #if __profile__ /* is the profiler on? */
12486 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12487 exit(1);
12488 #endif
12490 #if __MWERKS__
12491 /* set creator and type for files created by MSL */
12492 _fcreator = 'EMAx';
12493 _ftype = 'TEXT';
12494 #endif
12496 do_init_managers ();
12498 do_get_menus ();
12500 do_check_ram_size ();
12502 init_emacs_passwd_dir ();
12504 init_environ ();
12506 initialize_applescript ();
12508 init_required_apple_events ();
12511 char **argv;
12512 int argc = 0;
12514 /* set up argv array from STR# resource */
12515 get_string_list (&argv, ARGV_STRING_LIST_ID);
12516 while (argv[argc])
12517 argc++;
12519 /* free up AppleScript resources on exit */
12520 atexit (terminate_applescript);
12522 #if __profile__ /* is the profiler on? */
12523 atexit (profiler_exit_proc);
12524 #endif
12526 /* 3rd param "envp" never used in emacs_main */
12527 (void) emacs_main (argc, argv, 0);
12530 /* Never reached - real exit in Fkill_emacs */
12531 return 0;
12533 #endif
12535 /* Table for translating Mac keycode to X keysym values. Contributed
12536 by Sudhir Shenoy. */
12537 static unsigned char keycode_to_xkeysym_table[] = {
12538 /* 0x00 - 0x3f */
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,
12543 /* 0x40 */
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,
12548 /* 0x50 */
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,
12553 /* 0x60 */
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 */,
12558 /* 0x70 */
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
12565 static int
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
12573 user. */
12575 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12577 int count = 0;
12578 #if USE_CARBON_EVENTS
12579 OSStatus rneResult;
12580 EventRef eventRef;
12581 EventMouseButton mouseBtn;
12582 #endif
12583 EventRecord er;
12584 int the_modifiers;
12585 EventMask event_mask;
12587 #if 0
12588 if (interrupt_input_blocked)
12590 interrupt_input_pending = 1;
12591 return -1;
12593 #endif
12595 interrupt_input_pending = 0;
12596 BLOCK_INPUT;
12598 /* So people can tell when we have read the available input. */
12599 input_signal_count++;
12601 if (numchars <= 0)
12602 abort ();
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)
12611 UNBLOCK_INPUT;
12612 return 0;
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. */
12622 bufp->arg = Qnil;
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,
12630 expected
12631 ? TicksToEventTime (app_sleep_time)
12632 : 0,
12633 true, &eventRef);
12634 if (!rneResult)
12636 /* Handle new events */
12637 if (!mac_convert_event_ref (eventRef, &er))
12638 switch (GetEventClass (eventRef))
12640 case kEventClassMouse:
12641 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
12643 SInt32 delta;
12644 Point point;
12645 WindowPtr window_ptr = FrontNonFloatingWindow ();
12646 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12647 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
12648 typeSInt32, NULL, sizeof (SInt32),
12649 NULL, &delta);
12650 GetEventParameter(eventRef, kEventParamMouseLocation,
12651 typeQDPoint, NULL, sizeof (Point),
12652 NULL, &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);
12662 count++;
12664 else
12665 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12667 break;
12668 default:
12669 /* Send the event to the appropriate receiver. */
12670 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12672 else
12673 #else
12674 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12675 #endif /* USE_CARBON_EVENTS */
12676 switch (er.what)
12678 case mouseDown:
12679 case mouseUp:
12681 WindowPtr window_ptr = FrontWindow ();
12682 SInt16 part_code;
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 ())) {
12688 break;
12691 if (!is_emacs_window(window_ptr))
12692 break;
12693 #endif
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));
12704 #else
12705 SetPort (window_ptr);
12706 #endif
12708 GlobalToLocal (&mouse_loc);
12710 #if USE_CARBON_EVENTS
12711 bufp->code = mac_get_mouse_btn (eventRef);
12712 #else
12713 bufp->code = 0; /* only one mouse button */
12714 #endif
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);
12720 #else
12721 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12722 #endif
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;
12732 count++;
12733 break;
12736 part_code = FindWindow (er.where, &window_ptr);
12738 switch (part_code)
12740 case inMenuBar:
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);
12747 count++;
12749 break;
12751 case inContent:
12752 if (window_ptr != FrontWindow ())
12753 SelectWindow (window_ptr);
12754 else
12756 SInt16 control_part_code;
12757 ControlHandle ch;
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));
12765 #else
12766 SetPort (window_ptr);
12767 #endif
12769 GlobalToLocal (&mouse_loc);
12770 #if TARGET_API_MAC_CARBON
12771 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12772 &control_part_code);
12773 #else
12774 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12775 #endif
12777 #if USE_CARBON_EVENTS
12778 bufp->code = mac_get_mouse_btn (eventRef);
12779 #else
12780 bufp->code = 0; /* only one mouse button */
12781 #endif
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
12788 if (ch != 0)
12789 #else
12790 if (control_part_code != 0)
12791 #endif
12793 struct scroll_bar *bar = (struct scroll_bar *)
12794 GetControlReference (ch);
12795 x_scroll_bar_handle_click (bar, control_part_code, &er,
12796 bufp);
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;
12804 else
12806 mouse_tracking_in_progress = mouse_tracking_none;
12807 tracked_scroll_bar = NULL;
12810 else
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;
12817 else
12818 mouse_tracking_in_progress = mouse_tracking_none;
12821 #if USE_CARBON_EVENTS
12822 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12823 #else
12824 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12825 #endif
12827 switch (er.what)
12829 case mouseDown:
12830 bufp->modifiers |= down_modifier;
12831 break;
12832 case mouseUp:
12833 bufp->modifiers |= up_modifier;
12834 break;
12837 count++;
12839 break;
12841 case inDrag:
12842 #if TARGET_API_MAC_CARBON
12844 BitMap bm;
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 */
12852 break;
12854 case inGoAway:
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);
12860 count++;
12862 break;
12864 /* window resize handling added --ben */
12865 case inGrow:
12866 do_grow_window(window_ptr, &er);
12867 break;
12869 /* window zoom handling added --ben */
12870 case inZoomIn:
12871 case inZoomOut:
12872 if (TrackBox (window_ptr, er.where, part_code))
12873 do_zoom_window (window_ptr, part_code);
12874 break;
12876 default:
12877 break;
12880 break;
12882 case updateEvt:
12883 case osEvt:
12884 case activateEvt:
12885 #if USE_CARBON_EVENTS
12886 if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
12887 #endif
12888 do_events (&er);
12889 break;
12891 case keyDown:
12892 case autoKey:
12894 int keycode = (er.message & keyCodeMask) >> 8;
12895 int xkeysym;
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)))
12907 OSStatus err;
12908 err = SendEventToEventTarget (eventRef,
12909 GetEventDispatcherTarget ());
12910 if (err != eventNotHandledErr)
12911 break;
12913 #endif
12915 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12917 SysBeep (1);
12918 UNBLOCK_INPUT;
12919 return 0;
12922 ObscureCursor ();
12924 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12926 bufp->code = 0x7f;
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;
12934 else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
12936 /* This is a special case to deal with converting from
12937 a control character to non-control character */
12938 int new_modifiers = er.modifiers & ~controlKey;
12939 int new_keycode = keycode | new_modifiers;
12940 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12941 unsigned long some_state = 0;
12942 bufp->code = KeyTranslate (kchr_ptr, new_keycode, &some_state) & 0xff;
12943 bufp->kind = ASCII_KEYSTROKE_EVENT;
12945 else
12947 if (er.modifiers & macMetaKey)
12949 /* This code comes from Keyboard Resource, Appendix
12950 C of IM - Text. This is necessary since shift is
12951 ignored in KCHR table translation when option or
12952 command is pressed. */
12953 int new_modifiers = er.modifiers & 0xf600;
12954 /* mask off option and command */
12955 int new_keycode = keycode | new_modifiers;
12956 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12957 unsigned long some_state = 0;
12958 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12959 &some_state) & 0xff;
12961 else
12962 bufp->code = er.message & charCodeMask;
12963 bufp->kind = ASCII_KEYSTROKE_EVENT;
12967 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12968 convert non-ASCII characters typed at the Mac keyboard
12969 (presumed to be in the Mac Roman encoding) to iso-latin-1
12970 encoding before they are passed to Emacs. This enables the
12971 Mac keyboard to be used to enter non-ASCII iso-latin-1
12972 characters directly. */
12973 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12974 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12976 static TECObjectRef converter = NULL;
12977 OSStatus the_err = noErr;
12978 OSStatus convert_status = noErr;
12980 if (converter == NULL)
12982 the_err = TECCreateConverter (&converter,
12983 kTextEncodingMacRoman,
12984 mac_keyboard_text_encoding);
12985 current_mac_keyboard_text_encoding
12986 = mac_keyboard_text_encoding;
12988 else if (mac_keyboard_text_encoding
12989 != current_mac_keyboard_text_encoding)
12991 /* Free the converter for the current encoding before
12992 creating a new one. */
12993 TECDisposeConverter (converter);
12994 the_err = TECCreateConverter (&converter,
12995 kTextEncodingMacRoman,
12996 mac_keyboard_text_encoding);
12997 current_mac_keyboard_text_encoding
12998 = mac_keyboard_text_encoding;
13001 if (the_err == noErr)
13003 unsigned char ch = bufp->code;
13004 ByteCount actual_input_length, actual_output_length;
13005 unsigned char outch;
13007 convert_status = TECConvertText (converter, &ch, 1,
13008 &actual_input_length,
13009 &outch, 1,
13010 &actual_output_length);
13011 if (convert_status == noErr
13012 && actual_input_length == 1
13013 && actual_output_length == 1)
13014 bufp->code = outch;
13018 #if USE_CARBON_EVENTS
13019 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13020 #else
13021 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13022 #endif
13025 mac_output *mwp
13026 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
13027 XSETFRAME (bufp->frame_or_window, mwp->mFP);
13030 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
13032 count++;
13033 break;
13035 case kHighLevelEvent:
13036 drag_and_drop_file_list = Qnil;
13038 AEProcessAppleEvent(&er);
13040 /* Build a DRAG_N_DROP_EVENT type event as is done in
13041 constuct_drag_n_drop in w32term.c. */
13042 if (!NILP (drag_and_drop_file_list))
13044 struct frame *f = NULL;
13045 WindowPtr wp;
13046 Lisp_Object frame;
13048 wp = FrontNonFloatingWindow ();
13049 if (wp && is_emacs_window(wp))
13050 f = ((mac_output *) GetWRefCon (wp))->mFP;
13052 bufp->kind = DRAG_N_DROP_EVENT;
13053 bufp->code = 0;
13054 bufp->timestamp = er.when * (1000 / 60);
13055 /* ticks to milliseconds */
13056 #if USE_CARBON_EVENTS
13057 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13058 #else
13059 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13060 #endif
13062 XSETINT (bufp->x, 0);
13063 XSETINT (bufp->y, 0);
13065 XSETFRAME (frame, f);
13066 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
13068 /* Regardless of whether Emacs was suspended or in the
13069 foreground, ask it to redraw its entire screen.
13070 Otherwise parts of the screen can be left in an
13071 inconsistent state. */
13072 if (wp)
13073 #if TARGET_API_MAC_CARBON
13075 Rect r;
13077 GetWindowPortBounds (wp, &r);
13078 InvalWindowRect (wp, &r);
13080 #else /* not TARGET_API_MAC_CARBON */
13081 InvalRect (&(wp->portRect));
13082 #endif /* not TARGET_API_MAC_CARBON */
13084 count++;
13086 default:
13087 break;
13089 #if USE_CARBON_EVENTS
13090 ReleaseEvent (eventRef);
13092 #endif
13094 /* If the focus was just given to an autoraising frame,
13095 raise it now. */
13096 /* ??? This ought to be able to handle more than one such frame. */
13097 if (pending_autoraise_frame)
13099 x_raise_frame (pending_autoraise_frame);
13100 pending_autoraise_frame = 0;
13103 #if !TARGET_API_MAC_CARBON
13104 check_alarm (); /* simulate the handling of a SIGALRM */
13105 #endif
13108 static Point old_mouse_pos = { -1, -1 };
13110 if (app_is_suspended)
13112 old_mouse_pos.h = -1;
13113 old_mouse_pos.v = -1;
13115 else
13117 Point mouse_pos;
13118 WindowPtr wp;
13119 struct frame *f;
13120 Lisp_Object bar;
13121 struct scroll_bar *sb;
13123 wp = FrontWindow ();
13124 if (is_emacs_window (wp))
13126 f = ((mac_output *) GetWRefCon (wp))->mFP;
13128 #if TARGET_API_MAC_CARBON
13129 SetPort (GetWindowPort (wp));
13130 #else
13131 SetPort (wp);
13132 #endif
13134 GetMouse (&mouse_pos);
13136 if (!EqualPt (mouse_pos, old_mouse_pos))
13138 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
13139 && tracked_scroll_bar)
13140 x_scroll_bar_note_movement (tracked_scroll_bar,
13141 mouse_pos.v
13142 - XINT (tracked_scroll_bar->top),
13143 TickCount() * (1000 / 60));
13144 else
13145 note_mouse_movement (f, &mouse_pos);
13147 old_mouse_pos = mouse_pos;
13153 UNBLOCK_INPUT;
13155 return count;
13159 /* Need to override CodeWarrior's input function so no conversion is
13160 done on newlines Otherwise compiled functions in .elc files will be
13161 read incorrectly. Defined in ...:MSL C:MSL
13162 Common:Source:buffer_io.c. */
13163 #ifdef __MWERKS__
13164 void
13165 __convert_to_newlines (unsigned char * p, size_t * n)
13167 #pragma unused(p,n)
13170 void
13171 __convert_from_newlines (unsigned char * p, size_t * n)
13173 #pragma unused(p,n)
13175 #endif
13178 /* Initialize the struct pointed to by MW to represent a new COLS x
13179 ROWS Macintosh window, using font with name FONTNAME and size
13180 FONTSIZE. */
13181 void
13182 NewMacWindow (FRAME_PTR fp)
13184 mac_output *mwp;
13185 #if TARGET_API_MAC_CARBON
13186 static int making_terminal_window = 0;
13187 #else
13188 static int making_terminal_window = 1;
13189 #endif
13191 mwp = fp->output_data.mac;
13193 if (making_terminal_window)
13195 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
13196 (WindowPtr) -1)))
13197 abort ();
13198 making_terminal_window = 0;
13200 else
13201 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
13202 abort ();
13204 SetWRefCon (mwp->mWP, (long) mwp);
13205 /* so that update events can find this mac_output struct */
13206 mwp->mFP = fp; /* point back to emacs frame */
13208 #if TARGET_API_MAC_CARBON
13209 SetPort (GetWindowPort (mwp->mWP));
13210 #else
13211 SetPort (mwp->mWP);
13212 #endif
13214 mwp->fontset = -1;
13216 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
13217 ShowWindow (mwp->mWP);
13222 void
13223 make_mac_frame (struct frame *f)
13225 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
13226 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
13228 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
13230 NewMacWindow(f);
13232 f->output_data.mac->cursor_pixel = 0;
13233 f->output_data.mac->border_pixel = 0x00ff00;
13234 f->output_data.mac->mouse_pixel = 0xff00ff;
13235 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
13237 f->output_data.mac->fontset = -1;
13238 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13239 f->output_data.mac->scroll_bar_background_pixel = -1;
13240 f->output_data.mac->left_pos = 4;
13241 f->output_data.mac->top_pos = 4;
13242 f->output_data.mac->border_width = 0;
13243 f->output_data.mac->explicit_parent = 0;
13245 f->output_data.mac->internal_border_width = 0;
13247 f->output_method = output_mac;
13249 f->auto_raise = 1;
13250 f->auto_lower = 1;
13252 f->new_width = 0;
13253 f->new_height = 0;
13256 void
13257 make_mac_terminal_frame (struct frame *f)
13259 Lisp_Object frame;
13261 XSETFRAME (frame, f);
13263 f->output_method = output_mac;
13264 f->output_data.mac = (struct mac_output *)
13265 xmalloc (sizeof (struct mac_output));
13266 bzero (f->output_data.mac, sizeof (struct mac_output));
13267 f->output_data.mac->fontset = -1;
13268 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13269 f->output_data.mac->scroll_bar_background_pixel = -1;
13271 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
13273 f->width = 96;
13274 f->height = 4;
13276 make_mac_frame (f);
13278 x_make_gc (f);
13280 /* Need to be initialized for unshow_buffer in window.c. */
13281 selected_window = f->selected_window;
13283 Fmodify_frame_parameters (frame,
13284 Fcons (Fcons (Qfont,
13285 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
13286 Fmodify_frame_parameters (frame,
13287 Fcons (Fcons (Qforeground_color,
13288 build_string ("black")), Qnil));
13289 Fmodify_frame_parameters (frame,
13290 Fcons (Fcons (Qbackground_color,
13291 build_string ("white")), Qnil));
13295 /***********************************************************************
13296 Initialization
13297 ***********************************************************************/
13299 #ifdef USE_X_TOOLKIT
13300 static XrmOptionDescRec emacs_options[] = {
13301 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13302 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13304 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13305 XrmoptionSepArg, NULL},
13306 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13308 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13309 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13310 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13311 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13312 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13313 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13314 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13316 #endif /* USE_X_TOOLKIT */
13318 #ifdef MULTI_KBOARD
13319 /* Test whether two display-name strings agree up to the dot that separates
13320 the screen number from the server number. */
13321 static int
13322 same_x_server (name1, name2)
13323 char *name1, *name2;
13325 int seen_colon = 0;
13326 unsigned char *system_name = SDATA (Vsystem_name);
13327 int system_name_length = strlen (system_name);
13328 int length_until_period = 0;
13330 while (system_name[length_until_period] != 0
13331 && system_name[length_until_period] != '.')
13332 length_until_period++;
13334 /* Treat `unix' like an empty host name. */
13335 if (! strncmp (name1, "unix:", 5))
13336 name1 += 4;
13337 if (! strncmp (name2, "unix:", 5))
13338 name2 += 4;
13339 /* Treat this host's name like an empty host name. */
13340 if (! strncmp (name1, system_name, system_name_length)
13341 && name1[system_name_length] == ':')
13342 name1 += system_name_length;
13343 if (! strncmp (name2, system_name, system_name_length)
13344 && name2[system_name_length] == ':')
13345 name2 += system_name_length;
13346 /* Treat this host's domainless name like an empty host name. */
13347 if (! strncmp (name1, system_name, length_until_period)
13348 && name1[length_until_period] == ':')
13349 name1 += length_until_period;
13350 if (! strncmp (name2, system_name, length_until_period)
13351 && name2[length_until_period] == ':')
13352 name2 += length_until_period;
13354 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13356 if (*name1 == ':')
13357 seen_colon++;
13358 if (seen_colon && *name1 == '.')
13359 return 1;
13361 return (seen_colon
13362 && (*name1 == '.' || *name1 == '\0')
13363 && (*name2 == '.' || *name2 == '\0'));
13365 #endif
13367 int mac_initialized = 0;
13369 void
13370 mac_initialize_display_info ()
13372 struct mac_display_info *dpyinfo = &one_mac_display_info;
13373 GDHandle main_device_handle;
13375 bzero (dpyinfo, sizeof (*dpyinfo));
13377 /* Put it on x_display_name_list. */
13378 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13379 x_display_name_list);
13380 dpyinfo->name_list_element = XCAR (x_display_name_list);
13382 #if 0
13383 dpyinfo->mac_id_name
13384 = (char *) xmalloc (SCHARS (Vinvocation_name)
13385 + SCHARS (Vsystem_name)
13386 + 2);
13387 sprintf (dpyinfo->mac_id_name, "%s@%s",
13388 SDATA (Vinvocation_name), SDATA (Vsystem_name));
13389 #else
13390 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13391 strcpy (dpyinfo->mac_id_name, "Mac Display");
13392 #endif
13394 main_device_handle = LMGetMainDevice();
13396 dpyinfo->reference_count = 0;
13397 dpyinfo->resx = 75.0;
13398 dpyinfo->resy = 75.0;
13399 dpyinfo->n_planes = 1;
13400 dpyinfo->n_cbits = 16;
13401 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13402 dpyinfo->width = (**main_device_handle).gdRect.right;
13403 dpyinfo->grabbed = 0;
13404 dpyinfo->root_window = NULL;
13406 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13407 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13408 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13409 dpyinfo->mouse_face_window = Qnil;
13412 struct mac_display_info *
13413 mac_term_init (display_name, xrm_option, resource_name)
13414 Lisp_Object display_name;
13415 char *xrm_option;
13416 char *resource_name;
13418 struct mac_display_info *dpyinfo;
13419 GDHandle main_device_handle;
13421 if (!mac_initialized)
13423 mac_initialize ();
13424 mac_initialized = 1;
13427 mac_initialize_display_info (display_name);
13429 dpyinfo = &one_mac_display_info;
13431 main_device_handle = LMGetMainDevice();
13433 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13434 dpyinfo->width = (**main_device_handle).gdRect.right;
13436 return dpyinfo;
13439 #ifdef MAC_OSX
13440 void
13441 MakeMeTheFrontProcess ()
13443 ProcessSerialNumber psn;
13444 OSErr err;
13446 err = GetCurrentProcess (&psn);
13447 if (err == noErr)
13448 (void) SetFrontProcess (&psn);
13450 #endif /* MAC_OSX */
13452 /* Set up use of X before we make the first connection. */
13454 static struct redisplay_interface x_redisplay_interface =
13456 x_produce_glyphs,
13457 x_write_glyphs,
13458 x_insert_glyphs,
13459 x_clear_end_of_line,
13460 x_scroll_run,
13461 x_after_update_window_line,
13462 x_update_window_begin,
13463 x_update_window_end,
13464 XTcursor_to,
13465 x_flush,
13466 x_clear_mouse_face,
13467 x_get_glyph_overhangs,
13468 x_fix_overlapping_area
13471 void
13472 mac_initialize ()
13474 rif = &x_redisplay_interface;
13476 clear_frame_hook = x_clear_frame;
13477 ins_del_lines_hook = x_ins_del_lines;
13478 delete_glyphs_hook = x_delete_glyphs;
13479 ring_bell_hook = XTring_bell;
13480 reset_terminal_modes_hook = XTreset_terminal_modes;
13481 set_terminal_modes_hook = XTset_terminal_modes;
13482 update_begin_hook = x_update_begin;
13483 update_end_hook = x_update_end;
13484 set_terminal_window_hook = XTset_terminal_window;
13485 read_socket_hook = XTread_socket;
13486 frame_up_to_date_hook = XTframe_up_to_date;
13487 mouse_position_hook = XTmouse_position;
13488 frame_rehighlight_hook = XTframe_rehighlight;
13489 frame_raise_lower_hook = XTframe_raise_lower;
13491 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13492 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13493 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13494 judge_scroll_bars_hook = XTjudge_scroll_bars;
13496 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13498 scroll_region_ok = 1; /* we'll scroll partial frames */
13499 char_ins_del_ok = 1;
13500 line_ins_del_ok = 1; /* we'll just blt 'em */
13501 fast_clear_end_of_line = 1; /* X does this well */
13502 memory_below_frame = 0; /* we don't remember what scrolls
13503 off the bottom */
13504 baud_rate = 19200;
13506 x_noop_count = 0;
13507 last_tool_bar_item = -1;
13508 any_help_event_p = 0;
13510 /* Try to use interrupt input; if we can't, then start polling. */
13511 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13513 #ifdef USE_X_TOOLKIT
13514 XtToolkitInitialize ();
13515 Xt_app_con = XtCreateApplicationContext ();
13516 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13518 /* Install an asynchronous timer that processes Xt timeout events
13519 every 0.1s. This is necessary because some widget sets use
13520 timeouts internally, for example the LessTif menu bar, or the
13521 Xaw3d scroll bar. When Xt timouts aren't processed, these
13522 widgets don't behave normally. */
13524 EMACS_TIME interval;
13525 EMACS_SET_SECS_USECS (interval, 0, 100000);
13526 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13528 #endif
13530 #if USE_TOOLKIT_SCROLL_BARS
13531 xaw3d_arrow_scroll = False;
13532 xaw3d_pick_top = True;
13533 #endif
13535 #if 0
13536 /* Note that there is no real way portable across R3/R4 to get the
13537 original error handler. */
13538 XSetErrorHandler (x_error_handler);
13539 XSetIOErrorHandler (x_io_error_quitter);
13541 /* Disable Window Change signals; they are handled by X events. */
13542 #ifdef SIGWINCH
13543 signal (SIGWINCH, SIG_DFL);
13544 #endif /* ! defined (SIGWINCH) */
13546 signal (SIGPIPE, x_connection_signal);
13547 #endif
13549 mac_initialize_display_info ();
13551 #if TARGET_API_MAC_CARBON
13552 init_required_apple_events ();
13554 init_mac_drag_n_drop ();
13556 #if USE_CARBON_EVENTS
13557 init_service_handler ();
13558 #endif
13560 DisableMenuCommand (NULL, kHICommandQuit);
13562 if (!inhibit_window_system)
13563 MakeMeTheFrontProcess ();
13564 #endif
13568 void
13569 syms_of_macterm ()
13571 #if 0
13572 staticpro (&x_error_message_string);
13573 x_error_message_string = Qnil;
13574 #endif
13576 staticpro (&x_display_name_list);
13577 x_display_name_list = Qnil;
13579 staticpro (&last_mouse_scroll_bar);
13580 last_mouse_scroll_bar = Qnil;
13582 staticpro (&Qvendor_specific_keysyms);
13583 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13585 staticpro (&last_mouse_press_frame);
13586 last_mouse_press_frame = Qnil;
13588 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13589 staticpro (&Qmac_ready_for_drag_n_drop);
13591 help_echo = Qnil;
13592 staticpro (&help_echo);
13593 help_echo_object = Qnil;
13594 staticpro (&help_echo_object);
13595 help_echo_window = Qnil;
13596 staticpro (&help_echo_window);
13597 previous_help_echo = Qnil;
13598 staticpro (&previous_help_echo);
13599 help_echo_pos = -1;
13601 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13602 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13603 x_autoselect_window_p = 0;
13605 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13606 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13607 For example, if a block cursor is over a tab, it will be drawn as
13608 wide as that tab on the display. */);
13609 x_stretch_cursor_p = 0;
13611 #if 0 /* TODO: Setting underline position from font properties. */
13612 DEFVAR_BOOL ("x-use-underline-position-properties",
13613 &x_use_underline_position_properties,
13614 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13615 nil means ignore them. If you encounter fonts with bogus
13616 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13617 to 4.1, set this to nil. */);
13618 x_use_underline_position_properties = 1;
13619 #endif
13621 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13622 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13623 Vx_toolkit_scroll_bars = Qt;
13625 staticpro (&last_mouse_motion_frame);
13626 last_mouse_motion_frame = Qnil;
13628 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13629 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13630 Otherwise the option key is used. */);
13631 Vmac_command_key_is_meta = Qt;
13633 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
13634 doc: /* Non-nil means that the control and meta keys are reversed. This is
13635 useful for non-standard keyboard layouts. */);
13636 Vmac_reverse_ctrl_meta = Qnil;
13638 #if USE_CARBON_EVENTS
13639 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
13640 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
13641 the right click will be mouse-3.
13642 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13643 Vmac_wheel_button_is_mouse_2 = Qnil;
13645 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
13646 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
13647 Toolbox for processing before Emacs sees it. */);
13648 Vmac_pass_command_to_system = Qt;
13650 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
13651 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
13652 Toolbox for processing before Emacs sees it. */);
13653 Vmac_pass_control_to_system = Qt;
13654 #endif
13656 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13657 doc: /* One of the Text Encoding Base constant values defined in the
13658 Basic Text Constants section of Inside Macintosh - Text Encoding
13659 Conversion Manager. Its value determines the encoding characters
13660 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13661 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13662 its default value, no conversion takes place. If it is set to
13663 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13664 characters typed on Mac keyboard are first converted into the
13665 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13666 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13667 command, this enables the Mac keyboard to be used to enter non-ASCII
13668 characters directly. */);
13669 mac_keyboard_text_encoding = kTextEncodingMacRoman;