(tex-start-shell): Obey shell-file-name.
[emacs.git] / mac / src / macterm.c
blob0676e47864e168199a3f721833f53695479cc28f
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000 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@users.sourceforge.net). */
23 #include <config.h>
25 /* On 4.3 these lose if they come after xterm.h. */
26 /* Putting these at the beginning seems to be standard for other .c files. */
27 #include <signal.h>
29 #include <stdio.h>
31 #include "lisp.h"
32 #include "blockinput.h"
34 /* Need syssignal.h for various externs and definitions that may be required
35 by some configurations for calls to signal later in this source file. */
36 #include "syssignal.h"
38 /* This may include sys/types.h, and that somehow loses
39 if this is not done before the other system files. */
40 #include "macterm.h"
42 #include <stdlib.h>
43 #include <string.h>
44 #include <alloca.h>
46 #include <Quickdraw.h>
47 #include <ToolUtils.h>
48 #include <Sound.h>
49 #include <Events.h>
50 #include <Script.h>
51 #include <Resources.h>
52 #include <Fonts.h>
53 #include <TextUtils.h>
54 #include <LowMem.h>
55 #include <Controls.h>
56 #if defined (__MRC__) || defined (CODEWARRIOR_VERSION_6)
57 #include <ControlDefinitions.h>
58 #endif
60 #if __profile__
61 #include <profiler.h>
62 #endif
64 #include <sys/types.h>
66 #include "systty.h"
67 #include "systime.h"
69 #ifndef INCLUDED_FCNTL
70 #include <fcntl.h>
71 #endif
72 #include <ctype.h>
73 #include <errno.h>
74 #include <setjmp.h>
75 #include <sys/stat.h>
77 #include "charset.h"
78 #include "ccl.h"
79 #include "frame.h"
80 #include "dispextern.h"
81 #include "fontset.h"
82 #include "termhooks.h"
83 #include "termopts.h"
84 #include "termchar.h"
85 #include "gnu.h"
86 #include "disptab.h"
87 #include "buffer.h"
88 #include "window.h"
89 #include "keyboard.h"
90 #include "intervals.h"
91 #include "process.h"
92 #include "atimer.h"
93 #include "coding.h"
95 #ifdef HAVE_UNISTD_H
96 #include <unistd.h>
97 #endif
99 #ifndef USE_X_TOOLKIT
100 #define x_any_window_to_frame x_window_to_frame
101 #define x_top_window_to_frame x_window_to_frame
102 #endif
104 #ifndef min
105 #define min(a,b) ((a) < (b) ? (a) : (b))
106 #endif
107 #ifndef max
108 #define max(a,b) ((a) > (b) ? (a) : (b))
109 #endif
111 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
114 /* Bitmaps for truncated lines. */
116 enum bitmap_type
118 NO_BITMAP,
119 LEFT_TRUNCATION_BITMAP,
120 RIGHT_TRUNCATION_BITMAP,
121 OVERLAY_ARROW_BITMAP,
122 CONTINUED_LINE_BITMAP,
123 CONTINUATION_LINE_BITMAP,
124 ZV_LINE_BITMAP
127 /* Bitmap drawn to indicate lines not displaying text if
128 `indicate-empty-lines' is non-nil. */
130 #define zv_width 8
131 #define zv_height 8
132 static unsigned char zv_bits[] = {
133 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
135 /* An arrow like this: `<-'. */
137 #define left_width 8
138 #define left_height 8
139 static unsigned char left_bits[] = {
140 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
142 /* Right truncation arrow bitmap `->'. */
144 #define right_width 8
145 #define right_height 8
146 static unsigned char right_bits[] = {
147 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
149 /* Marker for continued lines. */
151 #define continued_width 8
152 #define continued_height 8
153 static unsigned char continued_bits[] = {
154 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
156 /* Marker for continuation lines. */
158 #define continuation_width 8
159 #define continuation_height 8
160 static unsigned char continuation_bits[] = {
161 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
163 /* Overlay arrow bitmap. */
165 #if 0
166 /* A bomb. */
167 #define ov_width 8
168 #define ov_height 8
169 static unsigned char ov_bits[] = {
170 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
171 #else
172 /* A triangular arrow. */
173 #define ov_width 8
174 #define ov_height 8
175 static unsigned char ov_bits[] = {
176 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
177 #endif
179 extern Lisp_Object Qhelp_echo;
182 /* Non-zero means Emacs uses toolkit scroll bars. */
184 int x_toolkit_scroll_bars_p;
186 /* If a string, XTread_socket generates an event to display that string.
187 (The display is done in read_char.) */
189 static Lisp_Object help_echo;
190 static Lisp_Object help_echo_window;
191 static Lisp_Object help_echo_object;
192 static int help_echo_pos;
194 /* Temporary variable for XTread_socket. */
196 static Lisp_Object previous_help_echo;
198 /* Non-zero means that a HELP_EVENT has been generated since Emacs
199 start. */
201 static int any_help_event_p;
203 /* Non-zero means draw block and hollow cursor as wide as the glyph
204 under it. For example, if a block cursor is over a tab, it will be
205 drawn as wide as that tab on the display. */
207 int x_stretch_cursor_p;
209 /* This is a chain of structures for all the X displays currently in
210 use. */
212 struct x_display_info *x_display_list;
214 /* This is a list of cons cells, each of the form (NAME
215 . FONT-LIST-CACHE), one for each element of x_display_list and in
216 the same order. NAME is the name of the frame. FONT-LIST-CACHE
217 records previous values returned by x-list-fonts. */
219 Lisp_Object x_display_name_list;
221 /* This is display since Mac does not support multiple ones. */
222 struct mac_display_info one_mac_display_info;
224 /* Frame being updated by update_frame. This is declared in term.c.
225 This is set by update_begin and looked at by all the XT functions.
226 It is zero while not inside an update. In that case, the XT
227 functions assume that `selected_frame' is the frame to apply to. */
229 extern struct frame *updating_frame;
231 extern int waiting_for_input;
233 /* This is a frame waiting to be auto-raised, within XTread_socket. */
235 struct frame *pending_autoraise_frame;
237 /* Nominal cursor position -- where to draw output.
238 HPOS and VPOS are window relative glyph matrix coordinates.
239 X and Y are window relative pixel coordinates. */
241 struct cursor_pos output_cursor;
243 /* Non-zero means user is interacting with a toolkit scroll bar. */
245 static int toolkit_scroll_bar_interaction;
247 /* Mouse movement.
249 Formerly, we used PointerMotionHintMask (in standard_event_mask)
250 so that we would have to call XQueryPointer after each MotionNotify
251 event to ask for another such event. However, this made mouse tracking
252 slow, and there was a bug that made it eventually stop.
254 Simply asking for MotionNotify all the time seems to work better.
256 In order to avoid asking for motion events and then throwing most
257 of them away or busy-polling the server for mouse positions, we ask
258 the server for pointer motion hints. This means that we get only
259 one event per group of mouse movements. "Groups" are delimited by
260 other kinds of events (focus changes and button clicks, for
261 example), or by XQueryPointer calls; when one of these happens, we
262 get another MotionNotify event the next time the mouse moves. This
263 is at least as efficient as getting motion events when mouse
264 tracking is on, and I suspect only negligibly worse when tracking
265 is off. */
267 /* Where the mouse was last time we reported a mouse event. */
269 FRAME_PTR last_mouse_frame;
270 static Rect last_mouse_glyph;
271 static Lisp_Object last_mouse_press_frame;
273 /* The scroll bar in which the last X motion event occurred.
275 If the last X motion event occurred in a scroll bar, we set this so
276 XTmouse_position can know whether to report a scroll bar motion or
277 an ordinary motion.
279 If the last X motion event didn't occur in a scroll bar, we set
280 this to Qnil, to tell XTmouse_position to return an ordinary motion
281 event. */
283 static Lisp_Object last_mouse_scroll_bar;
285 /* This is a hack. We would really prefer that XTmouse_position would
286 return the time associated with the position it returns, but there
287 doesn't seem to be any way to wrest the time-stamp from the server
288 along with the position query. So, we just keep track of the time
289 of the last movement we received, and return that in hopes that
290 it's somewhat accurate. */
292 static Time last_mouse_movement_time;
294 enum mouse_tracking_type {
295 mouse_tracking_none,
296 mouse_tracking_mouse_movement,
297 mouse_tracking_scroll_bar
300 enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
302 struct scroll_bar *tracked_scroll_bar = NULL;
304 /* Incremented by XTread_socket whenever it really tries to read
305 events. */
307 #ifdef __STDC__
308 static int volatile input_signal_count;
309 #else
310 static int input_signal_count;
311 #endif
313 /* Used locally within XTread_socket. */
315 static int x_noop_count;
317 /* Initial values of argv and argc. */
319 extern char **initial_argv;
320 extern int initial_argc;
322 extern Lisp_Object Vcommand_line_args, Vsystem_name;
324 /* Tells if a window manager is present or not. */
326 extern Lisp_Object Vx_no_window_manager;
328 extern Lisp_Object Qface, Qmouse_face;
330 extern int errno;
332 /* A mask of extra modifier bits to put into every keyboard char. */
334 extern int extra_keyboard_modifiers;
336 static Lisp_Object Qvendor_specific_keysyms;
338 #if 0
339 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
340 #endif
342 extern Lisp_Object x_icon_type P_ ((struct frame *));
345 #if __MRC__
346 QDGlobals qd; /* QuickDraw global information structure. */
347 #endif
350 /* Enumeration for overriding/changing the face to use for drawing
351 glyphs in x_draw_glyphs. */
353 enum draw_glyphs_face
355 DRAW_NORMAL_TEXT,
356 DRAW_INVERSE_VIDEO,
357 DRAW_CURSOR,
358 DRAW_MOUSE_FACE,
359 DRAW_IMAGE_RAISED,
360 DRAW_IMAGE_SUNKEN
363 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
364 struct mac_display_info *mac_display_info_for_display (Display *);
365 static void x_update_window_end P_ ((struct window *, int, int));
366 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
367 void x_delete_display P_ ((struct x_display_info *));
368 static unsigned int x_mac_to_emacs_modifiers P_ ((struct x_display_info *,
369 unsigned short));
370 static int fast_find_position P_ ((struct window *, int, int *, int *,
371 int *, int *));
372 static void set_output_cursor P_ ((struct cursor_pos *));
373 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
374 int *, int *, int *));
375 static void note_mode_line_highlight P_ ((struct window *, int, int));
376 static void note_mouse_highlight P_ ((struct frame *, int, int));
377 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
378 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
379 static void show_mouse_face P_ ((struct x_display_info *,
380 enum draw_glyphs_face));
381 void clear_mouse_face P_ ((struct mac_display_info *));
382 static int x_io_error_quitter P_ ((Display *));
383 int x_catch_errors P_ ((Display *));
384 void x_uncatch_errors P_ ((Display *, int));
385 void x_lower_frame P_ ((struct frame *));
386 void x_scroll_bar_clear P_ ((struct frame *));
387 int x_had_errors_p P_ ((Display *));
388 void x_wm_set_size_hint P_ ((struct frame *, long, int));
389 void x_raise_frame P_ ((struct frame *));
390 void x_set_window_size P_ ((struct frame *, int, int, int));
391 void x_wm_set_window_state P_ ((struct frame *, int));
392 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
393 void x_initialize P_ ((void));
394 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
395 static int x_compute_min_glyph_bounds P_ ((struct frame *));
396 enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
397 static void x_draw_phys_cursor_glyph P_ ((struct window *,
398 struct glyph_row *,
399 enum draw_glyphs_face));
400 static void x_update_end P_ ((struct frame *));
401 static void XTframe_up_to_date P_ ((struct frame *));
402 static void XTreassert_line_highlight P_ ((int, int));
403 static void x_change_line_highlight P_ ((int, int, int, int));
404 static void XTset_terminal_modes P_ ((void));
405 static void XTreset_terminal_modes P_ ((void));
406 static void XTcursor_to P_ ((int, int, int, int));
407 static void x_write_glyphs P_ ((struct glyph *, int));
408 static void x_clear_end_of_line P_ ((int));
409 static void x_clear_frame P_ ((void));
410 static void x_clear_cursor P_ ((struct window *));
411 static void frame_highlight P_ ((struct frame *));
412 static void frame_unhighlight P_ ((struct frame *));
413 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
414 static void XTframe_rehighlight P_ ((struct frame *));
415 static void x_frame_rehighlight P_ ((struct x_display_info *));
416 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
417 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
418 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
419 static void expose_frame P_ ((struct frame *, int, int, int, int));
420 static void expose_window_tree P_ ((struct window *, Rect *));
421 static void expose_window P_ ((struct window *, Rect *));
422 static void expose_area P_ ((struct window *, struct glyph_row *,
423 XRectangle *, enum glyph_row_area));
424 static void expose_line P_ ((struct window *, struct glyph_row *,
425 XRectangle *));
426 void x_display_cursor (struct window *, int, int, int, int, int);
427 void x_update_cursor P_ ((struct frame *, int));
428 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
429 static void x_update_window_cursor P_ ((struct window *, int));
430 static void x_erase_phys_cursor P_ ((struct window *));
431 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
432 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
433 enum bitmap_type));
435 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
436 GC, int));
437 static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
438 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
439 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
440 static void x_flush P_ ((struct frame *f));
441 static void x_update_begin P_ ((struct frame *));
442 static void x_update_window_begin P_ ((struct window *));
443 static void x_draw_vertical_border P_ ((struct window *));
444 static void x_after_update_window_line P_ ((struct glyph_row *));
445 static INLINE void take_vertical_position_into_account P_ ((struct it *));
446 static void x_produce_stretch_glyph P_ ((struct it *));
448 static void activate_scroll_bars (FRAME_PTR);
449 static void deactivate_scroll_bars (FRAME_PTR);
451 extern int image_ascent (struct image *, struct face *);
452 void x_set_offset (struct frame *, int, int, int);
453 int x_bitmap_icon (struct frame *, Lisp_Object);
454 void x_make_frame_visible (struct frame *);
456 extern void window_scroll (Lisp_Object, int, int, int);
458 /* Defined in macmenu.h. */
459 extern void menubar_selection_callback (FRAME_PTR, int);
460 extern void set_frame_menubar (FRAME_PTR, int, int);
462 /* X display function emulation */
464 /* Structure borrowed from Xlib.h to represent two-byte characters in
465 dumpglyphs. */
467 typedef struct {
468 unsigned char byte1;
469 unsigned char byte2;
470 } XChar2b;
472 static void
473 XFreePixmap (display, pixmap)
474 Display *display;
475 Pixmap pixmap;
477 PixMap *p = (PixMap *) pixmap;
479 xfree (p->baseAddr);
480 xfree (p);
484 /* Set foreground color for subsequent QuickDraw commands. Assume
485 graphic port has already been set. */
487 static void
488 mac_set_forecolor (unsigned long color)
490 RGBColor fg_color;
492 fg_color.red = RED_FROM_ULONG (color) * 256;
493 fg_color.green = GREEN_FROM_ULONG (color) * 256;
494 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
496 RGBForeColor (&fg_color);
500 /* Set background color for subsequent QuickDraw commands. Assume
501 graphic port has already been set. */
503 static void
504 mac_set_backcolor (unsigned long color)
506 RGBColor bg_color;
508 bg_color.red = RED_FROM_ULONG (color) * 256;
509 bg_color.green = GREEN_FROM_ULONG (color) * 256;
510 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
512 RGBBackColor (&bg_color);
515 /* Set foreground and background color for subsequent QuickDraw
516 commands. Assume that the graphic port has already been set. */
518 static void
519 mac_set_colors (GC gc)
521 mac_set_forecolor (gc->foreground);
522 mac_set_backcolor (gc->background);
525 /* Mac version of XDrawLine. */
527 static void
528 XDrawLine (display, w, gc, x1, y1, x2, y2)
529 Display *display;
530 WindowPtr w;
531 GC gc;
532 int x1, y1, x2, y2;
534 SetPort (w);
535 mac_set_colors (gc);
537 MoveTo (x1, y1);
538 LineTo (x2, y2);
541 /* Mac version of XClearArea. */
543 static void
544 XClearArea (display, w, x, y, width, height, exposures)
545 Display *display;
546 WindowPtr w;
547 int x, y;
548 unsigned int width, height;
549 int exposures;
551 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
552 Rect r;
553 XGCValues xgc;
555 xgc.foreground = mwp->foreground_pixel;
556 xgc.background = mwp->background_pixel;
558 SetPort (w);
559 mac_set_colors (&xgc);
560 SetRect (&r, x, y, x + width, y + height);
562 EraseRect (&r);
565 /* Mac version of XClearWindow. */
567 static void
568 XClearWindow (display, w)
569 Display *display;
570 WindowPtr w;
572 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
573 XGCValues xgc;
575 xgc.foreground = mwp->foreground_pixel;
576 xgc.background = mwp->background_pixel;
578 SetPort (w);
579 mac_set_colors (&xgc);
581 EraseRect (&(w->portRect));
585 /* Mac replacement for XCopyArea. */
587 static void
588 mac_draw_bitmap (display, w, gc, x, y, bitmap)
589 Display *display;
590 WindowPtr w;
591 GC gc;
592 int x, y;
593 BitMap *bitmap;
595 Rect r;
597 SetPort (w);
598 mac_set_colors (gc);
599 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
601 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
605 /* Mac replacement for XSetClipRectangles. */
607 static void
608 mac_set_clip_rectangle (display, w, r)
609 Display *display;
610 WindowPtr w;
611 Rect *r;
613 SetPort (w);
615 ClipRect (r);
619 /* Mac replacement for XSetClipMask. */
621 static void
622 mac_reset_clipping (display, w)
623 Display *display;
624 WindowPtr w;
626 Rect r;
628 SetPort (w);
630 SetRect (&r, -32767, -32767, 32767, 32767);
631 ClipRect (&r);
635 /* Mac replacement for XCreateBitmapFromBitmapData. */
637 static void
638 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
639 BitMap *bitmap;
640 char *bits;
641 int w, h;
643 int bytes_per_row, i, j;
645 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
646 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
647 if (!bitmap->baseAddr)
648 abort ();
650 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
651 for (i = 0; i < h; i++)
652 for (j = 0; j < w; j++)
653 if (BitTst (bits, i * w + j))
654 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
656 SetRect (&(bitmap->bounds), 0, 0, w, h);
660 static void
661 mac_free_bitmap (bitmap)
662 BitMap *bitmap;
664 xfree (bitmap->baseAddr);
667 /* Mac replacement for XFillRectangle. */
669 static void
670 XFillRectangle (display, w, gc, x, y, width, height)
671 Display *display;
672 WindowPtr w;
673 GC gc;
674 int x, y;
675 unsigned int width, height;
677 Rect r;
679 SetPort (w);
680 mac_set_colors (gc);
681 SetRect (&r, x, y, x + width, y + height);
683 PaintRect (&r); /* using foreground color of gc */
687 /* Mac replacement for XDrawRectangle: dest is a window. */
689 static void
690 mac_draw_rectangle (display, w, gc, x, y, width, height)
691 Display *display;
692 WindowPtr w;
693 GC gc;
694 int x, y;
695 unsigned int width, height;
697 Rect r;
699 SetPort (w);
700 mac_set_colors (gc);
701 SetRect (&r, x, y, x + width + 1, y + height + 1);
703 FrameRect (&r); /* using foreground color of gc */
707 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
709 static void
710 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
711 Display *display;
712 Pixmap p;
713 GC gc;
714 int x, y;
715 unsigned int width, height;
717 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
718 Rect r;
720 SetPort (w);
721 mac_set_colors (gc);
722 SetRect (&r, x, y, x + width, y + height);
724 FrameRect (&r); /* using foreground color of gc */
725 #endif
729 static void
730 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
731 bytes_per_char)
732 Display *display;
733 WindowPtr w;
734 GC gc;
735 int x, y;
736 char *buf;
737 int nchars, mode, bytes_per_char;
739 SetPort (w);
740 mac_set_colors (gc);
742 TextFont (gc->font->mac_fontnum);
743 TextSize (gc->font->mac_fontsize);
744 TextFace (gc->font->mac_fontface);
745 TextMode (mode);
747 MoveTo (x, y);
748 DrawText (buf, 0, nchars * bytes_per_char);
752 /* Mac replacement for XDrawString. */
754 static void
755 XDrawString (display, w, gc, x, y, buf, nchars)
756 Display *display;
757 WindowPtr w;
758 GC gc;
759 int x, y;
760 char *buf;
761 int nchars;
763 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
767 /* Mac replacement for XDrawString16. */
769 static void
770 XDrawString16 (display, w, gc, x, y, buf, nchars)
771 Display *display;
772 WindowPtr w;
773 GC gc;
774 int x, y;
775 XChar2b *buf;
776 int nchars;
778 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
783 /* Mac replacement for XDrawImageString. */
785 static void
786 XDrawImageString (display, w, gc, x, y, buf, nchars)
787 Display *display;
788 WindowPtr w;
789 GC gc;
790 int x, y;
791 char *buf;
792 int nchars;
794 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
798 /* Mac replacement for XDrawString16. */
800 static void
801 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
802 Display *display;
803 WindowPtr w;
804 GC gc;
805 int x, y;
806 XChar2b *buf;
807 int nchars;
809 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
814 /* Mac replacement for XCopyArea: dest must be window. */
816 static void
817 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
818 dest_y)
819 Display *display;
820 Pixmap src;
821 WindowPtr dest;
822 GC gc;
823 int src_x, src_y;
824 unsigned int width, height;
825 int dest_x, dest_y;
827 Rect src_r, dest_r;
829 SetPort (dest);
830 mac_set_colors (gc);
832 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
833 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
835 CopyBits ((BitMap *) src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
839 /* Convert a pair of local coordinates to global (screen) coordinates.
840 Assume graphic port has been properly set. */
841 static void
842 local_to_global_coord (short *h, short *v)
844 Point p;
846 p.h = *h;
847 p.v = *v;
849 LocalToGlobal (&p);
851 *h = p.h;
852 *v = p.v;
856 /* Mac replacement for XCopyArea: used only for scrolling. */
858 static void
859 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
860 Display *display;
861 WindowPtr w;
862 GC gc;
863 int src_x, src_y;
864 unsigned int width, height;
865 int dest_x, dest_y;
867 Rect src_r, dest_r;
869 SetPort (w);
870 mac_set_colors (gc);
872 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
873 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
875 /* Need to use global coordinates and screenBits since src and dest
876 areas overlap in general. */
877 local_to_global_coord (&src_r.left, &src_r.top);
878 local_to_global_coord (&src_r.right, &src_r.bottom);
879 local_to_global_coord (&dest_r.left, &dest_r.top);
880 local_to_global_coord (&dest_r.right, &dest_r.bottom);
882 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
886 /* Mac replacement for XCopyArea: dest must be Pixmap. */
888 static void
889 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
890 dest_x, dest_y)
891 Display *display;
892 Pixmap src;
893 Pixmap dest;
894 GC gc;
895 int src_x, src_y;
896 unsigned int width, height;
897 int dest_x, dest_y;
899 Rect src_r, dest_r;
900 int src_right = ((PixMap *) src)->bounds.right;
901 int src_bottom = ((PixMap *) src)->bounds.bottom;
902 int w = src_right - src_x;
903 int h = src_bottom - src_y;
905 mac_set_colors (gc);
907 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
908 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
910 CopyBits ((BitMap *) src, (BitMap *) dest, &src_r, &dest_r, srcCopy, 0);
914 /* Mac replacement for XChangeGC. */
916 static void
917 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
918 XGCValues *xgcv)
920 if (mask & GCForeground)
921 gc->foreground = xgcv->foreground;
922 if (mask & GCBackground)
923 gc->background = xgcv->background;
924 if (mask & GCFont)
925 gc->font = xgcv->font;
929 /* Mac replacement for XCreateGC. */
931 XGCValues *
932 XCreateGC (void * ignore, Window window, unsigned long mask,
933 XGCValues *xgcv)
935 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
936 bzero (gc, sizeof (XGCValues));
938 XChangeGC (ignore, gc, mask, xgcv);
940 return gc;
944 /* Used in xfaces.c. */
946 void
947 XFreeGC (display, gc)
948 Display *display;
949 GC gc;
951 xfree (gc);
955 /* Mac replacement for XGetGCValues. */
957 static void
958 XGetGCValues (void* ignore, XGCValues *gc,
959 unsigned long mask, XGCValues *xgcv)
961 XChangeGC (ignore, xgcv, mask, gc);
965 /* Mac replacement for XSetForeground. */
967 static void
968 XSetForeground (display, gc, color)
969 Display *display;
970 GC gc;
971 unsigned long color;
973 gc->foreground = color;
977 /* Mac replacement for XSetFont. */
979 static void
980 XSetFont (display, gc, font)
981 Display *display;
982 GC gc;
983 XFontStruct *font;
985 gc->font = font;
989 static void
990 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
991 int *direction,int *font_ascent,
992 int *font_descent, XCharStruct *cs)
994 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
998 /* x_sync is a no-op on Mac. */
999 void
1000 x_sync (f)
1001 void *f;
1006 /* Flush display of frame F, or of all frames if F is null. */
1008 void
1009 x_flush (f)
1010 struct frame *f;
1012 #if 0 /* Nothing to do for Mac OS (needed in OS X perhaps?). */
1013 BLOCK_INPUT;
1014 if (f == NULL)
1016 Lisp_Object rest, frame;
1017 FOR_EACH_FRAME (rest, frame)
1018 x_flush (XFRAME (frame));
1020 else if (FRAME_X_P (f))
1021 XFlush (FRAME_MAC_DISPLAY (f));
1022 UNBLOCK_INPUT;
1023 #endif
1027 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1028 Calls to XFlush should be unnecessary because the X output buffer
1029 is flushed automatically as needed by calls to XPending,
1030 XNextEvent, or XWindowEvent according to the XFlush man page.
1031 XTread_socket calls XPending. Removing XFlush improves
1032 performance. */
1034 #define XFlush(DISPLAY) (void) 0
1037 /* Return the struct mac_display_info corresponding to DPY. There's
1038 only one. */
1040 struct mac_display_info *
1041 mac_display_info_for_display (dpy)
1042 Display *dpy;
1044 return &one_mac_display_info;
1049 /***********************************************************************
1050 Starting and ending an update
1051 ***********************************************************************/
1053 /* Start an update of frame F. This function is installed as a hook
1054 for update_begin, i.e. it is called when update_begin is called.
1055 This function is called prior to calls to x_update_window_begin for
1056 each window being updated. Currently, there is nothing to do here
1057 because all interesting stuff is done on a window basis. */
1059 void
1060 x_update_begin (f)
1061 struct frame *f;
1063 /* Nothing to do. */
1067 /* Start update of window W. Set the global variable updated_window
1068 to the window being updated and set output_cursor to the cursor
1069 position of W. */
1071 void
1072 x_update_window_begin (w)
1073 struct window *w;
1075 struct frame *f = XFRAME (WINDOW_FRAME (w));
1076 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1078 updated_window = w;
1079 set_output_cursor (&w->cursor);
1081 BLOCK_INPUT;
1083 if (f == display_info->mouse_face_mouse_frame)
1085 /* Don't do highlighting for mouse motion during the update. */
1086 display_info->mouse_face_defer = 1;
1088 /* If F needs to be redrawn, simply forget about any prior mouse
1089 highlighting. */
1090 if (FRAME_GARBAGED_P (f))
1091 display_info->mouse_face_window = Qnil;
1093 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1094 their mouse_face_p flag set, which means that they are always
1095 unequal to rows in a desired matrix which never have that
1096 flag set. So, rows containing mouse-face glyphs are never
1097 scrolled, and we don't have to switch the mouse highlight off
1098 here to prevent it from being scrolled. */
1100 /* Can we tell that this update does not affect the window
1101 where the mouse highlight is? If so, no need to turn off.
1102 Likewise, don't do anything if the frame is garbaged;
1103 in that case, the frame's current matrix that we would use
1104 is all wrong, and we will redisplay that line anyway. */
1105 if (!NILP (display_info->mouse_face_window)
1106 && w == XWINDOW (display_info->mouse_face_window))
1108 int i;
1110 for (i = 0; i < w->desired_matrix->nrows; ++i)
1111 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1112 break;
1114 if (i < w->desired_matrix->nrows)
1115 clear_mouse_face (display_info);
1117 #endif /* 0 */
1120 UNBLOCK_INPUT;
1124 /* Draw a vertical window border to the right of window W if W doesn't
1125 have vertical scroll bars. */
1127 static void
1128 x_draw_vertical_border (w)
1129 struct window *w;
1131 struct frame *f = XFRAME (WINDOW_FRAME (w));
1133 /* Redraw borders between horizontally adjacent windows. Don't
1134 do it for frames with vertical scroll bars because either the
1135 right scroll bar of a window, or the left scroll bar of its
1136 neighbor will suffice as a border. */
1137 if (!WINDOW_RIGHTMOST_P (w)
1138 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1140 int x0, x1, y0, y1;
1142 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1143 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
1144 y1 -= 1;
1146 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1147 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1152 /* End update of window W (which is equal to updated_window).
1154 Draw vertical borders between horizontally adjacent windows, and
1155 display W's cursor if CURSOR_ON_P is non-zero.
1157 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1158 glyphs in mouse-face were overwritten. In that case we have to
1159 make sure that the mouse-highlight is properly redrawn.
1161 W may be a menu bar pseudo-window in case we don't have X toolkit
1162 support. Such windows don't have a cursor, so don't display it
1163 here. */
1165 void
1166 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1167 struct window *w;
1168 int cursor_on_p, mouse_face_overwritten_p;
1170 if (!w->pseudo_window_p)
1172 struct mac_display_info *dpyinfo
1173 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1175 BLOCK_INPUT;
1177 /* If a row with mouse-face was overwritten, arrange for
1178 XTframe_up_to_date to redisplay the mouse highlight. */
1179 if (mouse_face_overwritten_p)
1181 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1182 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1183 dpyinfo->mouse_face_window = Qnil;
1186 if (cursor_on_p)
1187 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1188 output_cursor.vpos,
1189 output_cursor.x, output_cursor.y);
1191 x_draw_vertical_border (w);
1192 UNBLOCK_INPUT;
1195 updated_window = NULL;
1199 /* End update of frame F. This function is installed as a hook in
1200 update_end. */
1202 void
1203 x_update_end (f)
1204 struct frame *f;
1206 /* Reset the background color of Mac OS Window to that of the frame after
1207 update so that it is used by Mac Toolbox to clear the update region before
1208 an update event is generated. */
1209 SetPort (FRAME_MAC_WINDOW (f));
1210 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1212 /* Mouse highlight may be displayed again. */
1213 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1215 BLOCK_INPUT;
1216 XFlush (FRAME_MAC_DISPLAY (f));
1217 UNBLOCK_INPUT;
1221 /* This function is called from various places in xdisp.c whenever a
1222 complete update has been performed. The global variable
1223 updated_window is not available here. */
1225 void
1226 XTframe_up_to_date (f)
1227 struct frame *f;
1229 if (FRAME_X_P (f))
1231 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1233 if (dpyinfo->mouse_face_deferred_gc
1234 || f == dpyinfo->mouse_face_mouse_frame)
1236 BLOCK_INPUT;
1237 if (dpyinfo->mouse_face_mouse_frame)
1238 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1239 dpyinfo->mouse_face_mouse_x,
1240 dpyinfo->mouse_face_mouse_y);
1241 dpyinfo->mouse_face_deferred_gc = 0;
1242 UNBLOCK_INPUT;
1248 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1249 arrow bitmaps, or clear the areas where they would be displayed
1250 before DESIRED_ROW is made current. The window being updated is
1251 found in updated_window. This function It is called from
1252 update_window_line only if it is known that there are differences
1253 between bitmaps to be drawn between current row and DESIRED_ROW. */
1255 void
1256 x_after_update_window_line (desired_row)
1257 struct glyph_row *desired_row;
1259 struct window *w = updated_window;
1261 xassert (w);
1263 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1265 BLOCK_INPUT;
1266 x_draw_row_bitmaps (w, desired_row);
1268 /* When a window has disappeared, make sure that no rest of
1269 full-width rows stays visible in the internal border. */
1270 if (windows_or_buffers_changed)
1272 struct frame *f = XFRAME (w->frame);
1273 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
1274 int height = desired_row->visible_height;
1275 int x = (window_box_right (w, -1)
1276 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
1277 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1279 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1280 x, y, width, height, 0);
1283 UNBLOCK_INPUT;
1288 /* Draw the bitmap WHICH in one of the areas to the left or right of
1289 window W. ROW is the glyph row for which to display the bitmap; it
1290 determines the vertical position at which the bitmap has to be
1291 drawn. */
1293 static void
1294 x_draw_bitmap (w, row, which)
1295 struct window *w;
1296 struct glyph_row *row;
1297 enum bitmap_type which;
1299 struct frame *f = XFRAME (WINDOW_FRAME (w));
1300 Display *display = FRAME_MAC_DISPLAY (f);
1301 WindowPtr window = FRAME_MAC_WINDOW (f);
1302 int x, y, wd, h, dy;
1303 unsigned char *bits;
1304 BitMap bitmap;
1305 XGCValues gcv;
1306 struct face *face;
1308 /* Must clip because of partially visible lines. */
1309 x_clip_to_row (w, row, 1);
1311 switch (which)
1313 case LEFT_TRUNCATION_BITMAP:
1314 wd = left_width;
1315 h = left_height;
1316 bits = left_bits;
1317 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1318 - wd
1319 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
1320 break;
1322 case OVERLAY_ARROW_BITMAP:
1323 wd = left_width;
1324 h = left_height;
1325 bits = ov_bits;
1326 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1327 - wd
1328 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
1329 break;
1331 case RIGHT_TRUNCATION_BITMAP:
1332 wd = right_width;
1333 h = right_height;
1334 bits = right_bits;
1335 x = window_box_right (w, -1);
1336 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
1337 break;
1339 case CONTINUED_LINE_BITMAP:
1340 wd = right_width;
1341 h = right_height;
1342 bits = continued_bits;
1343 x = window_box_right (w, -1);
1344 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
1345 break;
1347 case CONTINUATION_LINE_BITMAP:
1348 wd = continuation_width;
1349 h = continuation_height;
1350 bits = continuation_bits;
1351 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1352 - wd
1353 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
1354 break;
1356 case ZV_LINE_BITMAP:
1357 wd = zv_width;
1358 h = zv_height;
1359 bits = zv_bits;
1360 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1361 - wd
1362 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
1363 break;
1365 default:
1366 abort ();
1369 /* Convert to frame coordinates. Set dy to the offset in the row to
1370 start drawing the bitmap. */
1371 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1372 dy = (row->height - h) / 2;
1374 /* Draw the bitmap. I believe these small pixmaps can be cached
1375 by the server. */
1376 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
1378 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1379 gcv.foreground = face->foreground;
1380 gcv.background = face->background;
1382 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1384 mac_free_bitmap (&bitmap);
1385 mac_reset_clipping (display, window);
1389 /* Draw flags bitmaps for glyph row ROW on window W. Call this
1390 function with input blocked. */
1392 static void
1393 x_draw_row_bitmaps (w, row)
1394 struct window *w;
1395 struct glyph_row *row;
1397 struct frame *f = XFRAME (w->frame);
1398 enum bitmap_type bitmap;
1399 struct face *face;
1400 int header_line_height = -1;
1402 xassert (interrupt_input_blocked);
1404 /* If row is completely invisible, because of vscrolling, we
1405 don't have to draw anything. */
1406 if (row->visible_height <= 0)
1407 return;
1409 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
1410 PREPARE_FACE_FOR_DISPLAY (f, face);
1412 /* Decide which bitmap to draw at the left side. */
1413 if (row->overlay_arrow_p)
1414 bitmap = OVERLAY_ARROW_BITMAP;
1415 else if (row->truncated_on_left_p)
1416 bitmap = LEFT_TRUNCATION_BITMAP;
1417 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1418 bitmap = CONTINUATION_LINE_BITMAP;
1419 else if (row->indicate_empty_line_p)
1420 bitmap = ZV_LINE_BITMAP;
1421 else
1422 bitmap = NO_BITMAP;
1424 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
1425 the flags area. */
1426 if (bitmap == NO_BITMAP
1427 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
1428 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
1430 /* If W has a vertical border to its left, don't draw over it. */
1431 int border = ((XFASTINT (w->left) > 0
1432 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1433 ? 1 : 0);
1434 int left = window_box_left (w, -1);
1436 if (header_line_height < 0)
1437 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1439 #if 0 /* MAC_TODO: stipple */
1440 /* In case the same realized face is used for bitmap areas and
1441 for something displayed in the text (e.g. face `region' on
1442 mono-displays, the fill style may have been changed to
1443 FillSolid in x_draw_glyph_string_background. */
1444 if (face->stipple)
1445 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1446 else
1447 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1449 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1450 face->gc,
1451 (left
1452 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
1453 + border),
1454 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1455 row->y)),
1456 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
1457 row->visible_height);
1458 if (!face->stipple)
1459 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1460 #endif
1462 XGCValues gcv;
1463 gcv.foreground = face->background;
1464 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1465 &gcv,
1466 (left
1467 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
1468 + border),
1469 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1470 row->y)),
1471 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
1472 row->visible_height);
1477 /* Draw the left bitmap. */
1478 if (bitmap != NO_BITMAP)
1479 x_draw_bitmap (w, row, bitmap);
1481 /* Decide which bitmap to draw at the right side. */
1482 if (row->truncated_on_right_p)
1483 bitmap = RIGHT_TRUNCATION_BITMAP;
1484 else if (row->continued_p)
1485 bitmap = CONTINUED_LINE_BITMAP;
1486 else
1487 bitmap = NO_BITMAP;
1489 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
1490 the flags area. */
1491 if (bitmap == NO_BITMAP
1492 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
1493 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
1495 int right = window_box_right (w, -1);
1497 if (header_line_height < 0)
1498 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1500 #if 0 /* MAC_TODO: stipple */
1501 /* In case the same realized face is used for bitmap areas and
1502 for something displayed in the text (e.g. face `region' on
1503 mono-displays, the fill style may have been changed to
1504 FillSolid in x_draw_glyph_string_background. */
1505 if (face->stipple)
1506 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1507 else
1508 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1509 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1510 face->gc,
1511 right,
1512 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1513 row->y)),
1514 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
1515 row->visible_height);
1516 if (!face->stipple)
1517 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1518 #endif
1520 XGCValues gcv;
1521 gcv.foreground = face->background;
1522 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1523 &gcv,
1524 right,
1525 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1526 row->y)),
1527 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
1528 row->visible_height);
1533 /* Draw the right bitmap. */
1534 if (bitmap != NO_BITMAP)
1535 x_draw_bitmap (w, row, bitmap);
1539 /***********************************************************************
1540 Line Highlighting
1541 ***********************************************************************/
1543 /* External interface to control of standout mode. Not used for X
1544 frames. Aborts when called. */
1546 void
1547 XTreassert_line_highlight (new, vpos)
1548 int new, vpos;
1550 abort ();
1554 /* Call this when about to modify line at position VPOS and change
1555 whether it is highlighted. Not used for X frames. Aborts when
1556 called. */
1558 void
1559 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1560 int new_highlight, vpos, y, first_unused_hpos;
1562 abort ();
1566 /* This is called when starting Emacs and when restarting after
1567 suspend. When starting Emacs, no X window is mapped. And nothing
1568 must be done to Emacs's own window if it is suspended (though that
1569 rarely happens). */
1571 void
1572 XTset_terminal_modes ()
1576 /* This is called when exiting or suspending Emacs. Exiting will make
1577 the X-windows go away, and suspending requires no action. */
1579 void
1580 XTreset_terminal_modes ()
1586 /***********************************************************************
1587 Output Cursor
1588 ***********************************************************************/
1590 /* Set the global variable output_cursor to CURSOR. All cursor
1591 positions are relative to updated_window. */
1593 static void
1594 set_output_cursor (cursor)
1595 struct cursor_pos *cursor;
1597 output_cursor.hpos = cursor->hpos;
1598 output_cursor.vpos = cursor->vpos;
1599 output_cursor.x = cursor->x;
1600 output_cursor.y = cursor->y;
1604 /* Set a nominal cursor position.
1606 HPOS and VPOS are column/row positions in a window glyph matrix. X
1607 and Y are window text area relative pixel positions.
1609 If this is done during an update, updated_window will contain the
1610 window that is being updated and the position is the future output
1611 cursor position for that window. If updated_window is null, use
1612 selected_window and display the cursor at the given position. */
1614 void
1615 XTcursor_to (vpos, hpos, y, x)
1616 int vpos, hpos, y, x;
1618 struct window *w;
1620 /* If updated_window is not set, work on selected_window. */
1621 if (updated_window)
1622 w = updated_window;
1623 else
1624 w = XWINDOW (selected_window);
1626 /* Set the output cursor. */
1627 output_cursor.hpos = hpos;
1628 output_cursor.vpos = vpos;
1629 output_cursor.x = x;
1630 output_cursor.y = y;
1632 /* If not called as part of an update, really display the cursor.
1633 This will also set the cursor position of W. */
1634 if (updated_window == NULL)
1636 BLOCK_INPUT;
1637 x_display_cursor (w, 1, hpos, vpos, x, y);
1638 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1639 UNBLOCK_INPUT;
1645 /***********************************************************************
1646 Display Iterator
1647 ***********************************************************************/
1649 /* Function prototypes of this page. */
1651 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1652 struct glyph *,
1653 XChar2b *,
1654 int *));
1655 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1656 int, XChar2b *, int));
1657 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1658 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1659 static void x_append_glyph P_ ((struct it *));
1660 static void x_append_composite_glyph P_ ((struct it *));
1661 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1662 int, int, double));
1663 static void x_produce_glyphs P_ ((struct it *));
1664 static void x_produce_image_glyph P_ ((struct it *it));
1667 /* Return a pointer to per-char metric information in FONT of a
1668 character pointed by B which is a pointer to an XChar2b. */
1670 #define PER_CHAR_METRIC(font, b) \
1671 ((font)->per_char \
1672 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1673 + (((font)->min_byte1 || (font)->max_byte1) \
1674 ? (((b)->byte1 - (font)->min_byte1) \
1675 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1676 : 0)) \
1677 : &((font)->max_bounds))
1680 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1681 is not contained in the font. */
1683 static INLINE XCharStruct *
1684 x_per_char_metric (font, char2b)
1685 XFontStruct *font;
1686 XChar2b *char2b;
1688 /* The result metric information. */
1689 XCharStruct *pcm = NULL;
1691 xassert (font && char2b);
1693 if (font->per_char != NULL)
1695 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1697 /* min_char_or_byte2 specifies the linear character index
1698 corresponding to the first element of the per_char array,
1699 max_char_or_byte2 is the index of the last character. A
1700 character with non-zero CHAR2B->byte1 is not in the font.
1701 A character with byte2 less than min_char_or_byte2 or
1702 greater max_char_or_byte2 is not in the font. */
1703 if (char2b->byte1 == 0
1704 && char2b->byte2 >= font->min_char_or_byte2
1705 && char2b->byte2 <= font->max_char_or_byte2)
1706 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1708 else
1710 /* If either min_byte1 or max_byte1 are nonzero, both
1711 min_char_or_byte2 and max_char_or_byte2 are less than
1712 256, and the 2-byte character index values corresponding
1713 to the per_char array element N (counting from 0) are:
1715 byte1 = N/D + min_byte1
1716 byte2 = N\D + min_char_or_byte2
1718 where:
1720 D = max_char_or_byte2 - min_char_or_byte2 + 1
1721 / = integer division
1722 \ = integer modulus */
1723 if (char2b->byte1 >= font->min_byte1
1724 && char2b->byte1 <= font->max_byte1
1725 && char2b->byte2 >= font->min_char_or_byte2
1726 && char2b->byte2 <= font->max_char_or_byte2)
1728 pcm = (font->per_char
1729 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1730 * (char2b->byte1 - font->min_byte1))
1731 + (char2b->byte2 - font->min_char_or_byte2));
1735 else
1737 /* If the per_char pointer is null, all glyphs between the first
1738 and last character indexes inclusive have the same
1739 information, as given by both min_bounds and max_bounds. */
1740 if (char2b->byte2 >= font->min_char_or_byte2
1741 && char2b->byte2 <= font->max_char_or_byte2)
1742 pcm = &font->max_bounds;
1745 return ((pcm == NULL
1746 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1747 ? NULL : pcm);
1751 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1752 the two-byte form of C. Encoding is returned in *CHAR2B. */
1754 static INLINE void
1755 x_encode_char (c, char2b, font_info)
1756 int c;
1757 XChar2b *char2b;
1758 struct font_info *font_info;
1760 int charset = CHAR_CHARSET (c);
1761 XFontStruct *font = font_info->font;
1763 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1764 This may be either a program in a special encoder language or a
1765 fixed encoding. */
1766 if (font_info->font_encoder)
1768 /* It's a program. */
1769 struct ccl_program *ccl = font_info->font_encoder;
1771 if (CHARSET_DIMENSION (charset) == 1)
1773 ccl->reg[0] = charset;
1774 ccl->reg[1] = char2b->byte2;
1776 else
1778 ccl->reg[0] = charset;
1779 ccl->reg[1] = char2b->byte1;
1780 ccl->reg[2] = char2b->byte2;
1783 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1785 /* We assume that MSBs are appropriately set/reset by CCL
1786 program. */
1787 if (font->max_byte1 == 0) /* 1-byte font */
1788 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1789 else
1790 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1792 else if (font_info->encoding[charset])
1794 /* Fixed encoding scheme. See fontset.h for the meaning of the
1795 encoding numbers. */
1796 int enc = font_info->encoding[charset];
1798 if ((enc == 1 || enc == 2)
1799 && CHARSET_DIMENSION (charset) == 2)
1800 char2b->byte1 |= 0x80;
1802 if (enc == 1 || enc == 3)
1803 char2b->byte2 |= 0x80;
1805 if (enc == 4)
1807 int sjis1, sjis2;
1809 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1810 char2b->byte1 = sjis1;
1811 char2b->byte2 = sjis2;
1817 /* Get face and two-byte form of character C in face FACE_ID on frame
1818 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1819 means we want to display multibyte text. Value is a pointer to a
1820 realized face that is ready for display. */
1822 static INLINE struct face *
1823 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1824 struct frame *f;
1825 int c, face_id;
1826 XChar2b *char2b;
1827 int multibyte_p;
1829 struct face *face = FACE_FROM_ID (f, face_id);
1831 if (!multibyte_p)
1833 /* Unibyte case. We don't have to encode, but we have to make
1834 sure to use a face suitable for unibyte. */
1835 char2b->byte1 = 0;
1836 char2b->byte2 = c;
1837 face_id = FACE_FOR_CHAR (f, face, c);
1838 face = FACE_FROM_ID (f, face_id);
1840 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1842 /* Case of ASCII in a face known to fit ASCII. */
1843 char2b->byte1 = 0;
1844 char2b->byte2 = c;
1846 else
1848 int c1, c2, charset;
1850 /* Split characters into bytes. If c2 is -1 afterwards, C is
1851 really a one-byte character so that byte1 is zero. */
1852 SPLIT_CHAR (c, charset, c1, c2);
1853 if (c2 > 0)
1854 char2b->byte1 = c1, char2b->byte2 = c2;
1855 else
1856 char2b->byte1 = 0, char2b->byte2 = c1;
1858 /* Maybe encode the character in *CHAR2B. */
1859 if (face->font != NULL)
1861 struct font_info *font_info
1862 = FONT_INFO_FROM_ID (f, face->font_info_id);
1863 if (font_info)
1864 x_encode_char (c, char2b, font_info);
1868 /* Make sure X resources of the face are allocated. */
1869 xassert (face != NULL);
1870 PREPARE_FACE_FOR_DISPLAY (f, face);
1872 return face;
1876 /* Get face and two-byte form of character glyph GLYPH on frame F.
1877 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1878 a pointer to a realized face that is ready for display. */
1880 static INLINE struct face *
1881 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1882 struct frame *f;
1883 struct glyph *glyph;
1884 XChar2b *char2b;
1885 int *two_byte_p;
1887 struct face *face;
1889 xassert (glyph->type == CHAR_GLYPH);
1890 face = FACE_FROM_ID (f, glyph->face_id);
1892 if (two_byte_p)
1893 *two_byte_p = 0;
1895 if (!glyph->multibyte_p)
1897 /* Unibyte case. We don't have to encode, but we have to make
1898 sure to use a face suitable for unibyte. */
1899 char2b->byte1 = 0;
1900 char2b->byte2 = glyph->u.ch;
1902 else if (glyph->u.ch < 128
1903 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1905 /* Case of ASCII in a face known to fit ASCII. */
1906 char2b->byte1 = 0;
1907 char2b->byte2 = glyph->u.ch;
1909 else
1911 int c1, c2, charset;
1913 /* Split characters into bytes. If c2 is -1 afterwards, C is
1914 really a one-byte character so that byte1 is zero. */
1915 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1916 if (c2 > 0)
1917 char2b->byte1 = c1, char2b->byte2 = c2;
1918 else
1919 char2b->byte1 = 0, char2b->byte2 = c1;
1921 /* Maybe encode the character in *CHAR2B. */
1922 if (charset != CHARSET_ASCII)
1924 struct font_info *font_info
1925 = FONT_INFO_FROM_ID (f, face->font_info_id);
1926 if (font_info)
1928 x_encode_char (glyph->u.ch, char2b, font_info);
1929 if (two_byte_p)
1930 *two_byte_p
1931 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1936 /* Make sure X resources of the face are allocated. */
1937 xassert (face != NULL);
1938 PREPARE_FACE_FOR_DISPLAY (f, face);
1939 return face;
1943 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1944 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1946 static INLINE void
1947 x_append_glyph (it)
1948 struct it *it;
1950 struct glyph *glyph;
1951 enum glyph_row_area area = it->area;
1953 xassert (it->glyph_row);
1954 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1956 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1957 if (glyph < it->glyph_row->glyphs[area + 1])
1959 glyph->charpos = CHARPOS (it->position);
1960 glyph->object = it->object;
1961 glyph->pixel_width = it->pixel_width;
1962 glyph->voffset = it->voffset;
1963 glyph->type = CHAR_GLYPH;
1964 glyph->multibyte_p = it->multibyte_p;
1965 glyph->left_box_line_p = it->start_of_box_run_p;
1966 glyph->right_box_line_p = it->end_of_box_run_p;
1967 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1968 || it->phys_descent > it->descent);
1969 glyph->padding_p = 0;
1970 glyph->glyph_not_available_p = it->glyph_not_available_p;
1971 glyph->face_id = it->face_id;
1972 glyph->u.ch = it->char_to_display;
1973 ++it->glyph_row->used[area];
1977 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1978 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1980 static INLINE void
1981 x_append_composite_glyph (it)
1982 struct it *it;
1984 struct glyph *glyph;
1985 enum glyph_row_area area = it->area;
1987 xassert (it->glyph_row);
1989 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1990 if (glyph < it->glyph_row->glyphs[area + 1])
1992 glyph->charpos = CHARPOS (it->position);
1993 glyph->object = it->object;
1994 glyph->pixel_width = it->pixel_width;
1995 glyph->voffset = it->voffset;
1996 glyph->type = COMPOSITE_GLYPH;
1997 glyph->multibyte_p = it->multibyte_p;
1998 glyph->left_box_line_p = it->start_of_box_run_p;
1999 glyph->right_box_line_p = it->end_of_box_run_p;
2000 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2001 || it->phys_descent > it->descent);
2002 glyph->padding_p = 0;
2003 glyph->glyph_not_available_p = 0;
2004 glyph->face_id = it->face_id;
2005 glyph->u.cmp_id = it->cmp_id;
2006 ++it->glyph_row->used[area];
2011 /* Change IT->ascent and IT->height according to the setting of
2012 IT->voffset. */
2014 static INLINE void
2015 take_vertical_position_into_account (it)
2016 struct it *it;
2018 if (it->voffset)
2020 if (it->voffset < 0)
2021 /* Increase the ascent so that we can display the text higher
2022 in the line. */
2023 it->ascent += abs (it->voffset);
2024 else
2025 /* Increase the descent so that we can display the text lower
2026 in the line. */
2027 it->descent += it->voffset;
2032 /* Produce glyphs/get display metrics for the image IT is loaded with.
2033 See the description of struct display_iterator in dispextern.h for
2034 an overview of struct display_iterator. */
2036 static void
2037 x_produce_image_glyph (it)
2038 struct it *it;
2040 struct image *img;
2041 struct face *face;
2043 xassert (it->what == IT_IMAGE);
2045 face = FACE_FROM_ID (it->f, it->face_id);
2046 img = IMAGE_FROM_ID (it->f, it->image_id);
2047 xassert (img);
2049 /* Make sure X resources of the face and image are loaded. */
2050 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2051 prepare_image_for_display (it->f, img);
2053 it->ascent = it->phys_ascent = image_ascent (img, face);
2054 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
2055 it->pixel_width = img->width + 2 * img->margin;
2057 it->nglyphs = 1;
2059 if (face->box != FACE_NO_BOX)
2061 it->ascent += face->box_line_width;
2062 it->descent += face->box_line_width;
2064 if (it->start_of_box_run_p)
2065 it->pixel_width += face->box_line_width;
2066 if (it->end_of_box_run_p)
2067 it->pixel_width += face->box_line_width;
2070 take_vertical_position_into_account (it);
2072 if (it->glyph_row)
2074 struct glyph *glyph;
2075 enum glyph_row_area area = it->area;
2077 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2078 if (glyph < it->glyph_row->glyphs[area + 1])
2080 glyph->charpos = CHARPOS (it->position);
2081 glyph->object = it->object;
2082 glyph->pixel_width = it->pixel_width;
2083 glyph->voffset = it->voffset;
2084 glyph->type = IMAGE_GLYPH;
2085 glyph->multibyte_p = it->multibyte_p;
2086 glyph->left_box_line_p = it->start_of_box_run_p;
2087 glyph->right_box_line_p = it->end_of_box_run_p;
2088 glyph->overlaps_vertically_p = 0;
2089 glyph->padding_p = 0;
2090 glyph->glyph_not_available_p = 0;
2091 glyph->face_id = it->face_id;
2092 glyph->u.img_id = img->id;
2093 ++it->glyph_row->used[area];
2099 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2100 of the glyph, WIDTH and HEIGHT are the width and height of the
2101 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2102 ascent of the glyph (0 <= ASCENT <= 1). */
2104 static void
2105 x_append_stretch_glyph (it, object, width, height, ascent)
2106 struct it *it;
2107 Lisp_Object object;
2108 int width, height;
2109 double ascent;
2111 struct glyph *glyph;
2112 enum glyph_row_area area = it->area;
2114 xassert (ascent >= 0 && ascent <= 1);
2116 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2117 if (glyph < it->glyph_row->glyphs[area + 1])
2119 glyph->charpos = CHARPOS (it->position);
2120 glyph->object = object;
2121 glyph->pixel_width = width;
2122 glyph->voffset = it->voffset;
2123 glyph->type = STRETCH_GLYPH;
2124 glyph->multibyte_p = it->multibyte_p;
2125 glyph->left_box_line_p = it->start_of_box_run_p;
2126 glyph->right_box_line_p = it->end_of_box_run_p;
2127 glyph->overlaps_vertically_p = 0;
2128 glyph->padding_p = 0;
2129 glyph->glyph_not_available_p = 0;
2130 glyph->face_id = it->face_id;
2131 glyph->u.stretch.ascent = height * ascent;
2132 glyph->u.stretch.height = height;
2133 ++it->glyph_row->used[area];
2138 /* Produce a stretch glyph for iterator IT. IT->object is the value
2139 of the glyph property displayed. The value must be a list
2140 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2141 being recognized:
2143 1. `:width WIDTH' specifies that the space should be WIDTH *
2144 canonical char width wide. WIDTH may be an integer or floating
2145 point number.
2147 2. `:relative-width FACTOR' specifies that the width of the stretch
2148 should be computed from the width of the first character having the
2149 `glyph' property, and should be FACTOR times that width.
2151 3. `:align-to HPOS' specifies that the space should be wide enough
2152 to reach HPOS, a value in canonical character units.
2154 Exactly one of the above pairs must be present.
2156 4. `:height HEIGHT' specifies that the height of the stretch produced
2157 should be HEIGHT, measured in canonical character units.
2159 5. `:relative-height FACTOR' specifies that the height of the the
2160 stretch should be FACTOR times the height of the characters having
2161 the glyph property.
2163 Either none or exactly one of 4 or 5 must be present.
2165 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2166 of the stretch should be used for the ascent of the stretch.
2167 ASCENT must be in the range 0 <= ASCENT <= 100. */
2169 #define NUMVAL(X) \
2170 ((INTEGERP (X) || FLOATP (X)) \
2171 ? XFLOATINT (X) \
2172 : - 1)
2175 static void
2176 x_produce_stretch_glyph (it)
2177 struct it *it;
2179 /* (space :width WIDTH :height HEIGHT. */
2180 #if GLYPH_DEBUG
2181 extern Lisp_Object Qspace;
2182 #endif
2183 extern Lisp_Object QCwidth, QCheight, QCascent;
2184 extern Lisp_Object QCrelative_width, QCrelative_height;
2185 extern Lisp_Object QCalign_to;
2186 Lisp_Object prop, plist;
2187 double width = 0, height = 0, ascent = 0;
2188 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2189 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2191 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2193 /* List should start with `space'. */
2194 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2195 plist = XCDR (it->object);
2197 /* Compute the width of the stretch. */
2198 if (prop = Fplist_get (plist, QCwidth),
2199 NUMVAL (prop) > 0)
2200 /* Absolute width `:width WIDTH' specified and valid. */
2201 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2202 else if (prop = Fplist_get (plist, QCrelative_width),
2203 NUMVAL (prop) > 0)
2205 /* Relative width `:relative-width FACTOR' specified and valid.
2206 Compute the width of the characters having the `glyph'
2207 property. */
2208 struct it it2;
2209 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2211 it2 = *it;
2212 if (it->multibyte_p)
2214 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2215 - IT_BYTEPOS (*it));
2216 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2218 else
2219 it2.c = *p, it2.len = 1;
2221 it2.glyph_row = NULL;
2222 it2.what = IT_CHARACTER;
2223 x_produce_glyphs (&it2);
2224 width = NUMVAL (prop) * it2.pixel_width;
2226 else if (prop = Fplist_get (plist, QCalign_to),
2227 NUMVAL (prop) > 0)
2228 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2229 else
2230 /* Nothing specified -> width defaults to canonical char width. */
2231 width = CANON_X_UNIT (it->f);
2233 /* Compute height. */
2234 if (prop = Fplist_get (plist, QCheight),
2235 NUMVAL (prop) > 0)
2236 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2237 else if (prop = Fplist_get (plist, QCrelative_height),
2238 NUMVAL (prop) > 0)
2239 height = FONT_HEIGHT (font) * NUMVAL (prop);
2240 else
2241 height = FONT_HEIGHT (font);
2243 /* Compute percentage of height used for ascent. If
2244 `:ascent ASCENT' is present and valid, use that. Otherwise,
2245 derive the ascent from the font in use. */
2246 if (prop = Fplist_get (plist, QCascent),
2247 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2248 ascent = NUMVAL (prop) / 100.0;
2249 else
2250 ascent = (double) font->ascent / FONT_HEIGHT (font);
2252 if (width <= 0)
2253 width = 1;
2254 if (height <= 0)
2255 height = 1;
2257 if (it->glyph_row)
2259 Lisp_Object object = it->stack[it->sp - 1].string;
2260 if (!STRINGP (object))
2261 object = it->w->buffer;
2262 x_append_stretch_glyph (it, object, width, height, ascent);
2265 it->pixel_width = width;
2266 it->ascent = it->phys_ascent = height * ascent;
2267 it->descent = it->phys_descent = height - it->ascent;
2268 it->nglyphs = 1;
2270 if (face->box != FACE_NO_BOX)
2272 it->ascent += face->box_line_width;
2273 it->descent += face->box_line_width;
2275 if (it->start_of_box_run_p)
2276 it->pixel_width += face->box_line_width;
2277 if (it->end_of_box_run_p)
2278 it->pixel_width += face->box_line_width;
2281 take_vertical_position_into_account (it);
2284 /* Return proper value to be used as baseline offset of font that has
2285 ASCENT and DESCENT to draw characters by the font at the vertical
2286 center of the line of frame F.
2288 Here, out task is to find the value of BOFF in the following figure;
2290 -------------------------+-----------+-
2291 -+-+---------+-+ | |
2292 | | | | | |
2293 | | | | F_ASCENT F_HEIGHT
2294 | | | ASCENT | |
2295 HEIGHT | | | | |
2296 | | |-|-+------+-----------|------- baseline
2297 | | | | BOFF | |
2298 | |---------|-+-+ | |
2299 | | | DESCENT | |
2300 -+-+---------+-+ F_DESCENT |
2301 -------------------------+-----------+-
2303 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2304 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2305 DESCENT = FONT->descent
2306 HEIGHT = FONT_HEIGHT (FONT)
2307 F_DESCENT = (F->output_data.x->font->descent
2308 - F->output_data.x->baseline_offset)
2309 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2312 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2313 ((FONT)->descent \
2314 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
2315 - ((F)->output_data.mac->font->descent - (F)->output_data.mac->baseline_offset))
2317 /* Produce glyphs/get display metrics for the display element IT is
2318 loaded with. See the description of struct display_iterator in
2319 dispextern.h for an overview of struct display_iterator. */
2321 void
2322 x_produce_glyphs (it)
2323 struct it *it;
2325 it->glyph_not_available_p = 0;
2327 if (it->what == IT_CHARACTER)
2329 XChar2b char2b;
2330 XFontStruct *font;
2331 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2332 XCharStruct *pcm;
2333 int font_not_found_p;
2334 struct font_info *font_info;
2335 int boff; /* baseline offset */
2337 /* Maybe translate single-byte characters to multibyte, or the
2338 other way. */
2339 it->char_to_display = it->c;
2340 if (!ASCII_BYTE_P (it->c))
2342 if (unibyte_display_via_language_environment
2343 && SINGLE_BYTE_CHAR_P (it->c)
2344 && (it->c >= 0240
2345 || !NILP (Vnonascii_translation_table)))
2347 it->char_to_display = unibyte_char_to_multibyte (it->c);
2348 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2349 face = FACE_FROM_ID (it->f, it->face_id);
2351 else if (!SINGLE_BYTE_CHAR_P (it->c)
2352 && !it->multibyte_p)
2354 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
2355 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2356 face = FACE_FROM_ID (it->f, it->face_id);
2360 /* Get font to use. Encode IT->char_to_display. */
2361 x_get_char_face_and_encoding (it->f, it->char_to_display,
2362 it->face_id, &char2b,
2363 it->multibyte_p);
2364 font = face->font;
2366 /* When no suitable font found, use the default font. */
2367 font_not_found_p = font == NULL;
2368 if (font_not_found_p)
2370 font = FRAME_FONT (it->f);
2371 boff = it->f->output_data.mac->baseline_offset;
2372 font_info = NULL;
2374 else
2376 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2377 boff = font_info->baseline_offset;
2378 if (font_info->vertical_centering)
2379 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2382 if (it->char_to_display >= ' '
2383 && (!it->multibyte_p || it->char_to_display < 128))
2385 /* Either unibyte or ASCII. */
2386 int stretched_p;
2388 it->nglyphs = 1;
2390 pcm = x_per_char_metric (font, &char2b);
2391 it->ascent = font->ascent + boff;
2392 it->descent = font->descent - boff;
2394 if (pcm)
2396 it->phys_ascent = pcm->ascent + boff;
2397 it->phys_descent = pcm->descent - boff;
2398 it->pixel_width = pcm->width;
2400 else
2402 it->glyph_not_available_p = 1;
2403 it->phys_ascent = font->ascent + boff;
2404 it->phys_descent = font->descent - boff;
2405 it->pixel_width = FONT_WIDTH (font);
2408 /* If this is a space inside a region of text with
2409 `space-width' property, change its width. */
2410 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2411 if (stretched_p)
2412 it->pixel_width *= XFLOATINT (it->space_width);
2414 /* If face has a box, add the box thickness to the character
2415 height. If character has a box line to the left and/or
2416 right, add the box line width to the character's width. */
2417 if (face->box != FACE_NO_BOX)
2419 int thick = face->box_line_width;
2421 it->ascent += thick;
2422 it->descent += thick;
2424 if (it->start_of_box_run_p)
2425 it->pixel_width += thick;
2426 if (it->end_of_box_run_p)
2427 it->pixel_width += thick;
2430 /* If face has an overline, add the height of the overline
2431 (1 pixel) and a 1 pixel margin to the character height. */
2432 if (face->overline_p)
2433 it->ascent += 2;
2435 take_vertical_position_into_account (it);
2437 /* If we have to actually produce glyphs, do it. */
2438 if (it->glyph_row)
2440 if (stretched_p)
2442 /* Translate a space with a `space-width' property
2443 into a stretch glyph. */
2444 double ascent = (double) font->ascent / FONT_HEIGHT (font);
2445 x_append_stretch_glyph (it, it->object, it->pixel_width,
2446 it->ascent + it->descent, ascent);
2448 else
2449 x_append_glyph (it);
2451 /* If characters with lbearing or rbearing are displayed
2452 in this line, record that fact in a flag of the
2453 glyph row. This is used to optimize X output code. */
2454 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2455 it->glyph_row->contains_overlapping_glyphs_p = 1;
2458 else if (it->char_to_display == '\n')
2460 /* A newline has no width but we need the height of the line. */
2461 it->pixel_width = 0;
2462 it->nglyphs = 0;
2463 it->ascent = it->phys_ascent = font->ascent + boff;
2464 it->descent = it->phys_descent = font->descent - boff;
2466 if (face->box != FACE_NO_BOX)
2468 int thick = face->box_line_width;
2469 it->ascent += thick;
2470 it->descent += thick;
2473 else if (it->char_to_display == '\t')
2475 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2476 int x = it->current_x + it->continuation_lines_width;
2477 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2479 it->pixel_width = next_tab_x - x;
2480 it->nglyphs = 1;
2481 it->ascent = it->phys_ascent = font->ascent + boff;
2482 it->descent = it->phys_descent = font->descent - boff;
2484 if (it->glyph_row)
2486 double ascent = (double) it->ascent / (it->ascent + it->descent);
2487 x_append_stretch_glyph (it, it->object, it->pixel_width,
2488 it->ascent + it->descent, ascent);
2491 else
2493 /* A multi-byte character. Assume that the display width of the
2494 character is the width of the character multiplied by the
2495 width of the font. */
2497 /* If we found a font, this font should give us the right
2498 metrics. If we didn't find a font, use the frame's
2499 default font and calculate the width of the character
2500 from the charset width; this is what old redisplay code
2501 did. */
2502 pcm = x_per_char_metric (font, &char2b);
2503 if (font_not_found_p || !pcm)
2505 int charset = CHAR_CHARSET (it->char_to_display);
2507 it->glyph_not_available_p = 1;
2508 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2509 * CHARSET_WIDTH (charset));
2510 it->phys_ascent = font->ascent + boff;
2511 it->phys_descent = font->descent - boff;
2513 else
2515 it->pixel_width = pcm->width;
2516 it->phys_ascent = pcm->ascent + boff;
2517 it->phys_descent = pcm->descent - boff;
2518 if (it->glyph_row
2519 && (pcm->lbearing < 0
2520 || pcm->rbearing > pcm->width))
2521 it->glyph_row->contains_overlapping_glyphs_p = 1;
2523 it->nglyphs = 1;
2524 it->ascent = font->ascent + boff;
2525 it->descent = font->descent - boff;
2526 if (face->box != FACE_NO_BOX)
2528 int thick = face->box_line_width;
2529 it->ascent += thick;
2530 it->descent += thick;
2532 if (it->start_of_box_run_p)
2533 it->pixel_width += thick;
2534 if (it->end_of_box_run_p)
2535 it->pixel_width += thick;
2538 /* If face has an overline, add the height of the overline
2539 (1 pixel) and a 1 pixel margin to the character height. */
2540 if (face->overline_p)
2541 it->ascent += 2;
2543 take_vertical_position_into_account (it);
2545 if (it->glyph_row)
2546 x_append_glyph (it);
2549 else if (it->what == IT_COMPOSITION)
2551 /* Note: A composition is represented as one glyph in the
2552 glyph matrix. There are no padding glyphs. */
2553 XChar2b char2b;
2554 XFontStruct *font;
2555 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2556 XCharStruct *pcm;
2557 int font_not_found_p;
2558 struct font_info *font_info;
2559 int boff; /* baseline offset */
2560 struct composition *cmp = composition_table[it->cmp_id];
2562 /* Maybe translate single-byte characters to multibyte. */
2563 it->char_to_display = it->c;
2564 if (unibyte_display_via_language_environment
2565 && SINGLE_BYTE_CHAR_P (it->c)
2566 && (it->c >= 0240
2567 || (it->c >= 0200
2568 && !NILP (Vnonascii_translation_table))))
2570 it->char_to_display = unibyte_char_to_multibyte (it->c);
2573 /* Get face and font to use. Encode IT->char_to_display. */
2574 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2575 face = FACE_FROM_ID (it->f, it->face_id);
2576 x_get_char_face_and_encoding (it->f, it->char_to_display,
2577 it->face_id, &char2b, it->multibyte_p);
2578 font = face->font;
2580 /* When no suitable font found, use the default font. */
2581 font_not_found_p = font == NULL;
2582 if (font_not_found_p)
2584 font = FRAME_FONT (it->f);
2585 boff = it->f->output_data.mac->baseline_offset;
2586 font_info = NULL;
2588 else
2590 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2591 boff = font_info->baseline_offset;
2592 if (font_info->vertical_centering)
2593 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2596 /* There are no padding glyphs, so there is only one glyph to
2597 produce for the composition. Important is that pixel_width,
2598 ascent and descent are the values of what is drawn by
2599 draw_glyphs (i.e. the values of the overall glyphs composed). */
2600 it->nglyphs = 1;
2602 /* If we have not yet calculated pixel size data of glyphs of
2603 the composition for the current face font, calculate them
2604 now. Theoretically, we have to check all fonts for the
2605 glyphs, but that requires much time and memory space. So,
2606 here we check only the font of the first glyph. This leads
2607 to incorrect display very rarely, and C-l (recenter) can
2608 correct the display anyway. */
2609 if (cmp->font != (void *) font)
2611 /* Ascent and descent of the font of the first character of
2612 this composition (adjusted by baseline offset). Ascent
2613 and descent of overall glyphs should not be less than
2614 them respectively. */
2615 int font_ascent = font->ascent + boff;
2616 int font_descent = font->descent - boff;
2617 /* Bounding box of the overall glyphs. */
2618 int leftmost, rightmost, lowest, highest;
2619 int i, width, ascent, descent;
2621 cmp->font = (void *) font;
2623 /* Initialize the bounding box. */
2624 pcm = x_per_char_metric (font, &char2b);
2625 if (pcm)
2627 width = pcm->width;
2628 ascent = pcm->ascent;
2629 descent = pcm->descent;
2631 else
2633 width = FONT_WIDTH (font);
2634 ascent = font->ascent;
2635 descent = font->descent;
2638 rightmost = width;
2639 lowest = - descent + boff;
2640 highest = ascent + boff;
2641 leftmost = 0;
2643 if (font_info
2644 && font_info->default_ascent
2645 && CHAR_TABLE_P (Vuse_default_ascent)
2646 && !NILP (Faref (Vuse_default_ascent,
2647 make_number (it->char_to_display))))
2648 highest = font_info->default_ascent + boff;
2650 /* Draw the first glyph at the normal position. It may be
2651 shifted to right later if some other glyphs are drawn at
2652 the left. */
2653 cmp->offsets[0] = 0;
2654 cmp->offsets[1] = boff;
2656 /* Set cmp->offsets for the remaining glyphs. */
2657 for (i = 1; i < cmp->glyph_len; i++)
2659 int left, right, btm, top;
2660 int ch = COMPOSITION_GLYPH (cmp, i);
2661 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2663 face = FACE_FROM_ID (it->f, face_id);
2664 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2665 it->multibyte_p);
2666 font = face->font;
2667 if (font == NULL)
2669 font = FRAME_FONT (it->f);
2670 boff = it->f->output_data.mac->baseline_offset;
2671 font_info = NULL;
2673 else
2675 font_info
2676 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2677 boff = font_info->baseline_offset;
2678 if (font_info->vertical_centering)
2679 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2682 pcm = x_per_char_metric (font, &char2b);
2683 if (pcm)
2685 width = pcm->width;
2686 ascent = pcm->ascent;
2687 descent = pcm->descent;
2689 else
2691 width = FONT_WIDTH (font);
2692 ascent = font->ascent;
2693 descent = font->descent;
2696 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2698 /* Relative composition with or without
2699 alternate chars. */
2700 left = (leftmost + rightmost - width) / 2;
2701 btm = - descent + boff;
2702 if (font_info && font_info->relative_compose
2703 && (! CHAR_TABLE_P (Vignore_relative_composition)
2704 || NILP (Faref (Vignore_relative_composition,
2705 make_number (ch)))))
2708 if (- descent >= font_info->relative_compose)
2709 /* One extra pixel between two glyphs. */
2710 btm = highest + 1;
2711 else if (ascent <= 0)
2712 /* One extra pixel between two glyphs. */
2713 btm = lowest - 1 - ascent - descent;
2716 else
2718 /* A composition rule is specified by an integer
2719 value that encodes global and new reference
2720 points (GREF and NREF). GREF and NREF are
2721 specified by numbers as below:
2723 0---1---2 -- ascent
2727 9--10--11 -- center
2729 ---3---4---5--- baseline
2731 6---7---8 -- descent
2733 int rule = COMPOSITION_RULE (cmp, i);
2734 int gref, nref, grefx, grefy, nrefx, nrefy;
2736 COMPOSITION_DECODE_RULE (rule, gref, nref);
2737 grefx = gref % 3, nrefx = nref % 3;
2738 grefy = gref / 3, nrefy = nref / 3;
2740 left = (leftmost
2741 + grefx * (rightmost - leftmost) / 2
2742 - nrefx * width / 2);
2743 btm = ((grefy == 0 ? highest
2744 : grefy == 1 ? 0
2745 : grefy == 2 ? lowest
2746 : (highest + lowest) / 2)
2747 - (nrefy == 0 ? ascent + descent
2748 : nrefy == 1 ? descent - boff
2749 : nrefy == 2 ? 0
2750 : (ascent + descent) / 2));
2753 cmp->offsets[i * 2] = left;
2754 cmp->offsets[i * 2 + 1] = btm + descent;
2756 /* Update the bounding box of the overall glyphs. */
2757 right = left + width;
2758 top = btm + descent + ascent;
2759 if (left < leftmost)
2760 leftmost = left;
2761 if (right > rightmost)
2762 rightmost = right;
2763 if (top > highest)
2764 highest = top;
2765 if (btm < lowest)
2766 lowest = btm;
2769 /* If there are glyphs whose x-offsets are negative,
2770 shift all glyphs to the right and make all x-offsets
2771 non-negative. */
2772 if (leftmost < 0)
2774 for (i = 0; i < cmp->glyph_len; i++)
2775 cmp->offsets[i * 2] -= leftmost;
2776 rightmost -= leftmost;
2779 cmp->pixel_width = rightmost;
2780 cmp->ascent = highest;
2781 cmp->descent = - lowest;
2782 if (cmp->ascent < font_ascent)
2783 cmp->ascent = font_ascent;
2784 if (cmp->descent < font_descent)
2785 cmp->descent = font_descent;
2788 it->pixel_width = cmp->pixel_width;
2789 it->ascent = it->phys_ascent = cmp->ascent;
2790 it->descent = it->phys_descent = cmp->descent;
2792 if (face->box != FACE_NO_BOX)
2794 int thick = face->box_line_width;
2795 it->ascent += thick;
2796 it->descent += thick;
2798 if (it->start_of_box_run_p)
2799 it->pixel_width += thick;
2800 if (it->end_of_box_run_p)
2801 it->pixel_width += thick;
2804 /* If face has an overline, add the height of the overline
2805 (1 pixel) and a 1 pixel margin to the character height. */
2806 if (face->overline_p)
2807 it->ascent += 2;
2809 take_vertical_position_into_account (it);
2811 if (it->glyph_row)
2812 x_append_composite_glyph (it);
2814 else if (it->what == IT_IMAGE)
2815 x_produce_image_glyph (it);
2816 else if (it->what == IT_STRETCH)
2817 x_produce_stretch_glyph (it);
2819 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2820 because this isn't true for images with `:ascent 100'. */
2821 xassert (it->ascent >= 0 && it->descent >= 0);
2822 if (it->area == TEXT_AREA)
2823 it->current_x += it->pixel_width;
2825 it->descent += it->extra_line_spacing;
2827 it->max_ascent = max (it->max_ascent, it->ascent);
2828 it->max_descent = max (it->max_descent, it->descent);
2829 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2830 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2834 /* Estimate the pixel height of the mode or top line on frame F.
2835 FACE_ID specifies what line's height to estimate. */
2838 x_estimate_mode_line_height (f, face_id)
2839 struct frame *f;
2840 enum face_id face_id;
2842 int height = 1;
2844 /* This function is called so early when Emacs starts that the face
2845 cache and mode line face are not yet initialized. */
2846 if (FRAME_FACE_CACHE (f))
2848 struct face *face = FACE_FROM_ID (f, face_id);
2849 if (face)
2850 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2853 return height;
2857 /***********************************************************************
2858 Glyph display
2859 ***********************************************************************/
2861 /* A sequence of glyphs to be drawn in the same face.
2863 This data structure is not really completely X specific, so it
2864 could possibly, at least partially, be useful for other systems. It
2865 is currently not part of the external redisplay interface because
2866 it's not clear what other systems will need. */
2868 struct glyph_string
2870 /* X-origin of the string. */
2871 int x;
2873 /* Y-origin and y-position of the base line of this string. */
2874 int y, ybase;
2876 /* The width of the string, not including a face extension. */
2877 int width;
2879 /* The width of the string, including a face extension. */
2880 int background_width;
2882 /* The height of this string. This is the height of the line this
2883 string is drawn in, and can be different from the height of the
2884 font the string is drawn in. */
2885 int height;
2887 /* Number of pixels this string overwrites in front of its x-origin.
2888 This number is zero if the string has an lbearing >= 0; it is
2889 -lbearing, if the string has an lbearing < 0. */
2890 int left_overhang;
2892 /* Number of pixels this string overwrites past its right-most
2893 nominal x-position, i.e. x + width. Zero if the string's
2894 rbearing is <= its nominal width, rbearing - width otherwise. */
2895 int right_overhang;
2897 /* The frame on which the glyph string is drawn. */
2898 struct frame *f;
2900 /* The window on which the glyph string is drawn. */
2901 struct window *w;
2903 /* X display and window for convenience. */
2904 Display *display;
2905 Window window;
2907 /* The glyph row for which this string was built. It determines the
2908 y-origin and height of the string. */
2909 struct glyph_row *row;
2911 /* The area within row. */
2912 enum glyph_row_area area;
2914 /* Characters to be drawn, and number of characters. */
2915 XChar2b *char2b;
2916 int nchars;
2918 /* A face-override for drawing cursors, mouse face and similar. */
2919 enum draw_glyphs_face hl;
2921 /* Face in which this string is to be drawn. */
2922 struct face *face;
2924 /* Font in which this string is to be drawn. */
2925 XFontStruct *font;
2927 /* Font info for this string. */
2928 struct font_info *font_info;
2930 /* Non-null means this string describes (part of) a composition.
2931 All characters from char2b are drawn composed. */
2932 struct composition *cmp;
2934 /* Index of this glyph string's first character in the glyph
2935 definition of CMP. If this is zero, this glyph string describes
2936 the first character of a composition. */
2937 int gidx;
2939 /* 1 means this glyph strings face has to be drawn to the right end
2940 of the window's drawing area. */
2941 unsigned extends_to_end_of_line_p : 1;
2943 /* 1 means the background of this string has been drawn. */
2944 unsigned background_filled_p : 1;
2946 /* 1 means glyph string must be drawn with 16-bit functions. */
2947 unsigned two_byte_p : 1;
2949 /* 1 means that the original font determined for drawing this glyph
2950 string could not be loaded. The member `font' has been set to
2951 the frame's default font in this case. */
2952 unsigned font_not_found_p : 1;
2954 /* 1 means that the face in which this glyph string is drawn has a
2955 stipple pattern. */
2956 unsigned stippled_p : 1;
2958 /* 1 means only the foreground of this glyph string must be drawn,
2959 and we should use the physical height of the line this glyph
2960 string appears in as clip rect. */
2961 unsigned for_overlaps_p : 1;
2963 /* The GC to use for drawing this glyph string. */
2964 GC gc;
2966 /* A pointer to the first glyph in the string. This glyph
2967 corresponds to char2b[0]. Needed to draw rectangles if
2968 font_not_found_p is 1. */
2969 struct glyph *first_glyph;
2971 /* Image, if any. */
2972 struct image *img;
2974 struct glyph_string *next, *prev;
2978 #if 0
2980 static void
2981 x_dump_glyph_string (s)
2982 struct glyph_string *s;
2984 fprintf (stderr, "glyph string\n");
2985 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2986 s->x, s->y, s->width, s->height);
2987 fprintf (stderr, " ybase = %d\n", s->ybase);
2988 fprintf (stderr, " hl = %d\n", s->hl);
2989 fprintf (stderr, " left overhang = %d, right = %d\n",
2990 s->left_overhang, s->right_overhang);
2991 fprintf (stderr, " nchars = %d\n", s->nchars);
2992 fprintf (stderr, " extends to end of line = %d\n",
2993 s->extends_to_end_of_line_p);
2994 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2995 fprintf (stderr, " bg width = %d\n", s->background_width);
2998 #endif /* GLYPH_DEBUG */
3002 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3003 struct glyph_string **,
3004 struct glyph_string *,
3005 struct glyph_string *));
3006 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3007 struct glyph_string **,
3008 struct glyph_string *,
3009 struct glyph_string *));
3010 static void x_append_glyph_string P_ ((struct glyph_string **,
3011 struct glyph_string **,
3012 struct glyph_string *));
3013 static int x_left_overwritten P_ ((struct glyph_string *));
3014 static int x_left_overwriting P_ ((struct glyph_string *));
3015 static int x_right_overwritten P_ ((struct glyph_string *));
3016 static int x_right_overwriting P_ ((struct glyph_string *));
3017 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3018 int));
3019 static void x_init_glyph_string P_ ((struct glyph_string *,
3020 XChar2b *, struct window *,
3021 struct glyph_row *,
3022 enum glyph_row_area, int,
3023 enum draw_glyphs_face));
3024 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3025 enum glyph_row_area, int, int,
3026 enum draw_glyphs_face, int *, int *, int));
3027 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3028 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3029 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3030 int));
3031 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3032 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3033 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3034 static void x_draw_glyph_string P_ ((struct glyph_string *));
3035 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3036 static void x_set_cursor_gc P_ ((struct glyph_string *));
3037 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3038 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3039 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3040 int *, int *));
3041 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
3042 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3043 unsigned long *, double, int));
3044 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3045 double, int, unsigned long));
3046 static void x_setup_relief_colors P_ ((struct glyph_string *));
3047 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3048 static void x_draw_image_relief P_ ((struct glyph_string *));
3049 static void x_draw_image_foreground P_ ((struct glyph_string *));
3050 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3051 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3052 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3053 int, int, int));
3054 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
3055 int, int, int, int, XRectangle *));
3056 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
3057 int, int, int, XRectangle *));
3058 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3059 enum glyph_row_area));
3060 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3061 struct glyph_row *,
3062 enum glyph_row_area, int, int));
3064 #if GLYPH_DEBUG
3065 static void x_check_font P_ ((struct frame *, XFontStruct *));
3066 #endif
3069 /* Append the list of glyph strings with head H and tail T to the list
3070 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3072 static INLINE void
3073 x_append_glyph_string_lists (head, tail, h, t)
3074 struct glyph_string **head, **tail;
3075 struct glyph_string *h, *t;
3077 if (h)
3079 if (*head)
3080 (*tail)->next = h;
3081 else
3082 *head = h;
3083 h->prev = *tail;
3084 *tail = t;
3089 /* Prepend the list of glyph strings with head H and tail T to the
3090 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3091 result. */
3093 static INLINE void
3094 x_prepend_glyph_string_lists (head, tail, h, t)
3095 struct glyph_string **head, **tail;
3096 struct glyph_string *h, *t;
3098 if (h)
3100 if (*head)
3101 (*head)->prev = t;
3102 else
3103 *tail = t;
3104 t->next = *head;
3105 *head = h;
3110 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3111 Set *HEAD and *TAIL to the resulting list. */
3113 static INLINE void
3114 x_append_glyph_string (head, tail, s)
3115 struct glyph_string **head, **tail;
3116 struct glyph_string *s;
3118 s->next = s->prev = NULL;
3119 x_append_glyph_string_lists (head, tail, s, s);
3123 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3124 face. */
3126 static void
3127 x_set_cursor_gc (s)
3128 struct glyph_string *s;
3130 if (s->font == FRAME_FONT (s->f)
3131 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3132 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3133 && !s->cmp)
3134 s->gc = s->f->output_data.mac->cursor_gc;
3135 else
3137 /* Cursor on non-default face: must merge. */
3138 XGCValues xgcv;
3139 unsigned long mask;
3141 xgcv.background = s->f->output_data.mac->cursor_pixel;
3142 xgcv.foreground = s->face->background;
3144 /* If the glyph would be invisible, try a different foreground. */
3145 if (xgcv.foreground == xgcv.background)
3146 xgcv.foreground = s->face->foreground;
3147 if (xgcv.foreground == xgcv.background)
3148 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3149 if (xgcv.foreground == xgcv.background)
3150 xgcv.foreground = s->face->foreground;
3152 /* Make sure the cursor is distinct from text in this face. */
3153 if (xgcv.background == s->face->background
3154 && xgcv.foreground == s->face->foreground)
3156 xgcv.background = s->face->foreground;
3157 xgcv.foreground = s->face->background;
3160 IF_DEBUG (x_check_font (s->f, s->font));
3161 xgcv.font = s->font;
3162 mask = GCForeground | GCBackground | GCFont;
3164 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3165 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3166 mask, &xgcv);
3167 else
3168 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3169 = XCreateGC (s->display, s->window, mask, &xgcv);
3171 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3176 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3178 static void
3179 x_set_mouse_face_gc (s)
3180 struct glyph_string *s;
3182 int face_id;
3183 struct face *face;
3185 /* What face has to be used for the mouse face? */
3186 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3187 face = FACE_FROM_ID (s->f, face_id);
3188 if (s->first_glyph->type == CHAR_GLYPH)
3189 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3190 else
3191 face_id = FACE_FOR_CHAR (s->f, face, 0);
3192 s->face = FACE_FROM_ID (s->f, face_id);
3193 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3195 /* If font in this face is same as S->font, use it. */
3196 if (s->font == s->face->font)
3197 s->gc = s->face->gc;
3198 else
3200 /* Otherwise construct scratch_cursor_gc with values from FACE
3201 but font FONT. */
3202 XGCValues xgcv;
3203 unsigned long mask;
3205 xgcv.background = s->face->background;
3206 xgcv.foreground = s->face->foreground;
3207 IF_DEBUG (x_check_font (s->f, s->font));
3208 xgcv.font = s->font;
3209 mask = GCForeground | GCBackground | GCFont;
3211 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3212 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3213 mask, &xgcv);
3214 else
3215 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3216 = XCreateGC (s->display, s->window, mask, &xgcv);
3218 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3221 xassert (s->gc != 0);
3225 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3226 Faces to use in the mode line have already been computed when the
3227 matrix was built, so there isn't much to do, here. */
3229 static INLINE void
3230 x_set_mode_line_face_gc (s)
3231 struct glyph_string *s;
3233 s->gc = s->face->gc;
3237 /* Set S->gc of glyph string S for drawing that glyph string. Set
3238 S->stippled_p to a non-zero value if the face of S has a stipple
3239 pattern. */
3241 static INLINE void
3242 x_set_glyph_string_gc (s)
3243 struct glyph_string *s;
3245 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3247 if (s->hl == DRAW_NORMAL_TEXT)
3249 s->gc = s->face->gc;
3250 s->stippled_p = s->face->stipple != 0;
3252 else if (s->hl == DRAW_INVERSE_VIDEO)
3254 x_set_mode_line_face_gc (s);
3255 s->stippled_p = s->face->stipple != 0;
3257 else if (s->hl == DRAW_CURSOR)
3259 x_set_cursor_gc (s);
3260 s->stippled_p = 0;
3262 else if (s->hl == DRAW_MOUSE_FACE)
3264 x_set_mouse_face_gc (s);
3265 s->stippled_p = s->face->stipple != 0;
3267 else if (s->hl == DRAW_IMAGE_RAISED
3268 || s->hl == DRAW_IMAGE_SUNKEN)
3270 s->gc = s->face->gc;
3271 s->stippled_p = s->face->stipple != 0;
3273 else
3275 s->gc = s->face->gc;
3276 s->stippled_p = s->face->stipple != 0;
3279 /* GC must have been set. */
3280 xassert (s->gc != 0);
3284 /* Return in *R the clipping rectangle for glyph string S. */
3286 static void
3287 x_get_glyph_string_clip_rect (s, r)
3288 struct glyph_string *s;
3289 Rect *r;
3291 int r_height, r_width;
3293 if (s->row->full_width_p)
3295 /* Draw full-width. X coordinates are relative to S->w->left. */
3296 int canon_x = CANON_X_UNIT (s->f);
3298 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3299 r_width = XFASTINT (s->w->width) * canon_x;
3301 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3303 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3304 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3305 r->left -= width;
3308 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3310 /* Unless displaying a mode or menu bar line, which are always
3311 fully visible, clip to the visible part of the row. */
3312 if (s->w->pseudo_window_p)
3313 r_height = s->row->visible_height;
3314 else
3315 r_height = s->height;
3317 else
3319 /* This is a text line that may be partially visible. */
3320 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3321 r_width = window_box_width (s->w, s->area);
3322 r_height = s->row->visible_height;
3325 /* Don't use S->y for clipping because it doesn't take partially
3326 visible lines into account. For example, it can be negative for
3327 partially visible lines at the top of a window. */
3328 if (!s->row->full_width_p
3329 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3330 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3331 else
3332 r->top = max (0, s->row->y);
3334 /* If drawing a tool-bar window, draw it over the internal border
3335 at the top of the window. */
3336 if (s->w == XWINDOW (s->f->tool_bar_window))
3337 r->top -= s->f->output_data.mac->internal_border_width;
3339 /* If S draws overlapping rows, it's sufficient to use the top and
3340 bottom of the window for clipping because this glyph string
3341 intentionally draws over other lines. */
3342 if (s->for_overlaps_p)
3344 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3345 r_height = window_text_bottom_y (s->w) - r->top;
3348 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3350 r->bottom = r->top + r_height;
3351 r->right = r->left + r_width;
3355 /* Set clipping for output of glyph string S. S may be part of a mode
3356 line or menu if we don't have X toolkit support. */
3358 static INLINE void
3359 x_set_glyph_string_clipping (s)
3360 struct glyph_string *s;
3362 Rect r;
3363 x_get_glyph_string_clip_rect (s, &r);
3364 mac_set_clip_rectangle (s->display, s->window, &r);
3368 /* Compute left and right overhang of glyph string S. If S is a glyph
3369 string for a composition, assume overhangs don't exist. */
3371 static INLINE void
3372 x_compute_glyph_string_overhangs (s)
3373 struct glyph_string *s;
3375 if (s->cmp == NULL
3376 && s->first_glyph->type == CHAR_GLYPH)
3378 XCharStruct cs;
3379 int direction, font_ascent, font_descent;
3380 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3381 &font_ascent, &font_descent, &cs);
3382 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3383 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3388 /* Compute overhangs and x-positions for glyph string S and its
3389 predecessors, or successors. X is the starting x-position for S.
3390 BACKWARD_P non-zero means process predecessors. */
3392 static void
3393 x_compute_overhangs_and_x (s, x, backward_p)
3394 struct glyph_string *s;
3395 int x;
3396 int backward_p;
3398 if (backward_p)
3400 while (s)
3402 x_compute_glyph_string_overhangs (s);
3403 x -= s->width;
3404 s->x = x;
3405 s = s->prev;
3408 else
3410 while (s)
3412 x_compute_glyph_string_overhangs (s);
3413 s->x = x;
3414 x += s->width;
3415 s = s->next;
3421 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3422 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3423 assumed to be zero. */
3425 void
3426 x_get_glyph_overhangs (glyph, f, left, right)
3427 struct glyph *glyph;
3428 struct frame *f;
3429 int *left, *right;
3431 *left = *right = 0;
3433 if (glyph->type == CHAR_GLYPH)
3435 XFontStruct *font;
3436 struct face *face;
3437 struct font_info *font_info;
3438 XChar2b char2b;
3439 XCharStruct *pcm;
3441 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3442 font = face->font;
3443 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3444 if (font
3445 && (pcm = x_per_char_metric (font, &char2b)))
3447 if (pcm->rbearing > pcm->width)
3448 *right = pcm->rbearing - pcm->width;
3449 if (pcm->lbearing < 0)
3450 *left = -pcm->lbearing;
3456 /* Return the index of the first glyph preceding glyph string S that
3457 is overwritten by S because of S's left overhang. Value is -1
3458 if no glyphs are overwritten. */
3460 static int
3461 x_left_overwritten (s)
3462 struct glyph_string *s;
3464 int k;
3466 if (s->left_overhang)
3468 int x = 0, i;
3469 struct glyph *glyphs = s->row->glyphs[s->area];
3470 int first = s->first_glyph - glyphs;
3472 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3473 x -= glyphs[i].pixel_width;
3475 k = i + 1;
3477 else
3478 k = -1;
3480 return k;
3484 /* Return the index of the first glyph preceding glyph string S that
3485 is overwriting S because of its right overhang. Value is -1 if no
3486 glyph in front of S overwrites S. */
3488 static int
3489 x_left_overwriting (s)
3490 struct glyph_string *s;
3492 int i, k, x;
3493 struct glyph *glyphs = s->row->glyphs[s->area];
3494 int first = s->first_glyph - glyphs;
3496 k = -1;
3497 x = 0;
3498 for (i = first - 1; i >= 0; --i)
3500 int left, right;
3501 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3502 if (x + right > 0)
3503 k = i;
3504 x -= glyphs[i].pixel_width;
3507 return k;
3511 /* Return the index of the last glyph following glyph string S that is
3512 not overwritten by S because of S's right overhang. Value is -1 if
3513 no such glyph is found. */
3515 static int
3516 x_right_overwritten (s)
3517 struct glyph_string *s;
3519 int k = -1;
3521 if (s->right_overhang)
3523 int x = 0, i;
3524 struct glyph *glyphs = s->row->glyphs[s->area];
3525 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3526 int end = s->row->used[s->area];
3528 for (i = first; i < end && s->right_overhang > x; ++i)
3529 x += glyphs[i].pixel_width;
3531 k = i;
3534 return k;
3538 /* Return the index of the last glyph following glyph string S that
3539 overwrites S because of its left overhang. Value is negative
3540 if no such glyph is found. */
3542 static int
3543 x_right_overwriting (s)
3544 struct glyph_string *s;
3546 int i, k, x;
3547 int end = s->row->used[s->area];
3548 struct glyph *glyphs = s->row->glyphs[s->area];
3549 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3551 k = -1;
3552 x = 0;
3553 for (i = first; i < end; ++i)
3555 int left, right;
3556 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3557 if (x - left < 0)
3558 k = i;
3559 x += glyphs[i].pixel_width;
3562 return k;
3566 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3568 static INLINE void
3569 x_clear_glyph_string_rect (s, x, y, w, h)
3570 struct glyph_string *s;
3571 int x, y, w, h;
3573 XGCValues xgcv;
3575 xgcv.foreground = s->gc->background;
3576 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3580 /* Draw the background of glyph_string S. If S->background_filled_p
3581 is non-zero don't draw it. FORCE_P non-zero means draw the
3582 background even if it wouldn't be drawn normally. This is used
3583 when a string preceding S draws into the background of S, or S
3584 contains the first component of a composition. */
3586 static void
3587 x_draw_glyph_string_background (s, force_p)
3588 struct glyph_string *s;
3589 int force_p;
3591 /* Nothing to do if background has already been drawn or if it
3592 shouldn't be drawn in the first place. */
3593 if (!s->background_filled_p)
3595 #if 0 /* MAC_TODO: stipple */
3596 if (s->stippled_p)
3598 /* Fill background with a stipple pattern. */
3599 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3600 XFillRectangle (s->display, s->window, s->gc, s->x,
3601 s->y + s->face->box_line_width,
3602 s->background_width,
3603 s->height - 2 * s->face->box_line_width);
3604 XSetFillStyle (s->display, s->gc, FillSolid);
3605 s->background_filled_p = 1;
3607 else
3608 #endif
3609 if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3610 || s->font_not_found_p
3611 || s->extends_to_end_of_line_p
3612 || force_p)
3614 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3615 s->background_width,
3616 s->height - 2 * s->face->box_line_width);
3617 s->background_filled_p = 1;
3623 /* Draw the foreground of glyph string S. */
3625 static void
3626 x_draw_glyph_string_foreground (s)
3627 struct glyph_string *s;
3629 int i, x;
3631 /* If first glyph of S has a left box line, start drawing the text
3632 of S to the right of that box line. */
3633 if (s->face->box != FACE_NO_BOX
3634 && s->first_glyph->left_box_line_p)
3635 x = s->x + s->face->box_line_width;
3636 else
3637 x = s->x;
3639 /* Draw characters of S as rectangles if S's font could not be
3640 loaded. */
3641 if (s->font_not_found_p)
3643 for (i = 0; i < s->nchars; ++i)
3645 struct glyph *g = s->first_glyph + i;
3646 mac_draw_rectangle (s->display, s->window,
3647 s->gc, x, s->y, g->pixel_width - 1,
3648 s->height - 1);
3649 x += g->pixel_width;
3652 else
3654 char *char1b = (char *) s->char2b;
3655 int boff = s->font_info->baseline_offset;
3657 if (s->font_info->vertical_centering)
3658 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3660 /* If we can use 8-bit functions, condense S->char2b. */
3661 if (!s->two_byte_p)
3662 for (i = 0; i < s->nchars; ++i)
3663 char1b[i] = s->char2b[i].byte2;
3665 /* Draw text with XDrawString if background has already been
3666 filled. Otherwise, use XDrawImageString. (Note that
3667 XDrawImageString is usually faster than XDrawString.) Always
3668 use XDrawImageString when drawing the cursor so that there is
3669 no chance that characters under a box cursor are invisible. */
3670 if (s->for_overlaps_p
3671 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3673 /* Draw characters with 16-bit or 8-bit functions. */
3674 if (s->two_byte_p)
3675 XDrawString16 (s->display, s->window, s->gc, x,
3676 s->ybase - boff, s->char2b, s->nchars);
3677 else
3678 XDrawString (s->display, s->window, s->gc, x,
3679 s->ybase - boff, char1b, s->nchars);
3681 else
3683 if (s->two_byte_p)
3684 XDrawImageString16 (s->display, s->window, s->gc, x,
3685 s->ybase - boff, s->char2b, s->nchars);
3686 else
3687 XDrawImageString (s->display, s->window, s->gc, x,
3688 s->ybase - boff, char1b, s->nchars);
3693 /* Draw the foreground of composite glyph string S. */
3695 static void
3696 x_draw_composite_glyph_string_foreground (s)
3697 struct glyph_string *s;
3699 int i, x;
3701 /* If first glyph of S has a left box line, start drawing the text
3702 of S to the right of that box line. */
3703 if (s->face->box != FACE_NO_BOX
3704 && s->first_glyph->left_box_line_p)
3705 x = s->x + s->face->box_line_width;
3706 else
3707 x = s->x;
3709 /* S is a glyph string for a composition. S->gidx is the index of
3710 the first character drawn for glyphs of this composition.
3711 S->gidx == 0 means we are drawing the very first character of
3712 this composition. */
3714 /* Draw a rectangle for the composition if the font for the very
3715 first character of the composition could not be loaded. */
3716 if (s->font_not_found_p)
3718 if (s->gidx == 0)
3719 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3720 s->width - 1, s->height - 1);
3722 else
3724 for (i = 0; i < s->nchars; i++, ++s->gidx)
3725 XDrawString16 (s->display, s->window, s->gc,
3726 x + s->cmp->offsets[s->gidx * 2],
3727 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3728 s->char2b + i, 1);
3733 #ifdef USE_X_TOOLKIT
3735 static struct frame *x_frame_of_widget P_ ((Widget));
3738 /* Return the frame on which widget WIDGET is used.. Abort if frame
3739 cannot be determined. */
3741 static struct frame *
3742 x_frame_of_widget (widget)
3743 Widget widget;
3745 struct x_display_info *dpyinfo;
3746 Lisp_Object tail;
3747 struct frame *f;
3749 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3751 /* Find the top-level shell of the widget. Note that this function
3752 can be called when the widget is not yet realized, so XtWindow
3753 (widget) == 0. That's the reason we can't simply use
3754 x_any_window_to_frame. */
3755 while (!XtIsTopLevelShell (widget))
3756 widget = XtParent (widget);
3758 /* Look for a frame with that top-level widget. Allocate the color
3759 on that frame to get the right gamma correction value. */
3760 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3761 if (GC_FRAMEP (XCAR (tail))
3762 && (f = XFRAME (XCAR (tail)),
3763 (f->output_data.nothing != 1
3764 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3765 && f->output_data.x->widget == widget)
3766 return f;
3768 abort ();
3772 /* Allocate the color COLOR->pixel on the screen and display of
3773 widget WIDGET in colormap CMAP. If an exact match cannot be
3774 allocated, try the nearest color available. Value is non-zero
3775 if successful. This is called from lwlib. */
3778 x_alloc_nearest_color_for_widget (widget, cmap, color)
3779 Widget widget;
3780 Colormap cmap;
3781 XColor *color;
3783 struct frame *f = x_frame_of_widget (widget);
3784 return x_alloc_nearest_color (f, cmap, color);
3788 #endif /* USE_X_TOOLKIT */
3790 #if 0
3792 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3793 CMAP. If an exact match can't be allocated, try the nearest color
3794 available. Value is non-zero if successful. Set *COLOR to the
3795 color allocated. */
3798 x_alloc_nearest_color (f, cmap, color)
3799 struct frame *f;
3800 Colormap cmap;
3801 XColor *color;
3803 Display *display = FRAME_X_DISPLAY (f);
3804 Screen *screen = FRAME_X_SCREEN (f);
3805 int rc;
3807 gamma_correct (f, color);
3808 rc = XAllocColor (display, cmap, color);
3809 if (rc == 0)
3811 /* If we got to this point, the colormap is full, so we're going
3812 to try to get the next closest color. The algorithm used is
3813 a least-squares matching, which is what X uses for closest
3814 color matching with StaticColor visuals. */
3815 int nearest, i;
3816 unsigned long nearest_delta = ~0;
3817 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3818 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3820 for (i = 0; i < ncells; ++i)
3821 cells[i].pixel = i;
3822 XQueryColors (display, cmap, cells, ncells);
3824 for (nearest = i = 0; i < ncells; ++i)
3826 long dred = (color->red >> 8) - (cells[i].red >> 8);
3827 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3828 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3829 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3831 if (delta < nearest_delta)
3833 nearest = i;
3834 nearest_delta = delta;
3838 color->red = cells[nearest].red;
3839 color->green = cells[nearest].green;
3840 color->blue = cells[nearest].blue;
3841 rc = XAllocColor (display, cmap, color);
3844 #ifdef DEBUG_X_COLORS
3845 if (rc)
3846 register_color (color->pixel);
3847 #endif /* DEBUG_X_COLORS */
3849 return rc;
3853 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3854 It's necessary to do this instead of just using PIXEL directly to
3855 get color reference counts right. */
3857 unsigned long
3858 x_copy_color (f, pixel)
3859 struct frame *f;
3860 unsigned long pixel;
3862 XColor color;
3864 color.pixel = pixel;
3865 BLOCK_INPUT;
3866 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3867 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3868 UNBLOCK_INPUT;
3869 #ifdef DEBUG_X_COLORS
3870 register_color (pixel);
3871 #endif
3872 return color.pixel;
3876 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3877 It's necessary to do this instead of just using PIXEL directly to
3878 get color reference counts right. */
3880 unsigned long
3881 x_copy_dpy_color (dpy, cmap, pixel)
3882 Display *dpy;
3883 Colormap cmap;
3884 unsigned long pixel;
3886 XColor color;
3888 color.pixel = pixel;
3889 BLOCK_INPUT;
3890 XQueryColor (dpy, cmap, &color);
3891 XAllocColor (dpy, cmap, &color);
3892 UNBLOCK_INPUT;
3893 #ifdef DEBUG_X_COLORS
3894 register_color (pixel);
3895 #endif
3896 return color.pixel;
3899 #endif
3901 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3902 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3903 If this produces the same color as COLOR, try a color where all RGB
3904 values have DELTA added. Return the allocated color in *COLOR.
3905 DISPLAY is the X display, CMAP is the colormap to operate on.
3906 Value is non-zero if successful. */
3908 static int
3909 mac_alloc_lighter_color (f, color, factor, delta)
3910 struct frame *f;
3911 unsigned long *color;
3912 double factor;
3913 int delta;
3915 unsigned long new;
3917 /* Change RGB values by specified FACTOR. Avoid overflow! */
3918 xassert (factor >= 0);
3919 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3920 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3921 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3922 if (new == *color)
3923 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3924 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3925 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3927 /* MAC_TODO: Map to palette and retry with delta if same? */
3928 /* MAC_TODO: Free colors (if using palette)? */
3930 if (new == *color)
3931 return 0;
3933 *color = new;
3935 return 1;
3939 /* Set up the foreground color for drawing relief lines of glyph
3940 string S. RELIEF is a pointer to a struct relief containing the GC
3941 with which lines will be drawn. Use a color that is FACTOR or
3942 DELTA lighter or darker than the relief's background which is found
3943 in S->f->output_data.x->relief_background. If such a color cannot
3944 be allocated, use DEFAULT_PIXEL, instead. */
3946 static void
3947 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3948 struct frame *f;
3949 struct relief *relief;
3950 double factor;
3951 int delta;
3952 unsigned long default_pixel;
3954 XGCValues xgcv;
3955 struct mac_output *di = f->output_data.mac;
3956 unsigned long mask = GCForeground;
3957 unsigned long pixel;
3958 unsigned long background = di->relief_background;
3959 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3961 /* MAC_TODO: Free colors (if using palette)? */
3963 /* Allocate new color. */
3964 xgcv.foreground = default_pixel;
3965 pixel = background;
3966 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
3968 relief->allocated_p = 1;
3969 xgcv.foreground = relief->pixel = pixel;
3972 if (relief->gc == 0)
3974 #if 0 /* MAC_TODO: stipple */
3975 xgcv.stipple = dpyinfo->gray;
3976 mask |= GCStipple;
3977 #endif
3978 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3980 else
3981 XChangeGC (NULL, relief->gc, mask, &xgcv);
3985 /* Set up colors for the relief lines around glyph string S. */
3987 static void
3988 x_setup_relief_colors (s)
3989 struct glyph_string *s;
3991 struct mac_output *di = s->f->output_data.mac;
3992 unsigned long color;
3994 if (s->face->use_box_color_for_shadows_p)
3995 color = s->face->box_color;
3996 else
3998 XGCValues xgcv;
4000 /* Get the background color of the face. */
4001 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4002 color = xgcv.background;
4005 if (di->white_relief.gc == 0
4006 || color != di->relief_background)
4008 di->relief_background = color;
4009 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4010 WHITE_PIX_DEFAULT (s->f));
4011 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4012 BLACK_PIX_DEFAULT (s->f));
4017 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4018 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4019 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4020 relief. LEFT_P non-zero means draw a relief on the left side of
4021 the rectangle. RIGHT_P non-zero means draw a relief on the right
4022 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4023 when drawing. */
4025 static void
4026 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4027 raised_p, left_p, right_p, clip_rect)
4028 struct frame *f;
4029 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4030 Rect *clip_rect;
4032 int i;
4033 GC gc;
4035 if (raised_p)
4036 gc = f->output_data.mac->white_relief.gc;
4037 else
4038 gc = f->output_data.mac->black_relief.gc;
4039 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4041 /* Top. */
4042 for (i = 0; i < width; ++i)
4043 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4044 left_x + i * left_p, top_y + i,
4045 right_x + 1 - i * right_p, top_y + i);
4047 /* Left. */
4048 if (left_p)
4049 for (i = 0; i < width; ++i)
4050 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4051 left_x + i, top_y + i, left_x + i, bottom_y - i);
4053 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4054 if (raised_p)
4055 gc = f->output_data.mac->black_relief.gc;
4056 else
4057 gc = f->output_data.mac->white_relief.gc;
4058 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4060 /* Bottom. */
4061 for (i = 0; i < width; ++i)
4062 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4063 left_x + i * left_p, bottom_y - i,
4064 right_x + 1 - i * right_p, bottom_y - i);
4066 /* Right. */
4067 if (right_p)
4068 for (i = 0; i < width; ++i)
4069 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4070 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4072 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4076 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4077 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4078 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4079 left side of the rectangle. RIGHT_P non-zero means draw a line
4080 on the right side of the rectangle. CLIP_RECT is the clipping
4081 rectangle to use when drawing. */
4083 static void
4084 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4085 left_p, right_p, clip_rect)
4086 struct glyph_string *s;
4087 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4088 Rect *clip_rect;
4090 XGCValues xgcv;
4092 xgcv.foreground = s->face->box_color;
4093 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4095 /* Top. */
4096 XFillRectangle (s->display, s->window, &xgcv,
4097 left_x, top_y, right_x - left_x, width);
4099 /* Left. */
4100 if (left_p)
4101 XFillRectangle (s->display, s->window, &xgcv,
4102 left_x, top_y, width, bottom_y - top_y);
4104 /* Bottom. */
4105 XFillRectangle (s->display, s->window, &xgcv,
4106 left_x, bottom_y - width, right_x - left_x, width);
4108 /* Right. */
4109 if (right_p)
4110 XFillRectangle (s->display, s->window, &xgcv,
4111 right_x - width, top_y, width, bottom_y - top_y);
4113 mac_reset_clipping (s->display, s->window);
4117 /* Draw a box around glyph string S. */
4119 static void
4120 x_draw_glyph_string_box (s)
4121 struct glyph_string *s;
4123 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4124 int left_p, right_p;
4125 struct glyph *last_glyph;
4126 Rect clip_rect;
4128 last_x = window_box_right (s->w, s->area);
4129 if (s->row->full_width_p
4130 && !s->w->pseudo_window_p)
4132 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
4133 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4134 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4137 /* The glyph that may have a right box line. */
4138 last_glyph = (s->cmp || s->img
4139 ? s->first_glyph
4140 : s->first_glyph + s->nchars - 1);
4142 width = s->face->box_line_width;
4143 raised_p = s->face->box == FACE_RAISED_BOX;
4144 left_x = s->x;
4145 right_x = ((s->row->full_width_p
4146 ? last_x - 1
4147 : min (last_x, s->x + s->background_width) - 1));
4148 top_y = s->y;
4149 bottom_y = top_y + s->height - 1;
4151 left_p = (s->first_glyph->left_box_line_p
4152 || (s->hl == DRAW_MOUSE_FACE
4153 && (s->prev == NULL
4154 || s->prev->hl != s->hl)));
4155 right_p = (last_glyph->right_box_line_p
4156 || (s->hl == DRAW_MOUSE_FACE
4157 && (s->next == NULL
4158 || s->next->hl != s->hl)));
4160 x_get_glyph_string_clip_rect (s, &clip_rect);
4162 if (s->face->box == FACE_SIMPLE_BOX)
4163 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4164 left_p, right_p, &clip_rect);
4165 else
4167 x_setup_relief_colors (s);
4168 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4169 width, raised_p, left_p, right_p, &clip_rect);
4174 /* Draw foreground of image glyph string S. */
4176 static void
4177 x_draw_image_foreground (s)
4178 struct glyph_string *s;
4180 int x;
4181 int y = s->ybase - image_ascent (s->img, s->face);
4183 /* If first glyph of S has a left box line, start drawing it to the
4184 right of that line. */
4185 if (s->face->box != FACE_NO_BOX
4186 && s->first_glyph->left_box_line_p)
4187 x = s->x + s->face->box_line_width;
4188 else
4189 x = s->x;
4191 /* If there is a margin around the image, adjust x- and y-position
4192 by that margin. */
4193 if (s->img->margin)
4195 x += s->img->margin;
4196 y += s->img->margin;
4199 if (s->img->pixmap)
4201 #if 0 /* MAC_TODO: image mask */
4202 if (s->img->mask)
4204 /* We can't set both a clip mask and use XSetClipRectangles
4205 because the latter also sets a clip mask. We also can't
4206 trust on the shape extension to be available
4207 (XShapeCombineRegion). So, compute the rectangle to draw
4208 manually. */
4209 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4210 | GCFunction);
4211 XGCValues xgcv;
4212 XRectangle clip_rect, image_rect, r;
4214 xgcv.clip_mask = s->img->mask;
4215 xgcv.clip_x_origin = x;
4216 xgcv.clip_y_origin = y;
4217 xgcv.function = GXcopy;
4218 XChangeGC (s->display, s->gc, mask, &xgcv);
4220 x_get_glyph_string_clip_rect (s, &clip_rect);
4221 image_rect.x = x;
4222 image_rect.y = y;
4223 image_rect.width = s->img->width;
4224 image_rect.height = s->img->height;
4225 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4226 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4227 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4229 else
4230 #endif
4232 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4233 0, 0, s->img->width, s->img->height, x, y);
4235 /* When the image has a mask, we can expect that at
4236 least part of a mouse highlight or a block cursor will
4237 be visible. If the image doesn't have a mask, make
4238 a block cursor visible by drawing a rectangle around
4239 the image. I believe it's looking better if we do
4240 nothing here for mouse-face. */
4241 if (s->hl == DRAW_CURSOR)
4242 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4243 s->img->width - 1, s->img->height - 1);
4246 else
4247 /* Draw a rectangle if image could not be loaded. */
4248 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4249 s->img->width - 1, s->img->height - 1);
4253 /* Draw a relief around the image glyph string S. */
4255 static void
4256 x_draw_image_relief (s)
4257 struct glyph_string *s;
4259 int x0, y0, x1, y1, thick, raised_p;
4260 Rect r;
4261 int x;
4262 int y = s->ybase - image_ascent (s->img, s->face);
4264 /* If first glyph of S has a left box line, start drawing it to the
4265 right of that line. */
4266 if (s->face->box != FACE_NO_BOX
4267 && s->first_glyph->left_box_line_p)
4268 x = s->x + s->face->box_line_width;
4269 else
4270 x = s->x;
4272 /* If there is a margin around the image, adjust x- and y-position
4273 by that margin. */
4274 if (s->img->margin)
4276 x += s->img->margin;
4277 y += s->img->margin;
4280 if (s->hl == DRAW_IMAGE_SUNKEN
4281 || s->hl == DRAW_IMAGE_RAISED)
4283 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
4284 raised_p = s->hl == DRAW_IMAGE_RAISED;
4286 else
4288 thick = abs (s->img->relief);
4289 raised_p = s->img->relief > 0;
4292 x0 = x - thick;
4293 y0 = y - thick;
4294 x1 = x + s->img->width + thick - 1;
4295 y1 = y + s->img->height + thick - 1;
4297 x_setup_relief_colors (s);
4298 x_get_glyph_string_clip_rect (s, &r);
4299 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4303 /* Draw the foreground of image glyph string S to PIXMAP. */
4305 static void
4306 x_draw_image_foreground_1 (s, pixmap)
4307 struct glyph_string *s;
4308 Pixmap pixmap;
4310 int x;
4311 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4313 /* If first glyph of S has a left box line, start drawing it to the
4314 right of that line. */
4315 if (s->face->box != FACE_NO_BOX
4316 && s->first_glyph->left_box_line_p)
4317 x = s->face->box_line_width;
4318 else
4319 x = 0;
4321 /* If there is a margin around the image, adjust x- and y-position
4322 by that margin. */
4323 if (s->img->margin)
4325 x += s->img->margin;
4326 y += s->img->margin;
4329 if (s->img->pixmap)
4331 #if 0 /* MAC_TODO: image mask */
4332 if (s->img->mask)
4334 /* We can't set both a clip mask and use XSetClipRectangles
4335 because the latter also sets a clip mask. We also can't
4336 trust on the shape extension to be available
4337 (XShapeCombineRegion). So, compute the rectangle to draw
4338 manually. */
4339 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4340 | GCFunction);
4341 XGCValues xgcv;
4343 xgcv.clip_mask = s->img->mask;
4344 xgcv.clip_x_origin = x;
4345 xgcv.clip_y_origin = y;
4346 xgcv.function = GXcopy;
4347 XChangeGC (s->display, s->gc, mask, &xgcv);
4349 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4350 0, 0, s->img->width, s->img->height, x, y);
4351 XSetClipMask (s->display, s->gc, None);
4353 else
4354 #endif
4356 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4357 0, 0, s->img->width, s->img->height, x, y);
4359 /* When the image has a mask, we can expect that at
4360 least part of a mouse highlight or a block cursor will
4361 be visible. If the image doesn't have a mask, make
4362 a block cursor visible by drawing a rectangle around
4363 the image. I believe it's looking better if we do
4364 nothing here for mouse-face. */
4365 if (s->hl == DRAW_CURSOR)
4366 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4367 s->img->width - 1, s->img->height - 1);
4370 else
4371 /* Draw a rectangle if image could not be loaded. */
4372 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4373 s->img->width - 1, s->img->height - 1);
4377 /* Draw part of the background of glyph string S. X, Y, W, and H
4378 give the rectangle to draw. */
4380 static void
4381 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4382 struct glyph_string *s;
4383 int x, y, w, h;
4385 #if 0 /* MAC_TODO: stipple */
4386 if (s->stippled_p)
4388 /* Fill background with a stipple pattern. */
4389 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4390 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4391 XSetFillStyle (s->display, s->gc, FillSolid);
4393 else
4394 #endif
4395 x_clear_glyph_string_rect (s, x, y, w, h);
4399 /* Draw image glyph string S.
4401 s->y
4402 s->x +-------------------------
4403 | s->face->box
4405 | +-------------------------
4406 | | s->img->margin
4408 | | +-------------------
4409 | | | the image
4413 static void
4414 x_draw_image_glyph_string (s)
4415 struct glyph_string *s;
4417 int x, y;
4418 int box_line_width = s->face->box_line_width;
4419 int margin = s->img->margin;
4420 int height;
4421 Pixmap pixmap = 0;
4423 height = s->height - 2 * box_line_width;
4425 /* Fill background with face under the image. Do it only if row is
4426 taller than image or if image has a clip mask to reduce
4427 flickering. */
4428 s->stippled_p = s->face->stipple != 0;
4429 if (height > s->img->height
4430 || margin
4431 #if 0 /* MAC_TODO: image mask */
4432 || s->img->mask
4433 #endif
4434 || s->img->pixmap == 0
4435 || s->width != s->background_width)
4437 if (box_line_width && s->first_glyph->left_box_line_p)
4438 x = s->x + box_line_width;
4439 else
4440 x = s->x;
4442 y = s->y + box_line_width;
4444 #if 0 /* MAC_TODO: image mask */
4445 if (s->img->mask)
4447 /* Create a pixmap as large as the glyph string Fill it with
4448 the background color. Copy the image to it, using its
4449 mask. Copy the temporary pixmap to the display. */
4450 Screen *screen = FRAME_X_SCREEN (s->f);
4451 int depth = DefaultDepthOfScreen (screen);
4453 /* Create a pixmap as large as the glyph string. */
4454 pixmap = XCreatePixmap (s->display, s->window,
4455 s->background_width,
4456 s->height, depth);
4458 /* Don't clip in the following because we're working on the
4459 pixmap. */
4460 XSetClipMask (s->display, s->gc, None);
4462 /* Fill the pixmap with the background color/stipple. */
4463 if (s->stippled_p)
4465 /* Fill background with a stipple pattern. */
4466 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4467 XFillRectangle (s->display, pixmap, s->gc,
4468 0, 0, s->background_width, s->height);
4469 XSetFillStyle (s->display, s->gc, FillSolid);
4471 else
4473 XGCValues xgcv;
4474 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4475 &xgcv);
4476 XSetForeground (s->display, s->gc, xgcv.background);
4477 XFillRectangle (s->display, pixmap, s->gc,
4478 0, 0, s->background_width, s->height);
4479 XSetForeground (s->display, s->gc, xgcv.foreground);
4482 else
4483 #endif
4484 /* Implementation idea: Is it possible to construct a mask?
4485 We could look at the color at the margins of the image, and
4486 say that this color is probably the background color of the
4487 image. */
4488 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4490 s->background_filled_p = 1;
4493 /* Draw the foreground. */
4494 if (pixmap != 0)
4496 x_draw_image_foreground_1 (s, pixmap);
4497 x_set_glyph_string_clipping (s);
4498 mac_copy_area (s->display, pixmap, s->window, s->gc,
4499 0, 0, s->background_width, s->height, s->x, s->y);
4500 XFreePixmap (s->display, pixmap);
4502 else
4503 x_draw_image_foreground (s);
4505 /* If we must draw a relief around the image, do it. */
4506 if (s->img->relief
4507 || s->hl == DRAW_IMAGE_RAISED
4508 || s->hl == DRAW_IMAGE_SUNKEN)
4509 x_draw_image_relief (s);
4513 /* Draw stretch glyph string S. */
4515 static void
4516 x_draw_stretch_glyph_string (s)
4517 struct glyph_string *s;
4519 xassert (s->first_glyph->type == STRETCH_GLYPH);
4520 s->stippled_p = s->face->stipple != 0;
4522 if (s->hl == DRAW_CURSOR
4523 && !x_stretch_cursor_p)
4525 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4526 as wide as the stretch glyph. */
4527 int width = min (CANON_X_UNIT (s->f), s->background_width);
4529 /* Draw cursor. */
4530 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4532 /* Clear rest using the GC of the original non-cursor face. */
4533 if (width < s->background_width)
4535 GC gc = s->face->gc;
4536 int x = s->x + width, y = s->y;
4537 int w = s->background_width - width, h = s->height;
4538 Rect r;
4540 x_get_glyph_string_clip_rect (s, &r);
4541 mac_set_clip_rectangle (s->display, s->window, &r);
4543 #if 0 /* MAC_TODO: stipple */
4544 if (s->face->stipple)
4546 /* Fill background with a stipple pattern. */
4547 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4548 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4549 XSetFillStyle (s->display, gc, FillSolid);
4551 else
4552 #endif
4554 XGCValues xgcv;
4555 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4556 XSetForeground (s->display, gc, xgcv.background);
4557 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4558 XSetForeground (s->display, gc, xgcv.foreground);
4562 else
4563 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4564 s->height);
4566 s->background_filled_p = 1;
4570 /* Draw glyph string S. */
4572 static void
4573 x_draw_glyph_string (s)
4574 struct glyph_string *s;
4576 /* If S draws into the background of its successor, draw the
4577 background of the successor first so that S can draw into it.
4578 This makes S->next use XDrawString instead of XDrawImageString. */
4579 if (s->next && s->right_overhang && !s->for_overlaps_p)
4581 xassert (s->next->img == NULL);
4582 x_set_glyph_string_gc (s->next);
4583 x_set_glyph_string_clipping (s->next);
4584 x_draw_glyph_string_background (s->next, 1);
4587 /* Set up S->gc, set clipping and draw S. */
4588 x_set_glyph_string_gc (s);
4589 x_set_glyph_string_clipping (s);
4591 switch (s->first_glyph->type)
4593 case IMAGE_GLYPH:
4594 x_draw_image_glyph_string (s);
4595 break;
4597 case STRETCH_GLYPH:
4598 x_draw_stretch_glyph_string (s);
4599 break;
4601 case CHAR_GLYPH:
4602 if (s->for_overlaps_p)
4603 s->background_filled_p = 1;
4604 else
4605 x_draw_glyph_string_background (s, 0);
4606 x_draw_glyph_string_foreground (s);
4607 break;
4609 case COMPOSITE_GLYPH:
4610 if (s->for_overlaps_p || s->gidx > 0)
4611 s->background_filled_p = 1;
4612 else
4613 x_draw_glyph_string_background (s, 1);
4614 x_draw_composite_glyph_string_foreground (s);
4615 break;
4617 default:
4618 abort ();
4621 if (!s->for_overlaps_p)
4623 /* Draw underline. */
4624 if (s->face->underline_p)
4626 unsigned long h = 1;
4627 unsigned long dy = s->height - h;
4629 if (s->face->underline_defaulted_p)
4630 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4631 s->width, h);
4632 else
4634 XGCValues xgcv;
4635 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4636 XSetForeground (s->display, s->gc, s->face->underline_color);
4637 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4638 s->width, h);
4639 XSetForeground (s->display, s->gc, xgcv.foreground);
4643 /* Draw overline. */
4644 if (s->face->overline_p)
4646 unsigned long dy = 0, h = 1;
4648 if (s->face->overline_color_defaulted_p)
4649 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4650 s->width, h);
4651 else
4653 XGCValues xgcv;
4654 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4655 XSetForeground (s->display, s->gc, s->face->overline_color);
4656 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4657 s->width, h);
4658 XSetForeground (s->display, s->gc, xgcv.foreground);
4662 /* Draw strike-through. */
4663 if (s->face->strike_through_p)
4665 unsigned long h = 1;
4666 unsigned long dy = (s->height - h) / 2;
4668 if (s->face->strike_through_color_defaulted_p)
4669 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4670 s->width, h);
4671 else
4673 XGCValues xgcv;
4674 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4675 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4676 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4677 s->width, h);
4678 XSetForeground (s->display, s->gc, xgcv.foreground);
4682 /* Draw relief. */
4683 if (s->face->box != FACE_NO_BOX)
4684 x_draw_glyph_string_box (s);
4687 /* Reset clipping. */
4688 mac_reset_clipping (s->display, s->window);
4692 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4693 struct face **, int));
4696 /* Fill glyph string S with composition components specified by S->cmp.
4698 FACES is an array of faces for all components of this composition.
4699 S->gidx is the index of the first component for S.
4700 OVERLAPS_P non-zero means S should draw the foreground only, and
4701 use its physical height for clipping.
4703 Value is the index of a component not in S. */
4705 static int
4706 x_fill_composite_glyph_string (s, faces, overlaps_p)
4707 struct glyph_string *s;
4708 struct face **faces;
4709 int overlaps_p;
4711 int i;
4713 xassert (s);
4715 s->for_overlaps_p = overlaps_p;
4717 s->face = faces[s->gidx];
4718 s->font = s->face->font;
4719 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4721 /* For all glyphs of this composition, starting at the offset
4722 S->gidx, until we reach the end of the definition or encounter a
4723 glyph that requires the different face, add it to S. */
4724 ++s->nchars;
4725 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4726 ++s->nchars;
4728 /* All glyph strings for the same composition has the same width,
4729 i.e. the width set for the first component of the composition. */
4731 s->width = s->first_glyph->pixel_width;
4733 /* If the specified font could not be loaded, use the frame's
4734 default font, but record the fact that we couldn't load it in
4735 the glyph string so that we can draw rectangles for the
4736 characters of the glyph string. */
4737 if (s->font == NULL)
4739 s->font_not_found_p = 1;
4740 s->font = FRAME_FONT (s->f);
4743 /* Adjust base line for subscript/superscript text. */
4744 s->ybase += s->first_glyph->voffset;
4746 xassert (s->face && s->face->gc);
4748 /* This glyph string must always be drawn with 16-bit functions. */
4749 s->two_byte_p = 1;
4751 return s->gidx + s->nchars;
4755 /* Fill glyph string S from a sequence of character glyphs.
4757 FACE_ID is the face id of the string. START is the index of the
4758 first glyph to consider, END is the index of the last + 1.
4759 OVERLAPS_P non-zero means S should draw the foreground only, and
4760 use its physical height for clipping.
4762 Value is the index of the first glyph not in S. */
4764 static int
4765 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4766 struct glyph_string *s;
4767 int face_id;
4768 int start, end, overlaps_p;
4770 struct glyph *glyph, *last;
4771 int voffset;
4772 int glyph_not_available_p;
4774 xassert (s->f == XFRAME (s->w->frame));
4775 xassert (s->nchars == 0);
4776 xassert (start >= 0 && end > start);
4778 s->for_overlaps_p = overlaps_p,
4779 glyph = s->row->glyphs[s->area] + start;
4780 last = s->row->glyphs[s->area] + end;
4781 voffset = glyph->voffset;
4783 glyph_not_available_p = glyph->glyph_not_available_p;
4785 while (glyph < last
4786 && glyph->type == CHAR_GLYPH
4787 && glyph->voffset == voffset
4788 /* Same face id implies same font, nowadays. */
4789 && glyph->face_id == face_id
4790 && glyph->glyph_not_available_p == glyph_not_available_p)
4792 int two_byte_p;
4794 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4795 s->char2b + s->nchars,
4796 &two_byte_p);
4797 s->two_byte_p = two_byte_p;
4798 ++s->nchars;
4799 xassert (s->nchars <= end - start);
4800 s->width += glyph->pixel_width;
4801 ++glyph;
4804 s->font = s->face->font;
4805 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4807 /* If the specified font could not be loaded, use the frame's font,
4808 but record the fact that we couldn't load it in
4809 S->font_not_found_p so that we can draw rectangles for the
4810 characters of the glyph string. */
4811 if (s->font == NULL || glyph_not_available_p)
4813 s->font_not_found_p = 1;
4814 s->font = FRAME_FONT (s->f);
4817 /* Adjust base line for subscript/superscript text. */
4818 s->ybase += voffset;
4820 xassert (s->face && s->face->gc);
4821 return glyph - s->row->glyphs[s->area];
4825 /* Fill glyph string S from image glyph S->first_glyph. */
4827 static void
4828 x_fill_image_glyph_string (s)
4829 struct glyph_string *s;
4831 xassert (s->first_glyph->type == IMAGE_GLYPH);
4832 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4833 xassert (s->img);
4834 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4835 s->font = s->face->font;
4836 s->width = s->first_glyph->pixel_width;
4838 /* Adjust base line for subscript/superscript text. */
4839 s->ybase += s->first_glyph->voffset;
4843 /* Fill glyph string S from a sequence of stretch glyphs.
4845 ROW is the glyph row in which the glyphs are found, AREA is the
4846 area within the row. START is the index of the first glyph to
4847 consider, END is the index of the last + 1.
4849 Value is the index of the first glyph not in S. */
4851 static int
4852 x_fill_stretch_glyph_string (s, row, area, start, end)
4853 struct glyph_string *s;
4854 struct glyph_row *row;
4855 enum glyph_row_area area;
4856 int start, end;
4858 struct glyph *glyph, *last;
4859 int voffset, face_id;
4861 xassert (s->first_glyph->type == STRETCH_GLYPH);
4863 glyph = s->row->glyphs[s->area] + start;
4864 last = s->row->glyphs[s->area] + end;
4865 face_id = glyph->face_id;
4866 s->face = FACE_FROM_ID (s->f, face_id);
4867 s->font = s->face->font;
4868 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4869 s->width = glyph->pixel_width;
4870 voffset = glyph->voffset;
4872 for (++glyph;
4873 (glyph < last
4874 && glyph->type == STRETCH_GLYPH
4875 && glyph->voffset == voffset
4876 && glyph->face_id == face_id);
4877 ++glyph)
4878 s->width += glyph->pixel_width;
4880 /* Adjust base line for subscript/superscript text. */
4881 s->ybase += voffset;
4883 xassert (s->face && s->face->gc);
4884 return glyph - s->row->glyphs[s->area];
4888 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4889 of XChar2b structures for S; it can't be allocated in
4890 x_init_glyph_string because it must be allocated via `alloca'. W
4891 is the window on which S is drawn. ROW and AREA are the glyph row
4892 and area within the row from which S is constructed. START is the
4893 index of the first glyph structure covered by S. HL is a
4894 face-override for drawing S. */
4896 static void
4897 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4898 struct glyph_string *s;
4899 XChar2b *char2b;
4900 struct window *w;
4901 struct glyph_row *row;
4902 enum glyph_row_area area;
4903 int start;
4904 enum draw_glyphs_face hl;
4906 bzero (s, sizeof *s);
4907 s->w = w;
4908 s->f = XFRAME (w->frame);
4909 s->display = FRAME_MAC_DISPLAY (s->f);
4910 s->window = FRAME_MAC_WINDOW (s->f);
4911 s->char2b = char2b;
4912 s->hl = hl;
4913 s->row = row;
4914 s->area = area;
4915 s->first_glyph = row->glyphs[area] + start;
4916 s->height = row->height;
4917 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4919 /* Display the internal border below the tool-bar window. */
4920 if (s->w == XWINDOW (s->f->tool_bar_window))
4921 s->y -= s->f->output_data.mac->internal_border_width;
4923 s->ybase = s->y + row->ascent;
4927 /* Set background width of glyph string S. START is the index of the
4928 first glyph following S. LAST_X is the right-most x-position + 1
4929 in the drawing area. */
4931 static INLINE void
4932 x_set_glyph_string_background_width (s, start, last_x)
4933 struct glyph_string *s;
4934 int start;
4935 int last_x;
4937 /* If the face of this glyph string has to be drawn to the end of
4938 the drawing area, set S->extends_to_end_of_line_p. */
4939 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4941 if (start == s->row->used[s->area]
4942 && s->hl == DRAW_NORMAL_TEXT
4943 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4944 || s->face->background != default_face->background
4945 || s->face->stipple != default_face->stipple))
4946 s->extends_to_end_of_line_p = 1;
4948 /* If S extends its face to the end of the line, set its
4949 background_width to the distance to the right edge of the drawing
4950 area. */
4951 if (s->extends_to_end_of_line_p)
4952 s->background_width = last_x - s->x + 1;
4953 else
4954 s->background_width = s->width;
4958 /* Add a glyph string for a stretch glyph to the list of strings
4959 between HEAD and TAIL. START is the index of the stretch glyph in
4960 row area AREA of glyph row ROW. END is the index of the last glyph
4961 in that glyph row area. X is the current output position assigned
4962 to the new glyph string constructed. HL overrides that face of the
4963 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4964 is the right-most x-position of the drawing area. */
4966 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4967 and below -- keep them on one line. */
4968 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4969 do \
4971 s = (struct glyph_string *) alloca (sizeof *s); \
4972 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4973 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4974 x_append_glyph_string (&HEAD, &TAIL, s); \
4975 s->x = (X); \
4977 while (0)
4980 /* Add a glyph string for an image glyph to the list of strings
4981 between HEAD and TAIL. START is the index of the image glyph in
4982 row area AREA of glyph row ROW. END is the index of the last glyph
4983 in that glyph row area. X is the current output position assigned
4984 to the new glyph string constructed. HL overrides that face of the
4985 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4986 is the right-most x-position of the drawing area. */
4988 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4989 do \
4991 s = (struct glyph_string *) alloca (sizeof *s); \
4992 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4993 x_fill_image_glyph_string (s); \
4994 x_append_glyph_string (&HEAD, &TAIL, s); \
4995 ++START; \
4996 s->x = (X); \
4998 while (0)
5001 /* Add a glyph string for a sequence of character glyphs to the list
5002 of strings between HEAD and TAIL. START is the index of the first
5003 glyph in row area AREA of glyph row ROW that is part of the new
5004 glyph string. END is the index of the last glyph in that glyph row
5005 area. X is the current output position assigned to the new glyph
5006 string constructed. HL overrides that face of the glyph; e.g. it
5007 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5008 right-most x-position of the drawing area. */
5010 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5011 do \
5013 int c, face_id; \
5014 XChar2b *char2b; \
5016 c = (ROW)->glyphs[AREA][START].u.ch; \
5017 face_id = (ROW)->glyphs[AREA][START].face_id; \
5019 s = (struct glyph_string *) alloca (sizeof *s); \
5020 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5021 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5022 x_append_glyph_string (&HEAD, &TAIL, s); \
5023 s->x = (X); \
5024 START = x_fill_glyph_string (s, face_id, START, END, \
5025 OVERLAPS_P); \
5027 while (0)
5030 /* Add a glyph string for a composite sequence to the list of strings
5031 between HEAD and TAIL. START is the index of the first glyph in
5032 row area AREA of glyph row ROW that is part of the new glyph
5033 string. END is the index of the last glyph in that glyph row area.
5034 X is the current output position assigned to the new glyph string
5035 constructed. HL overrides that face of the glyph; e.g. it is
5036 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5037 x-position of the drawing area. */
5039 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5040 do { \
5041 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5042 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5043 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5044 struct composition *cmp = composition_table[cmp_id]; \
5045 int glyph_len = cmp->glyph_len; \
5046 XChar2b *char2b; \
5047 struct face **faces; \
5048 struct glyph_string *first_s = NULL; \
5049 int n; \
5051 base_face = base_face->ascii_face; \
5052 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5053 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5054 /* At first, fill in `char2b' and `faces'. */ \
5055 for (n = 0; n < glyph_len; n++) \
5057 int c = COMPOSITION_GLYPH (cmp, n); \
5058 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5059 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5060 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5061 this_face_id, char2b + n, 1); \
5064 /* Make glyph_strings for each glyph sequence that is drawable by \
5065 the same face, and append them to HEAD/TAIL. */ \
5066 for (n = 0; n < cmp->glyph_len;) \
5068 s = (struct glyph_string *) alloca (sizeof *s); \
5069 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5070 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5071 s->cmp = cmp; \
5072 s->gidx = n; \
5073 s->x = (X); \
5075 if (n == 0) \
5076 first_s = s; \
5078 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5081 ++START; \
5082 s = first_s; \
5083 } while (0)
5086 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5087 of AREA of glyph row ROW on window W between indices START and END.
5088 HL overrides the face for drawing glyph strings, e.g. it is
5089 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5090 x-positions of the drawing area.
5092 This is an ugly monster macro construct because we must use alloca
5093 to allocate glyph strings (because x_draw_glyphs can be called
5094 asynchronously). */
5096 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5097 do \
5099 HEAD = TAIL = NULL; \
5100 while (START < END) \
5102 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5103 switch (first_glyph->type) \
5105 case CHAR_GLYPH: \
5106 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5107 TAIL, HL, X, LAST_X, \
5108 OVERLAPS_P); \
5109 break; \
5111 case COMPOSITE_GLYPH: \
5112 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5113 HEAD, TAIL, HL, X, LAST_X,\
5114 OVERLAPS_P); \
5115 break; \
5117 case STRETCH_GLYPH: \
5118 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5119 HEAD, TAIL, HL, X, LAST_X); \
5120 break; \
5122 case IMAGE_GLYPH: \
5123 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5124 TAIL, HL, X, LAST_X); \
5125 break; \
5127 default: \
5128 abort (); \
5131 x_set_glyph_string_background_width (s, START, LAST_X); \
5132 (X) += s->width; \
5135 while (0)
5138 /* Draw glyphs between START and END in AREA of ROW on window W,
5139 starting at x-position X. X is relative to AREA in W. HL is a
5140 face-override with the following meaning:
5142 DRAW_NORMAL_TEXT draw normally
5143 DRAW_CURSOR draw in cursor face
5144 DRAW_MOUSE_FACE draw in mouse face.
5145 DRAW_INVERSE_VIDEO draw in mode line face
5146 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5147 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5149 If REAL_START is non-null, return in *REAL_START the real starting
5150 position for display. This can be different from START in case
5151 overlapping glyphs must be displayed. If REAL_END is non-null,
5152 return in *REAL_END the real end position for display. This can be
5153 different from END in case overlapping glyphs must be displayed.
5155 If OVERLAPS_P is non-zero, draw only the foreground of characters
5156 and clip to the physical height of ROW.
5158 Value is the x-position reached, relative to AREA of W. */
5160 static int
5161 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
5162 overlaps_p)
5163 struct window *w;
5164 int x;
5165 struct glyph_row *row;
5166 enum glyph_row_area area;
5167 int start, end;
5168 enum draw_glyphs_face hl;
5169 int *real_start, *real_end;
5170 int overlaps_p;
5172 struct glyph_string *head, *tail;
5173 struct glyph_string *s;
5174 int last_x, area_width;
5175 int x_reached;
5176 int i, j;
5178 /* Let's rather be paranoid than getting a SEGV. */
5179 start = max (0, start);
5180 end = min (end, row->used[area]);
5181 if (real_start)
5182 *real_start = start;
5183 if (real_end)
5184 *real_end = end;
5186 /* Translate X to frame coordinates. Set last_x to the right
5187 end of the drawing area. */
5188 if (row->full_width_p)
5190 /* X is relative to the left edge of W, without scroll bars
5191 or flag areas. */
5192 struct frame *f = XFRAME (w->frame);
5193 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
5194 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5196 x += window_left_x;
5197 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5198 last_x = window_left_x + area_width;
5200 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5202 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5203 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5204 last_x += width;
5205 else
5206 x -= width;
5209 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5210 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5212 else
5214 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5215 area_width = window_box_width (w, area);
5216 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5219 /* Build a doubly-linked list of glyph_string structures between
5220 head and tail from what we have to draw. Note that the macro
5221 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5222 the reason we use a separate variable `i'. */
5223 i = start;
5224 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5225 overlaps_p);
5226 if (tail)
5227 x_reached = tail->x + tail->background_width;
5228 else
5229 x_reached = x;
5231 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5232 the row, redraw some glyphs in front or following the glyph
5233 strings built above. */
5234 if (!overlaps_p && row->contains_overlapping_glyphs_p)
5236 int dummy_x = 0;
5237 struct glyph_string *h, *t;
5239 /* Compute overhangs for all glyph strings. */
5240 for (s = head; s; s = s->next)
5241 x_compute_glyph_string_overhangs (s);
5243 /* Prepend glyph strings for glyphs in front of the first glyph
5244 string that are overwritten because of the first glyph
5245 string's left overhang. The background of all strings
5246 prepended must be drawn because the first glyph string
5247 draws over it. */
5248 i = x_left_overwritten (head);
5249 if (i >= 0)
5251 j = i;
5252 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5253 DRAW_NORMAL_TEXT, dummy_x, last_x,
5254 overlaps_p);
5255 start = i;
5256 if (real_start)
5257 *real_start = start;
5258 x_compute_overhangs_and_x (t, head->x, 1);
5259 x_prepend_glyph_string_lists (&head, &tail, h, t);
5262 /* Prepend glyph strings for glyphs in front of the first glyph
5263 string that overwrite that glyph string because of their
5264 right overhang. For these strings, only the foreground must
5265 be drawn, because it draws over the glyph string at `head'.
5266 The background must not be drawn because this would overwrite
5267 right overhangs of preceding glyphs for which no glyph
5268 strings exist. */
5269 i = x_left_overwriting (head);
5270 if (i >= 0)
5272 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5273 DRAW_NORMAL_TEXT, dummy_x, last_x,
5274 overlaps_p);
5275 for (s = h; s; s = s->next)
5276 s->background_filled_p = 1;
5277 if (real_start)
5278 *real_start = i;
5279 x_compute_overhangs_and_x (t, head->x, 1);
5280 x_prepend_glyph_string_lists (&head, &tail, h, t);
5283 /* Append glyphs strings for glyphs following the last glyph
5284 string tail that are overwritten by tail. The background of
5285 these strings has to be drawn because tail's foreground draws
5286 over it. */
5287 i = x_right_overwritten (tail);
5288 if (i >= 0)
5290 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5291 DRAW_NORMAL_TEXT, x, last_x,
5292 overlaps_p);
5293 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5294 x_append_glyph_string_lists (&head, &tail, h, t);
5295 if (real_end)
5296 *real_end = i;
5299 /* Append glyph strings for glyphs following the last glyph
5300 string tail that overwrite tail. The foreground of such
5301 glyphs has to be drawn because it writes into the background
5302 of tail. The background must not be drawn because it could
5303 paint over the foreground of following glyphs. */
5304 i = x_right_overwriting (tail);
5305 if (i >= 0)
5307 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5308 DRAW_NORMAL_TEXT, x, last_x,
5309 overlaps_p);
5310 for (s = h; s; s = s->next)
5311 s->background_filled_p = 1;
5312 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5313 x_append_glyph_string_lists (&head, &tail, h, t);
5314 if (real_end)
5315 *real_end = i;
5319 /* Draw all strings. */
5320 for (s = head; s; s = s->next)
5321 x_draw_glyph_string (s);
5323 /* Value is the x-position up to which drawn, relative to AREA of W.
5324 This doesn't include parts drawn because of overhangs. */
5325 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5326 if (!row->full_width_p)
5328 if (area > LEFT_MARGIN_AREA)
5329 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5330 if (area > TEXT_AREA)
5331 x_reached -= window_box_width (w, TEXT_AREA);
5333 return x_reached;
5337 /* Fix the display of area AREA of overlapping row ROW in window W. */
5339 void
5340 x_fix_overlapping_area (w, row, area)
5341 struct window *w;
5342 struct glyph_row *row;
5343 enum glyph_row_area area;
5345 int i, x;
5347 BLOCK_INPUT;
5349 if (area == LEFT_MARGIN_AREA)
5350 x = 0;
5351 else if (area == TEXT_AREA)
5352 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5353 else
5354 x = (window_box_width (w, LEFT_MARGIN_AREA)
5355 + window_box_width (w, TEXT_AREA));
5357 for (i = 0; i < row->used[area];)
5359 if (row->glyphs[area][i].overlaps_vertically_p)
5361 int start = i, start_x = x;
5365 x += row->glyphs[area][i].pixel_width;
5366 ++i;
5368 while (i < row->used[area]
5369 && row->glyphs[area][i].overlaps_vertically_p);
5371 x_draw_glyphs (w, start_x, row, area, start, i,
5372 (row->inverse_p
5373 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5374 NULL, NULL, 1);
5376 else
5378 x += row->glyphs[area][i].pixel_width;
5379 ++i;
5383 UNBLOCK_INPUT;
5387 /* Output LEN glyphs starting at START at the nominal cursor position.
5388 Advance the nominal cursor over the text. The global variable
5389 updated_window contains the window being updated, updated_row is
5390 the glyph row being updated, and updated_area is the area of that
5391 row being updated. */
5393 void
5394 x_write_glyphs (start, len)
5395 struct glyph *start;
5396 int len;
5398 int x, hpos, real_start, real_end;
5400 xassert (updated_window && updated_row);
5401 BLOCK_INPUT;
5403 /* Write glyphs. */
5405 hpos = start - updated_row->glyphs[updated_area];
5406 x = x_draw_glyphs (updated_window, output_cursor.x,
5407 updated_row, updated_area,
5408 hpos, hpos + len,
5409 (updated_row->inverse_p
5410 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5411 &real_start, &real_end, 0);
5413 /* If we drew over the cursor, note that it is not visible any more. */
5414 note_overwritten_text_cursor (updated_window, real_start,
5415 real_end - real_start);
5417 UNBLOCK_INPUT;
5419 /* Advance the output cursor. */
5420 output_cursor.hpos += len;
5421 output_cursor.x = x;
5425 /* Insert LEN glyphs from START at the nominal cursor position. */
5427 void
5428 x_insert_glyphs (start, len)
5429 struct glyph *start;
5430 register int len;
5432 struct frame *f;
5433 struct window *w;
5434 int line_height, shift_by_width, shifted_region_width;
5435 struct glyph_row *row;
5436 struct glyph *glyph;
5437 int frame_x, frame_y, hpos, real_start, real_end;
5439 xassert (updated_window && updated_row);
5440 BLOCK_INPUT;
5441 w = updated_window;
5442 f = XFRAME (WINDOW_FRAME (w));
5444 /* Get the height of the line we are in. */
5445 row = updated_row;
5446 line_height = row->height;
5448 /* Get the width of the glyphs to insert. */
5449 shift_by_width = 0;
5450 for (glyph = start; glyph < start + len; ++glyph)
5451 shift_by_width += glyph->pixel_width;
5453 /* Get the width of the region to shift right. */
5454 shifted_region_width = (window_box_width (w, updated_area)
5455 - output_cursor.x
5456 - shift_by_width);
5458 /* Shift right. */
5459 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
5460 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5462 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5463 f->output_data.mac->normal_gc,
5464 frame_x, frame_y,
5465 shifted_region_width, line_height,
5466 frame_x + shift_by_width, frame_y);
5468 /* Write the glyphs. */
5469 hpos = start - row->glyphs[updated_area];
5470 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5471 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
5472 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5474 /* Advance the output cursor. */
5475 output_cursor.hpos += len;
5476 output_cursor.x += shift_by_width;
5477 UNBLOCK_INPUT;
5481 /* Delete N glyphs at the nominal cursor position. Not implemented
5482 for X frames. */
5484 void
5485 x_delete_glyphs (n)
5486 register int n;
5488 abort ();
5492 /* Erase the current text line from the nominal cursor position
5493 (inclusive) to pixel column TO_X (exclusive). The idea is that
5494 everything from TO_X onward is already erased.
5496 TO_X is a pixel position relative to updated_area of
5497 updated_window. TO_X == -1 means clear to the end of this area. */
5499 void
5500 x_clear_end_of_line (to_x)
5501 int to_x;
5503 struct frame *f;
5504 struct window *w = updated_window;
5505 int max_x, min_y, max_y;
5506 int from_x, from_y, to_y;
5508 xassert (updated_window && updated_row);
5509 f = XFRAME (w->frame);
5511 if (updated_row->full_width_p)
5513 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5514 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5515 && !w->pseudo_window_p)
5516 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5518 else
5519 max_x = window_box_width (w, updated_area);
5520 max_y = window_text_bottom_y (w);
5522 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5523 of window. For TO_X > 0, truncate to end of drawing area. */
5524 if (to_x == 0)
5525 return;
5526 else if (to_x < 0)
5527 to_x = max_x;
5528 else
5529 to_x = min (to_x, max_x);
5531 to_y = min (max_y, output_cursor.y + updated_row->height);
5533 /* Notice if the cursor will be cleared by this operation. */
5534 if (!updated_row->full_width_p)
5535 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
5537 from_x = output_cursor.x;
5539 /* Translate to frame coordinates. */
5540 if (updated_row->full_width_p)
5542 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5543 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5545 else
5547 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5548 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5551 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5552 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5553 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5555 /* Prevent inadvertently clearing to end of the X window. */
5556 if (to_x > from_x && to_y > from_y)
5558 BLOCK_INPUT;
5559 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5560 from_x, from_y, to_x - from_x, to_y - from_y,
5562 UNBLOCK_INPUT;
5567 /* Clear entire frame. If updating_frame is non-null, clear that
5568 frame. Otherwise clear the selected frame. */
5570 void
5571 x_clear_frame ()
5573 struct frame *f;
5575 if (updating_frame)
5576 f = updating_frame;
5577 else
5578 f = SELECTED_FRAME ();
5580 /* Clearing the frame will erase any cursor, so mark them all as no
5581 longer visible. */
5582 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5583 output_cursor.hpos = output_cursor.vpos = 0;
5584 output_cursor.x = -1;
5586 /* We don't set the output cursor here because there will always
5587 follow an explicit cursor_to. */
5588 BLOCK_INPUT;
5589 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5591 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5592 /* We have to clear the scroll bars, too. If we have changed
5593 colors or something like that, then they should be notified. */
5594 x_scroll_bar_clear (f);
5595 #endif
5597 XFlush (FRAME_MAC_DISPLAY (f));
5598 UNBLOCK_INPUT;
5603 /* Invert the middle quarter of the frame for .15 sec. */
5605 /* We use the select system call to do the waiting, so we have to make
5606 sure it's available. If it isn't, we just won't do visual bells. */
5608 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5610 /* Subtract the `struct timeval' values X and Y, storing the result in
5611 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5613 static int
5614 timeval_subtract (result, x, y)
5615 struct timeval *result, x, y;
5617 /* Perform the carry for the later subtraction by updating y. This
5618 is safer because on some systems the tv_sec member is unsigned. */
5619 if (x.tv_usec < y.tv_usec)
5621 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5622 y.tv_usec -= 1000000 * nsec;
5623 y.tv_sec += nsec;
5626 if (x.tv_usec - y.tv_usec > 1000000)
5628 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5629 y.tv_usec += 1000000 * nsec;
5630 y.tv_sec -= nsec;
5633 /* Compute the time remaining to wait. tv_usec is certainly
5634 positive. */
5635 result->tv_sec = x.tv_sec - y.tv_sec;
5636 result->tv_usec = x.tv_usec - y.tv_usec;
5638 /* Return indication of whether the result should be considered
5639 negative. */
5640 return x.tv_sec < y.tv_sec;
5643 void
5644 XTflash (f)
5645 struct frame *f;
5647 BLOCK_INPUT;
5649 FlashMenuBar (0);
5652 struct timeval wakeup;
5654 EMACS_GET_TIME (wakeup);
5656 /* Compute time to wait until, propagating carry from usecs. */
5657 wakeup.tv_usec += 150000;
5658 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5659 wakeup.tv_usec %= 1000000;
5661 /* Keep waiting until past the time wakeup. */
5662 while (1)
5664 struct timeval timeout;
5666 EMACS_GET_TIME (timeout);
5668 /* In effect, timeout = wakeup - timeout.
5669 Break if result would be negative. */
5670 if (timeval_subtract (&timeout, wakeup, timeout))
5671 break;
5673 /* Try to wait that long--but we might wake up sooner. */
5674 select (0, NULL, NULL, NULL, &timeout);
5678 FlashMenuBar (0);
5680 UNBLOCK_INPUT;
5683 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5686 /* Make audible bell. */
5688 void
5689 XTring_bell ()
5691 struct frame *f = SELECTED_FRAME ();
5693 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5694 if (visible_bell)
5695 XTflash (f);
5696 else
5697 #endif
5699 BLOCK_INPUT;
5700 SysBeep (1);
5701 XFlush (FRAME_MAC_DISPLAY (f));
5702 UNBLOCK_INPUT;
5708 /* Specify how many text lines, from the top of the window,
5709 should be affected by insert-lines and delete-lines operations.
5710 This, and those operations, are used only within an update
5711 that is bounded by calls to x_update_begin and x_update_end. */
5713 void
5714 XTset_terminal_window (n)
5715 register int n;
5717 /* This function intentionally left blank. */
5722 /***********************************************************************
5723 Line Dance
5724 ***********************************************************************/
5726 /* Perform an insert-lines or delete-lines operation, inserting N
5727 lines or deleting -N lines at vertical position VPOS. */
5729 void
5730 x_ins_del_lines (vpos, n)
5731 int vpos, n;
5733 abort ();
5737 /* Scroll part of the display as described by RUN. */
5739 void
5740 x_scroll_run (w, run)
5741 struct window *w;
5742 struct run *run;
5744 struct frame *f = XFRAME (w->frame);
5745 int x, y, width, height, from_y, to_y, bottom_y;
5747 /* Get frame-relative bounding box of the text display area of W,
5748 without mode lines. Include in this box the flags areas to the
5749 left and right of W. */
5750 window_box (w, -1, &x, &y, &width, &height);
5751 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5752 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5754 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5755 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5756 bottom_y = y + height;
5758 if (to_y < from_y)
5760 /* Scrolling up. Make sure we don't copy part of the mode
5761 line at the bottom. */
5762 if (from_y + run->height > bottom_y)
5763 height = bottom_y - from_y;
5764 else
5765 height = run->height;
5767 else
5769 /* Scolling down. Make sure we don't copy over the mode line.
5770 at the bottom. */
5771 if (to_y + run->height > bottom_y)
5772 height = bottom_y - to_y;
5773 else
5774 height = run->height;
5777 BLOCK_INPUT;
5779 /* Cursor off. Will be switched on again in x_update_window_end. */
5780 updated_window = w;
5781 x_clear_cursor (w);
5783 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5784 f->output_data.mac->normal_gc,
5785 x, from_y,
5786 width, height,
5787 x, to_y);
5789 UNBLOCK_INPUT;
5794 /***********************************************************************
5795 Exposure Events
5796 ***********************************************************************/
5798 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5799 corner of the exposed rectangle. W and H are width and height of
5800 the exposed area. All are pixel values. W or H zero means redraw
5801 the entire frame. */
5803 static void
5804 expose_frame (f, x, y, w, h)
5805 struct frame *f;
5806 int x, y, w, h;
5808 Rect r;
5810 TRACE ((stderr, "expose_frame "));
5812 /* No need to redraw if frame will be redrawn soon. */
5813 if (FRAME_GARBAGED_P (f))
5815 TRACE ((stderr, " garbaged\n"));
5816 return;
5819 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
5820 or deactivated here, for unknown reasons, activated scroll bars
5821 are shown in deactivated frames in some instances. */
5822 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
5823 activate_scroll_bars (f);
5824 else
5825 deactivate_scroll_bars (f);
5827 /* If basic faces haven't been realized yet, there is no point in
5828 trying to redraw anything. This can happen when we get an expose
5829 event while Emacs is starting, e.g. by moving another window. */
5830 if (FRAME_FACE_CACHE (f) == NULL
5831 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5833 TRACE ((stderr, " no faces\n"));
5834 return;
5837 if (w == 0 || h == 0)
5839 r.left = r.top = 0;
5840 r.right = CANON_X_UNIT (f) * f->width;
5841 r.bottom = CANON_Y_UNIT (f) * f->height;
5843 else
5845 r.left = x;
5846 r.top = y;
5847 r.right = x + w;
5848 r.bottom = y + h;
5851 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
5852 expose_window_tree (XWINDOW (f->root_window), &r);
5854 if (WINDOWP (f->tool_bar_window))
5856 struct window *w = XWINDOW (f->tool_bar_window);
5857 Rect window_rect;
5858 Rect intersection_rect;
5859 int window_x, window_y, window_width, window_height;
5862 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5863 window_rect.left = window_x;
5864 window_rect.top = window_y;
5865 window_rect.right = window_x + window_width;
5866 window_rect.bottom = window_y + window_height;
5868 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5869 expose_window (w, &intersection_rect);
5872 #ifndef USE_X_TOOLKIT
5873 if (WINDOWP (f->menu_bar_window))
5875 struct window *w = XWINDOW (f->menu_bar_window);
5876 Rect window_rect;
5877 Rect intersection_rect;
5878 int window_x, window_y, window_width, window_height;
5881 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5882 window_rect.left = window_x;
5883 window_rect.top = window_y;
5884 window_rect.right = window_x + window_width;
5885 window_rect.bottom = window_y + window_height;
5887 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5888 expose_window (w, &intersection_rect);
5890 #endif /* not USE_X_TOOLKIT */
5894 /* Redraw (parts) of all windows in the window tree rooted at W that
5895 intersect R. R contains frame pixel coordinates. */
5897 static void
5898 expose_window_tree (w, r)
5899 struct window *w;
5900 Rect *r;
5902 while (w)
5904 if (!NILP (w->hchild))
5905 expose_window_tree (XWINDOW (w->hchild), r);
5906 else if (!NILP (w->vchild))
5907 expose_window_tree (XWINDOW (w->vchild), r);
5908 else
5910 Rect window_rect;
5911 Rect intersection_rect;
5912 struct frame *f = XFRAME (w->frame);
5913 int window_x, window_y, window_width, window_height;
5915 /* Frame-relative pixel rectangle of W. */
5916 window_box (w, -1, &window_x, &window_y, &window_width,
5917 &window_height);
5918 window_rect.left
5919 = (window_x
5920 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5921 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
5922 window_rect.top = window_y;
5923 window_rect.right = window_rect.left
5924 + (window_width
5925 + FRAME_X_FLAGS_AREA_WIDTH (f)
5926 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5927 window_rect.bottom = window_rect.top
5928 + window_height + CURRENT_MODE_LINE_HEIGHT (w);
5930 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5931 expose_window (w, &intersection_rect);
5934 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5939 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5940 which intersects rectangle R. R is in window-relative coordinates. */
5942 static void
5943 expose_area (w, row, r, area)
5944 struct window *w;
5945 struct glyph_row *row;
5946 Rect *r;
5947 enum glyph_row_area area;
5949 int x;
5950 struct glyph *first = row->glyphs[area];
5951 struct glyph *end = row->glyphs[area] + row->used[area];
5952 struct glyph *last;
5953 int first_x;
5955 /* Set x to the window-relative start position for drawing glyphs of
5956 AREA. The first glyph of the text area can be partially visible.
5957 The first glyphs of other areas cannot. */
5958 if (area == LEFT_MARGIN_AREA)
5959 x = 0;
5960 else if (area == TEXT_AREA)
5961 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5962 else
5963 x = (window_box_width (w, LEFT_MARGIN_AREA)
5964 + window_box_width (w, TEXT_AREA));
5966 if (area == TEXT_AREA && row->fill_line_p)
5967 /* If row extends face to end of line write the whole line. */
5968 x_draw_glyphs (w, x, row, area,
5969 0, row->used[area],
5970 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5971 NULL, NULL, 0);
5972 else
5974 /* Find the first glyph that must be redrawn. */
5975 while (first < end
5976 && x + first->pixel_width < r->left)
5978 x += first->pixel_width;
5979 ++first;
5982 /* Find the last one. */
5983 last = first;
5984 first_x = x;
5985 while (last < end
5986 && x < r->right)
5988 x += last->pixel_width;
5989 ++last;
5992 /* Repaint. */
5993 if (last > first)
5994 x_draw_glyphs (w, first_x, row, area,
5995 first - row->glyphs[area],
5996 last - row->glyphs[area],
5997 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5998 NULL, NULL, 0);
6003 /* Redraw the parts of the glyph row ROW on window W intersecting
6004 rectangle R. R is in window-relative coordinates. */
6006 static void
6007 expose_line (w, row, r)
6008 struct window *w;
6009 struct glyph_row *row;
6010 Rect *r;
6012 xassert (row->enabled_p);
6014 if (row->mode_line_p || w->pseudo_window_p)
6015 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6016 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
6017 NULL, NULL, 0);
6018 else
6020 if (row->used[LEFT_MARGIN_AREA])
6021 expose_area (w, row, r, LEFT_MARGIN_AREA);
6022 if (row->used[TEXT_AREA])
6023 expose_area (w, row, r, TEXT_AREA);
6024 if (row->used[RIGHT_MARGIN_AREA])
6025 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6026 x_draw_row_bitmaps (w, row);
6031 /* Return non-zero if W's cursor intersects rectangle R. */
6033 static int
6034 x_phys_cursor_in_rect_p (w, r)
6035 struct window *w;
6036 Rect *r;
6038 Rect cr, result;
6039 struct glyph *cursor_glyph;
6041 cursor_glyph = get_phys_cursor_glyph (w);
6042 if (cursor_glyph)
6044 cr.left = w->phys_cursor.x;
6045 cr.top = w->phys_cursor.y;
6046 cr.right = cr.left + cursor_glyph->pixel_width;
6047 cr.bottom = cr.top + w->phys_cursor_height;
6048 return x_intersect_rectangles (&cr, r, &result);
6050 else
6051 return 0;
6055 /* Redraw a rectangle of window W. R is a rectangle in window
6056 relative coordinates. Call this function with input blocked. */
6058 static void
6059 expose_window (w, r)
6060 struct window *w;
6061 Rect *r;
6063 struct glyph_row *row;
6064 int y;
6065 int yb = window_text_bottom_y (w);
6066 int cursor_cleared_p;
6068 /* If window is not yet fully initialized, do nothing. This can
6069 happen when toolkit scroll bars are used and a window is split.
6070 Reconfiguring the scroll bar will generate an expose for a newly
6071 created window. */
6072 if (w->current_matrix == NULL)
6073 return;
6075 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6076 r->left, r->top, r->right, r->bottom));
6078 /* Convert to window coordinates. */
6079 r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
6080 r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
6081 r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
6082 r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
6084 /* Turn off the cursor. */
6085 if (!w->pseudo_window_p
6086 && x_phys_cursor_in_rect_p (w, r))
6088 x_clear_cursor (w);
6089 cursor_cleared_p = 1;
6091 else
6092 cursor_cleared_p = 0;
6094 /* Find the first row intersecting the rectangle R. */
6095 row = w->current_matrix->rows;
6096 y = 0;
6097 while (row->enabled_p
6098 && y < yb
6099 && y + row->height < r->top)
6101 y += row->height;
6102 ++row;
6105 /* Display the text in the rectangle, one text line at a time. */
6106 while (row->enabled_p
6107 && y < yb
6108 && y < r->bottom)
6110 expose_line (w, row, r);
6111 y += row->height;
6112 ++row;
6115 /* Display the mode line if there is one. */
6116 if (WINDOW_WANTS_MODELINE_P (w)
6117 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6118 row->enabled_p)
6119 && row->y < r->bottom)
6120 expose_line (w, row, r);
6122 if (!w->pseudo_window_p)
6124 /* Draw border between windows. */
6125 x_draw_vertical_border (w);
6127 /* Turn the cursor on again. */
6128 if (cursor_cleared_p)
6129 x_update_window_cursor (w, 1);
6132 /* Display scroll bar for this window. */
6133 if (!NILP (w->vertical_scroll_bar))
6135 ControlHandle ch
6136 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6138 Draw1Control (ch);
6143 /* Determine the intersection of two rectangles R1 and R2. Return
6144 the intersection in *RESULT. Value is non-zero if RESULT is not
6145 empty. */
6147 static int
6148 x_intersect_rectangles (r1, r2, result)
6149 Rect *r1, *r2, *result;
6151 Rect *left, *right;
6152 Rect *upper, *lower;
6153 int intersection_p = 0;
6155 /* Rerrange so that R1 is the left-most rectangle. */
6156 if (r1->left < r2->left)
6157 left = r1, right = r2;
6158 else
6159 left = r2, right = r1;
6161 /* X0 of the intersection is right.x0, if this is inside R1,
6162 otherwise there is no intersection. */
6163 if (right->left <= left->right)
6165 result->left = right->left;
6167 /* The right end of the intersection is the minimum of the
6168 the right ends of left and right. */
6169 result->right = min (left->right, right->right);
6171 /* Same game for Y. */
6172 if (r1->top < r2->top)
6173 upper = r1, lower = r2;
6174 else
6175 upper = r2, lower = r1;
6177 /* The upper end of the intersection is lower.y0, if this is inside
6178 of upper. Otherwise, there is no intersection. */
6179 if (lower->top <= upper->bottom)
6181 result->top = lower->top;
6183 /* The lower end of the intersection is the minimum of the lower
6184 ends of upper and lower. */
6185 result->bottom = min (lower->bottom, upper->bottom);
6186 intersection_p = 1;
6190 return intersection_p;
6197 static void
6198 frame_highlight (f)
6199 struct frame *f;
6201 x_update_cursor (f, 1);
6204 static void
6205 frame_unhighlight (f)
6206 struct frame *f;
6208 x_update_cursor (f, 1);
6211 /* The focus has changed. Update the frames as necessary to reflect
6212 the new situation. Note that we can't change the selected frame
6213 here, because the Lisp code we are interrupting might become confused.
6214 Each event gets marked with the frame in which it occurred, so the
6215 Lisp code can tell when the switch took place by examining the events. */
6217 static void
6218 x_new_focus_frame (dpyinfo, frame)
6219 struct x_display_info *dpyinfo;
6220 struct frame *frame;
6222 struct frame *old_focus = dpyinfo->x_focus_frame;
6224 if (frame != dpyinfo->x_focus_frame)
6226 /* Set this before calling other routines, so that they see
6227 the correct value of x_focus_frame. */
6228 dpyinfo->x_focus_frame = frame;
6230 if (old_focus && old_focus->auto_lower)
6231 x_lower_frame (old_focus);
6233 #if 0
6234 selected_frame = frame;
6235 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6236 selected_frame);
6237 Fselect_window (selected_frame->selected_window);
6238 choose_minibuf_frame ();
6239 #endif /* ! 0 */
6241 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6242 pending_autoraise_frame = dpyinfo->x_focus_frame;
6243 else
6244 pending_autoraise_frame = 0;
6247 x_frame_rehighlight (dpyinfo);
6250 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6252 static void
6253 x_mouse_leave (dpyinfo)
6254 struct x_display_info *dpyinfo;
6256 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6259 /* The focus has changed, or we have redirected a frame's focus to
6260 another frame (this happens when a frame uses a surrogate
6261 mini-buffer frame). Shift the highlight as appropriate.
6263 The FRAME argument doesn't necessarily have anything to do with which
6264 frame is being highlighted or un-highlighted; we only use it to find
6265 the appropriate X display info. */
6267 void
6268 XTframe_rehighlight (frame)
6269 struct frame *frame;
6271 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6274 static void
6275 x_frame_rehighlight (dpyinfo)
6276 struct x_display_info *dpyinfo;
6278 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6280 if (dpyinfo->x_focus_frame)
6282 dpyinfo->x_highlight_frame
6283 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6284 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6285 : dpyinfo->x_focus_frame);
6286 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6288 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6289 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6292 else
6293 dpyinfo->x_highlight_frame = 0;
6295 if (dpyinfo->x_highlight_frame != old_highlight)
6297 if (old_highlight)
6298 frame_unhighlight (old_highlight);
6299 if (dpyinfo->x_highlight_frame)
6300 frame_highlight (dpyinfo->x_highlight_frame);
6306 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6308 #if 0
6309 /* Initialize mode_switch_bit and modifier_meaning. */
6310 static void
6311 x_find_modifier_meanings (dpyinfo)
6312 struct x_display_info *dpyinfo;
6314 int min_code, max_code;
6315 KeySym *syms;
6316 int syms_per_code;
6317 XModifierKeymap *mods;
6319 dpyinfo->meta_mod_mask = 0;
6320 dpyinfo->shift_lock_mask = 0;
6321 dpyinfo->alt_mod_mask = 0;
6322 dpyinfo->super_mod_mask = 0;
6323 dpyinfo->hyper_mod_mask = 0;
6325 #ifdef HAVE_X11R4
6326 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6327 #else
6328 min_code = dpyinfo->display->min_keycode;
6329 max_code = dpyinfo->display->max_keycode;
6330 #endif
6332 syms = XGetKeyboardMapping (dpyinfo->display,
6333 min_code, max_code - min_code + 1,
6334 &syms_per_code);
6335 mods = XGetModifierMapping (dpyinfo->display);
6337 /* Scan the modifier table to see which modifier bits the Meta and
6338 Alt keysyms are on. */
6340 int row, col; /* The row and column in the modifier table. */
6342 for (row = 3; row < 8; row++)
6343 for (col = 0; col < mods->max_keypermod; col++)
6345 KeyCode code
6346 = mods->modifiermap[(row * mods->max_keypermod) + col];
6348 /* Zeroes are used for filler. Skip them. */
6349 if (code == 0)
6350 continue;
6352 /* Are any of this keycode's keysyms a meta key? */
6354 int code_col;
6356 for (code_col = 0; code_col < syms_per_code; code_col++)
6358 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6360 switch (sym)
6362 case XK_Meta_L:
6363 case XK_Meta_R:
6364 dpyinfo->meta_mod_mask |= (1 << row);
6365 break;
6367 case XK_Alt_L:
6368 case XK_Alt_R:
6369 dpyinfo->alt_mod_mask |= (1 << row);
6370 break;
6372 case XK_Hyper_L:
6373 case XK_Hyper_R:
6374 dpyinfo->hyper_mod_mask |= (1 << row);
6375 break;
6377 case XK_Super_L:
6378 case XK_Super_R:
6379 dpyinfo->super_mod_mask |= (1 << row);
6380 break;
6382 case XK_Shift_Lock:
6383 /* Ignore this if it's not on the lock modifier. */
6384 if ((1 << row) == LockMask)
6385 dpyinfo->shift_lock_mask = LockMask;
6386 break;
6393 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6394 if (! dpyinfo->meta_mod_mask)
6396 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6397 dpyinfo->alt_mod_mask = 0;
6400 /* If some keys are both alt and meta,
6401 make them just meta, not alt. */
6402 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6404 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6407 XFree ((char *) syms);
6408 XFreeModifiermap (mods);
6411 #endif
6413 /* Convert between the modifier bits X uses and the modifier bits
6414 Emacs uses. */
6416 static unsigned int
6417 x_mac_to_emacs_modifiers (dpyinfo, state)
6418 struct x_display_info *dpyinfo;
6419 unsigned short state;
6421 return (((state & shiftKey) ? shift_modifier : 0)
6422 | ((state & controlKey) ? ctrl_modifier : 0)
6423 | ((state & cmdKey) ? meta_modifier : 0)
6424 | ((state & optionKey) ? alt_modifier : 0));
6427 #if 0
6428 static unsigned short
6429 x_emacs_to_x_modifiers (dpyinfo, state)
6430 struct x_display_info *dpyinfo;
6431 unsigned int state;
6433 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6434 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6435 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6436 | ((state & shift_modifier) ? ShiftMask : 0)
6437 | ((state & ctrl_modifier) ? ControlMask : 0)
6438 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6440 #endif
6442 /* Convert a keysym to its name. */
6444 char *
6445 x_get_keysym_name (keysym)
6446 int keysym;
6448 char *value;
6450 BLOCK_INPUT;
6451 #if 0
6452 value = XKeysymToString (keysym);
6453 #else
6454 value = 0;
6455 #endif
6456 UNBLOCK_INPUT;
6458 return value;
6463 /* Mouse clicks and mouse movement. Rah. */
6465 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6466 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6467 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6468 not force the value into range. */
6470 void
6471 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6472 FRAME_PTR f;
6473 register int pix_x, pix_y;
6474 register int *x, *y;
6475 Rect *bounds;
6476 int noclip;
6478 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6479 even for negative values. */
6480 if (pix_x < 0)
6481 pix_x -= FONT_WIDTH ((f)->output_data.mac->font) - 1;
6482 if (pix_y < 0)
6483 pix_y -= (f)->output_data.mac->line_height - 1;
6485 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6486 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6488 if (bounds)
6490 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6491 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6492 bounds->right = bounds->left + FONT_WIDTH (f->output_data.mac->font);
6493 bounds->bottom = bounds->top + f->output_data.mac->line_height;
6496 if (!noclip)
6498 if (pix_x < 0)
6499 pix_x = 0;
6500 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6501 pix_x = FRAME_WINDOW_WIDTH (f);
6503 if (pix_y < 0)
6504 pix_y = 0;
6505 else if (pix_y > f->height)
6506 pix_y = f->height;
6509 *x = pix_x;
6510 *y = pix_y;
6514 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6515 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6516 can't tell the positions because W's display is not up to date,
6517 return 0. */
6519 static int
6520 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6521 struct window *w;
6522 int hpos, vpos;
6523 int *frame_x, *frame_y;
6525 int success_p;
6527 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6528 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6530 if (display_completed)
6532 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6533 struct glyph *glyph = row->glyphs[TEXT_AREA];
6534 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6536 *frame_y = row->y;
6537 *frame_x = row->x;
6538 while (glyph < end)
6540 *frame_x += glyph->pixel_width;
6541 ++glyph;
6544 success_p = 1;
6546 else
6548 *frame_y = *frame_x = 0;
6549 success_p = 0;
6552 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6553 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6554 return success_p;
6558 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6560 If the event is a button press, then note that we have grabbed
6561 the mouse. */
6563 static Lisp_Object
6564 construct_mouse_click (result, event, f)
6565 struct input_event *result;
6566 EventRecord *event;
6567 struct frame *f;
6569 Point mouseLoc;
6571 result->kind = mouse_click;
6572 result->code = 0; /* only one mouse button */
6573 result->timestamp = event->when;
6574 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6576 mouseLoc = event->where;
6577 SetPort (FRAME_MAC_WINDOW (f));
6578 GlobalToLocal (&mouseLoc);
6579 XSETINT (result->x, mouseLoc.h);
6580 XSETINT (result->y, mouseLoc.v);
6582 XSETFRAME (result->frame_or_window, f);
6584 result->arg = Qnil;
6585 return Qnil;
6589 /* Function to report a mouse movement to the mainstream Emacs code.
6590 The input handler calls this.
6592 We have received a mouse movement event, which is given in *event.
6593 If the mouse is over a different glyph than it was last time, tell
6594 the mainstream emacs code by setting mouse_moved. If not, ask for
6595 another motion event, so we can check again the next time it moves. */
6597 static Point last_mouse_motion_position;
6598 static Lisp_Object last_mouse_motion_frame;
6600 static void
6601 note_mouse_movement (frame, pos)
6602 FRAME_PTR frame;
6603 Point *pos;
6605 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6606 last_mouse_motion_position = *pos;
6607 XSETFRAME (last_mouse_motion_frame, frame);
6609 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6611 frame->mouse_moved = 1;
6612 last_mouse_scroll_bar = Qnil;
6613 note_mouse_highlight (frame, -1, -1);
6615 /* Has the mouse moved off the glyph it was on at the last sighting? */
6616 else if (pos->h < last_mouse_glyph.left
6617 || pos->h >= last_mouse_glyph.right
6618 || pos->v < last_mouse_glyph.top
6619 || pos->v >= last_mouse_glyph.bottom)
6621 frame->mouse_moved = 1;
6622 last_mouse_scroll_bar = Qnil;
6623 note_mouse_highlight (frame, pos->h, pos->v);
6627 /* This is used for debugging, to turn off note_mouse_highlight. */
6629 int disable_mouse_highlight;
6633 /************************************************************************
6634 Mouse Face
6635 ************************************************************************/
6637 /* Find the glyph under window-relative coordinates X/Y in window W.
6638 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6639 strings. Return in *HPOS and *VPOS the row and column number of
6640 the glyph found. Return in *AREA the glyph area containing X.
6641 Value is a pointer to the glyph found or null if X/Y is not on
6642 text, or we can't tell because W's current matrix is not up to
6643 date. */
6645 static struct glyph *
6646 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6647 struct window *w;
6648 int x, y;
6649 int *hpos, *vpos, *area;
6651 struct glyph *glyph, *end;
6652 struct glyph_row *row = NULL;
6653 int x0, i, left_area_width;
6655 /* Find row containing Y. Give up if some row is not enabled. */
6656 for (i = 0; i < w->current_matrix->nrows; ++i)
6658 row = MATRIX_ROW (w->current_matrix, i);
6659 if (!row->enabled_p)
6660 return NULL;
6661 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6662 break;
6665 *vpos = i;
6666 *hpos = 0;
6668 /* Give up if Y is not in the window. */
6669 if (i == w->current_matrix->nrows)
6670 return NULL;
6672 /* Get the glyph area containing X. */
6673 if (w->pseudo_window_p)
6675 *area = TEXT_AREA;
6676 x0 = 0;
6678 else
6680 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6681 if (x < left_area_width)
6683 *area = LEFT_MARGIN_AREA;
6684 x0 = 0;
6686 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6688 *area = TEXT_AREA;
6689 x0 = row->x + left_area_width;
6691 else
6693 *area = RIGHT_MARGIN_AREA;
6694 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6698 /* Find glyph containing X. */
6699 glyph = row->glyphs[*area];
6700 end = glyph + row->used[*area];
6701 while (glyph < end)
6703 if (x < x0 + glyph->pixel_width)
6705 if (w->pseudo_window_p)
6706 break;
6707 else if (BUFFERP (glyph->object))
6708 break;
6711 x0 += glyph->pixel_width;
6712 ++glyph;
6715 if (glyph == end)
6716 return NULL;
6718 *hpos = glyph - row->glyphs[*area];
6719 return glyph;
6723 /* Convert frame-relative x/y to coordinates relative to window W.
6724 Takes pseudo-windows into account. */
6726 static void
6727 frame_to_window_pixel_xy (w, x, y)
6728 struct window *w;
6729 int *x, *y;
6731 if (w->pseudo_window_p)
6733 /* A pseudo-window is always full-width, and starts at the
6734 left edge of the frame, plus a frame border. */
6735 struct frame *f = XFRAME (w->frame);
6736 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6737 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6739 else
6741 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6742 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6747 /* Take proper action when mouse has moved to the mode or top line of
6748 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6749 mode line. X is relative to the start of the text display area of
6750 W, so the width of bitmap areas and scroll bars must be subtracted
6751 to get a position relative to the start of the mode line. */
6753 static void
6754 note_mode_line_highlight (w, x, mode_line_p)
6755 struct window *w;
6756 int x, mode_line_p;
6758 struct frame *f = XFRAME (w->frame);
6759 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6760 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6761 struct glyph_row *row;
6763 if (mode_line_p)
6764 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6765 else
6766 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6768 if (row->enabled_p)
6770 struct glyph *glyph, *end;
6771 Lisp_Object help, map;
6772 int x0;
6774 /* Find the glyph under X. */
6775 glyph = row->glyphs[TEXT_AREA];
6776 end = glyph + row->used[TEXT_AREA];
6777 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6778 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6779 while (glyph < end
6780 && x >= x0 + glyph->pixel_width)
6782 x0 += glyph->pixel_width;
6783 ++glyph;
6786 if (glyph < end
6787 && STRINGP (glyph->object)
6788 && XSTRING (glyph->object)->intervals
6789 && glyph->charpos >= 0
6790 && glyph->charpos < XSTRING (glyph->object)->size)
6792 /* If we're on a string with `help-echo' text property,
6793 arrange for the help to be displayed. This is done by
6794 setting the global variable help_echo to the help string. */
6795 help = Fget_text_property (make_number (glyph->charpos),
6796 Qhelp_echo, glyph->object);
6797 if (!NILP (help))
6799 help_echo = help;
6800 XSETWINDOW (help_echo_window, w);
6801 help_echo_object = glyph->object;
6802 help_echo_pos = glyph->charpos;
6805 /* Change the mouse pointer according to what is under X/Y. */
6806 map = Fget_text_property (make_number (glyph->charpos),
6807 Qlocal_map, glyph->object);
6808 if (!NILP (Fkeymapp (map)))
6809 cursor = f->output_data.mac->nontext_cursor;
6810 else
6812 map = Fget_text_property (make_number (glyph->charpos),
6813 Qkeymap, glyph->object);
6814 if (!NILP (Fkeymapp (map)))
6815 cursor = f->output_data.mac->nontext_cursor;
6820 #if 0 /* MAC_TODO: mouse cursor */
6821 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6822 #endif
6826 /* Take proper action when the mouse has moved to position X, Y on
6827 frame F as regards highlighting characters that have mouse-face
6828 properties. Also de-highlighting chars where the mouse was before.
6829 X and Y can be negative or out of range. */
6831 static void
6832 note_mouse_highlight (f, x, y)
6833 struct frame *f;
6834 int x, y;
6836 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6837 int portion;
6838 Lisp_Object window;
6839 struct window *w;
6841 /* When a menu is active, don't highlight because this looks odd. */
6842 #ifdef USE_X_TOOLKIT
6843 if (popup_activated ())
6844 return;
6845 #endif
6847 if (disable_mouse_highlight
6848 || !f->glyphs_initialized_p)
6849 return;
6851 dpyinfo->mouse_face_mouse_x = x;
6852 dpyinfo->mouse_face_mouse_y = y;
6853 dpyinfo->mouse_face_mouse_frame = f;
6855 if (dpyinfo->mouse_face_defer)
6856 return;
6858 if (gc_in_progress)
6860 dpyinfo->mouse_face_deferred_gc = 1;
6861 return;
6864 /* Which window is that in? */
6865 window = window_from_coordinates (f, x, y, &portion, 1);
6867 /* If we were displaying active text in another window, clear that. */
6868 if (! EQ (window, dpyinfo->mouse_face_window))
6869 clear_mouse_face (dpyinfo);
6871 /* Not on a window -> return. */
6872 if (!WINDOWP (window))
6873 return;
6875 /* Convert to window-relative pixel coordinates. */
6876 w = XWINDOW (window);
6877 frame_to_window_pixel_xy (w, &x, &y);
6879 /* Handle tool-bar window differently since it doesn't display a
6880 buffer. */
6881 if (EQ (window, f->tool_bar_window))
6883 note_tool_bar_highlight (f, x, y);
6884 return;
6887 if (portion == 1 || portion == 3)
6889 /* Mouse is on the mode or top line. */
6890 note_mode_line_highlight (w, x, portion == 1);
6891 return;
6893 #if 0 /* MAC_TODO: mouse cursor */
6894 else
6895 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6896 f->output_data.x->text_cursor);
6897 #endif
6899 /* Are we in a window whose display is up to date?
6900 And verify the buffer's text has not changed. */
6901 if (/* Within text portion of the window. */
6902 portion == 0
6903 && EQ (w->window_end_valid, w->buffer)
6904 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6905 && (XFASTINT (w->last_overlay_modified)
6906 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6908 int hpos, vpos, pos, i, area;
6909 struct glyph *glyph;
6911 /* Find the glyph under X/Y. */
6912 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6914 /* Clear mouse face if X/Y not over text. */
6915 if (glyph == NULL
6916 || area != TEXT_AREA
6917 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6919 clear_mouse_face (dpyinfo);
6920 return;
6923 pos = glyph->charpos;
6924 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6926 /* Check for mouse-face and help-echo. */
6928 Lisp_Object mouse_face, overlay, position;
6929 Lisp_Object *overlay_vec;
6930 int len, noverlays;
6931 struct buffer *obuf;
6932 int obegv, ozv;
6934 /* If we get an out-of-range value, return now; avoid an error. */
6935 if (pos > BUF_Z (XBUFFER (w->buffer)))
6936 return;
6938 /* Make the window's buffer temporarily current for
6939 overlays_at and compute_char_face. */
6940 obuf = current_buffer;
6941 current_buffer = XBUFFER (w->buffer);
6942 obegv = BEGV;
6943 ozv = ZV;
6944 BEGV = BEG;
6945 ZV = Z;
6947 /* Is this char mouse-active or does it have help-echo? */
6948 XSETINT (position, pos);
6950 /* Put all the overlays we want in a vector in overlay_vec.
6951 Store the length in len. If there are more than 10, make
6952 enough space for all, and try again. */
6953 len = 10;
6954 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6955 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6956 if (noverlays > len)
6958 len = noverlays;
6959 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6960 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6963 /* Sort overlays into increasing priority order. */
6964 noverlays = sort_overlays (overlay_vec, noverlays, w);
6966 /* Check mouse-face highlighting. */
6967 if (! (EQ (window, dpyinfo->mouse_face_window)
6968 && vpos >= dpyinfo->mouse_face_beg_row
6969 && vpos <= dpyinfo->mouse_face_end_row
6970 && (vpos > dpyinfo->mouse_face_beg_row
6971 || hpos >= dpyinfo->mouse_face_beg_col)
6972 && (vpos < dpyinfo->mouse_face_end_row
6973 || hpos < dpyinfo->mouse_face_end_col
6974 || dpyinfo->mouse_face_past_end)))
6976 /* Clear the display of the old active region, if any. */
6977 clear_mouse_face (dpyinfo);
6979 /* Find the highest priority overlay that has a mouse-face prop. */
6980 overlay = Qnil;
6981 for (i = noverlays - 1; i >= 0; --i)
6983 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6984 if (!NILP (mouse_face))
6986 overlay = overlay_vec[i];
6987 break;
6991 /* If no overlay applies, get a text property. */
6992 if (NILP (overlay))
6993 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6995 /* Handle the overlay case. */
6996 if (! NILP (overlay))
6998 /* Find the range of text around this char that
6999 should be active. */
7000 Lisp_Object before, after;
7001 int ignore;
7003 before = Foverlay_start (overlay);
7004 after = Foverlay_end (overlay);
7005 /* Record this as the current active region. */
7006 fast_find_position (w, XFASTINT (before),
7007 &dpyinfo->mouse_face_beg_col,
7008 &dpyinfo->mouse_face_beg_row,
7009 &dpyinfo->mouse_face_beg_x,
7010 &dpyinfo->mouse_face_beg_y);
7011 dpyinfo->mouse_face_past_end
7012 = !fast_find_position (w, XFASTINT (after),
7013 &dpyinfo->mouse_face_end_col,
7014 &dpyinfo->mouse_face_end_row,
7015 &dpyinfo->mouse_face_end_x,
7016 &dpyinfo->mouse_face_end_y);
7017 dpyinfo->mouse_face_window = window;
7018 dpyinfo->mouse_face_face_id
7019 = face_at_buffer_position (w, pos, 0, 0,
7020 &ignore, pos + 1, 1);
7022 /* Display it as active. */
7023 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7025 /* Handle the text property case. */
7026 else if (! NILP (mouse_face))
7028 /* Find the range of text around this char that
7029 should be active. */
7030 Lisp_Object before, after, beginning, end;
7031 int ignore;
7033 beginning = Fmarker_position (w->start);
7034 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
7035 - XFASTINT (w->window_end_pos)));
7036 before
7037 = Fprevious_single_property_change (make_number (pos + 1),
7038 Qmouse_face,
7039 w->buffer, beginning);
7040 after
7041 = Fnext_single_property_change (position, Qmouse_face,
7042 w->buffer, end);
7043 /* Record this as the current active region. */
7044 fast_find_position (w, XFASTINT (before),
7045 &dpyinfo->mouse_face_beg_col,
7046 &dpyinfo->mouse_face_beg_row,
7047 &dpyinfo->mouse_face_beg_x,
7048 &dpyinfo->mouse_face_beg_y);
7049 dpyinfo->mouse_face_past_end
7050 = !fast_find_position (w, XFASTINT (after),
7051 &dpyinfo->mouse_face_end_col,
7052 &dpyinfo->mouse_face_end_row,
7053 &dpyinfo->mouse_face_end_x,
7054 &dpyinfo->mouse_face_end_y);
7055 dpyinfo->mouse_face_window = window;
7056 dpyinfo->mouse_face_face_id
7057 = face_at_buffer_position (w, pos, 0, 0,
7058 &ignore, pos + 1, 1);
7060 /* Display it as active. */
7061 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7065 /* Look for a `help-echo' property. */
7067 Lisp_Object help, overlay;
7069 /* Check overlays first. */
7070 help = Qnil;
7071 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7073 overlay = overlay_vec[i];
7074 help = Foverlay_get (overlay, Qhelp_echo);
7077 if (!NILP (help))
7079 help_echo = help;
7080 help_echo_window = window;
7081 help_echo_object = overlay;
7082 help_echo_pos = pos;
7084 else
7086 /* Try text properties. */
7087 if ((STRINGP (glyph->object)
7088 && glyph->charpos >= 0
7089 && glyph->charpos < XSTRING (glyph->object)->size)
7090 || (BUFFERP (glyph->object)
7091 && glyph->charpos >= BEGV
7092 && glyph->charpos < ZV))
7093 help = Fget_text_property (make_number (glyph->charpos),
7094 Qhelp_echo, glyph->object);
7096 if (!NILP (help))
7098 help_echo = help;
7099 help_echo_window = window;
7100 help_echo_object = glyph->object;
7101 help_echo_pos = glyph->charpos;
7106 BEGV = obegv;
7107 ZV = ozv;
7108 current_buffer = obuf;
7113 static void
7114 redo_mouse_highlight ()
7116 if (!NILP (last_mouse_motion_frame)
7117 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7118 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7119 last_mouse_motion_position.h,
7120 last_mouse_motion_position.v);
7125 /***********************************************************************
7126 Tool-bars
7127 ***********************************************************************/
7129 static int x_tool_bar_item P_ ((struct frame *, int, int,
7130 struct glyph **, int *, int *, int *));
7132 /* Tool-bar item index of the item on which a mouse button was pressed
7133 or -1. */
7135 static int last_tool_bar_item;
7138 /* Get information about the tool-bar item at position X/Y on frame F.
7139 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7140 the current matrix of the tool-bar window of F, or NULL if not
7141 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7142 item in F->current_tool_bar_items. Value is
7144 -1 if X/Y is not on a tool-bar item
7145 0 if X/Y is on the same item that was highlighted before.
7146 1 otherwise. */
7148 static int
7149 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7150 struct frame *f;
7151 int x, y;
7152 struct glyph **glyph;
7153 int *hpos, *vpos, *prop_idx;
7155 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7156 struct window *w = XWINDOW (f->tool_bar_window);
7157 int area;
7159 /* Find the glyph under X/Y. */
7160 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
7161 if (*glyph == NULL)
7162 return -1;
7164 /* Get the start of this tool-bar item's properties in
7165 f->current_tool_bar_items. */
7166 if (!tool_bar_item_info (f, *glyph, prop_idx))
7167 return -1;
7169 /* Is mouse on the highlighted item? */
7170 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7171 && *vpos >= dpyinfo->mouse_face_beg_row
7172 && *vpos <= dpyinfo->mouse_face_end_row
7173 && (*vpos > dpyinfo->mouse_face_beg_row
7174 || *hpos >= dpyinfo->mouse_face_beg_col)
7175 && (*vpos < dpyinfo->mouse_face_end_row
7176 || *hpos < dpyinfo->mouse_face_end_col
7177 || dpyinfo->mouse_face_past_end))
7178 return 0;
7180 return 1;
7184 /* Handle mouse button event on the tool-bar of frame F, at
7185 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7186 or ButtonRelase. */
7188 static void
7189 x_handle_tool_bar_click (f, button_event)
7190 struct frame *f;
7191 EventRecord *button_event;
7193 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7194 struct window *w = XWINDOW (f->tool_bar_window);
7195 int hpos, vpos, prop_idx;
7196 struct glyph *glyph;
7197 Lisp_Object enabled_p;
7198 int x = button_event->where.h;
7199 int y = button_event->where.v;
7201 /* If not on the highlighted tool-bar item, return. */
7202 frame_to_window_pixel_xy (w, &x, &y);
7203 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7204 return;
7206 /* If item is disabled, do nothing. */
7207 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7208 if (NILP (enabled_p))
7209 return;
7211 if (button_event->what == mouseDown)
7213 /* Show item in pressed state. */
7214 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7215 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7216 last_tool_bar_item = prop_idx;
7218 else
7220 Lisp_Object key, frame;
7221 struct input_event event;
7223 /* Show item in released state. */
7224 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7225 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7227 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7229 XSETFRAME (frame, f);
7230 event.kind = TOOL_BAR_EVENT;
7231 event.frame_or_window = frame;
7232 event.arg = frame;
7233 kbd_buffer_store_event (&event);
7235 event.kind = TOOL_BAR_EVENT;
7236 event.frame_or_window = frame;
7237 event.arg = key;
7238 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7239 button_event->modifiers);
7240 kbd_buffer_store_event (&event);
7241 last_tool_bar_item = -1;
7246 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7247 tool-bar window-relative coordinates X/Y. Called from
7248 note_mouse_highlight. */
7250 static void
7251 note_tool_bar_highlight (f, x, y)
7252 struct frame *f;
7253 int x, y;
7255 Lisp_Object window = f->tool_bar_window;
7256 struct window *w = XWINDOW (window);
7257 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7258 int hpos, vpos;
7259 struct glyph *glyph;
7260 struct glyph_row *row;
7261 int i;
7262 Lisp_Object enabled_p;
7263 int prop_idx;
7264 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7265 int mouse_down_p, rc;
7267 /* Function note_mouse_highlight is called with negative x(y
7268 values when mouse moves outside of the frame. */
7269 if (x <= 0 || y <= 0)
7271 clear_mouse_face (dpyinfo);
7272 return;
7275 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7276 if (rc < 0)
7278 /* Not on tool-bar item. */
7279 clear_mouse_face (dpyinfo);
7280 return;
7282 else if (rc == 0)
7283 /* On same tool-bar item as before. */
7284 goto set_help_echo;
7286 clear_mouse_face (dpyinfo);
7288 /* Mouse is down, but on different tool-bar item? */
7289 mouse_down_p = (dpyinfo->grabbed
7290 && f == last_mouse_frame
7291 && FRAME_LIVE_P (f));
7292 if (mouse_down_p
7293 && last_tool_bar_item != prop_idx)
7294 return;
7296 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7297 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7299 /* If tool-bar item is not enabled, don't highlight it. */
7300 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7301 if (!NILP (enabled_p))
7303 /* Compute the x-position of the glyph. In front and past the
7304 image is a space. We include this is the highlighted area. */
7305 row = MATRIX_ROW (w->current_matrix, vpos);
7306 for (i = x = 0; i < hpos; ++i)
7307 x += row->glyphs[TEXT_AREA][i].pixel_width;
7309 /* Record this as the current active region. */
7310 dpyinfo->mouse_face_beg_col = hpos;
7311 dpyinfo->mouse_face_beg_row = vpos;
7312 dpyinfo->mouse_face_beg_x = x;
7313 dpyinfo->mouse_face_beg_y = row->y;
7314 dpyinfo->mouse_face_past_end = 0;
7316 dpyinfo->mouse_face_end_col = hpos + 1;
7317 dpyinfo->mouse_face_end_row = vpos;
7318 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7319 dpyinfo->mouse_face_end_y = row->y;
7320 dpyinfo->mouse_face_window = window;
7321 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7323 /* Display it as active. */
7324 show_mouse_face (dpyinfo, draw);
7325 dpyinfo->mouse_face_image_state = draw;
7328 set_help_echo:
7330 /* Set help_echo to a help string.to display for this tool-bar item.
7331 XTread_socket does the rest. */
7332 help_echo_object = help_echo_window = Qnil;
7333 help_echo_pos = -1;
7334 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7335 if (NILP (help_echo))
7336 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7341 /* Find the glyph matrix position of buffer position POS in window W.
7342 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7343 current glyphs must be up to date. If POS is above window start
7344 return (0, 0, 0, 0). If POS is after end of W, return end of
7345 last line in W. */
7347 static int
7348 fast_find_position (w, pos, hpos, vpos, x, y)
7349 struct window *w;
7350 int pos;
7351 int *hpos, *vpos, *x, *y;
7353 int i;
7354 int lastcol;
7355 int maybe_next_line_p = 0;
7356 int line_start_position;
7357 int yb = window_text_bottom_y (w);
7358 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
7359 struct glyph_row *best_row = row;
7360 int row_vpos = 0, best_row_vpos = 0;
7361 int current_x;
7363 while (row->y < yb)
7365 if (row->used[TEXT_AREA])
7366 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7367 else
7368 line_start_position = 0;
7370 if (line_start_position > pos)
7371 break;
7372 /* If the position sought is the end of the buffer,
7373 don't include the blank lines at the bottom of the window. */
7374 else if (line_start_position == pos
7375 && pos == BUF_ZV (XBUFFER (w->buffer)))
7377 maybe_next_line_p = 1;
7378 break;
7380 else if (line_start_position > 0)
7382 best_row = row;
7383 best_row_vpos = row_vpos;
7386 if (row->y + row->height >= yb)
7387 break;
7389 ++row;
7390 ++row_vpos;
7393 /* Find the right column within BEST_ROW. */
7394 lastcol = 0;
7395 current_x = best_row->x;
7396 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7398 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7399 int charpos;
7401 charpos = glyph->charpos;
7402 if (charpos == pos)
7404 *hpos = i;
7405 *vpos = best_row_vpos;
7406 *x = current_x;
7407 *y = best_row->y;
7408 return 1;
7410 else if (charpos > pos)
7411 break;
7412 else if (charpos > 0)
7413 lastcol = i;
7415 current_x += glyph->pixel_width;
7418 /* If we're looking for the end of the buffer,
7419 and we didn't find it in the line we scanned,
7420 use the start of the following line. */
7421 if (maybe_next_line_p)
7423 ++best_row;
7424 ++best_row_vpos;
7425 lastcol = 0;
7426 current_x = best_row->x;
7429 *vpos = best_row_vpos;
7430 *hpos = lastcol + 1;
7431 *x = current_x;
7432 *y = best_row->y;
7433 return 0;
7437 /* Display the active region described by mouse_face_*
7438 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7440 static void
7441 show_mouse_face (dpyinfo, draw)
7442 struct mac_display_info *dpyinfo;
7443 enum draw_glyphs_face draw;
7445 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7446 struct frame *f = XFRAME (WINDOW_FRAME (w));
7447 int i;
7448 int cursor_off_p = 0;
7449 struct cursor_pos saved_cursor;
7451 saved_cursor = output_cursor;
7453 /* If window is in the process of being destroyed, don't bother
7454 to do anything. */
7455 if (w->current_matrix == NULL)
7456 goto set_x_cursor;
7458 /* Recognize when we are called to operate on rows that don't exist
7459 anymore. This can happen when a window is split. */
7460 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7461 goto set_x_cursor;
7463 set_output_cursor (&w->phys_cursor);
7465 /* Note that mouse_face_beg_row etc. are window relative. */
7466 for (i = dpyinfo->mouse_face_beg_row;
7467 i <= dpyinfo->mouse_face_end_row;
7468 i++)
7470 int start_hpos, end_hpos, start_x;
7471 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7473 /* Don't do anything if row doesn't have valid contents. */
7474 if (!row->enabled_p)
7475 continue;
7477 /* For all but the first row, the highlight starts at column 0. */
7478 if (i == dpyinfo->mouse_face_beg_row)
7480 start_hpos = dpyinfo->mouse_face_beg_col;
7481 start_x = dpyinfo->mouse_face_beg_x;
7483 else
7485 start_hpos = 0;
7486 start_x = 0;
7489 if (i == dpyinfo->mouse_face_end_row)
7490 end_hpos = dpyinfo->mouse_face_end_col;
7491 else
7492 end_hpos = row->used[TEXT_AREA];
7494 /* If the cursor's in the text we are about to rewrite, turn the
7495 cursor off. */
7496 if (!w->pseudo_window_p
7497 && i == output_cursor.vpos
7498 && output_cursor.hpos >= start_hpos - 1
7499 && output_cursor.hpos <= end_hpos)
7501 x_update_window_cursor (w, 0);
7502 cursor_off_p = 1;
7505 if (end_hpos > start_hpos)
7507 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7508 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7509 start_hpos, end_hpos, draw, NULL, NULL, 0);
7513 /* If we turned the cursor off, turn it back on. */
7514 if (cursor_off_p)
7515 x_display_cursor (w, 1,
7516 output_cursor.hpos, output_cursor.vpos,
7517 output_cursor.x, output_cursor.y);
7519 output_cursor = saved_cursor;
7521 set_x_cursor:
7522 #if 0 /* MAC_TODO: mouse cursor */
7523 /* Change the mouse cursor. */
7524 if (draw == DRAW_NORMAL_TEXT)
7525 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7526 f->output_data.x->text_cursor);
7527 else if (draw == DRAW_MOUSE_FACE)
7528 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7529 f->output_data.x->cross_cursor);
7530 else
7531 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7532 f->output_data.x->nontext_cursor);
7533 #endif
7537 /* Clear out the mouse-highlighted active region.
7538 Redraw it un-highlighted first. */
7540 void
7541 clear_mouse_face (dpyinfo)
7542 struct mac_display_info *dpyinfo;
7544 if (tip_frame)
7545 return;
7547 if (! NILP (dpyinfo->mouse_face_window))
7548 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7550 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7551 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7552 dpyinfo->mouse_face_window = Qnil;
7556 /* Clear any mouse-face on window W. This function is part of the
7557 redisplay interface, and is called from try_window_id and similar
7558 functions to ensure the mouse-highlight is off. */
7560 void
7561 x_clear_mouse_face (w)
7562 struct window *w;
7564 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
7565 Lisp_Object window;
7567 XSETWINDOW (window, w);
7568 if (EQ (window, dpyinfo->mouse_face_window))
7569 clear_mouse_face (dpyinfo);
7573 /* Just discard the mouse face information for frame F, if any.
7574 This is used when the size of F is changed. */
7576 static void
7577 cancel_mouse_face (f)
7578 FRAME_PTR f;
7580 Lisp_Object window;
7581 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7583 window = dpyinfo->mouse_face_window;
7584 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7586 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7587 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7588 dpyinfo->mouse_face_window = Qnil;
7592 static struct scroll_bar *x_window_to_scroll_bar ();
7593 static void x_scroll_bar_report_motion ();
7595 /* Return the current position of the mouse.
7596 *fp should be a frame which indicates which display to ask about.
7598 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7599 and *part to the frame, window, and scroll bar part that the mouse
7600 is over. Set *x and *y to the portion and whole of the mouse's
7601 position on the scroll bar.
7603 If the mouse movement started elsewhere, set *fp to the frame the
7604 mouse is on, *bar_window to nil, and *x and *y to the character cell
7605 the mouse is over.
7607 Set *time to the server time-stamp for the time at which the mouse
7608 was at this position.
7610 Don't store anything if we don't have a valid set of values to report.
7612 This clears the mouse_moved flag, so we can wait for the next mouse
7613 movement. */
7615 void
7616 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7617 FRAME_PTR *fp;
7618 int insist;
7619 Lisp_Object *bar_window;
7620 enum scroll_bar_part *part;
7621 Lisp_Object *x, *y;
7622 unsigned long *time;
7624 Point mouse_pos;
7625 int ignore1, ignore2;
7626 WindowPtr wp = FrontWindow ();
7627 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
7628 Lisp_Object frame, tail;
7630 BLOCK_INPUT;
7632 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7633 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7634 else
7636 /* Clear the mouse-moved flag for every frame on this display. */
7637 FOR_EACH_FRAME (tail, frame)
7638 XFRAME (frame)->mouse_moved = 0;
7640 last_mouse_scroll_bar = Qnil;
7642 SetPort (wp);
7643 GetMouse (&mouse_pos);
7645 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
7646 &last_mouse_glyph, insist);
7648 *bar_window = Qnil;
7649 *part = scroll_bar_handle;
7650 *fp = f;
7651 XSETINT (*x, mouse_pos.h);
7652 XSETINT (*y, mouse_pos.v);
7653 *time = last_mouse_movement_time;
7656 UNBLOCK_INPUT;
7660 /************************************************************************
7661 Scroll bars, general
7662 ************************************************************************/
7664 /* Create a scroll bar and return the scroll bar vector for it. W is
7665 the Emacs window on which to create the scroll bar. TOP, LEFT,
7666 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7667 scroll bar. */
7669 static struct scroll_bar *
7670 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
7671 struct window *w;
7672 int top, left, width, height, disp_top, disp_height;
7674 struct frame *f = XFRAME (w->frame);
7675 struct scroll_bar *bar
7676 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
7677 Rect r;
7678 ControlHandle ch;
7680 BLOCK_INPUT;
7682 r.left = left;
7683 r.top = disp_top;
7684 r.right = left + width;
7685 r.bottom = disp_top + disp_height;
7687 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
7688 0L);
7689 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
7690 SetControlReference (ch, (long) bar);
7692 XSETWINDOW (bar->window, w);
7693 XSETINT (bar->top, top);
7694 XSETINT (bar->left, left);
7695 XSETINT (bar->width, width);
7696 XSETINT (bar->height, height);
7697 XSETINT (bar->start, 0);
7698 XSETINT (bar->end, 0);
7699 bar->dragging = Qnil;
7701 /* Add bar to its frame's list of scroll bars. */
7702 bar->next = FRAME_SCROLL_BARS (f);
7703 bar->prev = Qnil;
7704 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7705 if (!NILP (bar->next))
7706 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7708 UNBLOCK_INPUT;
7709 return bar;
7713 /* Draw BAR's handle in the proper position.
7715 If the handle is already drawn from START to END, don't bother
7716 redrawing it, unless REBUILD is non-zero; in that case, always
7717 redraw it. (REBUILD is handy for drawing the handle after expose
7718 events.)
7720 Normally, we want to constrain the start and end of the handle to
7721 fit inside its rectangle, but if the user is dragging the scroll
7722 bar handle, we want to let them drag it down all the way, so that
7723 the bar's top is as far down as it goes; otherwise, there's no way
7724 to move to the very end of the buffer. */
7726 static void
7727 x_scroll_bar_set_handle (bar, start, end, rebuild)
7728 struct scroll_bar *bar;
7729 int start, end;
7730 int rebuild;
7732 int dragging = ! NILP (bar->dragging);
7733 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
7734 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7736 /* If the display is already accurate, do nothing. */
7737 if (! rebuild
7738 && start == XINT (bar->start)
7739 && end == XINT (bar->end))
7740 return;
7742 BLOCK_INPUT;
7745 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
7746 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
7747 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7749 /* Make sure the values are reasonable, and try to preserve
7750 the distance between start and end. */
7752 int length = end - start;
7754 if (start < 0)
7755 start = 0;
7756 else if (start > top_range)
7757 start = top_range;
7758 end = start + length;
7760 if (end < start)
7761 end = start;
7762 else if (end > top_range && ! dragging)
7763 end = top_range;
7766 /* Store the adjusted setting in the scroll bar. */
7767 XSETINT (bar->start, start);
7768 XSETINT (bar->end, end);
7770 /* Clip the end position, just for display. */
7771 if (end > top_range)
7772 end = top_range;
7774 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
7775 below top positions, to make sure the handle is always at least
7776 that many pixels tall. */
7777 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
7779 SetControlMinimum (ch, 0);
7780 /* Don't inadvertently activate deactivated scroll bars */
7781 if (GetControlMaximum (ch) != -1)
7782 SetControlMaximum (ch,
7783 VERTICAL_SCROLL_BAR_TOP_RANGE (f,
7784 XINT (bar->height))
7785 - 1);
7786 SetControlValue (ch, start);
7787 #if 0 /* MAC_TODO: detect Appearance Manager 1.1 before use. */
7788 SetControlViewSize (ch, end);
7789 #endif
7792 UNBLOCK_INPUT;
7796 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7797 nil. */
7799 static void
7800 x_scroll_bar_remove (bar)
7801 struct scroll_bar *bar;
7803 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7805 BLOCK_INPUT;
7807 /* Destroy the Mac scroll bar control */
7808 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
7810 /* Disassociate this scroll bar from its window. */
7811 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
7813 UNBLOCK_INPUT;
7817 /* Set the handle of the vertical scroll bar for WINDOW to indicate
7818 that we are displaying PORTION characters out of a total of WHOLE
7819 characters, starting at POSITION. If WINDOW has no scroll bar,
7820 create one. */
7822 static void
7823 XTset_vertical_scroll_bar (w, portion, whole, position)
7824 struct window *w;
7825 int portion, whole, position;
7827 struct frame *f = XFRAME (w->frame);
7828 struct scroll_bar *bar;
7829 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
7830 int window_x, window_y, window_width, window_height;
7832 /* Get window dimensions. */
7833 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7834 top = window_y;
7835 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
7836 height = window_height;
7838 /* Compute the left edge of the scroll bar area. */
7839 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7840 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
7841 else
7842 left = XFASTINT (w->left);
7843 left *= CANON_X_UNIT (f);
7844 left += FRAME_INTERNAL_BORDER_WIDTH (f);
7846 /* Compute the width of the scroll bar which might be less than
7847 the width of the area reserved for the scroll bar. */
7848 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
7849 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
7850 else
7851 sb_width = width;
7853 /* Compute the left edge of the scroll bar. */
7854 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7855 sb_left = left + width - sb_width - (width - sb_width) / 2;
7856 else
7857 sb_left = left + (width - sb_width) / 2;
7859 /* Adjustments according to Inside Macintosh to make it look nice */
7860 disp_top = top;
7861 disp_height = height;
7862 if (disp_top == 0)
7864 disp_top = -1;
7865 disp_height++;
7867 else if (disp_top == PIXEL_HEIGHT (f) - 16)
7869 disp_top++;
7870 disp_height--;
7873 if (sb_left + sb_width == PIXEL_WIDTH (f))
7874 sb_left++;
7876 /* Does the scroll bar exist yet? */
7877 if (NILP (w->vertical_scroll_bar))
7879 BLOCK_INPUT;
7880 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
7881 left, top, width, height, 0);
7882 UNBLOCK_INPUT;
7883 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
7884 disp_height);
7885 XSETVECTOR (w->vertical_scroll_bar, bar);
7887 else
7889 /* It may just need to be moved and resized. */
7890 ControlHandle ch;
7892 bar = XSCROLL_BAR (w->vertical_scroll_bar);
7893 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
7895 BLOCK_INPUT;
7897 /* If already correctly positioned, do nothing. */
7898 if (XINT (bar->left) == sb_left
7899 && XINT (bar->top) == top
7900 && XINT (bar->width) == sb_width
7901 && XINT (bar->height) == height)
7902 Draw1Control (ch);
7903 else
7905 if (sb_left + sb_width >= PIXEL_WIDTH (f))
7906 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
7907 sb_left - 1, top, 1, height, 0);
7909 HideControl (ch);
7910 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
7911 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7912 disp_height);
7913 ShowControl (ch);
7915 /* Remember new settings. */
7916 XSETINT (bar->left, sb_left);
7917 XSETINT (bar->top, top);
7918 XSETINT (bar->width, sb_width);
7919 XSETINT (bar->height, height);
7922 UNBLOCK_INPUT;
7925 /* Set the scroll bar's current state, unless we're currently being
7926 dragged. */
7927 if (NILP (bar->dragging))
7929 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
7931 if (whole == 0)
7932 x_scroll_bar_set_handle (bar, 0, top_range, 0);
7933 else
7935 int start = ((double) position * top_range) / whole;
7936 int end = ((double) (position + portion) * top_range) / whole;
7937 x_scroll_bar_set_handle (bar, start, end, 0);
7943 /* The following three hooks are used when we're doing a thorough
7944 redisplay of the frame. We don't explicitly know which scroll bars
7945 are going to be deleted, because keeping track of when windows go
7946 away is a real pain - "Can you say set-window-configuration, boys
7947 and girls?" Instead, we just assert at the beginning of redisplay
7948 that *all* scroll bars are to be removed, and then save a scroll bar
7949 from the fiery pit when we actually redisplay its window. */
7951 /* Arrange for all scroll bars on FRAME to be removed at the next call
7952 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
7953 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
7955 static void
7956 XTcondemn_scroll_bars (frame)
7957 FRAME_PTR frame;
7959 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
7960 while (! NILP (FRAME_SCROLL_BARS (frame)))
7962 Lisp_Object bar;
7963 bar = FRAME_SCROLL_BARS (frame);
7964 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
7965 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
7966 XSCROLL_BAR (bar)->prev = Qnil;
7967 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
7968 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
7969 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
7973 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
7974 Note that WINDOW isn't necessarily condemned at all. */
7975 static void
7976 XTredeem_scroll_bar (window)
7977 struct window *window;
7979 struct scroll_bar *bar;
7981 /* We can't redeem this window's scroll bar if it doesn't have one. */
7982 if (NILP (window->vertical_scroll_bar))
7983 abort ();
7985 bar = XSCROLL_BAR (window->vertical_scroll_bar);
7987 /* Unlink it from the condemned list. */
7989 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
7991 if (NILP (bar->prev))
7993 /* If the prev pointer is nil, it must be the first in one of
7994 the lists. */
7995 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
7996 /* It's not condemned. Everything's fine. */
7997 return;
7998 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7999 window->vertical_scroll_bar))
8000 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8001 else
8002 /* If its prev pointer is nil, it must be at the front of
8003 one or the other! */
8004 abort ();
8006 else
8007 XSCROLL_BAR (bar->prev)->next = bar->next;
8009 if (! NILP (bar->next))
8010 XSCROLL_BAR (bar->next)->prev = bar->prev;
8012 bar->next = FRAME_SCROLL_BARS (f);
8013 bar->prev = Qnil;
8014 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8015 if (! NILP (bar->next))
8016 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8020 /* Remove all scroll bars on FRAME that haven't been saved since the
8021 last call to `*condemn_scroll_bars_hook'. */
8023 static void
8024 XTjudge_scroll_bars (f)
8025 FRAME_PTR f;
8027 Lisp_Object bar, next;
8029 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8031 /* Clear out the condemned list now so we won't try to process any
8032 more events on the hapless scroll bars. */
8033 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8035 for (; ! NILP (bar); bar = next)
8037 struct scroll_bar *b = XSCROLL_BAR (bar);
8039 x_scroll_bar_remove (b);
8041 next = b->next;
8042 b->next = b->prev = Qnil;
8045 /* Now there should be no references to the condemned scroll bars,
8046 and they should get garbage-collected. */
8050 static void
8051 activate_scroll_bars (frame)
8052 FRAME_PTR frame;
8054 Lisp_Object bar;
8055 ControlHandle ch;
8057 bar = FRAME_SCROLL_BARS (frame);
8058 while (! NILP (bar))
8060 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8061 SetControlMaximum (ch,
8062 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8063 XINT (XSCROLL_BAR (bar)
8064 ->height)) - 1);
8066 bar = XSCROLL_BAR (bar)->next;
8071 static void
8072 deactivate_scroll_bars (frame)
8073 FRAME_PTR frame;
8075 Lisp_Object bar;
8076 ControlHandle ch;
8078 bar = FRAME_SCROLL_BARS (frame);
8079 while (! NILP (bar))
8081 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8082 SetControlMaximum (ch, XINT (-1));
8084 bar = XSCROLL_BAR (bar)->next;
8088 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8089 is set to something other than no_event, it is enqueued.
8091 This may be called from a signal handler, so we have to ignore GC
8092 mark bits. */
8094 static void
8095 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8096 struct scroll_bar *bar;
8097 int part_code;
8098 EventRecord *er;
8099 struct input_event *bufp;
8101 if (! GC_WINDOWP (bar->window))
8102 abort ();
8104 bufp->kind = scroll_bar_click;
8105 bufp->frame_or_window = bar->window;
8106 bufp->arg = Qnil;
8108 bar->dragging = Qnil;
8110 switch (part_code)
8112 case kControlUpButtonPart:
8113 bufp->part = scroll_bar_up_arrow;
8114 break;
8115 case kControlDownButtonPart:
8116 bufp->part = scroll_bar_down_arrow;
8117 break;
8118 case kControlPageUpPart:
8119 bufp->part = scroll_bar_above_handle;
8120 break;
8121 case kControlPageDownPart:
8122 bufp->part = scroll_bar_below_handle;
8123 break;
8124 case kControlIndicatorPart:
8125 if (er->what == mouseDown)
8126 bar->dragging = make_number (0);
8127 XSETVECTOR (last_mouse_scroll_bar, bar);
8128 bufp->part = scroll_bar_handle;
8129 break;
8134 /* Handle some mouse motion while someone is dragging the scroll bar.
8136 This may be called from a signal handler, so we have to ignore GC
8137 mark bits. */
8139 static void
8140 x_scroll_bar_note_movement (bar, y_pos, t)
8141 struct scroll_bar *bar;
8142 int y_pos;
8143 Time t;
8145 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8147 last_mouse_movement_time = t;
8149 f->mouse_moved = 1;
8150 XSETVECTOR (last_mouse_scroll_bar, bar);
8152 /* If we're dragging the bar, display it. */
8153 if (! GC_NILP (bar->dragging))
8155 /* Where should the handle be now? */
8156 int new_start = y_pos - 24;
8158 if (new_start != XINT (bar->start))
8160 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8162 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8168 /* Return information to the user about the current position of the
8169 mouse on the scroll bar. */
8171 static void
8172 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8173 FRAME_PTR *fp;
8174 Lisp_Object *bar_window;
8175 enum scroll_bar_part *part;
8176 Lisp_Object *x, *y;
8177 unsigned long *time;
8179 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8180 WindowPtr wp = FrontWindow ();
8181 Point mouse_pos;
8182 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8183 int win_y, top_range;
8185 SetPort (wp);
8186 GetMouse (&mouse_pos);
8188 win_y = mouse_pos.v - XINT (bar->top);
8189 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8191 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8193 win_y -= 24;
8195 if (! NILP (bar->dragging))
8196 win_y -= XINT (bar->dragging);
8198 if (win_y < 0)
8199 win_y = 0;
8200 if (win_y > top_range)
8201 win_y = top_range;
8203 *fp = f;
8204 *bar_window = bar->window;
8206 if (! NILP (bar->dragging))
8207 *part = scroll_bar_handle;
8208 else if (win_y < XINT (bar->start))
8209 *part = scroll_bar_above_handle;
8210 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8211 *part = scroll_bar_handle;
8212 else
8213 *part = scroll_bar_below_handle;
8215 XSETINT (*x, win_y);
8216 XSETINT (*y, top_range);
8218 f->mouse_moved = 0;
8219 last_mouse_scroll_bar = Qnil;
8221 *time = last_mouse_movement_time;
8224 /***********************************************************************
8225 Text Cursor
8226 ***********************************************************************/
8228 /* Note if the text cursor of window W has been overwritten by a
8229 drawing operation that outputs N glyphs starting at HPOS in the
8230 line given by output_cursor.vpos. N < 0 means all the rest of the
8231 line after HPOS has been written. */
8233 static void
8234 note_overwritten_text_cursor (w, hpos, n)
8235 struct window *w;
8236 int hpos, n;
8238 if (updated_area == TEXT_AREA
8239 && output_cursor.vpos == w->phys_cursor.vpos
8240 && hpos <= w->phys_cursor.hpos
8241 && (n < 0
8242 || hpos + n > w->phys_cursor.hpos))
8243 w->phys_cursor_on_p = 0;
8247 /* Set clipping for output in glyph row ROW. W is the window in which
8248 we operate. GC is the graphics context to set clipping in.
8249 WHOLE_LINE_P non-zero means include the areas used for truncation
8250 mark display and alike in the clipping rectangle.
8252 ROW may be a text row or, e.g., a mode line. Text rows must be
8253 clipped to the interior of the window dedicated to text display,
8254 mode lines must be clipped to the whole window. */
8256 static void
8257 x_clip_to_row (w, row, gc, whole_line_p)
8258 struct window *w;
8259 struct glyph_row *row;
8260 GC gc;
8261 int whole_line_p;
8263 struct frame *f = XFRAME (WINDOW_FRAME (w));
8264 Rect clip_rect;
8265 int window_x, window_y, window_width, window_height;
8267 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8269 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8270 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8271 clip_rect.top = max (clip_rect.top, window_y);
8272 clip_rect.right = clip_rect.left + window_width;
8273 clip_rect.bottom = clip_rect.top + row->visible_height;
8275 /* If clipping to the whole line, including trunc marks, extend
8276 the rectangle to the left and increase its width. */
8277 if (whole_line_p)
8279 clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
8280 clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f);
8283 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8287 /* Draw a hollow box cursor on window W in glyph row ROW. */
8289 static void
8290 x_draw_hollow_cursor (w, row)
8291 struct window *w;
8292 struct glyph_row *row;
8294 struct frame *f = XFRAME (WINDOW_FRAME (w));
8295 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8296 Display *dpy = FRAME_MAC_DISPLAY (f);
8297 int x, y, wd, h;
8298 XGCValues xgcv;
8299 struct glyph *cursor_glyph;
8300 GC gc;
8302 /* Compute frame-relative coordinates from window-relative
8303 coordinates. */
8304 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8305 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8306 + row->ascent - w->phys_cursor_ascent);
8307 h = row->height - 1;
8309 /* Get the glyph the cursor is on. If we can't tell because
8310 the current matrix is invalid or such, give up. */
8311 cursor_glyph = get_phys_cursor_glyph (w);
8312 if (cursor_glyph == NULL)
8313 return;
8315 /* Compute the width of the rectangle to draw. If on a stretch
8316 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8317 rectangle as wide as the glyph, but use a canonical character
8318 width instead. */
8319 wd = cursor_glyph->pixel_width - 1;
8320 if (cursor_glyph->type == STRETCH_GLYPH
8321 && !x_stretch_cursor_p)
8322 wd = min (CANON_X_UNIT (f), wd);
8324 /* The foreground of cursor_gc is typically the same as the normal
8325 background color, which can cause the cursor box to be invisible. */
8326 xgcv.foreground = f->output_data.mac->cursor_pixel;
8327 if (dpyinfo->scratch_cursor_gc)
8328 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8329 else
8330 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8331 GCForeground, &xgcv);
8332 gc = dpyinfo->scratch_cursor_gc;
8334 /* Set clipping, draw the rectangle, and reset clipping again. */
8335 x_clip_to_row (w, row, gc, 0);
8336 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8337 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8341 /* Draw a bar cursor on window W in glyph row ROW.
8343 Implementation note: One would like to draw a bar cursor with an
8344 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8345 Unfortunately, I didn't find a font yet that has this property set.
8346 --gerd. */
8348 static void
8349 x_draw_bar_cursor (w, row, width)
8350 struct window *w;
8351 struct glyph_row *row;
8352 int width;
8354 /* If cursor hpos is out of bounds, don't draw garbage. This can
8355 happen in mini-buffer windows when switching between echo area
8356 glyphs and mini-buffer. */
8357 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8359 struct frame *f = XFRAME (w->frame);
8360 struct glyph *cursor_glyph;
8361 GC gc;
8362 int x;
8363 unsigned long mask;
8364 XGCValues xgcv;
8365 Display *dpy;
8366 Window window;
8368 cursor_glyph = get_phys_cursor_glyph (w);
8369 if (cursor_glyph == NULL)
8370 return;
8372 xgcv.background = f->output_data.mac->cursor_pixel;
8373 xgcv.foreground = f->output_data.mac->cursor_pixel;
8374 mask = GCForeground | GCBackground;
8375 dpy = FRAME_MAC_DISPLAY (f);
8376 window = FRAME_MAC_WINDOW (f);
8377 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
8379 if (gc)
8380 XChangeGC (dpy, gc, mask, &xgcv);
8381 else
8383 gc = XCreateGC (dpy, window, mask, &xgcv);
8384 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
8387 if (width < 0)
8388 width = f->output_data.mac->cursor_width;
8390 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8391 x_clip_to_row (w, row, gc, 0);
8392 XFillRectangle (dpy, window, gc,
8394 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
8395 min (cursor_glyph->pixel_width, width),
8396 row->height);
8397 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8402 /* Clear the cursor of window W to background color, and mark the
8403 cursor as not shown. This is used when the text where the cursor
8404 is is about to be rewritten. */
8406 static void
8407 x_clear_cursor (w)
8408 struct window *w;
8410 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
8411 x_update_window_cursor (w, 0);
8415 /* Draw the cursor glyph of window W in glyph row ROW. See the
8416 comment of x_draw_glyphs for the meaning of HL. */
8418 static void
8419 x_draw_phys_cursor_glyph (w, row, hl)
8420 struct window *w;
8421 struct glyph_row *row;
8422 enum draw_glyphs_face hl;
8424 /* If cursor hpos is out of bounds, don't draw garbage. This can
8425 happen in mini-buffer windows when switching between echo area
8426 glyphs and mini-buffer. */
8427 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8429 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
8430 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
8431 hl, 0, 0, 0);
8433 /* When we erase the cursor, and ROW is overlapped by other
8434 rows, make sure that these overlapping parts of other rows
8435 are redrawn. */
8436 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
8438 if (row > w->current_matrix->rows
8439 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
8440 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
8442 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
8443 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
8444 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
8450 /* Erase the image of a cursor of window W from the screen. */
8452 static void
8453 x_erase_phys_cursor (w)
8454 struct window *w;
8456 struct frame *f = XFRAME (w->frame);
8457 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8458 int hpos = w->phys_cursor.hpos;
8459 int vpos = w->phys_cursor.vpos;
8460 int mouse_face_here_p = 0;
8461 struct glyph_matrix *active_glyphs = w->current_matrix;
8462 struct glyph_row *cursor_row;
8463 struct glyph *cursor_glyph;
8464 enum draw_glyphs_face hl;
8466 /* No cursor displayed or row invalidated => nothing to do on the
8467 screen. */
8468 if (w->phys_cursor_type == NO_CURSOR)
8469 goto mark_cursor_off;
8471 /* VPOS >= active_glyphs->nrows means that window has been resized.
8472 Don't bother to erase the cursor. */
8473 if (vpos >= active_glyphs->nrows)
8474 goto mark_cursor_off;
8476 /* If row containing cursor is marked invalid, there is nothing we
8477 can do. */
8478 cursor_row = MATRIX_ROW (active_glyphs, vpos);
8479 if (!cursor_row->enabled_p)
8480 goto mark_cursor_off;
8482 /* This can happen when the new row is shorter than the old one.
8483 In this case, either x_draw_glyphs or clear_end_of_line
8484 should have cleared the cursor. Note that we wouldn't be
8485 able to erase the cursor in this case because we don't have a
8486 cursor glyph at hand. */
8487 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
8488 goto mark_cursor_off;
8490 /* If the cursor is in the mouse face area, redisplay that when
8491 we clear the cursor. */
8492 if (! NILP (dpyinfo->mouse_face_window)
8493 && w == XWINDOW (dpyinfo->mouse_face_window)
8494 && (vpos > dpyinfo->mouse_face_beg_row
8495 || (vpos == dpyinfo->mouse_face_beg_row
8496 && hpos >= dpyinfo->mouse_face_beg_col))
8497 && (vpos < dpyinfo->mouse_face_end_row
8498 || (vpos == dpyinfo->mouse_face_end_row
8499 && hpos < dpyinfo->mouse_face_end_col))
8500 /* Don't redraw the cursor's spot in mouse face if it is at the
8501 end of a line (on a newline). The cursor appears there, but
8502 mouse highlighting does not. */
8503 && cursor_row->used[TEXT_AREA] > hpos)
8504 mouse_face_here_p = 1;
8506 /* Maybe clear the display under the cursor. */
8507 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
8509 int x;
8510 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
8512 cursor_glyph = get_phys_cursor_glyph (w);
8513 if (cursor_glyph == NULL)
8514 goto mark_cursor_off;
8516 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
8518 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8520 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
8521 cursor_row->y)),
8522 cursor_glyph->pixel_width,
8523 cursor_row->visible_height,
8527 /* Erase the cursor by redrawing the character underneath it. */
8528 if (mouse_face_here_p)
8529 hl = DRAW_MOUSE_FACE;
8530 else if (cursor_row->inverse_p)
8531 hl = DRAW_INVERSE_VIDEO;
8532 else
8533 hl = DRAW_NORMAL_TEXT;
8534 x_draw_phys_cursor_glyph (w, cursor_row, hl);
8536 mark_cursor_off:
8537 w->phys_cursor_on_p = 0;
8538 w->phys_cursor_type = NO_CURSOR;
8542 /* Display or clear cursor of window W. If ON is zero, clear the
8543 cursor. If it is non-zero, display the cursor. If ON is nonzero,
8544 where to put the cursor is specified by HPOS, VPOS, X and Y. */
8546 void
8547 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
8548 struct window *w;
8549 int on, hpos, vpos, x, y;
8551 struct frame *f = XFRAME (w->frame);
8552 int new_cursor_type;
8553 int new_cursor_width;
8554 struct glyph_matrix *current_glyphs;
8555 struct glyph_row *glyph_row;
8556 struct glyph *glyph;
8558 /* This is pointless on invisible frames, and dangerous on garbaged
8559 windows and frames; in the latter case, the frame or window may
8560 be in the midst of changing its size, and x and y may be off the
8561 window. */
8562 if (! FRAME_VISIBLE_P (f)
8563 || FRAME_GARBAGED_P (f)
8564 || vpos >= w->current_matrix->nrows
8565 || hpos >= w->current_matrix->matrix_w)
8566 return;
8568 /* If cursor is off and we want it off, return quickly. */
8569 if (!on && !w->phys_cursor_on_p)
8570 return;
8572 current_glyphs = w->current_matrix;
8573 glyph_row = MATRIX_ROW (current_glyphs, vpos);
8574 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
8576 /* If cursor row is not enabled, we don't really know where to
8577 display the cursor. */
8578 if (!glyph_row->enabled_p)
8580 w->phys_cursor_on_p = 0;
8581 return;
8584 xassert (interrupt_input_blocked);
8586 /* Set new_cursor_type to the cursor we want to be displayed. In a
8587 mini-buffer window, we want the cursor only to appear if we are
8588 reading input from this window. For the selected window, we want
8589 the cursor type given by the frame parameter. If explicitly
8590 marked off, draw no cursor. In all other cases, we want a hollow
8591 box cursor. */
8592 new_cursor_width = -1;
8593 if (cursor_in_echo_area
8594 && FRAME_HAS_MINIBUF_P (f)
8595 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
8597 if (w == XWINDOW (echo_area_window))
8598 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8599 else
8600 new_cursor_type = HOLLOW_BOX_CURSOR;
8602 else
8604 if (w != XWINDOW (selected_window)
8605 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
8607 extern int cursor_in_non_selected_windows;
8609 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
8610 new_cursor_type = NO_CURSOR;
8611 else
8612 new_cursor_type = HOLLOW_BOX_CURSOR;
8614 else if (w->cursor_off_p)
8615 new_cursor_type = NO_CURSOR;
8616 else
8618 struct buffer *b = XBUFFER (w->buffer);
8620 if (EQ (b->cursor_type, Qt))
8621 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8622 else
8623 new_cursor_type = x_specified_cursor_type (b->cursor_type,
8624 &new_cursor_width);
8628 /* If cursor is currently being shown and we don't want it to be or
8629 it is in the wrong place, or the cursor type is not what we want,
8630 erase it. */
8631 if (w->phys_cursor_on_p
8632 && (!on
8633 || w->phys_cursor.x != x
8634 || w->phys_cursor.y != y
8635 || new_cursor_type != w->phys_cursor_type))
8636 x_erase_phys_cursor (w);
8638 /* If the cursor is now invisible and we want it to be visible,
8639 display it. */
8640 if (on && !w->phys_cursor_on_p)
8642 w->phys_cursor_ascent = glyph_row->ascent;
8643 w->phys_cursor_height = glyph_row->height;
8645 /* Set phys_cursor_.* before x_draw_.* is called because some
8646 of them may need the information. */
8647 w->phys_cursor.x = x;
8648 w->phys_cursor.y = glyph_row->y;
8649 w->phys_cursor.hpos = hpos;
8650 w->phys_cursor.vpos = vpos;
8651 w->phys_cursor_type = new_cursor_type;
8652 w->phys_cursor_on_p = 1;
8654 switch (new_cursor_type)
8656 case HOLLOW_BOX_CURSOR:
8657 x_draw_hollow_cursor (w, glyph_row);
8658 break;
8660 case FILLED_BOX_CURSOR:
8661 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
8662 break;
8664 case BAR_CURSOR:
8665 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
8666 break;
8668 case NO_CURSOR:
8669 break;
8671 default:
8672 abort ();
8675 #ifdef HAVE_X_I18N
8676 if (w == XWINDOW (f->selected_window))
8677 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
8678 xic_set_preeditarea (w, x, y);
8679 #endif
8682 #ifndef XFlush
8683 if (updating_frame != f)
8684 XFlush (FRAME_X_DISPLAY (f));
8685 #endif
8689 /* Display the cursor on window W, or clear it. X and Y are window
8690 relative pixel coordinates. HPOS and VPOS are glyph matrix
8691 positions. If W is not the selected window, display a hollow
8692 cursor. ON non-zero means display the cursor at X, Y which
8693 correspond to HPOS, VPOS, otherwise it is cleared. */
8695 void
8696 x_display_cursor (w, on, hpos, vpos, x, y)
8697 struct window *w;
8698 int on, hpos, vpos, x, y;
8700 BLOCK_INPUT;
8701 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
8702 UNBLOCK_INPUT;
8706 /* Display the cursor on window W, or clear it, according to ON_P.
8707 Don't change the cursor's position. */
8709 void
8710 x_update_cursor (f, on_p)
8711 struct frame *f;
8713 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
8717 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
8718 in the window tree rooted at W. */
8720 static void
8721 x_update_cursor_in_window_tree (w, on_p)
8722 struct window *w;
8723 int on_p;
8725 while (w)
8727 if (!NILP (w->hchild))
8728 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
8729 else if (!NILP (w->vchild))
8730 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
8731 else
8732 x_update_window_cursor (w, on_p);
8734 w = NILP (w->next) ? 0 : XWINDOW (w->next);
8739 /* Switch the display of W's cursor on or off, according to the value
8740 of ON. */
8742 static void
8743 x_update_window_cursor (w, on)
8744 struct window *w;
8745 int on;
8747 /* Don't update cursor in windows whose frame is in the process
8748 of being deleted. */
8749 if (w->current_matrix)
8751 BLOCK_INPUT;
8752 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
8753 w->phys_cursor.x, w->phys_cursor.y);
8754 UNBLOCK_INPUT;
8759 #if 0 /* MAC_TODO: no icon and X error handling (?) */
8760 /* Icons. */
8762 /* Refresh bitmap kitchen sink icon for frame F
8763 when we get an expose event for it. */
8765 void
8766 refreshicon (f)
8767 struct frame *f;
8769 /* Normally, the window manager handles this function. */
8772 /* Make the x-window of frame F use the gnu icon bitmap. */
8775 x_bitmap_icon (f, file)
8776 struct frame *f;
8777 Lisp_Object file;
8779 int bitmap_id;
8781 if (FRAME_X_WINDOW (f) == 0)
8782 return 1;
8784 /* Free up our existing icon bitmap if any. */
8785 if (f->output_data.x->icon_bitmap > 0)
8786 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
8787 f->output_data.x->icon_bitmap = 0;
8789 if (STRINGP (file))
8790 bitmap_id = x_create_bitmap_from_file (f, file);
8791 else
8793 /* Create the GNU bitmap if necessary. */
8794 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
8795 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
8796 = x_create_bitmap_from_data (f, gnu_bits,
8797 gnu_width, gnu_height);
8799 /* The first time we create the GNU bitmap,
8800 this increments the ref-count one extra time.
8801 As a result, the GNU bitmap is never freed.
8802 That way, we don't have to worry about allocating it again. */
8803 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
8805 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
8808 x_wm_set_icon_pixmap (f, bitmap_id);
8809 f->output_data.x->icon_bitmap = bitmap_id;
8811 return 0;
8815 /* Make the x-window of frame F use a rectangle with text.
8816 Use ICON_NAME as the text. */
8819 x_text_icon (f, icon_name)
8820 struct frame *f;
8821 char *icon_name;
8823 if (FRAME_X_WINDOW (f) == 0)
8824 return 1;
8826 #ifdef HAVE_X11R4
8828 XTextProperty text;
8829 text.value = (unsigned char *) icon_name;
8830 text.encoding = XA_STRING;
8831 text.format = 8;
8832 text.nitems = strlen (icon_name);
8833 #ifdef USE_X_TOOLKIT
8834 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
8835 &text);
8836 #else /* not USE_X_TOOLKIT */
8837 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
8838 #endif /* not USE_X_TOOLKIT */
8840 #else /* not HAVE_X11R4 */
8841 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
8842 #endif /* not HAVE_X11R4 */
8844 if (f->output_data.x->icon_bitmap > 0)
8845 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
8846 f->output_data.x->icon_bitmap = 0;
8847 x_wm_set_icon_pixmap (f, 0);
8849 return 0;
8852 #define X_ERROR_MESSAGE_SIZE 200
8854 /* If non-nil, this should be a string.
8855 It means catch X errors and store the error message in this string. */
8857 static Lisp_Object x_error_message_string;
8859 /* An X error handler which stores the error message in
8860 x_error_message_string. This is called from x_error_handler if
8861 x_catch_errors is in effect. */
8863 static void
8864 x_error_catcher (display, error)
8865 Display *display;
8866 XErrorEvent *error;
8868 XGetErrorText (display, error->error_code,
8869 XSTRING (x_error_message_string)->data,
8870 X_ERROR_MESSAGE_SIZE);
8873 /* Begin trapping X errors for display DPY. Actually we trap X errors
8874 for all displays, but DPY should be the display you are actually
8875 operating on.
8877 After calling this function, X protocol errors no longer cause
8878 Emacs to exit; instead, they are recorded in the string
8879 stored in x_error_message_string.
8881 Calling x_check_errors signals an Emacs error if an X error has
8882 occurred since the last call to x_catch_errors or x_check_errors.
8884 Calling x_uncatch_errors resumes the normal error handling. */
8886 void x_check_errors ();
8887 static Lisp_Object x_catch_errors_unwind ();
8890 x_catch_errors (dpy)
8891 Display *dpy;
8893 int count = specpdl_ptr - specpdl;
8895 /* Make sure any errors from previous requests have been dealt with. */
8896 XSync (dpy, False);
8898 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
8900 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
8901 XSTRING (x_error_message_string)->data[0] = 0;
8903 return count;
8906 /* Unbind the binding that we made to check for X errors. */
8908 static Lisp_Object
8909 x_catch_errors_unwind (old_val)
8910 Lisp_Object old_val;
8912 x_error_message_string = old_val;
8913 return Qnil;
8916 /* If any X protocol errors have arrived since the last call to
8917 x_catch_errors or x_check_errors, signal an Emacs error using
8918 sprintf (a buffer, FORMAT, the x error message text) as the text. */
8920 void
8921 x_check_errors (dpy, format)
8922 Display *dpy;
8923 char *format;
8925 /* Make sure to catch any errors incurred so far. */
8926 XSync (dpy, False);
8928 if (XSTRING (x_error_message_string)->data[0])
8929 error (format, XSTRING (x_error_message_string)->data);
8932 /* Nonzero if we had any X protocol errors
8933 since we did x_catch_errors on DPY. */
8936 x_had_errors_p (dpy)
8937 Display *dpy;
8939 /* Make sure to catch any errors incurred so far. */
8940 XSync (dpy, False);
8942 return XSTRING (x_error_message_string)->data[0] != 0;
8945 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
8947 void
8948 x_clear_errors (dpy)
8949 Display *dpy;
8951 XSTRING (x_error_message_string)->data[0] = 0;
8954 /* Stop catching X protocol errors and let them make Emacs die.
8955 DPY should be the display that was passed to x_catch_errors.
8956 COUNT should be the value that was returned by
8957 the corresponding call to x_catch_errors. */
8959 void
8960 x_uncatch_errors (dpy, count)
8961 Display *dpy;
8962 int count;
8964 unbind_to (count, Qnil);
8967 #if 0
8968 static unsigned int x_wire_count;
8969 x_trace_wire ()
8971 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
8973 #endif /* ! 0 */
8976 /* Handle SIGPIPE, which can happen when the connection to a server
8977 simply goes away. SIGPIPE is handled by x_connection_signal.
8978 Don't need to do anything, because the write which caused the
8979 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
8980 which will do the appropriate cleanup for us. */
8982 static SIGTYPE
8983 x_connection_signal (signalnum) /* If we don't have an argument, */
8984 int signalnum; /* some compilers complain in signal calls. */
8986 #ifdef USG
8987 /* USG systems forget handlers when they are used;
8988 must reestablish each time */
8989 signal (signalnum, x_connection_signal);
8990 #endif /* USG */
8993 /* Handling X errors. */
8995 /* Handle the loss of connection to display DISPLAY. */
8997 static SIGTYPE
8998 x_connection_closed (display, error_message)
8999 Display *display;
9000 char *error_message;
9002 struct x_display_info *dpyinfo = x_display_info_for_display (display);
9003 Lisp_Object frame, tail;
9005 /* Indicate that this display is dead. */
9007 #if 0 /* Closing the display caused a bus error on OpenWindows. */
9008 #ifdef USE_X_TOOLKIT
9009 XtCloseDisplay (display);
9010 #endif
9011 #endif
9013 if (dpyinfo)
9014 dpyinfo->display = 0;
9016 /* First delete frames whose mini-buffers are on frames
9017 that are on the dead display. */
9018 FOR_EACH_FRAME (tail, frame)
9020 Lisp_Object minibuf_frame;
9021 minibuf_frame
9022 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
9023 if (FRAME_X_P (XFRAME (frame))
9024 && FRAME_X_P (XFRAME (minibuf_frame))
9025 && ! EQ (frame, minibuf_frame)
9026 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
9027 Fdelete_frame (frame, Qt);
9030 /* Now delete all remaining frames on the dead display.
9031 We are now sure none of these is used as the mini-buffer
9032 for another frame that we need to delete. */
9033 FOR_EACH_FRAME (tail, frame)
9034 if (FRAME_X_P (XFRAME (frame))
9035 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
9037 /* Set this to t so that Fdelete_frame won't get confused
9038 trying to find a replacement. */
9039 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
9040 Fdelete_frame (frame, Qt);
9043 if (dpyinfo)
9044 x_delete_display (dpyinfo);
9046 if (x_display_list == 0)
9048 fprintf (stderr, "%s\n", error_message);
9049 shut_down_emacs (0, 0, Qnil);
9050 exit (70);
9053 /* Ordinary stack unwind doesn't deal with these. */
9054 #ifdef SIGIO
9055 sigunblock (sigmask (SIGIO));
9056 #endif
9057 sigunblock (sigmask (SIGALRM));
9058 TOTALLY_UNBLOCK_INPUT;
9060 clear_waiting_for_input ();
9061 error ("%s", error_message);
9064 /* This is the usual handler for X protocol errors.
9065 It kills all frames on the display that we got the error for.
9066 If that was the only one, it prints an error message and kills Emacs. */
9068 static void
9069 x_error_quitter (display, error)
9070 Display *display;
9071 XErrorEvent *error;
9073 char buf[256], buf1[356];
9075 /* Note that there is no real way portable across R3/R4 to get the
9076 original error handler. */
9078 XGetErrorText (display, error->error_code, buf, sizeof (buf));
9079 sprintf (buf1, "X protocol error: %s on protocol request %d",
9080 buf, error->request_code);
9081 x_connection_closed (display, buf1);
9084 /* This is the first-level handler for X protocol errors.
9085 It calls x_error_quitter or x_error_catcher. */
9087 static int
9088 x_error_handler (display, error)
9089 Display *display;
9090 XErrorEvent *error;
9092 if (! NILP (x_error_message_string))
9093 x_error_catcher (display, error);
9094 else
9095 x_error_quitter (display, error);
9096 return 0;
9099 /* This is the handler for X IO errors, always.
9100 It kills all frames on the display that we lost touch with.
9101 If that was the only one, it prints an error message and kills Emacs. */
9103 static int
9104 x_io_error_quitter (display)
9105 Display *display;
9107 char buf[256];
9109 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
9110 x_connection_closed (display, buf);
9111 return 0;
9113 #endif
9115 /* Changing the font of the frame. */
9117 /* Give frame F the font named FONTNAME as its default font, and
9118 return the full name of that font. FONTNAME may be a wildcard
9119 pattern; in that case, we choose some font that fits the pattern.
9120 The return value shows which font we chose. */
9122 Lisp_Object
9123 x_new_font (f, fontname)
9124 struct frame *f;
9125 register char *fontname;
9127 struct font_info *fontp
9128 = FS_LOAD_FONT (f, 0, fontname, -1);
9130 if (!fontp)
9131 return Qnil;
9133 f->output_data.mac->font = (XFontStruct *) (fontp->font);
9134 f->output_data.mac->baseline_offset = fontp->baseline_offset;
9135 f->output_data.mac->fontset = -1;
9137 /* Compute the scroll bar width in character columns. */
9138 if (f->scroll_bar_pixel_width > 0)
9140 int wid = FONT_WIDTH (f->output_data.mac->font);
9141 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9143 else
9145 int wid = FONT_WIDTH (f->output_data.mac->font);
9146 f->scroll_bar_cols = (14 + wid - 1) / wid;
9149 /* Now make the frame display the given font. */
9150 if (FRAME_MAC_WINDOW (f) != 0)
9152 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9153 f->output_data.mac->font);
9154 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9155 f->output_data.mac->font);
9156 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9157 f->output_data.mac->font);
9159 frame_update_line_height (f);
9160 x_set_window_size (f, 0, f->width, f->height);
9162 else
9163 /* If we are setting a new frame's font for the first time, there
9164 are no faces yet, so this font's height is the line height. */
9165 f->output_data.mac->line_height = FONT_HEIGHT (f->output_data.mac->font);
9167 return build_string (fontp->full_name);
9170 /* Give frame F the fontset named FONTSETNAME as its default font, and
9171 return the full name of that fontset. FONTSETNAME may be a
9172 wildcard pattern; in that case, we choose some fontset that fits
9173 the pattern. The return value shows which fontset we chose. */
9175 Lisp_Object
9176 x_new_fontset (f, fontsetname)
9177 struct frame *f;
9178 char *fontsetname;
9180 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9181 Lisp_Object result;
9183 if (fontset < 0)
9184 return Qnil;
9186 if (f->output_data.mac->fontset == fontset)
9187 /* This fontset is already set in frame F. There's nothing more
9188 to do. */
9189 return fontset_name (fontset);
9191 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
9193 if (!STRINGP (result))
9194 /* Can't load ASCII font. */
9195 return Qnil;
9197 /* Since x_new_font doesn't update any fontset information, do it
9198 now. */
9199 f->output_data.mac->fontset = fontset;
9201 #ifdef HAVE_X_I18N
9202 if (FRAME_XIC (f)
9203 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
9204 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
9205 #endif
9207 return build_string (fontsetname);
9210 #if 0 /* MAC_TODO: inline input methods for Mac */
9212 /***********************************************************************
9213 X Input Methods
9214 ***********************************************************************/
9216 #ifdef HAVE_X_I18N
9218 #ifdef HAVE_X11R6
9220 /* XIM destroy callback function, which is called whenever the
9221 connection to input method XIM dies. CLIENT_DATA contains a
9222 pointer to the x_display_info structure corresponding to XIM. */
9224 static void
9225 xim_destroy_callback (xim, client_data, call_data)
9226 XIM xim;
9227 XPointer client_data;
9228 XPointer call_data;
9230 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
9231 Lisp_Object frame, tail;
9233 BLOCK_INPUT;
9235 /* No need to call XDestroyIC.. */
9236 FOR_EACH_FRAME (tail, frame)
9238 struct frame *f = XFRAME (frame);
9239 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
9241 FRAME_XIC (f) = NULL;
9242 if (FRAME_XIC_FONTSET (f))
9244 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
9245 FRAME_XIC_FONTSET (f) = NULL;
9250 /* No need to call XCloseIM. */
9251 dpyinfo->xim = NULL;
9252 XFree (dpyinfo->xim_styles);
9253 UNBLOCK_INPUT;
9256 #endif /* HAVE_X11R6 */
9258 /* Open the connection to the XIM server on display DPYINFO.
9259 RESOURCE_NAME is the resource name Emacs uses. */
9261 static void
9262 xim_open_dpy (dpyinfo, resource_name)
9263 struct x_display_info *dpyinfo;
9264 char *resource_name;
9266 #ifdef USE_XIM
9267 XIM xim;
9269 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
9270 dpyinfo->xim = xim;
9272 if (xim)
9274 #ifdef HAVE_X11R6
9275 XIMCallback destroy;
9276 #endif
9278 /* Get supported styles and XIM values. */
9279 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
9281 #ifdef HAVE_X11R6
9282 destroy.callback = xim_destroy_callback;
9283 destroy.client_data = (XPointer)dpyinfo;
9284 /* This isn't prptotyped in OSF 5.0. */
9285 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
9286 #endif
9289 #else /* not USE_XIM */
9290 dpyinfo->xim = NULL;
9291 #endif /* not USE_XIM */
9295 #ifdef HAVE_X11R6_XIM
9297 struct xim_inst_t
9299 struct x_display_info *dpyinfo;
9300 char *resource_name;
9303 /* XIM instantiate callback function, which is called whenever an XIM
9304 server is available. DISPLAY is teh display of the XIM.
9305 CLIENT_DATA contains a pointer to an xim_inst_t structure created
9306 when the callback was registered. */
9308 static void
9309 xim_instantiate_callback (display, client_data, call_data)
9310 Display *display;
9311 XPointer client_data;
9312 XPointer call_data;
9314 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
9315 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
9317 /* We don't support multiple XIM connections. */
9318 if (dpyinfo->xim)
9319 return;
9321 xim_open_dpy (dpyinfo, xim_inst->resource_name);
9323 /* Create XIC for the existing frames on the same display, as long
9324 as they have no XIC. */
9325 if (dpyinfo->xim && dpyinfo->reference_count > 0)
9327 Lisp_Object tail, frame;
9329 BLOCK_INPUT;
9330 FOR_EACH_FRAME (tail, frame)
9332 struct frame *f = XFRAME (frame);
9334 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
9335 if (FRAME_XIC (f) == NULL)
9337 create_frame_xic (f);
9338 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
9339 xic_set_statusarea (f);
9340 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
9342 struct window *w = XWINDOW (f->selected_window);
9343 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
9348 UNBLOCK_INPUT;
9352 #endif /* HAVE_X11R6_XIM */
9355 /* Open a connection to the XIM server on display DPYINFO.
9356 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
9357 connection only at the first time. On X11R6, open the connection
9358 in the XIM instantiate callback function. */
9360 static void
9361 xim_initialize (dpyinfo, resource_name)
9362 struct x_display_info *dpyinfo;
9363 char *resource_name;
9365 #ifdef USE_XIM
9366 #ifdef HAVE_X11R6_XIM
9367 struct xim_inst_t *xim_inst;
9368 int len;
9370 dpyinfo->xim = NULL;
9371 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
9372 xim_inst->dpyinfo = dpyinfo;
9373 len = strlen (resource_name);
9374 xim_inst->resource_name = (char *) xmalloc (len + 1);
9375 bcopy (resource_name, xim_inst->resource_name, len + 1);
9376 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
9377 resource_name, EMACS_CLASS,
9378 xim_instantiate_callback,
9379 /* Fixme: This is XPointer in
9380 XFree86 but (XPointer *) on
9381 Tru64, at least. */
9382 (XPointer) xim_inst);
9383 #else /* not HAVE_X11R6_XIM */
9384 dpyinfo->xim = NULL;
9385 xim_open_dpy (dpyinfo, resource_name);
9386 #endif /* not HAVE_X11R6_XIM */
9388 #else /* not USE_XIM */
9389 dpyinfo->xim = NULL;
9390 #endif /* not USE_XIM */
9394 /* Close the connection to the XIM server on display DPYINFO. */
9396 static void
9397 xim_close_dpy (dpyinfo)
9398 struct x_display_info *dpyinfo;
9400 #ifdef USE_XIM
9401 #ifdef HAVE_X11R6_XIM
9402 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
9403 NULL, EMACS_CLASS,
9404 xim_instantiate_callback, NULL);
9405 #endif /* not HAVE_X11R6_XIM */
9406 XCloseIM (dpyinfo->xim);
9407 dpyinfo->xim = NULL;
9408 XFree (dpyinfo->xim_styles);
9409 #endif /* USE_XIM */
9412 #endif /* not HAVE_X11R6_XIM */
9414 #endif
9416 /* Calculate the absolute position in frame F
9417 from its current recorded position values and gravity. */
9419 static void
9420 x_calc_absolute_position (f)
9421 struct frame *f;
9423 Point pt;
9424 int flags = f->output_data.mac->size_hint_flags;
9426 pt.h = pt.v = 0;
9428 /* Find the position of the outside upper-left corner of
9429 the inner window, with respect to the outer window. */
9430 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9432 GrafPtr savePort;
9433 GetPort (&savePort);
9434 SetPort (FRAME_MAC_WINDOW (f));
9435 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9436 LocalToGlobal (&pt);
9437 SetPort (savePort);
9440 /* Treat negative positions as relative to the leftmost bottommost
9441 position that fits on the screen. */
9442 if (flags & XNegative)
9443 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9444 - 2 * f->output_data.mac->border_width - pt.h
9445 - PIXEL_WIDTH (f)
9446 + f->output_data.mac->left_pos);
9447 /* NTEMACS_TODO: Subtract menubar height? */
9448 if (flags & YNegative)
9449 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9450 - 2 * f->output_data.mac->border_width - pt.v
9451 - PIXEL_HEIGHT (f)
9452 + f->output_data.mac->top_pos);
9453 /* The left_pos and top_pos
9454 are now relative to the top and left screen edges,
9455 so the flags should correspond. */
9456 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9459 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9460 to really change the position, and 0 when calling from
9461 x_make_frame_visible (in that case, XOFF and YOFF are the current
9462 position values). It is -1 when calling from x_set_frame_parameters,
9463 which means, do adjust for borders but don't change the gravity. */
9465 void
9466 x_set_offset (f, xoff, yoff, change_gravity)
9467 struct frame *f;
9468 register int xoff, yoff;
9469 int change_gravity;
9471 if (change_gravity > 0)
9473 f->output_data.mac->top_pos = yoff;
9474 f->output_data.mac->left_pos = xoff;
9475 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9476 if (xoff < 0)
9477 f->output_data.mac->size_hint_flags |= XNegative;
9478 if (yoff < 0)
9479 f->output_data.mac->size_hint_flags |= YNegative;
9480 f->output_data.mac->win_gravity = NorthWestGravity;
9482 x_calc_absolute_position (f);
9484 BLOCK_INPUT;
9485 x_wm_set_size_hint (f, (long) 0, 0);
9487 MoveWindow (f->output_data.mac->mWP, xoff + 6, yoff + 42, false);
9489 UNBLOCK_INPUT;
9492 /* Call this to change the size of frame F's x-window.
9493 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9494 for this size change and subsequent size changes.
9495 Otherwise we leave the window gravity unchanged. */
9497 void
9498 x_set_window_size (f, change_gravity, cols, rows)
9499 struct frame *f;
9500 int change_gravity;
9501 int cols, rows;
9503 int pixelwidth, pixelheight;
9505 check_frame_size (f, &rows, &cols);
9506 f->output_data.mac->vertical_scroll_bar_extra
9507 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9509 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
9510 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
9511 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9512 f->output_data.mac->flags_areas_extra
9513 = FRAME_FLAGS_AREA_WIDTH (f);
9514 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9515 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9517 f->output_data.mac->win_gravity = NorthWestGravity;
9518 x_wm_set_size_hint (f, (long) 0, 0);
9520 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9522 /* Now, strictly speaking, we can't be sure that this is accurate,
9523 but the window manager will get around to dealing with the size
9524 change request eventually, and we'll hear how it went when the
9525 ConfigureNotify event gets here.
9527 We could just not bother storing any of this information here,
9528 and let the ConfigureNotify event set everything up, but that
9529 might be kind of confusing to the Lisp code, since size changes
9530 wouldn't be reported in the frame parameters until some random
9531 point in the future when the ConfigureNotify event arrives.
9533 We pass 1 for DELAY since we can't run Lisp code inside of
9534 a BLOCK_INPUT. */
9535 change_frame_size (f, rows, cols, 0, 1, 0);
9536 PIXEL_WIDTH (f) = pixelwidth;
9537 PIXEL_HEIGHT (f) = pixelheight;
9539 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9540 receive in the ConfigureNotify event; if we get what we asked
9541 for, then the event won't cause the screen to become garbaged, so
9542 we have to make sure to do it here. */
9543 SET_FRAME_GARBAGED (f);
9545 XFlush (FRAME_X_DISPLAY (f));
9547 /* If cursor was outside the new size, mark it as off. */
9548 mark_window_cursors_off (XWINDOW (f->root_window));
9550 /* Clear out any recollection of where the mouse highlighting was,
9551 since it might be in a place that's outside the new frame size.
9552 Actually checking whether it is outside is a pain in the neck,
9553 so don't try--just let the highlighting be done afresh with new size. */
9554 cancel_mouse_face (f);
9557 /* Mouse warping. */
9559 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9561 void
9562 x_set_mouse_position (f, x, y)
9563 struct frame *f;
9564 int x, y;
9566 int pix_x, pix_y;
9568 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9569 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9571 if (pix_x < 0) pix_x = 0;
9572 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9574 if (pix_y < 0) pix_y = 0;
9575 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9577 x_set_mouse_pixel_position (f, pix_x, pix_y);
9580 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
9582 void
9583 x_set_mouse_pixel_position (f, pix_x, pix_y)
9584 struct frame *f;
9585 int pix_x, pix_y;
9587 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9588 BLOCK_INPUT;
9590 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9591 0, 0, 0, 0, pix_x, pix_y);
9592 UNBLOCK_INPUT;
9593 #endif
9596 /* focus shifting, raising and lowering. */
9598 static void
9599 x_focus_on_frame (f)
9600 struct frame *f;
9602 #if 0 /* This proves to be unpleasant. */
9603 x_raise_frame (f);
9604 #endif
9605 #if 0
9606 /* I don't think that the ICCCM allows programs to do things like this
9607 without the interaction of the window manager. Whatever you end up
9608 doing with this code, do it to x_unfocus_frame too. */
9609 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9610 RevertToPointerRoot, CurrentTime);
9611 #endif /* ! 0 */
9614 static void
9615 x_unfocus_frame (f)
9616 struct frame *f;
9618 #if 0
9619 /* Look at the remarks in x_focus_on_frame. */
9620 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
9621 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
9622 RevertToPointerRoot, CurrentTime);
9623 #endif /* ! 0 */
9626 /* Raise frame F. */
9628 void
9629 x_raise_frame (f)
9630 struct frame *f;
9632 if (f->async_visible)
9633 SelectWindow (FRAME_MAC_WINDOW (f));
9636 /* Lower frame F. */
9638 void
9639 x_lower_frame (f)
9640 struct frame *f;
9642 if (f->async_visible)
9643 SendBehind (FRAME_MAC_WINDOW (f), nil);
9646 void
9647 XTframe_raise_lower (f, raise_flag)
9648 FRAME_PTR f;
9649 int raise_flag;
9651 if (raise_flag)
9652 x_raise_frame (f);
9653 else
9654 x_lower_frame (f);
9657 /* Change of visibility. */
9659 /* This tries to wait until the frame is really visible.
9660 However, if the window manager asks the user where to position
9661 the frame, this will return before the user finishes doing that.
9662 The frame will not actually be visible at that time,
9663 but it will become visible later when the window manager
9664 finishes with it. */
9666 void
9667 x_make_frame_visible (f)
9668 struct frame *f;
9670 Lisp_Object type;
9671 int original_top, original_left;
9673 BLOCK_INPUT;
9675 if (! FRAME_VISIBLE_P (f))
9677 /* We test FRAME_GARBAGED_P here to make sure we don't
9678 call x_set_offset a second time
9679 if we get to x_make_frame_visible a second time
9680 before the window gets really visible. */
9681 if (! FRAME_ICONIFIED_P (f)
9682 && ! f->output_data.mac->asked_for_visible)
9683 x_set_offset (f, f->output_data.mac->left_pos,
9684 f->output_data.mac->top_pos, 0);
9686 f->output_data.mac->asked_for_visible = 1;
9688 ShowWindow (FRAME_MAC_WINDOW (f));
9691 XFlush (FRAME_MAC_DISPLAY (f));
9693 /* Synchronize to ensure Emacs knows the frame is visible
9694 before we do anything else. We do this loop with input not blocked
9695 so that incoming events are handled. */
9697 Lisp_Object frame;
9698 int count;
9700 /* This must come after we set COUNT. */
9701 UNBLOCK_INPUT;
9703 XSETFRAME (frame, f);
9705 /* Wait until the frame is visible. Process X events until a
9706 MapNotify event has been seen, or until we think we won't get a
9707 MapNotify at all.. */
9708 for (count = input_signal_count + 10;
9709 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9711 /* Force processing of queued events. */
9712 x_sync (f);
9714 /* Machines that do polling rather than SIGIO have been
9715 observed to go into a busy-wait here. So we'll fake an
9716 alarm signal to let the handler know that there's something
9717 to be read. We used to raise a real alarm, but it seems
9718 that the handler isn't always enabled here. This is
9719 probably a bug. */
9720 if (input_polling_used ())
9722 /* It could be confusing if a real alarm arrives while
9723 processing the fake one. Turn it off and let the
9724 handler reset it. */
9725 extern void poll_for_input_1 P_ ((void));
9726 int old_poll_suppress_count = poll_suppress_count;
9727 poll_suppress_count = 1;
9728 poll_for_input_1 ();
9729 poll_suppress_count = old_poll_suppress_count;
9732 /* See if a MapNotify event has been processed. */
9733 FRAME_SAMPLE_VISIBILITY (f);
9738 /* Change from mapped state to withdrawn state. */
9740 /* Make the frame visible (mapped and not iconified). */
9742 void
9743 x_make_frame_invisible (f)
9744 struct frame *f;
9746 /* Don't keep the highlight on an invisible frame. */
9747 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
9748 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
9750 BLOCK_INPUT;
9752 HideWindow (FRAME_MAC_WINDOW (f));
9754 /* We can't distinguish this from iconification
9755 just by the event that we get from the server.
9756 So we can't win using the usual strategy of letting
9757 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9758 and synchronize with the server to make sure we agree. */
9759 f->visible = 0;
9760 FRAME_ICONIFIED_P (f) = 0;
9761 f->async_visible = 0;
9762 f->async_iconified = 0;
9764 UNBLOCK_INPUT;
9767 /* Change window state from mapped to iconified. */
9769 void
9770 x_iconify_frame (f)
9771 struct frame *f;
9773 #if 0 /* MAC_TODO: really no iconify on Mac */
9774 int result;
9775 Lisp_Object type;
9777 /* Don't keep the highlight on an invisible frame. */
9778 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9779 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9781 if (f->async_iconified)
9782 return;
9784 BLOCK_INPUT;
9786 FRAME_SAMPLE_VISIBILITY (f);
9788 type = x_icon_type (f);
9789 if (!NILP (type))
9790 x_bitmap_icon (f, type);
9792 #ifdef USE_X_TOOLKIT
9794 if (! FRAME_VISIBLE_P (f))
9796 if (! EQ (Vx_no_window_manager, Qt))
9797 x_wm_set_window_state (f, IconicState);
9798 /* This was XtPopup, but that did nothing for an iconified frame. */
9799 XtMapWidget (f->output_data.x->widget);
9800 /* The server won't give us any event to indicate
9801 that an invisible frame was changed to an icon,
9802 so we have to record it here. */
9803 f->iconified = 1;
9804 f->visible = 1;
9805 f->async_iconified = 1;
9806 f->async_visible = 0;
9807 UNBLOCK_INPUT;
9808 return;
9811 result = XIconifyWindow (FRAME_X_DISPLAY (f),
9812 XtWindow (f->output_data.x->widget),
9813 DefaultScreen (FRAME_X_DISPLAY (f)));
9814 UNBLOCK_INPUT;
9816 if (!result)
9817 error ("Can't notify window manager of iconification");
9819 f->async_iconified = 1;
9820 f->async_visible = 0;
9823 BLOCK_INPUT;
9824 XFlush (FRAME_X_DISPLAY (f));
9825 UNBLOCK_INPUT;
9826 #else /* not USE_X_TOOLKIT */
9828 /* Make sure the X server knows where the window should be positioned,
9829 in case the user deiconifies with the window manager. */
9830 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
9831 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
9833 /* Since we don't know which revision of X we're running, we'll use both
9834 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9836 /* X11R4: send a ClientMessage to the window manager using the
9837 WM_CHANGE_STATE type. */
9839 XEvent message;
9841 message.xclient.window = FRAME_X_WINDOW (f);
9842 message.xclient.type = ClientMessage;
9843 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
9844 message.xclient.format = 32;
9845 message.xclient.data.l[0] = IconicState;
9847 if (! XSendEvent (FRAME_X_DISPLAY (f),
9848 DefaultRootWindow (FRAME_X_DISPLAY (f)),
9849 False,
9850 SubstructureRedirectMask | SubstructureNotifyMask,
9851 &message))
9853 UNBLOCK_INPUT_RESIGNAL;
9854 error ("Can't notify window manager of iconification");
9858 /* X11R3: set the initial_state field of the window manager hints to
9859 IconicState. */
9860 x_wm_set_window_state (f, IconicState);
9862 if (!FRAME_VISIBLE_P (f))
9864 /* If the frame was withdrawn, before, we must map it. */
9865 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9868 f->async_iconified = 1;
9869 f->async_visible = 0;
9871 XFlush (FRAME_X_DISPLAY (f));
9872 UNBLOCK_INPUT;
9873 #endif /* not USE_X_TOOLKIT */
9874 #endif
9877 /* Destroy the X window of frame F. */
9879 void
9880 x_destroy_window (f)
9881 struct frame *f;
9883 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9885 BLOCK_INPUT;
9887 DisposeWindow (FRAME_MAC_WINDOW (f));
9889 free_frame_menubar (f);
9890 free_frame_faces (f);
9892 xfree (f->output_data.mac);
9893 f->output_data.mac = 0;
9894 if (f == dpyinfo->x_focus_frame)
9895 dpyinfo->x_focus_frame = 0;
9896 if (f == dpyinfo->x_focus_event_frame)
9897 dpyinfo->x_focus_event_frame = 0;
9898 if (f == dpyinfo->x_highlight_frame)
9899 dpyinfo->x_highlight_frame = 0;
9901 dpyinfo->reference_count--;
9903 if (f == dpyinfo->mouse_face_mouse_frame)
9905 dpyinfo->mouse_face_beg_row
9906 = dpyinfo->mouse_face_beg_col = -1;
9907 dpyinfo->mouse_face_end_row
9908 = dpyinfo->mouse_face_end_col = -1;
9909 dpyinfo->mouse_face_window = Qnil;
9910 dpyinfo->mouse_face_deferred_gc = 0;
9911 dpyinfo->mouse_face_mouse_frame = 0;
9914 UNBLOCK_INPUT;
9917 /* Setting window manager hints. */
9919 /* Set the normal size hints for the window manager, for frame F.
9920 FLAGS is the flags word to use--or 0 meaning preserve the flags
9921 that the window now has.
9922 If USER_POSITION is nonzero, we set the USPosition
9923 flag (this is useful when FLAGS is 0). */
9925 void
9926 x_wm_set_size_hint (f, flags, user_position)
9927 struct frame *f;
9928 long flags;
9929 int user_position;
9931 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
9932 XSizeHints size_hints;
9934 #ifdef USE_X_TOOLKIT
9935 Arg al[2];
9936 int ac = 0;
9937 Dimension widget_width, widget_height;
9938 Window window = XtWindow (f->output_data.x->widget);
9939 #else /* not USE_X_TOOLKIT */
9940 Window window = FRAME_X_WINDOW (f);
9941 #endif /* not USE_X_TOOLKIT */
9943 /* Setting PMaxSize caused various problems. */
9944 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
9946 size_hints.x = f->output_data.x->left_pos;
9947 size_hints.y = f->output_data.x->top_pos;
9949 #ifdef USE_X_TOOLKIT
9950 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
9951 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
9952 XtGetValues (f->output_data.x->widget, al, ac);
9953 size_hints.height = widget_height;
9954 size_hints.width = widget_width;
9955 #else /* not USE_X_TOOLKIT */
9956 size_hints.height = PIXEL_HEIGHT (f);
9957 size_hints.width = PIXEL_WIDTH (f);
9958 #endif /* not USE_X_TOOLKIT */
9960 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
9961 size_hints.height_inc = f->output_data.x->line_height;
9962 size_hints.max_width
9963 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
9964 size_hints.max_height
9965 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
9967 /* Calculate the base and minimum sizes.
9969 (When we use the X toolkit, we don't do it here.
9970 Instead we copy the values that the widgets are using, below.) */
9971 #ifndef USE_X_TOOLKIT
9973 int base_width, base_height;
9974 int min_rows = 0, min_cols = 0;
9976 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
9977 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
9979 check_frame_size (f, &min_rows, &min_cols);
9981 /* The window manager uses the base width hints to calculate the
9982 current number of rows and columns in the frame while
9983 resizing; min_width and min_height aren't useful for this
9984 purpose, since they might not give the dimensions for a
9985 zero-row, zero-column frame.
9987 We use the base_width and base_height members if we have
9988 them; otherwise, we set the min_width and min_height members
9989 to the size for a zero x zero frame. */
9991 #ifdef HAVE_X11R4
9992 size_hints.flags |= PBaseSize;
9993 size_hints.base_width = base_width;
9994 size_hints.base_height = base_height;
9995 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
9996 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
9997 #else
9998 size_hints.min_width = base_width;
9999 size_hints.min_height = base_height;
10000 #endif
10003 /* If we don't need the old flags, we don't need the old hint at all. */
10004 if (flags)
10006 size_hints.flags |= flags;
10007 goto no_read;
10009 #endif /* not USE_X_TOOLKIT */
10012 XSizeHints hints; /* Sometimes I hate X Windows... */
10013 long supplied_return;
10014 int value;
10016 #ifdef HAVE_X11R4
10017 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10018 &supplied_return);
10019 #else
10020 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10021 #endif
10023 #ifdef USE_X_TOOLKIT
10024 size_hints.base_height = hints.base_height;
10025 size_hints.base_width = hints.base_width;
10026 size_hints.min_height = hints.min_height;
10027 size_hints.min_width = hints.min_width;
10028 #endif
10030 if (flags)
10031 size_hints.flags |= flags;
10032 else
10034 if (value == 0)
10035 hints.flags = 0;
10036 if (hints.flags & PSize)
10037 size_hints.flags |= PSize;
10038 if (hints.flags & PPosition)
10039 size_hints.flags |= PPosition;
10040 if (hints.flags & USPosition)
10041 size_hints.flags |= USPosition;
10042 if (hints.flags & USSize)
10043 size_hints.flags |= USSize;
10047 #ifndef USE_X_TOOLKIT
10048 no_read:
10049 #endif
10051 #ifdef PWinGravity
10052 size_hints.win_gravity = f->output_data.x->win_gravity;
10053 size_hints.flags |= PWinGravity;
10055 if (user_position)
10057 size_hints.flags &= ~ PPosition;
10058 size_hints.flags |= USPosition;
10060 #endif /* PWinGravity */
10062 #ifdef HAVE_X11R4
10063 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10064 #else
10065 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10066 #endif
10067 #endif /* MACTODO */
10070 #if 0 /* MACTODO: hide application instead of iconify? */
10071 /* Used for IconicState or NormalState */
10073 void
10074 x_wm_set_window_state (f, state)
10075 struct frame *f;
10076 int state;
10078 #ifdef USE_X_TOOLKIT
10079 Arg al[1];
10081 XtSetArg (al[0], XtNinitialState, state);
10082 XtSetValues (f->output_data.x->widget, al, 1);
10083 #else /* not USE_X_TOOLKIT */
10084 Window window = FRAME_X_WINDOW (f);
10086 f->output_data.x->wm_hints.flags |= StateHint;
10087 f->output_data.x->wm_hints.initial_state = state;
10089 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10090 #endif /* not USE_X_TOOLKIT */
10093 void
10094 x_wm_set_icon_pixmap (f, pixmap_id)
10095 struct frame *f;
10096 int pixmap_id;
10098 Pixmap icon_pixmap;
10100 #ifndef USE_X_TOOLKIT
10101 Window window = FRAME_X_WINDOW (f);
10102 #endif
10104 if (pixmap_id > 0)
10106 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10107 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10109 else
10111 /* It seems there is no way to turn off use of an icon pixmap.
10112 The following line does it, only if no icon has yet been created,
10113 for some window managers. But with mwm it crashes.
10114 Some people say it should clear the IconPixmapHint bit in this case,
10115 but that doesn't work, and the X consortium said it isn't the
10116 right thing at all. Since there is no way to win,
10117 best to explicitly give up. */
10118 #if 0
10119 f->output_data.x->wm_hints.icon_pixmap = None;
10120 #else
10121 return;
10122 #endif
10125 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10128 Arg al[1];
10129 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10130 XtSetValues (f->output_data.x->widget, al, 1);
10133 #else /* not USE_X_TOOLKIT */
10135 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10136 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10138 #endif /* not USE_X_TOOLKIT */
10141 #endif
10143 void
10144 x_wm_set_icon_position (f, icon_x, icon_y)
10145 struct frame *f;
10146 int icon_x, icon_y;
10148 #if 0 /* MAC_TODO: no icons on Mac */
10149 #ifdef USE_X_TOOLKIT
10150 Window window = XtWindow (f->output_data.x->widget);
10151 #else
10152 Window window = FRAME_X_WINDOW (f);
10153 #endif
10155 f->output_data.x->wm_hints.flags |= IconPositionHint;
10156 f->output_data.x->wm_hints.icon_x = icon_x;
10157 f->output_data.x->wm_hints.icon_y = icon_y;
10159 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10160 #endif
10164 /***********************************************************************
10165 Fonts
10166 ***********************************************************************/
10168 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10170 struct font_info *
10171 x_get_font_info (f, font_idx)
10172 FRAME_PTR f;
10173 int font_idx;
10175 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10178 /* the global font name table */
10179 char **font_name_table = NULL;
10180 int font_name_table_size = 0;
10181 int font_name_count = 0;
10183 /* compare two strings ignoring case */
10184 static int
10185 stricmp (const char *s, const char *t)
10187 for ( ; tolower (*s) == tolower (*t); s++, t++)
10188 if (*s == '\0')
10189 return 0;
10190 return tolower (*s) - tolower (*t);
10193 /* compare two strings ignoring case and handling wildcard */
10194 static int
10195 wildstrieq (char *s1, char *s2)
10197 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10198 return true;
10200 return stricmp (s1, s2) == 0;
10203 /* Assume parameter 1 is fully qualified, no wildcards. */
10204 static int
10205 mac_font_pattern_match (fontname, pattern)
10206 char * fontname;
10207 char * pattern;
10209 char *regex = (char *) alloca (strlen (pattern) * 2);
10210 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10211 char *ptr;
10213 /* Copy fontname so we can modify it during comparison. */
10214 strcpy (font_name_copy, fontname);
10216 ptr = regex;
10217 *ptr++ = '^';
10219 /* Turn pattern into a regexp and do a regexp match. */
10220 for (; *pattern; pattern++)
10222 if (*pattern == '?')
10223 *ptr++ = '.';
10224 else if (*pattern == '*')
10226 *ptr++ = '.';
10227 *ptr++ = '*';
10229 else
10230 *ptr++ = *pattern;
10232 *ptr = '$';
10233 *(ptr + 1) = '\0';
10235 return (fast_c_string_match_ignore_case (build_string (regex),
10236 font_name_copy) >= 0);
10239 /* Two font specs are considered to match if their foundry, family,
10240 weight, slant, and charset match. */
10241 static int
10242 mac_font_match (char *mf, char *xf)
10244 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10245 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10247 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10248 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10249 return mac_font_pattern_match (mf, xf);
10251 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10252 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10253 return mac_font_pattern_match (mf, xf);
10255 return (wildstrieq (m_foundry, x_foundry)
10256 && wildstrieq (m_family, x_family)
10257 && wildstrieq (m_weight, x_weight)
10258 && wildstrieq (m_slant, x_slant)
10259 && wildstrieq (m_charset, x_charset))
10260 || mac_font_pattern_match (mf, xf);
10264 static char *
10265 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10267 char foundry[32], family[32], cs[32];
10268 char xf[255], *result, *p;
10270 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10272 strcpy(foundry, "Apple");
10273 strcpy(family, name);
10275 switch (scriptcode)
10277 case smTradChinese:
10278 strcpy(cs, "big5-0");
10279 break;
10280 case smSimpChinese:
10281 strcpy(cs, "gb2312-0");
10282 break;
10283 case smJapanese:
10284 strcpy(cs, "jisx0208.1983-sjis");
10285 break;
10286 case smKorean:
10287 strcpy(cs, "ksc5601-0");
10288 break;
10289 default:
10290 strcpy(cs, "mac-roman");
10291 break;
10295 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10296 foundry, family, style & bold ? "bold" : "medium",
10297 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10299 result = (char *) xmalloc (strlen (xf) + 1);
10300 strcpy (result, xf);
10301 for (p = result; *p; p++)
10302 *p = tolower(*p);
10303 return result;
10307 /* Convert an X font spec to the corresponding mac font name, which
10308 can then be passed to GetFNum after conversion to a Pascal string.
10309 For ordinary Mac fonts, this should just be their names, like
10310 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10311 collection contain their charset designation in their names, like
10312 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10313 names are handled accordingly. */
10314 static void
10315 x_font_name_to_mac_font_name (char *xf, char *mf)
10317 char foundry[32], family[32], weight[20], slant[2], cs[32];
10319 strcpy (mf, "");
10321 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10322 foundry, family, weight, slant, cs) != 5 &&
10323 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10324 foundry, family, weight, slant, cs) != 5)
10325 return;
10327 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312-0") == 0
10328 || strcmp (cs, "jisx0208.1983-sjis") == 0
10329 || strcmp (cs, "ksc5601-0") == 0 || strcmp (cs, "mac-roman") == 0)
10330 strcpy(mf, family);
10331 else
10332 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10336 /* Sets up the table font_name_table to contain the list of all
10337 monospace fonts in the system the first time the table is used so
10338 that the Resource Manager need not be accessed every time this
10339 information is needed. */
10341 static void
10342 init_font_name_table ()
10344 GrafPtr port;
10345 SInt16 fontnum, old_fontnum;
10346 int num_mac_fonts = CountResources('FOND');
10347 int i, j;
10348 Handle font_handle, font_handle_2;
10349 short id, scriptcode;
10350 ResType type;
10351 Str32 name;
10352 struct FontAssoc *fat;
10353 struct AsscEntry *assc_entry;
10355 GetPort (&port); /* save the current font number used */
10356 old_fontnum = port->txFont;
10358 for (i = 1; i <= num_mac_fonts; i++) /* loop to get all available fonts */
10360 font_handle = GetIndResource ('FOND', i);
10361 if (!font_handle)
10362 continue;
10364 GetResInfo (font_handle, &id, &type, name);
10365 GetFNum (name, &fontnum);
10366 p2cstr (name);
10367 if (fontnum == 0)
10368 continue;
10370 TextFont (fontnum);
10371 scriptcode = FontToScript (fontnum);
10374 HLock (font_handle);
10376 if (GetResourceSizeOnDisk (font_handle) >= sizeof (struct FamRec))
10378 fat = (struct FontAssoc *) (*font_handle
10379 + sizeof (struct FamRec));
10380 assc_entry = (struct AsscEntry *) (*font_handle
10381 + sizeof (struct FamRec)
10382 + sizeof (struct FontAssoc));
10384 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10386 if (font_name_table_size == 0)
10388 font_name_table_size = 16;
10389 font_name_table = (char **)
10390 xmalloc (font_name_table_size * sizeof (char *));
10392 else if (font_name_count >= font_name_table_size)
10394 font_name_table_size += 16;
10395 font_name_table = (char **)
10396 xrealloc (font_name_table,
10397 font_name_table_size * sizeof (char *));
10399 font_name_table[font_name_count++]
10400 = mac_to_x_fontname (name,
10401 assc_entry->fontSize,
10402 assc_entry->fontStyle,
10403 scriptcode);
10407 HUnlock (font_handle);
10408 font_handle_2 = GetNextFOND (font_handle);
10409 ReleaseResource (font_handle);
10410 font_handle = font_handle_2;
10412 while (ResError () == noErr && font_handle);
10415 TextFont (old_fontnum);
10419 /* Return a list of at most MAXNAMES font specs matching the one in
10420 PATTERN. Note that each '*' in the PATTERN matches exactly one
10421 field of the font spec, unlike X in which an '*' in a font spec can
10422 match a number of fields. The result is in the Mac implementation
10423 all fonts must be specified by a font spec with all 13 fields
10424 (although many of these can be "*'s"). */
10426 Lisp_Object
10427 x_list_fonts (struct frame *f,
10428 Lisp_Object pattern,
10429 int size,
10430 int maxnames)
10432 char *ptnstr;
10433 Lisp_Object newlist = Qnil;
10434 int n_fonts = 0;
10435 int i;
10437 if (font_name_table == NULL) /* Initialize when first used. */
10438 init_font_name_table ();
10440 ptnstr = XSTRING (pattern)->data;
10442 /* Scan and matching bitmap fonts. */
10443 for (i = 0; i < font_name_count; i++)
10445 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10447 newlist = Fcons (build_string (font_name_table[i]), newlist);
10449 n_fonts++;
10450 if (n_fonts >= maxnames)
10451 break;
10455 /* MAC_TODO: add code for matching outline fonts here */
10457 return newlist;
10461 #if GLYPH_DEBUG
10463 /* Check that FONT is valid on frame F. It is if it can be found in
10464 F's font table. */
10466 static void
10467 x_check_font (f, font)
10468 struct frame *f;
10469 XFontStruct *font;
10471 int i;
10472 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10474 xassert (font != NULL);
10476 for (i = 0; i < dpyinfo->n_fonts; i++)
10477 if (dpyinfo->font_table[i].name
10478 && font == dpyinfo->font_table[i].font)
10479 break;
10481 xassert (i < dpyinfo->n_fonts);
10484 #endif /* GLYPH_DEBUG != 0 */
10487 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10488 Note: There are (broken) X fonts out there with invalid XFontStruct
10489 min_bounds contents. For example, handa@etl.go.jp reports that
10490 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10491 have font->min_bounds.width == 0. */
10493 static INLINE void
10494 x_font_min_bounds (font, w, h)
10495 MacFontStruct *font;
10496 int *w, *h;
10498 *h = FONT_HEIGHT (font);
10499 *w = font->min_bounds.width;
10501 /* Try to handle the case where FONT->min_bounds has invalid
10502 contents. Since the only font known to have invalid min_bounds
10503 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
10504 if (*w <= 0)
10505 *w = font->max_bounds.width;
10509 /* Compute the smallest character width and smallest font height over
10510 all fonts available on frame F. Set the members smallest_char_width
10511 and smallest_font_height in F's x_display_info structure to
10512 the values computed. Value is non-zero if smallest_font_height or
10513 smallest_char_width become smaller than they were before. */
10515 static int
10516 x_compute_min_glyph_bounds (f)
10517 struct frame *f;
10519 int i;
10520 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10521 MacFontStruct *font;
10522 int old_width = dpyinfo->smallest_char_width;
10523 int old_height = dpyinfo->smallest_font_height;
10525 dpyinfo->smallest_font_height = 100000;
10526 dpyinfo->smallest_char_width = 100000;
10528 for (i = 0; i < dpyinfo->n_fonts; ++i)
10529 if (dpyinfo->font_table[i].name)
10531 struct font_info *fontp = dpyinfo->font_table + i;
10532 int w, h;
10534 font = (MacFontStruct *) fontp->font;
10535 xassert (font != (MacFontStruct *) ~0);
10536 x_font_min_bounds (font, &w, &h);
10538 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10539 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10542 xassert (dpyinfo->smallest_char_width > 0
10543 && dpyinfo->smallest_font_height > 0);
10545 return (dpyinfo->n_fonts == 1
10546 || dpyinfo->smallest_char_width < old_width
10547 || dpyinfo->smallest_font_height < old_height);
10551 /* Determine whether given string is a fully-specified XLFD: all 14
10552 fields are present, none is '*'. */
10554 static int
10555 is_fully_specified_xlfd (char *p)
10557 int i;
10558 char *q;
10560 if (*p != '-')
10561 return 0;
10563 for (i = 0; i < 13; i++)
10565 q = strchr (p + 1, '-');
10566 if (q == NULL)
10567 return 0;
10568 if (q - p == 2 && *(p + 1) == '*')
10569 return 0;
10570 p = q;
10573 if (strchr (p + 1, '-') != NULL)
10574 return 0;
10576 if (*(p + 1) == '*' && *(p + 2) == '\0')
10577 return 0;
10579 return 1;
10583 const int kDefaultFontSize = 9;
10586 /* MacLoadQueryFont creates and returns an internal representation for
10587 a font in a MacFontStruct struct (similar in function to
10588 XLoadQueryFont in X). There is really no concept corresponding to
10589 "loading" a font on the Mac. But we check its existence and find
10590 the font number and all other information for it and store them in
10591 the returned MacFontStruct. */
10593 static MacFontStruct *
10594 XLoadQueryFont (Display *dpy, char *fontname)
10596 int i, size, is_two_byte_font, char_width;
10597 char *name;
10598 GrafPtr port;
10599 SInt16 old_fontnum, old_fontsize;
10600 Style old_fontface;
10601 Str32 mfontname;
10602 SInt16 fontnum;
10603 Style fontface = normal;
10604 MacFontStruct *font;
10605 FontInfo the_fontinfo;
10606 char s_weight[7], c_slant;
10608 if (is_fully_specified_xlfd (fontname))
10609 name = fontname;
10610 else
10612 for (i = 0; i < font_name_count; i++)
10613 if (mac_font_pattern_match (font_name_table[i], fontname))
10614 break;
10616 if (i >= font_name_count)
10617 return NULL;
10619 name = font_name_table[i];
10622 GetPort (&port); /* save the current font number used */
10623 old_fontnum = port->txFont;
10624 old_fontsize = port->txSize;
10625 old_fontface = port->txFace;
10627 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
10628 size = kDefaultFontSize;
10630 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
10631 if (strcmp (s_weight, "bold") == 0)
10632 fontface |= bold;
10634 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
10635 if (c_slant == 'i')
10636 fontface |= italic;
10638 x_font_name_to_mac_font_name (name, mfontname);
10639 c2pstr (mfontname);
10640 GetFNum (mfontname, &fontnum);
10641 if (fontnum == 0)
10642 return NULL;
10644 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
10646 font->fontname = (char *) xmalloc (strlen (name) + 1);
10647 bcopy (name, font->fontname, strlen (name) + 1);
10649 font->mac_fontnum = fontnum;
10650 font->mac_fontsize = size;
10651 font->mac_fontface = fontface;
10652 font->mac_scriptcode = FontToScript (fontnum);
10654 is_two_byte_font = font->mac_scriptcode == smJapanese ||
10655 font->mac_scriptcode == smTradChinese ||
10656 font->mac_scriptcode == smSimpChinese ||
10657 font->mac_scriptcode == smKorean;
10659 TextFont (fontnum);
10660 TextSize (size);
10661 TextFace (fontface);
10663 GetFontInfo (&the_fontinfo);
10665 font->ascent = the_fontinfo.ascent;
10666 font->descent = the_fontinfo.descent;
10668 font->min_byte1 = 0;
10669 if (is_two_byte_font)
10670 font->max_byte1 = 1;
10671 else
10672 font->max_byte1 = 0;
10673 font->min_char_or_byte2 = 0x20;
10674 font->max_char_or_byte2 = 0xff;
10676 if (is_two_byte_font)
10678 /* Use the width of an "ideographic space" of that font because
10679 the_fontinfo.widMax returns the wrong width for some fonts. */
10680 switch (font->mac_scriptcode)
10682 case smJapanese:
10683 char_width = StringWidth("\p\x81\x40");
10684 break;
10685 case smTradChinese:
10686 char_width = StringWidth("\p\xa1\x40");
10687 break;
10688 case smSimpChinese:
10689 char_width = StringWidth("\p\xa1\xa1");
10690 break;
10691 case smKorean:
10692 char_width = StringWidth("\p\xa1\xa1");
10693 break;
10696 else
10697 /* Do this instead of use the_fontinfo.widMax, which incorrectly
10698 returns 15 for 12-point Monaco! */
10699 char_width = CharWidth ('m');
10701 font->max_bounds.rbearing = char_width;
10702 font->max_bounds.lbearing = 0;
10703 font->max_bounds.width = char_width;
10704 font->max_bounds.ascent = the_fontinfo.ascent;
10705 font->max_bounds.descent = the_fontinfo.descent;
10707 font->min_bounds = font->max_bounds;
10709 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
10710 font->per_char = NULL;
10711 else
10713 font->per_char = (XCharStruct *)
10714 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
10716 int c;
10718 for (c = 0x20; c <= 0xff; c++)
10720 font->per_char[c - 0x20] = font->max_bounds;
10721 font->per_char[c - 0x20].width = CharWidth (c);
10726 TextFont (old_fontnum); /* restore previous font number, size and face */
10727 TextSize (old_fontsize);
10728 TextFace (old_fontface);
10730 return font;
10734 /* Load font named FONTNAME of the size SIZE for frame F, and return a
10735 pointer to the structure font_info while allocating it dynamically.
10736 If SIZE is 0, load any size of font.
10737 If loading is failed, return NULL. */
10739 struct font_info *
10740 x_load_font (f, fontname, size)
10741 struct frame *f;
10742 register char *fontname;
10743 int size;
10745 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10746 Lisp_Object font_names;
10748 /* Get a list of all the fonts that match this name. Once we
10749 have a list of matching fonts, we compare them against the fonts
10750 we already have by comparing names. */
10751 font_names = x_list_fonts (f, build_string (fontname), size, 1);
10753 if (!NILP (font_names))
10755 Lisp_Object tail;
10756 int i;
10758 for (i = 0; i < dpyinfo->n_fonts; i++)
10759 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
10760 if (dpyinfo->font_table[i].name
10761 && (!strcmp (dpyinfo->font_table[i].name,
10762 XSTRING (XCAR (tail))->data)
10763 || !strcmp (dpyinfo->font_table[i].full_name,
10764 XSTRING (XCAR (tail))->data)))
10765 return (dpyinfo->font_table + i);
10768 /* Load the font and add it to the table. */
10770 char *full_name;
10771 struct MacFontStruct *font;
10772 struct font_info *fontp;
10773 unsigned long value;
10774 int i;
10776 /* If we have found fonts by x_list_font, load one of them. If
10777 not, we still try to load a font by the name given as FONTNAME
10778 because XListFonts (called in x_list_font) of some X server has
10779 a bug of not finding a font even if the font surely exists and
10780 is loadable by XLoadQueryFont. */
10781 if (size > 0 && !NILP (font_names))
10782 fontname = (char *) XSTRING (XCAR (font_names))->data;
10784 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
10785 if (!font)
10786 return NULL;
10788 /* Find a free slot in the font table. */
10789 for (i = 0; i < dpyinfo->n_fonts; ++i)
10790 if (dpyinfo->font_table[i].name == NULL)
10791 break;
10793 /* If no free slot found, maybe enlarge the font table. */
10794 if (i == dpyinfo->n_fonts
10795 && dpyinfo->n_fonts == dpyinfo->font_table_size)
10797 int sz;
10798 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
10799 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
10800 dpyinfo->font_table
10801 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
10804 fontp = dpyinfo->font_table + i;
10805 if (i == dpyinfo->n_fonts)
10806 ++dpyinfo->n_fonts;
10808 /* Now fill in the slots of *FONTP. */
10809 BLOCK_INPUT;
10810 fontp->font = font;
10811 fontp->font_idx = i;
10812 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
10813 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
10815 fontp->full_name = fontp->name;
10817 fontp->size = font->max_bounds.width;
10818 fontp->height = FONT_HEIGHT (font);
10820 /* For some font, ascent and descent in max_bounds field is
10821 larger than the above value. */
10822 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
10823 if (max_height > fontp->height)
10824 fontp->height = max_height;
10827 /* The slot `encoding' specifies how to map a character
10828 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
10829 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
10830 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
10831 2:0xA020..0xFF7F). For the moment, we don't know which charset
10832 uses this font. So, we set information in fontp->encoding[1]
10833 which is never used by any charset. If mapping can't be
10834 decided, set FONT_ENCODING_NOT_DECIDED. */
10835 if (font->mac_scriptcode == smJapanese)
10836 fontp->encoding[1] = 4;
10837 else
10839 fontp->encoding[1]
10840 = (font->max_byte1 == 0
10841 /* 1-byte font */
10842 ? (font->min_char_or_byte2 < 0x80
10843 ? (font->max_char_or_byte2 < 0x80
10844 ? 0 /* 0x20..0x7F */
10845 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
10846 : 1) /* 0xA0..0xFF */
10847 /* 2-byte font */
10848 : (font->min_byte1 < 0x80
10849 ? (font->max_byte1 < 0x80
10850 ? (font->min_char_or_byte2 < 0x80
10851 ? (font->max_char_or_byte2 < 0x80
10852 ? 0 /* 0x2020..0x7F7F */
10853 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
10854 : 3) /* 0x20A0..0x7FFF */
10855 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
10856 : (font->min_char_or_byte2 < 0x80
10857 ? (font->max_char_or_byte2 < 0x80
10858 ? 2 /* 0xA020..0xFF7F */
10859 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
10860 : 1))); /* 0xA0A0..0xFFFF */
10863 #if 0 /* MAC_TODO: fill these out with more reasonably values */
10864 fontp->baseline_offset
10865 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
10866 ? (long) value : 0);
10867 fontp->relative_compose
10868 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
10869 ? (long) value : 0);
10870 fontp->default_ascent
10871 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
10872 ? (long) value : 0);
10873 #else
10874 fontp->baseline_offset = 0;
10875 fontp->relative_compose = 0;
10876 fontp->default_ascent = 0;
10877 #endif
10879 /* Set global flag fonts_changed_p to non-zero if the font loaded
10880 has a character with a smaller width than any other character
10881 before, or if the font loaded has a smalle>r height than any
10882 other font loaded before. If this happens, it will make a
10883 glyph matrix reallocation necessary. */
10884 fonts_changed_p = x_compute_min_glyph_bounds (f);
10885 UNBLOCK_INPUT;
10886 return fontp;
10891 /* Return a pointer to struct font_info of a font named FONTNAME for
10892 frame F. If no such font is loaded, return NULL. */
10894 struct font_info *
10895 x_query_font (f, fontname)
10896 struct frame *f;
10897 register char *fontname;
10899 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10900 int i;
10902 for (i = 0; i < dpyinfo->n_fonts; i++)
10903 if (dpyinfo->font_table[i].name
10904 && (!strcmp (dpyinfo->font_table[i].name, fontname)
10905 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
10906 return (dpyinfo->font_table + i);
10907 return NULL;
10911 /* Find a CCL program for a font specified by FONTP, and set the member
10912 `encoder' of the structure. */
10914 void
10915 x_find_ccl_program (fontp)
10916 struct font_info *fontp;
10918 Lisp_Object list, elt;
10920 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
10922 elt = XCAR (list);
10923 if (CONSP (elt)
10924 && STRINGP (XCAR (elt))
10925 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
10926 >= 0))
10927 break;
10929 if (! NILP (list))
10931 struct ccl_program *ccl
10932 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
10934 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
10935 xfree (ccl);
10936 else
10937 fontp->font_encoder = ccl;
10943 /***********************************************************************
10944 Initialization
10945 ***********************************************************************/
10947 #ifdef USE_X_TOOLKIT
10948 static XrmOptionDescRec emacs_options[] = {
10949 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
10950 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
10952 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
10953 XrmoptionSepArg, NULL},
10954 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
10956 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
10957 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
10958 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
10959 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
10960 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
10961 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
10962 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
10964 #endif /* USE_X_TOOLKIT */
10966 static int x_initialized;
10968 #ifdef MULTI_KBOARD
10969 /* Test whether two display-name strings agree up to the dot that separates
10970 the screen number from the server number. */
10971 static int
10972 same_x_server (name1, name2)
10973 char *name1, *name2;
10975 int seen_colon = 0;
10976 unsigned char *system_name = XSTRING (Vsystem_name)->data;
10977 int system_name_length = strlen (system_name);
10978 int length_until_period = 0;
10980 while (system_name[length_until_period] != 0
10981 && system_name[length_until_period] != '.')
10982 length_until_period++;
10984 /* Treat `unix' like an empty host name. */
10985 if (! strncmp (name1, "unix:", 5))
10986 name1 += 4;
10987 if (! strncmp (name2, "unix:", 5))
10988 name2 += 4;
10989 /* Treat this host's name like an empty host name. */
10990 if (! strncmp (name1, system_name, system_name_length)
10991 && name1[system_name_length] == ':')
10992 name1 += system_name_length;
10993 if (! strncmp (name2, system_name, system_name_length)
10994 && name2[system_name_length] == ':')
10995 name2 += system_name_length;
10996 /* Treat this host's domainless name like an empty host name. */
10997 if (! strncmp (name1, system_name, length_until_period)
10998 && name1[length_until_period] == ':')
10999 name1 += length_until_period;
11000 if (! strncmp (name2, system_name, length_until_period)
11001 && name2[length_until_period] == ':')
11002 name2 += length_until_period;
11004 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11006 if (*name1 == ':')
11007 seen_colon++;
11008 if (seen_colon && *name1 == '.')
11009 return 1;
11011 return (seen_colon
11012 && (*name1 == '.' || *name1 == '\0')
11013 && (*name2 == '.' || *name2 == '\0'));
11015 #endif
11017 struct mac_display_info *
11018 x_term_init (display_name, xrm_option, resource_name)
11019 Lisp_Object display_name;
11020 char *xrm_option;
11021 char *resource_name;
11023 if (!x_initialized)
11025 x_initialize ();
11026 x_initialized = 1;
11029 return &one_mac_display_info;
11032 /* Set up use of X before we make the first connection. */
11034 static struct redisplay_interface x_redisplay_interface =
11036 x_produce_glyphs,
11037 x_write_glyphs,
11038 x_insert_glyphs,
11039 x_clear_end_of_line,
11040 x_scroll_run,
11041 x_after_update_window_line,
11042 x_update_window_begin,
11043 x_update_window_end,
11044 XTcursor_to,
11045 x_flush,
11046 x_clear_mouse_face,
11047 x_get_glyph_overhangs,
11048 x_fix_overlapping_area
11052 /* The Mac Event loop code */
11054 #include <Events.h>
11055 #include <Quickdraw.h>
11056 #include <Balloons.h>
11057 #include <Devices.h>
11058 #include <Fonts.h>
11059 #include <Gestalt.h>
11060 #include <Menus.h>
11061 #include <Processes.h>
11062 #include <Sound.h>
11063 #include <ToolUtils.h>
11064 #include <TextUtils.h>
11065 #include <Dialogs.h>
11066 #include <Script.h>
11067 #include <Scrap.h>
11068 #include <Types.h>
11069 #include <TextEncodingConverter.h>
11070 #include <Resources.h>
11072 #if __MWERKS__
11073 #include <unix.h>
11074 #endif
11076 #define M_APPLE 128
11077 #define I_ABOUT 1
11079 #define WINDOW_RESOURCE 128
11080 #define TERM_WINDOW_RESOURCE 129
11082 #define DEFAULT_NUM_COLS 80
11084 #define MIN_DOC_SIZE 64
11085 #define MAX_DOC_SIZE 32767
11087 /* sleep time for WaitNextEvent */
11088 #define WNE_SLEEP_AT_SUSPEND 10
11089 #define WNE_SLEEP_AT_RESUME 1
11091 /* true when cannot handle any Mac OS events */
11092 static int handling_window_update = 0;
11094 /* the flag appl_is_suspended is used both for determining the sleep
11095 time to be passed to WaitNextEvent and whether the cursor should be
11096 drawn when updating the display. The cursor is turned off when
11097 Emacs is suspended. Redrawing it is unnecessary and what needs to
11098 be done depends on whether the cursor lies inside or outside the
11099 redraw region. So we might as well skip drawing it when Emacs is
11100 suspended. */
11101 static Boolean app_is_suspended = false;
11102 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11104 #define EXTRA_STACK_ALLOC (256 * 1024)
11106 #define ARGV_STRING_LIST_ID 129
11107 #define ABOUT_ALERT_ID 128
11109 Boolean terminate_flag = false;
11111 /* true if using command key as meta key */
11112 Lisp_Object Vmac_command_key_is_meta;
11114 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11115 to this text encoding */
11116 int mac_keyboard_text_encoding;
11117 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11119 /* Set in term/mac-win.el to indicate that event loop can now generate
11120 drag and drop events. */
11121 Lisp_Object Qmac_ready_for_drag_n_drop;
11123 Lisp_Object drag_and_drop_file_list;
11125 Point saved_menu_event_location;
11127 /* Apple Events */
11128 static void init_required_apple_events(void);
11129 static pascal OSErr do_ae_open_application(const AppleEvent *, AppleEvent *, long);
11130 static pascal OSErr do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
11131 static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
11132 static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
11134 extern void init_emacs_passwd_dir ();
11135 extern int emacs_main (int, char **, char **);
11136 extern void check_alarm ();
11138 extern void initialize_applescript();
11139 extern void terminate_applescript();
11142 static void
11143 do_get_menus (void)
11145 Handle menubar_handle;
11146 MenuHandle menu_handle;
11148 menubar_handle = GetNewMBar (128);
11149 if(menubar_handle == NULL)
11150 abort ();
11151 SetMenuBar (menubar_handle);
11152 DrawMenuBar ();
11154 menu_handle = GetMenuHandle (M_APPLE);
11155 if(menu_handle != NULL)
11156 AppendResMenu (menu_handle,'DRVR');
11157 else
11158 abort ();
11162 static void
11163 do_init_managers (void)
11165 InitGraf (&qd.thePort);
11166 InitFonts ();
11167 FlushEvents (everyEvent, 0);
11168 InitWindows ();
11169 InitMenus ();
11170 TEInit ();
11171 InitDialogs (NULL);
11172 InitCursor ();
11174 /* set up some extra stack space for use by emacs */
11175 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11177 /* MaxApplZone must be called for AppleScript to execute more
11178 complicated scripts */
11179 MaxApplZone ();
11180 MoreMasters ();
11184 static void
11185 do_window_update (WindowPtr win)
11187 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11188 struct frame *f = mwp->mFP;
11190 if (f)
11192 if (f->async_visible == 0)
11194 f->async_visible = 1;
11195 f->async_iconified = 0;
11196 SET_FRAME_GARBAGED (f);
11198 /* An update event is equivalent to MapNotify on X, so report
11199 visibility changes properly. */
11200 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11201 /* Force a redisplay sooner or later to update the
11202 frame titles in case this is the second frame. */
11203 record_asynch_buffer_change ();
11205 else
11207 BeginUpdate (win);
11208 handling_window_update = 1;
11210 expose_frame (f, 0, 0, 0, 0);
11212 handling_window_update = 0;
11213 EndUpdate (win);
11218 static void
11219 do_window_activate (WindowPtr win)
11221 mac_output *mwp = (mac_output *) GetWRefCon (win);
11222 struct frame *f = mwp->mFP;
11224 if (f)
11226 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11227 activate_scroll_bars (f);
11231 static void
11232 do_window_deactivate (WindowPtr win)
11234 mac_output *mwp = (mac_output *) GetWRefCon (win);
11235 struct frame *f = mwp->mFP;
11237 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11239 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11240 deactivate_scroll_bars (f);
11244 static void
11245 do_app_resume ()
11247 mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
11248 struct frame *f = mwp->mFP;
11250 if (f)
11252 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11253 activate_scroll_bars (f);
11256 app_is_suspended = false;
11257 app_sleep_time = WNE_SLEEP_AT_RESUME;
11260 static void
11261 do_app_suspend ()
11263 mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
11264 struct frame *f = mwp->mFP;
11266 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11268 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11269 deactivate_scroll_bars (f);
11272 app_is_suspended = true;
11273 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11277 static void
11278 do_mouse_moved (Point mouse_pos)
11280 WindowPtr wp = FrontWindow ();
11281 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11283 SetPort (wp);
11284 GlobalToLocal (&mouse_pos);
11286 note_mouse_movement (f, &mouse_pos);
11290 static void
11291 do_os_event (EventRecord *erp)
11293 switch((erp->message >> 24) & 0x000000FF)
11295 case suspendResumeMessage:
11296 if((erp->message & resumeFlag) == 1)
11297 do_app_resume ();
11298 else
11299 do_app_suspend ();
11300 break;
11302 case mouseMovedMessage:
11303 do_mouse_moved (erp->where);
11304 break;
11308 static void
11309 do_events (EventRecord *erp)
11311 switch (erp->what)
11313 case updateEvt:
11314 do_window_update ((WindowPtr) erp->message);
11315 break;
11317 case osEvt:
11318 do_os_event (erp);
11319 break;
11321 case activateEvt:
11322 if ((erp->modifiers & activeFlag) != 0)
11323 do_window_activate ((WindowPtr) erp->message);
11324 else
11325 do_window_deactivate ((WindowPtr) erp->message);
11326 break;
11330 static void
11331 do_apple_menu (SInt16 menu_item)
11333 Str255 item_name;
11334 SInt16 da_driver_refnum;
11336 if (menu_item == I_ABOUT)
11337 NoteAlert (ABOUT_ALERT_ID, NULL);
11338 else
11340 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11341 da_driver_refnum = OpenDeskAcc (item_name);
11345 void
11346 do_menu_choice (SInt32 menu_choice)
11348 SInt16 menu_id, menu_item;
11350 menu_id = HiWord (menu_choice);
11351 menu_item = LoWord (menu_choice);
11353 if (menu_id == 0)
11354 return;
11356 switch (menu_id)
11358 case M_APPLE:
11359 do_apple_menu (menu_item);
11360 break;
11362 default:
11364 WindowPtr wp = FrontWindow ();
11365 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11366 MenuHandle menu = GetMenuHandle (menu_id);
11367 if (menu)
11369 UInt32 refcon;
11371 GetMenuItemRefCon (menu, menu_item, &refcon);
11372 menubar_selection_callback (f, refcon);
11377 HiliteMenu (0);
11381 /* Handle drags in size box. Based on code contributed by Ben
11382 Mesander and IM - Window Manager A. */
11384 static void
11385 do_grow_window (WindowPtr w, EventRecord *e)
11387 long grow_size;
11388 Rect limit_rect;
11389 int rows, columns;
11390 mac_output *mwp = (mac_output *) GetWRefCon (w);
11391 struct frame *f = mwp->mFP;
11393 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11395 grow_size = GrowWindow (w, e->where, &limit_rect);
11397 /* see if it really changed size */
11398 if (grow_size != 0)
11400 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11401 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11403 x_set_window_size (f, 0, columns, rows);
11408 /* Handle clicks in zoom box. Calculation of "standard state" based
11409 on code in IM - Window Manager A and code contributed by Ben
11410 Mesander. The standard state of an Emacs window is 80-characters
11411 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11413 static void
11414 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11416 GrafPtr save_port;
11417 Rect zoom_rect, port_rect;
11418 Point top_left;
11419 int w_title_height, columns, rows, width, height, dummy, x, y;
11420 mac_output *mwp = (mac_output *) GetWRefCon (w);
11421 struct frame *f = mwp->mFP;
11423 GetPort (&save_port);
11424 SetPort (w);
11425 EraseRect (&(w->portRect)); /* erase to avoid flicker */
11426 if (zoom_in_or_out == inZoomOut)
11428 SetPt(&top_left, w->portRect.left, w->portRect.top);
11429 LocalToGlobal (&top_left);
11431 /* calculate height of window's title bar */
11432 w_title_height = top_left.v - 1
11433 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight();
11435 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
11436 zoom_rect = qd.screenBits.bounds;
11437 zoom_rect.top += w_title_height;
11438 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11440 zoom_rect.right = zoom_rect.left
11441 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11443 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState = zoom_rect;
11446 ZoomWindow (w, zoom_in_or_out, w == FrontWindow());
11448 /* retrieve window size and update application values */
11449 port_rect = w->portRect;
11450 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
11451 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
11452 x_set_window_size (mwp->mFP, 0, columns, rows);
11454 SetPort (save_port);
11458 /* Intialize AppleEvent dispatcher table for the required events. */
11459 void
11460 init_required_apple_events ()
11462 OSErr err;
11463 long result;
11465 /* Make sure we have apple events before starting. */
11466 err = Gestalt (gestaltAppleEventsAttr, &result);
11467 if (err != noErr)
11468 abort ();
11470 if (!(result & (1 << gestaltAppleEventsPresent)))
11471 abort ();
11473 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
11474 NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_open_application),
11475 0L, false);
11476 if (err != noErr)
11477 abort ();
11479 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
11480 NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_open_documents),
11481 0L, false);
11482 if (err != noErr)
11483 abort ();
11485 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
11486 NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_print_documents),
11487 0L, false);
11488 if (err != noErr)
11489 abort ();
11491 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
11492 NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_quit_application),
11493 0L, false);
11494 if (err != noErr)
11495 abort ();
11499 /* Open Application Apple Event */
11500 static pascal OSErr
11501 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
11503 return noErr;
11507 /* Defined in mac.c. */
11508 extern int
11509 path_from_vol_dir_name (char *, int, short, long, char *);
11512 /* Called when we receive an AppleEvent with an ID of
11513 "kAEOpenDocuments". This routine gets the direct parameter,
11514 extracts the FSSpecs in it, and puts their names on a list. */
11515 static pascal OSErr
11516 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
11518 OSErr err, err2;
11519 AEDesc the_desc;
11520 AEKeyword keyword;
11521 DescType actual_type;
11522 Size actual_size;
11524 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
11525 if (err != noErr)
11526 goto descriptor_error_exit;
11528 /* Check to see that we got all of the required parameters from the
11529 event descriptor. For an 'odoc' event this should just be the
11530 file list. */
11531 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
11532 &actual_type, (Ptr) &keyword,
11533 sizeof (keyword), &actual_size);
11534 /* No error means that we found some unused parameters.
11535 errAEDescNotFound means that there are no more parameters. If we
11536 get an error code other than that, flag it. */
11537 if ((err == noErr) || (err != errAEDescNotFound))
11539 err = errAEEventNotHandled;
11540 goto error_exit;
11542 err = noErr;
11544 /* Got all the parameters we need. Now, go through the direct
11545 object list and parse it up. */
11547 long num_files_to_open;
11549 err = AECountItems (&the_desc, &num_files_to_open);
11550 if (err == noErr)
11552 int i;
11554 /* AE file list is one based so just use that for indexing here. */
11555 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) {
11556 FSSpec fs;
11557 Str255 path_name, unix_path_name;
11559 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
11560 (Ptr) &fs, sizeof (fs), &actual_size);
11561 if (err != noErr) break;
11563 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
11564 fs.name) &&
11565 mac_to_unix_pathname (path_name, unix_path_name, 255))
11566 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
11567 drag_and_drop_file_list);
11572 error_exit:
11573 /* Nuke the coerced file list in any case */
11574 err2 = AEDisposeDesc(&the_desc);
11576 descriptor_error_exit:
11577 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
11578 return err;
11582 /* Print Document Apple Event */
11583 static pascal OSErr
11584 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
11586 return errAEEventNotHandled;
11590 static pascal OSErr
11591 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
11593 /* FixMe: Do we need an unwind-protect or something here? And what
11594 do we do about unsaved files. Currently just forces quit rather
11595 than doing recursive callback to get user input. */
11597 terminate_flag = true;
11599 /* Fkill_emacs doesn't return. We have to return. (TI) */
11600 return noErr;
11604 #if __profile__
11605 void
11606 profiler_exit_proc ()
11608 ProfilerDump ("\pEmacs.prof");
11609 ProfilerTerm ();
11611 #endif
11613 /* These few functions implement Emacs as a normal Mac application
11614 (almost): set up the the heap and the Toolbox, handle necessary
11615 system events plus a few simple menu events. They also set up
11616 Emacs's access to functions defined in the rest of this file.
11617 Emacs uses function hooks to perform all its terminal I/O. A
11618 complete list of these functions appear in termhooks.h. For what
11619 they do, read the comments there and see also w32term.c and
11620 xterm.c. What's noticeably missing here is the event loop, which
11621 is normally present in most Mac application. After performing the
11622 necessary Mac initializations, main passes off control to
11623 emacs_main (corresponding to main in emacs.c). Emacs_main calls
11624 mac_read_socket (defined further below) to read input. This is
11625 where WaitNextEvent is called to process Mac events. This is also
11626 where check_alarm in sysdep.c is called to simulate alarm signals.
11627 This makes the cursor jump back to its correct position after
11628 briefly jumping to that of the matching parenthesis, print useful
11629 hints and prompts in the minibuffer after the user stops typing for
11630 a wait, etc. */
11632 #undef main
11633 int
11634 main (void)
11636 #if __profile__ /* is the profiler on? */
11637 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
11638 exit(1);
11639 #endif
11641 #if __MWERKS__
11642 /* set creator and type for files created by MSL */
11643 _fcreator = 'EMAx';
11644 _ftype = 'TEXT';
11645 #endif
11647 do_init_managers ();
11649 do_get_menus ();
11651 init_emacs_passwd_dir ();
11653 init_environ ();
11655 initialize_applescript ();
11657 init_required_apple_events ();
11660 char **argv;
11661 int argc = 0;
11663 /* set up argv array from STR# resource */
11664 get_string_list (&argv, ARGV_STRING_LIST_ID);
11665 while (argv[argc])
11666 argc++;
11668 /* free up AppleScript resources on exit */
11669 atexit (terminate_applescript);
11671 #if __profile__ /* is the profiler on? */
11672 atexit (profiler_exit_proc);
11673 #endif
11675 /* 3rd param "envp" never used in emacs_main */
11676 (void) emacs_main (argc, argv, 0);
11679 /* Never reached - real exit in Fkill_emacs */
11680 return 0;
11684 /* Table for translating Mac keycode to X keysym values. Contributed
11685 by Sudhir Shenoy. */
11686 static unsigned char keycode_to_xkeysym_table[] = {
11687 /* 0x00 - 0x3f */
11688 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11689 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11690 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11691 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11692 /* 0x40 */
11693 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
11694 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
11695 0, 0, 0, '\xaf' /* kp/ */,
11696 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
11697 /* 0x50 */
11698 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
11699 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
11700 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
11701 '\xb9' /* kp9 */, 0, 0, 0,
11702 /* 0x60 */
11703 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
11704 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
11705 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
11706 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
11707 /* 0x70 */
11708 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
11709 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
11710 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
11711 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
11714 static int
11715 keycode_to_xkeysym (int keyCode, int *xKeySym)
11717 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
11718 return *xKeySym != 0;
11721 /* Emacs calls this whenever it wants to read an input event from the
11722 user. */
11724 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
11726 int count = 0;
11727 EventRecord er;
11728 int the_modifiers;
11729 EventMask event_mask;
11731 if (interrupt_input_blocked)
11733 interrupt_input_pending = 1;
11734 return -1;
11737 interrupt_input_pending = 0;
11738 BLOCK_INPUT;
11740 /* So people can tell when we have read the available input. */
11741 input_signal_count++;
11743 if (numchars <= 0)
11744 abort ();
11746 /* Don't poll for events to process (specifically updateEvt) if
11747 window update currently already in progress. A call to redisplay
11748 (in do_window_update) can be preempted by another call to
11749 redisplay, causing blank regions to be left on the screen and the
11750 cursor to be left at strange places. */
11751 if (handling_window_update)
11753 UNBLOCK_INPUT;
11754 return 0;
11757 if (terminate_flag)
11758 Fkill_emacs (make_number (1));
11760 /* It is necessary to set this (additional) argument slot of an
11761 event to nil because keyboard.c protects incompletely processed
11762 event from being garbage collected by placing them in the
11763 kbd_buffer_gcpro vector. */
11764 bufp->arg = Qnil;
11766 event_mask = everyEvent;
11767 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
11768 event_mask -= highLevelEventMask;
11770 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
11771 switch (er.what)
11773 case mouseDown:
11774 case mouseUp:
11776 WindowPtr window_ptr = FrontWindow ();
11777 SInt16 part_code;
11779 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
11780 && er.what == mouseUp)
11782 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
11783 Point mouse_loc = er.where;
11785 /* Convert to local coordinates of new window. */
11786 SetPort (window_ptr);
11787 GlobalToLocal (&mouse_loc);
11789 bufp->code = 0; /* only one mouse button */
11790 bufp->kind = scroll_bar_click;
11791 bufp->frame_or_window = tracked_scroll_bar->window;
11792 bufp->part = scroll_bar_handle;
11793 bufp->modifiers = up_modifier;
11794 bufp->timestamp = er.when * (1000 / 60);
11795 /* ticks to milliseconds */
11797 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
11798 XSETINT (bufp->y, mouse_loc.v - 24);
11799 tracked_scroll_bar->dragging = Qnil;
11800 mouse_tracking_in_progress = mouse_tracking_none;
11801 tracked_scroll_bar = NULL;
11802 count++;
11803 break;
11806 part_code = FindWindow (er.where, &window_ptr);
11808 switch (part_code)
11810 case inMenuBar:
11812 struct frame *f = ((mac_output *)
11813 GetWRefCon (FrontWindow ()))->mFP;
11814 saved_menu_event_location = er.where;
11815 bufp->kind = menu_bar_activate_event;
11816 XSETFRAME (bufp->frame_or_window, f);
11817 count++;
11819 break;
11821 case inContent:
11822 if (window_ptr != FrontWindow ())
11823 SelectWindow (window_ptr);
11824 else
11826 int control_part_code;
11827 ControlHandle ch;
11828 struct mac_output *mwp = (mac_output *)
11829 GetWRefCon (window_ptr);
11830 Point mouse_loc = er.where;
11832 /* convert to local coordinates of new window */
11833 SetPort (window_ptr);
11834 GlobalToLocal (&mouse_loc);
11835 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
11837 bufp->code = 0; /* only one mouse button */
11838 XSETINT (bufp->x, mouse_loc.h);
11839 XSETINT (bufp->y, mouse_loc.v);
11840 bufp->timestamp = er.when * (1000 / 60);
11841 /* ticks to milliseconds */
11843 if (control_part_code != 0)
11845 struct scroll_bar *bar = (struct scroll_bar *)
11846 GetControlReference (ch);
11847 x_scroll_bar_handle_click (bar, control_part_code, &er,
11848 bufp);
11849 if (er.what == mouseDown
11850 && control_part_code == kControlIndicatorPart)
11852 mouse_tracking_in_progress = mouse_tracking_scroll_bar;
11853 tracked_scroll_bar = bar;
11855 else
11857 mouse_tracking_in_progress = mouse_tracking_none;
11858 tracked_scroll_bar = NULL;
11861 else
11863 bufp->kind = mouse_click;
11864 XSETFRAME (bufp->frame_or_window, mwp->mFP);
11865 if (er.what == mouseDown)
11866 mouse_tracking_in_progress = mouse_tracking_mouse_movement;
11867 else
11868 mouse_tracking_in_progress = mouse_tracking_none;
11871 switch (er.what)
11873 case mouseDown:
11874 bufp->modifiers = down_modifier;
11875 break;
11876 case mouseUp:
11877 bufp->modifiers = up_modifier;
11878 break;
11881 count++;
11883 break;
11885 case inDrag:
11886 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
11887 break;
11889 case inGoAway:
11890 if (TrackGoAway (window_ptr, er.where))
11892 bufp->kind = delete_window_event;
11893 XSETFRAME (bufp->frame_or_window,
11894 ((mac_output *) GetWRefCon (window_ptr))->mFP);
11895 count++;
11897 break;
11899 /* window resize handling added --ben */
11900 case inGrow:
11901 do_grow_window(window_ptr, &er);
11902 break;
11904 /* window zoom handling added --ben */
11905 case inZoomIn:
11906 case inZoomOut:
11907 if (TrackBox (window_ptr, er.where, part_code))
11908 do_zoom_window (window_ptr, part_code);
11909 break;
11911 default:
11912 break;
11915 break;
11917 case updateEvt:
11918 case osEvt:
11919 case activateEvt:
11920 do_events (&er);
11921 break;
11923 case keyDown:
11924 case autoKey:
11926 int keycode = (er.message & keyCodeMask) >> 8;
11927 int xkeysym;
11929 ObscureCursor ();
11931 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
11933 bufp->code = 0x7f;
11934 bufp->kind = ascii_keystroke;
11936 else if (keycode_to_xkeysym (keycode, &xkeysym))
11938 bufp->code = 0xff00 | xkeysym;
11939 bufp->kind = non_ascii_keystroke;
11941 else
11943 if (er.modifiers
11944 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
11946 /* This code comes from Keyboard Resource, Appendix
11947 C of IM - Text. This is necessary since shift is
11948 ignored in KCHR table translation when option or
11949 command is pressed. */
11950 int new_modifiers = er.modifiers & 0xf600;
11951 /* mask off option and command */
11952 int new_keycode = keycode | new_modifiers;
11953 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
11954 unsigned long some_state = 0;
11955 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
11956 &some_state) & 0xff;
11958 else
11959 bufp->code = er.message & charCodeMask;
11960 bufp->kind = ascii_keystroke;
11964 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
11965 convert non-ASCII characters typed at the Mac keyboard
11966 (presumed to be in the Mac Roman encoding) to iso-latin-1
11967 encoding before they are passed to Emacs. This enables the
11968 Mac keyboard to be used to enter non-ASCII iso-latin-1
11969 characters directly. */
11970 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
11971 && bufp->kind == ascii_keystroke && bufp->code >= 128)
11973 static TECObjectRef converter = NULL;
11974 OSStatus the_err = noErr;
11975 OSStatus convert_status = noErr;
11977 if (converter == NULL)
11979 the_err = TECCreateConverter (&converter,
11980 kTextEncodingMacRoman,
11981 mac_keyboard_text_encoding);
11982 current_mac_keyboard_text_encoding = mac_keyboard_text_encoding;
11984 else if (mac_keyboard_text_encoding != current_mac_keyboard_text_encoding)
11986 /* Free the converter for the current encoding before
11987 creating a new one. */
11988 TECDisposeConverter (converter);
11989 the_err = TECCreateConverter (&converter,
11990 kTextEncodingMacRoman,
11991 mac_keyboard_text_encoding);
11992 current_mac_keyboard_text_encoding = mac_keyboard_text_encoding;
11995 if (the_err == noErr)
11997 unsigned char ch = bufp->code;
11998 ByteCount actual_input_length, actual_output_length;
11999 unsigned char outch;
12001 convert_status = TECConvertText (converter, &ch, 1,
12002 &actual_input_length,
12003 &outch, 1,
12004 &actual_output_length);
12005 if (convert_status == noErr
12006 && actual_input_length == 1
12007 && actual_output_length == 1)
12008 bufp->code = outch;
12012 the_modifiers = 0;
12013 if (er.modifiers & shiftKey)
12014 the_modifiers |= shift_modifier;
12015 if (er.modifiers & controlKey)
12016 the_modifiers |= ctrl_modifier;
12017 /* use option or command key as meta depending on value of
12018 mac-command-key-is-meta */
12019 if (er.modifiers
12020 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12021 the_modifiers |= meta_modifier;
12022 bufp->modifiers = the_modifiers;
12025 mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
12026 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12029 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12031 count++;
12032 break;
12034 case kHighLevelEvent:
12035 drag_and_drop_file_list = Qnil;
12037 AEProcessAppleEvent(&er);
12039 /* Build a drag_n_drop type event as is done in
12040 constuct_drag_n_drop in w32term.c. */
12041 if (!NILP (drag_and_drop_file_list))
12043 struct frame *f;
12044 WindowPtr wp;
12045 Lisp_Object frame;
12047 wp = FrontWindow ();
12048 if (!wp)
12049 f = NULL;
12050 else
12051 f = ((mac_output *) GetWRefCon (wp))->mFP;
12053 bufp->kind = drag_n_drop;
12054 bufp->code = 0;
12055 bufp->timestamp = er.when * (1000 / 60);
12056 /* ticks to milliseconds */
12057 bufp->modifiers = 0;
12059 XSETINT (bufp->x, 0);
12060 XSETINT (bufp->y, 0);
12062 XSETFRAME (frame, f);
12063 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
12065 /* Regardless of whether Emacs was suspended or in the
12066 foreground, ask it to redraw its entire screen.
12067 Otherwise parts of the screen can be left in an
12068 inconsistent state. */
12069 if (wp)
12070 InvalRect (&(wp->portRect));
12072 count++;
12075 default:
12076 break;
12079 /* If the focus was just given to an autoraising frame,
12080 raise it now. */
12081 /* ??? This ought to be able to handle more than one such frame. */
12082 if (pending_autoraise_frame)
12084 x_raise_frame (pending_autoraise_frame);
12085 pending_autoraise_frame = 0;
12088 check_alarm (); /* simulate the handling of a SIGALRM */
12091 static Point old_mouse_pos = { -1, -1 };
12093 if (app_is_suspended)
12095 old_mouse_pos.h = -1;
12096 old_mouse_pos.v = -1;
12098 else
12100 Point mouse_pos;
12101 WindowPtr wp = FrontWindow ();
12102 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
12103 Lisp_Object bar;
12104 struct scroll_bar *sb;
12106 SetPort (wp);
12107 GetMouse (&mouse_pos);
12109 if (!EqualPt (mouse_pos, old_mouse_pos))
12111 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12112 && tracked_scroll_bar)
12113 x_scroll_bar_note_movement (tracked_scroll_bar,
12114 mouse_pos.v
12115 - XINT (tracked_scroll_bar->top),
12116 TickCount() * (1000 / 60));
12117 else
12118 note_mouse_movement (f, &mouse_pos);
12120 old_mouse_pos = mouse_pos;
12125 UNBLOCK_INPUT;
12127 return count;
12131 /* Need to override CodeWarrior's input function so no conversion is
12132 done on newlines Otherwise compiled functions in .elc files will be
12133 read incorrectly. Defined in ...:MSL C:MSL
12134 Common:Source:buffer_io.c. */
12135 #ifdef __MWERKS__
12136 void
12137 __convert_to_newlines (unsigned char * p, size_t * n)
12139 #pragma unused(p,n)
12142 void
12143 __convert_from_newlines (unsigned char * p, size_t * n)
12145 #pragma unused(p,n)
12147 #endif
12150 /* Initialize the struct pointed to by MW to represent a new COLS x
12151 ROWS Macintosh window, using font with name FONTNAME and size
12152 FONTSIZE. */
12153 void
12154 NewMacWindow (FRAME_PTR fp)
12156 mac_output *mwp;
12157 static int making_terminal_window = 1;
12159 mwp = fp->output_data.mac;
12161 if (making_terminal_window)
12163 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
12164 (WindowPtr) -1)))
12165 abort ();
12166 making_terminal_window = 0;
12168 else
12169 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
12170 abort ();
12173 SetWRefCon (mwp->mWP, (long) mwp);
12174 /* so that update events can find this mac_output struct */
12175 mwp->mFP = fp; /* point back to emacs frame */
12177 SetPort (mwp->mWP);
12179 mwp->fontset = -1;
12181 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
12182 ShowWindow (mwp->mWP);
12187 void make_mac_frame (struct frame *f)
12189 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12190 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12192 NewMacWindow(f);
12193 f->output_data.mac->background_pixel = 0xffffff;
12194 f->output_data.mac->foreground_pixel = 0;
12196 f->output_data.mac->cursor_pixel = 0;
12197 f->output_data.mac->border_pixel = 0x00ff00;
12198 f->output_data.mac->mouse_pixel = 0xff00ff;
12199 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12201 f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
12203 f->output_data.mac->fontset = -1;
12204 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12205 f->output_data.mac->scroll_bar_background_pixel = -1;
12206 f->output_data.mac->left_pos = 4;
12207 f->output_data.mac->top_pos = 4;
12208 f->output_data.mac->border_width = 0;
12209 f->output_data.mac->explicit_parent = 0;
12211 f->output_data.mac->internal_border_width = 0;
12213 f->output_method = output_mac;
12215 f->auto_raise = 1;
12216 f->auto_lower = 1;
12218 f->new_width = 0;
12219 f->new_height = 0;
12222 void make_mac_terminal_frame (struct frame *f)
12224 Lisp_Object frame;
12226 XSETFRAME (frame, f);
12228 f->output_method = output_mac;
12229 f->output_data.mac = (struct mac_output *)
12230 xmalloc (sizeof (struct mac_output));
12231 bzero (f->output_data.mac, sizeof (struct mac_output));
12232 f->output_data.mac->fontset = -1;
12233 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12234 f->output_data.mac->scroll_bar_background_pixel = -1;
12236 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12238 f->width = 96;
12239 f->height = 4;
12241 make_mac_frame (f);
12243 Fmodify_frame_parameters (frame,
12244 Fcons (Fcons (Qfont,
12245 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12246 Fmodify_frame_parameters (frame,
12247 Fcons (Fcons (Qforeground_color,
12248 build_string ("black")), Qnil));
12249 Fmodify_frame_parameters (frame,
12250 Fcons (Fcons (Qbackground_color,
12251 build_string ("white")), Qnil));
12254 void
12255 mac_initialize_display_info ()
12257 struct mac_display_info *dpyinfo = &one_mac_display_info;
12258 GDHandle main_device_handle;
12260 bzero (dpyinfo, sizeof (*dpyinfo));
12262 /* Put it on x_display_name_list. */
12263 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
12264 x_display_name_list);
12265 dpyinfo->name_list_element = XCAR (x_display_name_list);
12267 main_device_handle = LMGetMainDevice();
12269 dpyinfo->reference_count = 0;
12270 dpyinfo->resx = 75.0;
12271 dpyinfo->resy = 75.0;
12272 dpyinfo->n_planes = 1;
12273 dpyinfo->n_cbits = 16;
12274 dpyinfo->height = (**main_device_handle).gdRect.bottom;
12275 dpyinfo->width = (**main_device_handle).gdRect.right;
12276 dpyinfo->grabbed = 0;
12277 dpyinfo->root_window = NULL;
12279 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12280 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
12281 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
12282 dpyinfo->mouse_face_window = Qnil;
12286 void
12287 x_initialize ()
12289 rif = &x_redisplay_interface;
12291 clear_frame_hook = x_clear_frame;
12292 ins_del_lines_hook = x_ins_del_lines;
12293 change_line_highlight_hook = x_change_line_highlight;
12294 delete_glyphs_hook = x_delete_glyphs;
12295 ring_bell_hook = XTring_bell;
12296 reset_terminal_modes_hook = XTreset_terminal_modes;
12297 set_terminal_modes_hook = XTset_terminal_modes;
12298 update_begin_hook = x_update_begin;
12299 update_end_hook = x_update_end;
12300 set_terminal_window_hook = XTset_terminal_window;
12301 read_socket_hook = XTread_socket;
12302 frame_up_to_date_hook = XTframe_up_to_date;
12303 reassert_line_highlight_hook = XTreassert_line_highlight;
12304 mouse_position_hook = XTmouse_position;
12305 frame_rehighlight_hook = XTframe_rehighlight;
12306 frame_raise_lower_hook = XTframe_raise_lower;
12308 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
12309 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
12310 redeem_scroll_bar_hook = XTredeem_scroll_bar;
12311 judge_scroll_bars_hook = XTjudge_scroll_bars;
12313 estimate_mode_line_height_hook = x_estimate_mode_line_height;
12315 scroll_region_ok = 1; /* we'll scroll partial frames */
12316 char_ins_del_ok = 0; /* just as fast to write the line */
12317 line_ins_del_ok = 1; /* we'll just blt 'em */
12318 fast_clear_end_of_line = 1; /* X does this well */
12319 memory_below_frame = 0; /* we don't remember what scrolls
12320 off the bottom */
12321 baud_rate = 19200;
12323 x_noop_count = 0;
12324 last_tool_bar_item = -1;
12325 any_help_event_p = 0;
12327 /* Try to use interrupt input; if we can't, then start polling. */
12328 Fset_input_mode (Qt, Qnil, Qt, Qnil);
12330 #ifdef USE_X_TOOLKIT
12331 XtToolkitInitialize ();
12332 Xt_app_con = XtCreateApplicationContext ();
12333 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
12335 /* Install an asynchronous timer that processes Xt timeout events
12336 every 0.1s. This is necessary because some widget sets use
12337 timeouts internally, for example the LessTif menu bar, or the
12338 Xaw3d scroll bar. When Xt timouts aren't processed, these
12339 widgets don't behave normally. */
12341 EMACS_TIME interval;
12342 EMACS_SET_SECS_USECS (interval, 0, 100000);
12343 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
12345 #endif
12347 #if USE_TOOLKIT_SCROLL_BARS
12348 xaw3d_arrow_scroll = False;
12349 xaw3d_pick_top = True;
12350 #endif
12352 #if 0
12353 /* Note that there is no real way portable across R3/R4 to get the
12354 original error handler. */
12355 XSetErrorHandler (x_error_handler);
12356 XSetIOErrorHandler (x_io_error_quitter);
12358 /* Disable Window Change signals; they are handled by X events. */
12359 #ifdef SIGWINCH
12360 signal (SIGWINCH, SIG_DFL);
12361 #endif /* ! defined (SIGWINCH) */
12363 signal (SIGPIPE, x_connection_signal);
12364 #endif
12366 mac_initialize_display_info ();
12370 void
12371 syms_of_macterm ()
12373 #if 0
12374 staticpro (&x_error_message_string);
12375 x_error_message_string = Qnil;
12376 #endif
12378 staticpro (&x_display_name_list);
12379 x_display_name_list = Qnil;
12381 staticpro (&last_mouse_scroll_bar);
12382 last_mouse_scroll_bar = Qnil;
12384 staticpro (&Qvendor_specific_keysyms);
12385 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
12387 staticpro (&last_mouse_press_frame);
12388 last_mouse_press_frame = Qnil;
12390 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
12391 staticpro (&Qmac_ready_for_drag_n_drop);
12393 help_echo = Qnil;
12394 staticpro (&help_echo);
12395 help_echo_object = Qnil;
12396 staticpro (&help_echo_object);
12397 help_echo_window = Qnil;
12398 staticpro (&help_echo_window);
12399 previous_help_echo = Qnil;
12400 staticpro (&previous_help_echo);
12401 help_echo_pos = -1;
12403 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
12404 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
12405 For example, if a block cursor is over a tab, it will be drawn as\n\
12406 wide as that tab on the display.");
12407 x_stretch_cursor_p = 0;
12409 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
12410 "If not nil, Emacs uses toolkit scroll bars.");
12411 #if USE_TOOLKIT_SCROLL_BARS
12412 x_toolkit_scroll_bars_p = 1;
12413 #else
12414 x_toolkit_scroll_bars_p = 0;
12415 #endif
12417 staticpro (&last_mouse_motion_frame);
12418 last_mouse_motion_frame = Qnil;
12420 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
12421 "Non-nil means that the command key is used as the Emacs meta key.\n\
12422 Otherwise the option key is used.");
12423 Vmac_command_key_is_meta = Qt;
12425 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
12426 "One of the Text Encoding Base constant values defined in the\n\
12427 Basic Text Constants section of Inside Macintosh - Text Encoding\n\
12428 Conversion Manager. Its value determines the encoding characters\n\
12429 typed at the Mac keyboard (presumed to be in the MacRoman encoding)\n\
12430 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),\n\
12431 its default value, no conversion takes place. If it is set to\n\
12432 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),\n\
12433 characters typed on Mac keyboard are first converted into the\n\
12434 ISO Latin-1 or ISO Latin-2 encoding, respectively before being\n\
12435 passed to Emacs. Together with Emacs's set-keyboard-coding-system\n\
12436 command, this enables the Mac keyboard to be used to enter non-ASCII\n\
12437 characters directly.");
12438 mac_keyboard_text_encoding = kTextEncodingMacRoman;